diff --git a/.DS_Store b/.DS_Store
index ce75319..6779848 100644
Binary files a/.DS_Store and b/.DS_Store differ
diff --git a/.github/workflows/code_quality.yml b/.github/workflows/code_quality.yml
new file mode 100644
index 0000000..b05889f
--- /dev/null
+++ b/.github/workflows/code_quality.yml
@@ -0,0 +1,17 @@
+name: Code Quality
+
+on:
+ - pull_request
+ - push
+
+jobs:
+ eslint:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+ - name: Install dependencies
+ run: npm ci
+ working-directory: node
+ - name: Run ESLint
+ run: npm run lint
+ working-directory: node
diff --git a/.vscode/extensions.json b/.vscode/extensions.json
new file mode 100644
index 0000000..1d7ac85
--- /dev/null
+++ b/.vscode/extensions.json
@@ -0,0 +1,3 @@
+{
+ "recommendations": ["dbaeumer.vscode-eslint", "esbenp.prettier-vscode"]
+}
diff --git a/.vscode/settings.json b/.vscode/settings.json
new file mode 100644
index 0000000..e01df6a
--- /dev/null
+++ b/.vscode/settings.json
@@ -0,0 +1,13 @@
+{
+ "editor.defaultFormatter": "esbenp.prettier-vscode",
+ "prettier.configPath": "./node/.prettierrc",
+ "prettier.printWidth": 120,
+ "prettier.tabWidth": 2,
+ "prettier.trailingComma": "all",
+ "prettier.semi": true,
+ "prettier.useTabs": true,
+ "editor.formatOnSave": true,
+ "editor.codeActionsOnSave": {
+ "source.fixAll.eslint": true
+ }
+}
diff --git a/README.md b/README.md
index 2269f6d..928557f 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,9 @@
# Adventure Land - The Open Source CODE MMORPG
+
https://adventure.land
+
The Source Code is now available to anyone, even for commercial use! (License applies)
+
**Please consider supporting Adventure Land on Patreon: https://www.patreon.com/AdventureLand**
## Discussion
@@ -10,17 +13,29 @@ Consider using the #development channel on Discord or messaging me directly on D
## Installation
Clone the game files into the adventureland folder:
+
```sh
git clone https://github.com/kaansoral/adventureland adventureland
```
+
Clone a modified copy of Python2 App Engine Local App Server into the python folder along with an initialized database with map files:
```sh
git clone https://github.com/kaansoral/adventureland-appserver appserver
```
+
+Set up secrets files and remember to change secret keys!
+
+```sh
+cp adventureland/useful/template.secrets.py adventureland/secrets.py
+cp adventureland/useful/template.variables.js adventureland/node/variables.js
+cp adventureland/useful/template.live_variables.js adventureland/node/live_variables.js
+```
+
You'll need to download Python2.7 and use the command that comes along with it - it could be ./python or python.exe depending on your setup method
Here's the download page: https://www.python.org/downloads/release/python-2718/
For Linux:
+
```sh
apt update
apt upgrade -y
@@ -35,47 +50,54 @@ pip2.7 check
For MacOS pyenv makes sense as it prevents clash between Python versions and allows local versioning by just adding a .python-version to the folder https://github.com/pyenv/pyenv
Make sure to install lxml afterwards:
+
```sh
pip2.7 install lxml
```
Run the Python2.7 backend - includes an HTTP server, datastore, various utilities - emulates Google App Engine:
-```sh
-python2.7 appserver/sdk/dev_appserver.py --storage_path=appserver/storage/ --blobstore_path=appserver/storage/blobstore/ --datastore_path=appserver/storage/db.rdbms --host=0.0.0.0 --port=8083 adventureland/ --require_indexes --skip_sdk_update_check
-```
-Set up the NodeJS project for helpful scripts:
```sh
-npm install adventureland/scripts/
+python2.7 appserver/sdk/dev_appserver.py --storage_path=appserver/storage/ --blobstore_path=appserver/storage/blobstore/ --datastore_path=appserver/storage/db.rdbms --host=0.0.0.0 --port=80 adventureland/ --require_indexes --skip_sdk_update_check
```
Set up the NodeJS game server:
+
```sh
npm install adventureland/node/
```
-Edit the paths in `adventureland/node/variables.js`
+Edit the paths in `adventureland/node/variables.js` if you want to run the server from any path
+
+Enter the path of the NodeJS server:
+
+```sh
+cd adventureland/node
+```
Run a server:
-```sh
-node adventureland/node/server.js EU I 8022
-```
-You should be able to access the game at: http://0.0.0.0:8083/
+```sh
+node server.js EU I 8022
+```
+
+You should be able to access the game at: http://0.0.0.0/
+
+If you're on Windows and have issues with `0.0.0.0` - replace them with `127.0.0.1` and use http://127.0.0.1/
The **useful/** folder has useful commands
-`secrets.py` has the secrets
-
## Network
Add these to your /etc/hosts file:
+
```sh
0.0.0.0 thegame.com
0.0.0.0 www.thegame.com
```
And setup nginx with a conf such as:
+
```sh
worker_processes 3;
@@ -130,6 +152,14 @@ I suggest you go live with this development codebase and approach development in
The main problem with traditional MMORPG's is people seeking power and while an offline game can provide this for everyone, an online game cannot. Pretty soon new players will avoid such MMORPG's and existing players will also dwindle. In my opinion there are 2 solutions, you could introduce a decay mechanic to overcome this, or concentrate your innovations and additions to make a more social game rather than a game for power hungry people. Originally I intended to add a lot more social integrations, for example browser notifications integrated to the social hub of the game and easy drop ins to friends playing the game etc. So making a more idle and more social game, with new custom art and a new direction could also be a good option, it's definitely the more serene option that anyone can pursue.
+## Code formatting
+
+This project uses [Eslint](https://eslint.org/) and [Prettier](https://prettier.io/).
+For now, this is only used inside the game servers (`/node/` folder).
+If you use VSCode, please install the recommended extensions for [eslint](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint) and [prettier](https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode). The formatting will be automatically done on save.
+If you have suggestions regarding the formatting, feel free to open an issue or discuss it on Discord. [Here is the history](https://discord.com/channels/238332476743745536/1163453037126357074) of the conversation regarding the formatting.
+As you might notice, several eslint rules have been marked as warnings instead of errors. This is to allow a smooth and iterative transition. Make sure your new code respects the rules, even the warnings. If you want to submit a PR to fix a specific warning in a specific part of the code, feel free to do so.
+
## Freelancers
Adventure Land's map designer is available for freelance work or for hire. Contact: markjlacandula@gmail.com
@@ -140,4 +170,4 @@ If you have specific requirements, for example a unique cloud architecture in mi
## License
-https://github.com/kaansoral/adventureland/blob/master/LICENSE
\ No newline at end of file
+https://github.com/kaansoral/adventureland/blob/master/LICENSE
diff --git a/main.py b/main.py
index 0b81dcf..d1cff96 100644
--- a/main.py
+++ b/main.py
@@ -407,7 +407,7 @@ class MapLister(webapp.RequestHandler):
def map_to_html(m):
return "
"%(url,m.id(),m.id())
html=""
- if is_sdk: url="http://thegame.com/admin/map_editor"
+ if is_sdk: url="%s/admin/map_editor"%(domain.base_url)
else: url="%s/%s"%(domain.base_url,"communitymaps")
if order=="key":
for m in Map.query().fetch(5000,keys_only=True): html+=map_to_html(m)
diff --git a/node/.eslintrc b/node/.eslintrc
new file mode 100644
index 0000000..a806da0
--- /dev/null
+++ b/node/.eslintrc
@@ -0,0 +1,25 @@
+{
+ "extends": ["eslint:recommended", "eslint-config-prettier"],
+ "env": {
+ "node": true
+ },
+ "parserOptions": {
+ "ecmaVersion": 10
+ },
+ "plugins": ["prettier"],
+ "rules": {
+ "no-constant-condition": "off",
+ "no-dupe-else-if": "off",
+ "indent": "off",
+ "no-empty": "warn",
+ "no-inner-declarations": "warn",
+ "no-unreachable": "warn",
+ "no-undef": "warn",
+ "no-unused-vars": "warn",
+ "no-redeclare": "warn",
+ "curly": "error",
+ "prettier/prettier": "error",
+ "one-var": ["error", "never"],
+ "no-sequences": "error"
+ }
+}
diff --git a/node/.prettierrc b/node/.prettierrc
new file mode 100644
index 0000000..0bb2a47
--- /dev/null
+++ b/node/.prettierrc
@@ -0,0 +1,10 @@
+{
+ "tabWidth": 2,
+ "singleQuote": false,
+ "printWidth": 120,
+ "trailingComma": "all",
+ "semi": true,
+ "bracketSpacing": true,
+ "arrowParens": "always",
+ "useTabs": true
+}
\ No newline at end of file
diff --git a/node/live_variables.js b/node/live_variables.js
deleted file mode 100644
index 25c4114..0000000
--- a/node/live_variables.js
+++ /dev/null
@@ -1,19 +0,0 @@
-module.exports={
- "cfunctions_path":"./server/common_functions.js",
- "functions_path":"./server/server_functions.js",
- "worker_path":"./server/server_worker.js",
- "data_path":"./server/data.js",
- "base_url":"https://yourappspoturldontincludedashes.appspot.com",
- "keyword":"123",
- "master":"123",
- "server_master":"123",
- "bot_key":"123",
- "discord_token":"NDXXXXXXXXXXX...",
- "apple_token":"acXXXXXXXX...",
- "steam_key":"8aXXXXXXXXX...",
- "steam_web_key":"B4XXXXXXX...",
- "steam_partner_key":"F9XXXXXXX...",
- "close_timeout":24000,
- "ip_limit":3,
- "character_limit":3,
-}
diff --git a/node/package-lock.json b/node/package-lock.json
index fa7d787..5e7075f 100644
--- a/node/package-lock.json
+++ b/node/package-lock.json
@@ -7,13 +7,172 @@
"": {
"name": "adventureland-server",
"version": "1.0.0",
- "license": "ISC",
+ "license": "AdventureLandOnlyUse",
"dependencies": {
"bytebuffer": "^5.0.1",
"protobufjs": "^6.9.0",
"range_check": "^1.4.0",
"request": "^2.88.2",
"socket.io": "^4.0.0"
+ },
+ "devDependencies": {
+ "eslint": "^8.52.0",
+ "eslint-config-prettier": "^9.0.0",
+ "eslint-plugin-prettier": "^5.0.1",
+ "prettier": "^3.0.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/@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.9.1",
+ "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.9.1.tgz",
+ "integrity": "sha512-Y27x+MBLjXa+0JWDhykM3+JE+il3kHKAEqabfEWq3SDhZjLYb6/BHL/JKFnH3fe207JaXkyDo685Oc2Glt6ifA==",
+ "dev": true,
+ "engines": {
+ "node": "^12.0.0 || ^14.0.0 || >=16.0.0"
+ }
+ },
+ "node_modules/@eslint/eslintrc": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.2.tgz",
+ "integrity": "sha512-+wvgpDsrB1YqAMdEUCcnTlpfVBH7Vqn6A/NT3D8WVXFIaKMlErPIZT3oCIAVCOtarRpMtelZLqJeU3t7WY6X6g==",
+ "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/js": {
+ "version": "8.52.0",
+ "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.52.0.tgz",
+ "integrity": "sha512-mjZVbpaeMZludF2fsWLD0Z9gCref1Tk4i9+wddjRvpUNqqcndPkBD09N/Mapey0b3jaXbLm2kICwFv2E64QinA==",
+ "dev": true,
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ }
+ },
+ "node_modules/@humanwhocodes/config-array": {
+ "version": "0.11.13",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.13.tgz",
+ "integrity": "sha512-JSBDMiDKSzQVngfRjOdFXgFfklaXI4K9nLF49Auh21lmBWRLIK3+xTErTWD4KU54pb6coM6ESE7Awz/FNU3zgQ==",
+ "dev": true,
+ "dependencies": {
+ "@humanwhocodes/object-schema": "^2.0.1",
+ "debug": "^4.1.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.1",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.1.tgz",
+ "integrity": "sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw==",
+ "dev": true
+ },
+ "node_modules/@nodelib/fs.scandir": {
+ "version": "2.1.5",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
+ "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
+ "dev": true,
+ "dependencies": {
+ "@nodelib/fs.stat": "2.0.5",
+ "run-parallel": "^1.1.9"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@nodelib/fs.stat": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
+ "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
+ "dev": true,
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@nodelib/fs.walk": {
+ "version": "1.2.8",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
+ "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
+ "dev": true,
+ "dependencies": {
+ "@nodelib/fs.scandir": "2.1.5",
+ "fastq": "^1.6.0"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@pkgr/utils": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/@pkgr/utils/-/utils-2.4.2.tgz",
+ "integrity": "sha512-POgTXhjrTfbTV63DiFXav4lBHiICLKKwDeaKn9Nphwj7WH6m0hMMCaJkMyRWjgtPFyRKRVoMXXjczsTQRDEhYw==",
+ "dev": true,
+ "dependencies": {
+ "cross-spawn": "^7.0.3",
+ "fast-glob": "^3.3.0",
+ "is-glob": "^4.0.3",
+ "open": "^9.1.0",
+ "picocolors": "^1.0.0",
+ "tslib": "^2.6.0"
+ },
+ "engines": {
+ "node": "^12.20.0 || ^14.18.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/unts"
}
},
"node_modules/@protobufjs/aspromise": {
@@ -98,6 +257,12 @@
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.8.0.tgz",
"integrity": "sha512-LzcWltT83s1bthcvjBmiBvGJiiUe84NWRHkw+ZV6Fr41z2FbIzvc815dk2nQ3RAKMuN2fkenM/z3Xv2QzEpYxQ=="
},
+ "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/accepts": {
"version": "1.3.8",
"resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz",
@@ -110,6 +275,27 @@
"node": ">= 0.6"
}
},
+ "node_modules/acorn": {
+ "version": "8.10.0",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz",
+ "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==",
+ "dev": true,
+ "bin": {
+ "acorn": "bin/acorn"
+ },
+ "engines": {
+ "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/ajv": {
"version": "6.12.6",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
@@ -125,6 +311,36 @@
"url": "https://github.com/sponsors/epoberezkin"
}
},
+ "node_modules/ansi-regex": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "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/argparse": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
+ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
+ "dev": true
+ },
"node_modules/asn1": {
"version": "0.2.6",
"resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz",
@@ -159,6 +375,12 @@
"resolved": "https://registry.npmjs.org/aws4/-/aws4-1.12.0.tgz",
"integrity": "sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg=="
},
+ "node_modules/balanced-match": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
+ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
+ "dev": true
+ },
"node_modules/base64id": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz",
@@ -175,6 +397,64 @@
"tweetnacl": "^0.14.3"
}
},
+ "node_modules/big-integer": {
+ "version": "1.6.51",
+ "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.51.tgz",
+ "integrity": "sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.6"
+ }
+ },
+ "node_modules/bplist-parser": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/bplist-parser/-/bplist-parser-0.2.0.tgz",
+ "integrity": "sha512-z0M+byMThzQmD9NILRniCUXYsYpjwnlO8N5uCFaCqIOpqRsJCrQL9NK3JsD67CN5a08nF5oIL2bD6loTdHOuKw==",
+ "dev": true,
+ "dependencies": {
+ "big-integer": "^1.6.44"
+ },
+ "engines": {
+ "node": ">= 5.10.0"
+ }
+ },
+ "node_modules/brace-expansion": {
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+ "dev": true,
+ "dependencies": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "node_modules/braces": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
+ "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
+ "dev": true,
+ "dependencies": {
+ "fill-range": "^7.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/bundle-name": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-3.0.0.tgz",
+ "integrity": "sha512-PKA4BeSvBpQKQ8iPOGCSiell+N8P+Tf1DlwqmYhpe2gAhKPHn8EYOxVT+ShuGmhg8lN8XiSlS80yiExKXrURlw==",
+ "dev": true,
+ "dependencies": {
+ "run-applescript": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/bytebuffer": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/bytebuffer/-/bytebuffer-5.0.1.tgz",
@@ -186,11 +466,54 @@
"node": ">=0.8"
}
},
+ "node_modules/callsites": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
+ "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
"node_modules/caseless": {
"version": "0.12.0",
"resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz",
"integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw=="
},
+ "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/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/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/combined-stream": {
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
@@ -202,6 +525,12 @@
"node": ">= 0.8"
}
},
+ "node_modules/concat-map": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
+ "dev": true
+ },
"node_modules/cookie": {
"version": "0.4.2",
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz",
@@ -227,6 +556,20 @@
"node": ">= 0.10"
}
},
+ "node_modules/cross-spawn": {
+ "version": "7.0.3",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
+ "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
+ "dev": true,
+ "dependencies": {
+ "path-key": "^3.1.0",
+ "shebang-command": "^2.0.0",
+ "which": "^2.0.1"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
"node_modules/dashdash": {
"version": "1.14.1",
"resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz",
@@ -254,6 +597,58 @@
}
}
},
+ "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/default-browser": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-4.0.0.tgz",
+ "integrity": "sha512-wX5pXO1+BrhMkSbROFsyxUm0i/cJEScyNhA4PPxc41ICuv05ZZB/MX28s8aZx6xjmatvebIapF6hLEKEcpneUA==",
+ "dev": true,
+ "dependencies": {
+ "bundle-name": "^3.0.0",
+ "default-browser-id": "^3.0.0",
+ "execa": "^7.1.1",
+ "titleize": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=14.16"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/default-browser-id": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-3.0.0.tgz",
+ "integrity": "sha512-OZ1y3y0SqSICtE8DE4S8YOE9UZOJ8wO16fKWVP5J1Qz42kV9jcnMVFrEE/noXb/ss3Q4pZIH79kxofzyNNtUNA==",
+ "dev": true,
+ "dependencies": {
+ "bplist-parser": "^0.2.0",
+ "untildify": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/define-lazy-prop": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz",
+ "integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==",
+ "dev": true,
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/delayed-stream": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
@@ -262,6 +657,18 @@
"node": ">=0.4.0"
}
},
+ "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/ecc-jsbn": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz",
@@ -299,6 +706,224 @@
"node": ">=10.0.0"
}
},
+ "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": {
+ "version": "8.52.0",
+ "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.52.0.tgz",
+ "integrity": "sha512-zh/JHnaixqHZsolRB/w9/02akBk9EPrOs9JwcTP2ek7yL5bVvXuRariiaAjjoJ5DvuwQ1WAE/HsMz+w17YgBCg==",
+ "dev": true,
+ "dependencies": {
+ "@eslint-community/eslint-utils": "^4.2.0",
+ "@eslint-community/regexpp": "^4.6.1",
+ "@eslint/eslintrc": "^2.1.2",
+ "@eslint/js": "8.52.0",
+ "@humanwhocodes/config-array": "^0.11.13",
+ "@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-config-prettier": {
+ "version": "9.0.0",
+ "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.0.0.tgz",
+ "integrity": "sha512-IcJsTkJae2S35pRsRAwoCE+925rJJStOdkKnLVgtE+tEpqU0EVVM7OqrwxqgptKdX29NUwC82I5pXsGFIgSevw==",
+ "dev": true,
+ "bin": {
+ "eslint-config-prettier": "bin/cli.js"
+ },
+ "peerDependencies": {
+ "eslint": ">=7.0.0"
+ }
+ },
+ "node_modules/eslint-plugin-prettier": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.0.1.tgz",
+ "integrity": "sha512-m3u5RnR56asrwV/lDC4GHorlW75DsFfmUcjfCYylTUs85dBRnB7VM6xG8eCMJdeDRnppzmxZVf1GEPJvl1JmNg==",
+ "dev": true,
+ "dependencies": {
+ "prettier-linter-helpers": "^1.0.0",
+ "synckit": "^0.8.5"
+ },
+ "engines": {
+ "node": "^14.18.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/prettier"
+ },
+ "peerDependencies": {
+ "@types/eslint": ">=8.0.0",
+ "eslint": ">=8.0.0",
+ "prettier": ">=3.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/eslint": {
+ "optional": true
+ },
+ "eslint-config-prettier": {
+ "optional": true
+ }
+ }
+ },
+ "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-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/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,
+ "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"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/esquery": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz",
+ "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==",
+ "dev": true,
+ "dependencies": {
+ "estraverse": "^5.1.0"
+ },
+ "engines": {
+ "node": ">=0.10"
+ }
+ },
+ "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==",
+ "dev": true,
+ "dependencies": {
+ "estraverse": "^5.2.0"
+ },
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "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/esutils": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
+ "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/execa": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/execa/-/execa-7.2.0.tgz",
+ "integrity": "sha512-UduyVP7TLB5IcAQl+OzLyLcS/l32W/GLg+AhHJ+ow40FOk2U3SAllPwR44v4vmdFwIWqpdwxxpQbF1n5ta9seA==",
+ "dev": true,
+ "dependencies": {
+ "cross-spawn": "^7.0.3",
+ "get-stream": "^6.0.1",
+ "human-signals": "^4.3.0",
+ "is-stream": "^3.0.0",
+ "merge-stream": "^2.0.0",
+ "npm-run-path": "^5.1.0",
+ "onetime": "^6.0.0",
+ "signal-exit": "^3.0.7",
+ "strip-final-newline": "^3.0.0"
+ },
+ "engines": {
+ "node": "^14.18.0 || ^16.14.0 || >=18.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sindresorhus/execa?sponsor=1"
+ }
+ },
"node_modules/extend": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
@@ -317,11 +942,120 @@
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="
},
+ "node_modules/fast-diff": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz",
+ "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==",
+ "dev": true
+ },
+ "node_modules/fast-glob": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz",
+ "integrity": "sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==",
+ "dev": true,
+ "dependencies": {
+ "@nodelib/fs.stat": "^2.0.2",
+ "@nodelib/fs.walk": "^1.2.3",
+ "glob-parent": "^5.1.2",
+ "merge2": "^1.3.0",
+ "micromatch": "^4.0.4"
+ },
+ "engines": {
+ "node": ">=8.6.0"
+ }
+ },
+ "node_modules/fast-glob/node_modules/glob-parent": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
+ "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
+ "dev": true,
+ "dependencies": {
+ "is-glob": "^4.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
"node_modules/fast-json-stable-stringify": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
"integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw=="
},
+ "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/fastq": {
+ "version": "1.15.0",
+ "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz",
+ "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==",
+ "dev": true,
+ "dependencies": {
+ "reusify": "^1.0.4"
+ }
+ },
+ "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/fill-range": {
+ "version": "7.0.1",
+ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
+ "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
+ "dev": true,
+ "dependencies": {
+ "to-regex-range": "^5.0.1"
+ },
+ "engines": {
+ "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/flat-cache": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.1.1.tgz",
+ "integrity": "sha512-/qM2b3LUIaIgviBQovTLvijfyOQXPtSRnRK26ksj2J7rzPIecePUIpJsZ4T02Qg+xiAEKIs5K8dsHEd+VaKa/Q==",
+ "dev": true,
+ "dependencies": {
+ "flatted": "^3.2.9",
+ "keyv": "^4.5.3",
+ "rimraf": "^3.0.2"
+ },
+ "engines": {
+ "node": ">=12.0.0"
+ }
+ },
+ "node_modules/flatted": {
+ "version": "3.2.9",
+ "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.9.tgz",
+ "integrity": "sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==",
+ "dev": true
+ },
"node_modules/forever-agent": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz",
@@ -343,6 +1077,24 @@
"node": ">= 0.12"
}
},
+ "node_modules/fs.realpath": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+ "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
+ "dev": true
+ },
+ "node_modules/get-stream": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz",
+ "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/getpass": {
"version": "0.1.7",
"resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz",
@@ -351,6 +1103,59 @@
"assert-plus": "^1.0.0"
}
},
+ "node_modules/glob": {
+ "version": "7.2.3",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
+ "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
+ "dev": true,
+ "dependencies": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.1.1",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ },
+ "engines": {
+ "node": "*"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "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"
+ },
+ "engines": {
+ "node": ">=10.13.0"
+ }
+ },
+ "node_modules/globals": {
+ "version": "13.23.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-13.23.0.tgz",
+ "integrity": "sha512-XAmF0RjlrjY23MA51q3HltdlGxUpXPvg0GioKiD9X6HD28iMjo2dKC8Vqwm7lne4GNr78+RHTfliktR6ZH09wA==",
+ "dev": true,
+ "dependencies": {
+ "type-fest": "^0.20.2"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "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/har-schema": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz",
@@ -372,6 +1177,15 @@
"node": ">=6"
}
},
+ "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==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/http-signature": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz",
@@ -386,6 +1200,65 @@
"npm": ">=1.3.7"
}
},
+ "node_modules/human-signals": {
+ "version": "4.3.1",
+ "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-4.3.1.tgz",
+ "integrity": "sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=14.18.0"
+ }
+ },
+ "node_modules/ignore": {
+ "version": "5.2.4",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz",
+ "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==",
+ "dev": true,
+ "engines": {
+ "node": ">= 4"
+ }
+ },
+ "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/imurmurhash": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
+ "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.8.19"
+ }
+ },
+ "node_modules/inflight": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
+ "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
+ "dev": true,
+ "dependencies": {
+ "once": "^1.3.0",
+ "wrappy": "1"
+ }
+ },
+ "node_modules/inherits": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
+ "dev": true
+ },
"node_modules/ip6": {
"version": "0.0.4",
"resolved": "https://registry.npmjs.org/ip6/-/ip6-0.0.4.tgz",
@@ -399,21 +1272,156 @@
"node": ">= 0.10"
}
},
+ "node_modules/is-docker": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz",
+ "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==",
+ "dev": true,
+ "bin": {
+ "is-docker": "cli.js"
+ },
+ "engines": {
+ "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/is-extglob": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
+ "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-glob": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
+ "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
+ "dev": true,
+ "dependencies": {
+ "is-extglob": "^2.1.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-inside-container": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz",
+ "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==",
+ "dev": true,
+ "dependencies": {
+ "is-docker": "^3.0.0"
+ },
+ "bin": {
+ "is-inside-container": "cli.js"
+ },
+ "engines": {
+ "node": ">=14.16"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/is-number": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
+ "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
+ "dev": true,
+ "engines": {
+ "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-stream": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz",
+ "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==",
+ "dev": true,
+ "engines": {
+ "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/is-typedarray": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
"integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA=="
},
+ "node_modules/is-wsl": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz",
+ "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==",
+ "dev": true,
+ "dependencies": {
+ "is-docker": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/is-wsl/node_modules/is-docker": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz",
+ "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==",
+ "dev": true,
+ "bin": {
+ "is-docker": "cli.js"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/isexe": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
+ "dev": true
+ },
"node_modules/isstream": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
"integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g=="
},
+ "node_modules/js-yaml": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
+ "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
+ "dev": true,
+ "dependencies": {
+ "argparse": "^2.0.1"
+ },
+ "bin": {
+ "js-yaml": "bin/js-yaml.js"
+ }
+ },
"node_modules/jsbn": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
"integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg=="
},
+ "node_modules/json-buffer": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz",
+ "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==",
+ "dev": true
+ },
"node_modules/json-schema": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz",
@@ -424,6 +1432,12 @@
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
"integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="
},
+ "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/json-stringify-safe": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
@@ -443,6 +1457,49 @@
"node": ">=0.6.0"
}
},
+ "node_modules/keyv": {
+ "version": "4.5.4",
+ "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz",
+ "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==",
+ "dev": true,
+ "dependencies": {
+ "json-buffer": "3.0.1"
+ }
+ },
+ "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/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.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/long": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/long/-/long-3.2.0.tgz",
@@ -451,6 +1508,34 @@
"node": ">=0.6"
}
},
+ "node_modules/merge-stream": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
+ "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==",
+ "dev": true
+ },
+ "node_modules/merge2": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
+ "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
+ "dev": true,
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/micromatch": {
+ "version": "4.0.5",
+ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz",
+ "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==",
+ "dev": true,
+ "dependencies": {
+ "braces": "^3.0.2",
+ "picomatch": "^2.3.1"
+ },
+ "engines": {
+ "node": ">=8.6"
+ }
+ },
"node_modules/mime-db": {
"version": "1.52.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
@@ -470,11 +1555,41 @@
"node": ">= 0.6"
}
},
+ "node_modules/mimic-fn": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz",
+ "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==",
+ "dev": true,
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/minimatch": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+ "dev": true,
+ "dependencies": {
+ "brace-expansion": "^1.1.7"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
"node_modules/ms": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
},
+ "node_modules/natural-compare": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
+ "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",
+ "dev": true
+ },
"node_modules/negotiator": {
"version": "0.6.3",
"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz",
@@ -483,6 +1598,33 @@
"node": ">= 0.6"
}
},
+ "node_modules/npm-run-path": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.1.0.tgz",
+ "integrity": "sha512-sJOdmRGrY2sjNTRMbSvluQqg+8X7ZK61yvzBEIDhz4f8z1TZFYABsqjjCBd/0PUNE9M6QDgHJXQkGUEm7Q+l9Q==",
+ "dev": true,
+ "dependencies": {
+ "path-key": "^4.0.0"
+ },
+ "engines": {
+ "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/npm-run-path/node_modules/path-key": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz",
+ "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/oauth-sign": {
"version": "0.9.0",
"resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz",
@@ -499,11 +1641,193 @@
"node": ">=0.10.0"
}
},
+ "node_modules/once": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+ "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
+ "dev": true,
+ "dependencies": {
+ "wrappy": "1"
+ }
+ },
+ "node_modules/onetime": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz",
+ "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==",
+ "dev": true,
+ "dependencies": {
+ "mimic-fn": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/open": {
+ "version": "9.1.0",
+ "resolved": "https://registry.npmjs.org/open/-/open-9.1.0.tgz",
+ "integrity": "sha512-OS+QTnw1/4vrf+9hh1jc1jnYjzSG4ttTBB8UxOwAnInG3Uo4ssetzC1ihqaIHjLJnA5GGlRl6QlZXOTQhRBUvg==",
+ "dev": true,
+ "dependencies": {
+ "default-browser": "^4.0.0",
+ "define-lazy-prop": "^3.0.0",
+ "is-inside-container": "^1.0.0",
+ "is-wsl": "^2.2.0"
+ },
+ "engines": {
+ "node": ">=14.16"
+ },
+ "funding": {
+ "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-limit": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
+ "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
+ "dev": true,
+ "dependencies": {
+ "yocto-queue": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "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/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/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/path-is-absolute": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+ "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/path-key": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
+ "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/performance-now": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
"integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow=="
},
+ "node_modules/picocolors": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
+ "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==",
+ "dev": true
+ },
+ "node_modules/picomatch": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
+ "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
+ "dev": true,
+ "engines": {
+ "node": ">=8.6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
+ }
+ },
+ "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/prettier": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.0.3.tgz",
+ "integrity": "sha512-L/4pUDMxcNa8R/EthV08Zt42WBO4h1rarVtK0K+QJG0X187OLo7l699jWw0GKuwzkPQ//jMFA/8Xm6Fh3J/DAg==",
+ "dev": true,
+ "bin": {
+ "prettier": "bin/prettier.cjs"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/prettier/prettier?sponsor=1"
+ }
+ },
+ "node_modules/prettier-linter-helpers": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz",
+ "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==",
+ "dev": true,
+ "dependencies": {
+ "fast-diff": "^1.1.2"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
"node_modules/protobufjs": {
"version": "6.11.4",
"resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-6.11.4.tgz",
@@ -555,6 +1879,26 @@
"node": ">=0.6"
}
},
+ "node_modules/queue-microtask": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
+ "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ]
+ },
"node_modules/range_check": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/range_check/-/range_check-1.4.0.tgz",
@@ -595,6 +1939,167 @@
"node": ">= 6"
}
},
+ "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/reusify": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
+ "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==",
+ "dev": true,
+ "engines": {
+ "iojs": ">=1.0.0",
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/rimraf": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
+ "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
+ "dev": true,
+ "dependencies": {
+ "glob": "^7.1.3"
+ },
+ "bin": {
+ "rimraf": "bin.js"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/run-applescript": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-5.0.0.tgz",
+ "integrity": "sha512-XcT5rBksx1QdIhlFOCtgZkB99ZEouFZ1E2Kc2LHqNW13U3/74YGdkQRmThTwxy4QIyookibDKYZOPqX//6BlAg==",
+ "dev": true,
+ "dependencies": {
+ "execa": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/run-applescript/node_modules/execa": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz",
+ "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==",
+ "dev": true,
+ "dependencies": {
+ "cross-spawn": "^7.0.3",
+ "get-stream": "^6.0.0",
+ "human-signals": "^2.1.0",
+ "is-stream": "^2.0.0",
+ "merge-stream": "^2.0.0",
+ "npm-run-path": "^4.0.1",
+ "onetime": "^5.1.2",
+ "signal-exit": "^3.0.3",
+ "strip-final-newline": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sindresorhus/execa?sponsor=1"
+ }
+ },
+ "node_modules/run-applescript/node_modules/human-signals": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz",
+ "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==",
+ "dev": true,
+ "engines": {
+ "node": ">=10.17.0"
+ }
+ },
+ "node_modules/run-applescript/node_modules/is-stream": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz",
+ "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/run-applescript/node_modules/mimic-fn": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz",
+ "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/run-applescript/node_modules/npm-run-path": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz",
+ "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==",
+ "dev": true,
+ "dependencies": {
+ "path-key": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/run-applescript/node_modules/onetime": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz",
+ "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==",
+ "dev": true,
+ "dependencies": {
+ "mimic-fn": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/run-applescript/node_modules/strip-final-newline": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz",
+ "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/run-parallel": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
+ "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "dependencies": {
+ "queue-microtask": "^1.2.2"
+ }
+ },
"node_modules/safe-buffer": {
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
@@ -619,6 +2124,33 @@
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
},
+ "node_modules/shebang-command": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
+ "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
+ "dev": true,
+ "dependencies": {
+ "shebang-regex": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/shebang-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
+ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/signal-exit": {
+ "version": "3.0.7",
+ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
+ "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==",
+ "dev": true
+ },
"node_modules/socket.io": {
"version": "4.7.2",
"resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.7.2.tgz",
@@ -680,6 +2212,100 @@
"node": ">=0.10.0"
}
},
+ "node_modules/strip-ansi": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "dev": true,
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/strip-final-newline": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz",
+ "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==",
+ "dev": true,
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/strip-json-comments": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
+ "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "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==",
+ "dev": true,
+ "dependencies": {
+ "has-flag": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/synckit": {
+ "version": "0.8.5",
+ "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.8.5.tgz",
+ "integrity": "sha512-L1dapNV6vu2s/4Sputv8xGsCdAVlb5nRDMFU/E27D44l5U6cw1g0dGd45uLc+OXjNMmF4ntiMdCimzcjFKQI8Q==",
+ "dev": true,
+ "dependencies": {
+ "@pkgr/utils": "^2.3.1",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": "^14.18.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/unts"
+ }
+ },
+ "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/titleize": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/titleize/-/titleize-3.0.0.tgz",
+ "integrity": "sha512-KxVu8EYHDPBdUYdKZdKtU2aj2XfEx9AfjXxE/Aj0vT06w2icA09Vus1rh6eSu1y01akYg6BjIK/hxyLJINoMLQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/to-regex-range": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
+ "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
+ "dev": true,
+ "dependencies": {
+ "is-number": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=8.0"
+ }
+ },
"node_modules/tough-cookie": {
"version": "2.5.0",
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz",
@@ -692,6 +2318,12 @@
"node": ">=0.8"
}
},
+ "node_modules/tslib": {
+ "version": "2.6.2",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz",
+ "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==",
+ "dev": true
+ },
"node_modules/tunnel-agent": {
"version": "0.6.0",
"resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
@@ -708,6 +2340,39 @@
"resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
"integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA=="
},
+ "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-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/untildify": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/untildify/-/untildify-4.0.0.tgz",
+ "integrity": "sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/uri-js": {
"version": "4.4.1",
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
@@ -746,6 +2411,27 @@
"extsprintf": "^1.2.0"
}
},
+ "node_modules/which": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
+ "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
+ "dev": true,
+ "dependencies": {
+ "isexe": "^2.0.0"
+ },
+ "bin": {
+ "node-which": "bin/node-which"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/wrappy": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
+ "dev": true
+ },
"node_modules/ws": {
"version": "8.11.0",
"resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz",
@@ -765,9 +2451,128 @@
"optional": true
}
}
+ },
+ "node_modules/yocto-queue": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
+ "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
}
},
"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
+ },
+ "@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.9.1",
+ "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.9.1.tgz",
+ "integrity": "sha512-Y27x+MBLjXa+0JWDhykM3+JE+il3kHKAEqabfEWq3SDhZjLYb6/BHL/JKFnH3fe207JaXkyDo685Oc2Glt6ifA==",
+ "dev": true
+ },
+ "@eslint/eslintrc": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.2.tgz",
+ "integrity": "sha512-+wvgpDsrB1YqAMdEUCcnTlpfVBH7Vqn6A/NT3D8WVXFIaKMlErPIZT3oCIAVCOtarRpMtelZLqJeU3t7WY6X6g==",
+ "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"
+ }
+ },
+ "@eslint/js": {
+ "version": "8.52.0",
+ "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.52.0.tgz",
+ "integrity": "sha512-mjZVbpaeMZludF2fsWLD0Z9gCref1Tk4i9+wddjRvpUNqqcndPkBD09N/Mapey0b3jaXbLm2kICwFv2E64QinA==",
+ "dev": true
+ },
+ "@humanwhocodes/config-array": {
+ "version": "0.11.13",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.13.tgz",
+ "integrity": "sha512-JSBDMiDKSzQVngfRjOdFXgFfklaXI4K9nLF49Auh21lmBWRLIK3+xTErTWD4KU54pb6coM6ESE7Awz/FNU3zgQ==",
+ "dev": true,
+ "requires": {
+ "@humanwhocodes/object-schema": "^2.0.1",
+ "debug": "^4.1.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.1",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.1.tgz",
+ "integrity": "sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw==",
+ "dev": true
+ },
+ "@nodelib/fs.scandir": {
+ "version": "2.1.5",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
+ "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
+ "dev": true,
+ "requires": {
+ "@nodelib/fs.stat": "2.0.5",
+ "run-parallel": "^1.1.9"
+ }
+ },
+ "@nodelib/fs.stat": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
+ "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
+ "dev": true
+ },
+ "@nodelib/fs.walk": {
+ "version": "1.2.8",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
+ "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
+ "dev": true,
+ "requires": {
+ "@nodelib/fs.scandir": "2.1.5",
+ "fastq": "^1.6.0"
+ }
+ },
+ "@pkgr/utils": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/@pkgr/utils/-/utils-2.4.2.tgz",
+ "integrity": "sha512-POgTXhjrTfbTV63DiFXav4lBHiICLKKwDeaKn9Nphwj7WH6m0hMMCaJkMyRWjgtPFyRKRVoMXXjczsTQRDEhYw==",
+ "dev": true,
+ "requires": {
+ "cross-spawn": "^7.0.3",
+ "fast-glob": "^3.3.0",
+ "is-glob": "^4.0.3",
+ "open": "^9.1.0",
+ "picocolors": "^1.0.0",
+ "tslib": "^2.6.0"
+ }
+ },
"@protobufjs/aspromise": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz",
@@ -850,6 +2655,12 @@
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.8.0.tgz",
"integrity": "sha512-LzcWltT83s1bthcvjBmiBvGJiiUe84NWRHkw+ZV6Fr41z2FbIzvc815dk2nQ3RAKMuN2fkenM/z3Xv2QzEpYxQ=="
},
+ "@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
+ },
"accepts": {
"version": "1.3.8",
"resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz",
@@ -859,6 +2670,19 @@
"negotiator": "0.6.3"
}
},
+ "acorn": {
+ "version": "8.10.0",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz",
+ "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==",
+ "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": {}
+ },
"ajv": {
"version": "6.12.6",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
@@ -870,6 +2694,27 @@
"uri-js": "^4.2.2"
}
},
+ "ansi-regex": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "dev": true
+ },
+ "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"
+ }
+ },
+ "argparse": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
+ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
+ "dev": true
+ },
"asn1": {
"version": "0.2.6",
"resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz",
@@ -898,6 +2743,12 @@
"resolved": "https://registry.npmjs.org/aws4/-/aws4-1.12.0.tgz",
"integrity": "sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg=="
},
+ "balanced-match": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
+ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
+ "dev": true
+ },
"base64id": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz",
@@ -911,6 +2762,49 @@
"tweetnacl": "^0.14.3"
}
},
+ "big-integer": {
+ "version": "1.6.51",
+ "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.51.tgz",
+ "integrity": "sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg==",
+ "dev": true
+ },
+ "bplist-parser": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/bplist-parser/-/bplist-parser-0.2.0.tgz",
+ "integrity": "sha512-z0M+byMThzQmD9NILRniCUXYsYpjwnlO8N5uCFaCqIOpqRsJCrQL9NK3JsD67CN5a08nF5oIL2bD6loTdHOuKw==",
+ "dev": true,
+ "requires": {
+ "big-integer": "^1.6.44"
+ }
+ },
+ "brace-expansion": {
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+ "dev": true,
+ "requires": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "braces": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
+ "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
+ "dev": true,
+ "requires": {
+ "fill-range": "^7.0.1"
+ }
+ },
+ "bundle-name": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-3.0.0.tgz",
+ "integrity": "sha512-PKA4BeSvBpQKQ8iPOGCSiell+N8P+Tf1DlwqmYhpe2gAhKPHn8EYOxVT+ShuGmhg8lN8XiSlS80yiExKXrURlw==",
+ "dev": true,
+ "requires": {
+ "run-applescript": "^5.0.0"
+ }
+ },
"bytebuffer": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/bytebuffer/-/bytebuffer-5.0.1.tgz",
@@ -919,11 +2813,42 @@
"long": "~3"
}
},
+ "callsites": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
+ "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
+ "dev": true
+ },
"caseless": {
"version": "0.12.0",
"resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz",
"integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw=="
},
+ "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
+ },
"combined-stream": {
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
@@ -932,6 +2857,12 @@
"delayed-stream": "~1.0.0"
}
},
+ "concat-map": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
+ "dev": true
+ },
"cookie": {
"version": "0.4.2",
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz",
@@ -951,6 +2882,17 @@
"vary": "^1"
}
},
+ "cross-spawn": {
+ "version": "7.0.3",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
+ "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
+ "dev": true,
+ "requires": {
+ "path-key": "^3.1.0",
+ "shebang-command": "^2.0.0",
+ "which": "^2.0.1"
+ }
+ },
"dashdash": {
"version": "1.14.1",
"resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz",
@@ -967,11 +2909,54 @@
"ms": "2.1.2"
}
},
+ "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
+ },
+ "default-browser": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-4.0.0.tgz",
+ "integrity": "sha512-wX5pXO1+BrhMkSbROFsyxUm0i/cJEScyNhA4PPxc41ICuv05ZZB/MX28s8aZx6xjmatvebIapF6hLEKEcpneUA==",
+ "dev": true,
+ "requires": {
+ "bundle-name": "^3.0.0",
+ "default-browser-id": "^3.0.0",
+ "execa": "^7.1.1",
+ "titleize": "^3.0.0"
+ }
+ },
+ "default-browser-id": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-3.0.0.tgz",
+ "integrity": "sha512-OZ1y3y0SqSICtE8DE4S8YOE9UZOJ8wO16fKWVP5J1Qz42kV9jcnMVFrEE/noXb/ss3Q4pZIH79kxofzyNNtUNA==",
+ "dev": true,
+ "requires": {
+ "bplist-parser": "^0.2.0",
+ "untildify": "^4.0.0"
+ }
+ },
+ "define-lazy-prop": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz",
+ "integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==",
+ "dev": true
+ },
"delayed-stream": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
"integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ=="
},
+ "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"
+ }
+ },
"ecc-jsbn": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz",
@@ -1003,6 +2988,149 @@
"resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.1.tgz",
"integrity": "sha512-9JktcM3u18nU9N2Lz3bWeBgxVgOKpw7yhRaoxQA3FUDZzzw+9WlA6p4G4u0RixNkg14fH7EfEc/RhpurtiROTQ=="
},
+ "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": {
+ "version": "8.52.0",
+ "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.52.0.tgz",
+ "integrity": "sha512-zh/JHnaixqHZsolRB/w9/02akBk9EPrOs9JwcTP2ek7yL5bVvXuRariiaAjjoJ5DvuwQ1WAE/HsMz+w17YgBCg==",
+ "dev": true,
+ "requires": {
+ "@eslint-community/eslint-utils": "^4.2.0",
+ "@eslint-community/regexpp": "^4.6.1",
+ "@eslint/eslintrc": "^2.1.2",
+ "@eslint/js": "8.52.0",
+ "@humanwhocodes/config-array": "^0.11.13",
+ "@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"
+ }
+ },
+ "eslint-config-prettier": {
+ "version": "9.0.0",
+ "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.0.0.tgz",
+ "integrity": "sha512-IcJsTkJae2S35pRsRAwoCE+925rJJStOdkKnLVgtE+tEpqU0EVVM7OqrwxqgptKdX29NUwC82I5pXsGFIgSevw==",
+ "dev": true,
+ "requires": {}
+ },
+ "eslint-plugin-prettier": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.0.1.tgz",
+ "integrity": "sha512-m3u5RnR56asrwV/lDC4GHorlW75DsFfmUcjfCYylTUs85dBRnB7VM6xG8eCMJdeDRnppzmxZVf1GEPJvl1JmNg==",
+ "dev": true,
+ "requires": {
+ "prettier-linter-helpers": "^1.0.0",
+ "synckit": "^0.8.5"
+ }
+ },
+ "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"
+ }
+ },
+ "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"
+ }
+ },
+ "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"
+ }
+ },
+ "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"
+ }
+ },
+ "estraverse": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
+ "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
+ "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": "7.2.0",
+ "resolved": "https://registry.npmjs.org/execa/-/execa-7.2.0.tgz",
+ "integrity": "sha512-UduyVP7TLB5IcAQl+OzLyLcS/l32W/GLg+AhHJ+ow40FOk2U3SAllPwR44v4vmdFwIWqpdwxxpQbF1n5ta9seA==",
+ "dev": true,
+ "requires": {
+ "cross-spawn": "^7.0.3",
+ "get-stream": "^6.0.1",
+ "human-signals": "^4.3.0",
+ "is-stream": "^3.0.0",
+ "merge-stream": "^2.0.0",
+ "npm-run-path": "^5.1.0",
+ "onetime": "^6.0.0",
+ "signal-exit": "^3.0.7",
+ "strip-final-newline": "^3.0.0"
+ }
+ },
"extend": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
@@ -1018,11 +3146,101 @@
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="
},
+ "fast-diff": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz",
+ "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==",
+ "dev": true
+ },
+ "fast-glob": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz",
+ "integrity": "sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==",
+ "dev": true,
+ "requires": {
+ "@nodelib/fs.stat": "^2.0.2",
+ "@nodelib/fs.walk": "^1.2.3",
+ "glob-parent": "^5.1.2",
+ "merge2": "^1.3.0",
+ "micromatch": "^4.0.4"
+ },
+ "dependencies": {
+ "glob-parent": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
+ "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
+ "dev": true,
+ "requires": {
+ "is-glob": "^4.0.1"
+ }
+ }
+ }
+ },
"fast-json-stable-stringify": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
"integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw=="
},
+ "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
+ },
+ "fastq": {
+ "version": "1.15.0",
+ "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz",
+ "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==",
+ "dev": true,
+ "requires": {
+ "reusify": "^1.0.4"
+ }
+ },
+ "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"
+ }
+ },
+ "fill-range": {
+ "version": "7.0.1",
+ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
+ "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
+ "dev": true,
+ "requires": {
+ "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"
+ }
+ },
+ "flat-cache": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.1.1.tgz",
+ "integrity": "sha512-/qM2b3LUIaIgviBQovTLvijfyOQXPtSRnRK26ksj2J7rzPIecePUIpJsZ4T02Qg+xiAEKIs5K8dsHEd+VaKa/Q==",
+ "dev": true,
+ "requires": {
+ "flatted": "^3.2.9",
+ "keyv": "^4.5.3",
+ "rimraf": "^3.0.2"
+ }
+ },
+ "flatted": {
+ "version": "3.2.9",
+ "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.9.tgz",
+ "integrity": "sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==",
+ "dev": true
+ },
"forever-agent": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz",
@@ -1038,6 +3256,18 @@
"mime-types": "^2.1.12"
}
},
+ "fs.realpath": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+ "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
+ "dev": true
+ },
+ "get-stream": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz",
+ "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==",
+ "dev": true
+ },
"getpass": {
"version": "0.1.7",
"resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz",
@@ -1046,6 +3276,44 @@
"assert-plus": "^1.0.0"
}
},
+ "glob": {
+ "version": "7.2.3",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
+ "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
+ "dev": true,
+ "requires": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.1.1",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ }
+ },
+ "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.23.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-13.23.0.tgz",
+ "integrity": "sha512-XAmF0RjlrjY23MA51q3HltdlGxUpXPvg0GioKiD9X6HD28iMjo2dKC8Vqwm7lne4GNr78+RHTfliktR6ZH09wA==",
+ "dev": true,
+ "requires": {
+ "type-fest": "^0.20.2"
+ }
+ },
+ "graphemer": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz",
+ "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==",
+ "dev": true
+ },
"har-schema": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz",
@@ -1060,6 +3328,12 @@
"har-schema": "^2.0.0"
}
},
+ "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
+ },
"http-signature": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz",
@@ -1070,6 +3344,50 @@
"sshpk": "^1.7.0"
}
},
+ "human-signals": {
+ "version": "4.3.1",
+ "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-4.3.1.tgz",
+ "integrity": "sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ==",
+ "dev": true
+ },
+ "ignore": {
+ "version": "5.2.4",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz",
+ "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==",
+ "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"
+ }
+ },
+ "imurmurhash": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
+ "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
+ "dev": true
+ },
+ "inflight": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
+ "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
+ "dev": true,
+ "requires": {
+ "once": "^1.3.0",
+ "wrappy": "1"
+ }
+ },
+ "inherits": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
+ "dev": true
+ },
"ip6": {
"version": "0.0.4",
"resolved": "https://registry.npmjs.org/ip6/-/ip6-0.0.4.tgz",
@@ -1080,21 +3398,107 @@
"resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.2.0.tgz",
"integrity": "sha512-ku//LD7ie/m9UVGCm9KweBIIHP4mB0maNGvav6Hz778fQCNLQF7iZ+H/UuHuqmjJCHCpA5hw8hOeRKxZl8IlXw=="
},
+ "is-docker": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz",
+ "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==",
+ "dev": true
+ },
+ "is-extglob": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
+ "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
+ "dev": true
+ },
+ "is-glob": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
+ "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
+ "dev": true,
+ "requires": {
+ "is-extglob": "^2.1.1"
+ }
+ },
+ "is-inside-container": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz",
+ "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==",
+ "dev": true,
+ "requires": {
+ "is-docker": "^3.0.0"
+ }
+ },
+ "is-number": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
+ "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-stream": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz",
+ "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==",
+ "dev": true
+ },
"is-typedarray": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
"integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA=="
},
+ "is-wsl": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz",
+ "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==",
+ "dev": true,
+ "requires": {
+ "is-docker": "^2.0.0"
+ },
+ "dependencies": {
+ "is-docker": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz",
+ "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==",
+ "dev": true
+ }
+ }
+ },
+ "isexe": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
+ "dev": true
+ },
"isstream": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
"integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g=="
},
+ "js-yaml": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
+ "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
+ "dev": true,
+ "requires": {
+ "argparse": "^2.0.1"
+ }
+ },
"jsbn": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
"integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg=="
},
+ "json-buffer": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz",
+ "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==",
+ "dev": true
+ },
"json-schema": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz",
@@ -1105,6 +3509,12 @@
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
"integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="
},
+ "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
+ },
"json-stringify-safe": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
@@ -1121,11 +3531,67 @@
"verror": "1.10.0"
}
},
+ "keyv": {
+ "version": "4.5.4",
+ "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz",
+ "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==",
+ "dev": true,
+ "requires": {
+ "json-buffer": "3.0.1"
+ }
+ },
+ "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"
+ }
+ },
+ "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.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
+ },
"long": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/long/-/long-3.2.0.tgz",
"integrity": "sha512-ZYvPPOMqUwPoDsbJaR10iQJYnMuZhRTvHYl62ErLIEX7RgFlziSBUUvrt3OVfc47QlHHpzPZYP17g3Fv7oeJkg=="
},
+ "merge-stream": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
+ "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==",
+ "dev": true
+ },
+ "merge2": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
+ "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
+ "dev": true
+ },
+ "micromatch": {
+ "version": "4.0.5",
+ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz",
+ "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==",
+ "dev": true,
+ "requires": {
+ "braces": "^3.0.2",
+ "picomatch": "^2.3.1"
+ }
+ },
"mime-db": {
"version": "1.52.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
@@ -1139,16 +3605,54 @@
"mime-db": "1.52.0"
}
},
+ "mimic-fn": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz",
+ "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==",
+ "dev": true
+ },
+ "minimatch": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+ "dev": true,
+ "requires": {
+ "brace-expansion": "^1.1.7"
+ }
+ },
"ms": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
},
+ "natural-compare": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
+ "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",
+ "dev": true
+ },
"negotiator": {
"version": "0.6.3",
"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz",
"integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg=="
},
+ "npm-run-path": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.1.0.tgz",
+ "integrity": "sha512-sJOdmRGrY2sjNTRMbSvluQqg+8X7ZK61yvzBEIDhz4f8z1TZFYABsqjjCBd/0PUNE9M6QDgHJXQkGUEm7Q+l9Q==",
+ "dev": true,
+ "requires": {
+ "path-key": "^4.0.0"
+ },
+ "dependencies": {
+ "path-key": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz",
+ "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==",
+ "dev": true
+ }
+ }
+ },
"oauth-sign": {
"version": "0.9.0",
"resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz",
@@ -1159,11 +3663,133 @@
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
"integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg=="
},
+ "once": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+ "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
+ "dev": true,
+ "requires": {
+ "wrappy": "1"
+ }
+ },
+ "onetime": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz",
+ "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==",
+ "dev": true,
+ "requires": {
+ "mimic-fn": "^4.0.0"
+ }
+ },
+ "open": {
+ "version": "9.1.0",
+ "resolved": "https://registry.npmjs.org/open/-/open-9.1.0.tgz",
+ "integrity": "sha512-OS+QTnw1/4vrf+9hh1jc1jnYjzSG4ttTBB8UxOwAnInG3Uo4ssetzC1ihqaIHjLJnA5GGlRl6QlZXOTQhRBUvg==",
+ "dev": true,
+ "requires": {
+ "default-browser": "^4.0.0",
+ "define-lazy-prop": "^3.0.0",
+ "is-inside-container": "^1.0.0",
+ "is-wsl": "^2.2.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-limit": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
+ "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
+ "dev": true,
+ "requires": {
+ "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"
+ }
+ },
+ "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"
+ }
+ },
+ "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
+ },
+ "path-is-absolute": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+ "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
+ "dev": true
+ },
+ "path-key": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
+ "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
+ "dev": true
+ },
"performance-now": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
"integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow=="
},
+ "picocolors": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
+ "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==",
+ "dev": true
+ },
+ "picomatch": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
+ "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
+ "dev": true
+ },
+ "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
+ },
+ "prettier": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.0.3.tgz",
+ "integrity": "sha512-L/4pUDMxcNa8R/EthV08Zt42WBO4h1rarVtK0K+QJG0X187OLo7l699jWw0GKuwzkPQ//jMFA/8Xm6Fh3J/DAg==",
+ "dev": true
+ },
+ "prettier-linter-helpers": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz",
+ "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==",
+ "dev": true,
+ "requires": {
+ "fast-diff": "^1.1.2"
+ }
+ },
"protobufjs": {
"version": "6.11.4",
"resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-6.11.4.tgz",
@@ -1206,6 +3832,12 @@
"resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz",
"integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA=="
},
+ "queue-microtask": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
+ "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
+ "dev": true
+ },
"range_check": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/range_check/-/range_check-1.4.0.tgz",
@@ -1242,6 +3874,106 @@
"uuid": "^3.3.2"
}
},
+ "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
+ },
+ "reusify": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
+ "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==",
+ "dev": true
+ },
+ "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"
+ }
+ },
+ "run-applescript": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-5.0.0.tgz",
+ "integrity": "sha512-XcT5rBksx1QdIhlFOCtgZkB99ZEouFZ1E2Kc2LHqNW13U3/74YGdkQRmThTwxy4QIyookibDKYZOPqX//6BlAg==",
+ "dev": true,
+ "requires": {
+ "execa": "^5.0.0"
+ },
+ "dependencies": {
+ "execa": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz",
+ "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==",
+ "dev": true,
+ "requires": {
+ "cross-spawn": "^7.0.3",
+ "get-stream": "^6.0.0",
+ "human-signals": "^2.1.0",
+ "is-stream": "^2.0.0",
+ "merge-stream": "^2.0.0",
+ "npm-run-path": "^4.0.1",
+ "onetime": "^5.1.2",
+ "signal-exit": "^3.0.3",
+ "strip-final-newline": "^2.0.0"
+ }
+ },
+ "human-signals": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz",
+ "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==",
+ "dev": true
+ },
+ "is-stream": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz",
+ "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==",
+ "dev": true
+ },
+ "mimic-fn": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz",
+ "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==",
+ "dev": true
+ },
+ "npm-run-path": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz",
+ "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==",
+ "dev": true,
+ "requires": {
+ "path-key": "^3.0.0"
+ }
+ },
+ "onetime": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz",
+ "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==",
+ "dev": true,
+ "requires": {
+ "mimic-fn": "^2.1.0"
+ }
+ },
+ "strip-final-newline": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz",
+ "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==",
+ "dev": true
+ }
+ }
+ },
+ "run-parallel": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
+ "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
+ "dev": true,
+ "requires": {
+ "queue-microtask": "^1.2.2"
+ }
+ },
"safe-buffer": {
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
@@ -1252,6 +3984,27 @@
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
},
+ "shebang-command": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
+ "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
+ "dev": true,
+ "requires": {
+ "shebang-regex": "^3.0.0"
+ }
+ },
+ "shebang-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
+ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
+ "dev": true
+ },
+ "signal-exit": {
+ "version": "3.0.7",
+ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
+ "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==",
+ "dev": true
+ },
"socket.io": {
"version": "4.7.2",
"resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.7.2.tgz",
@@ -1299,6 +4052,67 @@
"tweetnacl": "~0.14.0"
}
},
+ "strip-ansi": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "^5.0.1"
+ }
+ },
+ "strip-final-newline": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz",
+ "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==",
+ "dev": true
+ },
+ "strip-json-comments": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
+ "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
+ "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"
+ }
+ },
+ "synckit": {
+ "version": "0.8.5",
+ "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.8.5.tgz",
+ "integrity": "sha512-L1dapNV6vu2s/4Sputv8xGsCdAVlb5nRDMFU/E27D44l5U6cw1g0dGd45uLc+OXjNMmF4ntiMdCimzcjFKQI8Q==",
+ "dev": true,
+ "requires": {
+ "@pkgr/utils": "^2.3.1",
+ "tslib": "^2.5.0"
+ }
+ },
+ "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
+ },
+ "titleize": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/titleize/-/titleize-3.0.0.tgz",
+ "integrity": "sha512-KxVu8EYHDPBdUYdKZdKtU2aj2XfEx9AfjXxE/Aj0vT06w2icA09Vus1rh6eSu1y01akYg6BjIK/hxyLJINoMLQ==",
+ "dev": true
+ },
+ "to-regex-range": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
+ "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
+ "dev": true,
+ "requires": {
+ "is-number": "^7.0.0"
+ }
+ },
"tough-cookie": {
"version": "2.5.0",
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz",
@@ -1308,6 +4122,12 @@
"punycode": "^2.1.1"
}
},
+ "tslib": {
+ "version": "2.6.2",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz",
+ "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==",
+ "dev": true
+ },
"tunnel-agent": {
"version": "0.6.0",
"resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
@@ -1321,6 +4141,27 @@
"resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
"integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA=="
},
+ "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-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
+ },
+ "untildify": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/untildify/-/untildify-4.0.0.tgz",
+ "integrity": "sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==",
+ "dev": true
+ },
"uri-js": {
"version": "4.4.1",
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
@@ -1349,11 +4190,32 @@
"extsprintf": "^1.2.0"
}
},
+ "which": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
+ "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
+ "dev": true,
+ "requires": {
+ "isexe": "^2.0.0"
+ }
+ },
+ "wrappy": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
+ "dev": true
+ },
"ws": {
"version": "8.11.0",
"resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz",
"integrity": "sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==",
"requires": {}
+ },
+ "yocto-queue": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
+ "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
+ "dev": true
}
}
}
diff --git a/node/package.json b/node/package.json
index 3267a6b..42a750f 100644
--- a/node/package.json
+++ b/node/package.json
@@ -5,15 +5,27 @@
"main": "server.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
- "start": "node server.js EU I 8120"
+ "start": "node server.js EU I 8120",
+ "lint": "eslint --ext .js .",
+ "lint:fix": "eslint --fix --ext .js ."
},
"author": "",
"license": "AdventureLandOnlyUse",
"dependencies": {
- "socket.io": "^4.0.0",
- "request": "^2.88.2",
- "range_check": "^1.4.0",
+ "bytebuffer": "^5.0.1",
"protobufjs": "^6.9.0",
- "bytebuffer": "^5.0.1"
- }
-}
+ "range_check": "^1.4.0",
+ "request": "^2.88.2",
+ "socket.io": "^4.0.0"
+ },
+ "devDependencies": {
+ "eslint": "^8.52.0",
+ "eslint-config-prettier": "^9.0.0",
+ "eslint-plugin-prettier": "^5.0.1",
+ "prettier": "^3.0.3"
+ },
+ "eslintIgnore": [
+ "node_modules/*",
+ "data.js"
+ ]
+}
\ No newline at end of file
diff --git a/node/precompute.js b/node/precompute.js
index d5d258a..e086d1c 100644
--- a/node/precompute.js
+++ b/node/precompute.js
@@ -1,27 +1,35 @@
-var is_game=0,is_server=0,is_code=0;
-var variables=require('./variables');
-var is_sdk=variables.is_sdk;
-var fs=require('fs');
-var precomputed=null;
-eval(""+fs.readFileSync(variables.cfunctions_path));
-eval(""+fs.readFileSync(variables.functions_path));
-var mode={},server_id='precompute',server_auth="123456",base_url=variables.base_url;
+var is_game = 0;
+var is_server = 0;
+var is_code = 0;
+var variables = require("./variables");
+var is_sdk = variables.is_sdk;
+var fs = require("fs");
+var precomputed = null;
+eval("" + fs.readFileSync(variables.cfunctions_path));
+eval("" + fs.readFileSync(variables.functions_path));
+var mode = {};
+var server_id = "precompute";
+var server_auth = "123456";
+var base_url = variables.base_url;
-appengine_call("reload_server",{keyword:variables.keyword},function(result){
- if(result.failed) return;
- G=result.game;
- var start=new Date();
- for(var mname in G.maps)
- {
- if(G.maps[mname].ignore) continue;
- var cstart=new Date();
- server_bfs(mname);
- console.log("Precomputed: "+mname+" in "+mssince(cstart)+"ms");
+appengine_call("reload_server", { keyword: variables.keyword }, function (result) {
+ if (result.failed) {
+ return;
}
- console.log("Done: "+mssince(start)+"ms");
- var precomputed={};
- precomputed.version=G.version;
- precomputed.amap_data=amap_data;
- precomputed.smap_data=smap_data;
- fs.writeFileSync(variables.data_path,'var precomputed='+JSON.stringify(precomputed)+';');
-});
\ No newline at end of file
+ G = result.game;
+ var start = new Date();
+ for (var mname in G.maps) {
+ if (G.maps[mname].ignore) {
+ continue;
+ }
+ var cstart = new Date();
+ server_bfs(mname);
+ console.log("Precomputed: " + mname + " in " + mssince(cstart) + "ms");
+ }
+ console.log("Done: " + mssince(start) + "ms");
+ var precomputed = {};
+ precomputed.version = G.version;
+ precomputed.amap_data = amap_data;
+ precomputed.smap_data = smap_data;
+ fs.writeFileSync(variables.data_path, "var precomputed=" + JSON.stringify(precomputed) + ";");
+});
diff --git a/node/server.js b/node/server.js
index 76c0118..9efe6d6 100644
--- a/node/server.js
+++ b/node/server.js
@@ -1,980 +1,1482 @@
-var is_game=0,is_server=1,is_code=0,is_pvp=false;
-var server={
- started:false,
- live:false,
- last_update:false,
- shutdown:false, // shutdown start
- stopped:false, // shutdown end
- s:{},
+var is_game = 0;
+var is_server = 1;
+var is_code = 0;
+var is_pvp = false;
+var server = {
+ started: false,
+ live: false,
+ last_update: false,
+ shutdown: false, // shutdown start
+ stopped: false, // shutdown end
+ s: {},
};
-var variables=require('./variables');
-var is_sdk=variables.is_sdk;
-var app=require('http').createServer(http_handler);
+var variables = require("./variables");
+var is_sdk = variables.is_sdk;
+var app = require("http").createServer(http_handler);
//var io=require('socket.io')(app,{pingInterval:2400,pingTimeout:6000});
-var io=require('socket.io')(app,{pingInterval:4000,pingTimeout:12000,cors:{
- origin:false,
- methods:"GET,HEAD,PUT,PATCH,POST,DELETE",
- credentials:true,
- }}); // default is 25000 to 60000
-var fs=require('fs'),url=require('url');
-var {Worker,SHARE_ENV}=require('worker_threads'),workers=[],wlast=0;
-eval(""+fs.readFileSync(variables.cfunctions_path));
-eval(""+fs.readFileSync(variables.functions_path));
-eval(""+fs.readFileSync(variables.data_path));
-var base_url=variables.base_url,server_id="1",server_auth="123456",server_name="";
-var players={};
-var dc_players={};
-var sockets={};
-var observers={};
-var total_monsters=0;
-var max_players=96;
-var chests={};
-var projectiles={};
-var name_to_id={},id_to_id={};
-var invitations={},challenges={},magiportations={},requests={},parties={},frequests={},trequests={};
-var total_moves=1,total_players=0,unique_players=0;
-var observer_map="winterland",observer_x=0,observer_y=0;
-var merchant_map="main",merchant_y=-50,merchant_x=0,total_merchants=0;
-var csold=[],cfound=[]; // cache of S.sold + S.found
-var monster_c={}; // monster counts
-var pwns=[],pend=0;
-var tavern={};
-var dbase={h:8,v:7,vn:2}; // default-base
-var G={},D={},P={}; // the game
-var S={}; // server data
-var T={}; // cosmetics
-var E={
- schedule:{
- time_offset:0,
- dailies:[13,20],
- nightlies:[23],
- night:false,
+var io = require("socket.io")(app, {
+ pingInterval: 4000,
+ pingTimeout: 12000,
+ cors: {
+ origin: false,
+ methods: "GET,HEAD,PUT,PATCH,POST,DELETE",
+ credentials: true,
+ },
+}); // default is 25000 to 60000
+var fs = require("fs");
+var url = require("url");
+var { Worker, SHARE_ENV } = require("worker_threads");
+var workers = [];
+var wlast = 0;
+eval("" + fs.readFileSync(variables.cfunctions_path));
+eval("" + fs.readFileSync(variables.functions_path));
+eval("" + fs.readFileSync(variables.data_path));
+var base_url = variables.base_url;
+var server_id = "1";
+var server_auth = "123456";
+var server_name = "";
+var players = {};
+var dc_players = {};
+var sockets = {};
+var observers = {};
+var total_monsters = 0;
+var max_players = 96;
+var chests = {};
+var projectiles = {};
+var name_to_id = {};
+var id_to_id = {};
+var invitations = {};
+var challenges = {};
+var magiportations = {};
+var requests = {};
+var parties = {};
+var frequests = {};
+var trequests = {};
+var total_moves = 1;
+var total_players = 0;
+var unique_players = 0;
+var observer_map = "winterland";
+var observer_x = 0;
+var observer_y = 0;
+var merchant_map = "main";
+var merchant_y = -50;
+var merchant_x = 0;
+var total_merchants = 0;
+var csold = [];
+var cfound = []; // cache of S.sold + S.found
+var monster_c = {}; // monster counts
+var pwns = [];
+var pend = 0;
+var tavern = {};
+var dbase = { h: 8, v: 7, vn: 2 }; // default-base
+var G = {};
+var D = {};
+var P = {}; // the game
+var S = {}; // server data
+var T = {}; // cosmetics
+var E = {
+ schedule: {
+ time_offset: 0,
+ dailies: [13, 20],
+ nightlies: [23],
+ night: false,
},
}; // server event data
-var TX=[],TXX={}; // all inter account transactions [07/02/22]
-var B={
- "ext_vision":120, // extends the vision by 120 each at all 4 directions -- obsolete now
- "u_boundary":70, // when an entity moves 70px in x or y, triggers .u || xy_u_logic, last_u
- "u_vision":65, // when an entity moves 65px in x or y, new entities in the new area are sent || xy_upush_logic, last_upush
- "vision":[700,500],
- "max_vision":1000, // used at the 'attack'/'heal'-'nothtere' logic
- "dist":400,
- "sell_dist":400,
- "door_dist":112,
+var TX = [];
+var TXX = {}; // all inter account transactions [07/02/22]
+var B = {
+ ext_vision: 120, // extends the vision by 120 each at all 4 directions -- obsolete now
+ u_boundary: 70, // when an entity moves 70px in x or y, triggers .u || xy_u_logic, last_u
+ u_vision: 65, // when an entity moves 65px in x or y, new entities in the new area are sent || xy_upush_logic, last_upush
+ vision: [700, 500],
+ max_vision: 1000, // used at the 'attack'/'heal'-'nothtere' logic
+ dist: 400,
+ sell_dist: 400,
+ door_dist: 112,
// game dynamics
- "transporter_dist":160,
- "rip_time":12,
- "hlevel_loss":3,
- "heal_multiplier":1,
- "arena_limit":1,
- "use_pack_golds":true,
- "v":true,
- "dps_heal_mult":1.8, // originally 1.6
- "dps_tank_mult":0.25, // originally 0.25
- "game_loop_log_edge":60,
- "instance_loop_log_edge":120,
- "m_outgoing_gmult":0.12,
- "start_map":"main",
- "free_last_hits":false,
- "pause_instances":true,
- "global_drops":true,
+ transporter_dist: 160,
+ rip_time: 12,
+ hlevel_loss: 3,
+ heal_multiplier: 1,
+ arena_limit: 1,
+ use_pack_golds: true,
+ v: true,
+ dps_heal_mult: 1.8, // originally 1.6
+ dps_tank_mult: 0.25, // originally 0.25
+ game_loop_log_edge: 60,
+ instance_loop_log_edge: 120,
+ m_outgoing_gmult: 0.12,
+ start_map: "main",
+ free_last_hits: false,
+ pause_instances: true,
+ global_drops: true,
};
-var CC={
- "auth":2,
- "move":1.5,
- "players":12,
- "secondhands":16,
- "friend":24,
- "send_updates":12,
- "cruise":10,
- "random_look":10,
- "equip":3,
- "unequip":6,
- "tracker":50,
- "ccreport":3,
+var CC = {
+ auth: 2,
+ move: 1.5,
+ players: 12,
+ secondhands: 16,
+ friend: 24,
+ send_updates: 12,
+ cruise: 10,
+ random_look: 10,
+ equip: 3,
+ unequip: 6,
+ tracker: 50,
+ ccreport: 3,
};
-var limits={
- "calls":200, // 4 seconds
- "party":9,
- "party_max":10,
+var limits = {
+ calls: 200, // 4 seconds
+ party: 9,
+ party_max: 10,
};
-var W={ // warning flags
- "chest":{},
+var W = {
+ // warning flags
+ chest: {},
};
-var mode={
- "range_test":0,
- "path_checks":1, // when pursuing a player, monsters check each x/y-line, stop pursuit on collision [14/08/16]
+var mode = {
+ range_test: 0,
+ path_checks: 1, // when pursuing a player, monsters check each x/y-line, stop pursuit on collision [14/08/16]
//#IDEA: Disable when low performance is detected [14/08/16]
- "upush_test":0, // stops monsters to test the "push" logic
- "random_attacks":0, // a test mode that makes monsters attack nearby players randomly [11/09/16]
- "aggro":1,
- "dpvpblock":1, // double-sided pvp blocks
- "novi":1, // no vision improvement - added as a patch [12/01/17]
- "xyinf":0, //sends xy data for corrections
- "log_pvp":1, //sends pvp data to appengine, mainly to see whether people leech xp from sub-characters [03/02/17]
- "drop_all":0,
- "red_zone":1,
- "lcorrection":1,
- "enforce_smap":1,
- "rbugs":0,
- "noxy":0,
- "nopush":0,
- "freeze_latest":0, // to test latest_calls numbers
- "log_all":0, // logs all incoming websocket calls
- "friendly_fire":1,
- "fast_mlevels":0,
- "map_respawns":0, // respawn at maps or where they define [05/12/18]
- "low49_20xglobal":1, // 20x global drops for <=49 level players [03/02/19]
- "low49_200xgoo":1,
- "pve_safe_magiports":1,
- "instant_monster_attacks":1, // #TODO: Consider dynamically sending target data instantly too
- "drm_check":1,
- "all_roam":0,
- "all_smart":1,
- "prevent_external":0, // for "test" / "hardcore"
- "pvp_level_gap":0, // have to be within 10 level to attack
+ upush_test: 0, // stops monsters to test the "push" logic
+ random_attacks: 0, // a test mode that makes monsters attack nearby players randomly [11/09/16]
+ aggro: 1,
+ dpvpblock: 1, // double-sided pvp blocks
+ novi: 1, // no vision improvement - added as a patch [12/01/17]
+ xyinf: 0, //sends xy data for corrections
+ log_pvp: 1, //sends pvp data to appengine, mainly to see whether people leech xp from sub-characters [03/02/17]
+ drop_all: 0,
+ red_zone: 1,
+ lcorrection: 1,
+ enforce_smap: 1,
+ rbugs: 0,
+ noxy: 0,
+ nopush: 0,
+ freeze_latest: 0, // to test latest_calls numbers
+ log_all: 0, // logs all incoming websocket calls
+ friendly_fire: 1,
+ fast_mlevels: 0,
+ map_respawns: 0, // respawn at maps or where they define [05/12/18]
+ low49_20xglobal: 1, // 20x global drops for <=49 level players [03/02/19]
+ low49_200xgoo: 1,
+ pve_safe_magiports: 1,
+ instant_monster_attacks: 1, // #TODO: Consider dynamically sending target data instantly too
+ drm_check: 1,
+ all_roam: 0,
+ all_smart: 1,
+ prevent_external: 0, // for "test" / "hardcore"
+ pvp_level_gap: 0, // have to be within 10 level to attack
};
-var events={
+var events = {
// SEASONS
- "holidayseason":false,
- "lunarnewyear":false,
- "valentines":false,
- "pinkgoo":0, // every N minutes - 60
- "snowman":20*60, // 1200 normally - 60 - at sprocess_game_data
- "egghunt":0, // every N minutes - 60
+ holidayseason: false,
+ lunarnewyear: false,
+ valentines: false,
+ pinkgoo: 0, // every N minutes - 60
+ snowman: 20 * 60, // 1200 normally - 60 - at sprocess_game_data
+ egghunt: 0, // every N minutes - 60
// RANDOM
- "halloween":true,
- "goblin":false,
- "goldenbat":160000,
- "cutebee":960000,
- "hide_and_seek":0,
+ halloween: true,
+ goblin: false,
+ goldenbat: 160000,
+ cutebee: 960000,
+ hide_and_seek: 0,
// DAILIES
- "goobrawl":false,
- "crabxx":false,
- "abtesting":false,
+ goobrawl: false,
+ crabxx: false,
+ abtesting: false,
// NIGHTLIES
- "icegolem":false,
- "franky":false,
+ icegolem: false,
+ franky: false,
};
-var dailies=["crabxx","goobrawl","abtesting"]; shuffle(dailies);
-var nightlies=["icegolem","franky"]; shuffle(nightlies);
-if(events.holidayseason) events.snowman=60;
-if(events.valentines) events.pinkgoo=60;
-TIMEO={
- "EU":1,
- "US":-5,
- "ASIA":7,
+var dailies = ["crabxx", "goobrawl", "abtesting"];
+shuffle(dailies);
+var nightlies = ["icegolem", "franky"];
+shuffle(nightlies);
+if (events.holidayseason) {
+ events.snowman = 60;
}
-var perfc={
- "game_loop":{},
- "instance_loop":{},
- "instance_delay":{},
- "cps":0,
- "sxyu":0,
- "game_loops":0,
- "instance_loops":0,
- "roams":0,
- "roam_ops":0,
+if (events.valentines) {
+ events.pinkgoo = 60;
}
-var instances={};
+TIMEO = {
+ EU: 1,
+ US: -5,
+ ASIA: 7,
+};
+var perfc = {
+ game_loop: {},
+ instance_loop: {},
+ instance_delay: {},
+ cps: 0,
+ sxyu: 0,
+ game_loops: 0,
+ instance_loops: 0,
+ roams: 0,
+ roam_ops: 0,
+};
+var instances = {};
// at first there were no instances, monsters were global
// instances improve performance and allow things like dynamic events, dungeons
-var luckm=1,xpm=1,goldm=1,buym=1;
+var luckm = 1;
+var xpm = 1;
+var goldm = 1;
+var buym = 1;
+region = process.argv[process.argv.length - 3];
+server_name = process.argv[process.argv.length - 2];
+port = process.argv[process.argv.length - 1];
-region=process.argv[process.argv.length-3];
-server_name=process.argv[process.argv.length-2];
-port=process.argv[process.argv.length-1];
+E.schedule.time_offset = TIMEO[region];
-E.schedule.time_offset=TIMEO[region];
-
-if(server_name=="HARDCORE")
-{
- gameplay="hardcore";
- xpm=2188;
+if (server_name == "HARDCORE") {
+ gameplay = "hardcore";
+ xpm = 2188;
// luckm=500;
- goldm=12000;
- is_pvp=true;
- variables.ip_limit=1;
- variables.character_limit=1;
- B.rip_time=-1;
- B.heal_multiplier=0.6;
- B.sell_dist=9999999+1000;
- events.golden_bat=8000;
- B.arena_limit=1;
- B.v=false;
- B.free_last_hits=true;
- mode.prevent_external=1;
- mode.pvp_level_gap=1;
+ goldm = 12000;
+ is_pvp = true;
+ variables.ip_limit = 1;
+ variables.character_limit = 1;
+ B.rip_time = -1;
+ B.heal_multiplier = 0.6;
+ B.sell_dist = 9999999 + 1000;
+ events.golden_bat = 8000;
+ B.arena_limit = 1;
+ B.v = false;
+ B.free_last_hits = true;
+ mode.prevent_external = 1;
+ mode.pvp_level_gap = 1;
+} else if (server_name == "TEST") {
+ gameplay = "test";
+ is_pvp = true;
+ variables.ip_limit = 5;
+ variables.character_limit = 5;
+ B.rip_time = -1;
+ B.sell_dist = 9999999 + 1000;
+ B.arena_limit = 1;
+ B.rbugs = 1;
+ mode.prevent_external = 1;
+} else if (server_name == "DUNGEON") {
+ gameplay = "dungeon";
+ is_pvp = true;
+ variables.ip_limit = 1;
+ variables.character_limit = 1;
+ B.start_map = observer_map = "d_e";
+ B.free_last_hits = true;
+ B.pause_instances = false;
+ for (var name in events) {
+ if (is_number(events[name])) {
+ events[name] = (events[name] !== 0 && 9999999999) || 0;
+ } else {
+ events[name] = false;
+ }
+ }
+} else {
+ gameplay = "normal";
}
-else if(server_name=="TEST")
-{
- gameplay="test";
- is_pvp=true;
- variables.ip_limit=5;
- variables.character_limit=5;
- B.rip_time=-1;
- B.sell_dist=9999999+1000;
- B.arena_limit=1;
- B.rbugs=1;
- mode.prevent_external=1;
-}
-else if(server_name=="DUNGEON")
-{
- gameplay="dungeon";
- is_pvp=true;
- variables.ip_limit=1;
- variables.character_limit=1;
- B.start_map=observer_map="d_e";
- B.free_last_hits=true;
- B.pause_instances=false;
- for(var name in events)
- if(is_number(events[name])) events[name]=events[name]!==0&&9999999999||0;
- else events[name]=false;
-}
-else gameplay="normal";
// B.u_boundary=12; B.u_vision=12; B["vision"]=[320,270]
// B.vision[0]*=100; B.vision[1]*=100;
-if(server_name.startsWith("PVP") || server_name.startsWith("HARDCORE"))
-{
- is_pvp=true;
+if (server_name.startsWith("PVP") || server_name.startsWith("HARDCORE")) {
+ is_pvp = true;
// variables.ip_limit=2+1;
// variables.character_limit=1+1;
- luckm*=1.15;
- xpm*=1.20;
- goldm*=1.25;
+ luckm *= 1.15;
+ xpm *= 1.2;
+ goldm *= 1.25;
}
// var secure_app=require('https').createServer(s_options,https_handler); #GTODO: Implement secure communications at one point
-function init_game()
-{
- appengine_call("create_server",{keyword:variables.keyword,port:port,region:region,name:server_name,pvp:is_pvp||'',gameplay:gameplay},function(result){
- try{
- if(result.exists) return [console.log("Server Exists!"),process.exit()];
- // console.log(result);
- server_id=result.id;
- server_auth=result.auth;
- server_name=result.name;
- server_log("Server Live: "+server_name+" "+server_id,1);
- server_log("Node Version: "+process.version,1);
- //server_log("Socket.IO Version: "+require("socket.io").version);
- S=result.data;
- G=result.game;
- server_log("Game Version: "+G.version,1);
- D=result.dynamics;
- if(S) init_server_data(S);
- if(G) sprocess_game_data();
- try{
- app.listen(port);
- init_io();
- // app2.listen(parseInt(port)+40);
- }
- catch(e){
- server.exists=true;
- server.started=true;
- log_trace("port",e);
- return shutdown_routine();
- }
- //create_instance("main2","main2");
- var start=new Date();
- if(gameplay=="normal" || gameplay=="hardcore" || gameplay=="test")
- {
- create_instance("main");
- create_instance("tunnel");
- create_instance("cave");
- create_instance("tavern");
- create_instance("resort_e"); create_instance("resort");
- create_instance("mansion");
- create_instance("woffice");
- create_instance("halloween");
- create_instance("spookytown");
- if(gameplay=="normal") create_instance("test");
- create_instance("arena","arena",{pvp:1});
- create_instance("bank");
- create_instance("bank_b");
- create_instance("bank_u");
- //create_instance("batcave","batcave");
- create_instance("winterland");
- create_instance("winter_inn"); create_instance("winter_inn_rooms");
- create_instance("winter_cave"); create_instance("winter_cove");
- create_instance("desertland");
- create_instance("level1");
- create_instance("level2");
- create_instance("level2n");
- create_instance("level2e");
- create_instance("level2s");
- create_instance("level2w");
- create_instance("level3");
- create_instance("level4");
- create_instance("cyberland");
- create_instance("hut");
- create_instance("mtunnel");
- create_instance("ship0");
- create_instance("goobrawl");
- create_instance("d_e"); create_instance("d_g"); create_instance("d_b1"); create_instance("d_a1"); create_instance("d_a2");
- server_bfs("crypt");
- server_bfs("winter_instance");
- server_bfs("tomb");
- server_bfs("dungeon0");
- server_bfs("cgallery");
- }
- else if(gameplay=="dungeon")
- {
- for(var name in G.maps)
- if(G.maps[name].world=="dungeon")
- create_instance(name);
- }
- create_instance("jail");
- console.log("Calculations took: "+mssince(start)+"ms");
- shuffle(hiding_places);
- init_tavern();
- init_server();
- server.started=true;
- server.live=true;
- server.last_update=new Date();
- }
- catch(e)
+function init_game() {
+ appengine_call(
+ "create_server",
{
- log_trace("init",e);
- }
- },function(){
- console.log("#X init_game's create_server call failed");
- });
+ keyword: variables.keyword,
+ port: port,
+ region: region,
+ name: server_name,
+ pvp: is_pvp || "",
+ gameplay: gameplay,
+ },
+ function (result) {
+ try {
+ if (result.exists) {
+ return [console.log("Server Exists!"), process.exit()];
+ }
+ // console.log(result);
+ server_id = result.id;
+ server_auth = result.auth;
+ server_name = result.name;
+ server_log("Server Live: " + server_name + " " + server_id, 1);
+ server_log("Node Version: " + process.version, 1);
+ //server_log("Socket.IO Version: "+require("socket.io").version);
+ S = result.data;
+ G = result.game;
+ server_log("Game Version: " + G.version, 1);
+ D = result.dynamics;
+ if (S) {
+ init_server_data(S);
+ }
+ if (G) {
+ sprocess_game_data();
+ }
+ try {
+ app.listen(port);
+ init_io();
+ // app2.listen(parseInt(port)+40);
+ } catch (e) {
+ server.exists = true;
+ server.started = true;
+ log_trace("port", e);
+ return shutdown_routine();
+ }
+ //create_instance("main2","main2");
+ var start = new Date();
+ if (gameplay == "normal" || gameplay == "hardcore" || gameplay == "test") {
+ create_instance("main");
+ create_instance("tunnel");
+ create_instance("cave");
+ create_instance("tavern");
+ create_instance("resort_e");
+ create_instance("resort");
+ create_instance("mansion");
+ create_instance("woffice");
+ create_instance("halloween");
+ create_instance("spookytown");
+ if (gameplay == "normal") {
+ create_instance("test");
+ }
+ create_instance("arena", "arena", { pvp: 1 });
+ create_instance("bank");
+ create_instance("bank_b");
+ create_instance("bank_u");
+ //create_instance("batcave","batcave");
+ create_instance("winterland");
+ create_instance("winter_inn");
+ create_instance("winter_inn_rooms");
+ create_instance("winter_cave");
+ create_instance("winter_cove");
+ create_instance("desertland");
+ create_instance("level1");
+ create_instance("level2");
+ create_instance("level2n");
+ create_instance("level2e");
+ create_instance("level2s");
+ create_instance("level2w");
+ create_instance("level3");
+ create_instance("level4");
+ create_instance("cyberland");
+ create_instance("hut");
+ create_instance("mtunnel");
+ create_instance("ship0");
+ create_instance("goobrawl");
+ create_instance("d_e");
+ create_instance("d_g");
+ create_instance("d_b1");
+ create_instance("d_a1");
+ create_instance("d_a2");
+ server_bfs("crypt");
+ server_bfs("winter_instance");
+ server_bfs("tomb");
+ server_bfs("dungeon0");
+ server_bfs("cgallery");
+ } else if (gameplay == "dungeon") {
+ for (var name in G.maps) {
+ if (G.maps[name].world == "dungeon") {
+ create_instance(name);
+ }
+ }
+ }
+ create_instance("jail");
+ console.log("Calculations took: " + mssince(start) + "ms");
+ shuffle(hiding_places);
+ init_tavern();
+ init_server();
+ server.started = true;
+ server.live = true;
+ server.last_update = new Date();
+ } catch (e) {
+ log_trace("init", e);
+ }
+ },
+ function () {
+ console.log("#X init_game's create_server call failed");
+ },
+ );
}
init_game();
-function reload_server(to_broadcast,change)
-{
- appengine_call("reload_server",{keyword:variables.keyword,port:port,region:region,pvp:is_pvp||'',gameplay:gameplay},function(result){
- try{
- G=result.game;
- D=result.dynamics;
- sprocess_game_data();
- prop_cache={};
- if(to_broadcast) broadcast("reloaded",{change:change||""});
- }
- catch(e)
- {
- broadcast("notice",{message:"Server Live Reload Failed"});
- log_trace("#X live_reload",e);
- }
- },function(){
- // setTimeout(init_game,1000);
- server_log("#X live_reload failed",1);
- broadcast("notice",{message:"Live Reload Failed"});
- });
+function reload_server(to_broadcast, change) {
+ appengine_call(
+ "reload_server",
+ { keyword: variables.keyword, port: port, region: region, pvp: is_pvp || "", gameplay: gameplay },
+ function (result) {
+ try {
+ G = result.game;
+ D = result.dynamics;
+ sprocess_game_data();
+ prop_cache = {};
+ if (to_broadcast) {
+ broadcast("reloaded", { change: change || "" });
+ }
+ } catch (e) {
+ broadcast("notice", { message: "Server Live Reload Failed" });
+ log_trace("#X live_reload", e);
+ }
+ },
+ function () {
+ // setTimeout(init_game,1000);
+ server_log("#X live_reload failed", 1);
+ broadcast("notice", { message: "Live Reload Failed" });
+ },
+ );
}
-function decode_http_data(data)
-{
+function decode_http_data(data) {
// #TODO: Find a better way to transfer data [28/09/17]
- var result=decodeURIComponent(data).replace_all("u'","'").replace_all("'",'"').replace_all("+"," ").replace_all("%2B","+");
+ var result = decodeURIComponent(data)
+ .replace_all("u'", "'")
+ .replace_all("'", '"')
+ .replace_all("+", " ")
+ .replace_all("%2B", "+");
return result;
}
-function parse_http_json(data)
-{
- var result=decode_http_data(data),json={};
- try{
- json=JSON.parse(result);
- }
- catch(e){
- console.log("\n"+data);
- log_trace("parse_http_json",e);
+function parse_http_json(data) {
+ var result = decode_http_data(data);
+ var json = {};
+ try {
+ json = JSON.parse(result);
+ } catch (e) {
+ console.log("\n" + data);
+ log_trace("parse_http_json", e);
}
return json;
}
-function http_handler(request,response)
-{
+function http_handler(request, response) {
var body = [];
- request.on('error', function(err) {
- server_log("http_err: "+err,1);
- }).on('data', function(chunk) {
- body.push(chunk);
- }).on('end', function() {
- body = Buffer.concat(body).toString();
- try{
- // server_log("http_handle's end");
- var url_parts = url.parse(request.url,true),args=url_parts.query,output="";
- //console.log(body);
- (body||"").split("&").forEach(function(pv){
- var pvp=pv.split("=");
- args[pvp[0]]=pvp[1];
- });
- if(args.checkin)
- {
- // console.log(JSON.stringify(args));
- // safe_search(request,"::1");
- // console.log(JSON.stringify(request.headers));
- console.log("start"); req=request;
- console.log(req.connection ? req.connection.remoteAddress : null);
- console.log(req.socket ? req.socket.remoteAddress : null);
- console.log((req.connection && req.connection.socket) ? req.connection.socket.remoteAddress : null);
- console.log(req.info ? req.info.remoteAddress : null);
- var ip=getClientIp(request),id=id_to_id[args.id];
- // console.log(ip);
- if(players[id] && players[id].ipass==args.ipass)
- {
- players[id].last_ip=ip;
- players[id].last_ipass=new Date();
- // server_log("ipass for "+players[id].name);
+ request
+ .on("error", function (err) {
+ server_log("http_err: " + err, 1);
+ })
+ .on("data", function (chunk) {
+ body.push(chunk);
+ })
+ .on("end", function () {
+ body = Buffer.concat(body).toString();
+ try {
+ // server_log("http_handle's end");
+ var url_parts = url.parse(request.url, true);
+ var args = url_parts.query;
+ var output = "";
+ //console.log(body);
+ (body || "").split("&").forEach(function (pv) {
+ var pvp = pv.split("=");
+ args[pvp[0]] = pvp[1];
+ });
+ if (args.checkin) {
+ // console.log(JSON.stringify(args));
+ // safe_search(request,"::1");
+ // console.log(JSON.stringify(request.headers));
+ console.log("start");
+ req = request;
+ console.log(req.connection ? req.connection.remoteAddress : null);
+ console.log(req.socket ? req.socket.remoteAddress : null);
+ console.log(req.connection && req.connection.socket ? req.connection.socket.remoteAddress : null);
+ console.log(req.info ? req.info.remoteAddress : null);
+ var ip = getClientIp(request);
+ var id = id_to_id[args.id];
+ // console.log(ip);
+ if (players[id] && players[id].ipass == args.ipass) {
+ players[id].last_ip = ip;
+ players[id].last_ipass = new Date();
+ // server_log("ipass for "+players[id].name);
+ }
+ }
+ if (args.spass != variables.access_master) {
+ response.writeHead(200);
+ response.end(output);
+ return;
+ }
+ if (args.aevent == "shutdown") {
+ shutdown_routine();
+ }
+ if (args.aevent == "cupdate") {
+ var id = id_to_id[args.id];
+ server_log("cupdate for " + args.id + " socket.id: " + id);
+ if (players[id]) {
+ var player = players[id];
+ player.cash = args.cash;
+ if (args.ncash && args.ncash != "0") {
+ player.socket.emit("game_log", { message: "Received " + args.ncash + " shells", color: colors.cash });
+ }
+
+ resend(player, "reopen+nc");
+ }
+ output = "yes";
+ }
+ if (args.aevent == "new_friend") {
+ var id = id_to_id[args.id];
+ server_log("new_friend for " + args.id + " socket.id: " + id, 1);
+ if (players[id]) {
+ var player = players[id];
+ player.friends = parse_http_json(args.friends);
+ player.socket.emit("friend", { event: "new", name: args.name, friends: player.friends });
+ resend(player, "redata");
+ }
+ output = "yes";
+ }
+ if (args.aevent == "lost_friend") {
+ var id = id_to_id[args.id];
+ server_log("lost_friend for " + args.id + " socket.id: " + id, 1);
+ if (players[id]) {
+ var player = players[id];
+ player.friends = parse_http_json(args.friends);
+ player.socket.emit("friend", { event: "lost", friends: player.friends }); // ,name:args.name
+ resend(player, "redata");
+ }
+ output = "yes";
+ }
+ if (args.aevent == "eval") {
+ var data = parse_http_json(args.data);
+ try {
+ eval(decode_http_data(args.code));
+ } catch (e) {
+ console.log("\n" + args.code);
+ log_trace("chttp_eval", e);
+ }
+ output = JSON.stringify(output);
}
- }
- if(args.spass!=variables.master)
- {
response.writeHead(200);
response.end(output);
- return;
+ } catch (e) {
+ log_trace("chttp_err", e);
}
- if(args.aevent=="shutdown")
- {
- shutdown_routine();
- }
- if(args.aevent=="cupdate")
- {
- var id=id_to_id[args.id];
- server_log("cupdate for "+args.id+" socket.id: "+id);
- if(players[id])
- {
- var player=players[id];
- player.cash=args.cash;
- if(args.ncash && args.ncash!="0") player.socket.emit("game_log",{message:"Received "+args.ncash+" shells",color:colors.cash});
-
- resend(player,"reopen+nc");
- }
- output="yes";
- }
- if(args.aevent=="new_friend")
- {
- var id=id_to_id[args.id];
- server_log("new_friend for "+args.id+" socket.id: "+id,1);
- if(players[id])
- {
- var player=players[id];
- player.friends=parse_http_json(args.friends);
- player.socket.emit("friend",{event:"new",name:args.name,friends:player.friends});
- resend(player,"redata");
- }
- output="yes";
- }
- if(args.aevent=="lost_friend")
- {
- var id=id_to_id[args.id];
- server_log("lost_friend for "+args.id+" socket.id: "+id,1);
- if(players[id])
- {
- var player=players[id];
- player.friends=parse_http_json(args.friends);
- player.socket.emit("friend",{event:"lost",friends:player.friends}); // ,name:args.name
- resend(player,"redata");
- }
- output="yes";
- }
- if(args.aevent=="eval")
- {
- var data=parse_http_json(args.data);
- try{
- eval(decode_http_data(args.code));
- }
- catch(e){
- console.log("\n"+args.code);
- log_trace("chttp_eval",e);
- }
- output=JSON.stringify(output);
- }
- response.writeHead(200);
- response.end(output);
- }catch(e){
- log_trace("chttp_err",e);
- }
- });
+ });
}
-function player_to_server(player,place)
-{
- var char={};
- for(prop in player)
- if(!in_arr(prop,["auth","last_sync","socket","character","last_upush","push","last","last_u","width","height","u"]))
- char[prop]=player[prop];
- if(place=="sync" && !Object.keys(player.q).length && player.type!="merchant") delete char.p; // ~20KB - too much [19/11/18]
+function player_to_server(player, place) {
+ var char = {};
+ for (prop in player) {
+ if (
+ !in_arr(prop, [
+ "auth",
+ "last_sync",
+ "socket",
+ "character",
+ "last_upush",
+ "push",
+ "last",
+ "last_u",
+ "width",
+ "height",
+ "u",
+ ])
+ ) {
+ char[prop] = player[prop];
+ }
+ }
+ if (place == "sync" && !Object.keys(player.q).length && player.type != "merchant") {
+ delete char.p;
+ } // ~20KB - too much [19/11/18]
return char;
}
-function player_to_client(player,stranger)
-{
- var data={};
- ["hp","max_hp","mp","max_mp","xp","attack","heal","frequency","speed","range","armor","resistance","level","party",
- "rip","npc","allow","code","afk","target","focus","role","s","c","q","b","age","pdps",
- "id","x","y","moving","going_x","going_y","abs","move_num","angle","cid","guild","team"].forEach(function(p){
- // removed "vx","vy"
- if(player[p]!==undefined) data[p]=player[p];
+function player_to_client(player, stranger) {
+ var data = {};
+ [
+ "hp",
+ "max_hp",
+ "mp",
+ "max_mp",
+ "xp",
+ "attack",
+ "heal",
+ "frequency",
+ "speed",
+ "range",
+ "armor",
+ "resistance",
+ "level",
+ "party",
+ "rip",
+ "npc",
+ "allow",
+ "code",
+ "afk",
+ "target",
+ "focus",
+ "role",
+ "s",
+ "c",
+ "q",
+ "b",
+ "age",
+ "pdps",
+ "id",
+ "x",
+ "y",
+ "moving",
+ "going_x",
+ "going_y",
+ "abs",
+ "move_num",
+ "angle",
+ "cid",
+ "guild",
+ "team",
+ ].forEach(function (p) {
+ // removed "vx","vy"
+ if (player[p] !== undefined) {
+ data[p] = player[p];
+ }
});
- ["stand"].forEach(function(p){
- if(player.p && player.p[p]!==undefined) data[p]=player.p[p];
+ ["stand"].forEach(function (p) {
+ if (player.p && player.p[p] !== undefined) {
+ data[p] = player.p[p];
+ }
});
- if(player.afk=="code") data.controller=player.controller;
- if(player.rip && (player.tcx&&player.tcx.gravestone||player.cx.gravestone)) player.rip=(player.tcx&&player.tcx.gravestone||player.cx.gravestone);
- data.skin=player.tskin||player.skin;
- data.cx=player.tcx||player.cx;
- data.slots=player.cslots;
- if(player.tp) data.tp=true;
- data.ctype=player.type;
- data.owner=!player.private&&player.owner||"";
+ if (player.afk == "code") {
+ data.controller = player.controller;
+ }
+ if (player.rip && ((player.tcx && player.tcx.gravestone) || player.cx.gravestone)) {
+ player.rip = (player.tcx && player.tcx.gravestone) || player.cx.gravestone;
+ }
+ data.skin = player.tskin || player.skin;
+ data.cx = player.tcx || player.cx;
+ data.slots = player.cslots;
+ if (player.tp) {
+ data.tp = true;
+ }
+ data.ctype = player.type;
+ data.owner = (!player.private && player.owner) || "";
- if(player.is_npc)
- {
+ if (player.is_npc) {
// data.id="$"+data.id;
- data.name=player.name;
- if(player.direction!==undefined) data.direction=player.direction,data.npc=player.npc;
+ data.name = player.name;
+ if (player.direction !== undefined) {
+ data.direction = player.direction;
+ data.npc = player.npc;
+ }
}
- if(!stranger)
- {
- ["int","str","dex","vit","for","mp_cost","mp_reduction","max_xp","goldm","xpm","luckm","map","in","isize","esize","gold","cash","targets","m","evasion","miss","reflection","lifesteal","manasteal","rpiercing","apiercing","crit","critdamage","dreturn","tax","xrange","pnresistance","firesistance","fzresistance","phresistance","stresistance","incdmgamp","stun","blast","explosion","courage","mcourage","pcourage","fear"].forEach(function(p){ //"vision",
- data[p]=player[p];
+ if (!stranger) {
+ [
+ "int",
+ "str",
+ "dex",
+ "vit",
+ "for",
+ "mp_cost",
+ "mp_reduction",
+ "max_xp",
+ "goldm",
+ "xpm",
+ "luckm",
+ "map",
+ "in",
+ "isize",
+ "esize",
+ "gold",
+ "cash",
+ "targets",
+ "m",
+ "evasion",
+ "miss",
+ "reflection",
+ "lifesteal",
+ "manasteal",
+ "rpiercing",
+ "apiercing",
+ "crit",
+ "critdamage",
+ "dreturn",
+ "tax",
+ "xrange",
+ "pnresistance",
+ "firesistance",
+ "fzresistance",
+ "phresistance",
+ "stresistance",
+ "incdmgamp",
+ "stun",
+ "blast",
+ "explosion",
+ "courage",
+ "mcourage",
+ "pcourage",
+ "fear",
+ ].forEach(function (p) {
+ //"vision",
+ data[p] = player[p];
});
- data.items=player.citems;
- if(player.user!==undefined)
- {
- data.user=player.cuser;
- if(player.user) data.user.gold=player.user.gold;
+ data.items = player.citems;
+ if (player.user !== undefined) {
+ data.user = player.cuser;
+ if (player.user) {
+ data.user.gold = player.user.gold;
+ }
+ }
+ if (player.socket) {
+ data.cc = get_call_cost(player);
}
- if(player.socket) data.cc=get_call_cost(player);
}
return data;
}
-function monster_to_client(monster,events)
-{
- var data={},def=G.monsters[monster.type];
- ["speed","hp","mp","max_mp","attack","xp","frequency","armor","resistance","1hp","skin","cooperative","drops"].forEach(function(p){ //same array as game.js adopt_soft_properties
- if(p in monster && monster[p]!=def[p]) data[p]=monster[p];
+function monster_to_client(monster, events) {
+ var data = {};
+ var def = G.monsters[monster.type];
+ [
+ "speed",
+ "hp",
+ "mp",
+ "max_mp",
+ "attack",
+ "xp",
+ "frequency",
+ "armor",
+ "resistance",
+ "1hp",
+ "skin",
+ "cooperative",
+ "drops",
+ ].forEach(function (p) {
+ //same array as game.js adopt_soft_properties
+ if (p in monster && monster[p] != def[p]) {
+ data[p] = monster[p];
+ }
});
- if(monster.max_hp!=def.hp) data.max_hp=monster.max_hp;
- ["id","x","y","moving","going_x","going_y","abs","move_num","angle","type","cid","target","focus","s"].forEach(function(p){ // removed "vx","vy" from both datasets [16/04/18]
- if(monster[p]!==undefined) data[p]=monster[p];
+ if (monster.max_hp != def.hp) {
+ data.max_hp = monster.max_hp;
+ }
+ [
+ "id",
+ "x",
+ "y",
+ "moving",
+ "going_x",
+ "going_y",
+ "abs",
+ "move_num",
+ "angle",
+ "type",
+ "cid",
+ "target",
+ "focus",
+ "s",
+ ].forEach(function (p) {
+ // removed "vx","vy" from both datasets [16/04/18]
+ if (monster[p] !== undefined) {
+ data[p] = monster[p];
+ }
});
- if(monster.level>1) data.level=monster.level;
- if(monster.pet) data.pet=true,data.owner=monster.owner,data.name=monster.name;
- if(monster.trap) data.trap=true,data.owner=monster.owner;
+ if (monster.level > 1) {
+ data.level = monster.level;
+ }
+ if (monster.pet) {
+ data.pet = true;
+ data.owner = monster.owner;
+ data.name = monster.name;
+ }
+ if (monster.trap) {
+ data.trap = true;
+ data.owner = monster.owner;
+ }
- if(events && events.length) data.events=events;
+ if (events && events.length) {
+ data.events = events;
+ }
return data;
}
-function player_to_summary(player)
-{
- var summary={skin:player.tskin||player.skin,level:player.level,type:player.type,x:player.x,y:player.y,in:player.in,map:player.map,name:player.name,hp:player.hp,max_hp:player.max_hp};
- if(player.rip) summary.rip=(player.tcx&&player.tcx.gravestone||player.cx.gravestone)||true;
- summary.cx=(player.tcx||player.cx||{});
+function player_to_summary(player) {
+ var summary = {
+ skin: player.tskin || player.skin,
+ level: player.level,
+ type: player.type,
+ x: player.x,
+ y: player.y,
+ in: player.in,
+ map: player.map,
+ name: player.name,
+ hp: player.hp,
+ max_hp: player.max_hp,
+ };
+ if (player.rip) {
+ summary.rip = (player.tcx && player.tcx.gravestone) || player.cx.gravestone || true;
+ }
+ summary.cx = player.tcx || player.cx || {};
return summary;
}
-function save_state(player)
-{
- player.state={"map":player.map,"in":player.in,"hp":player.hp,"mp":player.mp,"s":player.s,"x":player.x,"y":player.y,"restored":false};
+function save_state(player) {
+ player.state = {
+ map: player.map,
+ in: player.in,
+ hp: player.hp,
+ mp: player.mp,
+ s: player.s,
+ x: player.x,
+ y: player.y,
+ restored: false,
+ };
}
-function clean_slate(player)
-{
+function clean_slate(player) {
restore_state(player);
save_state(player);
- player.hp=player.max_hp;
- player.mp=player.max_mp;
- player.s={};
- player.c={};
+ player.hp = player.max_hp;
+ player.mp = player.max_mp;
+ player.s = {};
+ player.c = {};
}
-function restore_state(player,dc)
-{
- if(player.state && !player.state.restored)
- {
- player.hp=player.state.hp;
- player.mp=player.state.mp;
- player.s=player.state.s;
- player.rip=false; if(player.state.rip) player.rip=true;
- if(dc)
- {
- player.map=player.state.map;
- player.in=player.state.in;
- player.x=player.state.x;
- player.y=player.state.y;
+function restore_state(player, dc) {
+ if (player.state && !player.state.restored) {
+ player.hp = player.state.hp;
+ player.mp = player.state.mp;
+ player.s = player.state.s;
+ player.rip = false;
+ if (player.state.rip) {
+ player.rip = true;
}
- player.state.restored=true;
+ if (dc) {
+ player.map = player.state.map;
+ player.in = player.state.in;
+ player.x = player.state.x;
+ player.y = player.state.y;
+ }
+ player.state.restored = true;
}
delete player.team;
delete player.duel;
}
-function party_to_client(oname)
-{
- var list=parties[oname];
- var party={},output=0,length=0,newbies=0,odps={},c={},add=36000;
+function party_to_client(oname) {
+ var list = parties[oname];
+ var party = {};
+ var output = 0;
+ var length = 0;
+ var newbies = 0;
+ var odps = {};
+ var c = {};
+ var add = 36000;
calculate_party(oname);
- list.forEach(function(name){
- var player=players[name_to_id[name]],dps_multiplier=1; if(!player) return;
- if(player.type=="merchant") return;
- if(player.type=="priest") dps_multiplier=1.36;
- length+=1;
- if(player.level<60) newbies+=1;
- output+=player.pdps*dps_multiplier+add;
- odps[player.owner]=(odps[player.owner]||0)+player.pdps*dps_multiplier+add;
- c[player.owner]=(c[player.owner]||0)+1;
+ list.forEach(function (name) {
+ var player = players[name_to_id[name]];
+ var dps_multiplier = 1;
+ if (!player) {
+ return;
+ }
+ if (player.type == "merchant") {
+ return;
+ }
+ if (player.type == "priest") {
+ dps_multiplier = 1.36;
+ }
+ length += 1;
+ if (player.level < 60) {
+ newbies += 1;
+ }
+ output += player.pdps * dps_multiplier + add;
+ odps[player.owner] = (odps[player.owner] || 0) + player.pdps * dps_multiplier + add;
+ c[player.owner] = (c[player.owner] || 0) + 1;
});
- list.forEach(function(name){
- var player=players[name_to_id[name]],dps_multiplier=1; if(!player) return;
- if(player.type=="priest") dps_multiplier=1.36;
- player.share=0;
- if(!output) // to handle an all merchant party
- {
- player.share=1.0/(max(1,list.length)+EPS);
+ list.forEach(function (name) {
+ var player = players[name_to_id[name]];
+ var dps_multiplier = 1;
+ if (!player) {
+ return;
}
- else if(player.type!="merchant")
- {
- player.share=odps[player.owner]/(c[player.owner]+EPS)/(output+EPS);
- player.share=min(1,player.share);
+ if (player.type == "priest") {
+ dps_multiplier = 1.36;
+ }
+ player.share = 0;
+ if (!output) {
+ // to handle an all merchant party
+ player.share = 1.0 / (max(1, list.length) + EPS);
+ } else if (player.type != "merchant") {
+ player.share = odps[player.owner] / (c[player.owner] + EPS) / (output + EPS);
+ player.share = min(1, player.share);
+ }
+ player.party_length = length;
+ player.party_gold = 5;
+ player.party_luck = newbies * 10;
+ player.party_xp = [0, 0, 10, 16, 20, 24, 25, 30, 36, 40, 40, 40, 40][length] || 0;
+ party[name] = {
+ skin: player.tskin || player.skin,
+ level: player.level,
+ type: player.type,
+ x: player.x,
+ y: player.y,
+ in: player.in,
+ map: player.map,
+ share: player.share,
+ pdps: player.pdps,
+ l: length,
+ xp: player.party_xp,
+ luck: player.party_luck,
+ gold: player.party_gold,
+ };
+ if (player.rip) {
+ party[name].rip = (player.tcx && player.tcx.gravestone) || player.cx.gravestone || true;
+ }
+ if (Object.keys(player.tcx || player.cx).length) {
+ party[name].cx = player.tcx || player.cx;
}
- player.party_length=length;
- player.party_gold=5;
- player.party_luck=newbies*10;
- player.party_xp=[0,0,10,16,20,24,25,30,36,40,40,40,40][length]||0;
- party[name]={skin:player.tskin||player.skin,level:player.level,type:player.type,x:player.x,y:player.y,in:player.in,map:player.map,share:player.share,pdps:player.pdps,l:length,xp:player.party_xp,luck:player.party_luck,gold:player.party_gold};
- if(player.rip) party[name].rip=(player.tcx&&player.tcx.gravestone||player.cx.gravestone)||true;
- if(Object.keys(player.tcx||player.cx).length) party[name].cx=(player.tcx||player.cx);
});
// git test
return party;
}
-function send_party_update(oname)
-{
- var party=party_to_client(oname);
- parties[oname].forEach(function(name){
- var player=players[name_to_id[name]];
- if(!player) { console.log("#X party player not found: "+oname); leave_party(oname,{name:name}); return; }
- players[name_to_id[name]].socket.emit("party_update",{list:parties[oname],party:party});
+function send_party_update(oname) {
+ var party = party_to_client(oname);
+ parties[oname].forEach(function (name) {
+ var player = players[name_to_id[name]];
+ if (!player) {
+ console.log("#X party player not found: " + oname);
+ leave_party(oname, { name: name });
+ return;
+ }
+ players[name_to_id[name]].socket.emit("party_update", { list: parties[oname], party: party });
});
}
-function calculate_party(oname)
-{
- var list=parties[oname];
- list.forEach(function(name){
- var player=players[name_to_id[name]]; if(!player) return;
- if(player.type=="merchant") player.party_weight=0;
- player.party_weight=20;
+function calculate_party(oname) {
+ var list = parties[oname];
+ list.forEach(function (name) {
+ var player = players[name_to_id[name]];
+ if (!player) {
+ return;
+ }
+ if (player.type == "merchant") {
+ player.party_weight = 0;
+ }
+ player.party_weight = 20;
});
}
-var stat_to_attr={
- "str":"str",
- "int":"int",
- "dex":"dex",
- "vit":"vit",
- "for":"for",
- "armor":"armor",
- "resistance":"resistance",
- "pnresistance":"pnresistance",
- "firesistance":"firesistance",
- "fzresistance":"fzresistance",
- "phresistance":"phresistance",
- "stresistance":"stresistance",
- "incdmgamp":"incdmgamp",
- "stun":"stun",
- "blast":"blast",
- "explosion":"explosion",
- "evasion":"evasion",
- "cuteness":"cuteness",
- "bling":"bling",
- "dreturn":"dreturn",
- "reflection":"reflection",
- "crit":"crit",
- "critdamage":"critdamage",
- "miss":"miss",
- "avoidance":"avoidance",
- "hp":"max_hp",
- "mp":"max_mp",
- "speed":"speed",
- "lifesteal":"lifesteal",
- "manasteal":"manasteal",
- "apiercing":"apiercing",
- "rpiercing":"rpiercing",
- "output":"output",
- "attack":"a_attack",
- "mp_cost":"a_mp_cost",
- "mp_reduction":"mp_reduction",
- "xp":"xxp",
- "luck":"xluck",
- "gold":"xgold",
- "range":"range",
- "courage":"courage",
- "mcourage":"mcourage",
- "pcourage":"pcourage",
-}
-
-function apply_stats(player,prop,args)
-{
- for(var stat in prop)
- {
- if(args && args.no_range && stat=="range") continue;
- if(stat_to_attr[stat])
- player[stat_to_attr[stat]]=player[stat_to_attr[stat]]+prop[stat];
- else if(stat=="frequency") player.frequency+=prop[stat]/100.0;
+var stat_to_attr = {
+ str: "str",
+ int: "int",
+ dex: "dex",
+ vit: "vit",
+ for: "for",
+ armor: "armor",
+ resistance: "resistance",
+ pnresistance: "pnresistance",
+ firesistance: "firesistance",
+ fzresistance: "fzresistance",
+ phresistance: "phresistance",
+ stresistance: "stresistance",
+ incdmgamp: "incdmgamp",
+ stun: "stun",
+ blast: "blast",
+ explosion: "explosion",
+ evasion: "evasion",
+ cuteness: "cuteness",
+ bling: "bling",
+ dreturn: "dreturn",
+ reflection: "reflection",
+ crit: "crit",
+ critdamage: "critdamage",
+ miss: "miss",
+ avoidance: "avoidance",
+ hp: "max_hp",
+ mp: "max_mp",
+ speed: "speed",
+ lifesteal: "lifesteal",
+ manasteal: "manasteal",
+ apiercing: "apiercing",
+ rpiercing: "rpiercing",
+ output: "output",
+ attack: "a_attack",
+ mp_cost: "a_mp_cost",
+ mp_reduction: "mp_reduction",
+ xp: "xxp",
+ luck: "xluck",
+ gold: "xgold",
+ range: "range",
+ courage: "courage",
+ mcourage: "mcourage",
+ pcourage: "pcourage",
+};
+function apply_stats(player, prop, args) {
+ for (var stat in prop) {
+ if (args && args.no_range && stat == "range") {
+ continue;
+ }
+ if (stat_to_attr[stat]) {
+ player[stat_to_attr[stat]] = player[stat_to_attr[stat]] + prop[stat];
+ } else if (stat == "frequency") {
+ player.frequency += prop[stat] / 100.0;
+ }
}
}
-function calculate_player_stats(player)
-{
- if(player.is_npc) return;
- player.max_xp=G.levels[player.level+""];
- var level_up=false;
- while(player.xp>=player.max_xp)
- {
- level_up=true;
- player.xp-=player.max_xp;
+function calculate_player_stats(player) {
+ if (player.is_npc) {
+ return;
+ }
+ player.max_xp = G.levels[player.level + ""];
+ var level_up = false;
+ while (player.xp >= player.max_xp) {
+ level_up = true;
+ player.xp -= player.max_xp;
player.level++;
- player.max_xp=G.levels[player.level+""];
- player.hp=0;
+ player.max_xp = G.levels[player.level + ""];
+ player.hp = 0;
achievement_logic_level(player);
}
- if(level_up)
- {
- if(player.level>=80) realm_broadcast("server_message",{message:player.name+" is now level "+player.level,color:"#968CFA"});
- else if(player.level>=70) broadcast("server_message",{message:player.name+" is now level "+player.level+"!",color:"#968CFA"});
- xy_emit(player,"ui",{type:"level_up",name:player.name});
+ if (level_up) {
+ if (player.level >= 80) {
+ realm_broadcast("server_message", { message: player.name + " is now level " + player.level, color: "#968CFA" });
+ } else if (player.level >= 70) {
+ broadcast("server_message", { message: player.name + " is now level " + player.level + "!", color: "#968CFA" });
+ }
+ xy_emit(player, "ui", { type: "level_up", name: player.name });
}
// disappearing_text(player.socket,player,"LEVEL UP!",{xy:1,size:"huge",color:"#724A8F"});
- if(player.xp<0)
- {
- player.xp=0;
- player.warnings=(player.warnings||0)+1;
- if(player.warnings==2)
- {
+ if (player.xp < 0) {
+ player.xp = 0;
+ player.warnings = (player.warnings || 0) + 1;
+ if (player.warnings == 2) {
console.log("'Your monster!' logged out ->");
- player.socket.emit("ui_log","You monster!");
+ player.socket.emit("ui_log", "You monster!");
player.socket.disconnect();
return;
}
}
- var class_def=G.classes[player.type],item_attack=0,the_date=new Date();
- if(!class_def) class_def=G.classes.merchant; // when npc's get resend't
- player.range=class_def.range;
- player.max_hp=class_def.hp;
- player.max_mp=class_def.mp;
- ["stealth"].forEach(function(prop){player[prop]=false;});
- ["a_mp_cost","a_attack","stones","lifesteal","manasteal","incdmgamp","mp_reduction","stun","blast","explosion","cuteness","bling"].forEach(function(prop){player[prop]=0;});
- ["speed","attack","frequency","mp_cost","armor","resistance","apiercing","rpiercing","a","aura","evasion","miss","reflection","crit","critdamage","dreturn","computer","xxp","xluck","xgold","output","courage","mcourage","pcourage","pnresistance","firesistance","fzresistance","phresistance","stresistance"].forEach(function(prop){
- player[prop]=class_def[prop]||0;
+ var class_def = G.classes[player.type];
+ var item_attack = 0;
+ var the_date = new Date();
+ if (!class_def) {
+ class_def = G.classes.merchant;
+ } // when npc's get resend't
+ player.range = class_def.range;
+ player.max_hp = class_def.hp;
+ player.max_mp = class_def.mp;
+ ["stealth"].forEach(function (prop) {
+ player[prop] = false;
});
- if(!player.a) player.a={}; //abilities
- if(!player.aura) player.aura={};
- if(player.paura) for(var id in player.paura) player.aura[id]=player.paura[id];
- for(stat in class_def.stats)
- {
- player[stat]=class_def.stats[stat]+player.level*class_def.lstats[stat];
- if(player.level>40) player[stat]+=(player.level-40)*class_def.lstats[stat];
- if(player.level>55) player[stat]+=(player.level-55)*class_def.lstats[stat];
- if(player.level>65) player[stat]+=(player.level-65)*class_def.lstats[stat];
- if(player.level>80) player[stat]-=(player.level-80)*class_def.lstats[stat];
- player[stat]=floor(player[stat]);
+ [
+ "a_mp_cost",
+ "a_attack",
+ "stones",
+ "lifesteal",
+ "manasteal",
+ "incdmgamp",
+ "mp_reduction",
+ "stun",
+ "blast",
+ "explosion",
+ "cuteness",
+ "bling",
+ ].forEach(function (prop) {
+ player[prop] = 0;
+ });
+ [
+ "speed",
+ "attack",
+ "frequency",
+ "mp_cost",
+ "armor",
+ "resistance",
+ "apiercing",
+ "rpiercing",
+ "a",
+ "aura",
+ "evasion",
+ "miss",
+ "reflection",
+ "crit",
+ "critdamage",
+ "dreturn",
+ "computer",
+ "xxp",
+ "xluck",
+ "xgold",
+ "output",
+ "courage",
+ "mcourage",
+ "pcourage",
+ "pnresistance",
+ "firesistance",
+ "fzresistance",
+ "phresistance",
+ "stresistance",
+ ].forEach(function (prop) {
+ player[prop] = class_def[prop] || 0;
+ });
+ if (!player.a) {
+ player.a = {};
+ } //abilities
+ if (!player.aura) {
+ player.aura = {};
+ }
+ if (player.paura) {
+ for (var id in player.paura) {
+ player.aura[id] = player.paura[id];
+ }
+ }
+ for (stat in class_def.stats) {
+ player[stat] = class_def.stats[stat] + player.level * class_def.lstats[stat];
+ if (player.level > 40) {
+ player[stat] += (player.level - 40) * class_def.lstats[stat];
+ }
+ if (player.level > 55) {
+ player[stat] += (player.level - 55) * class_def.lstats[stat];
+ }
+ if (player.level > 65) {
+ player[stat] += (player.level - 65) * class_def.lstats[stat];
+ }
+ if (player.level > 80) {
+ player[stat] -= (player.level - 80) * class_def.lstats[stat];
+ }
+ player[stat] = floor(player[stat]);
+ }
+ if (!player.slots) {
+ player.slots = {};
}
- if(!player.slots) player.slots={};
// players.citems[27]=null; //- to reproduce the bug
- while(player.items.length>42 && !player.items[player.items.length-1]) player.items.splice(player.items.length-1);
- while(player.citems.length>42 && !player.citems[player.citems.length-1]) player.citems.splice(player.citems.length-1);
- player.isize=42; player.sets={};
- player.esize=player.isize-player.items.length;
- player.xpm=player.goldm=player.luckm=1;
- for(var i=0;icurrent.expires)
- {
- player.items[i]=null; player.citems[i]=null;
- }
- else if(G.items[current.name].gain)
- {
- var prop=calculate_item_properties(current);
+ while (player.items.length > 42 && !player.items[player.items.length - 1]) {
+ player.items.splice(player.items.length - 1);
+ }
+ while (player.citems.length > 42 && !player.citems[player.citems.length - 1]) {
+ player.citems.splice(player.citems.length - 1);
+ }
+ player.isize = 42;
+ player.sets = {};
+ player.esize = player.isize - player.items.length;
+ player.xpm = player.goldm = player.luckm = 1;
+ for (var i = 0; i < player.items.length; i++) {
+ var current = player.items[i];
+ if (!current) {
+ player.esize++;
+ } else if (current.name == "supercomputer") {
+ player.tracker = player.computer = player.supercomputer = true;
+ } else if (current.name == "computer") {
+ player.computer = true;
+ } else if (current.name == "tracker") {
+ player.tracker = true;
+ } else if (current.expires) {
+ // &&!current.ex = ex=elixier
+ if (the_date > current.expires) {
+ player.items[i] = null;
+ player.citems[i] = null;
+ } else if (G.items[current.name].gain) {
+ var prop = calculate_item_properties(current);
player.stones++;
- player["x"+G.items[current.name].gain]=prop[G.items[current.name].gain];
+ player["x" + G.items[current.name].gain] = prop[G.items[current.name].gain];
}
}
}
- player.monster_stats={};
- if(player.tracker)
- {
- for(var name in G.monsters)
- {
- var mx=max((player.p.stats.monsters[name]||0)+(player.p.stats.monsters_diff[name]||0),(player.max_stats.monsters[name]||[0,0])[0]);
- if(!mx || !G.monsters[name].achievements) continue;
- G.monsters[name].achievements.forEach(function(def){
- if(mx 80 && 0.01) ||
+ (player.level > 80 && 0.012) ||
+ (player.level > 70 && 0.02) ||
+ (player.level > 60 && 0.025) ||
+ (player.level > 50 && 0.03) ||
+ (player.level > 20 && 0.04) ||
+ 0.05;
- if(player.s.invis) player.speed=max(player.speed*0.6,player.speed-25),player.attack=round(player.attack*1.25);
- if(player.s.invincible) player.attack=round(player.attack*0.45);
- if(player.s.dash) player.speed=500;
- calculate_common_stats(player)
+ var excess = max(
+ 0,
+ max(player.targets_p - player.courage, max(player.targets_m - player.mcourage, player.targets_u - player.pcourage)),
+ );
+ var sredux = [0, 20, 40, 70, 80, 90, 100];
+ player.speed -= sredux[min(sredux.length - 1, excess)];
+ if (excess > 2) {
+ player.attack = round(player.attack * 0.2);
+ } else if (excess > 1) {
+ player.attack = round(player.attack * 0.4);
+ } else if (excess) {
+ player.attack = round(player.attack * 0.6);
+ }
+ player.fear = excess;
- player.tax=(player.level>80)&&0.010||(player.level>80)&&0.012||(player.level>70)&&0.020||(player.level>60)&&0.025||(player.level>50)&&0.03||(player.level>20)&&0.04||0.05;
+ if (player.map == "winterland") {
+ player.speed *= 0.95;
+ }
- var excess=max(0,max(player.targets_p-player.courage,max(player.targets_m-player.mcourage,player.targets_u-player.pcourage)));
- var sredux=[0,20,40,70,80,90,100];
- player.speed-=sredux[min(sredux.length-1,excess)];
- if(excess>2) player.attack=round(player.attack*0.2);
- else if(excess>1) player.attack=round(player.attack*0.4);
- else if(excess) player.attack=round(player.attack*0.6);
- player.fear=excess;
-
- if(player.map=="winterland") player.speed*=0.95;
-
- if(player.p.stand || player.s.hardshell) player.speed=10;
- player.evasion=min(50,player.evasion);
- player.reflection=min(player.s.reflection&&50||30,player.reflection);
- player.speed=min(player.speed,player.cruise||200000);
- player.speed=round(max(5,player.speed));
- if(!player.gold && player.gold!==0) player.gold=0,server_log("#X - GOLD BUG calculate",1);
+ if (player.p.stand || player.s.hardshell) {
+ player.speed = 10;
+ }
+ player.evasion = min(50, player.evasion);
+ player.reflection = min((player.s.reflection && 50) || 30, player.reflection);
+ player.speed = min(player.speed, player.cruise || 200000);
+ player.speed = round(max(5, player.speed));
+ if (!player.gold && player.gold !== 0) {
+ player.gold = 0;
+ server_log("#X - GOLD BUG calculate", 1);
+ }
recalculate_vxy(player);
- perfc.cps+=1;
+ perfc.cps += 1;
}
-function calculate_common_stats(entity)
-{
- if(entity.s.poisoned) entity.frequency*=0.9;
- if(entity.s.frozen) entity.frequency*=0.3,entity.speed-=40;
- if(entity.speed<1) entity.speed=1;
- if(entity.s.tangled) entity.speed=min(entity.speed,24);
+function calculate_common_stats(entity) {
+ if (entity.s.poisoned) {
+ entity.frequency *= 0.9;
+ }
+ if (entity.s.frozen) {
+ entity.frequency *= 0.3;
+ entity.speed -= 40;
+ }
+ if (entity.speed < 1) {
+ entity.speed = 1;
+ }
+ if (entity.s.tangled) {
+ entity.speed = min(entity.speed, 24);
+ }
}
-
-function calculate_monster_stats(monster)
-{
- var def=G.monsters[monster.type];
- ["attack","speed","frequency","armor","resistance","output","incdmgamp","avoidance"].forEach(function(p){
- monster[p]=def[p]||0;
+function calculate_monster_stats(monster) {
+ var def = G.monsters[monster.type];
+ ["attack", "speed", "frequency", "armor", "resistance", "output", "incdmgamp", "avoidance"].forEach(function (p) {
+ monster[p] = def[p] || 0;
});
- monster.output=100;
- if(monster.target || monster.focus) monster.speed=G.monsters[monster.type].charge;
- for(var name in monster.s)
- {
+ monster.output = 100;
+ if (monster.target || monster.focus) {
+ monster.speed = G.monsters[monster.type].charge;
+ }
+ for (var name in monster.s) {
// if(G.conditions[name])
// {
// for(var p in G.conditions[name])
@@ -982,6679 +1484,10051 @@ function calculate_monster_stats(monster)
// monster[p]+=G.conditions[name][p];
// }
- var prop=G.conditions[name];
- apply_stats(monster,monster.s[name])
- if(!prop) continue;
- apply_stats(monster,prop);
+ var prop = G.conditions[name];
+ apply_stats(monster, monster.s[name]);
+ if (!prop) {
+ continue;
+ }
+ apply_stats(monster, prop);
}
- monster.attack=round(monster.attack*monster.output/100.0)
- if(monster.focus && instances[monster.in].monsters[monster.focus]) monster.speed=min(monster.speed,instances[monster.in].monsters[monster.focus].speed+4);
- if(monster.level>1)
- {
- var att_mult=0.125,freq_mult=0.034,speed_mult=0.24; // speed originally 0.34
- var mlevel=min(monster.level,12);
- if(monster.map_def.grow) att_mult=0.05,freq_mult=0.008,speed_mult=0.16;
- monster.attack=parseInt(monster.attack*(1+mlevel*att_mult));
- monster.speed+=mlevel*speed_mult;
- monster.frequency+=mlevel*freq_mult;
+ monster.attack = round((monster.attack * monster.output) / 100.0);
+ if (monster.focus && instances[monster.in].monsters[monster.focus]) {
+ monster.speed = min(monster.speed, instances[monster.in].monsters[monster.focus].speed + 4);
+ }
+ if (monster.level > 1) {
+ var att_mult = 0.125;
+ var freq_mult = 0.034;
+ var speed_mult = 0.24; // speed originally 0.34
+ var mlevel = min(monster.level, 12);
+ if (monster.map_def.grow) {
+ att_mult = 0.05;
+ freq_mult = 0.008;
+ speed_mult = 0.16;
+ }
+ monster.attack = parseInt(monster.attack * (1 + mlevel * att_mult));
+ monster.speed += mlevel * speed_mult;
+ monster.frequency += mlevel * freq_mult;
+ }
+ if (E.schedule.night) {
+ monster.speed = ceil(monster.speed * 0.7);
}
- if(E.schedule.night) monster.speed=ceil(monster.speed*0.7);
calculate_common_stats(monster);
recalculate_vxy(monster);
}
-function ccms(monster)
-{
- if(Object.keys(monster.s).length) calculate_monster_stats(monster);
+function ccms(monster) {
+ if (Object.keys(monster.s).length) {
+ calculate_monster_stats(monster);
+ }
}
-function can_equip_item(player,item,slot)
-{
- var class_def=G.classes[player.type];
- if(!slot) slot=item.type;
- if(slot=="offhand" && item.type!="weapon") slot=item.type; //Easiest solution to the slot:"offhand" challenge [15/11/16]
- if(item.type=="tool") slot="mainhand";
- if(item.type=="test" && slot!="test") return slot;
- if(!in_arr(item.type,["helmet","pants","chest","weapon","amulet","earring","shoes","gloves","ring","shield","belt","source","orb","quiver","cape","misc_offhand","tool"])) return "no";
- if(slot!=item.type && in_arr(item.type,["shield","source","quiver","misc_offhand"]) && slot!="offhand") return "no";
- if(in_arr(slot,["weapon","mainhand","offhand","tool"]))
- {
- if(slot=="weapon" && player.slots.mainhand && class_def.mainhand[G.items[player.slots.mainhand.name].wtype] && !player.slots.offhand && class_def.offhand[item.wtype])
- {
- slot="offhand";
+function can_equip_item(player, item, slot) {
+ var class_def = G.classes[player.type];
+ if (!slot) {
+ slot = item.type;
+ }
+ if (slot == "offhand" && item.type != "weapon") {
+ slot = item.type;
+ } //Easiest solution to the slot:"offhand" challenge [15/11/16]
+ if (item.type == "tool") {
+ slot = "mainhand";
+ }
+ if (item.type == "test" && slot != "test") {
+ return slot;
+ }
+ if (
+ !in_arr(item.type, [
+ "helmet",
+ "pants",
+ "chest",
+ "weapon",
+ "amulet",
+ "earring",
+ "shoes",
+ "gloves",
+ "ring",
+ "shield",
+ "belt",
+ "source",
+ "orb",
+ "quiver",
+ "cape",
+ "misc_offhand",
+ "tool",
+ ])
+ ) {
+ return "no";
+ }
+ if (slot != item.type && in_arr(item.type, ["shield", "source", "quiver", "misc_offhand"]) && slot != "offhand") {
+ return "no";
+ }
+ if (in_arr(slot, ["weapon", "mainhand", "offhand", "tool"])) {
+ if (
+ slot == "weapon" &&
+ player.slots.mainhand &&
+ class_def.mainhand[G.items[player.slots.mainhand.name].wtype] &&
+ !player.slots.offhand &&
+ class_def.offhand[item.wtype]
+ ) {
+ slot = "offhand";
+ } else if (
+ slot == "offhand" &&
+ (!player.slots.mainhand ||
+ (player.slots.mainhand && class_def.mainhand[G.items[player.slots.mainhand.name].wtype])) &&
+ class_def.offhand[item.wtype]
+ ) {
+ slot = "offhand";
+ } else if (slot == "weapon" || slot == "mainhand") {
+ if (class_def.doublehand[item.wtype] && !player.slots.offhand) {
+ } else if (!class_def.mainhand[item.wtype]) {
+ return "no";
+ }
+ slot = "mainhand";
+ } else {
+ return "no";
}
- else if(slot=="offhand" && (!player.slots.mainhand || player.slots.mainhand && class_def.mainhand[G.items[player.slots.mainhand.name].wtype]) && class_def.offhand[item.wtype])
- {
- slot="offhand";
+ } else if (item.type == "shield" || item.type == "misc_offhand") {
+ if (
+ class_def.offhand[item.type] &&
+ !(player.slots.mainhand && class_def.doublehand[G.items[player.slots.mainhand.name].wtype])
+ ) {
+ slot = "offhand";
+ } else {
+ return "no";
}
- else if(slot=="weapon" || slot=="mainhand")
- {
- if(class_def.doublehand[item.wtype] && !player.slots.offhand);
- else if(!class_def.mainhand[item.wtype]) return "no";
- slot="mainhand";
+ } else if (item.type == "quiver") {
+ if (
+ class_def.offhand.quiver &&
+ !(player.slots.mainhand && class_def.doublehand[G.items[player.slots.mainhand.name].wtype])
+ ) {
+ slot = "offhand";
+ } else {
+ return "no";
}
- else {return "no";}
- }
- else if(item.type=="shield" || item.type=="misc_offhand")
- {
- if(class_def.offhand[item.type] && !(player.slots.mainhand && class_def.doublehand[G.items[player.slots.mainhand.name].wtype])) slot="offhand";
- else {return "no";}
- }
- else if(item.type=="quiver")
- {
- if(class_def.offhand.quiver && !(player.slots.mainhand && class_def.doublehand[G.items[player.slots.mainhand.name].wtype])) slot="offhand";
- else {return "no";}
- }
- else if(item.type=="source")
- {
- if(class_def.offhand.source && !(player.slots.mainhand && class_def.doublehand[G.items[player.slots.mainhand.name].wtype])) slot="offhand";
- else {return "no";}
- }
- else if(item.type=="ring")
- {
- if(slot=="ring1" || slot=="ring2");
- else if(!player.slots["ring1"]) slot="ring1";
- else slot="ring2";
- }
- else if(item.type=="earring")
- {
- if(slot=="earring1" || slot=="earring2");
- else if(!player.slots["earring1"]) slot="earring1";
- else slot="earring2";
- }
- else if(slot!=item.type)
- {
+ } else if (item.type == "source") {
+ if (
+ class_def.offhand.source &&
+ !(player.slots.mainhand && class_def.doublehand[G.items[player.slots.mainhand.name].wtype])
+ ) {
+ slot = "offhand";
+ } else {
+ return "no";
+ }
+ } else if (item.type == "ring") {
+ if (slot == "ring1" || slot == "ring2") {
+ } else if (!player.slots["ring1"]) {
+ slot = "ring1";
+ } else {
+ slot = "ring2";
+ }
+ } else if (item.type == "earring") {
+ if (slot == "earring1" || slot == "earring2") {
+ } else if (!player.slots["earring1"]) {
+ slot = "earring1";
+ } else {
+ slot = "earring2";
+ }
+ } else if (slot != item.type) {
return "no";
}
return slot;
}
-function consume(player,num,quantity)
-{
- var available=player.items[num].q||1;
- if(quantity>available) exception=not_enough_items;
- if(available==quantity) player.items[num]=null,player.esize++;
- else player.items[num].q-=quantity;
- player.citems[num]=cache_item(player.items[num]);
+function consume(player, num, quantity) {
+ var available = player.items[num].q || 1;
+ if (quantity > available) {
+ exception = not_enough_items;
+ }
+ if (available == quantity) {
+ player.items[num] = null;
+ player.esize++;
+ } else {
+ player.items[num].q -= quantity;
+ }
+ player.citems[num] = cache_item(player.items[num]);
}
-function consume_one(player,num)
-{
- consume(player,num,1);
+function consume_one(player, num) {
+ consume(player, num, 1);
}
-function consume_one_by_id(player,id)
-{
- for(var i=0;i0.00001) && Math.random()/share/player.luckm/monster.level/monster_mult- 0.00001) && Math.random()/share/player.luckm/monster.level/monster_mult
- 0.00001) &&
+ Math.random() / share / player.luckm / monster.level / monster_mult < item[0]) ||
+ mode.drop_all
+ ) {
+ // /hp_mult - removed [13/07/18]
+ drop_item_logic(drop, item, is_in_pvp(player, 1));
+ }
+ });
+ }
+ if (monster.drops) {
+ monster.drops.forEach(function (item) {
+ if (
+ ((!monster.temp || item[0] > 0.00001) &&
+ Math.random() / share / player.luckm / monster.level / monster_mult < item[0]) ||
+ mode.drop_all
+ ) {
+ // /hp_mult - removed [13/07/18]
+ drop_item_logic(drop, item, is_in_pvp(player, 1));
+ }
+ });
+ }
+ if (player.tskin == "konami") {
+ D.drops.konami.forEach(function (item) {
+ if (Math.random() / share / player.luckm / monster.level < item[0] || mode.drop_all) {
+ drop_item_logic(drop, item, is_in_pvp(player, 1));
+ }
+ });
+ }
+ if (player.p.first && !player.p.first_drop) {
+ player.p.first_drop = true;
+ drop.gold += 100000;
drop.items.push(create_new_item("ringsj"));
drop.items.push(create_new_item("ringsj"));
drop.items.push(create_new_item("ringsj"));
drop.items.push(create_new_item("hpbelt"));
drop.items.push(create_new_item("gem0"));
}
- if(Math.random()1) // && !m.target - it was possible to keep a high level monsters aggroed and abuse the system [21/07/23]
- {
- player.s.monsterhunt.dl=true;
- level_monster(m,{delevel:true});
+function monster_hunt_logic(player, monster) {
+ var target = monster;
+ if (!player.s.monsterhunt || player.s.monsterhunt.sn != region + " " + server_name) {
+ return;
+ }
+ if (player.s.monsterhunt.id == monster.type && player.s.monsterhunt.c) {
+ player.s.monsterhunt.c--;
+ }
+ if (target.level == 1 && player.s.monsterhunt.id == target.type && player.s.monsterhunt.dl) {
+ player.s.monsterhunt.dl = false;
+ get_monsters(player.s.monsterhunt.id).forEach(function (m) {
+ if (!player.s.monsterhunt.dl && m.level > 1) {
+ // && !m.target - it was possible to keep a high level monsters aggroed and abuse the system [21/07/23]
+ player.s.monsterhunt.dl = true;
+ level_monster(m, { delevel: true });
}
});
}
}
-function calculate_monster_score(player,monster,share)
-{
- var score=min(1,monster.mult*2.2);
- var divider=1;
- if(!share) share=0;
- if(monster.cooperative) divider=2;
- for(var id in players)
- {
- var current=players[id];
- if(current.id==player.id) continue;
- if(current.owner==player.owner && current.type=="merchant" && simple_distance(current,player)<600) score-=0.2/divider;
- if(current.party && current.party==player.party && current.type=="merchant" && simple_distance(current,player)<600) score-=0.1/divider;
- else if(current.owner==player.owner && current.party==player.party && simple_distance(current,player)<600 && current.type!="merchant") score+=0.3/divider;
- else if(current.owner==player.owner && current.party && current.party==player.party && current.type!="merchant") score+=0.3/divider; // originally 0.25
+function calculate_monster_score(player, monster, share) {
+ var score = min(1, monster.mult * 2.2);
+ var divider = 1;
+ if (!share) {
+ share = 0;
}
- if(simple_distance(player,monster)>600 && share<0.01)
- {
- score-=0.3/divider;
+ if (monster.cooperative) {
+ divider = 2;
+ }
+ for (var id in players) {
+ var current = players[id];
+ if (current.id == player.id) {
+ continue;
+ }
+ if (current.owner == player.owner && current.type == "merchant" && simple_distance(current, player) < 600) {
+ score -= 0.2 / divider;
+ }
+ if (
+ current.party &&
+ current.party == player.party &&
+ current.type == "merchant" &&
+ simple_distance(current, player) < 600
+ ) {
+ score -= 0.1 / divider;
+ } else if (
+ current.owner == player.owner &&
+ current.party == player.party &&
+ simple_distance(current, player) < 600 &&
+ current.type != "merchant"
+ ) {
+ score += 0.3 / divider;
+ } else if (
+ current.owner == player.owner &&
+ current.party &&
+ current.party == player.party &&
+ current.type != "merchant"
+ ) {
+ score += 0.3 / divider;
+ } // originally 0.25
+ }
+ if (simple_distance(player, monster) > 600 && share < 0.01) {
+ score -= 0.3 / divider;
+ }
+ if (player.type == "merchant" && player.party) {
+ score /= 2;
+ }
+ if (score < 0) {
+ score = 0;
+ }
+ if (gameplay == "hardcore") {
+ score *= 10000;
}
- if(player.type=="merchant" && player.party) score/=2;
- if(score<0) score=0;
- if(gameplay=="hardcore") score*=10000;
return score;
}
-function issue_monster_awards(monster)
-{
- var total=0.1;
- for(var name in monster.points)
- {
- var current=players[name_to_id[name]];
- if(current) // && current.map==monster.map
- total+=max(0,monster.points[name]);
+function issue_monster_awards(monster) {
+ var total = 0.1;
+ for (var name in monster.points) {
+ var current = players[name_to_id[name]];
+ if (current) {
+ // && current.map==monster.map
+ total += max(0, monster.points[name]);
+ }
}
- for(var name in monster.points)
- {
- var current=players[name_to_id[name]];
- var share=max(0,monster.points[name])/total;
- if(current && share>0.0025) // && current.map==monster.map
- {
- if(monster.rbuff && G.conditions[monster.rbuff]) current.s[monster.rbuff]={ms:G.conditions[monster.rbuff].duration};
- if(monster.cbuff) for(var i=0;i 0.0025) {
+ // && current.map==monster.map
+ if (monster.rbuff && G.conditions[monster.rbuff]) {
+ current.s[monster.rbuff] = { ms: G.conditions[monster.rbuff].duration };
+ }
+ if (monster.cbuff) {
+ for (var i = 0; i < monster.cbuff.length; i++) {
+ if (current.level <= monster.cbuff[i][0] && G.conditions[monster.cbuff[i][1]]) {
+ current.s[monster.cbuff[i][1]] = { ms: G.conditions[monster.cbuff[i][1]].duration };
+ break;
+ }
+ }
+ }
+ if (G.monsters[monster.type]["1hp"]) {
+ drop_something(current, monster);
+ } else {
+ drop_something(current, monster, share);
+ }
+ var score = calculate_monster_score(current, monster, share);
+ current.p.stats.monsters[monster.type] = (current.p.stats.monsters[monster.type] || 0) + 1;
+ current.p.stats.monsters_diff[monster.type] = (current.p.stats.monsters_diff[monster.type] || 0) + (score - 1);
+ monster_hunt_logic(current, monster, share);
+ if (current.type == "merchant") {
+ continue;
+ }
+ current.xp += round(monster.xp * share * current.xpm);
+ if (current.t) {
+ current.t.xp += round(monster.xp * share * current.xpm);
+ }
delete current.s.coop;
- resend(current,"u+cid");
+ resend(current, "u+cid");
}
}
}
-function issue_monster_award(monster)
-{
- if(monster.cooperative) return issue_monster_awards(monster);
- var player=players[name_to_id[monster.target]];
- if(!player) return;
+function issue_monster_award(monster) {
+ if (monster.cooperative) {
+ return issue_monster_awards(monster);
+ }
+ var player = players[name_to_id[monster.target]];
+ if (!player) {
+ return;
+ }
// if(gameplay=="test" && player.level<80) player.level+=1;
stats.kills[monster.type]++;
- drop_something(player,monster);
- if(!player.party)
- {
- if(monster.rbuff && G.conditions[monster.rbuff]) player.s[monster.rbuff]={ms:G.conditions[monster.rbuff].duration};
- if(monster.cbuff) for(var i=0;i=10) lost_gold=1000;
- if(target.level>=20) lost_gold=5000;
- if(target.level>=30) lost_gold=12500;
- if(target.level>=40) lost_gold=25000;
- if(target.level>=50) lost_gold=50000;
- if(target.level>=55) lost_gold=75000;
- if(target.level>=60) lost_gold=125000;
- if(target.level>=65) lost_gold=250000;
- if(target.level>=70) lost_gold=500000;
- if(target.level>=75) lost_gold=1000000;
-
- lost_gold=min(lost_gold, max(attacker.gold,10000)*4 )||0;
- lost_xp=round(min(lost_xp, max(attacker.xp/15.0,50000) ))||0;
-
- if(G.maps[attacker.map].safe_pvp && !is_pvp)
- {
- lost_gold=0;
- lost_xp=0;
+ var lost_gold = 100;
+ var gain_gold = 100;
+ if (target.level >= 10) {
+ lost_gold = 1000;
+ }
+ if (target.level >= 20) {
+ lost_gold = 5000;
+ }
+ if (target.level >= 30) {
+ lost_gold = 12500;
+ }
+ if (target.level >= 40) {
+ lost_gold = 25000;
+ }
+ if (target.level >= 50) {
+ lost_gold = 50000;
+ }
+ if (target.level >= 55) {
+ lost_gold = 75000;
+ }
+ if (target.level >= 60) {
+ lost_gold = 125000;
+ }
+ if (target.level >= 65) {
+ lost_gold = 250000;
+ }
+ if (target.level >= 70) {
+ lost_gold = 500000;
+ }
+ if (target.level >= 75) {
+ lost_gold = 1000000;
}
+ lost_gold = min(lost_gold, max(attacker.gold, 10000) * 4) || 0;
+ lost_xp = round(min(lost_xp, max(attacker.xp / 15.0, 50000))) || 0;
- if(gameplay=="hardcore")
- {
- lost_gold=round(target.gold*0.8);
- lost_xp=target.xp;
- for(var i=1;i<=B.hlevel_loss;i++)
- if(target.level-i>0)
- lost_xp+=G.levels[(target.level-i)+""];
- target.level=max(1,target.level-B.hlevel_loss);
+ if (G.maps[attacker.map].safe_pvp && !is_pvp) {
+ lost_gold = 0;
+ lost_xp = 0;
}
-
- lost_gold=min(target.gold,lost_gold);
- gain_gold=round(lost_gold*0.9);
- if(target.type=="merchant") lost_xp=0;
- if(gameplay!="hardcore" && gameplay!="test" && is_same(attacker,target,1)) lost_gold=gain_gold=0,lost_xp=0;
+ if (gameplay == "hardcore") {
+ lost_gold = round(target.gold * 0.8);
+ lost_xp = target.xp;
+ for (var i = 1; i <= B.hlevel_loss; i++) {
+ if (target.level - i > 0) {
+ lost_xp += G.levels[target.level - i + ""];
+ }
+ }
+ target.level = max(1, target.level - B.hlevel_loss);
+ }
- if(!is_same(attacker,target,1)) attacker.kills++;
+ lost_gold = min(target.gold, lost_gold);
+ gain_gold = round(lost_gold * 0.9);
- if(mode.log_pvp) appengine_log("pvp",attacker.name+" pwned "+target.name+" For "+lost_gold+" Gold "+lost_xp+" XP");
- pwns[(pend++)%200]=[attacker.name,target.name];
+ if (target.type == "merchant") {
+ lost_xp = 0;
+ }
+ if (gameplay != "hardcore" && gameplay != "test" && is_same(attacker, target, 1)) {
+ lost_gold = gain_gold = 0;
+ lost_xp = 0;
+ }
+ if (!is_same(attacker, target, 1)) {
+ attacker.kills++;
+ }
- target.socket.emit("game_log",{message:"Slain by "+attacker.name,color:"#F12F02"});
- var lost_shells=0,psize=1;
- if(lost_xp)
- for(var i=0;i10)
- {
- attacker.socket.emit("game_response",{response:"attack_failed",id:target.id,reason:"level"});
- return {failed:true,reason:"level_gap",place:atype,id:target.id};
+ if (
+ mode.pvp_level_gap &&
+ attacker.is_player &&
+ target.is_player &&
+ !info.positive &&
+ abs(attacker.level - target.level) > 10
+ ) {
+ attacker.socket.emit("game_response", { response: "attack_failed", id: target.id, reason: "level" });
+ return { failed: true, reason: "level_gap", place: atype, id: target.id };
}
- var dist=distance(attacker,target),range=0;
- var def={hid:attacker.id,source:atype,projectile:null};
+ var dist = distance(attacker, target);
+ var range = 0;
+ var def = { hid: attacker.id, source: atype, projectile: null };
// PROJECTILE LOGIC
- if(attacker.is_monster) def.projectile=G.monsters[attacker.type].projectile||"stone";
- if(attacker.is_player && G.classes[attacker.type].projectile) def.projectile=G.classes[attacker.type].projectile;
- if(attacker.projectile) def.projectile=attacker.projectile;
- if(attacker.slots && attacker.slots.mainhand && G.items[attacker.slots.mainhand.name].projectile) def.projectile=G.items[attacker.slots.mainhand.name].projectile;
- if(attacker.tskin=="konami") def.projectile="stone_k";
- if((atype!="attack" || !def.projectile || atype=="heal") && G.skills[atype].projectile) def.projectile=G.skills[atype].projectile;
+ if (attacker.is_monster) {
+ def.projectile = G.monsters[attacker.type].projectile || "stone";
+ }
+ if (attacker.is_player && G.classes[attacker.type].projectile) {
+ def.projectile = G.classes[attacker.type].projectile;
+ }
+ if (attacker.projectile) {
+ def.projectile = attacker.projectile;
+ }
+ if (attacker.slots && attacker.slots.mainhand && G.items[attacker.slots.mainhand.name].projectile) {
+ def.projectile = G.items[attacker.slots.mainhand.name].projectile;
+ }
+ if (attacker.tskin == "konami") {
+ def.projectile = "stone_k";
+ }
+ if ((atype != "attack" || !def.projectile || atype == "heal") && G.skills[atype].projectile) {
+ def.projectile = G.skills[atype].projectile;
+ }
// DAMAGE TYPE LOGIC
- if(attacker.is_monster && G.monsters[attacker.type].damage_type) info.damage_type=G.monsters[attacker.type].damage_type;
- if(attacker.is_player && G.classes[attacker.type].damage_type) info.damage_type=G.classes[attacker.type].damage_type;
- if(attacker.is_player && attacker.slots.mainhand && G.items[attacker.slots.mainhand.name].damage_type) info.damage_type=G.items[attacker.slots.mainhand.name].damage_type;
- if(atype!="attack" && G.skills[atype].damage_type) info.damage_type=G.skills[atype].damage_type;
+ if (attacker.is_monster && G.monsters[attacker.type].damage_type) {
+ info.damage_type = G.monsters[attacker.type].damage_type;
+ }
+ if (attacker.is_player && G.classes[attacker.type].damage_type) {
+ info.damage_type = G.classes[attacker.type].damage_type;
+ }
+ if (attacker.is_player && attacker.slots.mainhand && G.items[attacker.slots.mainhand.name].damage_type) {
+ info.damage_type = G.items[attacker.slots.mainhand.name].damage_type;
+ }
+ if (atype != "attack" && G.skills[atype].damage_type) {
+ info.damage_type = G.skills[atype].damage_type;
+ }
// PROCS
- if(!attacker.is_player || G.skills[atype].procs) info.procs=true;
+ if (!attacker.is_player || G.skills[atype].procs) {
+ info.procs = true;
+ }
// HEAL / POSITIVE
- if(G.skills[atype].heal || attacker.is_player && attacker.slots.mainhand && attacker.slots.mainhand.name=="cupid")
- info.heal=true,info.positive=true;
-
- if(attacker.is_player && target.is_player && !is_in_pvp(target,true) && !info.positive || target.npc)
- {
- attacker.socket.emit("game_response",{response:"attack_failed",id:target.id});
- return {failed:true,reason:"no_pvp",place:atype,id:target.id}
+ if (
+ G.skills[atype].heal ||
+ (attacker.is_player && attacker.slots.mainhand && attacker.slots.mainhand.name == "cupid")
+ ) {
+ info.heal = true;
+ info.positive = true;
}
- // COMMON RANGE CHECKS
- if(G.skills[atype].use_range) range=attacker.range;
- if(G.skills[atype].range) range=G.skills[atype].range;
+ if ((attacker.is_player && target.is_player && !is_in_pvp(target, true) && !info.positive) || target.npc) {
+ attacker.socket.emit("game_response", { response: "attack_failed", id: target.id });
+ return { failed: true, reason: "no_pvp", place: atype, id: target.id };
+ }
+
+ // COMMON RANGE CHECKS
+ if (G.skills[atype].use_range) {
+ range = attacker.range;
+ }
+ if (G.skills[atype].range) {
+ range = G.skills[atype].range;
+ }
// DAMAGE
- if(G.skills[atype].damage) attack=G.skills[atype].damage;
+ if (G.skills[atype].damage) {
+ attack = G.skills[atype].damage;
+ }
// SKILL MP
- if(G.skills[atype].mp) mp_cost=G.skills[atype].mp;
-
- if(attacker.is_player && range && !attacker.is_npc)
- {
- if(dist>range+attacker.xrange)
- {
- attacker.socket.emit("game_response",{response:"too_far",id:target.id,dist:dist});
- return {failed:true,reason:"too_far",place:atype,id:target.id,dist:dist};
- }
- if(dist>range) attacker.xrange+=range-dist;
+ if (G.skills[atype].mp) {
+ mp_cost = G.skills[atype].mp;
}
- if(info.procs && attacker.s.poisonous) info.conditions.push("poisoned");
+ if (attacker.is_player && range && !attacker.is_npc) {
+ if (dist > range + attacker.xrange) {
+ attacker.socket.emit("game_response", { response: "too_far", id: target.id, dist: dist });
+ return { failed: true, reason: "too_far", place: atype, id: target.id, dist: dist };
+ }
+ if (dist > range) {
+ attacker.xrange += range - dist;
+ }
+ }
- if(atype=="heal")
- {
- attack=attacker.heal||attacker.attack;
- mp_cost=attacker.mp_cost;
- }
- else if(attacker.is_player && (atype=="attack" || atype=="3shot" || atype=="5shot" || atype=="cleave" || atype=="shadowstrike"))
- {
- var mp_mult=1,att_mult=1;
- if(atype=="3shot") mp_mult=0,att_mult=0.7;
- if(atype=="5shot") mp_mult=0,att_mult=0.5;
- if(atype=="cleave") mp_mult=0.02,info.lines=false,att_mult=0.1+Math.random()*0.8,def.aoe=true,attacker.first=true;
- if(atype=="shadowstrike") mp_mult=0,info.lines=false,att_mult=(0.2+Math.random()*1.2)*((Math.random()<0.05)&&12||1),def.aoe=true;
- if(attacker.mp=80) attack=800;
- else if(attacker.level>=72) attack=720;
- else if(attacker.level>=60) attack=600;
- else attack=400;
- }
- else if(atype=="selfheal")
- {
- if(attacker.level>=80) attack=800;
- else if(attacker.level>=72) attack=720;
- else if(attacker.level>=60) attack=600;
- else attack=400;
- }
- else if(atype=="taunt")
- {
- if(target.is_monster && target.target && get_player(target.target) && is_same(attacker,get_player(target.target),1))
- {
- stop_pursuit(target,{redirect:true,cause:"taunt redirect"});
- target_player(target,attacker);
- }
- }
- else if(atype=="curse")
- {
- if(distance(attacker,target)>min(200,attacker.range*5+20))
- {
- attacker.socket.emit("game_response",{response:"too_far",id:target.id,dist:dist});
- return {failed:true,reason:"too_far",place:atype,id:target.id,dist:dist}
- }
- attack=0;
- info.conditions.push("cursed");
- }
- else if(atype=="burst")
- {
- if(attacker.mp<1)
- {
- attacker.socket.emit("game_response",{response:"no_mp"});
- return {failed:true,reason:"no_mp",place:atype,id:target.id}
- }
- attack=attacker.mp*G.skills.burst.ratio;
- mp_cost=attacker.mp;
- }
- else if(atype=="cburst")
- {
- var mp_cutoff=attacker.next_mp,mp=attacker.next_mp;
- if(atype=="cburst") mp=mp_cutoff=attacker.next_mp;
- if(attacker.mp3*attacker.range+20)
- {
- attacker.socket.emit("game_response",{response:"too_far",id:target.id,dist:dist});
- return {failed:true,reason:"too_far",place:atype,id:target.id,dist:dist};
- }
- attack=attacker.attack*1.5;
- // if(attacker.slots.mainhand && attacker.slots.mainhand.name=="cupid") info.heal=info.positive=true,def.projectile=G.items.cupid.projectile;
- }
- else if(atype=="snowball")
- {
- if(target.is_monster && attacker.a.freeze && attacker.a.freeze.attr0)
- attack+=10*attacker.a.freeze.attr0*attacker.a.freeze.attr0;
- if(target.is_monster || is_in_pvp(attacker,true))
- info.conditions.push("frozen");
- }
- else if(atype=="quickpunch" || atype=="quickstab" || atype=="smash")
- {
- attack=attacker.attack*G.skills[atype].damage_multiplier;
- }
- else if(atype=="mentalburst")
- {
- if(attacker.in!=target.in || distance(attacker,target,true)>attacker.range*G.skills.mentalburst.range_multiplier+G.skills.mentalburst.range_bonus)
- {
- attacker.socket.emit("game_response",{response:"too_far",id:target.id,dist:dist});
- return {failed:true,reason:"too_far",place:atype,id:target.id,dist:dist}
- }
- attack=attacker.attack*G.skills[atype].damage_multiplier;
- }
- else if(atype=="poisonarrow")
- {
+ if (info.procs && attacker.s.poisonous) {
info.conditions.push("poisoned");
}
- else if(attacker.is_monster)
- {
- var rng=parseInt(Math.random()*100-50);
- if(attacker.s.poisonous) info.conditions.push("poisoned");
- attacker.last.attack=future_ms(rng);
+
+ if (atype == "heal") {
+ attack = attacker.heal || attacker.attack;
+ mp_cost = attacker.mp_cost;
+ } else if (
+ attacker.is_player &&
+ (atype == "attack" || atype == "3shot" || atype == "5shot" || atype == "cleave" || atype == "shadowstrike")
+ ) {
+ var mp_mult = 1;
+ var att_mult = 1;
+ if (atype == "3shot") {
+ mp_mult = 0;
+ att_mult = 0.7;
+ }
+ if (atype == "5shot") {
+ mp_mult = 0;
+ att_mult = 0.5;
+ }
+ if (atype == "cleave") {
+ mp_mult = 0.02;
+ info.lines = false;
+ att_mult = 0.1 + Math.random() * 0.8;
+ def.aoe = true;
+ attacker.first = true;
+ }
+ if (atype == "shadowstrike") {
+ mp_mult = 0;
+ info.lines = false;
+ att_mult = (0.2 + Math.random() * 1.2) * ((Math.random() < 0.05 && 12) || 1);
+ def.aoe = true;
+ }
+ if (attacker.mp < attacker.mp_cost * mp_mult) {
+ attacker.socket.emit("game_response", { response: "no_mp" });
+ return { failed: true, reason: "no_mp", place: atype, id: target.id };
+ }
+ mp_cost = parseInt(attacker.mp_cost * mp_mult);
+ attack = attacker.attack * att_mult;
+ } else if (atype == "piercingshot") {
+ info.apiercing = 500;
+ attack = attacker.attack * 0.75;
+ } else if (atype == "partyheal") {
+ if (attacker.level >= 80) {
+ attack = 800;
+ } else if (attacker.level >= 72) {
+ attack = 720;
+ } else if (attacker.level >= 60) {
+ attack = 600;
+ } else {
+ attack = 400;
+ }
+ } else if (atype == "selfheal") {
+ if (attacker.level >= 80) {
+ attack = 800;
+ } else if (attacker.level >= 72) {
+ attack = 720;
+ } else if (attacker.level >= 60) {
+ attack = 600;
+ } else {
+ attack = 400;
+ }
+ } else if (atype == "taunt") {
+ if (
+ target.is_monster &&
+ target.target &&
+ get_player(target.target) &&
+ is_same(attacker, get_player(target.target), 1)
+ ) {
+ stop_pursuit(target, { redirect: true, cause: "taunt redirect" });
+ target_player(target, attacker);
+ }
+ } else if (atype == "curse") {
+ if (distance(attacker, target) > min(200, attacker.range * 5 + 20)) {
+ attacker.socket.emit("game_response", { response: "too_far", id: target.id, dist: dist });
+ return { failed: true, reason: "too_far", place: atype, id: target.id, dist: dist };
+ }
+ attack = 0;
+ info.conditions.push("cursed");
+ } else if (atype == "burst") {
+ if (attacker.mp < 1) {
+ attacker.socket.emit("game_response", { response: "no_mp" });
+ return { failed: true, reason: "no_mp", place: atype, id: target.id };
+ }
+ attack = attacker.mp * G.skills.burst.ratio;
+ mp_cost = attacker.mp;
+ } else if (atype == "cburst") {
+ var mp_cutoff = attacker.next_mp;
+ var mp = attacker.next_mp;
+ if (atype == "cburst") {
+ mp = mp_cutoff = attacker.next_mp;
+ }
+ if (attacker.mp < mp_cutoff) {
+ attacker.socket.emit("game_response", { response: "no_mp" });
+ return { failed: true, reason: "no_mp", place: atype, id: target.id };
+ }
+ attack = mp * G.skills.cburst.ratio;
+ mp_cost = mp;
+ attacker.first = true;
+ } else if (atype == "purify") {
+ def.purify = true;
+ } else if (atype == "frostball") {
+ info.conditions.push("frozen");
+ } else if (atype == "fireball") {
+ info.conditions.push("burned");
+ } else if (atype == "supershot") {
+ if (attacker.in != target.in || distance(attacker, target, true) > 3 * attacker.range + 20) {
+ attacker.socket.emit("game_response", { response: "too_far", id: target.id, dist: dist });
+ return { failed: true, reason: "too_far", place: atype, id: target.id, dist: dist };
+ }
+ attack = attacker.attack * 1.5;
+ // if(attacker.slots.mainhand && attacker.slots.mainhand.name=="cupid") info.heal=info.positive=true,def.projectile=G.items.cupid.projectile;
+ } else if (atype == "snowball") {
+ if (target.is_monster && attacker.a.freeze && attacker.a.freeze.attr0) {
+ attack += 10 * attacker.a.freeze.attr0 * attacker.a.freeze.attr0;
+ }
+ if (target.is_monster || is_in_pvp(attacker, true)) {
+ info.conditions.push("frozen");
+ }
+ } else if (atype == "quickpunch" || atype == "quickstab" || atype == "smash") {
+ attack = attacker.attack * G.skills[atype].damage_multiplier;
+ } else if (atype == "mentalburst") {
+ if (
+ attacker.in != target.in ||
+ distance(attacker, target, true) >
+ attacker.range * G.skills.mentalburst.range_multiplier + G.skills.mentalburst.range_bonus
+ ) {
+ attacker.socket.emit("game_response", { response: "too_far", id: target.id, dist: dist });
+ return { failed: true, reason: "too_far", place: atype, id: target.id, dist: dist };
+ }
+ attack = attacker.attack * G.skills[atype].damage_multiplier;
+ } else if (atype == "poisonarrow") {
+ info.conditions.push("poisoned");
+ } else if (attacker.is_monster) {
+ var rng = parseInt(Math.random() * 100 - 50);
+ if (attacker.s.poisonous) {
+ info.conditions.push("poisoned");
+ }
+ attacker.last.attack = future_ms(rng);
}
- if(atype!="attack" && target.immune && (!G.skills[atype] || !G.skills[atype].pierces_immunity))
- {
- disappearing_text(target.socket,target,"IMMUNE!",{xy:1,color:"evade",nv:1,from:attacker.id});
- return {failed:true,reason:"skill_immune",place:atype,id:target.id};
+ if (atype != "attack" && target.immune && (!G.skills[atype] || !G.skills[atype].pierces_immunity)) {
+ disappearing_text(target.socket, target, "IMMUNE!", { xy: 1, color: "evade", nv: 1, from: attacker.id });
+ return { failed: true, reason: "skill_immune", place: atype, id: target.id };
}
- if(!info.positive && (attacker.is_player && G.maps[attacker.map].safe || !mode.friendly_fire && (!attacker.team || attacker.team!=target.team) && (attacker.party && attacker.party==target.party || attacker.guild && attacker.guild==target.guild)) || attacker.map=="duelland" && (!attacker.duel || !target.duel))
- {
- attacker.socket.emit("game_response",{response:"friendly",id:target.id});
- return {failed:true,reason:"friendly",place:atype,id:target.id}
+ if (
+ (!info.positive &&
+ ((attacker.is_player && G.maps[attacker.map].safe) ||
+ (!mode.friendly_fire &&
+ (!attacker.team || attacker.team != target.team) &&
+ ((attacker.party && attacker.party == target.party) ||
+ (attacker.guild && attacker.guild == target.guild))))) ||
+ (attacker.map == "duelland" && (!attacker.duel || !target.duel))
+ ) {
+ attacker.socket.emit("game_response", { response: "friendly", id: target.id });
+ return { failed: true, reason: "friendly", place: atype, id: target.id };
}
- direction_logic(attacker,target);
+ direction_logic(attacker, target);
- if(mp_cost && attacker.first && !attacker.is_npc) consume_mp(attacker,mp_cost,atype!="attack"&&atype!="heal"&&target);
- attacker.first=false;
+ if (mp_cost && attacker.first && !attacker.is_npc) {
+ consume_mp(attacker, mp_cost, atype != "attack" && atype != "heal" && target);
+ }
+ attacker.first = false;
- if(attacker.is_player)
- {
- attacker.c={};
- attacker.to_resend="u+cid";
- if(attacker.p && attacker.p.stand) attacker.p.stand=false;
+ if (attacker.is_player) {
+ attacker.c = {};
+ attacker.to_resend = "u+cid";
+ if (attacker.p && attacker.p.stand) {
+ attacker.p.stand = false;
+ }
step_out_of_invis(attacker);
- if(attacker.type=="merchant")
- {
- var gold=parseInt(attack*2);
- attack=parseInt(min(attack,attacker.gold/2));
- attacker.gold=max(0,attacker.gold-gold);
- attacker.to_resend+="+reopen";
+ if (attacker.type == "merchant") {
+ var gold = parseInt(attack * 2);
+ attack = parseInt(min(attack, attacker.gold / 2));
+ attacker.gold = max(0, attacker.gold - gold);
+ attacker.to_resend += "+reopen";
}
}
-
- if(info.procs)
- ["crit","critdamage","explosion","blast","lifesteal","manasteal"].forEach(function(p){if(attacker[p]) info[p]=attacker[p];});
- ["apiercing","rpiercing","miss"].forEach(function(p){if(attacker[p]) info[p]=attacker[p];});
- if(info.procs && attacker.a.freeze && Math.random()0 && !info.heal)
- {
- add_pdps(target,attacker,attack*B.dps_tank_mult); // "tank"
- if(attacker.cooperative) add_coop_points(attacker,target,attack*B.dps_tank_mult);
+function complete_attack(attacker, target, info) {
+ var defense = "armor";
+ var pierce = "apiercing";
+ var combo = 1;
+ var combo_m = 1;
+ var atype = info.atype;
+ var evade = false;
+ var first = true;
+ var attack = info.attack;
+ var o_attack;
+ var i_attack = info.attack;
+ var def = info.def;
+ if (G.monsters[attacker.type] && G.monsters[attacker.type].good) {
+ info.heal = info.positive = true;
}
- if(attacker.is_monster && attack>0 && !info.heal)
- {
- attacker.outgoing+=min(target.hp,attack);
+ var change = false;
+ var targets = [[target, "normal"]];
+ var otarget = target;
+ var events = [];
+ info.action.map = attacker.map;
+ info.action.in = attacker.in;
+
+ if (info.damage_type == "pure" || target === attacker) {
+ defense = "none_existent";
+ pierce = "non_existent";
+ info.apiercing = 0;
+ } else if (info.damage_type == "magical") {
+ defense = "resistance";
+ pierce = "rpiercing";
+ info.apiercing = 0;
+ } else {
+ info.damage_type = "physical";
}
- if(target.reflection && defense=="resistance" && Math.random()*100 0 && !info.heal) {
+ add_pdps(target, attacker, attack * B.dps_tank_mult); // "tank"
+ if (attacker.cooperative) {
+ add_coop_points(attacker, target, attack * B.dps_tank_mult);
+ }
+ }
+ if (attacker.is_monster && attack > 0 && !info.heal) {
+ attacker.outgoing += min(target.hp, attack);
+ }
+
+ if (
+ target.reflection &&
+ defense == "resistance" &&
+ Math.random() * 100 < target.reflection &&
+ !info.heal &&
+ attacker != target
+ ) {
+ var pid = randomStr(6);
+ var eta = 0;
+ var opid = info.action.pid;
// info.attack=ceil(attack*damage_multiplier(attacker.resistance||0))||1;
- info.attack=ceil(attack*(0.90+(attack&&(Math.random()*0.2)||0))); // A pure reflection was requested [29/03/22]
- if(!info.action.instant) eta=1000*distance(target,attacker,true)/G.projectiles[info.action.projectile].speed;
- info.target=attacker;
- info.attacker=target;
- info.eta=future_ms(eta);
- projectiles[pid]=info;
- info.action.pid=pid;
- info.action.target=attacker.id;
- info.action.attacker=target.id;
- info.action.x=attacker.x; info.action.y=attacker.y;
- info.action.reflect=info.attack;
- info.action.m=attacker.m;
+ info.attack = ceil(attack * (0.9 + ((attack && Math.random() * 0.2) || 0))); // A pure reflection was requested [29/03/22]
+ if (!info.action.instant) {
+ eta = (1000 * distance(target, attacker, true)) / G.projectiles[info.action.projectile].speed;
+ }
+ info.target = attacker;
+ info.attacker = target;
+ info.eta = future_ms(eta);
+ projectiles[pid] = info;
+ info.action.pid = pid;
+ info.action.target = attacker.id;
+ info.action.attacker = target.id;
+ info.action.x = attacker.x;
+ info.action.y = attacker.y;
+ info.action.reflect = info.attack;
+ info.action.m = attacker.m;
- if(attacker.is_player && target.is_monster || info.reflections) info.reflections=(info.reflections||0)+1;
- if(info.reflections>=4 && attacker.is_player) item_achievement_increment(attacker,attacker.slots.chest,"reflector");
- if(info.reflections>=4 && target.is_player) item_achievement_increment(target,target.slots.chest,"reflector");
+ if ((attacker.is_player && target.is_monster) || info.reflections) {
+ info.reflections = (info.reflections || 0) + 1;
+ }
+ if (info.reflections >= 4 && attacker.is_player) {
+ item_achievement_increment(attacker, attacker.slots.chest, "reflector");
+ }
+ if (info.reflections >= 4 && target.is_player) {
+ item_achievement_increment(target, target.slots.chest, "reflector");
+ }
- xy_emit(target,"hit",{pid:def.pid,hid:attacker.id,id:target.id,damage:0,reflect:info.attack},attacker.id);
- return xy_emit(target,"action",info.action,attacker.id);
+ xy_emit(
+ target,
+ "hit",
+ { pid: def.pid, hid: attacker.id, id: target.id, damage: 0, reflect: info.attack },
+ attacker.id,
+ );
+ return xy_emit(target, "action", info.action, attacker.id);
}
- if(attacker==target && !target.dead); // reflect after dead fix [04/02/23]
- else if(target.evasion && defense=="armor" && Math.random()*10072*(info.heal&&1.5||1))
- return xy_emit(info.action,"hit",{pid:def.pid,hid:attacker.id,id:target.id,damage:0,avoid:true,x:info.action.x,y:info.action.y,map:info.attacker.map,in:info.attacker.in},attacker.id);
-
- if(info.positive || !info.procs) combo=0;
- if(combo && target.targets>3)
- {
- if(!target.last_combo || ssince(target.last_combo)>5) target.combo=1;
- combo+=target.combo;
- target.last_combo=new Date();
- target.combo+=1;
- def.mobbing=target.combo;
+ if (attacker == target && !target.dead) {
+ } // reflect after dead fix [04/02/23]
+ else if (target.evasion && defense == "armor" && Math.random() * 100 < target.evasion) {
+ return xy_emit(
+ info.action,
+ "hit",
+ { pid: def.pid, hid: attacker.id, id: target.id, damage: 0, evade: true },
+ attacker.id,
+ );
+ } else if (
+ target.dc ||
+ target.dead ||
+ (attacker.miss && Math.random() * 100 < attacker.miss) ||
+ (target.avoidance && Math.random() * 100 < target.avoidance)
+ ) {
+ return xy_emit(
+ info.action,
+ "hit",
+ { pid: def.pid, hid: attacker.id, id: target.id, damage: 0, miss: true },
+ attacker.id,
+ );
+ } else if (
+ target.m != info.action.m ||
+ point_distance(target.x, target.y, info.action.x, info.action.y) > 72 * ((info.heal && 1.5) || 1)
+ ) {
+ return xy_emit(
+ info.action,
+ "hit",
+ {
+ pid: def.pid,
+ hid: attacker.id,
+ id: target.id,
+ damage: 0,
+ avoid: true,
+ x: info.action.x,
+ y: info.action.y,
+ map: info.attacker.map,
+ in: info.attacker.in,
+ },
+ attacker.id,
+ );
}
- if(combo && target.is_player && instances[target.in].pmap[target.last_hash] && Object.keys(instances[target.in].pmap[target.last_hash]).length>1)
- {
- var combo_check=false;
- for(var id in instances[target.in].pmap[target.last_hash])
- {
- var ntarget=instances[target.in].pmap[target.last_hash][id];
- if(target.id==ntarget.id || is_invinc(ntarget) || !is_same(target,ntarget,2) && !is_in_pvp(target) || attacker.id==ntarget.id) continue; //is_same(attacker,ntarget,1)
+
+ if (info.positive || !info.procs) {
+ combo = 0;
+ }
+ if (combo && target.targets > 3) {
+ if (!target.last_combo || ssince(target.last_combo) > 5) {
+ target.combo = 1;
+ }
+ combo += target.combo;
+ target.last_combo = new Date();
+ target.combo += 1;
+ def.mobbing = target.combo;
+ }
+ if (
+ combo &&
+ target.is_player &&
+ instances[target.in].pmap[target.last_hash] &&
+ Object.keys(instances[target.in].pmap[target.last_hash]).length > 1
+ ) {
+ var combo_check = false;
+ for (var id in instances[target.in].pmap[target.last_hash]) {
+ var ntarget = instances[target.in].pmap[target.last_hash][id];
+ if (
+ target.id == ntarget.id ||
+ is_invinc(ntarget) ||
+ (!is_same(target, ntarget, 2) && !is_in_pvp(target)) ||
+ attacker.id == ntarget.id
+ ) {
+ continue;
+ } //is_same(attacker,ntarget,1)
//!is_same(target,ntarget,1) && !is_in_pvp(target) to prevent people killing other people in non-pvp servers
//!is_same(target,ntarget,2) makes people kill others in coop fights
- combo_check=true; break;
+ combo_check = true;
+ break;
}
- if(combo_check)
- {
- targets=[]; combo=0;
- for(var id in instances[target.in].pmap[target.last_hash])
- {
- var ntarget=instances[target.in].pmap[target.last_hash][id];
- if(is_invinc(ntarget) || attacker.id==ntarget.id || !is_same(target,ntarget,2)) continue; //is_same(attacker,ntarget,1)
- targets.push([ntarget,"stack"]);
- if(!ntarget.last_combo || ssince(ntarget.last_combo)>5) ntarget.combo=1;
- combo+=ntarget.combo;
- ntarget.last_combo=new Date();
- ntarget.combo+=1;
+ if (combo_check) {
+ targets = [];
+ combo = 0;
+ for (var id in instances[target.in].pmap[target.last_hash]) {
+ var ntarget = instances[target.in].pmap[target.last_hash][id];
+ if (is_invinc(ntarget) || attacker.id == ntarget.id || !is_same(target, ntarget, 2)) {
+ continue;
+ } //is_same(attacker,ntarget,1)
+ targets.push([ntarget, "stack"]);
+ if (!ntarget.last_combo || ssince(ntarget.last_combo) > 5) {
+ ntarget.combo = 1;
+ }
+ combo += ntarget.combo;
+ ntarget.last_combo = new Date();
+ ntarget.combo += 1;
}
- if(targets.length>1)
- {
- def.stacked=[];
- targets.forEach(function(t){ def.stacked.push(t[0].id); })
+ if (targets.length > 1) {
+ def.stacked = [];
+ targets.forEach(function (t) {
+ def.stacked.push(t[0].id);
+ });
}
}
}
-
- if(combo>10) combo_m=combo/4.0;
- else if(combo>1) combo_m=[1,1.6,1.62,1.64,1.70,1.72,1.75,1.8,1.9,2,2,2,2][combo];
- combo_m=min(combo_m,max(300/attack,1.2)); // previously 2.4
- if(!info.positive && (info.explosion && info.damage_type=="physical" || info.blast && info.damage_type=="magical"))
- {
- var intensity=info.blast,defense="resistance";
- if(info.damage_type=="physical") intensity=info.explosion,defense="armor";
- var radius=intensity/3.6;
- if(is_in_pvp(attacker) || attacker.is_monster)
- for(var id in instances[target.in].players)
- {
- var target=instances[target.in].players[id];
- if(target.npc) continue;
- if(target.id!=otarget.id && distance(target,otarget) 10) {
+ combo_m = combo / 4.0;
+ } else if (combo > 1) {
+ combo_m = [1, 1.6, 1.62, 1.64, 1.7, 1.72, 1.75, 1.8, 1.9, 2, 2, 2, 2][combo];
+ }
+ combo_m = min(combo_m, max(300 / attack, 1.2)); // previously 2.4
+
+ if (
+ !info.positive &&
+ ((info.explosion && info.damage_type == "physical") || (info.blast && info.damage_type == "magical"))
+ ) {
+ var intensity = info.blast;
+ var defense = "resistance";
+ if (info.damage_type == "physical") {
+ intensity = info.explosion;
+ defense = "armor";
+ }
+ var radius = intensity / 3.6;
+ if (is_in_pvp(attacker) || attacker.is_monster) {
+ for (var id in instances[target.in].players) {
+ var target = instances[target.in].players[id];
+ if (target.npc) {
continue;
}
- if(target.id!=otarget.id && distance(target,otarget)0 && target.s.invincible) attack=0;
- if(attacker.tskin=="konami" && target.type!=attacker.p.target_lock) attack=0;
+ if (target["1hp"]) {
+ attack = (def.crit && 2) || 1;
+ }
+ if (attack > 0 && target.s.invincible) {
+ attack = 0;
+ }
+ if (attacker.tskin == "konami" && target.type != attacker.p.target_lock) {
+ attack = 0;
+ }
- o_attack=attack=ceil(attack);
+ o_attack = attack = ceil(attack);
- if(info.conditions.includes("frozen") && !target.immune && target.hp>attack)
- {
- if(Math.random() attack) {
+ if (Math.random() < target.fzresistance / 100.0) {
+ xy_emit(target, "ui", { type: "freeze_resist", id: target.id });
+ } else {
+ add_condition(target, "frozen");
+ disappearing_text(target.socket, target, "FREEZE!", { xy: 1, size: "huge", color: "freeze", nv: 1 }); //target.is_player&&"huge"||undefined
}
}
- if(info.conditions.includes("burned") && !target.immune && target.hp>attack)
- add_condition(target,"burned",{divider:attacker.a && attacker.a.burn && attacker.a.burn.unlimited && 1.5,
- fid:attacker.id,f:attacker.name||G.monsters[attacker.type].name,attack:attack})
+ if (info.conditions.includes("burned") && !target.immune && target.hp > attack) {
+ add_condition(target, "burned", {
+ divider: attacker.a && attacker.a.burn && attacker.a.burn.unlimited && 1.5,
+ fid: attacker.id,
+ f: attacker.name || G.monsters[attacker.type].name,
+ attack: attack,
+ });
+ }
- if(info.conditions.includes("woven") && !target.immune)
- add_condition(target,"woven");
+ if (info.conditions.includes("woven") && !target.immune) {
+ add_condition(target, "woven");
+ }
- if(info.conditions.includes("stunned") && target.hp>attack && add_condition(target,"stunned",{duration:2000}))
- disappearing_text(target.socket,target,"STUN!",{xy:1,size:"huge",color:"stun",nv:1}); //target.is_player&&"huge"||undefined
-
- if(info.procs && target.a.putrid)
- {
- add_condition(attacker,"poisoned");
- add_condition(attacker,"cursed");
- change=true;
+ if (
+ info.conditions.includes("stunned") &&
+ target.hp > attack &&
+ add_condition(target, "stunned", { duration: 2000 })
+ ) {
+ disappearing_text(target.socket, target, "STUN!", { xy: 1, size: "huge", color: "stun", nv: 1 });
+ } //target.is_player&&"huge"||undefined
+
+ if (info.procs && target.a.putrid) {
+ add_condition(attacker, "poisoned");
+ add_condition(attacker, "cursed");
+ change = true;
}
- info.conditions.forEach(function(c){
- if(["frozen","burned","woven","stunned"].includes(c)) return;
- if(target.hp>attack && !target.immune)
- add_condition(target,c);
- })
- if(info.procs && attacker.a.sugarrush && Math.random()<0.0025)
- {
- def.trigger="sugarrush";
- add_condition(attacker,"sugarrush");
- disappearing_text(attacker.socket,attacker,"SUGAR RUSH!",{xy:1,size:"huge",color:"sugar",nv:1}); //target.is_player&&"huge"||undefined
+ info.conditions.forEach(function (c) {
+ if (["frozen", "burned", "woven", "stunned"].includes(c)) {
+ return;
+ }
+ if (target.hp > attack && !target.immune) {
+ add_condition(target, c);
+ }
+ });
+ if (info.procs && attacker.a.sugarrush && Math.random() < 0.0025) {
+ def.trigger = "sugarrush";
+ add_condition(attacker, "sugarrush");
+ disappearing_text(attacker.socket, attacker, "SUGAR RUSH!", { xy: 1, size: "huge", color: "sugar", nv: 1 }); //target.is_player&&"huge"||undefined
}
- if(attacker.s.invis) // && target.is_player
- {
- def.sneak=true;
- disappearing_text(target.socket,target,"SNEAK!",{xy:1,size:"huge",color:"sneak",nv:1});
+ if (attacker.s.invis) {
+ // && target.is_player
+ def.sneak = true;
+ disappearing_text(target.socket, target, "SNEAK!", { xy: 1, size: "huge", color: "sneak", nv: 1 });
}
- if(info.damage_type=="pure") attack=ceil(info.first_attack);
- if(target["1hp"]) attack=def.crit&&2||1;
- }
- else
- {
- attack=o_attack;
- if(target_def[1]=="splash") attack=ceil(attack*target_def[2]);
- if(target["1hp"]) def.damage=o_attack=attack=1;
- }
- if(attack>=1)
- {
- target.last.attacked=new Date();
- if(target.is_monster && attacker.is_player) target.points[attacker.name]=(target.points[attacker.name]||0)+1;
- }
- if(atype=="deepfreeze" && add_condition(target,"deepfreezed"))
- def.deepfreeze=true;
-
- def.damage=attack;
- if(info.lifesteal)
- {
- var hp=ceil(min(attack,target.hp)*info.lifesteal/100.0);
- attacker.hp=min(attacker.max_hp,attacker.hp+hp); change=true;
- if(hp) def.lifesteal=hp;
- }
- if(info.manasteal)
- {
- var mp=ceil(min(attack,target.hp)*info.manasteal/100.0);
- if(target.mp!==undefined)
- {
- mp=min(target.mp,mp);
- target.mp=max(0,target.mp-mp);
+ if (info.damage_type == "pure") {
+ attack = ceil(info.first_attack);
}
- else
- mp=0;
- if(attacker.mp!==undefined)
- {
- attacker.mp=min(attacker.max_mp||0,attacker.mp+mp); change=true;
+ if (target["1hp"]) {
+ attack = (def.crit && 2) || 1;
+ }
+ } else {
+ attack = o_attack;
+ if (target_def[1] == "splash") {
+ attack = ceil(attack * target_def[2]);
+ }
+ if (target["1hp"]) {
+ def.damage = o_attack = attack = 1;
}
- if(mp) def.manasteal=mp;
}
- if(G.monsters[attacker.type] && G.monsters[attacker.type].goldsteal && target.gold)
- {
+ if (attack >= 1) {
+ target.last.attacked = new Date();
+ if (target.is_monster && attacker.is_player) {
+ target.points[attacker.name] = (target.points[attacker.name] || 0) + 1;
+ }
+ }
+ if (atype == "deepfreeze" && add_condition(target, "deepfreezed")) {
+ def.deepfreeze = true;
+ }
+
+ def.damage = attack;
+ if (info.lifesteal) {
+ var hp = ceil((min(attack, target.hp) * info.lifesteal) / 100.0);
+ attacker.hp = min(attacker.max_hp, attacker.hp + hp);
+ change = true;
+ if (hp) {
+ def.lifesteal = hp;
+ }
+ }
+ if (info.manasteal) {
+ var mp = ceil((min(attack, target.hp) * info.manasteal) / 100.0);
+ if (target.mp !== undefined) {
+ mp = min(target.mp, mp);
+ target.mp = max(0, target.mp - mp);
+ } else {
+ mp = 0;
+ }
+ if (attacker.mp !== undefined) {
+ attacker.mp = min(attacker.max_mp || 0, attacker.mp + mp);
+ change = true;
+ }
+ if (mp) {
+ def.manasteal = mp;
+ }
+ }
+ if (G.monsters[attacker.type] && G.monsters[attacker.type].goldsteal && target.gold) {
//var gold=min(target.gold,parseInt(ceil(target.level*target.level/10)));
- var gold=parseInt(Math.random()*12)+1;
- target.gold=max(0,target.gold-gold);
- attacker.extra_gold=(attacker.extra_gold||0)+gold;
- def.goldsteal=gold;
+ var gold = parseInt(Math.random() * 12) + 1;
+ target.gold = max(0, target.gold - gold);
+ attacker.extra_gold = (attacker.extra_gold || 0) + gold;
+ def.goldsteal = gold;
}
}
- var original=target.hp;
- if(target.s.mshield && target.mp>200 && attack>0)
- {
+ var original = target.hp;
+ if (target.s.mshield && target.mp > 200 && attack > 0) {
// console.log("HERE MPSHIELD!")
- var max_mp=target.mp-200,damage_per_mp=1.5;
- if(target.level>99) damage_per_mp=3;
- else if(target.level>89) damage_per_mp=2.4;
- else if(target.level>79) damage_per_mp=2;
- else if(target.level>69) damage_per_mp=1.75;
- var max_hp=ceil(max_mp*damage_per_mp);
- if(max_hp 99) {
+ damage_per_mp = 3;
+ } else if (target.level > 89) {
+ damage_per_mp = 2.4;
+ } else if (target.level > 79) {
+ damage_per_mp = 2;
+ } else if (target.level > 69) {
+ damage_per_mp = 1.75;
}
- else
- {
- def.mp_damage=parseInt(attack/damage_per_mp);
- attack=0;
- target.mp-=def.mp_damage;
+ var max_hp = ceil(max_mp * damage_per_mp);
+ if (max_hp < attack) {
+ def.mp_damage = max_mp;
+ attack -= max_hp;
+ target.mp = 200;
+ } else {
+ def.mp_damage = parseInt(attack / damage_per_mp);
+ attack = 0;
+ target.mp -= def.mp_damage;
}
- change=true;
+ change = true;
}
- target.hp=min(target.hp-attack,target.max_hp); // both for damage and heal
- var net=original-max(0,target.hp);
- if(target.hp<=0)
- {
- def.kill=true;
- if(G.skills[atype].kill_buff) add_condition(attacker,G.skills[atype].kill_buff);
+ target.hp = min(target.hp - attack, target.max_hp); // both for damage and heal
+ var net = original - max(0, target.hp);
+ if (target.hp <= 0) {
+ def.kill = true;
+ if (G.skills[atype].kill_buff) {
+ add_condition(attacker, G.skills[atype].kill_buff);
+ }
}
- if(target.dreturn && i_attack>0 && first && attacker.range<75 && info.damage_type=="physical" && !attacker["1hp"]) // dreturn happens at every hit
- {
- def.dreturn=ceil(i_attack*target.dreturn/100.0);
- if(attacker.is_monster) attacker.u=true,attacker.cid++;
- attacker.hp=max(attacker.hp-def.dreturn,0);
+ if (
+ target.dreturn &&
+ i_attack > 0 &&
+ first &&
+ attacker.range < 75 &&
+ info.damage_type == "physical" &&
+ !attacker["1hp"]
+ ) {
+ // dreturn happens at every hit
+ def.dreturn = ceil((i_attack * target.dreturn) / 100.0);
+ if (attacker.is_monster) {
+ attacker.u = true;
+ attacker.cid++;
+ }
+ attacker.hp = max(attacker.hp - def.dreturn, 0);
}
// if(target.is_player && net>0) target.s.damage_received={amount:target.s.damage_received&&(target.s.damage_received.amount+net)||net,ms:10000};
- if(attacker.is_player)
- {
- if(net>0) // "attack"
- {
- if(attacker.t) attacker.t.mdamage+=net;
- add_pdps(attacker,target,net);
+ if (attacker.is_player) {
+ if (net > 0) {
+ // "attack"
+ if (attacker.t) {
+ attacker.t.mdamage += net;
+ }
+ add_pdps(attacker, target, net);
+ } // "heal"
+ else {
+ add_pdps(attacker, target, -net * B.dps_heal_mult);
}
- else // "heal"
- add_pdps(attacker,target,-net*B.dps_heal_mult);
- var m=target,mnet=net;
- if(net<0 && target.s && target.s.coop)
- {
- m=instances[attacker.in].monsters[target.s.coop.id];
- mnet=-net*B.dps_heal_mult;
- if(m && m.attack<120) mnet/=100; // dirty fix
+ var m = target;
+ var mnet = net;
+ if (net < 0 && target.s && target.s.coop) {
+ m = instances[attacker.in].monsters[target.s.coop.id];
+ mnet = -net * B.dps_heal_mult;
+ if (m && m.attack < 120) {
+ mnet /= 100;
+ } // dirty fix
// console.log("coop heal: "+m)
}
- if(target.master)
- {
- m=instances[attacker.in].monsters[target.master];
+ if (target.master) {
+ m = instances[attacker.in].monsters[target.master];
}
- if(m && m.is_monster && m.cooperative) add_coop_points(m,attacker,mnet);
- }
-
- if(mode.instant_monster_attacks || attacker.is_player)
- xy_emit(target,"hit",def,attacker.id); // always sends the event to attacker.id
- else
- events.push(["hit",def]);
-
- if(attacker.is_monster) //monster attacks player
- {
- achievement_logic_monster_hit(attacker,target,attack);
- if(target.hp<=0 && !target.rip)
- {
- if(target.a && target.a.secondchance && Math.random()*1006000)
- {
- var ms=max(0,-mssince(player.last.attack))+3200,EV="";
- EV="skill_timeout('attack',"+ms+"); ";
- player.last.attack=future_ms(ms);
- for(var i in player.last)
- {
- if(G.skills[i] && player.last[i]>future_ms(-3000))
- player.last[i]=future_ms(3200),EV+="skill_timeout('"+i+"',"+(3200+(G.skills[i].cooldown||0))+"); ";
+ add_call_cost(player, 8, "transport"); // New - to offset send_all_xy [26/01/20]
+ if (0 && !effect && mssince(player.last.transport) > 6000) {
+ var ms = max(0, -mssince(player.last.attack)) + 3200;
+ var EV = "";
+ EV = "skill_timeout('attack'," + ms + "); ";
+ player.last.attack = future_ms(ms);
+ for (var i in player.last) {
+ if (G.skills[i] && player.last[i] > future_ms(-3000)) {
+ player.last[i] = future_ms(3200);
+ EV += "skill_timeout('" + i + "'," + (3200 + (G.skills[i].cooldown || 0)) + "); ";
+ }
}
}
- if(effect) player.s.penalty_cd={ms:min(((player.s.penalty_cd&&player.s.penalty_cd.ms)||0)+812,120000)};
- else player.s.penalty_cd={ms:min(((player.s.penalty_cd&&player.s.penalty_cd.ms)||0)+3200,120000)};
- player.socket.emit("new_map",{name:instance.map,in:name,x:player.x,y:player.y,direction:direction,effect:effect||0,info:instance.info,m:player.m,entities:send_all_xy(player,{raw:true}),eval:EV});
- player.last.transport=new Date();
- resend(player,"u+cid");
+ if (effect) {
+ player.s.penalty_cd = { ms: min(((player.s.penalty_cd && player.s.penalty_cd.ms) || 0) + 812, 120000) };
+ } else {
+ player.s.penalty_cd = { ms: min(((player.s.penalty_cd && player.s.penalty_cd.ms) || 0) + 3200, 120000) };
+ }
+ player.socket.emit("new_map", {
+ name: instance.map,
+ in: name,
+ x: player.x,
+ y: player.y,
+ direction: direction,
+ effect: effect || 0,
+ info: instance.info,
+ m: player.m,
+ entities: send_all_xy(player, { raw: true }),
+ eval: EV,
+ });
+ player.last.transport = new Date();
+ resend(player, "u+cid");
}
-function add_shells(player,amount,reason,announce,override)
-{
- if(gameplay=="hardcore" || gameplay=="test") return;
- var phrase="Received";
- if(reason=="xptome") phrase="Earned";
- player.cash+=amount;
- player.socket.emit("game_log",{message:phrase+" "+to_pretty_num(amount)+" SHELLS",color:"green"});
- disappearing_text(player.socket,player,"+"+to_pretty_num(amount),{color:colors.cash,xy:1,s:"cash",size:"huge"});
- appengine_call("bill_user",{auth:player.auth,amount:-parseInt(amount),reason:reason+"_drop",name:player.name,override:override},function(result){
- if(result.failed || !result.done) return;
- player.cash=result.cash;
- resend(player,"reopen");
+function add_shells(player, amount, reason, announce, override) {
+ if (gameplay == "hardcore" || gameplay == "test") {
+ return;
+ }
+ var phrase = "Received";
+ if (reason == "xptome") {
+ phrase = "Earned";
+ }
+ player.cash += amount;
+ player.socket.emit("game_log", { message: phrase + " " + to_pretty_num(amount) + " SHELLS", color: "green" });
+ disappearing_text(player.socket, player, "+" + to_pretty_num(amount), {
+ color: colors.cash,
+ xy: 1,
+ s: "cash",
+ size: "huge",
});
- if(announce) broadcast("server_message",{"message":player.name+" found "+to_pretty_num(amount)+" shells","color":"#85C76B","type":"server_found",shells:amount,name:player.name});
+ appengine_call(
+ "bill_user",
+ { auth: player.auth, amount: -parseInt(amount), reason: reason + "_drop", name: player.name, override: override },
+ function (result) {
+ if (result.failed || !result.done) {
+ return;
+ }
+ player.cash = result.cash;
+ resend(player, "reopen");
+ },
+ );
+ if (announce) {
+ broadcast("server_message", {
+ message: player.name + " found " + to_pretty_num(amount) + " shells",
+ color: "#85C76B",
+ type: "server_found",
+ shells: amount,
+ name: player.name,
+ });
+ }
}
-function is_socket_allowed(socket)
-{
- var loose=0;
- for(var id in sockets)
- {
- if(!players[id] && get_ip(sockets[id])==get_ip(socket)) loose++;
+function is_socket_allowed(socket) {
+ var loose = 0;
+ for (var id in sockets) {
+ if (!players[id] && get_ip(sockets[id]) == get_ip(socket)) {
+ loose++;
+ }
+ }
+ if (loose > 5) {
+ return false;
}
- if(loose>5) return false;
return true;
}
-function disconnect_old_sockets(socket)
-{
- for(var id in sockets)
- {
- if(id!=socket.id && !players[id] && get_ip(sockets[id])==get_ip(socket))
- {
- sockets[id].emit("disconnect_reason","Too many loose connections from your network. Simply reload to play.");
- if(sockets[id]) sockets[id].disconnect(); // emit can trigger a disconnect too, so this would throw an exception, bring down the server
+function disconnect_old_sockets(socket) {
+ for (var id in sockets) {
+ if (id != socket.id && !players[id] && get_ip(sockets[id]) == get_ip(socket)) {
+ sockets[id].emit("disconnect_reason", "Too many loose connections from your network. Simply reload to play.");
+ if (sockets[id]) {
+ sockets[id].disconnect();
+ } // emit can trigger a disconnect too, so this would throw an exception, bring down the server
}
}
}
-function init_io(){
-io.on('connection', function (socket) {
- if(socket.handshake.query.server_method)
- {
- if(socket.handshake.query.server_master==variables.server_master)
- {
- if(socket.handshake.query.server_method=="players")
- {
- socket.emit("players"); // decided to make the existing cron more aggressive [26/09/21]
+function init_io() {
+ io.on("connection", function (socket) {
+ if (socket.handshake.query.server_method) {
+ if (0 && socket.handshake.query.server_master == variables.server_master) {
+ // this was to make servers communicate with each other and disconnect overflows immediately [28/10/23]
+ if (socket.handshake.query.server_method == "players") {
+ socket.emit("players"); // decided to make the existing cron more aggressive [26/09/21]
+ }
}
+ socket.disconnect();
+ return;
}
- socket.disconnect();
- return;
- }
- sockets[socket.id]=socket;
- socket.total_calls=0;
- socket.calls=[];
- socket.fs={}; // function list
-
- if(!is_socket_allowed(socket)) disconnect_old_sockets(socket);
+ sockets[socket.id] = socket;
+ socket.total_calls = 0;
+ socket.calls = [];
+ socket.fs = {}; // function list
- var original_on=socket.on;
- socket.on=function(method,f){
- // takes the "f" function, the function thats sent to socket.on, wraps it into a "g" function
- var g=function(data){
- ls_method=method;
- if(mode.log_all) console.log("'"+method+"': "+JSON.stringify(data));
- try{
- var climit=limits.calls,name="_observer";
- if(data===undefined) data={}; // data normalisation [28/08/18]
- socket.total_calls++; add_call_cost(-1);
- current_socket=socket;
- call_modifier=({"open_chest":0.1,"skill":0.05,"target":0.5}[method])||1;
- if(players[socket.id])
- {
- name=players[socket.id].name;
- // if(players[socket.id].type=="merchant") climit=round(climit/3);
- // Merchants are first class citizens now! [14/01/18]
+ if (!is_socket_allowed(socket)) {
+ disconnect_old_sockets(socket);
+ }
+
+ var original_on = socket.on;
+ socket.on = function (method, f) {
+ // takes the "f" function, the function thats sent to socket.on, wraps it into a "g" function
+ var g = function (data) {
+ ls_method = method;
+ if (mode.log_all) {
+ console.log("'" + method + "': " + JSON.stringify(data));
}
- else
- {
- climit=round(climit/4);
- }
- if(method=="cm")
- {
- var add=1,len=data.message.length,mult=1;
- if(len>100) add=2;
- else if(len>1000) add=3;
- else if(len>10000) add=10;
- else if(len>50000) add=20;
- // console.log("add: "+add+"len: "+len);
- if(data.to.length>1) mult=0.8;
- add_call_cost(add*data.to.length*mult,undefined,"cm_data");
- }
- else
- {
- if(CC[method]) add_call_cost(CC[method]||0);
- }
- if(get_call_cost()>climit && method!="disconnect")
- {
- server_log(">>> LIMITDC "+name,1);
- socket.emit("limitdcreport",{calls:socket.calls,climit:climit,total:socket.total_calls});
- socket.emit("disconnect_reason","limitdc");
- socket.disconnect();
- }
- else f(data);
- }
- catch(e){
- try{
- var climit=limits.calls;
- add_call_cost(16);
- log_trace("socket.on: "+method.substr(0,200),e);
- if(get_call_cost()>climit)
- {
- server_log(">>> LIMITDC2 "+name,1);
- socket.emit("limitdcreport",{calls:socket.calls,climit:climit,total:socket.total_calls,method:method.substr(0,200)});
- socket.emit("disconnect_reason","limitdc");
- socket.disconnect();
+ try {
+ var climit = limits.calls;
+ var name = "_observer";
+ if (data === undefined) {
+ data = {};
+ } // data normalisation [28/08/18]
+ socket.total_calls++;
+ add_call_cost(-1);
+ current_socket = socket;
+ call_modifier = { open_chest: 0.1, skill: 0.05, target: 0.5 }[method] || 1;
+ if (players[socket.id]) {
+ name = players[socket.id].name;
+ // if(players[socket.id].type=="merchant") climit=round(climit/3);
+ // Merchants are first class citizens now! [14/01/18]
+ } else {
+ climit = round(climit / 4);
}
- else
- {
- try{
- socket.emit("game_error","ERROR!");
- }catch(e){}
- }
- }catch(e){
- log_trace("limit_calls",e);
- }
- }
- current_socket=false_socket;
- }
- socket.fs[method]=f;
- original_on.apply(socket,[method,g]);
- };
-
- var data={region:region,name:server_name,pvp:is_pvp,gameplay:gameplay,info:instances[socket.first_map]&&instances[socket.first_map].info||{}};
- socket.first_map=socket.first_in=observer_map;
- socket.first_x=observer_x;
- socket.first_y=observer_y+120;
- socket.desktop=true;
- if(socket.request && socket.request._query && socket.request._query.secret)
- {
- for(var id in players)
- {
- var player=players[id];
- if(player.secret==socket.request._query.secret)
- {
- socket.player=player;
- data.character=player_to_client(player); data.character.id=data.character.name=player.name;
- socket.first_map=player.map;
- socket.first_in=player.in;
- socket.first_x=player.x;
- socket.first_y=player.y;
- if(socket.request._query.desktop) socket.desktop=true,socket.first_y+=120;
- else socket.desktop=false;
- }
- }
- }
- data.x=socket.first_x; data.y=socket.first_y; data.map=socket.first_map; data.in=socket.first_in;
- broadcast_e(true);
- data.S=E;
- socket.emit('welcome',data);
- socket.on('send_updates',function(){
- if(observers[socket.id]) send_all_xy(observers[socket.id]);
- if(players[socket.id]) send_all_xy(players[socket.id]);
- })
- socket.on('loaded',function(data){
- var observer=observers[socket.id]={
- socket:socket,
- x:socket.first_x,y:socket.first_y,
- // vision:[round((data.width/2)/data.scale)+B.ext_vision,round((data.height/2)/data.scale)+B.ext_vision],
- map:socket.first_map,
- in:socket.first_in,
- observer:1,
- id:"o"+socket.id,
- s:{},
- };
- if(socket.player) observer.player=socket.player;
- // observer.vision[0]=min(1000,observer.vision[0]); observer.vision[1]=min(700,observer.vision[1]);
- observer.vision=B.vision;
- // socket.emit("observing",{map:observer.map,x:observer.x,y:observer.y});
- resume_instance(instances[observer.in]);
- instances[observer.in].observers[observer.id]=observer;
- send_all_xy(observer);
- });
- socket.on('o:home',function(data){
- var observer=observers[socket.id];
- if(!observer) return;
- var player=observer.player;
- if(!player || player.dc) return;
- transport_observer_to(observer,player.in,player.map,player.x,player.y+(socket.desktop&&120||0));
- });
- socket.on('o:command',function(data){
- var observer=observers[socket.id];
- if(!observer) return;
- var player=observer.player;
- if(!player || player.dc) return;
- player.socket.emit('code_eval',data);
- });
- socket.on('cm',function(data){
- var player=players[socket.id],receivers=[];
- if(!player || player.s.mute) return fail_response("muted");
- data.to.forEach(function(name){
- var p=players[name_to_id[name]];
- if(p) p.socket.emit("cm",{name:player.name,message:data.message||""}),receivers.push(name);
- });
- success_response("data",{locals:[],receivers:receivers});
- });
- socket.on('say',function(data){
- var player=players[socket.id],message=strip_string(data.message).substr(0,1200); if(!player || player.s.mute) return fail_response("muted");
- if(data.code && player.last_say && ssince(player.last_say)<15) return fail_response("chat_slowdown");
- if(player.last_say && mssince(player.last_say)<400) return fail_response("chat_slowdown");
- if(!message || !message.length) return fail_response("invalid");
- player.last_say=new Date();
- if(data.party)
- {
- if(!player.party) return fail_response("not_in_a_party");
- party_emit(player.party,"partym",{owner:player.name,message:message,id:player.id,p:true});
- }
- else if(data.name)
- {
- var target=get_player(data.name);
- if(!target)
- {
- player.socket.emit("pm",{owner:player.name,to:data.name,message:message,id:player.id,xserver:true});
- appengine_call("log_chat",{to:["",data.name],type:"xprivate",message:message,fro:player.name,author:player.owner},function(result){
- if(result.failed && players[socket.id])
- player.socket.emit("pm",{owner:player.name,to:data.name,message:"(FAILED)",id:player.id,xserver:true});
- });
- }
- else
- {
- if(target.name==player.name) return fail_response("invalid");
- player.socket.emit("pm",{owner:player.name,to:data.name,message:message,id:player.id});
- target.socket.emit("pm",{owner:player.name,message:message,id:player.id});
- appengine_call("log_chat",{to:[target.owner,target.name],type:"private",message:message,fro:player.name,author:player.owner});
- }
- }
- else
- {
- if(1)
- {
- broadcast("chat_log",{owner:player.name,message:message,id:player.id,p:true});
- var owners={};
- for(var id in players)
- {
- var p=players[id];
- owners[p.owner]=owners[p.owner]||[];
- owners[p.owner].push(p.name);
- }
- appengine_call("log_chat",{to:Object.entries(owners),type:"ambient",message:message,fro:player.name,author:player.owner});
- }
- else
- xy_emit(player,"chat_log",{owner:player.name,message:message,id:player.id,p:true});
- appengine_call("log_chat",{type:"server",message:message,fro:player.name,author:player.owner});
- }
- if(player.s.typing)
- {
- delete player.s.typing;
- resend(player,"u+cid+nc");
- }
- success_response();
- });
- socket.on('ping_trig',function(data){ socket.emit("ping_ack",data); });
- socket.on('target',function(data){
- var player=players[socket.id]; if(!player) return;
- reduce_call_cost();
- player.target=data.id;
- player.focus=data.xid;
- var target=instances[player.in].monsters[data.id];
- if(!target) target=instances[player.in].players[data.id];
- if(!target) target=instances[player.in].players[NPC_prefix+data.id];
- if(!target) player.target=null;
- var focus=instances[player.in].monsters[data.xid];
- if(!focus) focus=instances[player.in].players[data.xid];
- if(!focus) focus=instances[player.in].players[NPC_prefix+data.xid];
- if(!focus) player.focus=null;
- if(focus && focus.screenshot)
- {
- target.going_x=player.x;
- target.going_y=player.y;
- target.u=true;
- start_moving_element(focus);
- }
- if(focus && player.map=="cgallery" && focus.npc)
- {
- // target.going_x=player.x;
- // target.going_y=player.y;
- // target.u=true;
- // start_moving_element(target);
- if(!player.tcx) player.tcx={};
- if(focus.ctype=="body")
- player.tskin=focus.skin;
- else if(player.cx.length>5) return fail_response("invalid");
- player.tcx[focus.ctype]=focus.cx[focus.ctype];
- // player.tcx=target.cx;
- resend(player,"u+cid");
- }
- // server_log(player.name+" target: "+player.target+" focus: "+player.focus);
- resend(player,"u+nc");
- success_response({});
- });
- socket.on('ureward',function(data){
- if(!player || player.user || !data.name || !G.docs.rewards[data.name]) return;
- if(!player.verified || !player.auth_id) return socket.emit("game_response","reward_notverified");
- if(!player.user.rewards) player.user.rewards=[];
- if(player.user.rewards.includes(data.name)) return socket.emit("game_response","reward_already");
- player.user.rewards.push(data.name);
- exchange(player,G.docs.rewards[data.name],{name:"reward_"+data.name});
- socket.emit("game_response",{response:"reward_received",rewards:player.user.rewards});
-
- });
- socket.on('creward',function(data){
- if(!player || !data.name || !G.classes[player.type].rewards[data.name]) return;
- if(!player.verified || !player.auth_id) return socket.emit("game_response","reward_notverified");
- if(!player.p.rewards) player.p.rewards=[];
- if(player.p.rewards.includes(data.name)) return socket.emit("game_response","reward_already");
- player.p.rewards.push(data.name);
- exchange(player,G.classes[player.type].rewards[data.name].reward,{name:"reward_"+data.name});
- socket.emit("game_response",{response:"reward_received",rewards:player.p.rewards});
-
- });
- socket.on('cx',function(data){
- var player=players[socket.id]; if(!player) return;
- // if(player.role!="gm") return socket.emit('game_log',"Cosmetics system is out of the test phase for now");
- // console.log(data);
- var cx=player.cx,cxl=all_cx(player);
- // if(!player.tcx) player.tcx=clone(player.cx);
- if(data.slot && !data.name)
- {
- if(data.slot=="back") delete cx.tail; // synced with render_cgallery
- if(data.slot=="face") delete cx.makeup;
- delete cx[data.slot];
- }
- else
- {
- if(!T[data.name] || !cxl[data.name] && player.role!="cx") return fail_response("cx_not_found");
- if((T[data.name]=="body" || T[data.name]=="armor" || T[data.name]=="character") && data.slot=="skin") player.skin=data.name;
- else if((T[data.name]=="body" || T[data.name]=="armor") && data.slot=="upper") cx.upper=data.name;
- else if(cxtype_to_slot[T[data.name]] && cxtype_to_slot[T[data.name]]!="skin")
- cx[cxtype_to_slot[T[data.name]]]=data.name;
- }
- prune_cx(player.cx,player.skin);
- resend(player,"u+cid");
- success_response();
- });
- socket.on('gm',function(data){
- var player=players[socket.id]; if(!player || player.role!="gm") return;
- var target=players[id_to_id[data.id]],action=data.action;
- if(action=="mute")
- {
- if(!target) return socket.emit("game_log","Player not found: "+data.id);
- if(!target.s.mute)
- {
- target.s.mute={ms:48*60*60*1000};
- return socket.emit("game_chat","Muted "+target.name);
- }
- else
- {
- target.s.mute={ms:0};
- return socket.emit("game_chat","Unmuted "+target.name);
- }
- }
- else if(action=="jail")
- {
- if(!target) return socket.emit("game_log","Player not found: "+data.id);
- transport_player_to(target,"jail");
- }
- else if(action=="ban")
- {
- appengine_call("ban_user",{name:data.id},function(result){
- socket.emit("game_log","Ban: "+(result&&result.result||"No result"));
- });
- }
- else if(action=="invincible")
- {
- player.s.invincible={ms:24*60*60*1000};
- resend(player,"u+cid");
- }
- else if(action=="jump")
- {
- if(!target) return socket.emit("game_log","Player not found: "+data.id);
- var spot=safe_xy_nearby(target.map,target.x-8,target.y-6);
- if(spot)
- {
- pulled=player;
- pulled.s.magiport={ms:400};
- pulled.s.magiport.x=spot.x;
- pulled.s.magiport.y=spot.y;
- pulled.s.magiport.f=target.name;
- pulled.s.magiport.in=target.in;
- pulled.s.magiport.map=target.map;
- resend(pulled,"u+cid")
- }
- else return socket.emit("game_log","No safe spot near: "+data.id);
- }
- else if(action=="mjump")
- {
- target=get_monsters(data.monster)[0];
- if(!target) return socket.emit("game_log","Monster not found: "+data.monster);
- var spot=safe_xy_nearby(target.map,target.x-8,target.y-6);
- if(spot)
- {
- pulled=player;
- pulled.s.magiport={ms:400};
- pulled.s.magiport.x=spot.x;
- pulled.s.magiport.y=spot.y;
- pulled.s.magiport.f=target.name;
- pulled.s.magiport.in=target.in;
- pulled.s.magiport.map=target.map;
- resend(pulled,"u+cid")
- }
- else return socket.emit("game_log","No safe spot near: "+data.monster);
- }
- else if(action=="jump_list")
- {
- var ids=[];
- for(var id in players)
- ids.push(players[id].name);
- socket.emit("gm",{action:"jump_list",ids:ids});
- }
- else if(action=="server_info")
- {
- var info=[];
- for(var id in players)
- {
- info.push({name:players[id].name,owner:players[id].owner,ip:get_ip(players[id])});
- }
- //socket.emit("gm",{action:"server_info",info:info});
- }
- });
- socket.on('monsterhunt',function(data){
- var player=players[socket.id]; if(!player) return;
- if(simple_distance(G.maps.main.ref.monsterhunter,player,true)>B.sell_dist) return fail_response("distance");
- var hunted=[];
- for(var id in server.s)
- {
- if(server.s[id].type=="monsterhunt")
- hunted.push(server.s[id].id);
- }
- if(player.s.monsterhunt && player.s.monsterhunt.c) return fail_response("monsterhunt_already");
- else if(player.s.monsterhunt)
- {
- delete server.s["monsterhunt_"+player.s.monsterhunt.id]
- delete player.s.monsterhunt;
- add_item(player,"monstertoken",{log:true,q:(gameplay=="hardcore"&&100||1)});
- resend(player,"u+cid+reopen");
- return success_response({completed:true});
- }
- if(player.type=="merchant") return socket.emit("game_response","monsterhunt_merchant");
- var mmax=-1,name="goo",count=100,times=0,the_hp=0;
- for(var id in instances)
- {
- if(instances[id].name!=id || !G.maps[id] || G.maps[id].irregular) continue;
- for(var mid in instances[id].monsters)
- {
- var monster=instances[id].monsters[mid];
- if(monster.level>mmax && !in_arr(monster.type,hunted) && !monster.target) // added the target condition [21/07/23]
- {
- name=monster.type;
- mmax=monster.level;
- the_hp=monster.max_hp/1000.0;
- }
- }
- }
- for(var id in G.maps)
- {
- if(G.maps[id].irregular || !G.maps[id].monsters) continue;
- G.maps[id].monsters.forEach(function(p){
- if(p.type==name) times+=p.count;
- });
- }
- // console.log(times);
- count=max(1,min(500,parseInt(20*60*max(1,times)/the_hp/(G.monsters[name].respawn+0.25))));
- if(gameplay=="hardcore") count=max(1,parseInt(count/10))
- player.s.monsterhunt={sn:region+" "+server_name,id:name,c:count,ms:30*60*1000,dl:true};
- server.s["monsterhunt_"+name]={name:player.name,id:name,ms:20*60*1000,type:"monsterhunt"};
- player.hitchhikers.push(["game_response","monsterhunt_started"]);
- resend(player,"u+cid");
- success_response({started:true});
- });
- socket.on('ccreport',function(){
- socket.emit('ccreport',{calls:socket.calls,climit:limits.calls,total:socket.total_calls});
- });
- socket.on('tracker',function(data){
- var player=players[socket.id]; if(!player) return;
- if(!player.tracker) return;
- var data={monsters:player.p.stats.monsters,monsters_diff:player.p.stats.monsters_diff,exchanges:player.p.stats.exchanges,maps:D.drops.maps,tables:{},max:player.max_stats}; // ,computer:false
- function register_table(table)
- {
- if(table)
- table.forEach(function(drop){
- if(drop[1]=="open" && !data.tables[drop[2]])
- {
- data.tables[drop[2]]=D.drops[drop[2]];
- register_table(D.drops[drop[2]]);
- }
- });
- }
- if(player.computer || 1)
- {
- // data.computer=true;
- data.drops=D.drops.monsters;
- }
- else
- {
- data.drops={};
- for(var name in data.monsters)
- if(data.monsters[name]>=100 && D.drops.monsters[name])
- data.drops[name]=D.drops.monsters[name];
- }
- if(D.drops.maps.global) data.global=D.drops.maps.global,register_table(data.global);
- if(D.drops.maps.global_static) data.global_static=D.drops.maps.global_static,register_table(data.global_static);
- for(var name in data.drops)
- register_table(data.drops[name]);
- for(var name in data.maps)
- register_table(data.maps[name]);
- for(var name in G.items)
- if(G.items[name].e && (player.computer || 1 || player.p.stats.exchanges && player.p.stats.exchanges[name] && player.p.stats.exchanges[name]>=100))
- {
- if(G.items[name].upgrade || G.items[name].compound)
- {
- for(var i=0;i<13;i++)
- if(D.drops[name+i])
- {
- data.tables[name+i]=D.drops[name+i];
- register_table(data.tables[name+i]);
+ if (method == "cm") {
+ var add = 1;
+ var len = data.message.length;
+ var mult = 1;
+ if (len > 100) {
+ add = 2;
+ } else if (len > 1000) {
+ add = 3;
+ } else if (len > 10000) {
+ add = 10;
+ } else if (len > 50000) {
+ add = 20;
}
+ // console.log("add: "+add+"len: "+len);
+ if (data.to.length > 1) {
+ mult = 0.8;
+ }
+ add_call_cost(add * data.to.length * mult, undefined, "cm_data");
+ } else {
+ if (CC[method]) {
+ add_call_cost(CC[method] || 0);
+ }
+ }
+ if (get_call_cost() > climit && method != "disconnect") {
+ server_log(">>> LIMITDC " + name, 1);
+ socket.emit("limitdcreport", { calls: socket.calls, climit: climit, total: socket.total_calls });
+ socket.emit("disconnect_reason", "limitdc");
+ socket.disconnect();
+ } else {
+ f(data);
+ }
+ } catch (e) {
+ try {
+ var climit = limits.calls;
+ add_call_cost(16);
+ log_trace("socket.on: " + method.substr(0, 200), e);
+ if (get_call_cost() > climit) {
+ server_log(">>> LIMITDC2 " + name, 1);
+ socket.emit("limitdcreport", {
+ calls: socket.calls,
+ climit: climit,
+ total: socket.total_calls,
+ method: method.substr(0, 200),
+ });
+ socket.emit("disconnect_reason", "limitdc");
+ socket.disconnect();
+ } else {
+ try {
+ socket.emit("game_error", "ERROR!");
+ } catch (e) {}
+ }
+ } catch (e) {
+ log_trace("limit_calls", e);
+ }
}
- else if(D.drops[name])
- {
- data.tables[name]=D.drops[name];
- register_table(data.tables[name]);
+ current_socket = false_socket;
+ };
+ socket.fs[method] = f;
+ original_on.apply(socket, [method, g]);
+ };
+
+ var data = {
+ region: region,
+ name: server_name,
+ pvp: is_pvp,
+ gameplay: gameplay,
+ info: (instances[socket.first_map] && instances[socket.first_map].info) || {},
+ };
+ socket.first_map = socket.first_in = observer_map;
+ socket.first_x = observer_x;
+ socket.first_y = observer_y + 120;
+ socket.desktop = true;
+ if (socket.request && socket.request._query && socket.request._query.secret) {
+ for (var id in players) {
+ var player = players[id];
+ if (player.secret == socket.request._query.secret) {
+ socket.player = player;
+ data.character = player_to_client(player);
+ data.character.id = data.character.name = player.name;
+ socket.first_map = player.map;
+ socket.first_in = player.in;
+ socket.first_x = player.x;
+ socket.first_y = player.y;
+ if (socket.request._query.desktop) {
+ socket.desktop = true;
+ socket.first_y += 120;
+ } else {
+ socket.desktop = false;
+ }
}
}
- socket.emit('tracker',data)
- });
- socket.on('set_home',function(data){
- var player=players[socket.id]; if(!player) return;
- if(player.p.dt.last_homeset && hsince(player.p.dt.last_homeset)<36) return fail_response("sh_time",{hours:36-hsince(player.p.dt.last_homeset)});
- player.p.dt.last_homeset=new Date();
- player.p.home=region+server_name;
- delete player.s.hopsickness;
- success_response("home_set",{home:player.p.home});
- });
- socket.on('code',function(data){
- var player=players[socket.id]; if(!player) return;
- if(data.run) players[socket.id].code=true;
- else players[socket.id].code=false;
- resend(players[socket.id],"u+cid");
- });
- socket.on('property',function(data){
- var player=players[socket.id]; if(!player) return;
- if(data.typing)
- {
- if(!player.s.typing || player.s.typing.ms<3000) reduce_call_cost();
- player.s.typing={ms:4000};
- resend(player,"u+cid+nc");
}
- else
- {
- var original=player.afk;
- if(player.afk=="bot" || player.afk=="code");
- else if(data.afk===true)
- {
- player.afk=true;
+ data.x = socket.first_x;
+ data.y = socket.first_y;
+ data.map = socket.first_map;
+ data.in = socket.first_in;
+ broadcast_e(true);
+ data.S = E;
+ socket.emit("welcome", data);
+ socket.on("send_updates", function () {
+ if (observers[socket.id]) {
+ send_all_xy(observers[socket.id]);
}
- else if(data.afk===false)
- {
- if(player.afk!==undefined) player.afk=false;
+ if (players[socket.id]) {
+ send_all_xy(players[socket.id]);
}
- if(original!==player.afk)
- {
- reduce_call_cost();
- resend(player,"u+cid+nc");
- }
- }
- });
- socket.on('cruise',function(speed){
- var player=players[socket.id]; if(!player) return;
- player.cruise=parseInt(speed);
- resend(player,"u+cid");
- success_response("cruise",{speed:player.cruise});
- });
- socket.on('test',function(data){
- if(is_sdk) console.log(data.test);
- socket.emit('test',{date:new Date()});
- });
- socket.on('blocker',function(data){
- if(data.type=="pvp")
- {
- if(instances["arena"].allow)
- {
- socket.emit("blocker",{type:"pvp",allow:1});
- }
- else
- {
- socket.emit("blocker",{type:"pvp"});
- }
- }
- });
- socket.on('mail_take_item',function(data){
- var player=players[socket.id]; if(!player) return;
- if(mode.prevent_external) return socket.emit("game_response",{response:"not_in_this_server"});
- if(!player.esize) return socket.emit("game_response","inv_size");
- appengine_call("take_item_from_mail",{owner:player.owner,mid:data.id},function(result){
- var player=players[socket.id];
- if(result.failed) return socket.emit("game_response",{response:"mail_item_already_taken"});
- var item=JSON.parse(result.item);
- add_item(player,item,{announce:false});
- resend(player,"reopen");
- socket.emit("game_response",{response:"mail_item_taken"});
- },function(){
- socket.emit("game_response",{response:"mail_take_item_failed"});
});
- });
- socket.on('mail',function(data){
- var player=players[socket.id]; if(!player) return;
- if(mode.prevent_external) return fail_response("not_in_this_server");
- var item=null,retries=1;
- if(player.gold<48000) return fail_response("gold_not_enough");
- player.gold-=48000;
- if(data.item && player.items[0] && player.items[0].name!="placeholder")
- {
- if(player.items[0].l) return fail_response("item_locked");
- if(player.items[0].b || player.items[0].v) return fail_response("item_blocked");
- if(player.gold<312000) return fail_response("gold_not_enough");
- player.gold-=312000;
- item=JSON.stringify(player.items[0]);
- player.items[0]=player.citems[0]=null;
- retries=3;
- }
- appengine_call("send_mail",{fro:player.name,to:data.to,subject:data.subject||"",message:data.message||"",rid:randomStr(50),retries:retries,item:item},function(result){
- var player=players[socket.id];
- if(result.failed)
- {
- if(player) socket.emit("game_response",{response:"mail_failed",to:data.to,reason:result.reason,cevent:"mail_failed"});
- if(player && item && result.return && player.esize)
- {
- var r=JSON.parse(item);
- add_item(player,r);
- resend(player,"reopen");
- }
- else
- console.log("#M unsent mail, lost item: "+item);
+ socket.on("loaded", function (data) {
+ var observer = (observers[socket.id] = {
+ socket: socket,
+ x: socket.first_x,
+ y: socket.first_y,
+ // vision:[round((data.width/2)/data.scale)+B.ext_vision,round((data.height/2)/data.scale)+B.ext_vision],
+ map: socket.first_map,
+ in: socket.first_in,
+ observer: 1,
+ id: "o" + socket.id,
+ s: {},
+ });
+ if (socket.player) {
+ observer.player = socket.player;
+ }
+ // observer.vision[0]=min(1000,observer.vision[0]); observer.vision[1]=min(700,observer.vision[1]);
+ observer.vision = B.vision;
+ // socket.emit("observing",{map:observer.map,x:observer.x,y:observer.y});
+ resume_instance(instances[observer.in]);
+ instances[observer.in].observers[observer.id] = observer;
+ send_all_xy(observer);
+ });
+ socket.on("o:home", function (data) {
+ var observer = observers[socket.id];
+ if (!observer) {
return;
}
- if(player) socket.emit("game_response",{response:"mail_sent",to:data.to,cevent:"mail_sent"});
- },function(){
- var player=players[socket.id];
- if(player) socket.emit("game_response",{response:"mail_failed",reason:"coms_failure"});
- if(item) console.log("#M unsent mail, lost item: "+item);
+ var player = observer.player;
+ if (!player || player.dc) {
+ return;
+ }
+ transport_observer_to(observer, player.in, player.map, player.x, player.y + ((socket.desktop && 120) || 0));
});
- resend(player,"reopen");
- success_response("mail_sending",{sucess:false,in_progress:true,received:"unknown"});
- });
- socket.on('leave',function(data){
- var player=players[socket.id]; if(!player) return;
- if(!can_walk(player)) return fail_response("transport_failed");
- if(0 && player.s.block || player.targets>5 || !(player.map=="jail" || player.map=="cyberland" || instances[player.in].solo))
- return fail_response("cant_escape");
- transport_player_to(player,B.start_map);
- success_response();
- });
- socket.on('transport',function(data){
- var player=players[socket.id],can_reach=false; if(!player) return; // this was missing, probably caused a production exception - should be added everywhere [04/09/16]
- if(!can_walk(player) || player.map=="jail") return fail_response("transport_failed");
- var new_map=G.maps[data.to],s=data.s||0,the_door=null;
- if(!new_map || !instances[data.to] || !instances[data.to].allow) return fail_response("cant_enter");
- if(0 && player.s.block || player.targets>5) return fail_response("cant_escape");
-
- (G.maps[player.map].doors||[]).forEach(function(door){
- if(!can_reach && door[4]==data.to && s==(door[5]||0) && simple_distance({map:player.map,x:G.maps[player.map].spawns[door[6]][0],y:G.maps[player.map].spawns[door[6]][1]},player)5) return fail_response("cant_escape");
- // if(player.role!="gm" && !(data.place==player.map && player.map=="cgallery"))
- // {
- // if(data.place!="resort" && !G.maps[player.map].ref.transporter || simple_distance(G.maps[player.map].ref.transporter,player)>80) return socket.emit("game_response","transport_cant_reach");
- // if(data.place=="resort" && player.map!="resort") return socket.emit("game_response","transport_cant_reach");
- // }
- server_log(data);
- var name=randomStr(24);
- if(data.place=="resort" && 0)
- {
- var name="resort_"+data.name;
- instance=instances[name]||create_instance(name,"resort_map");
- transport_player_to(player,name);
- }
- else if(data.place=="duelland")
- {
- if(instances[data.name] && instances[data.name].map=="duelland")
- {
- transport_player_to(player,data.name);
- instance_emit(data.name,"game_log",{message:player.name+" is spectating the duel",color:"gray"});
- }
- else return fail_response("cant_enter");
- }
- else if(data.place=="crypt" || data.place=="winter_instance")
- {
- var f="cave",ref=G.maps.cave.spawns[2],item="cryptkey";
- if(data.place=="winter_instance") f="winterland",ref=G.maps.winterland.spawns[5],item="frozenkey";
- if(simple_distance(player,{in:f,map:f,x:ref[0],y:ref[1]})>120)
- return fail_response("transport_cant_reach");
- if(data.name && instances[data.name] && instances[data.name].map==data.place)
- {
- transport_player_to(player,data.name);
- }
- else
- {
- if(!consume_one_by_id(player,item))
- return fail_response("transport_cant_item");
- instance=create_instance(name,data.place);
- transport_player_to(player,name);
- }
- resend(player,"u+cid+reopen");
- }
- else if(data.place=="dungeon0" && player.role=="gm")
- {
- instance=create_instance(name,"dungeon0",{solo:player.id});
- transport_player_to(player,name);
- }
- else if(data.place=="cgallery" && player.role=="gm")
- {
- var point=null;
- if(player.map=="cgallery") point=[player.x,player.y];
- instance=create_instance(name,"cgallery",{solo:player.id});
- transport_player_to(player,name,point);
- var bodies=[],heads=[],hairs=[],wings=[],hats=[];
- for(var s in G.sprites)
- {
- var current=G.sprites[s],matrix=current.matrix;
- if(current.skip || current.rskip) continue;
- if(!in_arr(current.type,["body","head","hair","s_wings","hat"])) continue;
- for(var i=0;i5) return fail_response("cant_escape");
- player.c.town={ms:min(player.c.town&&player.c.town.ms||5000,3000)};
- resend(player,"u+nc");
- success_response({success:false,in_progress:true})
- });
- socket.on('respawn',function(data){
- var player=players[socket.id]; if(!player || !player.rip) return fail_response("invalid");
- if(player.rip_time && ssince(player.rip_time) 5) {
+ return fail_response("invalid");
+ }
+ player.tcx[focus.ctype] = focus.cx[focus.ctype];
+ // player.tcx=target.cx;
+ resend(player, "u+cid");
+ }
+ // server_log(player.name+" target: "+player.target+" focus: "+player.focus);
+ resend(player, "u+nc");
+ success_response({});
+ });
+ socket.on("ureward", function (data) {
+ if (!player || player.user || !data.name || !G.docs.rewards[data.name]) {
+ return;
+ }
+ if (!player.verified || !player.auth_id) {
+ return socket.emit("game_response", "reward_notverified");
+ }
+ if (!player.user.rewards) {
+ player.user.rewards = [];
+ }
+ if (player.user.rewards.includes(data.name)) {
+ return socket.emit("game_response", "reward_already");
+ }
+ player.user.rewards.push(data.name);
+ exchange(player, G.docs.rewards[data.name], { name: "reward_" + data.name });
+ socket.emit("game_response", { response: "reward_received", rewards: player.user.rewards });
+ });
+ socket.on("creward", function (data) {
+ if (!player || !data.name || !G.classes[player.type].rewards[data.name]) {
+ return;
+ }
+ if (!player.verified || !player.auth_id) {
+ return socket.emit("game_response", "reward_notverified");
+ }
+ if (!player.p.rewards) {
+ player.p.rewards = [];
+ }
+ if (player.p.rewards.includes(data.name)) {
+ return socket.emit("game_response", "reward_already");
+ }
+ player.p.rewards.push(data.name);
+ exchange(player, G.classes[player.type].rewards[data.name].reward, { name: "reward_" + data.name });
+ socket.emit("game_response", { response: "reward_received", rewards: player.p.rewards });
+ });
+ socket.on("cx", function (data) {
+ var player = players[socket.id];
+ if (!player) {
+ return;
+ }
+ // if(player.role!="gm") return socket.emit('game_log',"Cosmetics system is out of the test phase for now");
+ // console.log(data);
+ var cx = player.cx;
+ var cxl = all_cx(player);
+ // if(!player.tcx) player.tcx=clone(player.cx);
+ if (data.slot && !data.name) {
+ if (data.slot == "back") {
+ delete cx.tail;
+ } // synced with render_cgallery
+ if (data.slot == "face") {
+ delete cx.makeup;
+ }
+ delete cx[data.slot];
+ } else {
+ if (!T[data.name] || (!cxl[data.name] && player.role != "cx")) {
+ return fail_response("cx_not_found");
+ }
+ if ((T[data.name] == "body" || T[data.name] == "armor" || T[data.name] == "character") && data.slot == "skin") {
+ player.skin = data.name;
+ } else if ((T[data.name] == "body" || T[data.name] == "armor") && data.slot == "upper") {
+ cx.upper = data.name;
+ } else if (cxtype_to_slot[T[data.name]] && cxtype_to_slot[T[data.name]] != "skin") {
+ cx[cxtype_to_slot[T[data.name]]] = data.name;
+ }
+ }
+ prune_cx(player.cx, player.skin);
+ resend(player, "u+cid");
+ success_response();
+ });
+ socket.on("gm", function (data) {
+ var player = players[socket.id];
+ if (!player || player.role != "gm") {
+ return;
+ }
+ var target = players[id_to_id[data.id]];
+ var action = data.action;
+ if (action == "mute") {
+ if (!target) {
+ return socket.emit("game_log", "Player not found: " + data.id);
+ }
+ if (!target.s.mute) {
+ target.s.mute = { ms: 48 * 60 * 60 * 1000 };
+ return socket.emit("game_chat", "Muted " + target.name);
+ } else {
+ target.s.mute = { ms: 0 };
+ return socket.emit("game_chat", "Unmuted " + target.name);
+ }
+ } else if (action == "jail") {
+ if (!target) {
+ return socket.emit("game_log", "Player not found: " + data.id);
+ }
+ transport_player_to(target, "jail");
+ } else if (action == "ban") {
+ appengine_call("ban_user", { name: data.id }, function (result) {
+ socket.emit("game_log", "Ban: " + ((result && result.result) || "No result"));
+ });
+ } else if (action == "invincible") {
+ player.s.invincible = { ms: 24 * 60 * 60 * 1000 };
+ resend(player, "u+cid");
+ } else if (action == "jump") {
+ if (!target) {
+ return socket.emit("game_log", "Player not found: " + data.id);
+ }
+ var spot = safe_xy_nearby(target.map, target.x - 8, target.y - 6);
+ if (spot) {
+ pulled = player;
+ pulled.s.magiport = { ms: 400 };
+ pulled.s.magiport.x = spot.x;
+ pulled.s.magiport.y = spot.y;
+ pulled.s.magiport.f = target.name;
+ pulled.s.magiport.in = target.in;
+ pulled.s.magiport.map = target.map;
+ resend(pulled, "u+cid");
+ } else {
+ return socket.emit("game_log", "No safe spot near: " + data.id);
+ }
+ } else if (action == "mjump") {
+ target = get_monsters(data.monster)[0];
+ if (!target) {
+ return socket.emit("game_log", "Monster not found: " + data.monster);
+ }
+ var spot = safe_xy_nearby(target.map, target.x - 8, target.y - 6);
+ if (spot) {
+ pulled = player;
+ pulled.s.magiport = { ms: 400 };
+ pulled.s.magiport.x = spot.x;
+ pulled.s.magiport.y = spot.y;
+ pulled.s.magiport.f = target.name;
+ pulled.s.magiport.in = target.in;
+ pulled.s.magiport.map = target.map;
+ resend(pulled, "u+cid");
+ } else {
+ return socket.emit("game_log", "No safe spot near: " + data.monster);
+ }
+ } else if (action == "jump_list") {
+ var ids = [];
+ for (var id in players) {
+ ids.push(players[id].name);
+ }
+ socket.emit("gm", { action: "jump_list", ids: ids });
+ } else if (action == "server_info") {
+ var info = [];
+ for (var id in players) {
+ info.push({ name: players[id].name, owner: players[id].owner, ip: get_ip(players[id]) });
+ }
+ //socket.emit("gm",{action:"server_info",info:info});
+ }
+ });
+ socket.on("monsterhunt", function (data) {
+ var player = players[socket.id];
+ if (!player) {
+ return;
+ }
+ if (simple_distance(G.maps.main.ref.monsterhunter, player, true) > B.sell_dist) {
+ return fail_response("distance");
+ }
+ var hunted = [];
+ for (var id in server.s) {
+ if (server.s[id].type == "monsterhunt") {
+ hunted.push(server.s[id].id);
+ }
+ }
+ if (player.s.monsterhunt && player.s.monsterhunt.c) {
+ return fail_response("monsterhunt_already");
+ } else if (player.s.monsterhunt) {
+ delete server.s["monsterhunt_" + player.s.monsterhunt.id];
+ delete player.s.monsterhunt;
+ add_item(player, "monstertoken", { log: true, q: (gameplay == "hardcore" && 100) || 1 });
+ resend(player, "u+cid+reopen");
+ return success_response({ completed: true });
+ }
+ if (player.type == "merchant") {
+ return socket.emit("game_response", "monsterhunt_merchant");
+ }
+ var mmax = -1;
+ var name = "goo";
+ var count = 100;
+ var times = 0;
+ var the_hp = 0;
+ for (var id in instances) {
+ if (instances[id].name != id || !G.maps[id] || G.maps[id].irregular) {
+ continue;
+ }
+ for (var mid in instances[id].monsters) {
+ var monster = instances[id].monsters[mid];
+ if (monster.level > mmax && !in_arr(monster.type, hunted) && !monster.target) {
+ // added the target condition [21/07/23]
+ name = monster.type;
+ mmax = monster.level;
+ the_hp = monster.max_hp / 1000.0;
+ }
+ }
+ }
+ for (var id in G.maps) {
+ if (G.maps[id].irregular || !G.maps[id].monsters) {
+ continue;
+ }
+ G.maps[id].monsters.forEach(function (p) {
+ if (p.type == name) {
+ times += p.count;
+ }
+ });
+ }
+ // console.log(times);
+ count = max(1, min(500, parseInt((20 * 60 * max(1, times)) / the_hp / (G.monsters[name].respawn + 0.25))));
+ if (gameplay == "hardcore") {
+ count = max(1, parseInt(count / 10));
+ }
+ player.s.monsterhunt = { sn: region + " " + server_name, id: name, c: count, ms: 30 * 60 * 1000, dl: true };
+ server.s["monsterhunt_" + name] = { name: player.name, id: name, ms: 20 * 60 * 1000, type: "monsterhunt" };
+ player.hitchhikers.push(["game_response", "monsterhunt_started"]);
+ resend(player, "u+cid");
+ success_response({ started: true });
+ });
+ socket.on("ccreport", function () {
+ socket.emit("ccreport", { calls: socket.calls, climit: limits.calls, total: socket.total_calls });
+ });
+ socket.on("tracker", function (data) {
+ var player = players[socket.id];
+ if (!player) {
+ return;
+ }
+ if (!player.tracker) {
+ return;
+ }
+ var data = {
+ monsters: player.p.stats.monsters,
+ monsters_diff: player.p.stats.monsters_diff,
+ exchanges: player.p.stats.exchanges,
+ maps: D.drops.maps,
+ tables: {},
+ max: player.max_stats,
+ }; // ,computer:false
+ function register_table(table) {
+ if (table) {
+ table.forEach(function (drop) {
+ if (drop[1] == "open" && !data.tables[drop[2]]) {
+ data.tables[drop[2]] = D.drops[drop[2]];
+ register_table(D.drops[drop[2]]);
+ }
+ });
+ }
+ }
+ if (player.computer || 1) {
+ // data.computer=true;
+ data.drops = D.drops.monsters;
+ } else {
+ data.drops = {};
+ for (var name in data.monsters) {
+ if (data.monsters[name] >= 100 && D.drops.monsters[name]) {
+ data.drops[name] = D.drops.monsters[name];
+ }
+ }
+ }
+ if (D.drops.maps.global) {
+ data.global = D.drops.maps.global;
+ register_table(data.global);
+ }
+ if (D.drops.maps.global_static) {
+ data.global_static = D.drops.maps.global_static;
+ register_table(data.global_static);
+ }
+ for (var name in data.drops) {
+ register_table(data.drops[name]);
+ }
+ for (var name in data.maps) {
+ register_table(data.maps[name]);
+ }
+ for (var name in G.items) {
+ if (
+ G.items[name].e &&
+ (player.computer ||
+ 1 ||
+ (player.p.stats.exchanges && player.p.stats.exchanges[name] && player.p.stats.exchanges[name] >= 100))
+ ) {
+ if (G.items[name].upgrade || G.items[name].compound) {
+ for (var i = 0; i < 13; i++) {
+ if (D.drops[name + i]) {
+ data.tables[name + i] = D.drops[name + i];
+ register_table(data.tables[name + i]);
+ }
+ }
+ } else if (D.drops[name]) {
+ data.tables[name] = D.drops[name];
+ register_table(data.tables[name]);
+ }
+ }
+ }
+ socket.emit("tracker", data);
+ });
+ socket.on("set_home", function (data) {
+ var player = players[socket.id];
+ if (!player) {
+ return;
+ }
+ if (player.p.dt.last_homeset && hsince(player.p.dt.last_homeset) < 36) {
+ return fail_response("sh_time", { hours: 36 - hsince(player.p.dt.last_homeset) });
+ }
+ player.p.dt.last_homeset = new Date();
+ player.p.home = region + server_name;
+ delete player.s.hopsickness;
+ success_response("home_set", { home: player.p.home });
+ });
+ socket.on("code", function (data) {
+ var player = players[socket.id];
+ if (!player) {
+ return;
+ }
+ if (data.run) {
+ players[socket.id].code = true;
+ } else {
+ players[socket.id].code = false;
+ }
+ resend(players[socket.id], "u+cid");
+ });
+ socket.on("property", function (data) {
+ var player = players[socket.id];
+ if (!player) {
+ return;
+ }
+ if (data.typing) {
+ if (!player.s.typing || player.s.typing.ms < 3000) {
+ reduce_call_cost();
+ }
+ player.s.typing = { ms: 4000 };
+ resend(player, "u+cid+nc");
+ } else {
+ var original = player.afk;
+ if (player.afk == "bot" || player.afk == "code") {
+ } else if (data.afk === true) {
+ player.afk = true;
+ } else if (data.afk === false) {
+ if (player.afk !== undefined) {
+ player.afk = false;
+ }
+ }
+ if (original !== player.afk) {
+ reduce_call_cost();
+ resend(player, "u+cid+nc");
+ }
+ }
+ });
+ socket.on("cruise", function (speed) {
+ var player = players[socket.id];
+ if (!player) {
+ return;
+ }
+ player.cruise = parseInt(speed);
+ resend(player, "u+cid");
+ success_response("cruise", { speed: player.cruise });
+ });
+ socket.on("test", function (data) {
+ if (is_sdk) {
+ console.log(data.test);
+ }
+ socket.emit("test", { date: new Date() });
+ });
+ socket.on("blocker", function (data) {
+ if (data.type == "pvp") {
+ if (instances["arena"].allow) {
+ socket.emit("blocker", { type: "pvp", allow: 1 });
+ } else {
+ socket.emit("blocker", { type: "pvp" });
+ }
+ }
+ });
+ socket.on("mail_take_item", function (data) {
+ var player = players[socket.id];
+ if (!player) {
+ return;
+ }
+ if (mode.prevent_external) {
+ return socket.emit("game_response", { response: "not_in_this_server" });
+ }
+ if (!player.esize) {
+ return socket.emit("game_response", "inv_size");
+ }
+ appengine_call(
+ "take_item_from_mail",
+ { owner: player.owner, mid: data.id },
+ function (result) {
+ var player = players[socket.id];
+ if (result.failed) {
+ return socket.emit("game_response", { response: "mail_item_already_taken" });
+ }
+ var item = JSON.parse(result.item);
+ add_item(player, item, { announce: false });
+ resend(player, "reopen");
+ socket.emit("game_response", { response: "mail_item_taken" });
+ },
+ function () {
+ socket.emit("game_response", { response: "mail_take_item_failed" });
+ },
+ );
+ });
+ socket.on("mail", function (data) {
+ var player = players[socket.id];
+ if (!player) {
+ return;
+ }
+ if (mode.prevent_external) {
+ return fail_response("not_in_this_server");
+ }
+ var item = null;
+ var retries = 1;
+ if (player.gold < 48000) {
+ return fail_response("gold_not_enough");
+ }
+ player.gold -= 48000;
+ if (data.item && player.items[0] && player.items[0].name != "placeholder") {
+ if (player.items[0].l) {
+ return fail_response("item_locked");
+ }
+ if (player.items[0].b || player.items[0].v) {
+ return fail_response("item_blocked");
+ }
+ if (player.gold < 312000) {
+ return fail_response("gold_not_enough");
+ }
+ player.gold -= 312000;
+ item = JSON.stringify(player.items[0]);
+ player.items[0] = player.citems[0] = null;
+ retries = 3;
+ }
+ appengine_call(
+ "send_mail",
+ {
+ fro: player.name,
+ to: data.to,
+ subject: data.subject || "",
+ message: data.message || "",
+ rid: randomStr(50),
+ retries: retries,
+ item: item,
+ },
+ function (result) {
+ var player = players[socket.id];
+ if (result.failed) {
+ if (player) {
+ socket.emit("game_response", {
+ response: "mail_failed",
+ to: data.to,
+ reason: result.reason,
+ cevent: "mail_failed",
+ });
+ }
+ if (player && item && result.return && player.esize) {
+ var r = JSON.parse(item);
+ add_item(player, r);
+ resend(player, "reopen");
+ } else {
+ console.log("#M unsent mail, lost item: " + item);
+ }
+ return;
+ }
+ if (player) {
+ socket.emit("game_response", { response: "mail_sent", to: data.to, cevent: "mail_sent" });
+ }
+ },
+ function () {
+ var player = players[socket.id];
+ if (player) {
+ socket.emit("game_response", { response: "mail_failed", reason: "coms_failure" });
+ }
+ if (item) {
+ console.log("#M unsent mail, lost item: " + item);
+ }
+ },
+ );
+ resend(player, "reopen");
+ success_response("mail_sending", { sucess: false, in_progress: true, received: "unknown" });
+ });
+ socket.on("leave", function (data) {
+ var player = players[socket.id];
+ if (!player) {
+ return;
+ }
+ if (!can_walk(player)) {
+ return fail_response("transport_failed");
+ }
+ if (
+ (0 && player.s.block) ||
+ player.targets > 5 ||
+ !(player.map == "jail" || player.map == "cyberland" || instances[player.in].solo)
+ ) {
+ return fail_response("cant_escape");
+ }
+ transport_player_to(player, B.start_map);
+ success_response();
+ });
+ socket.on("transport", function (data) {
+ var player = players[socket.id];
+ var can_reach = false;
+ if (!player) {
+ return;
+ } // this was missing, probably caused a production exception - should be added everywhere [04/09/16]
+ if (!can_walk(player) || player.map == "jail") {
+ return fail_response("transport_failed");
+ }
+ var new_map = G.maps[data.to];
+ var s = data.s || 0;
+ var the_door = null;
+ if (!new_map || !instances[data.to] || !instances[data.to].allow) {
+ return fail_response("cant_enter");
+ }
+ if ((0 && player.s.block) || player.targets > 5) {
+ return fail_response("cant_escape");
+ }
+
+ (G.maps[player.map].doors || []).forEach(function (door) {
+ if (
+ !can_reach &&
+ door[4] == data.to &&
+ s == (door[5] || 0) &&
+ simple_distance(
+ { map: player.map, x: G.maps[player.map].spawns[door[6]][0], y: G.maps[player.map].spawns[door[6]][1] },
+ player,
+ ) < B.door_dist
+ ) {
+ can_reach = "door";
+ the_door = door;
+ }
+ });
+ if ((player.map == "woffice" && gameplay == "hardcore") || player.role == "gm") {
+ can_reach = "transport";
+ }
+ if (
+ !can_reach &&
+ G.maps[player.map].ref.transporter &&
+ simple_distance(G.maps[player.map].ref.transporter, player) < B.transporter_dist &&
+ G.npcs.transporter.places[data.to] === s
+ ) {
+ can_reach = "transport";
+ }
+ if (can_reach == "transport" && player.s.dampened) {
+ return fail_response("transport_cant_dampened");
+ }
+ if (!can_reach) {
+ return fail_response("transport_cant_reach");
+ }
+ if (the_door && the_door[7] == "protected") {
+ var protected = false;
+ for (var x in instances[player.in].monsters || {}) {
+ if (instances[player.in].monsters[x].map_def.gatekeeper) {
+ protected = true;
+ }
+ }
+ if (protected) {
+ return fail_response("transport_cant_protection");
+ }
+ }
+ if (
+ the_door &&
+ the_door[7] == "ulocked" &&
+ G.maps[data.to].mount &&
+ player.user &&
+ !player.user.unlocked[data.to]
+ ) {
+ return fail_response("transport_cant_locked");
+ }
+
+ if (instances[data.to].mount && !player.user) {
+ if (player.mounting || player.unmounting) {
+ return fail_response("bank_opi");
+ }
+ add_call_cost(32, undefined, "bank");
+ player.mounting = new Date();
+ player.mount_to = data.to;
+ player.mount_s = s;
+ sync_loop();
+ return success_response({ success: false, in_progress: true });
+ } else if (!instances[data.to].mount && player.user) {
+ // previously handled at transport_player_to
+ if (player.mounting || player.unmounting) {
+ return fail_response("bank_opi");
+ }
+ add_call_cost(16, undefined, "bank");
+ player.unmounting = new Date();
+ player.unmount_to = data.to;
+ player.unmount_s = s;
+ sync_loop();
+ return success_response({ success: false, in_progress: true });
+ } else if (0 && instances[data.to].mount && player.user && data.to != player.map) {
+ // an easy prevention for the bank re-entry nuisance, bank can be re-entered physically but not digitally [03/11/16]
+ // commented out for bank_u / bank_b [06/05/20]
+ return fail_response("transport_failed");
+ } else {
+ decay_s(player, 5200);
+ transport_player_to(player, data.to, s);
+ return success_response();
+ }
+ });
+ socket.on("enter", function (data) {
+ var player = players[socket.id];
+ if (!player) {
+ return;
+ }
+ if (gameplay != "normal") {
+ return fail_response("transport_failed");
+ }
+ if (!can_walk(player) || player.map == "jail") {
+ return fail_response("transport_failed");
+ }
+ if (player.s.block || player.targets > 5) {
+ return fail_response("cant_escape");
+ }
+ // if(player.role!="gm" && !(data.place==player.map && player.map=="cgallery"))
+ // {
+ // if(data.place!="resort" && !G.maps[player.map].ref.transporter || simple_distance(G.maps[player.map].ref.transporter,player)>80) return socket.emit("game_response","transport_cant_reach");
+ // if(data.place=="resort" && player.map!="resort") return socket.emit("game_response","transport_cant_reach");
+ // }
+ server_log(data);
+ var name = randomStr(24);
+ if (data.place == "resort" && 0) {
+ var name = "resort_" + data.name;
+ instance = instances[name] || create_instance(name, "resort_map");
+ transport_player_to(player, name);
+ } else if (data.place == "duelland") {
+ if (instances[data.name] && instances[data.name].map == "duelland") {
+ transport_player_to(player, data.name);
+ instance_emit(data.name, "game_log", { message: player.name + " is spectating the duel", color: "gray" });
+ } else {
+ return fail_response("cant_enter");
+ }
+ } else if (data.place == "crypt" || data.place == "winter_instance") {
+ var f = "cave";
+ var ref = G.maps.cave.spawns[2];
+ var item = "cryptkey";
+ if (data.place == "winter_instance") {
+ f = "winterland";
+ ref = G.maps.winterland.spawns[5];
+ item = "frozenkey";
+ }
+ if (simple_distance(player, { in: f, map: f, x: ref[0], y: ref[1] }) > 120) {
+ return fail_response("transport_cant_reach");
+ }
+ if (data.name && instances[data.name] && instances[data.name].map == data.place) {
+ transport_player_to(player, data.name);
+ } else {
+ if (!consume_one_by_id(player, item)) {
+ return fail_response("transport_cant_item");
+ }
+ instance = create_instance(name, data.place);
+ transport_player_to(player, name);
+ }
+ resend(player, "u+cid+reopen");
+ } else if (data.place == "dungeon0" && player.role == "gm") {
+ instance = create_instance(name, "dungeon0", { solo: player.id });
+ transport_player_to(player, name);
+ } else if (data.place == "cgallery" && player.role == "gm") {
+ var point = null;
+ if (player.map == "cgallery") {
+ point = [player.x, player.y];
+ }
+ instance = create_instance(name, "cgallery", { solo: player.id });
+ transport_player_to(player, name, point);
+ var bodies = [];
+ var heads = [];
+ var hairs = [];
+ var wings = [];
+ var hats = [];
+ for (var s in G.sprites) {
+ var current = G.sprites[s];
+ var matrix = current.matrix;
+ if (current.skip || current.rskip) {
+ continue;
+ }
+ if (!in_arr(current.type, ["body", "head", "hair", "s_wings", "hat"])) {
+ continue;
+ }
+ for (var i = 0; i < matrix.length; i++) {
+ for (var j = 0; j < matrix[i].length; j++) {
+ if (!matrix[i][j]) {
+ continue;
+ }
+ if (current.type == "body") {
+ bodies.push(matrix[i][j]);
+ }
+ if (current.type == "head") {
+ heads.push(matrix[i][j]);
+ }
+ if (current.type == "hair") {
+ hairs.push(matrix[i][j]);
+ }
+ if (current.type == "hat") {
+ hats.push(matrix[i][j]);
+ }
+ if (current.type == "s_wings") {
+ wings.push(matrix[i][j]);
+ }
+ T[matrix[i][j]] = current.type;
+ }
+ }
+ }
+ var xs = [-80, -40, 0, 40, 80];
+ for (var n = 0; n < bodies.length; n++) {
+ var npc = create_npc(
+ {
+ name: bodies[n],
+ level: 1,
+ speed: 12,
+ hp: 1000,
+ skin: bodies[n],
+ cx: {},
+ },
+ {
+ position: [xs[n % xs.length], -parseInt(n / xs.length) * 40],
+ id: bodies[n],
+ },
+ instance,
+ );
+ npc.ctype = "body";
+ npc.cx = { head: heads[n] };
+ npc.id = "body: " + bodies[n];
+ instance.players[NPC_prefix + npc.id] = npc;
+ }
+ for (var n = 0; n < heads.length; n++) {
+ var npc = create_npc(
+ { name: heads[n], level: 1, speed: 12, hp: 1000, skin: bodies[0], cx: {} },
+ { position: [xs[n % xs.length] + 240, -parseInt(n / xs.length) * 40], id: heads[n] },
+ instance,
+ );
+ npc.ctype = "head";
+ npc.cx = { head: heads[n] };
+ npc.id = "head: " + heads[n];
+ instance.players[NPC_prefix + npc.id] = npc;
+ }
+ for (var n = 0; n < hairs.length; n++) {
+ var npc = create_npc(
+ { name: hairs[n], level: 1, speed: 12, hp: 1000, skin: bodies[1], cx: {} },
+ { position: [xs[n % xs.length] + 480, -parseInt(n / xs.length) * 40], id: hairs[n] },
+ instance,
+ );
+ npc.ctype = "hair";
+ npc.cx = { head: heads[0], hair: hairs[n] };
+ npc.id = "hair: " + hairs[n];
+ instance.players[NPC_prefix + npc.id] = npc;
+ }
+ for (var n = 0; n < hats.length; n++) {
+ var npc = create_npc(
+ { name: hats[n], level: 1, speed: 12, hp: 1000, skin: bodies[2], cx: {} },
+ { position: [xs[n % xs.length] + 720, -parseInt(n / xs.length) * 40], id: hats[n] },
+ instance,
+ );
+ npc.ctype = "hat";
+ npc.cx = { head: heads[0], hat: hats[n] };
+ npc.id = "hair: " + hats[n];
+ instance.players[NPC_prefix + npc.id] = npc;
+ }
+ } else {
+ return fail_response("transport_cant_reach");
+ }
+ success_response();
+ });
+ socket.on("town", function (data) {
+ var player = players[socket.id];
+ if (!player) {
+ return;
+ }
+ // if(player.last.town && mssince(player.last.town)<1200) return; // bad ui experience [Unknown] - got reported and disabled [25/03/22]
+ if (!can_walk(player) || player.map == "jail") {
+ return fail_response("transport_failed");
+ }
+ if ((0 && player.s.block) || player.targets > 5) {
+ return fail_response("cant_escape");
+ }
+ player.c.town = { ms: min((player.c.town && player.c.town.ms) || 5000, 3000) };
+ resend(player, "u+nc");
+ success_response({ success: false, in_progress: true });
+ });
+ socket.on("respawn", function (data) {
+ var player = players[socket.id];
+ if (!player || !player.rip) {
+ return fail_response("invalid");
+ }
+ if (player.rip_time && ssince(player.rip_time) < B.rip_time) {
+ return fail_response("cant_respawn");
+ }
+
+ delete player.s.block;
+ player.hp = player.max_hp;
+ player.mp = round(player.max_mp / 2);
+ player.rip = false;
+ if (gameplay == "hardcore") {
+ reset_player(player, 1);
+ }
+
+ if (data && data.safe) {
+ // gameplay=="hardcore" &&
+ transport_player_to(player, "woffice", 0, 1);
+ } else {
+ var place = G.maps[player.map].on_death || G.maps[B.start_map].on_death || ["main", 0];
+ transport_player_to(player, place[0], place[1], 1);
+ }
+ if (player.party) {
+ send_party_update(player.party);
+ }
+ invincible_logic(player);
+ resend(player, "u+cid");
+ success_response("data", { place: "respawn", cevent: "respawn" });
+ });
+ socket.on("random_look", function (data) {
+ return socket.emit("game_log", "socket.emit('enter',{place:'cgallery'})");
+ var player = players[socket.id];
+ if (!player) {
+ return;
+ }
+ var bodies = [];
+ var heads = [];
+ var hairs = [];
+ var wings = [];
+ var hats = [];
+ if (player.rlooks == 25 && !is_sdk && player.role != "gm") {
+ return;
+ }
+ if (player.role == "gm") {
+ reduce_call_cost(40);
+ }
+ player.rlooks = (player.rlooks || 0) + 1;
+ for (var s in G.sprites) {
+ var current = G.sprites[s];
+ var matrix = current.matrix;
+ if (current.skip || current.rskip) {
+ continue;
+ }
+ if (!in_arr(current.type, ["body", "head", "hair", "s_wings", "hat"])) {
+ continue;
+ }
+ for (var i = 0; i < matrix.length; i++) {
+ for (var j = 0; j < matrix[i].length; j++) {
+ if (!matrix[i][j]) {
+ continue;
+ }
+ if (current.type == "body") {
+ bodies.push(matrix[i][j]);
+ }
+ if (current.type == "head") {
+ heads.push(matrix[i][j]);
+ }
+ if (current.type == "hair") {
+ hairs.push(matrix[i][j]);
+ }
+ if (current.type == "hat") {
+ hats.push(matrix[i][j]);
+ }
+ if (current.type == "s_wings") {
+ wings.push(matrix[i][j]);
+ }
+ }
+ }
+ }
+ var head = "head";
+ if (Math.random() < 0.1) {
+ head = random_one(heads);
+ }
+ player.tskin = random_one(bodies);
+ player.tcx = [head, random_one(hairs)];
+ if (Math.random() < 0.08) {
+ player.tcx.push(random_one(wings));
+ }
+ if (Math.random() < 0.4) {
+ player.tcx.push(random_one(hats));
+ }
+ resend(player, "u+cid");
+ });
+ socket.on("unlock", function (data) {
+ return; // [27/06/18]
+ var player = players[socket.id];
+ if (!player) {
+ return;
+ }
+ if (gameplay == "normal") {
+ return;
+ } // ? [27/06/18]
+ if (data.name == "code") {
+ var item = player.items[data.num || 0];
+ if (!item || item.name != "computer" || item.charges === 0 || item.charges < 0 || player.unlocking_code) {
return;
}
- socket.emit("game_log","CODE slots increased to 100!");
- resend(player,"reopen");
+ if (!item.charges) {
+ item.charges = 2;
+ }
+ item.charges--;
+ player.citems[data.num || 0] = player.items[data.num || 0]; // explicitly linked to the actual item
+ player.unlocking_code = true;
+ appengine_call(
+ "user_operation",
+ { auth: player.auth, operation: "code_unlock", suffix: "/code_unlock/" + player.owner, retries: 4 },
+ function (result) {
+ server_log("user_operation_code: " + JSON.stringify(result), 1);
+ if (result.failed) {
+ if (result.reason == "already") {
+ socket.emit(
+ "game_log",
+ "Your CODE slots are already unlocked. You can lend your Ancient Computer to a friend in need, that's why there are 2 charges :]",
+ );
+ item.charges++;
+ } else {
+ socket.emit("game_log", "Unlock Failed. Email hello@adventure.land with a screenshot.");
+ }
+ return;
+ }
+ socket.emit("game_log", "CODE slots increased to 100!");
+ resend(player, "reopen");
+ },
+ );
+ }
+ });
+ socket.on("dismantle", function (data) {
+ var player = players[socket.id];
+ var check = true;
+ var items = [];
+ if (!player || player.user) {
+ return fail_response("cant_in_bank");
+ }
+ if (!player.computer && simple_distance(G.maps.main.ref.craftsman, player) > B.sell_dist) {
+ return fail_response("distance");
+ }
+ // if(player.esize<=0) return socket.emit("game_response","inventory_full");
+ var item = player.items[data.num];
+ if (item && item.level && G.items[item.name].compound) {
+ var cost = min(50000000, calculate_item_value(item) * 10);
+ if (player.gold < cost) {
+ return fail_response("gold_not_enough");
+ }
+ if (player.esize < 2) {
+ return fail_response("inv_size");
+ }
+ if (G.items[item.name].type == "booster") {
+ return fail_response("dismantle_cant");
+ }
+ player.gold -= cost;
+ consume_one(player, data.num);
+ add_item(
+ player,
+ { name: item.name, level: item.level - 1, grace: parseInt((item.grace || 0) / 3) },
+ { announce: false },
+ );
+ add_item(
+ player,
+ { name: item.name, level: item.level - 1, grace: parseInt((item.grace || 0) / 3) },
+ { announce: false },
+ );
+ add_item(
+ player,
+ { name: item.name, level: item.level - 1, grace: parseInt((item.grace || 0) / 3) },
+ { announce: false },
+ );
+ resend(player, "reopen+nc+inv");
+ return success_response("dismantle", { name: item.name, level: item.level, cost: cost, cevent: true });
+ }
+ if (!item || !G.dismantle[item.name]) {
+ return fail_response("dismantle_cant");
+ }
+ if (item.l) {
+ return fail_response("item_locked");
+ }
+ if (item.b) {
+ return fail_response("item_blocked");
+ }
+ if (player.gold < G.dismantle[item.name].cost) {
+ return fail_response("gold_not_enough");
+ }
+ if (
+ !can_add_items(player, list_to_pseudo_items(G.dismantle[item.name].items), {
+ space: ((item.q || 1) == 1 && 1) || 0,
+ })
+ ) {
+ return fail_response("inv_size");
+ }
+ player.gold -= G.dismantle[item.name].cost;
+ consume_one(player, data.num);
+ G.dismantle[item.name].items.forEach(function (e) {
+ if (e[0] < 1 && Math.random() > e[0]) {
+ return;
+ }
+ add_item(player, e[1], { q: max(1, e[0]), p: item.p && !G.titles[item.p].misc && item.p });
});
- }
- });
- socket.on('dismantle',function(data){
- var player=players[socket.id],check=true,items=[];
- if(!player || player.user) return fail_response("cant_in_bank");
- if(!player.computer && simple_distance(G.maps.main.ref.craftsman,player)>B.sell_dist) return fail_response("distance");
- // if(player.esize<=0) return socket.emit("game_response","inventory_full");
- var item=player.items[data.num];
- if(item && item.level && G.items[item.name].compound)
- {
- var cost=min(50000000,calculate_item_value(item)*10);
- if(player.golde[0]) return;
- add_item(player,e[1],{q:max(1,e[0]),p:item.p&&!G.titles[item.p].misc&&item.p});
+ resend(player, "reopen+nc+inv");
+ success_response("dismantle", { name: item.name, cevent: true });
});
- resend(player,"reopen+nc+inv");
- success_response("dismantle",{name:item.name,cevent:true});
- });
- socket.on('craft',function(data){
- var player=players[socket.id],check=true,items=[],quantity={},place={},space=false,p={},locked=false;
- if(!player || player.user) return fail_response("cant_in_bank");
- data.items.forEach(function(x){
- if(!player.items[x[1]]) check=false;
- else if(player.items[x[1]].l || player.items[x[1]].b) check=false,locked=true;
- else
- {
- var name=player.items[x[1]].name;
- if(player.items[x[1]].level) name+="+"+player.items[x[1]].level;
- items.push(name);
- quantity[player.items[x[1]].name]=(player.items[x[1]].q||1); // (quantity[player.items[x[1]].name]||0)+ removed this part, seems like a bad initial addition [17/06/18]
- place[player.items[x[1]].name]=x[1];
- if(player.items[x[1]].p && !G.titles[player.items[x[1]].p].misc) p[player.items[x[1]].p]=player.items[x[1]].p;
+ socket.on("craft", function (data) {
+ var player = players[socket.id];
+ var check = true;
+ var items = [];
+ var quantity = {};
+ var place = {};
+ var space = false;
+ var p = {};
+ var locked = false;
+ if (!player || player.user) {
+ return fail_response("cant_in_bank");
}
+ data.items.forEach(function (x) {
+ if (!player.items[x[1]]) {
+ check = false;
+ } else if (player.items[x[1]].l || player.items[x[1]].b) {
+ check = false;
+ locked = true;
+ } else {
+ var name = player.items[x[1]].name;
+ if (player.items[x[1]].level) {
+ name += "+" + player.items[x[1]].level;
+ }
+ items.push(name);
+ quantity[player.items[x[1]].name] = player.items[x[1]].q || 1; // (quantity[player.items[x[1]].name]||0)+ removed this part, seems like a bad initial addition [17/06/18]
+ place[player.items[x[1]].name] = x[1];
+ if (player.items[x[1]].p && !G.titles[player.items[x[1]].p].misc) {
+ p[player.items[x[1]].p] = player.items[x[1]].p;
+ }
+ }
+ });
+ if (locked) {
+ return fail_response("item_locked");
+ }
+ if (!check) {
+ return fail_response("no_item");
+ }
+ //if(items.length<2) return socket.emit("game_response","craft_atleast2");
+ items.sort();
+ var key = items.join(",");
+ // console.log(key);
+ if (!D.craftmap[key]) {
+ return fail_response("craft_cant");
+ }
+ var name = D.craftmap[key];
+ var enough = true;
+ if (
+ !player.computer &&
+ !G.craft[name].quest &&
+ simple_distance(get_npc_coords("craftsman"), player) > B.sell_dist
+ ) {
+ return fail_response("distance");
+ }
+ if (
+ !player.computer &&
+ G.craft[name].quest &&
+ simple_distance(get_npc_coords(G.craft[name].quest), player) > B.sell_dist
+ ) {
+ return fail_response("distance");
+ }
+ if (player.gold < G.craft[name].cost) {
+ return fail_response("gold_not_enough");
+ }
+ G.craft[name].items.forEach(function (i) {
+ if (quantity[i[1]] < i[0]) {
+ enough = false;
+ }
+ if (quantity[i[1]] == i[0]) {
+ space = true;
+ }
+ });
+ if (!space && !can_add_item(player, create_new_item(name))) {
+ return fail_response("inventory_full");
+ }
+ if (!enough) {
+ return fail_response("craft_cant_quantity");
+ }
+ player.gold -= G.craft[name].cost;
+ G.craft[name].items.forEach(function (x) {
+ consume(player, place[x[1]], x[0]);
+ });
+ var i = add_item(player, name, { r: 1, p: Object.keys(p).length && random_one(p) });
+ resend(player, "reopen+nc+inv");
+ success_response("craft", { num: i, name: name, cevent: true });
});
- if(locked) return fail_response("item_locked")
- if(!check) return fail_response("no_item");
- //if(items.length<2) return socket.emit("game_response","craft_atleast2");
- items.sort();
- var key=items.join(",");
- // console.log(key);
- if(!D.craftmap[key]) return fail_response("craft_cant");
- var name=D.craftmap[key],enough=true;
- if(!player.computer && !G.craft[name].quest && simple_distance(get_npc_coords('craftsman'),player)>B.sell_dist) return fail_response("distance");
- if(!player.computer && G.craft[name].quest && simple_distance(get_npc_coords(G.craft[name].quest),player)>B.sell_dist) return fail_response("distance");
- if(player.gold B.sell_dist) {
+ return fail_response("distance");
+ }
+ if (!player.computer && def.quest && simple_distance(G.quests[def.quest], player) > B.sell_dist) {
+ return fail_response("distance");
+ }
+ if (player.esize <= 0 && !((item.q || 1) == 1)) {
+ return fail_response("inventory_full");
+ }
+ if (def.e > 1 && item.q < def.e) {
+ return fail_response("exchange_notenough");
+ }
+ player.p.stats.exchanges[item.name + suffix] = (player.p.stats.exchanges[item.name + suffix] || 0) + 1;
+ consume(player, data.item_num, def.e);
+ var num = add_item(player, "placeholder");
+ var ms = 3000 + parseInt(Math.random() * 3000);
+ if (gameplay == "hardcore") {
+ ms = 400;
+ }
+ player.q.exchange = { ms: ms, len: ms, name: item.name, id: item.name + suffix, q: def.e, num: num };
+ if (suffix) {
+ player.q.exchange.s = suffix;
+ }
+ if (item.v) {
+ player.q.exchange.v = item.v;
+ }
+ if (def.quest) {
+ player.q.exchange.qs = def.quest;
+ }
+ resend(player, "reopen+nc+inv");
+ success_response({ success: false, in_progress: true, num: num });
});
- if(!space && !can_add_item(player,create_new_item(name))) return fail_response("inventory_full");
- if(!enough) return fail_response("craft_cant_quantity");
- player.gold-=G.craft[name].cost;
- G.craft[name].items.forEach(function(x){
- consume(player,place[x[1]],x[0]);
- });
- var i=add_item(player,name,{r:1,p:Object.keys(p).length&&random_one(p)});
- resend(player,"reopen+nc+inv");
- success_response("craft",{num:i,name:name,cevent:true})
- });
- socket.on('exchange',function(data){
- var player=players[socket.id],item=player.items[data.item_num],def=G.items[item&&item.name],suffix="";
- if(player.q.exchange) return fail_response("exchange_existing");
- if(def && (def.compound||def.upgrade)) suffix=item.level||0;
- if(!player || player.user) return fail_response("cant_in_bank");
- G.maps.main.exchange.name=player.name;
- if(!def || !def.e || item.q!=data.q || !D.drops[item.name+suffix]) return fail_response("invalid");
- if(item.l) return fail_response("item_locked");
- if(!player.computer && !def.quest && simple_distance(G.maps.main.exchange,player)>B.sell_dist) return fail_response("distance");
- if(!player.computer && def.quest && simple_distance(G.quests[def.quest],player)>B.sell_dist) return fail_response("distance");
- if(player.esize<=0 && !((item.q||1)==1)) return fail_response("inventory_full");
- if(def.e>1 && item.qB.sell_dist) return fail_response("distance");
- if(item.q B.sell_dist) {
+ return fail_response("distance");
+ }
+ if (item.q < G.tokens[item.name][data.name]) {
+ return fail_response("exchange_notenough");
+ }
- if(G.tokens[item.name][data.name]<1)
- {
- var q=parseInt(1/G.tokens[item.name][data.name]);
- if(item.q!=1 && !can_add_item(player,{name:data.name,q:q})) return fail_response("inventory_full");
- consume(player,data.num,1);
- num=add_item(player,data.name,{q:q,announce:false,r:true});
- }
- else
- {
- var name=data.name,idata=undefined;
- if(name.search("-")!=-1) { idata=name.split("-")[1]; name=name.split("-")[0]; }
- var new_item=create_new_item(name);
- if(idata) new_item.data=idata;
- if(item.q!=G.tokens[item.name][data.name] && !can_add_item(player,new_item)) return fail_response("inventory_full");
- consume(player,data.num,G.tokens[item.name][data.name]);
- num=add_item(player,new_item,{announce:false,r:true});
- }
-
- xy_emit(npc,"upgrade",{type:item.name+"s",success:1});
- resend(player,"reopen+nc+inv");
- success_response({num:num,cevent:true});
- });
- socket.on('locksmith',function(data){
- var player=players[socket.id],item=player.items[data.item_num],def=G.items[item&&item.name];
- if(!player || player.user) return fail_response("cant_in_bank");
- if(!player.computer && simple_distance(G.maps.desertland.ref.locksmith,player)>B.sell_dist) return fail_response("distance");
- var item=player.items[data.num];
- if(!item) return fail_response("no_item");
- var def=G.items[item.name];
- if(in_arr(def.type,["uscroll","cscroll","pscroll","offering","tome"])) return fail_response("locksmith_cant");
- if(data.operation=="unlock")
- {
- if(!item.l) { resend(player,"reopen+nc"); return fail_response("locksmith_aunlocked","locksmith","already_unlocked"); }
- if(item.l=="s")
- {
- if(player.gold<250000) return fail_response("gold_not_enough");
- player.gold-=250000;
- item.ld=JSON.stringify(future_s(2*24*60*60));
- item.l="u";
- socket.emit("game_response","locksmith_unsealed");
+ if (G.tokens[item.name][data.name] < 1) {
+ var q = parseInt(1 / G.tokens[item.name][data.name]);
+ if (item.q != 1 && !can_add_item(player, { name: data.name, q: q })) {
+ return fail_response("inventory_full");
+ }
+ consume(player, data.num, 1);
+ num = add_item(player, data.name, { q: q, announce: false, r: true });
+ } else {
+ var name = data.name;
+ var idata = undefined;
+ if (name.search("-") != -1) {
+ idata = name.split("-")[1];
+ name = name.split("-")[0];
+ }
+ var new_item = create_new_item(name);
+ if (idata) {
+ new_item.data = idata;
+ }
+ if (item.q != G.tokens[item.name][data.name] && !can_add_item(player, new_item)) {
+ return fail_response("inventory_full");
+ }
+ consume(player, data.num, G.tokens[item.name][data.name]);
+ num = add_item(player, new_item, { announce: false, r: true });
}
- else if(item.l=="u")
- {
- var date=new Date(JSON.parse(item.ld));
- if(date B.sell_dist) {
+ return fail_response("distance");
+ }
+ var item = player.items[data.num];
+ if (!item) {
+ return fail_response("no_item");
+ }
+ var def = G.items[item.name];
+ if (in_arr(def.type, ["uscroll", "cscroll", "pscroll", "offering", "tome"])) {
+ return fail_response("locksmith_cant");
+ }
+ if (data.operation == "unlock") {
+ if (!item.l) {
+ resend(player, "reopen+nc");
+ return fail_response("locksmith_aunlocked", "locksmith", "already_unlocked");
+ }
+ if (item.l == "s") {
+ if (player.gold < 250000) {
+ return fail_response("gold_not_enough");
+ }
+ player.gold -= 250000;
+ item.ld = JSON.stringify(future_s(2 * 24 * 60 * 60));
+ item.l = "u";
+ socket.emit("game_response", "locksmith_unsealed");
+ } else if (item.l == "u") {
+ var date = new Date(JSON.parse(item.ld));
+ if (date < new Date()) {
+ delete item.l;
+ socket.emit("game_response", "locksmith_unseal_complete");
+ } else {
+ resend(player, "reopen+nc");
+ return success_response("locksmith_unsealing", { hours: -hsince(date), success: false, in_progress: true });
+ }
+ } else {
+ if (player.gold < 250000) {
+ return fail_response("gold_not_enough");
+ }
+ player.gold -= 250000;
delete item.l;
- socket.emit("game_response","locksmith_unseal_complete");
+ socket.emit("game_response", "locksmith_unlocked");
}
- else
- {
- resend(player,"reopen+nc");
- return success_response("locksmith_unsealing",{hours:-hsince(date),success:false,in_progress:true});
+ } else if (data.operation == "lock") {
+ if (item.l) {
+ resend(player, "reopen+nc");
+ return fail_response("locksmith_alocked", "locksmith", "already_locked");
}
+ if (player.gold < 250000) {
+ return fail_response("gold_not_enough");
+ }
+ player.gold -= 250000;
+ item.l = "l";
+ socket.emit("game_response", "locksmith_locked");
+ } else if (data.operation == "seal") {
+ if (player.gold < 250000) {
+ return fail_response("gold_not_enough");
+ }
+ player.gold -= 250000;
+ item.l = "s";
+ socket.emit("game_response", "locksmith_sealed");
}
- else
- {
- if(player.gold<250000) return fail_response("gold_not_enough");
- player.gold-=250000;
- delete item.l;
- socket.emit("game_response","locksmith_unlocked");
- }
- }
- else if(data.operation=="lock")
- {
- if(item.l) { resend(player,"reopen+nc"); return fail_response("locksmith_alocked","locksmith","already_locked"); }
- if(player.gold<250000) return fail_response("gold_not_enough");
- player.gold-=250000;
- item.l="l";
- socket.emit("game_response","locksmith_locked");
- }
- else if(data.operation=="seal")
- {
- if(player.gold<250000) return fail_response("gold_not_enough");
- player.gold-=250000;
- item.l="s";
- socket.emit("game_response","locksmith_sealed");
- }
- player.citems[data.num]=cache_item(player.items[data.num]);
- resend(player,"reopen+nc");
- success_response();
- });
- socket.on('compound',function(data){
- try{
- var player=players[socket.id],item0=player.items[data.items[0]],item1=player.items[data.items[1]],item2=player.items[data.items[2]],scroll=player.items[data.scroll_num],result,ex="";
- if(!player || player.user) return fail_response("cant_in_bank");
- G.maps.main.compound.name=player.name;
- if(player.q.compound) return fail_response("compound_in_progress","compound","in_progress");
- var offering=player.items[data.offering_num];
- if(offering && G.items[offering.name].type!="offering") return socket.emit("game_response","compound_invalid_offering");
- if(!item0 || (item0.level||0)!=data.clevel) return fail_response("no_item");
- if(!player.computer && simple_distance(G.maps.main.compound,player)>B.sell_dist) return socket.emit("game_response",{response:"distance",place:"compound",failed:true});
- var def=G.items[item0.name],scroll_def=G.items[scroll.name],offering_def=offering&&G.items[offering.name],grade=calculate_item_grade(def,item0);
- if(grade==4) return socket.emit("game_response",{response:"max_level",level:item.level,place:"compound",failed:true});
- if(!(item0.name == item1.name && item1.name==item2.name && (item0.level||0)==(item1.level||0) && (item1.level||0)==(item2.level||0) )) return socket.emit("game_response","compound_mismatch");
- if(!def.compound) return socket.emit("game_response","compound_cant");
- if(scroll_def.type!="cscroll" || grade>scroll_def.grade) return socket.emit("game_response","compound_incompatible_scroll");
- if(data.items[0]==data.items[1] || data.items[1]==data.items[2] || data.items[0]==data.items[2]) return socket.emit("game_response",{response:"misc_fail",place:"compound",failed:true});
- if(item0.l || item1.l || item2.l) return socket.emit("game_response",{response:"item_locked",place:"compound",failed:true});
-
- if(!data.calculate) consume_one(player,data.scroll_num);
-
- var new_level=(item0.level||0)+1,probability=1,oprobability=1,result=0,proc=0,grace=0,igrade=def.igrade,high=false,grace_bonus=0;
- if(item0.level>=3) igrade=calculate_item_grade(def,{name:item0.name,level:item0.level-2});
-
- delete player.p.c_item; delete player.p.c_itemx; delete player.p.c_roll;
-
- oprobability=probability=D.compounds[igrade][new_level];
- result=Math.random();
- server_log(result+" < "+probability);
-
- if(scroll_def.grade > grade)
- {
- probability=probability*1.1+0.001;
- server_log("higher grade scroll "+result+" < "+probability);
- if(!data.calculate) grace_bonus+=0.4;
- high=scroll_def.grade-grade;
- }
-
- if(offering)
- {
- var increase=0.5;
- if(!data.calculate) consume_one(player,data.offering_num);
- grace=0.027*((item0.grace||0)+(item1.grace||0)+(item2.grace||0)+0.5+player.p.ograce);
-
- if(offering_def.grade>grade+1)
- probability=probability*1.64+grace*2,high=true,increase=3;
- else if(offering_def.grade>grade)
- probability=probability*1.48+grace,high=true,increase=1;
- else if(offering_def.grade==grade)
- probability=probability*1.36+min(30*0.027,grace);
- else if(offering_def.grade==grade-1)
- probability=probability*1.15+min(25*0.019,grace)/max(item0.level-2,1),increase=0.2;
- else
- probability=probability*1.08+min(15*0.015,grace)/max(item0.level-1,1),increase=0.1;
-
- if(!data.calculate) item0.grace=(item0.grace||0)+(item1.grace||0)+(item2.grace||0),grace_bonus+=increase;
- server_log("offering "+result+" < "+probability);
- }
- else
- {
- grace=0.007*((item0.grace||0)+(item1.grace||0)+(item2.grace||0)+player.p.ograce);
- probability=probability+min(25*0.007,grace)/max(item0.level-1,1);
- if(!data.calculate) item0.grace=max(max((item0.grace||0),(item1.grace||0)),(item2.grace||0));
- }
-
- if(!data.calculate) item0.grace=item0.grace/6.4+grace_bonus;
-
- if(def.type=="booster") probability=0.9999999999999,proc=offering&&0.12;
- else probability=min(probability,min(oprobability*(3+(high&&high*0.6||0)),oprobability+0.2+(high&&high*0.05||0)));
-
- if(gameplay=="test") result=0;
-
- server_log(result+" < "+probability+" grace: "+grace);
-
- if(data.calculate) return success_response("compound_chance",{calculate:true,chance:probability,item:cache_item(item0),scroll:scroll.name,offering:offering&&offering.name||undefined,grace:(item0.grace||0)+(item1.grace||0)+(item2.grace||0)});
-
- player.p.c_roll=result;
- var len=10000;
- if(gameplay=="hardcore") len=1200;
- if(player.s.massproduction) { len/=2; delete player.s.massproduction; ex="+u+cid"; }
- if(player.s.massproductionpp) { len/=10; delete player.s.massproductionpp; ex="+u+cid"; }
- player.q.compound={ms:len,len:len,num:data.items[0],nums:[]};
- player.items[data.items[0]]={"name":"placeholder",p:{chance:probability,name:item0.name,level:item0.level,scroll:scroll.name,offering:offering&&offering.name,nums:[]}};
- player.items[data.items[1]]=null;
- player.items[data.items[2]]=null;
-
- if(result<=probability)
- {
- if(offering) player.p.ograce=0;
- else player.p.ograce*=1-new_level*0.02;
- item0.level=new_level;
- if((item0.p||item1.p||item2.p)!="legacy") item0.p=(item0.p||item1.p||item2.p);
- else { delete item0.p; }
- player.p.c_item=item0;
- if(item0.oo!=player.name) item0.o=player.name;
- player.esize+=2;
- if(parseInt(result*10000)==parseInt(probability*10000)) // && grade>=1
- add_achievement(player,"lucky"),add_item_property(item0,"lucky");
- if(item1.v||item2.v) item0.v=item1.v||item2.v;
- if(item0.name=="ctristone" && item0.level==1 && Math.random()<0.012) item0.name="cdarktristone";
- if(def.type=="booster")
- {
- var activate=false; item0.extra=0;
- while(offering && proc && Math.random() B.sell_dist) {
+ return socket.emit("game_response", { response: "distance", place: "compound", failed: true });
+ }
+ var def = G.items[item0.name];
+ var scroll_def = G.items[scroll.name];
+ var offering_def = offering && G.items[offering.name];
+ var grade = calculate_item_grade(def, item0);
+ if (grade == 4) {
+ return socket.emit("game_response", {
+ response: "max_level",
+ level: item.level,
+ place: "compound",
+ failed: true,
});
- if(activate) item0.expires=future_s(seconds/3);
}
- }
- else
- {
- if(offering) player.p.ograce+=0.4;
- player.esize+=2;
- player.p.c_item=null;
- player.p.c_itemx=item0;
- }
+ if (
+ !(
+ item0.name == item1.name &&
+ item1.name == item2.name &&
+ (item0.level || 0) == (item1.level || 0) &&
+ (item1.level || 0) == (item2.level || 0)
+ )
+ ) {
+ return socket.emit("game_response", "compound_mismatch");
+ }
+ if (!def.compound) {
+ return socket.emit("game_response", "compound_cant");
+ }
+ if (scroll_def.type != "cscroll" || grade > scroll_def.grade) {
+ return socket.emit("game_response", "compound_incompatible_scroll");
+ }
+ if (data.items[0] == data.items[1] || data.items[1] == data.items[2] || data.items[0] == data.items[2]) {
+ return socket.emit("game_response", { response: "misc_fail", place: "compound", failed: true });
+ }
+ if (item0.l || item1.l || item2.l) {
+ return socket.emit("game_response", { response: "item_locked", place: "compound", failed: true });
+ }
- player.citems[data.items[0]]=cache_item(player.items[data.items[0]]);
- player.citems[data.items[1]]=cache_item(player.items[data.items[1]]);
- player.citems[data.items[2]]=cache_item(player.items[data.items[2]]);
-
- resend(player,"reopen+nc+inv"+ex);
+ if (!data.calculate) {
+ consume_one(player, data.scroll_num);
+ }
- }catch(e){
- server_log('compound_e '+e);
- return socket.emit("game_response",{response:"exception",place:"compound",failed:true});
- }
- });
- socket.on('upgrade',function(data){
- try{
- var player=players[socket.id],item=player.items[data.item_num],scroll=player.items[data.scroll_num],offering=player.items[data.offering_num],result,ex="";
- if(!player || player.user) return fail_response("cant_in_bank");
- if(player.q.upgrade) return socket.emit("game_response","upgrade_in_progress");
- G.maps.main.upgrade.name=player.name;
- if(!player.computer && simple_distance(G.maps.main.upgrade,player)>B.sell_dist) return socket.emit("game_response",{response:"distance",place:"upgrade",failed:true});
- if(!item) return socket.emit("game_response","upgrade_no_item");
- if(offering && !(G.items[offering.name] && G.items[offering.name].type=="offering" || G.items[offering.name] && G.items[offering.name].offering!==undefined && !(item.level>0))) return socket.emit("game_response","upgrade_invalid_offering");
- if(!scroll && !offering) return socket.emit("game_response","upgrade_no_scroll");
- if((item.level||0)!=data.clevel) return socket.emit("game_response","upgrade_mismatch");
- var item_def=G.items[item.name],scroll_def=scroll&&G.items[scroll.name],offering_def=offering&&G.items[offering.name],grade=calculate_item_grade(item_def,item);
- if(!item_def.upgrade) return socket.emit("game_response","upgrade_cant");
- if(scroll && (!in_arr(scroll_def.type,["uscroll","pscroll"]) || (scroll_def.type=="uscroll" && !item_def.upgrade) || (scroll_def.type=="pscroll" && !item_def.stat) || grade>scroll_def.grade))
- {
- if(grade==4 && scroll_def.type=="uscroll") return socket.emit("game_response",{response:"max_level",level:item.level,place:"upgrade",failed:true});
- return socket.emit("game_response","upgrade_incompatible_scroll");
- }
+ var new_level = (item0.level || 0) + 1;
+ var probability = 1;
+ var oprobability = 1;
+ var result = 0;
+ var proc = 0;
+ var grace = 0;
+ var igrade = def.igrade;
+ var high = false;
+ var grace_bonus = 0;
+ if (item0.level >= 3) {
+ igrade = calculate_item_grade(def, { name: item0.name, level: item0.level - 2 });
+ }
- var new_level=(item.level||0)+1,probability=1,oprobability=1,grace=0,high=false;
- var ograde=calculate_item_grade(item_def,{name:item.name,level:0}),tmult=1;
- if(ograde==1) tmult=1.5; else if(ograde==2) tmult=2;
+ delete player.p.c_item;
+ delete player.p.c_itemx;
+ delete player.p.c_roll;
- delete player.p.u_item; delete player.p.u_type; delete player.p.u_itemx; delete player.p.u_roll; delete player.p.u_fail; delete player.p.u_level;
-
- player.p.u_level=(item.level||0);
-
- if(!scroll)
- {
- if(G.items[offering.name] && G.items[offering.name].offering!==undefined)
- {
- var chance=0.16,ms=2000;
- if(G.items[offering.name].offering>ograde || G.items[offering.name].offering==2 && calculate_item_value(item)<=20000000) chance=0.32;
- chance*=[2.8,1.6,1][ograde];
- if(G.items[offering.name].offering grade) {
+ probability = probability * 1.1 + 0.001;
+ server_log("higher grade scroll " + result + " < " + probability);
+ if (!data.calculate) {
+ grace_bonus += 0.4;
}
- else
- {
- player.p.u_item=item;
- player.p.u_fail=true;
+ high = scroll_def.grade - grade;
+ }
+
+ if (offering) {
+ var increase = 0.5;
+ if (!data.calculate) {
+ consume_one(player, data.offering_num);
+ }
+ grace = 0.027 * ((item0.grace || 0) + (item1.grace || 0) + (item2.grace || 0) + 0.5 + player.p.ograce);
+
+ if (offering_def.grade > grade + 1) {
+ probability = probability * 1.64 + grace * 2;
+ high = true;
+ increase = 3;
+ } else if (offering_def.grade > grade) {
+ probability = probability * 1.48 + grace;
+ high = true;
+ increase = 1;
+ } else if (offering_def.grade == grade) {
+ probability = probability * 1.36 + min(30 * 0.027, grace);
+ } else if (offering_def.grade == grade - 1) {
+ probability = probability * 1.15 + min(25 * 0.019, grace) / max(item0.level - 2, 1);
+ increase = 0.2;
+ } else {
+ probability = probability * 1.08 + min(15 * 0.015, grace) / max(item0.level - 1, 1);
+ increase = 0.1;
+ }
+
+ if (!data.calculate) {
+ item0.grace = (item0.grace || 0) + (item1.grace || 0) + (item2.grace || 0);
+ grace_bonus += increase;
+ }
+ server_log("offering " + result + " < " + probability);
+ } else {
+ grace = 0.007 * ((item0.grace || 0) + (item1.grace || 0) + (item2.grace || 0) + player.p.ograce);
+ probability = probability + min(25 * 0.007, grace) / max(item0.level - 1, 1);
+ if (!data.calculate) {
+ item0.grace = max(max(item0.grace || 0, item1.grace || 0), item2.grace || 0);
}
}
- else
- {
- var ms=1000;
- if(data.calculate) return success_response("upgrade_chance",{calculate:true,chance:1,offering:offering.name,item:cache_item(item),grace:item.grace||0});
- consume_one(player,data.offering_num);
- item.grace=(item.grace||0)+0.5;
- server_log("item.grace: "+item.grace);
- player.p.u_type="offering";
- player.p.u_item=item;
- player.p.u_roll=0.999999999999999;
- if(player.s.massproduction) { ms/=2; delete player.s.massproduction; ex="+u+cid"; }
- if(player.s.massproductionpp) { ms/=10; delete player.s.massproductionpp; ex="+u+cid"; }
- player.q.upgrade={ms:ms,len:ms,num:data.item_num};
- player.items[data.item_num]={"name":"placeholder",p:{chance:1,name:item.name,level:item.level,scroll:null,offering:offering.name,nums:[]}};
- }
- }
- else if(scroll_def.type=="uscroll")
- {
- if(item.l) return socket.emit("game_response",{response:"item_locked",place:"upgrade",failed:true});
- if(grade==4) return socket.emit("game_response",{response:"max_level",level:item.level,place:"upgrade",failed:true});
- if(!data.calculate) consume_one(player,data.scroll_num);
- oprobability=probability=D.upgrades[item_def.igrade][new_level];
- // grace=max(0,min(new_level+1, (item.grace||0) + min(3,player.p.ugrace[new_level]/3.0) +min(2,ugrace[new_level]/4.0) +item_def.igrace + player.p.ograce/2.0 )); - original [16/07/18]
- grace=max(0,min(new_level+1, (item.grace||0) + min(3,player.p.ugrace[new_level]/4.5) +item_def.igrace) + min(6,S.ugrace[new_level]/3.0) + player.p.ograce/3.2);
- server_log("Grace num: "+grace+"\nItem: "+(item.grace||0)+"\nPlayer: "+min(3,player.p.ugrace[new_level]/4.5)+"\nDef: "+item_def.igrace+"\nOgrace:"+(player.p.ograce/3.2)+"\nS.ugrace: "+min(6,S.ugrace[new_level]/3.0));
- grace=(probability*grace/new_level)+grace/1000.0;
- server_log("Grace-prob: "+grace);
- result=Math.random();
- server_log(result+" < "+probability);
- // if(!data.calculate && item.name=="throwingstars" && scroll_def.grade==2 && item.level==4) item.p="superfast";
-
- if(scroll_def.grade>grade && new_level<=10)
- {
- probability=probability*1.2+0.01;
- high=true;
- if(!data.calculate) item.grace=(item.grace||0)+0.4;
+ if (!data.calculate) {
+ item0.grace = item0.grace / 6.4 + grace_bonus;
}
- if(offering)
- {
- var increase=0.4;
- if(!data.calculate) consume_one(player,data.offering_num);
-
- if(offering_def.grade>grade+1)
- probability=probability*1.7+grace*4,high=true,increase=3;
- else if(offering_def.grade>grade)
- probability=probability*1.5+grace*1.2,high=true,increase=1;
- else if(offering_def.grade==grade)
- probability=probability*1.4+grace;
- else if(offering_def.grade==grade-1)
- probability=probability*1.15+grace/3.2,increase=0.2;
- else
- probability=probability*1.08+grace/4,increase=0.1;
-
- if(!data.calculate) item.grace=(item.grace||0)+increase; // previously +1 [16/07/18]
- }
- else
- {
- grace=max(0,grace/4.8-0.4/((new_level-0.999)*(new_level-0.999)));
- probability+=grace; // previously 12.0 // previously 9.0 [16/07/18]
+ if (def.type == "booster") {
+ probability = 0.9999999999999;
+ proc = offering && 0.12;
+ } else {
+ probability = min(
+ probability,
+ min(oprobability * (3 + ((high && high * 0.6) || 0)), oprobability + 0.2 + ((high && high * 0.05) || 0)),
+ );
}
- if(!data.calculate && Math.random()<0.025) // Bonus grace
- item.grace=(item.grace||0)+1;
-
- if(data.item_num==player.p.item_num && Math.random()<0.6) // Added [29/10/17]
- {
- server_log("16 cheat");
- result=max(Math.random()/10000.0,result*0.975-0.012);
+ if (gameplay == "test") {
+ result = 0;
}
- if(high) probability=min(probability,min(oprobability+0.36,oprobability*3));
- else probability=min(probability,min(oprobability+0.24,oprobability*2));
- server_log(result+" < "+probability+" grace: "+grace);
+ server_log(result + " < " + probability + " grace: " + grace);
- if(data.calculate) return success_response("upgrade_chance",{calculate:true,chance:probability,offering:offering&&offering.name||undefined,item:cache_item(item),grace:item.grace||0,scroll:scroll.name});
+ if (data.calculate) {
+ return success_response("compound_chance", {
+ calculate: true,
+ chance: probability,
+ item: cache_item(item0),
+ scroll: scroll.name,
+ offering: (offering && offering.name) || undefined,
+ grace: (item0.grace || 0) + (item1.grace || 0) + (item2.grace || 0),
+ });
+ }
- if(gameplay=="test") result=0;
- // result=probability;
- player.p.u_type="normal";
- player.p.u_roll=result;
- var ms=500*new_level*Math.sqrt(new_level)*tmult;
- if(player.s.massproduction) { ms/=2; delete player.s.massproduction; ex="+u+cid"; }
- if(player.s.massproductionpp) { ms/=10; delete player.s.massproductionpp; ex="+u+cid"; }
- player.q.upgrade={ms:ms,len:ms,num:data.item_num};
- if(gameplay=="hardcore") player.q.upgrade.ms=player.q.upgrade.len=500;
- player.items[data.item_num]={"name":"placeholder",p:{chance:probability,name:item.name,level:item.level,scroll:scroll.name,offering:offering&&offering.name,nums:[]}};
+ player.p.c_roll = result;
+ var len = 10000;
+ if (gameplay == "hardcore") {
+ len = 1200;
+ }
+ if (player.s.massproduction) {
+ len /= 2;
+ delete player.s.massproduction;
+ ex = "+u+cid";
+ }
+ if (player.s.massproductionpp) {
+ len /= 10;
+ delete player.s.massproductionpp;
+ ex = "+u+cid";
+ }
+ player.q.compound = { ms: len, len: len, num: data.items[0], nums: [] };
+ player.items[data.items[0]] = {
+ name: "placeholder",
+ p: {
+ chance: probability,
+ name: item0.name,
+ level: item0.level,
+ scroll: scroll.name,
+ offering: offering && offering.name,
+ nums: [],
+ },
+ };
+ player.items[data.items[1]] = null;
+ player.items[data.items[2]] = null;
- //result=probability+EPS;
-
- if(result<=probability)
- {
- // console.log("here");
- player.p.ugrace[new_level]=S.ugrace[new_level]=0;
- if(offering) player.p.ograce*=0.25;
- else player.p.ograce*=1-new_level*0.005;
- item.level=new_level;
- if(item.oo!=player.name) item.o=player.name;
- player.p.u_item=item;
- if(parseInt(result*10000)==parseInt(probability*10000) && grade>=1)
- {
- add_item_property(item,"lucky");
- add_achievement(player,"lucky")
+ if (result <= probability) {
+ if (offering) {
+ player.p.ograce = 0;
+ } else {
+ player.p.ograce *= 1 - new_level * 0.02;
}
- }
- else
- {
- player.p.ugrace[new_level-1]+=1; S.ugrace[new_level-1]+=1
- player.p.ugrace[new_level]+=1; S.ugrace[new_level]+=1;
- if(new_level>=8 && new_level<=15)
- {
- player.p.ugrace[new_level-1]+=1; S.ugrace[new_level-1]+=1;
- player.p.ugrace[new_level-2]+=2+(offering&&1||0); S.ugrace[new_level-2]+=2;
- player.p.ugrace[new_level-3]+=2+(offering&&2||0); S.ugrace[new_level-3]+=3+(offering&&1||0);
+ item0.level = new_level;
+ if ((item0.p || item1.p || item2.p) != "legacy") {
+ item0.p = item0.p || item1.p || item2.p;
+ } else {
+ delete item0.p;
}
- if(offering) player.p.ograce+=0.6; // previously 1 [16/07/18]
- if(scroll_def.grade!=3.6) player.p.u_itemx=item;
- else player.p.u_item=item,player.p.u_fail=true;
- if(parseInt(result*10000)==parseInt(probability*10000))
- {
- if(player.esize && grade>=1) add_item(player,"essenceofgreed");
- add_achievement(player,"unlucky");
+ player.p.c_item = item0;
+ if (item0.oo != player.name) {
+ item0.o = player.name;
}
- }
- }
- else if(scroll_def.type=="pscroll")
- {
- var needed=[1,10,100,1000,9999,9999,9999];
- if(scroll.q=1
+ add_achievement(player, "lucky");
+ add_item_property(item0, "lucky");
+ }
+ if (item1.v || item2.v) {
+ item0.v = item1.v || item2.v;
+ }
+ if (item0.name == "ctristone" && item0.level == 1 && Math.random() < 0.012) {
+ item0.name = "cdarktristone";
+ }
+ if (def.type == "booster") {
+ var activate = false;
+ item0.extra = 0;
+ while (offering && proc && Math.random() < proc) {
+ item0.extra++;
+ item0.level += 1;
+ proc /= 2.0;
+ }
+ var seconds = 6 * 24 * 60 * 60;
+ [item0, item1, item2].forEach(function (i) {
+ if (i.expires) {
+ seconds -= ssince(i.expires);
+ activate = true;
+ } else {
+ seconds += def.days * 24 * 60 * 60;
+ }
+ });
+ if (activate) {
+ item0.expires = future_s(seconds / 3);
+ }
+ }
+ } else {
+ if (offering) {
+ player.p.ograce += 0.4;
+ }
+ player.esize += 2;
+ player.p.c_item = null;
+ player.p.c_itemx = item0;
}
- item.stat_type=scroll_def.stat;
- player.p.u_roll=Math.random();
+ player.citems[data.items[0]] = cache_item(player.items[data.items[0]]);
+ player.citems[data.items[1]] = cache_item(player.items[data.items[1]]);
+ player.citems[data.items[2]] = cache_item(player.items[data.items[2]]);
- player.p.u_type="stat";
- if(player.p.u_roll<=0.99999 || offering) player.p.u_item=item;
- else player.p.u_itemx=item;
- var ms=2000*tmult*tmult;
- if(player.s.massproduction) { ms/=2; delete player.s.massproduction; ex="+u+cid"; }
- if(player.s.massproductionpp) { ms/=10; delete player.s.massproductionpp; ex="+u+cid"; }
- player.q.upgrade={ms:ms,len:ms,num:data.item_num};
- player.items[data.item_num]={"name":"placeholder",p:{chance:0.99999,name:item.name,level:item.level,scroll:scroll.name,offering:offering&&offering.name,nums:[]}};
+ resend(player, "reopen+nc+inv" + ex);
+ } catch (e) {
+ server_log("compound_e " + e);
+ return socket.emit("game_response", { response: "exception", place: "compound", failed: true });
}
-
- player.citems[data.item_num]=cache_item(player.items[data.item_num]);
-
- resend(player,"reopen+nc+inv"+ex);
-
- }catch(e){
- server_log('upgrade_e '+e);
- return socket.emit("game_response",{response:"exception",place:"upgrade",failed:true});
- }
- });
- socket.on('equip',function(data){
- var player=players[socket.id]; if(!player) return;
- player.c={};
- data.num=to_number(data.num);
- if(data.num>=player.items.length) return fail_response("invalid");
- var item=player.items[data.num];
- if(!item) return fail_response("no_item");
- if(item.b) return fail_response("item_blocked");
- if(item.name=="placeholder") return fail_response("item_placeholder");
- var def=G.items[item.name],to_update="reopen+u+cid",resolve={num:data.num},resolve_type="data";
- def.iname=item.name; //just for orb name checks [08/10/16]
- if(!def) return fail_response("no_item");
- // if(is_sdk) server_log("Trying to equip "+JSON.stringify(data));
-
- if(data.slot && get_trade_slots(player).includes(data.slot) && !data.consume)
- {
- if(item.acl || item.v) return fail_response("item_locked");
- var slot=data.slot,price=round(min(99999999999,max(parseInt(data.price)||1,1))),minutes=1;
- data.q=max(1,parseInt(data.q)||1);
- if((item.q||1)0) disappearing_text(socket,player,"+"+amount,{color:"hp",xy:1,s:"hp"});
- else disappearing_text(socket,player,amount,{color:"hp",xy:1,s:"hp"});
- }
- if(p[0]=="mp") disappearing_text(socket,player,"+"+amount,{color:"mp",xy:1,s:"mp"});
- if(p[0]=="xp") disappearing_text(socket,player,"+1M",{color:"1mxp",xy:1,s:"xp",size:"large"}),xp=true,timeout_ui=120,timeout=0.1;
- });
- if(def.debuff)
- {
- for(var c in player.s)
- {
- if(G.conditions[c] && G.conditions[c].debuff && (!G.conditions[c].persistent || c=="hopsickness"))
- delete player.s[c];
- }
- }
- player.hp=min(player.hp,player.max_hp); player.mp=min(player.mp,player.max_mp);
- if(def.cooldown) timeout=def.cooldown;
- player.last.potion=future_ms(timeout);
- if(!xp) to_update="u+cid+reopen+nc";
- socket.emit("eval",{code:"pot_timeout("+(timeout_ui||timeout)+")"});
- }
- else if(!data.consume)
- {
- // console.log(data);
- var slot=data.slot||def.type,existing;
- var comp=can_equip_item(player,def,slot);
- if(comp=="no")
- {
- resend(player,"u+cid+reopen"); // if you drop something on an invalid slot, it stays there for a bit otherwise [29/08/22]
- return fail_response("cant_equip");
- }
- slot=comp;
- existing=player.slots[slot];
- player.slots[slot]=player.items[data.num]; player.cslots[slot]=cache_item(player.slots[slot]);
- if(existing && existing.b) existing=null;
- player.items[data.num]=existing,player.citems[data.num]=cache_item(existing);
- player.s.penalty_cd={ms:min(((player.s.penalty_cd&&player.s.penalty_cd.ms)||0)+120,120000)};
- resolve.slot=slot;
- }
- else
- {
- return fail_response("cant_consume");
- }
-
- if(to_update) resend(player,to_update);
- success_response(resolve_type,resolve);
- });
- socket.on('misc_npc',function(data){
- var player=players[socket.id]; if(!player) return;
- var npc=players[data.npc]; if(!npc || !npc.npc) return;
- if(simple_distance(player,npc)>1000) return socket.emit("game_response","distance");
- if(data.npc==NPC_prefix+"Marven" && npc.misc==true)
- {
- server_log("Here!");
- }
- });
- socket.on('unequip',function(data){
- var player=players[socket.id];
- if(!player || !data.slot || !player.slots[data.slot]) return fail_response("invalid");
- if(data.slot=="elixir") return fail_response("cant");
- var item=player.slots[data.slot],done=false;
- if(in_arr(data.slot,trade_slots) && item.giveaway!==undefined) return fail_response("giveaway");
- // an oversight allowed .giveaway items to be equipped, so now they can be unequipped from regular slots [04/11/21]
- if(player.esize<=0 && !item.b) return fail_response("no_space");
- player.slots[data.slot]=null; player.cslots[data.slot]=null;
- player.c={};
- if(!item.b) add_item(player,item,{announce:false});
- resend(player,"reopen+u+cid");
- success_response("data");
- });
- socket.on('secondhands',function(data){
- var player=players[socket.id]; if(!player) return;
- if(simple_distance(G.maps.main.ref.secondhands,player)>500) return socket.emit("game_response","distance");
- socket.emit('secondhands',csold);
- });
- socket.on('lostandfound',function(data){
- var player=players[socket.id]; if(!player) return;
- if(data=="info") return socket.emit("game_response",{response:"lostandfound_info",gold:S.gold});
- if(!player.donation) return socket.emit("game_response","lostandfound_donate");
- if(simple_distance(G.maps.woffice.ref.lostandfound,player)>500) return socket.emit("game_response","distance");
- socket.emit('lostandfound',cfound);
- })
- socket.on('split',function(data){
- var player=players[socket.id],num=data.num,item=player.items[data.num],quantity=min(max(parseInt(data.quantity)||0,1),item&&item.q||1);
- if(!item) return fail_response("no_item");
- if(!G.items[item.name].s) return fail_response("invalid");
- quantity=min(quantity,G.items[item.name].s||1);
- if(!player.esize) return fail_response("cant_space");
- if(item.q==quantity) return success_response();
- if(item.name=="placeholder") return fail_response("item_placeholder");
- if(item.l) return fail_response("item_locked");
- if(item.b) return fail_response("item_blocked");
-
- consume(player,data.num,quantity);
-
- var new_item=cache_item(item);
- if(item.q) new_item.q=quantity;
-
- for(var i=0;iplayer.gold) return socket.emit("game_response","not_enough_gold");
- var shells=Math.floor(gold/G.multipliers.shells_to_gold);
- player.gold-=gold;
- socket.emit("game_log","Gave "+to_pretty_num(gold)+" gold");
- appengine_call("bill_user",{auth:player.auth,amount:-shells,reason:"buy_shells",name:player.name},function(result){
- server_log("buy_with_cash: "+JSON.stringify(result));
- if(result.failed || !result.done) { socket.emit("game_log","Purchase failed"); return; }
- player.cash=result.cash;
- socket.emit("game_log","Received "+to_pretty_num(shells)+" shells");
+ socket.on("upgrade", function (data) {
+ try {
+ var player = players[socket.id];
+ var item = player.items[data.item_num];
+ var scroll = player.items[data.scroll_num];
+ var offering = player.items[data.offering_num];
+ var result;
+ var ex = "";
+ if (!player || player.user) {
+ return fail_response("cant_in_bank");
+ }
+ if (player.q.upgrade) {
+ return socket.emit("game_response", "upgrade_in_progress");
+ }
+ G.maps.main.upgrade.name = player.name;
+ if (!player.computer && simple_distance(G.maps.main.upgrade, player) > B.sell_dist) {
+ return socket.emit("game_response", { response: "distance", place: "upgrade", failed: true });
+ }
+ if (!item) {
+ return socket.emit("game_response", "upgrade_no_item");
+ }
+ if (
+ offering &&
+ !(
+ (G.items[offering.name] && G.items[offering.name].type == "offering") ||
+ (G.items[offering.name] && G.items[offering.name].offering !== undefined && !(item.level > 0))
+ )
+ ) {
+ return socket.emit("game_response", "upgrade_invalid_offering");
+ }
+ if (!scroll && !offering) {
+ return socket.emit("game_response", "upgrade_no_scroll");
+ }
+ if ((item.level || 0) != data.clevel) {
+ return socket.emit("game_response", "upgrade_mismatch");
+ }
+ var item_def = G.items[item.name];
+ var scroll_def = scroll && G.items[scroll.name];
+ var offering_def = offering && G.items[offering.name];
+ var grade = calculate_item_grade(item_def, item);
+ if (!item_def.upgrade) {
+ return socket.emit("game_response", "upgrade_cant");
+ }
+ if (
+ scroll &&
+ (!in_arr(scroll_def.type, ["uscroll", "pscroll"]) ||
+ (scroll_def.type == "uscroll" && !item_def.upgrade) ||
+ (scroll_def.type == "pscroll" && !item_def.stat) ||
+ grade > scroll_def.grade)
+ ) {
+ if (grade == 4 && scroll_def.type == "uscroll") {
+ return socket.emit("game_response", {
+ response: "max_level",
+ level: item.level,
+ place: "upgrade",
+ failed: true,
+ });
+ }
+ return socket.emit("game_response", "upgrade_incompatible_scroll");
+ }
- resend(player,"reopen+nc");
+ var new_level = (item.level || 0) + 1;
+ var probability = 1;
+ var oprobability = 1;
+ var grace = 0;
+ var high = false;
+ var ograde = calculate_item_grade(item_def, { name: item.name, level: 0 });
+ var tmult = 1;
+ if (ograde == 1) {
+ tmult = 1.5;
+ } else if (ograde == 2) {
+ tmult = 2;
+ }
+
+ delete player.p.u_item;
+ delete player.p.u_type;
+ delete player.p.u_itemx;
+ delete player.p.u_roll;
+ delete player.p.u_fail;
+ delete player.p.u_level;
+
+ player.p.u_level = item.level || 0;
+
+ if (!scroll) {
+ if (G.items[offering.name] && G.items[offering.name].offering !== undefined) {
+ var chance = 0.16;
+ var ms = 2000;
+ if (
+ G.items[offering.name].offering > ograde ||
+ (G.items[offering.name].offering == 2 && calculate_item_value(item) <= 20000000)
+ ) {
+ chance = 0.32;
+ }
+ chance *= [2.8, 1.6, 1][ograde];
+ if (G.items[offering.name].offering < ograde) {
+ return socket.emit("game_response", "upgrade_invalid_offering");
+ }
+ if (data.calculate) {
+ return success_response("upgrade_chance", {
+ calculate: true,
+ chance: chance,
+ offering: offering.name,
+ item: cache_item(item),
+ grace: item.grace || 0,
+ });
+ }
+ var result = Math.random();
+
+ consume_one(player, data.offering_num);
+ player.p.u_type = "normal";
+ player.p.u_roll = result;
+ if (player.s.massproduction) {
+ ms /= 2;
+ delete player.s.massproduction;
+ ex = "+u+cid";
+ }
+ if (player.s.massproductionpp) {
+ ms /= 10;
+ delete player.s.massproductionpp;
+ ex = "+u+cid";
+ }
+ player.q.upgrade = { ms: ms, len: ms, num: data.item_num, silent: true };
+ player.items[data.item_num] = {
+ name: "placeholder",
+ p: {
+ chance: chance,
+ name: item.name,
+ level: item.level,
+ scroll: null,
+ offering: offering.name,
+ nums: [],
+ },
+ };
+
+ if (result <= chance) {
+ item.p = "shiny";
+ player.p.u_item = item;
+ } else {
+ player.p.u_item = item;
+ player.p.u_fail = true;
+ }
+ } else {
+ var ms = 1000;
+ if (data.calculate) {
+ return success_response("upgrade_chance", {
+ calculate: true,
+ chance: 1,
+ offering: offering.name,
+ item: cache_item(item),
+ grace: item.grace || 0,
+ });
+ }
+ consume_one(player, data.offering_num);
+ item.grace = (item.grace || 0) + 0.5;
+ server_log("item.grace: " + item.grace);
+ player.p.u_type = "offering";
+ player.p.u_item = item;
+ player.p.u_roll = 0.999999999999999;
+ if (player.s.massproduction) {
+ ms /= 2;
+ delete player.s.massproduction;
+ ex = "+u+cid";
+ }
+ if (player.s.massproductionpp) {
+ ms /= 10;
+ delete player.s.massproductionpp;
+ ex = "+u+cid";
+ }
+ player.q.upgrade = { ms: ms, len: ms, num: data.item_num };
+ player.items[data.item_num] = {
+ name: "placeholder",
+ p: { chance: 1, name: item.name, level: item.level, scroll: null, offering: offering.name, nums: [] },
+ };
+ }
+ } else if (scroll_def.type == "uscroll") {
+ if (item.l) {
+ return socket.emit("game_response", { response: "item_locked", place: "upgrade", failed: true });
+ }
+ if (grade == 4) {
+ return socket.emit("game_response", {
+ response: "max_level",
+ level: item.level,
+ place: "upgrade",
+ failed: true,
+ });
+ }
+ if (!data.calculate) {
+ consume_one(player, data.scroll_num);
+ }
+ oprobability = probability = D.upgrades[item_def.igrade][new_level];
+ // grace=max(0,min(new_level+1, (item.grace||0) + min(3,player.p.ugrace[new_level]/3.0) +min(2,ugrace[new_level]/4.0) +item_def.igrace + player.p.ograce/2.0 )); - original [16/07/18]
+ grace = max(
+ 0,
+ min(new_level + 1, (item.grace || 0) + min(3, player.p.ugrace[new_level] / 4.5) + item_def.igrace) +
+ min(6, S.ugrace[new_level] / 3.0) +
+ player.p.ograce / 3.2,
+ );
+ server_log(
+ "Grace num: " +
+ grace +
+ "\nItem: " +
+ (item.grace || 0) +
+ "\nPlayer: " +
+ min(3, player.p.ugrace[new_level] / 4.5) +
+ "\nDef: " +
+ item_def.igrace +
+ "\nOgrace:" +
+ player.p.ograce / 3.2 +
+ "\nS.ugrace: " +
+ min(6, S.ugrace[new_level] / 3.0),
+ );
+ grace = (probability * grace) / new_level + grace / 1000.0;
+ server_log("Grace-prob: " + grace);
+ result = Math.random();
+ server_log(result + " < " + probability);
+
+ // if(!data.calculate && item.name=="throwingstars" && scroll_def.grade==2 && item.level==4) item.p="superfast";
+
+ if (scroll_def.grade > grade && new_level <= 10) {
+ probability = probability * 1.2 + 0.01;
+ high = true;
+ if (!data.calculate) {
+ item.grace = (item.grace || 0) + 0.4;
+ }
+ }
+
+ if (offering) {
+ var increase = 0.4;
+ if (!data.calculate) {
+ consume_one(player, data.offering_num);
+ }
+
+ if (offering_def.grade > grade + 1) {
+ probability = probability * 1.7 + grace * 4;
+ high = true;
+ increase = 3;
+ } else if (offering_def.grade > grade) {
+ probability = probability * 1.5 + grace * 1.2;
+ high = true;
+ increase = 1;
+ } else if (offering_def.grade == grade) {
+ probability = probability * 1.4 + grace;
+ } else if (offering_def.grade == grade - 1) {
+ probability = probability * 1.15 + grace / 3.2;
+ increase = 0.2;
+ } else {
+ probability = probability * 1.08 + grace / 4;
+ increase = 0.1;
+ }
+
+ if (!data.calculate) {
+ item.grace = (item.grace || 0) + increase;
+ } // previously +1 [16/07/18]
+ } else {
+ grace = max(0, grace / 4.8 - 0.4 / ((new_level - 0.999) * (new_level - 0.999)));
+ probability += grace; // previously 12.0 // previously 9.0 [16/07/18]
+ }
+
+ if (!data.calculate && Math.random() < 0.025) {
+ // Bonus grace
+ item.grace = (item.grace || 0) + 1;
+ }
+
+ if (data.item_num == player.p.item_num && Math.random() < 0.6) {
+ // Added [29/10/17]
+ server_log("16 cheat");
+ result = max(Math.random() / 10000.0, result * 0.975 - 0.012);
+ }
+
+ if (high) {
+ probability = min(probability, min(oprobability + 0.36, oprobability * 3));
+ } else {
+ probability = min(probability, min(oprobability + 0.24, oprobability * 2));
+ }
+ server_log(result + " < " + probability + " grace: " + grace);
+
+ if (data.calculate) {
+ return success_response("upgrade_chance", {
+ calculate: true,
+ chance: probability,
+ offering: (offering && offering.name) || undefined,
+ item: cache_item(item),
+ grace: item.grace || 0,
+ scroll: scroll.name,
+ });
+ }
+
+ if (gameplay == "test") {
+ result = 0;
+ }
+ // result=probability;
+ player.p.u_type = "normal";
+ player.p.u_roll = result;
+ var ms = 500 * new_level * Math.sqrt(new_level) * tmult;
+ if (player.s.massproduction) {
+ ms /= 2;
+ delete player.s.massproduction;
+ ex = "+u+cid";
+ }
+ if (player.s.massproductionpp) {
+ ms /= 10;
+ delete player.s.massproductionpp;
+ ex = "+u+cid";
+ }
+ player.q.upgrade = { ms: ms, len: ms, num: data.item_num };
+ if (gameplay == "hardcore") {
+ player.q.upgrade.ms = player.q.upgrade.len = 500;
+ }
+ player.items[data.item_num] = {
+ name: "placeholder",
+ p: {
+ chance: probability,
+ name: item.name,
+ level: item.level,
+ scroll: scroll.name,
+ offering: offering && offering.name,
+ nums: [],
+ },
+ };
+
+ //result=probability+EPS;
+
+ if (result <= probability) {
+ // console.log("here");
+ player.p.ugrace[new_level] = S.ugrace[new_level] = 0;
+ if (offering) {
+ player.p.ograce *= 0.25;
+ } else {
+ player.p.ograce *= 1 - new_level * 0.005;
+ }
+ item.level = new_level;
+ if (item.oo != player.name) {
+ item.o = player.name;
+ }
+ player.p.u_item = item;
+ if (parseInt(result * 10000) == parseInt(probability * 10000) && grade >= 1) {
+ add_item_property(item, "lucky");
+ add_achievement(player, "lucky");
+ }
+ } else {
+ player.p.ugrace[new_level - 1] += 1;
+ S.ugrace[new_level - 1] += 1;
+ player.p.ugrace[new_level] += 1;
+ S.ugrace[new_level] += 1;
+ if (new_level >= 8 && new_level <= 15) {
+ player.p.ugrace[new_level - 1] += 1;
+ S.ugrace[new_level - 1] += 1;
+ player.p.ugrace[new_level - 2] += 2 + ((offering && 1) || 0);
+ S.ugrace[new_level - 2] += 2;
+ player.p.ugrace[new_level - 3] += 2 + ((offering && 2) || 0);
+ S.ugrace[new_level - 3] += 3 + ((offering && 1) || 0);
+ }
+ if (offering) {
+ player.p.ograce += 0.6;
+ } // previously 1 [16/07/18]
+ if (scroll_def.grade != 3.6) {
+ player.p.u_itemx = item;
+ } else {
+ player.p.u_item = item;
+ player.p.u_fail = true;
+ }
+ if (parseInt(result * 10000) == parseInt(probability * 10000)) {
+ if (player.esize && grade >= 1) {
+ add_item(player, "essenceofgreed");
+ }
+ add_achievement(player, "unlucky");
+ }
+ }
+ } else if (scroll_def.type == "pscroll") {
+ var needed = [1, 10, 100, 1000, 9999, 9999, 9999];
+ if (scroll.q < needed[grade]) {
+ return socket.emit("game_response", { response: "upgrade_scroll_q", q: needed[grade], h: scroll.q });
+ }
+ if (!data.calculate) {
+ consume(player, data.scroll_num, needed[grade]);
+ }
+
+ if (data.calculate) {
+ return success_response("upgrade_chance", {
+ calculate: true,
+ chance: 0.99999,
+ scroll: scroll.name,
+ item: cache_item(item),
+ grace: item.grace || 0,
+ });
+ }
+
+ if (offering) {
+ consume_one(player, data.offering_num);
+ item.grace = (item.grace || 0) + 1;
+ server_log("Graced up to " + item.grace);
+ }
+
+ item.stat_type = scroll_def.stat;
+ player.p.u_roll = Math.random();
+
+ player.p.u_type = "stat";
+ if (player.p.u_roll <= 0.99999 || offering) {
+ player.p.u_item = item;
+ } else {
+ player.p.u_itemx = item;
+ }
+ var ms = 2000 * tmult * tmult;
+ if (player.s.massproduction) {
+ ms /= 2;
+ delete player.s.massproduction;
+ ex = "+u+cid";
+ }
+ if (player.s.massproductionpp) {
+ ms /= 10;
+ delete player.s.massproductionpp;
+ ex = "+u+cid";
+ }
+ player.q.upgrade = { ms: ms, len: ms, num: data.item_num };
+ player.items[data.item_num] = {
+ name: "placeholder",
+ p: {
+ chance: 0.99999,
+ name: item.name,
+ level: item.level,
+ scroll: scroll.name,
+ offering: offering && offering.name,
+ nums: [],
+ },
+ };
+ }
+
+ player.citems[data.item_num] = cache_item(player.items[data.item_num]);
+
+ resend(player, "reopen+nc+inv" + ex);
+ } catch (e) {
+ server_log("upgrade_e " + e);
+ return socket.emit("game_response", { response: "exception", place: "upgrade", failed: true });
+ }
});
- resend(player,"reopen+nc");
- });
- socket.on('buy_with_cash',function(data){
- var player=players[socket.id],name=data.name,def=G.items[data.name],quantity=min(max(parseInt(data.quantity)||0,1),def&&def.s||9999);
- if(!player || player.user || gameplay=="hardcore" || gameplay=="test") return fail_response("cant_in_bank");
- var cost=def.cash*quantity;
- if(!def.cash || def.ignore) return fail_response("invalid");
- if(def.p2w) return fail_response("invalid");
- if(!def.s) quantity=1;
- if(!can_add_item(player,create_new_item(name,quantity))) return fail_response("no_space");
- appengine_call("bill_user",{auth:player.auth,amount:cost,reason:data.name,name:player.name},function(result){
- server_log("buy_with_cash: "+JSON.stringify(result));
- if(result.failed || !result.done) { socket.emit("game_log","Purchase failed"); return; }
- player.cash=result.cash;
- var new_item=create_new_item(name,quantity),done=false;
- add_item(player,new_item,{announce:false});
- socket.emit("game_log","Spent "+to_pretty_num(cost)+" shells");
-
- resend(player,"reopen+nc+inv");
- });
- success_response({success:false,in_progress:true});
- });
- socket.on('sbuy',function(data){
- var player=players[socket.id],done=false,npc=G.maps.main.ref.secondhands,c=S.sold,cc=csold,e="+$p",ev="secondhands",mult=2,src="scnd";
- if(data.f) npc=G.maps.woffice.ref.lostandfound,c=S.found,cc=cfound,e="+$f",ev="lostandfound",mult=4,src="lost";
- if(!player || player.user) return game_response("cant_in_bank");
- if(player.s.hopsickness && ev=="lostandfound") return fail_response("cant_when_sick",{goblin:true});
- if(simple_distance(npc,player)>500) return socket.emit("game_response","distance");
- for(var i=0;iplayer.gold) return socket.emit("game_response","buy_cost");
- player.gold-=gold;
- item.src=src;
- add_item(player,c[i],{announce:false});
- c.splice(i,1);
- cc.splice(i,1);
- socket.emit("game_log","Spent "+to_pretty_num(gold)+" gold");
- resend(player,"reopen+nc+inv");
- socket.emit(ev,cc);
- done=true;
- xy_emit(npc,"ui",{type:e,id:npc.id,name:player.name,item:cache_item(item,1)});
- break;
+ socket.on("equip", function (data) {
+ var player = players[socket.id];
+ if (!player) {
+ return;
}
- }
- if(!done) return socket.emit("game_log","Item gone");
- });
- socket.on('buy',function(data){
- var player=players[socket.id],can_reach=false;
- if(!player || player.user) return fail_response("cant_in_bank");
- var name=data.name,quantity=min(max(parseInt(data.quantity)||0,1),G.items[name]&&G.items[name].s||9999),cost=0,added=false,done=false;
- if(!can_buy[name] && gameplay!="test") return fail_response("buy_cant_npc");
- if(!can_add_item(player,create_new_item(name,quantity))) return fail_response("buy_cant_space");
- (G.maps[player.map].items[name]||[]).forEach(function(l){
- if(simple_distance(player,l)B.dist || receiver.map!=player.map)) return fail_response("distance");
- if(data.num!==undefined)
- {
- data.num=max(0,parseInt(data.num)||0);
- var item=player.items[data.num];
- if(!item) return fail_response("send_no_item");
- if(item.name=="placeholder") return fail_response("item_placeholder");
- if(item.l || item.acl && receiver.owner!=player.owner) return fail_response("item_locked");
- if(item.b) return fail_response("item_blocked");
- data.q=min((item.q||1),max(1,parseInt(data.q||1)||1));
- if(!data.q) return fail_response("no_item");
- if(!can_add_item(receiver,create_new_item(item.name,data.q))) return fail_response("send_no_space");
- if((item.q||1)==data.q) player.items[data.num]=player.citems[data.num]=null,player.esize++;
- else
- {
- player.items[data.num].q-=data.q;
- player.citems[data.num]=cache_item(player.items[data.num]);
+ player.c = {};
+ data.num = to_number(data.num);
+ if (data.num >= player.items.length) {
+ return fail_response("invalid");
}
-
- if(item.q)
- {
- s_item=create_new_item(item.name,data.q);
- if(item.v) s_item.v=item.v;
- if(item.data) s_item.data=item.data;
- num=add_item(receiver,s_item,{announce:false});
+ var item = player.items[data.num];
+ if (!item) {
+ return fail_response("no_item");
}
- else
- {
- s_item=item;
- num=add_item(receiver,item,{announce:false});
+ if (item.b) {
+ return fail_response("item_blocked");
}
-
- if(receiver.owner!=player.owner) item.src="snd";
-
-
- add_to_history(player,{"name":"item",to:receiver.name,item:item.name,q:data.q,level:item.level});
- add_to_history(receiver,{"name":"item",from:player.name,item:item.name,q:data.q,level:item.level});
-
- xy_emit(player,"ui",{type:"item_sent",receiver:receiver.name,sender:player.name,item:cache_item(s_item,null,{q:data.q}),num:num,fnum:data.num,event:true});
-
- resend(player,"reopen+nc+inv"); resend(receiver,"reopen+nc+inv");
- receiver.socket.emit("game_response",{response:"item_received",name:player.name,item:item.name,q:data.q,num:num,cevent:true});
- player.socket.emit("game_response",{response:"item_sent",name:receiver.name,item:item.name,q:data.q,num:data.num,cevent:true,place:"send"});
- }
- else if(data.gold!==undefined)
- {
- data.gold=min(player.gold,max(1,parseInt(data.gold||1)||1))||player.gold;
- if(!data.gold) return fail_response("invalid");
- player.gold-=data.gold;
- if(!is_same(player,receiver) && data.gold!=1) data.gold=parseInt(data.gold*0.975);
- receiver.gold+=data.gold;
-
- add_to_history(player,{"name":"gold",to:receiver.name,amount:data.gold});
- add_to_history(receiver,{"name":"gold",from:player.name,amount:data.gold});
-
- xy_emit(player,"ui",{type:"gold_sent",receiver:receiver.name,sender:player.name,gold:data.gold,event:true});
-
- resend(player,"reopen+nc+inv"); resend(receiver,"reopen+nc+inv");
- receiver.socket.emit("game_response",{response:"gold_received",name:player.name,gold:data.gold,cevent:true});
- player.socket.emit("game_response",{response:"gold_sent",name:receiver.name,gold:data.gold,cevent:true,place:"send"});
- }
- else if(data.cx!==undefined)
- {
- var cxl=map_cx(player),count=all_cx(player,1);
- if(!(cxl[data.cx] && player.p.acx[cxl[data.cx]] && count[data.cx]>0)) return fail_response("send_no_cx");
- // count[cxl[data.cx]] before [28/01/22]
- if(receiver.owner!=player.owner) return fail_response("send_diff_owner");
- player.p.acx[cxl[data.cx]]-=1;
- if(!player.p.acx[cxl[data.cx]]) delete player.p.acx[cxl[data.cx]];
- receiver.p.acx[cxl[data.cx]]=(receiver.p.acx[cxl[data.cx]]||0)+1;
-
- xy_emit(player,"ui",{type:"cx_sent",receiver:receiver.name,sender:player.name,cx:data.cx,event:true});
-
- receiver.socket.emit("game_response",{response:"cx_received",name:player.name,cx:data.cx,acx:receiver.p.acx,cevent:true});
- player.socket.emit("game_response",{response:"cx_sent",name:receiver.name,cx:data.cx,acx:player.p.acx,cevent:true,place:"send"});
- }
- });
- socket.on('donate',function(data){
- var player=players[socket.id],XPX=3.2;
- if(!player || player.user) return game_response("cant_in_bank");
- var gold=max(1,min(parseInt(data.gold)||0,1000000000));
- if(gold>player.gold) return socket.emit("game_response","gold_not_enough");
- if(gold>=1000000) response="thx",player.donation=true;
- else if(gold<100000) response="low";
- else add_item(player,"gum"),response="gum";
- if(S.gold<500000000) XPX=4.8;
- else if(S.gold<=1000000000) XPX=4;
- player.gold-=gold;
- S.gold+=gold;
- if(gold>=5000000) lstack(S.logs.donate,{name:player.name,gold:gold,xp:XPX});
- if(player.type=="merchant")
- player.xp+=parseInt(gold*XPX);
- resend(player,"reopen");
- socket.emit("game_response",{response:"donate_"+response,gold:gold,xprate:XPX});
- });
- socket.on('destroy',function(data){
- var player=players[socket.id],add="+nc+inv";
- data.num=max(0,parseInt(data.num)||0);
- if(!player.items[data.num]) return fail_response("no_item");
- var item=player.items[data.num],name=player.items[data.num].name;
- data.q=min(max(parseInt(data.q)||0,1),item&&item.q||1);
- if(item.name=="placeholder") return fail_response("item_placeholder");
- if(item.l) return fail_response("item_locked");
- if(item.b) return fail_response("item_blocked");
- if(item.level!=13)
- {
- consume(player,data.num,data.q);
- //player.items[data.num]=player.citems[data.num]=null;
- }
- if(data.statue)
- {
- if(item.name=="shadowstone")
- {
- add="+u+cid";
- player.s.invis={ms:99999};
+ if (item.name == "placeholder") {
+ return fail_response("item_placeholder");
}
- if(G.items[item.name].upgrade && Math.random()<1.0/(gameplay=="hardcore"&&10000||1000000))
- {
- add="+u+cid";
- item.level=13;
- player.items[data.num]=item;
- player.citems[data.num]=cache_item(player.items[data.num]);
+ var def = G.items[item.name];
+ var to_update = "reopen+u+cid";
+ var resolve = { num: data.num };
+ var resolve_type = "data";
+ def.iname = item.name; //just for orb name checks [08/10/16]
+ if (!def) {
+ return fail_response("no_item");
}
- xy_emit(G.maps.spookytown.ref.poof,"upgrade",{type:"poof",success:1});
- }
- resend(player,"reopen"+add);
- success_response("destroyed",{name:name,place:"destroy",cevent:"destroy"});
- });
- socket.on('join_giveaway',function(data){
- var player=players[socket.id],seller=players[id_to_id[data.id]],num;
- if(!player || player.user) return fail_response("cant_in_bank");
- if(!in_arr(data.slot,trade_slots)) return fail_response("invalid");
- if(!seller || seller.npc || is_invis(seller)) return fail_response("seller_gone");
- if(seller.user) return fail_response("cant_in_bank")
- if(distance(seller,player,true)>B.dist || seller.map!=player.map) return fail_response("distance");
- if(seller.id==player.id) return fail_response("hmm");
- var item=seller.slots[data.slot];
- if(!item || (data.rid && item.rid!=data.rid)) return fail_response("item_gone");
- if(!item.giveaway) return fail_response("sneaky");
- if(!player.auth_id) return fail_response("need_auth");
- //if(item.list.includes(player.name)) return socket.emit("game_log","Already joined!");
- //if(player.type!="merchant") return socket.emit("game_log","Only merchants can join giveaways!");
+ // if(is_sdk) server_log("Trying to equip "+JSON.stringify(data));
- //item.list.push(player.name);
-
- item.registry=item.registry||{};
- item.registry[player.auth_id]=player.name;
- item.list=Object.values(item.registry);
-
- socket.emit("game_log","Joined the giveaway!");
- seller.socket.emit("game_response",{response:"giveaway_join",name:player.name,slot:data.slot,cevent:true});
-
- resend(player,"reopen"); resend(seller,"reopen+u+cid");
- success_response({});
- });
- socket.on('trade_wishlist',function(data){
- var player=players[socket.id]; if(!player) return;
- data.q=min(9999,max(1,parseInt(data.q||1)||1));
- if(!in_arr(data.slot,trade_slots) || !G.items[data.name] || data.name=="placeholder") return fail_response("invalid");
- if(player.slots[data.slot] && !player.slots[data.slot].b) return fail_response("slot_occuppied");
- if(!get_trade_slots(player).includes(data.slot)) return fail_response("invalid");
- var item={name:data.name,rid:randomStr(4),price:round(min(99999999999,max(parseInt(data.price)||1,1))),b:true};
- if(G.items[data.name].upgrade || G.items[data.name].compound) item.q=min(99,data.q),item.level=round(min(12,max(parseInt(data.level)||0,0)));
- else item.q=data.q;
- player.slots[data.slot]=item; player.cslots[data.slot]=cache_item(player.slots[data.slot],true);
- resend(player,"reopen+u+cid+nc");
- success_response({})
- });
- socket.on('trade_sell',function(data){
- // if(!is_sdk) return;
- var player=players[socket.id],buyer=players[id_to_id[data.id]],num,actual=null,num=null;
- data.q=max(1,parseInt(data.q||1)||1);
- if(!player || player.user) return fail_response("cant_in_bank");
- if(!in_arr(data.slot,trade_slots)) return fail_response("invalid");
- if(!buyer || buyer.npc || is_invis(buyer)) return fail_response("buyer_gone");
- if(player.user) return fail_response("cant_in_bank");
- if(distance(buyer,player,true)>B.dist) return fail_response("distance");
- if(buyer.id==player.id) return fail_response("hmm");
- var item=buyer.slots[data.slot];
- if(!item || (data.rid && item.rid!=data.rid)) return fail_response("item_gone");
- if(item.name=="placeholder") return fail_response("item_placeholder");
- if(!item.b && !B.rbugs) return fail_response("sneaky");
- if((item.q||1)buyer.gold) return fail_response("buyer_gold");
- for(var i=0;i=data.q && player.items[i].level==item.level && !player.items[i].l)
- {
- actual=player.items[i]; num=i; break;
- }
- }
- if(!actual) return fail_response("no_item");
- if(actual.b) return fail_response("item_blocked");
- if(!can_add_item(buyer,create_new_item(item.name,data.q))) return fail_response("trade_bspace");
- var price=item.price*data.q;
- player.gold+=round(price*(1-player.tax)); add_to_trade_history(player,"sell",buyer.name,cache_item(actual,true,{q:data.q}),price);
- buyer.gold-=price; add_to_trade_history(buyer,"buy",player.name,cache_item(actual,true,{q:data.q}),price);
- S.gold+=price-round(price*(1-player.tax));
-
- if((item.q||1)==data.q) buyer.slots[data.slot]=buyer.cslots[data.slot]=null;
- else
- {
- buyer.slots[data.slot].q-=data.q;
- buyer.cslots[data.slot]=cache_item(buyer.slots[data.slot],true);
- }
-
- // up to here
-
- if((player.items[i].q||1)==data.q) player.items[num]=player.citems[num]=null;
- else player.items[num].q-=data.q,player.citems[num]=cache_item(player.items[num]);
-
- if(G.items[item.name].s) bnum=add_item(buyer,create_new_item(item.name,data.q),{announce:false});
- else bnum=add_item(buyer,actual,{announce:false});
-
- if(player.type=="merchant") merchant_xp_logic(player,buyer,price,price-round(price*(1-player.tax)));
- if(buyer.type=="merchant") merchant_xp_logic(buyer,player,price,price-round(price*(1-buyer.tax)));
-
- socket.emit("game_log","Sales tax "+to_pretty_num(price-round(price*(1-player.tax)))+" gold ["+(player.tax*100)+"%]");
- socket.emit("game_log","Received "+to_pretty_num(round(price*(1-player.tax)))+" gold");
- buyer.socket.emit("game_log","Spent "+to_pretty_num(price)+" gold");
-
- xy_emit(buyer,"ui",{type:"+$$",seller:player.name,buyer:buyer.name,item:cache_item(actual,true,{q:data.q,price:item.price}),slot:data.slot,num:bnum,snum:num});
-
- resend(player,"reopen"); resend(buyer,"reopen+u+cid");
- success_response({});
- });
- socket.on('trade_buy',function(data){
- var player=players[socket.id],seller=players[id_to_id[data.id]],num;
- data.q=max(1,parseInt(data.q||1)||1);
- if(!player || player.user) return fail_response("cant_in_bank");
- if(!in_arr(data.slot,trade_slots)) return fail_response("invalid");
- if(!seller || seller.npc || is_invis(seller)) return fail_response("seller_gone");
- if(seller.user) return fail_response("cant_in_bank");
- if(distance(seller,player,true)>B.dist || seller.map!=player.map) return fail_response("distance");
- if(seller.id==player.id) return fail_response("hmm");
- var item=seller.slots[data.slot];
- if(!item || (data.rid && item.rid!=data.rid)) return fail_response("item_gone");
- if(item.name=="placeholder") return fail_response("item_placeholder");
- if(item.b || item.giveaway) return fail_response("sneaky");
- if(item.price*data.q>player.gold) return fail_response("gold_not_enough");
- if((item.q||1)=player.items.length) player.items.push(null); [22/11/16]
- if(player.items[a] && player.items[a].name=="placeholder") return fail_response("item_placeholder");
- if(player.items[b] && player.items[b].name=="placeholder") return fail_response("item_placeholder");
- if(can_stack(player.items[a],player.items[b]))
- {
- player.items[data.a].q=(player.items[a].q||1)+(player.items[b].q||1);
- player.items[data.b]=null;
- player.esize++;
- }
- else
- {
- a_item=player.items[a];
- player.items[a]=player.items[b];
- player.items[b]=a_item;
- }
- player.citems[data.a]=cache_item(player.items[data.a]); player.citems[data.b]=cache_item(player.items[data.b]);
- resend(player,"reopen+nc+inv");
- return success_response("data");
- });
- socket.on('bank',function(data){
- var player=players[socket.id]; if(!player) return;
- if(!player.user || player.mounting || player.unmounting) return fail_response("bank_unavailable");
- var success={};
- if(data.operation=="withdraw")
- {
- var amount=max(0,min(parseInt(data.amount)||0,player.user.gold));
- player.user.gold-=amount;
- player.gold+=amount;
- success={response:"bank_withdraw",gold:amount,cevent:true};
- }
- if(data.operation=="deposit")
- {
- var amount=max(0,min(parseInt(data.amount)||0,player.gold));
- player.user.gold+=amount;
- player.gold-=amount;
- success={response:"bank_store",gold:amount,cevent:true};
- }
- if(data.operation=="unlock")
- {
- if(!bank_packs[data.pack]) return fail_response("invalid");
- var gold=bank_packs[data.pack][1],shells=bank_packs[data.pack][2];
- if(!gold) return fail_response("gold_not_enough");
- if(player.user[data.pack]) return fail_response("invalid");
- if(data.gold)
- {
- if(player.goldplayer.str*3) fail_response("too_far");
- consume_one(player,data.num);
- if(item.name=="confetti")
- {
- player.thrilling=future_s(20);
- xy_emit({map:player.map,in:player.in,x:x,y:y},"eval","confetti_shower({in:'"+player.in+"',map:'"+player.map+"',real_x:"+x+",real_y:"+y+"})");
- }
- if(item.name=="firecrackers")
- {
- player.thrilling=future_s(200);
- xy_emit({map:player.map,in:player.in,x:x,y:y},"eval","firecrackers({in:'"+player.in+"',map:'"+player.map+"',real_x:"+x+",real_y:"+y+"})");
- for(var id in instances[player.in].monsters)
- {
- var monster=instances[player.in].monsters[id];
- if(monster.target && distance({map:player.map,in:player.in,x:x,y:y},monster)<64) stop_pursuit(monster,{force:true,cause:"firecrackers"});
+ if (item.l) {
+ return fail_response("item_locked");
}
- }
- if(item.name=="whiteegg")
- {
- xy_emit({map:player.map,in:player.in,x:x,y:y},"eval","egg_splash("+x+","+y+")");
- for(var id in instances[player.in].monsters)
- {
- var monster=instances[player.in].monsters[id];
- if(!monster.target && distance({map:player.map,in:player.in,x:x,y:y},monster)<32)
- target_player(monster,player);
- }
- }
- if(item.name=="smoke")
- {
- xy_emit({map:player.map,in:player.in,x:x,y:y},"eval","assassin_smoke("+x+","+y+");");
- }
- resend(player,"reopen+nc+inv");
- success_response({});
- }
- else fail_response("no_item");
- });
- socket.on('poke',function(data){
- var player=players[socket.id],level=1;
- if(!player || !player.slots.gloves || player.slots.gloves.name!="poker") return;
- if(player.pokes>=50) return socket.emit("game_log","You are out of pokes!");
- player.pokes=(player.pokes||0)+1;
- if(player.slots.gloves.level>=10) level=4;
- else if(player.slots.gloves.level==9) level=3;
- else if(player.slots.gloves.level==8) level=2;
- xy_emit(player,"poke",{name:data.name,level:level,who:player.name});
- });
- socket.on('merge',function(data){
- var player=players[socket.id]; if(!player) return;
- var container=player.slots[data.container];
- var pet=player.slots[data.pet];
- if(!container || container.type!="container" || !pet || pet.type!="container") return socket.emit("game_response","merge_mismatch");
- if(G.items[container.name].grade=8 && (player.type=="mage" || player.type=="priest")) player.tskin="snow_angel";
- else { return socket.emit("game_response","nothing"); }
- }
- else if(item.name=="tristone")
- {
- var on=true;
- if(player.tskin || player.tactivations==100) player.tskin="",on=false;
- else if(item.level<=1 && deduct_gender(player)=="female") player.tskin=random_one(["tf_green","tf_pink"]);
- else if(item.level==2 && deduct_gender(player)=="female") player.tskin=random_one(["tf_blue","tf_purple"]);
- else if(deduct_gender(player)=="female") player.tskin="tf_orange";
- else if(item.level<=1) player.tskin=random_one(["tm_gray","tm_brown","tm_white"]);
- else if(item.level==2) player.tskin=random_one(["tm_green","tm_yellow","tm_purple"]);
- else player.tskin=random_one(["tm_blue","tm_red"]);
- player.tactivations=(player.tactivations||0)+1;
- }
- else if(item.name=="darktristone")
- {
- var on=true;
- if(player.tskin || player.tactivations==100) player.tskin="",on=false;
- else if(item.level==4 && deduct_gender(player)=="female") player.tskin="mf_blue";
- else if(deduct_gender(player)=="female") player.tskin="mf_yellow";
- else if(item.level==4) player.tskin="mm_blue";
- else player.tskin="mm_yellow";
- player.tactivations=(player.tactivations||0)+1;
- }
- else return;
- resend(player,"reopen+nc+inv+u+cid");
- }
- else
- {
- var item=player.items[data.num];
- if(item)
- {
- if(item.name=="frozenstone")
- {
- consume_one(player,data.num);
- }
- if(item.name=="bkey")
- {
- if(!player.user) return socket.emit("game_response","only_in_bank");
- if(player.user.unlocked && player.user.unlocked.bank_b) return socket.emit("game_response","already_unlocked");
- consume_one(player,data.num);
- player.user.unlocked=player.user.unlocked||{};
- player.user.unlocked.bank_b=new Date();
- player.user.items8=player.user.items8||[];
- socket.emit("game_response","door_unlocked");
- }
- if(item.name=="ukey")
- {
- if(!player.user) return socket.emit("game_response","only_in_bank");
- if(player.user.unlocked && player.user.unlocked.bank_u) return socket.emit("game_response","already_unlocked");
- consume_one(player,data.num);
- player.user.unlocked=player.user.unlocked||{};
- player.user.unlocked.bank_u=new Date();
- player.user.items24=player.user.items24||[];
- socket.emit("game_response","door_unlocked");
- }
- if(item.name=="dkey")
- {
- if(!player.user) return socket.emit("game_response","only_in_bank");
- var found=false;
- for(var i=0;i<48;i++)
- {
- var pack="items"+i;
- if(!bank_packs[pack] || player.user[pack]) continue;
- found=true;
- player.user[pack]=[]; player.cuser[pack]=[];
- break;
+ var timeout = 2000;
+ var timeout_ui = null;
+ var xp = false;
+ consume_one(player, data.num);
+ (def.gives || []).forEach(function (p) {
+ var amount = p[1];
+ if (player.s.poisoned) {
+ amount = round(amount / 2);
}
- if(!found) return;
- consume_one(player,data.num);
- socket.emit("game_response","bank_pack_unlocked");
- }
- }
- resend(player,"reopen+nc+inv");
- }
- });
- socket.on('booster',function(data){
- var player=players[socket.id],item=player.items[data.num]; if(!player) return;
- server_log("booster "+data.num+" "+data.action);
- if(!item || !in_arr(item.name,booster_items)) return fail_response("invalid");
- if(data.action=="activate" && !item.expires)
- {
- item.expires=new Date();
- item.expires.setDate(item.expires.getDate()+30+(item.level||0)*2);
- //item.expires.setMinutes(item.expires.getMinutes()+2);
- }
- else if(data.action=="shift")
- {
- if(!in_arr(data.to,booster_items)) return fail_response("invalid");
- player.xpm=player.goldm=player.luckm=1;
- item.name=data.to;
- player.s.penalty_cd={ms:min(((player.s.penalty_cd&&player.s.penalty_cd.ms)||0)+240,120000)};
- }
- // if(item.expires) item.p="legacy";
- player.citems[data.num]=cache_item(player.items[data.num]);
- resend(player,"reopen");
- success_response({name:player.items[data.num].name});
- });
- socket.on('convert',function(data){
- // There are a lot of routines that could give birth to an endgame bug
- // This routine ended up being the one
- // "stone" boosters were originally 1200 shells
- // when they were discontinued, I let players exchange them for 3600 shells instead
- // turns out 'buy_with_cash' didn't check whether an item has "ignore" or not
- // so one could buy the stones for 1200 shells and sell them for 3600
- // unlocking infinite gold and shells [17/01/18]
- var player=players[socket.id],item=player.items[data.num],amount=3600;
- server_log("stone "+data.num+" "+data.action);
- if(!item || !in_arr(item.name,["stoneofxp","stoneofgold","stoneofluck"])) return;
- if(item.expires)
- {
- amount=round(600-hsince(item.expires)*100/24.0);
- }
- add_shells(player,amount,"convert");
- player.items[data.num]=null;
- player.citems[data.num]=cache_item(player.items[data.num]);
- resend(player,"reopen+cid");
- });
- socket.on('emotion',function(data){
- var player=players[socket.id]; if(!player) return;
- if(!data.name) data.name=random_one(Object.keys(player.p.emx));
- if(player.last.emotion && mssince(player.last.emotion)<2000)
- return socket.emit("game_response","emotion_cooldown");
- player.last.emotion=new Date();
- if(!G.emotions[data.name] || !player.p.emx[data.name])
- return socket.emit("game_response","emotion_cant");
- xy_emit(player,"emotion",{name:data.name,player:player.name});
- });
- socket.on('skill',function(data){
- var player=players[socket.id]; if(!player) return;
- var target=null,cool=true,resolve={response:"data",place:data.name,success:true},reject=null;
- player.first=true; G.skills.attack.cooldown=player.attack_ms;
- server_log("skill "+JSON.stringify(data));
- if(is_disabled(player))
- return fail_response("disabled",data.name);
- if((player.tskin=="konami" || is_silenced(player)) && data.name!="attack")
- return socket.emit("game_response",{response:"skill_cant_incapacitated",place:data.name,failed:true});
- if(!G.skills[data.name]) return socket.emit("game_response",{response:"no_skill",place:data.name,failed:true});
- if(G.skills[data.name].mp && player.mpB.max_vision))
- return socket.emit("disappear",{id:data.id,place:data.name,reason:"not_there"});
- }
- if(G.skills[data.name].requirements)
- {
- for(var requirement in G.skills[data.name].requirements)
- {
- if(!player[requirement] || player[requirement] 0) {
+ disappearing_text(socket, player, "+" + amount, { color: "hp", xy: 1, s: "hp" });
+ } else {
+ disappearing_text(socket, player, amount, { color: "hp", xy: 1, s: "hp" });
+ }
}
- found=true;
- }
- });
- if(charges) return socket.emit("game_response",{response:"skill_cant_charges",place:data.name,failed:true});
- if(!found) return socket.emit("game_response",{response:"skill_cant_slot",place:data.name,failed:true});
- }
- if(player.s.invincible) {delete player.s.invincible; player.to_resend="u+cid"};
- if(data.name=="attack" || data.name=="heal")
- {
- var attack=commence_attack(player,target,data.name);
- if(!attack.failed) resolve=attack;
- else reject=attack,cool=false;
- }
- if(data.name=="invis" && !player.s.invis)
- {
- if(player.s.marked) return socket.emit("game_response",{response:"skill_cant_use",place:data.name,failed:true});
- player.s.invis={ms:999999999999999};
- xy_emit(player,"disappear",{id:player.id,invis:true,reason:"invis"});
- player.to_resend=" ";
- }
- if(data.name=="pickpocket")
- {
- if(distance(player,target,true)>G.skills[data.name].range)
- return socket.emit("game_response",{response:"too_far",place:data.name,failed:true});
-
- consume_mp(player,G.skills[data.name].mp);
- player.c[data.name]={ms:G.skills[data.name].duration_min+Math.random()*(G.skills[data.name].duration_max-G.skills[data.name].duration_min),target:target.name};
- player.to_resend="u+cid";
- resolve={response:"data",place:data.name,success:false,in_progress:true}
- }
- if(data.name=="fishing" || data.name=="mining")
- {
- var direction=0,the_zone=null;
- consume_mp(player,G.skills[data.name].mp);
- (G.maps[player.map].zones||[]).forEach(function(zone){
- if(zone.type!=data.name || the_zone) return;
- [[0,-24,3],[-24,0,1],[24,0,2],[0,24,0]].forEach(function(m){
- if(is_point_inside([player.x+m[0],player.y+m[1]],zone.polygon))
- {
- the_zone=zone;
- direction=m[2];
+ if (p[0] == "mp") {
+ disappearing_text(socket, player, "+" + amount, { color: "mp", xy: 1, s: "mp" });
+ }
+ if (p[0] == "xp") {
+ disappearing_text(socket, player, "+1M", { color: "1mxp", xy: 1, s: "xp", size: "large" });
+ xp = true;
+ timeout_ui = 120;
+ timeout = 0.1;
}
});
- });
- if(!the_zone || player.moving)
- {
- xy_emit(player,"ui",{type:data.name+"_fail",name:player.name});
- reject={response:"data",place:data.name};
- }
- else
- {
- xy_emit(player,"ui",{type:data.name+"_start",name:player.name,direction:direction});
- player.c[data.name]={ms:G.skills[data.name].duration_min+Math.random()*(G.skills[data.name].duration_max-G.skills[data.name].duration_min),drop:the_zone.drop};
- }
- resolve={response:"data",place:data.name,success:false,in_progress:true}
- player.to_resend="u+cid";
- }
- if(data.name=="light")
- {
- consume_mp(player,G.skills[data.name].mp);
- xy_emit(player,"light",{name:player.name});
- player.to_resend="u+cid";
- }
- if(data.name=="charge")
- {
- player.s.charging={ms:G.skills.charge.duration};
- player.to_resend="u+cid";
- }
- if(data.name=="dash")
- {
- //console.log(data);
- consume_mp(player,G.skills[data.name].mp);
- var x=parseFloat(data.x)||0,y=parseFloat(data.y)||0,point=true;
- if(point_distance(player.x,player.y,x,y)>50)
- {
- point=false;
- player.socket.emit("game_response","dash_failed");
- reject={response:"data",place:data.name};
- }
- if(point)
- {
- var spot=safe_xy_nearby(player.map,x,y);
- if(!spot) spot=safe_xy_nearby(player.map,player.x+(x-player.x)*0.8,player.y+(y-player.y)*0.8);
- if(!spot) spot=safe_xy_nearby(player.map,player.x+(x-player.x)*0.6,player.y+(y-player.y)*0.6);
- if(!spot || point_distance(player.x,player.y,spot.x,spot.y)<10)
- {
- point=false;
- player.socket.emit("game_response","dash_failed");
- reject={response:"data",place:data.name};
+ if (def.debuff) {
+ for (var c in player.s) {
+ if (G.conditions[c] && G.conditions[c].debuff && (!G.conditions[c].persistent || c == "hopsickness")) {
+ delete player.s[c];
+ }
+ }
}
- if(point)
- {
- //console.log([player.x,player.y,spot.x,spot.y]);
- player.s.dash={ms:1000}; player.speed=500;
- player.going_x=spot.x;
- player.going_y=spot.y;
- start_moving_element(player);
- player.to_resend="u+cid";
- player.socket.emit("eval",{code:"ui_move("+spot.x+","+spot.y+")"});
+ player.hp = min(player.hp, player.max_hp);
+ player.mp = min(player.mp, player.max_mp);
+ if (def.cooldown) {
+ timeout = def.cooldown;
}
+ player.last.potion = future_ms(timeout);
+ if (!xp) {
+ to_update = "u+cid+reopen+nc";
+ }
+ socket.emit("eval", { code: "pot_timeout(" + (timeout_ui || timeout) + ")" });
+ } else if (!data.consume) {
+ // console.log(data);
+ var slot = data.slot || def.type;
+ var existing;
+ var comp = can_equip_item(player, def, slot);
+ if (comp == "no") {
+ resend(player, "u+cid+reopen"); // if you drop something on an invalid slot, it stays there for a bit otherwise [29/08/22]
+ return fail_response("cant_equip");
+ }
+ slot = comp;
+ existing = player.slots[slot];
+ player.slots[slot] = player.items[data.num];
+ player.cslots[slot] = cache_item(player.slots[slot]);
+ if (existing && existing.b) {
+ existing = null;
+ }
+ player.items[data.num] = existing;
+ player.citems[data.num] = cache_item(existing);
+ player.s.penalty_cd = { ms: min(((player.s.penalty_cd && player.s.penalty_cd.ms) || 0) + 120, 120000) };
+ resolve.slot = slot;
+ } else {
+ return fail_response("cant_consume");
}
- }
- if(data.name=="hardshell" || data.name=="power" || data.name=="xpower")
- {
- consume_mp(player,G.skills[data.name].mp);
- player.s[G.skills[data.name].condition]={ms:G.skills[data.name].duration||G.conditions[G.skills[data.name].condition].duration};
- player.to_resend="u+cid";
- }
- if(data.name=="mshield")
- {
- consume_mp(player,G.skills[data.name].mp);
- if(player.s[G.skills[data.name].condition]) delete player.s[G.skills[data.name].condition];
- else player.s[G.skills[data.name].condition]={ms:999999999};
- player.to_resend="u+cid";
- }
- if(data.name=="mcourage" || data.name=="mfrenzy" || data.name=="massproduction" || data.name=="massproductionpp")
- {
- consume_mp(player,G.skills[data.name].mp);
- player.s[G.skills[data.name].condition]={ms:G.conditions[G.skills[data.name].condition].duration};
- xy_emit(player,"ui",{type:data.name,name:player.name});
- player.to_resend="u+cid";
- }
- if(data.name=="throw")
- {
- if(distance(player,target,true)>G.skills[data.name].range+player.level)
- return socket.emit("game_response",{response:"too_far",place:data.name,failed:true});
- if(target.s.invincible || target.immune)
- return socket.emit("game_response",{response:"target_invincible",place:data.name,failed:true});
- if(!player.items[data.num])
- return socket.emit("game_response",{response:"skill_no_item",place:data.name,failed:true});
- var item=player.items[data.num],r="u+cid",damage=0;
- if(item.name=="placeholder")
- return socket.emit("game_response",{response:"item_placeholder",place:data.name,failed:true});
- if(item.l)
- return socket.emit("game_response",{response:"item_locked",place:data.name,failed:true});
- if(item.b)
- return socket.emit("game_response",{response:"item_blocked",place:data.name,failed:true});
- var prop=calculate_item_properties(item),negative=false;
- if(in_arr(item.name,G.skills.throw.negative)) negative=true;
- G.skills.throw.nprop.forEach(function(p){if(prop[p]) negative=true;});
- if(negative && target.is_player && !is_in_pvp(player))
- return socket.emit("game_response",{response:"not_in_pvp",place:data.name,failed:true});
- consume_one(player,data.num);
- if(item.name=="essenceoffire") add_condition(target,"eburn",{from:player});
- else if(item.name=="essenceoflife") add_condition(target,"eheal",{from:player});
- else if(prop.attack) damage=round(Math.random()*prop.attack*15);
- else if(prop.armor) damage=round(Math.random()*prop.armor*24);
- if(damage)
- {
- if(target["1hp"]) damage=1;
- target.hp=max(1,target.hp-damage);
- disappearing_text({},target,"-"+damage,{color:"red",xy:1});
+
+ if (to_update) {
+ resend(player, to_update);
}
- consume_mp(player,G.skills[data.name].mp,target);
- xy_emit(player,"ui",{type:"throw",from:player.name,to:target.id,item:item.name});
- player.to_resend="u+cid+reopen";
- if(target.is_player) resend(target,r);
- else target.u=true,target.cid++;
- }
- if(data.name=="phaseout")
- {
- if(!player.items[data.num] || player.items[data.num].name!="shadowstone")
- return socket.emit("game_response",{response:"skill_cant_item",place:data.name,failed:true});
- consume_one(player,data.num);
- consume_mp(player,G.skills[data.name].mp);
- player.s.phasedout={ms:G.conditions.phasedout.duration};
- player.to_resend="u+cid+reopen";
- }
- if(data.name=="pcoat")
- {
- if(!player.items[data.num] || player.items[data.num].name!="poison")
- return socket.emit("game_response",{response:"skill_cant_item",place:data.name,failed:true});
- consume_one(player,data.num);
- consume_mp(player,G.skills[data.name].mp);
- player.s.poisonous={ms:G.skills.pcoat.cooldown};
- player.to_resend="u+cid+reopen";
- }
- if(data.name=="curse") //#TODO: last_curse variable + check for multiple curses
- {
- var attack=commence_attack(player,target,"curse");
- if(!attack.failed) resolve=attack,add_pdps(player,null,player.attack/2);
- else reject=attack,cool=false;
- }
- if(data.name=="snowball")
- {
- if(distance(player,target,true)>G.skills[data.name].range)
- return socket.emit("game_response",{response:"too_far",place:data.name,failed:true});
- var found=false;
- for(var i=player.isize-1;i>=0;i--)
- {
- if(player.items[i] && player.items[i].name=="snowball")
- {
- consume_one(player,i);
- found=true;
+ success_response(resolve_type, resolve);
+ });
+ socket.on("misc_npc", function (data) {
+ var player = players[socket.id];
+ if (!player) {
+ return;
+ }
+ var npc = players[data.npc];
+ if (!npc || !npc.npc) {
+ return;
+ }
+ if (simple_distance(player, npc) > 1000) {
+ return socket.emit("game_response", "distance");
+ }
+ if (data.npc == NPC_prefix + "Marven" && npc.misc == true) {
+ server_log("Here!");
+ }
+ });
+ socket.on("unequip", function (data) {
+ var player = players[socket.id];
+ if (!player || !data.slot || !player.slots[data.slot]) {
+ return fail_response("invalid");
+ }
+ if (data.slot == "elixir") {
+ return fail_response("cant");
+ }
+ var item = player.slots[data.slot];
+ var done = false;
+ if (in_arr(data.slot, trade_slots) && item.giveaway !== undefined) {
+ return fail_response("giveaway");
+ }
+ // an oversight allowed .giveaway items to be equipped, so now they can be unequipped from regular slots [04/11/21]
+ if (player.esize <= 0 && !item.b) {
+ return fail_response("no_space");
+ }
+ player.slots[data.slot] = null;
+ player.cslots[data.slot] = null;
+ player.c = {};
+ if (!item.b) {
+ add_item(player, item, { announce: false });
+ }
+ resend(player, "reopen+u+cid");
+ success_response("data");
+ });
+ socket.on("secondhands", function (data) {
+ var player = players[socket.id];
+ if (!player) {
+ return;
+ }
+ if (simple_distance(G.maps.main.ref.secondhands, player) > 500) {
+ return socket.emit("game_response", "distance");
+ }
+ socket.emit("secondhands", csold);
+ });
+ socket.on("lostandfound", function (data) {
+ var player = players[socket.id];
+ if (!player) {
+ return;
+ }
+ if (data == "info") {
+ return socket.emit("game_response", { response: "lostandfound_info", gold: S.gold });
+ }
+ if (!player.donation) {
+ return socket.emit("game_response", "lostandfound_donate");
+ }
+ if (simple_distance(G.maps.woffice.ref.lostandfound, player) > 500) {
+ return socket.emit("game_response", "distance");
+ }
+ socket.emit("lostandfound", cfound);
+ });
+ socket.on("split", function (data) {
+ var player = players[socket.id];
+ var num = data.num;
+ var item = player.items[data.num];
+ var quantity = min(max(parseInt(data.quantity) || 0, 1), (item && item.q) || 1);
+ if (!item) {
+ return fail_response("no_item");
+ }
+ if (!G.items[item.name].s) {
+ return fail_response("invalid");
+ }
+ quantity = min(quantity, G.items[item.name].s || 1);
+ if (!player.esize) {
+ return fail_response("cant_space");
+ }
+ if (item.q == quantity) {
+ return success_response();
+ }
+ if (item.name == "placeholder") {
+ return fail_response("item_placeholder");
+ }
+ if (item.l) {
+ return fail_response("item_locked");
+ }
+ if (item.b) {
+ return fail_response("item_blocked");
+ }
+
+ consume(player, data.num, quantity);
+
+ var new_item = cache_item(item);
+ if (item.q) {
+ new_item.q = quantity;
+ }
+
+ for (var i = 0; i < player.isize; i++) {
+ if (!player.items[i]) {
+ player.items[i] = new_item;
+ player.citems[i] = cache_item(new_item);
break;
}
}
- if(!found)
- return socket.emit("game_response",{response:"skill_cant_item",place:data.name,failed:true});
- var attack=commence_attack(player,target,"snowball");
- if(!attack.failed) resolve=attack;
- else reject=attack,cool=false;
- }
- if(data.name=="entangle" || data.name=="tangle")
- {
- if(data.name=="entangle")
- if(!player.items[data.num] || player.items[data.num].name!="essenceofnature")
- return socket.emit("game_response",{response:"skill_cant_item",place:data.name,failed:true});
- if(target.s.invincible)
- return socket.emit("game_response",{response:"target_invincible",place:data.name,failed:true});
- if(distance(player,target,true)>G.skills[data.name].range)
- return socket.emit("game_response",{response:"too_far",place:data.name,failed:true});
- add_condition(target,"tangled",{ms:G.skills['entangle'].duration});
- target.abs=true;
- target.moving=false;
- xy_emit(player,"ui",{type:"entangle",from:player.name,to:target.id});
- consume_mp(player,G.skills[data.name].mp,target);
- add_pdps(player,target,4000);
- if(data.name=="entangle") consume_one(player,data.num);
- player.to_resend="u+cid+reopen";
- if(target.is_monster)
- {
- target.u=true; target.cid++; ccms(target);
+ resend(player, "reopen");
+ success_response();
+ });
+ socket.on("sell", function (data) {
+ var player = players[socket.id];
+ var num = data.num;
+ var item = player.items[data.num];
+ var quantity = min(max(parseInt(data.quantity) || 0, 1), (item && item.q) || 1);
+ var can_reach = false;
+ if (!player || player.user) {
+ return fail_response("cant_in_bank");
}
- else
- resend(target,"u+cid");
- }
- if(data.name=="4fingers")
- {
- if(target.s.invincible)
- return socket.emit("game_response",{response:"target_invincible",place:data.name,failed:true});
- if(distance(player,target,true)>G.skills[data.name].range)
- return socket.emit("game_response",{response:"too_far",place:data.name,failed:true});
- if(!is_in_pvp(player) && !is_same(player,target,1))
- return socket.emit("game_response",{response:"non_friendly_target",place:data.name,failed:true});
- add_condition(target,"fingered",{ms:G.skills['4fingers'].duration});
- add_condition(target,"stunned",{duration:G.skills['4fingers'].duration-2000});
- xy_emit(player,"ui",{type:"4fingers",from:player.name,to:target.name});
- consume_mp(player,G.skills[data.name].mp,target);
- add_pdps(player,target,1000);
- resend(target,"u+cid");
- player.to_resend="u+cid";
- }
- if(["quickpunch","quickstab","smash","mentalburst","purify","taunt","supershot","zapperzap","burst","piercingshot"].includes(data.name))
- {
- var attack=commence_attack(player,target,data.name);
- if(!attack.failed) resolve=attack;
- else reject=attack,cool=false;
- }
- if(data.name=="poisonarrow")
- {
- if(!player.items[data.num] || player.items[data.num].name!="poison")
- return socket.emit("game_response",{response:"skill_cant_item",place:data.name,failed:true});
-
- var attack=commence_attack(player,target,data.name);
- if(!attack.failed) resolve=attack;
- else reject=attack,cool=false;
-
- consume_one(player,data.num);
- player.to_resend="reopen";
- }
- if(data.name=="revive")
- {
- if(!player.items[data.num] || player.items[data.num].name!="essenceoflife")
- return socket.emit("game_response",{response:"skill_cant_item",place:data.name,failed:true});
- if(distance(player,target,true)>G.skills[data.name].range)
- return socket.emit("game_response",{response:"too_far",place:data.name,failed:true});
- if(!target.rip)
- return socket.emit("game_response",{response:"target_alive",place:data.name,failed:true});
-
- consume_one(player,data.num);
- player.to_resend="reopen";
- if(target.party==player.party) add_pdps(player,target,target.pdps/5);
-
- if(target.hp!=target.max_hp)
- {
- reject={response:"data",place:data.name,reason:"hp"}
- player.socket.emit("game_response",{response:"revive_failed",id:data.id});
+ if (!item) {
+ return fail_response("no_item");
}
- else
- {
- target.c.revival={ms:8000,f:player.name};
+ if (item.name == "placeholder") {
+ return fail_response("item_placeholder");
}
- resend(target,"u+cid");
- }
- if(data.name=="cburst")
- {
- var hit={},times=0,attack=null,c_resolve=null;
- consume_mp(player,G.skills[data.name].mp);
- player.first_burst=true;
- player.halt=true;
- if(is_array(data.targets)) data.targets.forEach(function(t){
- // console.log(id);
- var id=t[0],mp=max(0,parseInt(t[1])||0);
- if(player.mp<20 || times>16 || !mp) return; times+=1;
- var target=instances[player.in].monsters[id]; if(!target) target=instances[player.in].players[id]; if(!target || is_invinc(target) || target.name==player.name) return;
- if(hit[id]) return;
- hit[id]=true;
- player.next_mp=mp;
- attack=commence_attack(player,target,"cburst");
- if(!attack || !attack.projectile) return;
- if(!c_resolve)
- {
- c_resolve=attack;
- attack.pids=[attack.pid];
- attack.targets=[attack.target];
- }
- else
- {
- c_resolve.pids.push(attack.pid);
- c_resolve.targets.push(attack.target);
+ if (item.l) {
+ return fail_response("item_locked");
+ }
+ if (item.b) {
+ return fail_response("item_blocked");
+ }
+ (G.maps[player.map].merchants || []).forEach(function (m) {
+ if (simple_distance(player, m) < B.sell_dist) {
+ can_reach = m;
}
});
- player.halt=false;
- player.to_resend="u+cid";
- if(!c_resolve)
- {
- if(attack) reject=attack;
- disappearing_text(player.socket,player,"NO HITS");
+ if (player.computer && !can_reach) {
+ can_reach = G.maps.main.merchants[0];
}
- else resolve=c_resolve;
- }
- if(data.name=="partyheal")
- {
- var targets=[player],attack=null,hits=0;
- if(parties[player.party])
- {
- targets=[];
- parties[player.party].forEach(function(name){
- var current=players[name_to_id[name]];
- targets.push(current);
+ if (!can_reach) {
+ return fail_response("distance");
+ }
+ can_reach.name = player.name;
+ var value = calculate_item_value(item);
+ consume(player, data.num, quantity);
+ player.gold += value * quantity;
+ var new_item = cache_item(item);
+ if (item.q) {
+ new_item.q = quantity;
+ }
+ xy_emit(can_reach, "ui", {
+ type: "-$",
+ id: can_reach.id,
+ name: player.name,
+ item: new_item,
+ num: num,
+ event: "sell",
+ });
+ resend(player, "reopen+nc+inv");
+ success_response("gold_received", { gold: value * quantity, item: new_item, cevent: "sell" });
+ secondhands_logic(item, quantity); // In the end, so if this fails, the "sell" still succeeds - otherwise it could cause a infinite gold loophole [10/07/18]
+ });
+ socket.on("buy_shells", function (data) {
+ return socket.emit("game_log", "No longer possible");
+ var player = players[socket.id];
+ if (!player || player.user || gameplay == "hardcore" || gameplay == "test") {
+ return game_response("cant_in_bank");
+ }
+ var gold = parseInt(data.gold) || 0;
+ if (gold < 1000000 || gold > player.gold) {
+ return socket.emit("game_response", "not_enough_gold");
+ }
+ var shells = Math.floor(gold / G.multipliers.shells_to_gold);
+ player.gold -= gold;
+ socket.emit("game_log", "Gave " + to_pretty_num(gold) + " gold");
+ appengine_call(
+ "bill_user",
+ { auth: player.auth, amount: -shells, reason: "buy_shells", name: player.name },
+ function (result) {
+ server_log("buy_with_cash: " + JSON.stringify(result));
+ if (result.failed || !result.done) {
+ socket.emit("game_log", "Purchase failed");
+ return;
+ }
+ player.cash = result.cash;
+ socket.emit("game_log", "Received " + to_pretty_num(shells) + " shells");
+
+ resend(player, "reopen+nc");
+ },
+ );
+ resend(player, "reopen+nc");
+ });
+ socket.on("buy_with_cash", function (data) {
+ var player = players[socket.id];
+ var name = data.name;
+ var def = G.items[data.name];
+ var quantity = min(max(parseInt(data.quantity) || 0, 1), (def && def.s) || 9999);
+ if (!player || player.user || gameplay == "hardcore" || gameplay == "test") {
+ return fail_response("cant_in_bank");
+ }
+ var cost = def.cash * quantity;
+ if (!def.cash || def.ignore) {
+ return fail_response("invalid");
+ }
+ if (def.p2w) {
+ return fail_response("invalid");
+ }
+ if (!def.s) {
+ quantity = 1;
+ }
+ if (!can_add_item(player, create_new_item(name, quantity))) {
+ return fail_response("no_space");
+ }
+ appengine_call(
+ "bill_user",
+ { auth: player.auth, amount: cost, reason: data.name, name: player.name },
+ function (result) {
+ server_log("buy_with_cash: " + JSON.stringify(result));
+ if (result.failed || !result.done) {
+ socket.emit("game_log", "Purchase failed");
+ return;
+ }
+ player.cash = result.cash;
+ var new_item = create_new_item(name, quantity);
+ var done = false;
+ add_item(player, new_item, { announce: false });
+ socket.emit("game_log", "Spent " + to_pretty_num(cost) + " shells");
+
+ resend(player, "reopen+nc+inv");
+ },
+ );
+ success_response({ success: false, in_progress: true });
+ });
+ socket.on("sbuy", function (data) {
+ var player = players[socket.id];
+ var done = false;
+ var npc = G.maps.main.ref.secondhands;
+ var c = S.sold;
+ var cc = csold;
+ var e = "+$p";
+ var ev = "secondhands";
+ var mult = 2;
+ var src = "scnd";
+ if (data.f) {
+ npc = G.maps.woffice.ref.lostandfound;
+ c = S.found;
+ cc = cfound;
+ e = "+$f";
+ ev = "lostandfound";
+ mult = 4;
+ src = "lost";
+ }
+ if (!player || player.user) {
+ return game_response("cant_in_bank");
+ }
+ if (player.s.hopsickness && ev == "lostandfound") {
+ return fail_response("cant_when_sick", { goblin: true });
+ }
+ if (simple_distance(npc, player) > 500) {
+ return socket.emit("game_response", "distance");
+ }
+ for (var i = 0; i < c.length; i++) {
+ if (c[i].rid == data.rid) {
+ if (mult == 2 && G.items[c[i].name].cash) {
+ mult = 3;
+ }
+ var gold = calculate_item_value(c[i]) * mult * (c[i].q || 1);
+ var item = c[i];
+ if (!can_add_item(player, c[i])) {
+ return disappearing_text(socket, player, "NO SPACE");
+ }
+ if (gold > player.gold) {
+ return socket.emit("game_response", "buy_cost");
+ }
+ player.gold -= gold;
+ item.src = src;
+ add_item(player, c[i], { announce: false });
+ c.splice(i, 1);
+ cc.splice(i, 1);
+ socket.emit("game_log", "Spent " + to_pretty_num(gold) + " gold");
+ resend(player, "reopen+nc+inv");
+ socket.emit(ev, cc);
+ done = true;
+ xy_emit(npc, "ui", { type: e, id: npc.id, name: player.name, item: cache_item(item, 1) });
+ break;
+ }
+ }
+ if (!done) {
+ return socket.emit("game_log", "Item gone");
+ }
+ });
+ socket.on("buy", function (data) {
+ var player = players[socket.id];
+ var can_reach = false;
+ if (!player || player.user) {
+ return fail_response("cant_in_bank");
+ }
+ var name = data.name;
+ var quantity = min(max(parseInt(data.quantity) || 0, 1), (G.items[name] && G.items[name].s) || 9999);
+ var cost = 0;
+ var added = false;
+ var done = false;
+ if (!can_buy[name] && gameplay != "test") {
+ return fail_response("buy_cant_npc");
+ }
+ if (!can_add_item(player, create_new_item(name, quantity))) {
+ return fail_response("buy_cant_space");
+ }
+ (G.maps[player.map].items[name] || []).forEach(function (l) {
+ if (simple_distance(player, l) < B.sell_dist) {
+ can_reach = l;
+ }
+ });
+ if (player.computer && !can_reach) {
+ can_reach = G.maps.main.merchants[0];
+ }
+ if (!can_reach) {
+ return fail_response("distance");
+ }
+ can_reach.name = player.name;
+ var def = G.items[name];
+ if (!def.s) {
+ quantity = 1;
+ }
+ cost = quantity * G.items[name].g;
+ if (G.items[name].p2w) {
+ cost *= G.inflation;
+ }
+ if (player.gold < cost) {
+ return fail_response("buy_cost");
+ }
+ var new_item = create_new_item(name, quantity);
+ player.gold -= cost;
+ var num = add_item(player, new_item, { announce: false });
+ xy_emit(can_reach, "ui", {
+ type: "+$",
+ id: can_reach.id,
+ name: player.name,
+ item: cache_item(new_item),
+ event: "buy",
+ });
+
+ resend(player, "reopen+nc+inv");
+ success_response("buy_success", { cost: cost, num: num, name: name, q: quantity, cevent: "buy" });
+ });
+ socket.on("send", function (data) {
+ var player = players[socket.id];
+ var receiver = players[name_to_id[data.name || ""]];
+ var num;
+ var s_item;
+ if (!player || player.user) {
+ return fail_response("cant_in_bank");
+ }
+ if (!receiver || receiver.user) {
+ return fail_response("receiver_unavailable");
+ }
+ if (distance(receiver, player, true) > B.dist || receiver.map != player.map) {
+ return fail_response("distance");
+ }
+ if (data.num !== undefined) {
+ data.num = max(0, parseInt(data.num) || 0);
+ var item = player.items[data.num];
+ if (!item) {
+ return fail_response("send_no_item");
+ }
+ if (item.name == "placeholder") {
+ return fail_response("item_placeholder");
+ }
+ if (item.l || (item.acl && receiver.owner != player.owner)) {
+ return fail_response("item_locked");
+ }
+ if (item.b) {
+ return fail_response("item_blocked");
+ }
+ data.q = min(item.q || 1, max(1, parseInt(data.q || 1) || 1));
+ if (!data.q) {
+ return fail_response("no_item");
+ }
+ if (!can_add_item(receiver, create_new_item(item.name, data.q))) {
+ return fail_response("send_no_space");
+ }
+ if ((item.q || 1) == data.q) {
+ player.items[data.num] = player.citems[data.num] = null;
+ player.esize++;
+ } else {
+ player.items[data.num].q -= data.q;
+ player.citems[data.num] = cache_item(player.items[data.num]);
+ }
+
+ if (item.q) {
+ s_item = create_new_item(item.name, data.q);
+ if (item.v) {
+ s_item.v = item.v;
+ }
+ if (item.data) {
+ s_item.data = item.data;
+ }
+ num = add_item(receiver, s_item, { announce: false });
+ } else {
+ s_item = item;
+ num = add_item(receiver, item, { announce: false });
+ }
+
+ if (receiver.owner != player.owner) {
+ item.src = "snd";
+ }
+
+ add_to_history(player, { name: "item", to: receiver.name, item: item.name, q: data.q, level: item.level });
+ add_to_history(receiver, { name: "item", from: player.name, item: item.name, q: data.q, level: item.level });
+
+ xy_emit(player, "ui", {
+ type: "item_sent",
+ receiver: receiver.name,
+ sender: player.name,
+ item: cache_item(s_item, null, { q: data.q }),
+ num: num,
+ fnum: data.num,
+ event: true,
+ });
+
+ resend(player, "reopen+nc+inv");
+ resend(receiver, "reopen+nc+inv");
+ receiver.socket.emit("game_response", {
+ response: "item_received",
+ name: player.name,
+ item: item.name,
+ q: data.q,
+ num: num,
+ cevent: true,
+ });
+ player.socket.emit("game_response", {
+ response: "item_sent",
+ name: receiver.name,
+ item: item.name,
+ q: data.q,
+ num: data.num,
+ cevent: true,
+ place: "send",
+ });
+ } else if (data.gold !== undefined) {
+ data.gold = min(player.gold, max(1, parseInt(data.gold || 1) || 1)) || player.gold;
+ if (!data.gold) {
+ return fail_response("invalid");
+ }
+ player.gold -= data.gold;
+ if (!is_same(player, receiver) && data.gold != 1) {
+ data.gold = parseInt(data.gold * 0.975);
+ }
+ receiver.gold += data.gold;
+
+ add_to_history(player, { name: "gold", to: receiver.name, amount: data.gold });
+ add_to_history(receiver, { name: "gold", from: player.name, amount: data.gold });
+
+ xy_emit(player, "ui", {
+ type: "gold_sent",
+ receiver: receiver.name,
+ sender: player.name,
+ gold: data.gold,
+ event: true,
+ });
+
+ resend(player, "reopen+nc+inv");
+ resend(receiver, "reopen+nc+inv");
+ receiver.socket.emit("game_response", {
+ response: "gold_received",
+ name: player.name,
+ gold: data.gold,
+ cevent: true,
+ });
+ player.socket.emit("game_response", {
+ response: "gold_sent",
+ name: receiver.name,
+ gold: data.gold,
+ cevent: true,
+ place: "send",
+ });
+ } else if (data.cx !== undefined) {
+ var cxl = map_cx(player);
+ var count = all_cx(player, 1);
+ if (!(cxl[data.cx] && player.p.acx[cxl[data.cx]] && count[data.cx] > 0)) {
+ return fail_response("send_no_cx");
+ }
+ // count[cxl[data.cx]] before [28/01/22]
+ if (receiver.owner != player.owner) {
+ return fail_response("send_diff_owner");
+ }
+ player.p.acx[cxl[data.cx]] -= 1;
+ if (!player.p.acx[cxl[data.cx]]) {
+ delete player.p.acx[cxl[data.cx]];
+ }
+ receiver.p.acx[cxl[data.cx]] = (receiver.p.acx[cxl[data.cx]] || 0) + 1;
+
+ xy_emit(player, "ui", {
+ type: "cx_sent",
+ receiver: receiver.name,
+ sender: player.name,
+ cx: data.cx,
+ event: true,
+ });
+
+ receiver.socket.emit("game_response", {
+ response: "cx_received",
+ name: player.name,
+ cx: data.cx,
+ acx: receiver.p.acx,
+ cevent: true,
+ });
+ player.socket.emit("game_response", {
+ response: "cx_sent",
+ name: receiver.name,
+ cx: data.cx,
+ acx: player.p.acx,
+ cevent: true,
+ place: "send",
});
}
- targets.forEach(function(target){
- attack=commence_attack(player,target,"partyheal");
- if(!attack.failed) hits=true;
+ });
+ socket.on("donate", function (data) {
+ var player = players[socket.id];
+ var XPX = 3.2;
+ if (!player || player.user) {
+ return game_response("cant_in_bank");
+ }
+ var gold = max(1, min(parseInt(data.gold) || 0, 1000000000));
+ if (gold > player.gold) {
+ return socket.emit("game_response", "gold_not_enough");
+ }
+ if (gold >= 1000000) {
+ response = "thx";
+ player.donation = true;
+ } else if (gold < 100000) {
+ response = "low";
+ } else {
+ add_item(player, "gum");
+ response = "gum";
+ }
+ if (S.gold < 500000000) {
+ XPX = 4.8;
+ } else if (S.gold <= 1000000000) {
+ XPX = 4;
+ }
+ player.gold -= gold;
+ S.gold += gold;
+ if (gold >= 5000000) {
+ lstack(S.logs.donate, { name: player.name, gold: gold, xp: XPX });
+ }
+ if (player.type == "merchant") {
+ player.xp += parseInt(gold * XPX);
+ }
+ resend(player, "reopen");
+ socket.emit("game_response", { response: "donate_" + response, gold: gold, xprate: XPX });
+ });
+ socket.on("destroy", function (data) {
+ var player = players[socket.id];
+ var add = "+nc+inv";
+ data.num = max(0, parseInt(data.num) || 0);
+ if (!player.items[data.num]) {
+ return fail_response("no_item");
+ }
+ var item = player.items[data.num];
+ var name = player.items[data.num].name;
+ data.q = min(max(parseInt(data.q) || 0, 1), (item && item.q) || 1);
+ if (item.name == "placeholder") {
+ return fail_response("item_placeholder");
+ }
+ if (item.l) {
+ return fail_response("item_locked");
+ }
+ if (item.b) {
+ return fail_response("item_blocked");
+ }
+ if (item.level != 13) {
+ consume(player, data.num, data.q);
+ //player.items[data.num]=player.citems[data.num]=null;
+ }
+ if (data.statue) {
+ if (item.name == "shadowstone") {
+ add = "+u+cid";
+ player.s.invis = { ms: 99999 };
+ }
+ if (G.items[item.name].upgrade && Math.random() < 1.0 / ((gameplay == "hardcore" && 10000) || 1000000)) {
+ add = "+u+cid";
+ item.level = 13;
+ player.items[data.num] = item;
+ player.citems[data.num] = cache_item(player.items[data.num]);
+ }
+ xy_emit(G.maps.spookytown.ref.poof, "upgrade", { type: "poof", success: 1 });
+ }
+ resend(player, "reopen" + add);
+ success_response("destroyed", { name: name, place: "destroy", cevent: "destroy" });
+ });
+ socket.on("join_giveaway", function (data) {
+ var player = players[socket.id];
+ var seller = players[id_to_id[data.id]];
+ var num;
+ if (!player || player.user) {
+ return fail_response("cant_in_bank");
+ }
+ if (!in_arr(data.slot, trade_slots)) {
+ return fail_response("invalid");
+ }
+ if (!seller || seller.npc || is_invis(seller)) {
+ return fail_response("seller_gone");
+ }
+ if (seller.user) {
+ return fail_response("cant_in_bank");
+ }
+ if (distance(seller, player, true) > B.dist || seller.map != player.map) {
+ return fail_response("distance");
+ }
+ if (seller.id == player.id) {
+ return fail_response("hmm");
+ }
+ var item = seller.slots[data.slot];
+ if (!item || (data.rid && item.rid != data.rid)) {
+ return fail_response("item_gone");
+ }
+ if (!item.giveaway) {
+ return fail_response("sneaky");
+ }
+ if (!player.auth_id) {
+ return fail_response("need_auth");
+ }
+ //if(item.list.includes(player.name)) return socket.emit("game_log","Already joined!");
+ //if(player.type!="merchant") return socket.emit("game_log","Only merchants can join giveaways!");
+
+ //item.list.push(player.name);
+
+ item.registry = item.registry || {};
+ item.registry[player.auth_id] = player.name;
+ item.list = Object.values(item.registry);
+
+ socket.emit("game_log", "Joined the giveaway!");
+ seller.socket.emit("game_response", {
+ response: "giveaway_join",
+ name: player.name,
+ slot: data.slot,
+ cevent: true,
});
- if(!hits) reject=attack;
- }
- if(data.name=="selfheal")
- {
- var attack=commence_attack(player,player,data.name);
- if(!attack.failed) resolve=attack;
- else reject=attack,cool=false;
- }
- if(data.name=="darkblessing" || data.name=="warcry")
- {
- consume_mp(player,G.skills[data.name].mp);
- for(var id in instances[player.in].players)
- {
- var target=instances[player.in].players[id];
- if(!target.npc && distance(player,target,true) B.dist) {
+ return fail_response("distance");
+ }
+ if (buyer.id == player.id) {
+ return fail_response("hmm");
+ }
+ var item = buyer.slots[data.slot];
+ if (!item || (data.rid && item.rid != data.rid)) {
+ return fail_response("item_gone");
+ }
+ if (item.name == "placeholder") {
+ return fail_response("item_placeholder");
+ }
+ if (!item.b && !B.rbugs) {
+ return fail_response("sneaky");
+ }
+ if ((item.q || 1) < data.q) {
+ return fail_response("dont_have_enough");
+ }
+ if (item.price * data.q > buyer.gold) {
+ return fail_response("buyer_gold");
+ }
+ for (var i = 0; i < player.isize; i++) {
+ if (
+ player.items[i] &&
+ player.items[i].name == item.name &&
+ (player.items[i].q || 1) >= data.q &&
+ player.items[i].level == item.level &&
+ !player.items[i].l
+ ) {
+ actual = player.items[i];
+ num = i;
+ break;
}
}
- xy_emit(player,"ui",{type:data.name});
- }
- if(data.name=="3shot" || data.name=="5shot")
- {
- player.halt=true;
- var times=0,hit={},reftarget=null,targets=3,attack=null,c_resolve=null;
- if(data.name=="5shot") targets=5;
- //console.log(data.ids);
- if(is_array(data.ids))
- data.ids.forEach(function(id){
- if(times>=targets) return; times+=1;
- var target=instances[player.in].monsters[id]; if(!target) target=instances[player.in].players[id];
- if(!target || is_invinc(target) || target.name==player.name)
- {
- attack={failed:true,place:data.name,reason:"no_target"};
+ if (!actual) {
+ return fail_response("no_item");
+ }
+ if (actual.b) {
+ return fail_response("item_blocked");
+ }
+ if (!can_add_item(buyer, create_new_item(item.name, data.q))) {
+ return fail_response("trade_bspace");
+ }
+ var price = item.price * data.q;
+ player.gold += round(price * (1 - player.tax));
+ add_to_trade_history(player, "sell", buyer.name, cache_item(actual, true, { q: data.q }), price);
+ buyer.gold -= price;
+ add_to_trade_history(buyer, "buy", player.name, cache_item(actual, true, { q: data.q }), price);
+ S.gold += price - round(price * (1 - player.tax));
+
+ if ((item.q || 1) == data.q) {
+ buyer.slots[data.slot] = buyer.cslots[data.slot] = null;
+ } else {
+ buyer.slots[data.slot].q -= data.q;
+ buyer.cslots[data.slot] = cache_item(buyer.slots[data.slot], true);
+ }
+
+ // up to here
+
+ if ((player.items[i].q || 1) == data.q) {
+ player.items[num] = player.citems[num] = null;
+ } else {
+ player.items[num].q -= data.q;
+ player.citems[num] = cache_item(player.items[num]);
+ }
+
+ if (G.items[item.name].s) {
+ bnum = add_item(buyer, create_new_item(item.name, data.q), { announce: false });
+ } else {
+ bnum = add_item(buyer, actual, { announce: false });
+ }
+
+ if (player.type == "merchant") {
+ merchant_xp_logic(player, buyer, price, price - round(price * (1 - player.tax)));
+ }
+ if (buyer.type == "merchant") {
+ merchant_xp_logic(buyer, player, price, price - round(price * (1 - buyer.tax)));
+ }
+
+ socket.emit(
+ "game_log",
+ "Sales tax " + to_pretty_num(price - round(price * (1 - player.tax))) + " gold [" + player.tax * 100 + "%]",
+ );
+ socket.emit("game_log", "Received " + to_pretty_num(round(price * (1 - player.tax))) + " gold");
+ buyer.socket.emit("game_log", "Spent " + to_pretty_num(price) + " gold");
+
+ xy_emit(buyer, "ui", {
+ type: "+$$",
+ seller: player.name,
+ buyer: buyer.name,
+ item: cache_item(actual, true, { q: data.q, price: item.price }),
+ slot: data.slot,
+ num: bnum,
+ snum: num,
+ });
+
+ resend(player, "reopen");
+ resend(buyer, "reopen+u+cid");
+ success_response({});
+ });
+ socket.on("trade_buy", function (data) {
+ var player = players[socket.id];
+ var seller = players[id_to_id[data.id]];
+ var num;
+ data.q = max(1, parseInt(data.q || 1) || 1);
+ if (!player || player.user) {
+ return fail_response("cant_in_bank");
+ }
+ if (!in_arr(data.slot, trade_slots)) {
+ return fail_response("invalid");
+ }
+ if (!seller || seller.npc || is_invis(seller)) {
+ return fail_response("seller_gone");
+ }
+ if (seller.user) {
+ return fail_response("cant_in_bank");
+ }
+ if (distance(seller, player, true) > B.dist || seller.map != player.map) {
+ return fail_response("distance");
+ }
+ if (seller.id == player.id) {
+ return fail_response("hmm");
+ }
+ var item = seller.slots[data.slot];
+ if (!item || (data.rid && item.rid != data.rid)) {
+ return fail_response("item_gone");
+ }
+ if (item.name == "placeholder") {
+ return fail_response("item_placeholder");
+ }
+ if (item.b || item.giveaway) {
+ return fail_response("sneaky");
+ }
+ if (item.price * data.q > player.gold) {
+ return fail_response("gold_not_enough");
+ }
+ if ((item.q || 1) < data.q) {
+ return fail_response("insufficient_q");
+ }
+ if (!can_add_item(player, create_new_item(item.name, data.q))) {
+ return fail_response("no_space");
+ }
+ var price = item.price * data.q;
+ player.gold -= price;
+ add_to_trade_history(player, "buy", seller.name, cache_item(seller.slots[data.slot], true, { q: data.q }), price);
+ seller.gold += round(price * (1 - seller.tax));
+ add_to_trade_history(
+ seller,
+ "sell",
+ player.name,
+ cache_item(seller.slots[data.slot], true, { q: data.q }),
+ price,
+ );
+ S.gold += price - round(price * (1 - seller.tax));
+
+ if ((item.q || 1) == data.q) {
+ seller.slots[data.slot] = seller.cslots[data.slot] = null;
+ } else {
+ seller.slots[data.slot].q -= data.q;
+ seller.cslots[data.slot] = cache_item(seller.slots[data.slot], true);
+ }
+
+ if (item.q) {
+ num = add_item(player, create_new_item(item.name, data.q), { announce: false });
+ } else {
+ num = add_item(player, item, { announce: false });
+ }
+
+ if (seller.owner != player.owner) {
+ item.src = "tb";
+ }
+
+ if (player.type == "merchant") {
+ merchant_xp_logic(player, seller, price, price - round(price * (1 - player.tax)));
+ }
+ if (seller.type == "merchant") {
+ merchant_xp_logic(seller, player, price, price - round(price * (1 - seller.tax)));
+ }
+
+ socket.emit("game_log", "Spent " + to_pretty_num(price) + " gold");
+ seller.socket.emit(
+ "game_log",
+ "Sales tax " + to_pretty_num(price - round(price * (1 - seller.tax))) + " gold [" + seller.tax * 100 + "%]",
+ );
+ seller.socket.emit("game_log", "Received " + to_pretty_num(round(price * (1 - seller.tax))) + " gold");
+
+ xy_emit(seller, "ui", {
+ type: "+$$",
+ seller: seller.name,
+ buyer: player.name,
+ item: cache_item(item, true, { q: data.q }),
+ slot: data.slot,
+ num: data.num,
+ });
+
+ resend(player, "reopen");
+ resend(seller, "reopen+u+cid");
+ success_response({});
+ });
+ socket.on("trade_history", function (data) {
+ var player = players[socket.id];
+ if (!player) {
+ return;
+ }
+ server_log("trade_history: " + player.name);
+ socket.emit("trade_history", player.p.trade_history || []);
+ });
+ socket.on("merchant", function (data) {
+ var player = players[socket.id];
+ if (!player) {
+ return;
+ }
+ var initial = player.p.stand;
+ server_log("merchant: " + player.name);
+ if (data.close || player.p.stand) {
+ player.p.stand = false;
+ for (var i = 0; i < player.items.length; i++) {
+ if (player.items[i] && player.items[i].b == "stand") {
+ delete player.items[i].b;
+ }
+ }
+ }
+ if (data.num !== undefined) {
+ var item = player.items[data.num];
+ if (item && G.items[item.name].stand) {
+ player.p.stand = G.items[item.name].stand;
+ item.b = "stand";
+ } else {
+ return fail_response("invalid");
+ }
+ }
+ if (initial != player.p.stand) {
+ // All unneccessary causes of resend's should be patched [03/08/18]
+ reslot_player(player);
+ resend(player, "u+cid");
+ }
+ success_response({});
+ });
+ socket.on("imove", function (data) {
+ var player = players[socket.id];
+ if (!player) {
+ return;
+ }
+ data.a = max(0, parseInt(data.a) || 0);
+ data.b = max(0, parseInt(data.b) || 0);
+ if (data.a == data.b) {
+ return fail_response("invalid");
+ }
+ var a = min(data.a, data.b);
+ var b = max(data.a, data.b);
+ var a_item;
+ if (!(b < player.isize || b < player.items.length)) {
+ return fail_response("invalid");
+ }
+ // while(b>=player.items.length) player.items.push(null); [22/11/16]
+ if (player.items[a] && player.items[a].name == "placeholder") {
+ return fail_response("item_placeholder");
+ }
+ if (player.items[b] && player.items[b].name == "placeholder") {
+ return fail_response("item_placeholder");
+ }
+ if (can_stack(player.items[a], player.items[b])) {
+ player.items[data.a].q = (player.items[a].q || 1) + (player.items[b].q || 1);
+ player.items[data.b] = null;
+ player.esize++;
+ } else {
+ a_item = player.items[a];
+ player.items[a] = player.items[b];
+ player.items[b] = a_item;
+ }
+ player.citems[data.a] = cache_item(player.items[data.a]);
+ player.citems[data.b] = cache_item(player.items[data.b]);
+ resend(player, "reopen+nc+inv");
+ return success_response("data");
+ });
+ socket.on("bank", function (data) {
+ var player = players[socket.id];
+ if (!player) {
+ return;
+ }
+ if (!player.user || player.mounting || player.unmounting) {
+ return fail_response("bank_unavailable");
+ }
+ var success = {};
+ if (data.operation == "withdraw") {
+ var amount = max(0, min(parseInt(data.amount) || 0, player.user.gold));
+ player.user.gold -= amount;
+ player.gold += amount;
+ success = { response: "bank_withdraw", gold: amount, cevent: true };
+ }
+ if (data.operation == "deposit") {
+ var amount = max(0, min(parseInt(data.amount) || 0, player.gold));
+ player.user.gold += amount;
+ player.gold -= amount;
+ success = { response: "bank_store", gold: amount, cevent: true };
+ }
+ if (data.operation == "unlock") {
+ if (!bank_packs[data.pack]) {
+ return fail_response("invalid");
+ }
+ var gold = bank_packs[data.pack][1];
+ var shells = bank_packs[data.pack][2];
+ if (!gold) {
+ return fail_response("gold_not_enough");
+ }
+ if (player.user[data.pack]) {
+ return fail_response("invalid");
+ }
+ if (data.gold) {
+ if (player.gold < gold) {
+ return fail_response("gold_not_enough");
+ }
+ player.gold -= gold;
+ player.user[data.pack] = [];
+ player.cuser[data.pack] = [];
+ success = { response: "bank_new_pack", pack: data.pack, gold: gold, cevent: true };
+ } else if (data.shells) {
+ if (player["unlocking_" + data.pack]) {
+ return fail_response("bank_opi");
+ }
+ player["unlocking_" + data.pack] = true;
+ appengine_call(
+ "bill_user",
+ {
+ auth: player.auth,
+ amount: shells,
+ reason: data.pack,
+ name: player.name,
+ suffix: "/" + player.name + "/" + data.pack,
+ override: true,
+ },
+ function (result) {
+ server_log("buy_with_cash: " + JSON.stringify(result));
+ player["unlocking_" + data.pack] = false;
+ if (result.failed || !result.done) {
+ return socket.emit("game_log", "Purchase failed");
+ }
+ player.cash = result.cash;
+
+ player.user[data.pack] = [];
+ player.cuser[data.pack] = [];
+ game_response("bank_new_pack", { cevent: true, pack: data.pack, shells: shells });
+
+ resend(player, "reopen");
+ },
+ );
+ success = { success: false, in_progress: true };
+ }
+ }
+ if (data.operation == "move") {
+ //within a .itemsN
+ if (!player.user[data.pack] || bank_packs[data.pack][0] != player.map) {
+ return fail_response("invalid");
+ }
+ server_log("storage move " + JSON.stringify(data));
+ data.a = max(0, min(41, parseInt(data.a) || 0));
+ data.b = max(0, min(41, parseInt(data.b) || 0));
+ if (data.a == data.b) {
+ return fail_response("invalid");
+ }
+ if (player.user[data.pack][data.a] && player.user[data.pack][data.a].name == "placeholder") {
+ return fail_response("item_placeholder");
+ }
+ if (player.user[data.pack][data.b] && player.user[data.pack][data.b].name == "placeholder") {
+ return fail_response("item_placeholder");
+ }
+ if (can_stack(player.user[data.pack][data.a], player.user[data.pack][data.b])) {
+ player.user[data.pack][data.b].q =
+ (player.user[data.pack][data.a].q || 1) + (player.user[data.pack][data.b].q || 1);
+ player.user[data.pack][data.a] = null;
+ } else {
+ var temp = player.user[data.pack][data.a];
+ player.user[data.pack][data.a] = player.user[data.pack][data.b];
+ player.user[data.pack][data.b] = temp;
+ }
+ player.cuser[data.pack][data.a] = cache_item(player.user[data.pack][data.a]);
+ player.cuser[data.pack][data.b] = cache_item(player.user[data.pack][data.b]);
+ }
+ if (data.operation == "swap") {
+ //between .items and a .itemsN
+ var operation = "swap";
+ if (!player.user[data.pack] || bank_packs[data.pack][0] != player.map) {
+ return fail_response("invalid");
+ }
+ data.str = parseInt(data.str);
+ data.inv = parseInt(data.inv);
+ if (data.inv == -1 || (!data.inv && data.inv !== 0)) {
+ operation = "pull";
+ for (var i = 0; i < player.isize; i++) {
+ if (!player.items[i]) {
+ data.inv = i;
+ break;
+ }
+ }
+ // if(data.inv==-1) { socket.emit("game_log","Inventory is full"); return; }
+ }
+ if (data.str == -1 || (!data.str && data.str !== 0)) {
+ if (operation == "pull") {
+ return fail_response("invalid");
+ }
+ operation = "store";
+ for (var i = 0; i < 42; i++) {
+ if (!player.user[data.pack][i]) {
+ data.str = i;
+ break;
+ }
+ }
+ // if(data.str==-1) { socket.emit("game_log","Storage is full"); return; }
+ }
+ server_log("storage swap " + JSON.stringify(data));
+ data.str = max(0, min(41, parseInt(data.str) || 0));
+ data.inv = max(0, min(player.isize - 1, parseInt(data.inv) || 0));
+ var bank_item = player.user[data.pack][data.str];
+ var inv_item = player.items[data.inv];
+ if (inv_item && inv_item.name == "placeholder") {
+ return fail_response("item_placeholder");
+ }
+ if (inv_item && inv_item.b) {
+ return fail_response("item_blocked");
+ }
+ if (inv_item) {
+ delete inv_item.m;
+ delete inv_item.v;
+ }
+ if (operation == "swap") {
+ player.user[data.pack][data.str] = inv_item;
+ player.items[data.inv] = bank_item;
+ player.cuser[data.pack][data.str] = cache_item(player.user[data.pack][data.str]);
+ player.citems[data.inv] = cache_item(player.items[data.inv]);
+ } else if (operation == "store" && inv_item) {
+ if (!can_add_item(player.user[data.pack], inv_item)) {
+ return fail_response("storage_full");
+ }
+ player.items[data.inv] = player.citems[data.inv] = null;
+ bank_add_item(player, data.pack, inv_item);
+ } else if (operation == "pull" && bank_item) {
+ if (!can_add_item(player, bank_item)) {
+ return fail_response("inventory_full");
+ }
+ player.user[data.pack][data.str] = player.cuser[data.pack][data.str] = null;
+ add_item(player, bank_item, { announce: false });
+ }
+ }
+ if (!player.user.gold && player.user.gold !== 0) {
+ player.user.gold = 0;
+ server_log("#X - GOLD BUG bank", 1);
+ }
+ resend(player, "reopen");
+ success_response(success);
+ });
+ socket.on("throw", function (data) {
+ var player = players[socket.id];
+ if (!player) {
+ return;
+ }
+ var item = player.items[data.num];
+ if (item) {
+ if (item.name == "placeholder") {
+ return fail_response("item_placeholder");
+ }
+ if (item.l) {
+ return fail_response("item_locked");
+ }
+ if (item.b) {
+ return fail_response("item_blocked");
+ }
+ var def = G.items[item.name];
+ if (!def.throw) {
+ return fail_response("invalid");
+ }
+ var x = parseFloat(data.x) || 0;
+ var y = parseFloat(data.y) || 0;
+ if (distance(player, { map: player.map, in: player.in, x: x, y: y }) > player.str * 3) {
+ fail_response("too_far");
+ }
+ consume_one(player, data.num);
+ if (item.name == "confetti") {
+ player.thrilling = future_s(20);
+ xy_emit(
+ { map: player.map, in: player.in, x: x, y: y },
+ "eval",
+ "confetti_shower({in:'" + player.in + "',map:'" + player.map + "',real_x:" + x + ",real_y:" + y + "})",
+ );
+ }
+ if (item.name == "firecrackers") {
+ player.thrilling = future_s(200);
+ xy_emit(
+ { map: player.map, in: player.in, x: x, y: y },
+ "eval",
+ "firecrackers({in:'" + player.in + "',map:'" + player.map + "',real_x:" + x + ",real_y:" + y + "})",
+ );
+ for (var id in instances[player.in].monsters) {
+ var monster = instances[player.in].monsters[id];
+ if (monster.target && distance({ map: player.map, in: player.in, x: x, y: y }, monster) < 64) {
+ stop_pursuit(monster, { force: true, cause: "firecrackers" });
+ }
+ }
+ }
+ if (item.name == "whiteegg") {
+ xy_emit({ map: player.map, in: player.in, x: x, y: y }, "eval", "egg_splash(" + x + "," + y + ")");
+ for (var id in instances[player.in].monsters) {
+ var monster = instances[player.in].monsters[id];
+ if (!monster.target && distance({ map: player.map, in: player.in, x: x, y: y }, monster) < 32) {
+ target_player(monster, player);
+ }
+ }
+ }
+ if (item.name == "smoke") {
+ xy_emit({ map: player.map, in: player.in, x: x, y: y }, "eval", "assassin_smoke(" + x + "," + y + ");");
+ }
+ resend(player, "reopen+nc+inv");
+ success_response({});
+ } else {
+ fail_response("no_item");
+ }
+ });
+ socket.on("poke", function (data) {
+ var player = players[socket.id];
+ var level = 1;
+ if (!player || !player.slots.gloves || player.slots.gloves.name != "poker") {
+ return;
+ }
+ if (player.pokes >= 50) {
+ return socket.emit("game_log", "You are out of pokes!");
+ }
+ player.pokes = (player.pokes || 0) + 1;
+ if (player.slots.gloves.level >= 10) {
+ level = 4;
+ } else if (player.slots.gloves.level == 9) {
+ level = 3;
+ } else if (player.slots.gloves.level == 8) {
+ level = 2;
+ }
+ xy_emit(player, "poke", { name: data.name, level: level, who: player.name });
+ });
+ socket.on("merge", function (data) {
+ var player = players[socket.id];
+ if (!player) {
+ return;
+ }
+ var container = player.slots[data.container];
+ var pet = player.slots[data.pet];
+ if (!container || container.type != "container" || !pet || pet.type != "container") {
+ return socket.emit("game_response", "merge_mismatch");
+ }
+ if (G.items[container.name].grade < G.items[pet.name].grade || container.data) {
+ return socket.emit("game_response", "merge_mismatch");
+ }
+ container.data = G.items[pet.name].pet;
+ player.slots[data.pet] = null;
+ socket.emit("game_response", "merge_complete");
+ resend(player, "reopen");
+ });
+ socket.on("activate", function (data) {
+ var player = players[socket.id];
+ // console.log(JSON.stringify(data));
+ if (!player) {
+ return;
+ }
+ if (data.slot) {
+ var item = player.slots[data.slot];
+ if (!item || in_arr(data.slot, trade_slots)) {
return;
}
- if(hit[id]) return;
- hit[id]=true;
- attack=commence_attack(player,target,data.name);
- if(!attack || !attack.projectile) return;
- if(!c_resolve)
- {
- reftarget=target;
- c_resolve=attack;
- attack.pids=[attack.pid];
- attack.targets=[attack.target];
- }
- else
- {
- c_resolve.pids.push(attack.pid);
- c_resolve.targets.push(attack.target);
- }
- // if(times==1 && attack==null) times=40;
- });
- consume_mp(player,G.skills[data.name].mp,reftarget);
- player.halt=false;
- player.to_resend="u+cid";
- if(!c_resolve)
- {
- if(attack) reject=attack;
- disappearing_text(player.socket,player,"NO HITS");
- }
- else resolve=c_resolve;
- }
- if(data.name=="track")
- {
- var list=[];
- for(var id in instances[player.in].players)
- {
- if(id==player.name) continue;
- var target=instances[player.in].players[id],current={sound:"wmp"}; if(target.npc) continue;
- if(is_invis(target)) current.invis=true;
- if(target.type=="rogue" || target.type=="ranger") current.sound="rr";
- else if(target.type=="priest" || target.type=="mage") current.sound="pm";
- current.dist=distance(player,target);
- if(current.distG.skills[data.name].range)
- return socket.emit("game_response",{response:"too_far",place:data.name,failed:true});
- var ids=[];
- if(is_same(player,target,1))
- {
- consume_mp(player,G.skills[data.name].mp);
- }
- else
- {
- if(player.mp= 8 && (player.type == "mage" || player.type == "priest")) {
+ player.tskin = "snow_angel";
+ } else {
+ return socket.emit("game_response", "nothing");
+ }
+ } else if (item.name == "tristone") {
+ var on = true;
+ if (player.tskin || player.tactivations == 100) {
+ player.tskin = "";
+ on = false;
+ } else if (item.level <= 1 && deduct_gender(player) == "female") {
+ player.tskin = random_one(["tf_green", "tf_pink"]);
+ } else if (item.level == 2 && deduct_gender(player) == "female") {
+ player.tskin = random_one(["tf_blue", "tf_purple"]);
+ } else if (deduct_gender(player) == "female") {
+ player.tskin = "tf_orange";
+ } else if (item.level <= 1) {
+ player.tskin = random_one(["tm_gray", "tm_brown", "tm_white"]);
+ } else if (item.level == 2) {
+ player.tskin = random_one(["tm_green", "tm_yellow", "tm_purple"]);
+ } else {
+ player.tskin = random_one(["tm_blue", "tm_red"]);
+ }
+ player.tactivations = (player.tactivations || 0) + 1;
+ } else if (item.name == "darktristone") {
+ var on = true;
+ if (player.tskin || player.tactivations == 100) {
+ player.tskin = "";
+ on = false;
+ } else if (item.level == 4 && deduct_gender(player) == "female") {
+ player.tskin = "mf_blue";
+ } else if (deduct_gender(player) == "female") {
+ player.tskin = "mf_yellow";
+ } else if (item.level == 4) {
+ player.tskin = "mm_blue";
+ } else {
+ player.tskin = "mm_yellow";
+ }
+ player.tactivations = (player.tactivations || 0) + 1;
+ } else {
+ return;
+ }
+ resend(player, "reopen+nc+inv+u+cid");
+ } else {
+ var item = player.items[data.num];
+ if (item) {
+ if (item.name == "frozenstone") {
+ consume_one(player, data.num);
+ }
+ if (item.name == "bkey") {
+ if (!player.user) {
+ return socket.emit("game_response", "only_in_bank");
+ }
+ if (player.user.unlocked && player.user.unlocked.bank_b) {
+ return socket.emit("game_response", "already_unlocked");
+ }
+ consume_one(player, data.num);
+ player.user.unlocked = player.user.unlocked || {};
+ player.user.unlocked.bank_b = new Date();
+ player.user.items8 = player.user.items8 || [];
+ socket.emit("game_response", "door_unlocked");
+ }
+ if (item.name == "ukey") {
+ if (!player.user) {
+ return socket.emit("game_response", "only_in_bank");
+ }
+ if (player.user.unlocked && player.user.unlocked.bank_u) {
+ return socket.emit("game_response", "already_unlocked");
+ }
+ consume_one(player, data.num);
+ player.user.unlocked = player.user.unlocked || {};
+ player.user.unlocked.bank_u = new Date();
+ player.user.items24 = player.user.items24 || [];
+ socket.emit("game_response", "door_unlocked");
+ }
+ if (item.name == "dkey") {
+ if (!player.user) {
+ return socket.emit("game_response", "only_in_bank");
+ }
+ var found = false;
+ for (var i = 0; i < 48; i++) {
+ var pack = "items" + i;
+ if (!bank_packs[pack] || player.user[pack]) {
+ continue;
+ }
+ found = true;
+ player.user[pack] = [];
+ player.cuser[pack] = [];
+ break;
+ }
+ if (!found) {
+ return;
+ }
+ consume_one(player, data.num);
+ socket.emit("game_response", "bank_pack_unlocked");
+ }
+ }
+ resend(player, "reopen+nc+inv");
+ }
+ });
+ socket.on("booster", function (data) {
+ var player = players[socket.id];
+ var item = player.items[data.num];
+ if (!player) {
+ return;
+ }
+ server_log("booster " + data.num + " " + data.action);
+ if (!item || !in_arr(item.name, booster_items)) {
+ return fail_response("invalid");
+ }
+ if (data.action == "activate" && !item.expires) {
+ item.expires = new Date();
+ item.expires.setDate(item.expires.getDate() + 30 + (item.level || 0) * 2);
+ //item.expires.setMinutes(item.expires.getMinutes()+2);
+ } else if (data.action == "shift") {
+ if (!in_arr(data.to, booster_items)) {
+ return fail_response("invalid");
+ }
+ player.xpm = player.goldm = player.luckm = 1;
+ item.name = data.to;
+ player.s.penalty_cd = { ms: min(((player.s.penalty_cd && player.s.penalty_cd.ms) || 0) + 240, 120000) };
+ }
+ // if(item.expires) item.p="legacy";
+ player.citems[data.num] = cache_item(player.items[data.num]);
+ resend(player, "reopen");
+ success_response({ name: player.items[data.num].name });
+ });
+ socket.on("convert", function (data) {
+ // There are a lot of routines that could give birth to an endgame bug
+ // This routine ended up being the one
+ // "stone" boosters were originally 1200 shells
+ // when they were discontinued, I let players exchange them for 3600 shells instead
+ // turns out 'buy_with_cash' didn't check whether an item has "ignore" or not
+ // so one could buy the stones for 1200 shells and sell them for 3600
+ // unlocking infinite gold and shells [17/01/18]
+ var player = players[socket.id];
+ var item = player.items[data.num];
+ var amount = 3600;
+ server_log("stone " + data.num + " " + data.action);
+ if (!item || !in_arr(item.name, ["stoneofxp", "stoneofgold", "stoneofluck"])) {
+ return;
+ }
+ if (item.expires) {
+ amount = round(600 - (hsince(item.expires) * 100) / 24.0);
+ }
+ add_shells(player, amount, "convert");
+ player.items[data.num] = null;
+ player.citems[data.num] = cache_item(player.items[data.num]);
+ resend(player, "reopen+cid");
+ });
+ socket.on("emotion", function (data) {
+ var player = players[socket.id];
+ if (!player) {
+ return;
+ }
+ if (!data.name) {
+ data.name = random_one(Object.keys(player.p.emx));
+ }
+ if (player.last.emotion && mssince(player.last.emotion) < 2000) {
+ return socket.emit("game_response", "emotion_cooldown");
+ }
+ player.last.emotion = new Date();
+ if (!G.emotions[data.name] || !player.p.emx[data.name]) {
+ return socket.emit("game_response", "emotion_cant");
+ }
+ xy_emit(player, "emotion", { name: data.name, player: player.name });
+ });
+ socket.on("skill", function (data) {
+ var player = players[socket.id];
+ if (!player) {
+ return;
+ }
+ var target = null;
+ var cool = true;
+ var resolve = { response: "data", place: data.name, success: true };
+ var reject = null;
+ player.first = true;
+ G.skills.attack.cooldown = player.attack_ms;
+ server_log("skill " + JSON.stringify(data));
+ if (is_disabled(player)) {
+ return fail_response("disabled", data.name);
+ }
+ if ((player.tskin == "konami" || is_silenced(player)) && data.name != "attack") {
+ return socket.emit("game_response", { response: "skill_cant_incapacitated", place: data.name, failed: true });
+ }
+ if (!G.skills[data.name]) {
+ return socket.emit("game_response", { response: "no_skill", place: data.name, failed: true });
+ }
+ if (
+ G.skills[data.name].mp &&
+ player.mp < (G.skills[data.name].mp * (100 - (player.mp_reduction || 0))) / 100.0 &&
+ !(player.role == "gm" && data.name == "blink")
+ ) {
+ return socket.emit("game_response", { response: "no_mp", place: data.name, failed: true });
+ }
+ if (G.skills[data.name].level && player.level < G.skills[data.name].level) {
+ return socket.emit("game_response", { response: "no_level", place: data.name, failed: true });
+ }
+ if (
+ (G.skills[data.name].cooldown || G.skills[data.name].reuse_cooldown) &&
+ player.last[data.name] &&
+ mssince(player.last[data.name]) < (G.skills[data.name].cooldown || G.skills[data.name].reuse_cooldown)
+ ) {
+ return socket.emit("game_response", {
+ response: "cooldown",
+ skill: data.name,
+ place: data.name,
+ id: data.id,
+ ms: (G.skills[data.name].cooldown || G.skills[data.name].reuse_cooldown) - mssince(player.last[data.name]),
+ failed: true,
+ });
+ }
+ if (
+ G.skills[data.name].share &&
+ player.last[G.skills[data.name].share] &&
+ mssince(player.last[G.skills[data.name].share]) <
+ G.skills[G.skills[data.name].share].cooldown * (G.skills[data.name].cooldown_multiplier || 1)
+ ) {
+ return socket.emit("game_response", {
+ response: "cooldown",
+ skill: data.name,
+ place: data.name,
+ failed: true,
+ id: data.id,
+ ms:
+ G.skills[G.skills[data.name].share].cooldown * (G.skills[data.name].cooldown_multiplier || 1) -
+ mssince(player.last[G.skills[data.name].share]),
+ });
+ }
+ if (G.skills[data.name].class && !in_arr(player.type, G.skills[data.name].class) && player.role != "gm") {
+ return socket.emit("game_response", { response: "skill_cant_use", place: data.name, failed: true });
+ }
+ if (
+ G.skills[data.name].wtype &&
+ !is_array(G.skills[data.name].wtype) &&
+ (!player.slots.mainhand || G.items[player.slots.mainhand.name].wtype != G.skills[data.name].wtype) &&
+ player.role != "gm"
+ ) {
+ return socket.emit("game_response", { response: "skill_cant_wtype", place: data.name, failed: true });
+ }
+ if (
+ is_array(G.skills[data.name].wtype) &&
+ (!player.slots.mainhand || !in_arr(G.items[player.slots.mainhand.name].wtype, G.skills[data.name].wtype)) &&
+ player.role != "gm"
+ ) {
+ return socket.emit("game_response", { response: "skill_cant_wtype", place: data.name, failed: true });
+ }
+ if (G.skills[data.name].hostile && G.maps[player.map].safe) {
+ return socket.emit("game_response", { response: "skill_cant_safe", place: data.name, failed: true });
+ }
+ if (G.skills[data.name].target) {
+ if (
+ ("" + parseInt(data.id) === "" + data.id && G.skills[data.name].target == "player") ||
+ ("" + parseInt(data.id) !== "" + data.id && G.skills[data.name].target == "monster")
+ ) {
+ return fail_response("invalid_target", data.name, { id: data.id });
+ }
+ if (G.skills[data.name].target != "monster" && players[id_to_id[data.id]]) {
+ target = players[id_to_id[data.id]];
+ if (G.skills[data.name].hostile && target.name == player.name) {
+ return socket.emit("game_response", { response: "no_target", place: data.name, failed: true });
+ }
+ } else if (G.skills[data.name].target != "player" && instances[player.in].monsters[data.id]) {
+ target = instances[player.in].monsters[data.id];
+ } else {
+ return socket.emit("disappear", { id: data.id, place: data.name, reason: "not_there" });
+ }
+
+ if (
+ is_invis(target) ||
+ (!G.skills[data.name].global && (target.map != player.map || distance(target, player, true) > B.max_vision))
+ ) {
+ return socket.emit("disappear", { id: data.id, place: data.name, reason: "not_there" });
+ }
+ }
+ if (G.skills[data.name].requirements) {
+ for (var requirement in G.skills[data.name].requirements) {
+ if (!player[requirement] || player[requirement] < G.skills[data.name].requirements[requirement]) {
+ return socket.emit("game_response", {
+ response: "skill_cant_requirements",
+ place: data.name,
+ failed: true,
+ });
+ }
+ }
+ }
+ if (G.skills[data.name].slot) {
+ var found = false;
+ var charges = false;
+ G.skills[data.name].slot.forEach(function (p) {
+ if (player.slots[p[0]] && player.slots[p[0]].name == p[1]) {
+ if (G.items[player.slots[p[0]].name].charge) {
+ if ((player.slots[p[0]].charges || 0) < G.items[player.slots[p[0]].name].charge) {
+ charges = true;
+ return;
+ }
+ player.slots[p[0]].charges -= G.items[player.slots[p[0]].name].charge;
+ player.cslots[p[0]] = cache_item(player.slots[p[0]]);
+ }
+ found = true;
+ }
+ });
+ if (charges) {
+ return socket.emit("game_response", { response: "skill_cant_charges", place: data.name, failed: true });
+ }
+ if (!found) {
+ return socket.emit("game_response", { response: "skill_cant_slot", place: data.name, failed: true });
+ }
+ }
+ if (player.s.invincible) {
+ delete player.s.invincible;
+ player.to_resend = "u+cid";
+ }
+ if (data.name == "attack" || data.name == "heal") {
+ var attack = commence_attack(player, target, data.name);
+ if (!attack.failed) {
+ resolve = attack;
+ } else {
+ reject = attack;
+ cool = false;
+ }
+ }
+ if (data.name == "invis" && !player.s.invis) {
+ if (player.s.marked) {
+ return socket.emit("game_response", { response: "skill_cant_use", place: data.name, failed: true });
+ }
+ player.s.invis = { ms: 999999999999999 };
+ xy_emit(player, "disappear", { id: player.id, invis: true, reason: "invis" });
+ player.to_resend = " ";
+ }
+ if (data.name == "pickpocket") {
+ if (distance(player, target, true) > G.skills[data.name].range) {
+ return socket.emit("game_response", { response: "too_far", place: data.name, failed: true });
+ }
+
+ consume_mp(player, G.skills[data.name].mp);
+ player.c[data.name] = {
+ ms:
+ G.skills[data.name].duration_min +
+ Math.random() * (G.skills[data.name].duration_max - G.skills[data.name].duration_min),
+ target: target.name,
+ };
+ player.to_resend = "u+cid";
+ resolve = { response: "data", place: data.name, success: false, in_progress: true };
+ }
+ if (data.name == "fishing" || data.name == "mining") {
+ var direction = 0;
+ var the_zone = null;
+ consume_mp(player, G.skills[data.name].mp);
+ (G.maps[player.map].zones || []).forEach(function (zone) {
+ if (zone.type != data.name || the_zone) {
+ return;
+ }
+ [
+ [0, -24, 3],
+ [-24, 0, 1],
+ [24, 0, 2],
+ [0, 24, 0],
+ ].forEach(function (m) {
+ if (is_point_inside([player.x + m[0], player.y + m[1]], zone.polygon)) {
+ the_zone = zone;
+ direction = m[2];
+ }
+ });
+ });
+ if (!the_zone || player.moving) {
+ xy_emit(player, "ui", { type: data.name + "_fail", name: player.name });
+ reject = { response: "data", place: data.name };
+ } else {
+ xy_emit(player, "ui", { type: data.name + "_start", name: player.name, direction: direction });
+ player.c[data.name] = {
+ ms:
+ G.skills[data.name].duration_min +
+ Math.random() * (G.skills[data.name].duration_max - G.skills[data.name].duration_min),
+ drop: the_zone.drop,
+ };
+ }
+ resolve = { response: "data", place: data.name, success: false, in_progress: true };
+ player.to_resend = "u+cid";
+ }
+ if (data.name == "light") {
+ consume_mp(player, G.skills[data.name].mp);
+ xy_emit(player, "light", { name: player.name });
+ player.to_resend = "u+cid";
+ }
+ if (data.name == "charge") {
+ player.s.charging = { ms: G.skills.charge.duration };
+ player.to_resend = "u+cid";
+ }
+ if (data.name == "dash") {
+ //console.log(data);
+ consume_mp(player, G.skills[data.name].mp);
+ var x = parseFloat(data.x) || 0;
+ var y = parseFloat(data.y) || 0;
+ var point = true;
+ if (point_distance(player.x, player.y, x, y) > 50) {
+ point = false;
+ player.socket.emit("game_response", "dash_failed");
+ reject = { response: "data", place: data.name };
+ }
+ if (point) {
+ var spot = safe_xy_nearby(player.map, x, y);
+ if (!spot) {
+ spot = safe_xy_nearby(player.map, player.x + (x - player.x) * 0.8, player.y + (y - player.y) * 0.8);
+ }
+ if (!spot) {
+ spot = safe_xy_nearby(player.map, player.x + (x - player.x) * 0.6, player.y + (y - player.y) * 0.6);
+ }
+ if (!spot || point_distance(player.x, player.y, spot.x, spot.y) < 10) {
+ point = false;
+ player.socket.emit("game_response", "dash_failed");
+ reject = { response: "data", place: data.name };
+ }
+ if (point) {
+ //console.log([player.x,player.y,spot.x,spot.y]);
+ player.s.dash = { ms: 1000 };
+ player.speed = 500;
+ player.going_x = spot.x;
+ player.going_y = spot.y;
+ start_moving_element(player);
+ player.to_resend = "u+cid";
+ player.socket.emit("eval", { code: "ui_move(" + spot.x + "," + spot.y + ")" });
+ }
+ }
+ }
+ if (data.name == "hardshell" || data.name == "power" || data.name == "xpower") {
+ consume_mp(player, G.skills[data.name].mp);
+ player.s[G.skills[data.name].condition] = {
+ ms: G.skills[data.name].duration || G.conditions[G.skills[data.name].condition].duration,
+ };
+ player.to_resend = "u+cid";
+ }
+ if (data.name == "mshield") {
+ consume_mp(player, G.skills[data.name].mp);
+ if (player.s[G.skills[data.name].condition]) {
+ delete player.s[G.skills[data.name].condition];
+ } else {
+ player.s[G.skills[data.name].condition] = { ms: 999999999 };
+ }
+ player.to_resend = "u+cid";
+ }
+ if (
+ data.name == "mcourage" ||
+ data.name == "mfrenzy" ||
+ data.name == "massproduction" ||
+ data.name == "massproductionpp"
+ ) {
+ consume_mp(player, G.skills[data.name].mp);
+ player.s[G.skills[data.name].condition] = { ms: G.conditions[G.skills[data.name].condition].duration };
+ xy_emit(player, "ui", { type: data.name, name: player.name });
+ player.to_resend = "u+cid";
+ }
+ if (data.name == "throw") {
+ if (distance(player, target, true) > G.skills[data.name].range + player.level) {
+ return socket.emit("game_response", { response: "too_far", place: data.name, failed: true });
+ }
+ if (target.s.invincible || target.immune) {
+ return socket.emit("game_response", { response: "target_invincible", place: data.name, failed: true });
+ }
+ if (!player.items[data.num]) {
+ return socket.emit("game_response", { response: "skill_no_item", place: data.name, failed: true });
+ }
+ var item = player.items[data.num];
+ var r = "u+cid";
+ var damage = 0;
+ if (item.name == "placeholder") {
+ return socket.emit("game_response", { response: "item_placeholder", place: data.name, failed: true });
+ }
+ if (item.l) {
+ return socket.emit("game_response", { response: "item_locked", place: data.name, failed: true });
+ }
+ if (item.b) {
+ return socket.emit("game_response", { response: "item_blocked", place: data.name, failed: true });
+ }
+ var prop = calculate_item_properties(item);
+ var negative = false;
+ if (in_arr(item.name, G.skills.throw.negative)) {
+ negative = true;
+ }
+ G.skills.throw.nprop.forEach(function (p) {
+ if (prop[p]) {
+ negative = true;
+ }
+ });
+ if (negative && target.is_player && !is_in_pvp(player)) {
+ return socket.emit("game_response", { response: "not_in_pvp", place: data.name, failed: true });
+ }
+ consume_one(player, data.num);
+ if (item.name == "essenceoffire") {
+ add_condition(target, "eburn", { from: player });
+ } else if (item.name == "essenceoflife") {
+ add_condition(target, "eheal", { from: player });
+ } else if (prop.attack) {
+ damage = round(Math.random() * prop.attack * 15);
+ } else if (prop.armor) {
+ damage = round(Math.random() * prop.armor * 24);
+ }
+ if (damage) {
+ if (target["1hp"]) {
+ damage = 1;
+ }
+ target.hp = max(1, target.hp - damage);
+ disappearing_text({}, target, "-" + damage, { color: "red", xy: 1 });
+ }
+ consume_mp(player, G.skills[data.name].mp, target);
+ xy_emit(player, "ui", { type: "throw", from: player.name, to: target.id, item: item.name });
+ player.to_resend = "u+cid+reopen";
+ if (target.is_player) {
+ resend(target, r);
+ } else {
+ target.u = true;
+ target.cid++;
+ }
+ }
+ if (data.name == "phaseout") {
+ if (!player.items[data.num] || player.items[data.num].name != "shadowstone") {
+ return socket.emit("game_response", { response: "skill_cant_item", place: data.name, failed: true });
+ }
+ consume_one(player, data.num);
+ consume_mp(player, G.skills[data.name].mp);
+ player.s.phasedout = { ms: G.conditions.phasedout.duration };
+ player.to_resend = "u+cid+reopen";
+ }
+ if (data.name == "pcoat") {
+ if (!player.items[data.num] || player.items[data.num].name != "poison") {
+ return socket.emit("game_response", { response: "skill_cant_item", place: data.name, failed: true });
+ }
+ consume_one(player, data.num);
+ consume_mp(player, G.skills[data.name].mp);
+ player.s.poisonous = { ms: G.skills.pcoat.cooldown };
+ player.to_resend = "u+cid+reopen";
+ }
+ if (data.name == "curse") {
+ //#TODO: last_curse variable + check for multiple curses
+ var attack = commence_attack(player, target, "curse");
+ if (!attack.failed) {
+ resolve = attack;
+ add_pdps(player, null, player.attack / 2);
+ } else {
+ reject = attack;
+ cool = false;
+ }
+ }
+ if (data.name == "snowball") {
+ if (distance(player, target, true) > G.skills[data.name].range) {
+ return socket.emit("game_response", { response: "too_far", place: data.name, failed: true });
+ }
+ var found = false;
+ for (var i = player.isize - 1; i >= 0; i--) {
+ if (player.items[i] && player.items[i].name == "snowball") {
+ consume_one(player, i);
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ return socket.emit("game_response", { response: "skill_cant_item", place: data.name, failed: true });
+ }
+ var attack = commence_attack(player, target, "snowball");
+ if (!attack.failed) {
+ resolve = attack;
+ } else {
+ reject = attack;
+ cool = false;
+ }
+ }
+ if (data.name == "entangle" || data.name == "tangle") {
+ if (data.name == "entangle") {
+ if (!player.items[data.num] || player.items[data.num].name != "essenceofnature") {
+ return socket.emit("game_response", { response: "skill_cant_item", place: data.name, failed: true });
+ }
+ }
+ if (target.s.invincible) {
+ return socket.emit("game_response", { response: "target_invincible", place: data.name, failed: true });
+ }
+ if (distance(player, target, true) > G.skills[data.name].range) {
+ return socket.emit("game_response", { response: "too_far", place: data.name, failed: true });
+ }
+ add_condition(target, "tangled", { ms: G.skills["entangle"].duration });
+ target.abs = true;
+ target.moving = false;
+ xy_emit(player, "ui", { type: "entangle", from: player.name, to: target.id });
+ consume_mp(player, G.skills[data.name].mp, target);
+ add_pdps(player, target, 4000);
+ if (data.name == "entangle") {
+ consume_one(player, data.num);
+ }
+ player.to_resend = "u+cid+reopen";
+ if (target.is_monster) {
+ target.u = true;
+ target.cid++;
+ ccms(target);
+ } else {
+ resend(target, "u+cid");
+ }
+ }
+ if (data.name == "4fingers") {
+ if (target.s.invincible) {
+ return socket.emit("game_response", { response: "target_invincible", place: data.name, failed: true });
+ }
+ if (distance(player, target, true) > G.skills[data.name].range) {
+ return socket.emit("game_response", { response: "too_far", place: data.name, failed: true });
+ }
+ if (!is_in_pvp(player) && !is_same(player, target, 1)) {
+ return socket.emit("game_response", { response: "non_friendly_target", place: data.name, failed: true });
+ }
+ add_condition(target, "fingered", { ms: G.skills["4fingers"].duration });
+ add_condition(target, "stunned", { duration: G.skills["4fingers"].duration - 2000 });
+ xy_emit(player, "ui", { type: "4fingers", from: player.name, to: target.name });
+ consume_mp(player, G.skills[data.name].mp, target);
+ add_pdps(player, target, 1000);
+ resend(target, "u+cid");
+ player.to_resend = "u+cid";
+ }
+ if (
+ [
+ "quickpunch",
+ "quickstab",
+ "smash",
+ "mentalburst",
+ "purify",
+ "taunt",
+ "supershot",
+ "zapperzap",
+ "burst",
+ "piercingshot",
+ ].includes(data.name)
+ ) {
+ var attack = commence_attack(player, target, data.name);
+ if (!attack.failed) {
+ resolve = attack;
+ } else {
+ reject = attack;
+ cool = false;
+ }
+ }
+ if (data.name == "poisonarrow") {
+ if (!player.items[data.num] || player.items[data.num].name != "poison") {
+ return socket.emit("game_response", { response: "skill_cant_item", place: data.name, failed: true });
+ }
+
+ var attack = commence_attack(player, target, data.name);
+ if (!attack.failed) {
+ resolve = attack;
+ } else {
+ reject = attack;
+ cool = false;
+ }
+
+ consume_one(player, data.num);
+ player.to_resend = "reopen";
+ }
+ if (data.name == "revive") {
+ if (!player.items[data.num] || player.items[data.num].name != "essenceoflife") {
+ return socket.emit("game_response", { response: "skill_cant_item", place: data.name, failed: true });
+ }
+ if (distance(player, target, true) > G.skills[data.name].range) {
+ return socket.emit("game_response", { response: "too_far", place: data.name, failed: true });
+ }
+ if (!target.rip) {
+ return socket.emit("game_response", { response: "target_alive", place: data.name, failed: true });
+ }
+
+ consume_one(player, data.num);
+ player.to_resend = "reopen";
+ if (target.party == player.party) {
+ add_pdps(player, target, target.pdps / 5);
+ }
+
+ if (target.hp != target.max_hp) {
+ reject = { response: "data", place: data.name, reason: "hp" };
+ player.socket.emit("game_response", { response: "revive_failed", id: data.id });
+ } else {
+ target.c.revival = { ms: 8000, f: player.name };
+ }
+ resend(target, "u+cid");
+ }
+ if (data.name == "cburst") {
+ var hit = {};
+ var times = 0;
+ var attack = null;
+ var c_resolve = null;
+ consume_mp(player, G.skills[data.name].mp);
+ player.first_burst = true;
+ player.halt = true;
+ if (is_array(data.targets)) {
+ data.targets.forEach(function (t) {
+ // console.log(id);
+ var id = t[0];
+ var mp = max(0, parseInt(t[1]) || 0);
+ if (player.mp < 20 || times > 16 || !mp) {
+ return;
+ }
+ times += 1;
+ var target = instances[player.in].monsters[id];
+ if (!target) {
+ target = instances[player.in].players[id];
+ }
+ if (!target || is_invinc(target) || target.name == player.name) {
+ return;
+ }
+ if (hit[id]) {
+ return;
+ }
+ hit[id] = true;
+ player.next_mp = mp;
+ attack = commence_attack(player, target, "cburst");
+ if (!attack || !attack.projectile) {
+ return;
+ }
+ if (!c_resolve) {
+ c_resolve = attack;
+ attack.pids = [attack.pid];
+ attack.targets = [attack.target];
+ } else {
+ c_resolve.pids.push(attack.pid);
+ c_resolve.targets.push(attack.target);
+ }
+ });
+ }
+ player.halt = false;
+ player.to_resend = "u+cid";
+ if (!c_resolve) {
+ if (attack) {
+ reject = attack;
+ }
+ disappearing_text(player.socket, player, "NO HITS");
+ } else {
+ resolve = c_resolve;
+ }
+ }
+ if (data.name == "partyheal") {
+ var targets = [player];
+ var attack = null;
+ var hits = 0;
+ if (parties[player.party]) {
+ targets = [];
+ parties[player.party].forEach(function (name) {
+ var current = players[name_to_id[name]];
+ targets.push(current);
+ });
+ }
+ targets.forEach(function (target) {
+ attack = commence_attack(player, target, "partyheal");
+ if (!attack.failed) {
+ hits = true;
+ }
+ });
+ if (!hits) {
+ reject = attack;
+ }
+ }
+ if (data.name == "selfheal") {
+ var attack = commence_attack(player, player, data.name);
+ if (!attack.failed) {
+ resolve = attack;
+ } else {
+ reject = attack;
+ cool = false;
+ }
+ }
+ if (data.name == "darkblessing" || data.name == "warcry") {
+ consume_mp(player, G.skills[data.name].mp);
+ for (var id in instances[player.in].players) {
+ var target = instances[player.in].players[id];
+ if (
+ !target.npc &&
+ distance(player, target, true) < G.skills[data.name].range &&
+ (!(G.maps[player.map].pvp || is_pvp) || is_same(player, target, 1))
+ ) {
+ target.s[G.skills[data.name].condition] = { ms: G.skills[data.name].duration, f: player.name };
+ resend(target, "u+cid");
+ add_pdps(player, target, 500);
+ }
+ }
+ xy_emit(player, "ui", { type: data.name });
+ }
+ if (data.name == "3shot" || data.name == "5shot") {
+ player.halt = true;
+ var times = 0;
+ var hit = {};
+ var reftarget = null;
+ var targets = 3;
+ var attack = null;
+ var c_resolve = null;
+ if (data.name == "5shot") {
+ targets = 5;
+ }
+ //console.log(data.ids);
+ if (is_array(data.ids)) {
+ data.ids.forEach(function (id) {
+ if (times >= targets) {
+ return;
+ }
+ times += 1;
+ var target = instances[player.in].monsters[id];
+ if (!target) {
+ target = instances[player.in].players[id];
+ }
+ if (!target || is_invinc(target) || target.name == player.name) {
+ attack = { failed: true, place: data.name, reason: "no_target" };
+ return;
+ }
+ if (hit[id]) {
+ return;
+ }
+ hit[id] = true;
+ attack = commence_attack(player, target, data.name);
+ if (!attack || !attack.projectile) {
+ return;
+ }
+ if (!c_resolve) {
+ reftarget = target;
+ c_resolve = attack;
+ attack.pids = [attack.pid];
+ attack.targets = [attack.target];
+ } else {
+ c_resolve.pids.push(attack.pid);
+ c_resolve.targets.push(attack.target);
+ }
+ // if(times==1 && attack==null) times=40;
+ });
+ }
+ consume_mp(player, G.skills[data.name].mp, reftarget);
+ player.halt = false;
+ player.to_resend = "u+cid";
+ if (!c_resolve) {
+ if (attack) {
+ reject = attack;
+ }
+ disappearing_text(player.socket, player, "NO HITS");
+ } else {
+ resolve = c_resolve;
+ }
+ }
+ if (data.name == "track") {
+ var list = [];
+ for (var id in instances[player.in].players) {
+ if (id == player.name) {
+ continue;
+ }
+ var target = instances[player.in].players[id];
+ var current = { sound: "wmp" };
+ if (target.npc) {
+ continue;
+ }
+ if (is_invis(target)) {
+ current.invis = true;
+ }
+ if (target.type == "rogue" || target.type == "ranger") {
+ current.sound = "rr";
+ } else if (target.type == "priest" || target.type == "mage") {
+ current.sound = "pm";
+ }
+ current.dist = distance(player, target);
+ if (current.dist < G.skills.track.range) {
+ list.push(current);
+ }
+ }
+ list.sort(function (a, b) {
+ return a.dist - b.dist;
+ });
+ consume_mp(player, G.skills[data.name].mp);
+ xy_emit(player, "ui", { type: "track", name: player.name });
+ socket.emit("track", list);
+ player.to_resend = "u+cid";
+ }
+ if (data.name == "agitate") {
+ var ids = [];
+ for (var id in instances[player.in].monsters) {
+ var target = instances[player.in].monsters[id];
+ if (target.target == player.name) {
+ ids.push(id);
+ continue;
+ } // why did the missing continue cause a disengage I have no idea [25/03/23]
+ if (target.target && !(get_player(target.target) && is_same(player, get_player(target.target), 1))) {
+ continue;
+ }
+ var dist = distance(player, target);
+ if (dist < G.skills.agitate.range) {
+ if (target.target) {
+ stop_pursuit(target, { redirect: true, cause: "agitate redirect" });
+ }
+ target.cid += 1;
+ target.u = true;
+ target.last.attacked = new Date();
+ target_player(target, player);
ids.push(id);
- add_pdps(player,target,500);
}
}
+ consume_mp(player, G.skills[data.name].mp, target);
+ xy_emit(player, "ui", { type: "agitate", name: player.name, ids: ids });
+ player.to_resend = "u+cid";
+ add_pdps(player, null, 1000);
}
- if(is_in_pvp(player,1))
- for(var id in instances[player.in].players)
- {
- var target=instances[player.in].players[id];
- var dist=distance(player,target);
- if(dist G.skills[data.name].range) {
+ return socket.emit("game_response", { response: "too_far", place: data.name, failed: true });
+ }
+ var ids = [];
+ if (is_same(player, target, 1)) {
+ consume_mp(player, G.skills[data.name].mp);
+ } else {
+ if (player.mp < G.skills[data.name].mp * 6 || player.level < 75) {
+ return socket.emit("game_response", { response: "non_friendly_target", place: data.name, failed: true });
+ }
+ consume_mp(player, G.skills[data.name].mp * 6);
+ if (Math.random() < 0.95) {
+ consume_skill(player, data.name);
+ resend(player, "u+cid");
+ return socket.emit("game_response", { response: "non_friendly_target", place: data.name, failed: true });
+ }
+ }
+ for (var id in instances[player.in].monsters) {
+ var monster = instances[player.in].monsters[id];
+ if (monster.target == target.name) {
+ stop_pursuit(monster, { redirect: true, cause: "absorb redirect" });
+ monster.cid += 1;
+ monster.u = true;
+ target_player(monster, player);
+ ids.push(id);
+ }
+ }
+ xy_emit(player, "ui", { type: "absorb", name: player.name, from: data.id, ids: ids });
+ player.to_resend = "u+cid";
+ add_pdps(player, target, 1000);
+ }
+ if (data.name == "stomp") {
+ var ids = [];
+ var reftarget = null;
+ for (var id in instances[player.in].monsters) {
+ var target = instances[player.in].monsters[id];
+ var dist = distance(player, target);
+ if (dist < G.skills.stomp.range) {
+ if (target.immune) {
+ player.hitchhikers.push(["game_response", { response: "skill_immune", skill: data.name }]);
+ player.to_resend = "nc";
+ disappearing_text(target.socket, target, "IMMUNE!", { xy: 1, color: "evade", nv: 1, from: player.id });
+ } else if (add_condition(target, "stunned", { duration: G.skills.stomp.duration })) {
ids.push(id);
- add_pdps(player,target,5000);
+ add_pdps(player, target, 500);
}
}
}
- consume_mp(player,G.skills[data.name].mp,reftarget);
- xy_emit(player,"ui",{type:"stomp",name:player.name,ids:ids});
- player.to_resend="u+cid";
- resolve={response:"data",place:data.name,success:true,ids:ids}
- }
- if(data.name=="scare")
- {
- var ids=[];
- consume_mp(player,G.skills[data.name].mp);
- for(var id in instances[player.in].monsters)
- {
- var target=instances[player.in].monsters[id];
- if(target.target==player.name)
- {
- if(target.immune)
- {
- player.hitchhikers.push(["game_response",{response:"skill_immune",skill:"scare"}]);
- player.to_resend="nc";
- disappearing_text(target.socket,target,"IMMUNE!",{xy:1,color:"evade",nv:1,from:player.id});
- }
- else
- {
- stop_pursuit(target,{force:true,cause:"scare"});
- target.abs=true;
- target.moving=false;
- ids.push(id);
- }
- }
- }
- xy_emit(player,"ui",{type:"scare",name:player.name,ids:ids});
- player.to_resend="u+cid";
- }
- if(data.name=="huntersmark")
- {
- if(target.is_player && !is_in_pvp(player) && !is_same(player,target,1))
- return socket.emit("game_response",{response:"skill_cant_pve",place:data.name,failed:true});
- consume_mp(player,G.skills[data.name].mp,target);
- add_condition(target,"marked");
- if(target.is_player)
- resend(target,"u+cid");
- else
- target.cid++,target.u=true;
- xy_emit(player,"ui",{type:"huntersmark",name:player.name,id:target.id});
- player.to_resend="u+cid";
- }
- if(data.name=="charm")
- {
- consume_mp(player,G.skills[data.name].mp);
- if(Math.random()>0.01)
- {
- socket.emit("game_response","charm_failed");
- xy_emit(player,"ui",{type:"charm",name:player.name,id:target.id,fail:true});
- }
- else
- {
- target.cid++;
- target.u=true;
- target.s.charmed={"ms":G.conditions.charmed.duration};
- xy_emit(player,"ui",{type:"charm",name:player.name,id:target.id});
- }
- player.to_resend="u+cid";
- }
- if(data.name=="cleave" || data.name=="shadowstrike")
- {
- player.to_resend="u+cid";
- if(data.name=="shadowstrike")
- {
- if(!player.items[data.num] || player.items[data.num].name!="shadowstone")
- return socket.emit("game_response",{response:"skill_cant_item",place:data.name,failed:true});
- consume_one(player,data.num);
- player.to_resend="u+cid+reopen";
- }
- player.halt=true;
- var ids=[],reftarget=null,c_resolve=null;
- for(var id in instances[player.in].monsters)
- {
- var target=instances[player.in].monsters[id];
- var dist=distance(player,target);
- if(dist 0.01) {
+ socket.emit("game_response", "charm_failed");
+ xy_emit(player, "ui", { type: "charm", name: player.name, id: target.id, fail: true });
+ } else {
+ target.cid++;
+ target.u = true;
+ target.s.charmed = { ms: G.conditions.charmed.duration };
+ xy_emit(player, "ui", { type: "charm", name: player.name, id: target.id });
+ }
+ player.to_resend = "u+cid";
+ }
+ if (data.name == "cleave" || data.name == "shadowstrike") {
+ player.to_resend = "u+cid";
+ if (data.name == "shadowstrike") {
+ if (!player.items[data.num] || player.items[data.num].name != "shadowstone") {
+ return socket.emit("game_response", { response: "skill_cant_item", place: data.name, failed: true });
+ }
+ consume_one(player, data.num);
+ player.to_resend = "u+cid+reopen";
+ }
+ player.halt = true;
+ var ids = [];
+ var reftarget = null;
+ var c_resolve = null;
+ for (var id in instances[player.in].monsters) {
+ var target = instances[player.in].monsters[id];
+ var dist = distance(player, target);
+ if (dist < G.skills[data.name].range) {
+ attack = commence_attack(player, target, data.name);
+ if (!attack || !attack.projectile) {
+ continue;
+ }
+ ids.push(id);
+ if (!c_resolve) {
+ c_resolve = attack;
+ attack.pids = [attack.pid];
+ attack.targets = [attack.target];
+ } else {
c_resolve.pids.push(attack.pid);
c_resolve.targets.push(attack.target);
}
}
}
- consume_mp(player,G.skills[data.name].mp,reftarget);
- xy_emit(player,"ui",{type:data.name,name:player.name,ids:ids});
- player.halt=false;
- if(c_resolve) resolve=c_resolve;
- }
- if(data.name=="magiport")
- {
- var pported=false;
- consume_mp(player,G.skills[data.name].mp);
- if(!is_pvp && mode.pve_safe_magiports)
- {
- if(!magiportations[player.name]) magiportations[player.name]={};
- magiportations[player.name][target.name]=true;
- target.socket.emit("magiport",{name:player.name});
- player.socket.emit("game_response",{response:"magiport_sent",id:data.id});
- xy_emit(player,"ui",{type:"magiport",name:player.name});
-
- }
- else
- {
- if((is_same(player,target,1) || !target.slots.helmet))
- {
- ported=magiport_someone(target,player);
- }
- if(!ported) player.socket.emit("game_response",{response:"magiport_failed",id:data.id});
- }
- player.to_resend="u+cid";
- }
- if(data.name=="blink")
- {
- var x=parseFloat(data.x)||0,y=parseFloat(data.y)||0;
- var spot=safe_xy_nearby(player.map,x,y);
- if(!spot) return player.socket.emit("game_response",{response:"blink_failed",place:data.name,failed:true});
- player.s.blink={ms:200};
- player.s.blink.in=player.in;
- player.s.blink.map=player.map;
- player.s.blink.x=spot.x;
- player.s.blink.y=spot.y;
- player.s.blink.d=0; if(in_arr(data.direction,[1,2,3])) player.s.blink.d=data.direction;
- if(player.role!="gm") consume_mp(player,G.skills[data.name].mp);
- // xy_emit(player,"ui",{type:"blinking",name:player.name});
- resend(player,"u+cid");
- // #TODO: Appear animation for non-self's [21/05/18]
- }
- if(data.name=="warp")
- {
- var x=parseFloat(data.x)||0,y=parseFloat(data.y)||0,ins=data.in||"main",instance=instances[ins];
- if(!instance) return player.socket.emit("game_response",{response:"blink_failed",place:data.name,failed:true});
- if(instance.mount!=instances[player.in].mount) return player.socket.emit("game_response",{response:"cant_in_bank",place:data.name,failed:true});
- var spot=safe_xy_nearby(instance.name,x,y);
- if(!spot) return player.socket.emit("game_response",{response:"blink_failed",place:data.name,failed:true});
- player.s.blink={ms:200};
- player.s.blink.in=ins;
- player.s.blink.map=instance.name;
- player.s.blink.x=spot.x;
- player.s.blink.y=spot.y;
- player.s.blink.d=0; if(in_arr(data.direction,[1,2,3])) player.s.blink.d=data.direction;
- if(player.role!="gm") consume_mp(player,G.skills[data.name].mp);
- // xy_emit(player,"ui",{type:"blinking",name:player.name});
- player.to_resend="u+cid";
- // #TODO: Appear animation for non-self's [21/05/18]
- }
- if(data.name=="mluck")
- {
- if(distance(player,target,true)>G.skills[data.name].range)
- return socket.emit("game_response",{response:"too_far",place:data.name,failed:true});
- consume_mp(player,G.skills[data.name].mp);
- if(!target.s[G.skills[data.name].condition] || !target.s[G.skills[data.name].condition].strong || target.s[G.skills[data.name].condition].f==player.name) target.s[G.skills[data.name].condition]={ms:G.conditions.mluck.duration,f:player.name};
- if(target.owner==player.owner) target.s[G.skills[data.name].condition].strong=true;
- xy_emit(player,"ui",{type:"mluck",from:player.name,to:target.name});
- resend(target,"u+cid"); resend(player,"u+cid");
- }
- if(data.name=="rspeed")
- {
- if(distance(player,target,true)>G.skills[data.name].range)
- return socket.emit("game_response",{response:"too_far",place:data.name,failed:true});
- consume_mp(player,G.skills[data.name].mp);
- target.s[G.skills[data.name].condition]={ms:G.conditions.rspeed.duration,f:player.name};
- xy_emit(player,"ui",{type:"rspeed",from:player.name,to:target.name});
- resend(target,"u+cid"); resend(player,"u+cid");
- if(player.party==target.party && player!=target) add_pdps(player,target,2000);
- }
- if(data.name=="reflection")
- {
- if(distance(player,target,true)>G.skills[data.name].range)
- return socket.emit("game_response",{response:"too_far",place:data.name,failed:true});
- consume_mp(player,G.skills[data.name].mp);
- target.s[G.skills[data.name].condition]={ms:G.conditions.reflection.duration,f:player.name};
- xy_emit(player,"ui",{type:"reflection",from:player.name,to:target.name});
- resend(target,"u+cid"); resend(player,"u+cid");
- if(player.party==target.party && player!=target) add_pdps(player,target,4000);
- }
- if(data.name=="energize")
- {
- if(distance(player,target,true)>G.skills[data.name].range)
- return socket.emit("game_response",{response:"too_far",place:data.name,failed:true});
- if(!player.mp)
- return socket.emit("game_response",{response:"no_mp",place:data.name,failed:true});
- var mp=parseInt(data.mp)||10000;
- mp=max(1,min(player.mp,mp));
- if(mp>target.max_mp-target.mp) mp=target.max_mp-target.mp;
- target.mp+=mp; player.mp-=mp;
- if(player.party==target.party && player!=target) add_pdps(player,target,mp*2);
- disappearing_text(player.socket,player,"-"+mp,{color:"mana",xy:1});
- disappearing_text(target.socket,target,"+"+mp,{color:"mana",xy:1});
- target.s[G.skills[data.name].condition]={ms:G.conditions[G.skills[data.name].condition].duration};
- xy_emit(player,"ui",{type:"energize",from:player.name,to:target.name});
- resend(target,"u+cid"); resend(player,"u+cid");
- }
- if(data.name=="alchemy")
- {
- var gold=0,rate=0.8;
- if(player.level>=100) rate=1.12;
- else if(player.level>=90) rate=1.10;
- else if(player.level>=80) rate=1.06;
- else if(player.level>=70) rate=1;
- else if(player.level>=60) rate=0.92;
- else if(player.level>=50) rate=0.86;
- consume_mp(player,G.skills[data.name].mp);
- xy_emit(player,"ui",{type:"alchemy",name:player.name});
- for(var i=0;i300) return socket.emit("game_response","distance");
- if(!player.s.holidayspirit && player.esize) add_item(player,"funtoken"),x="+reopen";
- add_condition(player,"holidayspirit");
- resend(player,"u+cid"+x);
- }
- else if(["redorb","blueorb","greenorb","yelloworb"].includes(data.type))
- {
- if(!G.maps[player.map].ref || !G.maps[player.map].ref[data.type] || distance(G.maps[player.map].ref[data.type],player,true)>40) return socket.emit("game_response","distance");
- ["redorb","blueorb","greenorb","yelloworb"].forEach(function(s){ delete player.s[s]; })
- add_condition(player,data.type);
- resend(player,"u+cid");
- }
- else if(data=="the_lever")
- {
- if(player.map!="resort_e") return socket.emit("game_response","distance");
- player.s.magiport={ms:300};
- player.s.magiport.x=player.x;
- player.s.magiport.y=player.y;
- player.s.magiport.f=player.name;
- player.s.magiport.in="resort";
- player.s.magiport.map="resort";
- resend(player,"u+cid");
- }
- else if(data.type=="dailytask")
- {
- if(!G.maps.main.ref.dailytask || distance(G.maps.main.ref.dailytask,player,true)>150) return socket.emit("game_response","distance");
- player.p.monsterhunt={ms:60*60*1000,m:"goo"};
- socket.emit("game_response",{"response":"monsterhunt",monster:"goo"});
- }
- else if(data.key && player.konami)
- {
- if(data.key=="B" && player.konami.length<20) player.konami.push(data.key[0]);
- else if(data.key=="A")
- {
- if(player.konami.join("")=="uuddlrlrB")
- {
- player.tskin="konami",resend(player,"u+cid");
- if(!player.p.target_lock || !G.monsters[player.p.target_lock] || hsince(player.p.dt.last_tl)>15*24)
- {
- var monsters=[];
- for(var name in G.monsters) if(!G.monsters[name].special && !G.monsters[name].stationary && G.monsters[name].c) monsters.push(name);
- player.p.target_lock=random_one(monsters);
- player.p.dt.last_tl=new Date();
- }
- socket.emit("game_response",{response:"target_lock",monster:player.p.target_lock});
- }
- else player.konami=[];
- }
- }
- });
- socket.on('mreport',function(data){
- var player=players[socket.id]; if(!player) return;
- var a=0,b=0;
- a=parseFloat(data.x)||0;
- b=parseFloat(data.y)||0;
- // console.log(JSON.stringify(data));
- socket.emit("game_log",""+simple_distance({x:player.x,y:player.y},{x:a,y:b}));
- })
- socket.on('move',function(data){
- // if(observers[socket.id]) observers[socket.id].x=data.x,observers[socket.id].y=data.y; Old observer code [17/02/17]
- var player=players[socket.id],current=-1,going=-1,actual=true;
- var x=parseFloat(data.going_x)||0,y=parseFloat(data.going_y)||0;
- if(data.pet) player=player.monster,actual=false;
- if(data.key && (!player.konami || player.konami.length<20))
- {
- // console.log(data.key);
- if(!player.konami) player.konami=[];
- player.konami.push(data.key[0]);
- }
- if(player && player.m==data.m && can_walk(player) && (x!=player.x || y!=player.y))
- {
- // if(is_sdk) server_log("Player moving to: "+data.going_x+","+data.going_y);
-
- // player.x=data.x; player.y=data.y; [03/08/16] Seems like a really bad idea to update x/y based on what players provide
- data.x=parseFloat(data.x)||0;
- data.y=parseFloat(data.y)||0;
- player.going_x=x;
- player.going_y=y;
- if(smap_data[player.map]!=-1 && mode.enforce_smap)
- {
- current=smap_data[player.map][rphash(data.x,data.y)],going=smap_data[player.map][rphash(player.going_x,player.going_y)];
- // server_log("current:"+current+" going:"+going+" real:"+smap_data[player.map][phash(player.x,player.y)]);
- if((current===undefined || current>=2) || (going===undefined || going>=2))
- {
- server_log("#C cheater: "+player.name+" current: "+current+"["+data.x+","+data.x+"] going: "+going+"["+player.going_x+","+player.going_y+"] at "+player.map,1);
- appengine_log("violation","move_line: "+player.name+" afk: "+player.afk+" code: "+player.code);
- player.socket.emit("game_log","Line violation detected");
- player.socket.emit("game_log","Make sure you only move with the built-in move function");
- defeat_player(player);
- transport_player_to(player,"jail");
- return;
- }
- }
- // player.check_x=player.going_x; player.check_y=player.going_y; player.checked_xy=false;
- start_moving_element(player);
- if(!player.pet && simple_distance(player,{x:data.x,y:data.y})>132 && current==0 && mode.lcorrection)
- {
- // server_log("Correction sent");
- socket.emit("correction",{x:player.x,y:player.y});
- }
- if(actual)
- {
- var change=false;
- for(var id in player.c)
- {
- if(G.conditions[id] && !G.conditions[id].can_move)
- {
- change=true;
- delete player.c[id];
+ if (is_in_pvp(player, 1)) {
+ for (var id in instances[player.in].players) {
+ var target = instances[player.in].players[id];
+ var dist = distance(player, target);
+ if (dist < G.skills[data.name].range && !target.npc && !is_same(player, target, 1)) {
+ attack = commence_attack(player, target, data.name);
+ if (!attack || !attack.projectile) {
+ continue;
+ }
+ ids.push(id);
+ if (!c_resolve) {
+ reftarget = target;
+ c_resolve = attack;
+ attack.pids = [attack.pid];
+ attack.targets = [attack.target];
+ } else {
+ c_resolve.pids.push(attack.pid);
+ c_resolve.targets.push(attack.target);
+ }
+ }
}
}
- if(change) resend(player,"u+cid");
+ consume_mp(player, G.skills[data.name].mp, reftarget);
+ xy_emit(player, "ui", { type: data.name, name: player.name, ids: ids });
+ player.halt = false;
+ if (c_resolve) {
+ resolve = c_resolve;
+ }
}
- //if(smap_data[player.map][rphash(player.x,player.y)]===0) push_xyh(player,player.x,player.y);
- //else push_xyh(player,data.x,data.y);
- }
- });
- socket.on('open_chest',function(data){
- var chest=chests[data.id],player=players[socket.id],reopen=false; if(!player) return;
- var r={id:data.id,goldm:player.goldm,opener:player.name,items:[]};
- if(chest && simple_distance(chest,player)>400) r.goldm=1,r.dry=true;
- if(chest && msince(chest.date)>8) r.goldm=1,r.stale=true;
- if(player.map=="woffice" || G.maps[player.map].mount || is_invis(player)) return fail_response("loot_failed");
- try{
- if(chest && !chest.pvp && chest.gold>100000000 && !player.stealth)
- {
- broadcast("server_message",{"message":player.name+" looted "+to_pretty_num(server_tax(round(chest.gold*r.goldm),true))+" gold","color":"gold","type":"server_gold",name:player.name});
+ if (data.name == "magiport") {
+ var pported = false;
+ consume_mp(player, G.skills[data.name].mp);
+ if (!is_pvp && mode.pve_safe_magiports) {
+ if (!magiportations[player.name]) {
+ magiportations[player.name] = {};
+ }
+ magiportations[player.name][target.name] = true;
+ target.socket.emit("magiport", { name: player.name });
+ player.socket.emit("game_response", { response: "magiport_sent", id: data.id });
+ xy_emit(player, "ui", { type: "magiport", name: player.name });
+ } else {
+ if (is_same(player, target, 1) || !target.slots.helmet) {
+ ported = magiport_someone(target, player);
+ }
+ if (!ported) {
+ player.socket.emit("game_response", { response: "magiport_failed", id: data.id });
+ }
+ }
+ player.to_resend = "u+cid";
}
- if(chest && player.owner && chest.owners && !in_arr(player.owner,chest.owners) && !W.chest[player.owner])
- {
- W.chest[player.owner]=new Date();
- server_log("SEVERE - Cross Loot from "+player.name+" not from "+chest.owners.toString());
+ if (data.name == "blink") {
+ var x = parseFloat(data.x) || 0;
+ var y = parseFloat(data.y) || 0;
+ var spot = safe_xy_nearby(player.map, x, y);
+ if (!spot) {
+ return player.socket.emit("game_response", { response: "blink_failed", place: data.name, failed: true });
+ }
+ player.s.blink = { ms: 200 };
+ player.s.blink.in = player.in;
+ player.s.blink.map = player.map;
+ player.s.blink.x = spot.x;
+ player.s.blink.y = spot.y;
+ player.s.blink.d = 0;
+ if (in_arr(data.direction, [1, 2, 3])) {
+ player.s.blink.d = data.direction;
+ }
+ if (player.role != "gm") {
+ consume_mp(player, G.skills[data.name].mp);
+ }
+ // xy_emit(player,"ui",{type:"blinking",name:player.name});
+ resend(player, "u+cid");
+ // #TODO: Appear animation for non-self's [21/05/18]
}
- if(chest && !player.party)
- {
- var all_items=chest.items.slice(0); all_items.concat(chest.pvp_items)
- if(!can_add_items(player,all_items)) return fail_response("loot_no_space");
- delete chests[data.id]; // The add_shells routine was at the top, so when inventory was full, attempting to open the chest gave shells infinitely, repeated lesson, always remove before adding, or exceptions [11/07/18]
- if(chest && chest.cash) add_shells(player,chest.cash,"chest",true,"override");
- chest.items.forEach(function(item){
- item.src="pvp";
- add_item(player,item,{found:1,m:1,v:B.v}); reopen=true;
- var ritem=cache_item(item); ritem.looter=player.name; r.items.push(ritem);
- socket.emit("game_log",{message:"Found "+item_to_phrase(item),color:"#4BAEAA"});
- if(player.t) player.t.dgold+=round(G.items[item.name].g*0.6);
+ if (data.name == "warp") {
+ var x = parseFloat(data.x) || 0;
+ var y = parseFloat(data.y) || 0;
+ var ins = data.in || "main";
+ var instance = instances[ins];
+ if (!instance) {
+ return player.socket.emit("game_response", { response: "blink_failed", place: data.name, failed: true });
+ }
+ if (instance.mount != instances[player.in].mount) {
+ return player.socket.emit("game_response", { response: "cant_in_bank", place: data.name, failed: true });
+ }
+ var spot = safe_xy_nearby(instance.name, x, y);
+ if (!spot) {
+ return player.socket.emit("game_response", { response: "blink_failed", place: data.name, failed: true });
+ }
+ player.s.blink = { ms: 200 };
+ player.s.blink.in = ins;
+ player.s.blink.map = instance.name;
+ player.s.blink.x = spot.x;
+ player.s.blink.y = spot.y;
+ player.s.blink.d = 0;
+ if (in_arr(data.direction, [1, 2, 3])) {
+ player.s.blink.d = data.direction;
+ }
+ if (player.role != "gm") {
+ consume_mp(player, G.skills[data.name].mp);
+ }
+ // xy_emit(player,"ui",{type:"blinking",name:player.name});
+ player.to_resend = "u+cid";
+ // #TODO: Appear animation for non-self's [21/05/18]
+ }
+ if (data.name == "mluck") {
+ if (distance(player, target, true) > G.skills[data.name].range) {
+ return socket.emit("game_response", { response: "too_far", place: data.name, failed: true });
+ }
+ consume_mp(player, G.skills[data.name].mp);
+ if (
+ !target.s[G.skills[data.name].condition] ||
+ !target.s[G.skills[data.name].condition].strong ||
+ target.s[G.skills[data.name].condition].f == player.name
+ ) {
+ target.s[G.skills[data.name].condition] = { ms: G.conditions.mluck.duration, f: player.name };
+ }
+ if (target.owner == player.owner) {
+ target.s[G.skills[data.name].condition].strong = true;
+ }
+ xy_emit(player, "ui", { type: "mluck", from: player.name, to: target.name });
+ resend(target, "u+cid");
+ resend(player, "u+cid");
+ }
+ if (data.name == "rspeed") {
+ if (distance(player, target, true) > G.skills[data.name].range) {
+ return socket.emit("game_response", { response: "too_far", place: data.name, failed: true });
+ }
+ consume_mp(player, G.skills[data.name].mp);
+ target.s[G.skills[data.name].condition] = { ms: G.conditions.rspeed.duration, f: player.name };
+ xy_emit(player, "ui", { type: "rspeed", from: player.name, to: target.name });
+ resend(target, "u+cid");
+ resend(player, "u+cid");
+ if (player.party == target.party && player != target) {
+ add_pdps(player, target, 2000);
+ }
+ }
+ if (data.name == "reflection") {
+ if (distance(player, target, true) > G.skills[data.name].range) {
+ return socket.emit("game_response", { response: "too_far", place: data.name, failed: true });
+ }
+ consume_mp(player, G.skills[data.name].mp);
+ target.s[G.skills[data.name].condition] = { ms: G.conditions.reflection.duration, f: player.name };
+ xy_emit(player, "ui", { type: "reflection", from: player.name, to: target.name });
+ resend(target, "u+cid");
+ resend(player, "u+cid");
+ if (player.party == target.party && player != target) {
+ add_pdps(player, target, 4000);
+ }
+ }
+ if (data.name == "energize") {
+ if (distance(player, target, true) > G.skills[data.name].range) {
+ return socket.emit("game_response", { response: "too_far", place: data.name, failed: true });
+ }
+ if (!player.mp) {
+ return socket.emit("game_response", { response: "no_mp", place: data.name, failed: true });
+ }
+ var mp = parseInt(data.mp) || 10000;
+ mp = max(1, min(player.mp, mp));
+ if (mp > target.max_mp - target.mp) {
+ mp = target.max_mp - target.mp;
+ }
+ target.mp += mp;
+ player.mp -= mp;
+ if (player.party == target.party && player != target) {
+ add_pdps(player, target, mp * 2);
+ }
+ disappearing_text(player.socket, player, "-" + mp, { color: "mana", xy: 1 });
+ disappearing_text(target.socket, target, "+" + mp, { color: "mana", xy: 1 });
+ target.s[G.skills[data.name].condition] = { ms: G.conditions[G.skills[data.name].condition].duration };
+ xy_emit(player, "ui", { type: "energize", from: player.name, to: target.name });
+ resend(target, "u+cid");
+ resend(player, "u+cid");
+ }
+ if (data.name == "alchemy") {
+ var gold = 0;
+ var rate = 0.8;
+ if (player.level >= 100) {
+ rate = 1.12;
+ } else if (player.level >= 90) {
+ rate = 1.1;
+ } else if (player.level >= 80) {
+ rate = 1.06;
+ } else if (player.level >= 70) {
+ rate = 1;
+ } else if (player.level >= 60) {
+ rate = 0.92;
+ } else if (player.level >= 50) {
+ rate = 0.86;
+ }
+ consume_mp(player, G.skills[data.name].mp);
+ xy_emit(player, "ui", { type: "alchemy", name: player.name });
+ for (var i = 0; i < player.isize; i++) {
+ if (!player.items[i] || player.items[i].l) {
+ continue;
+ }
+ gold = calculate_item_value(player.items[i]);
+ consume_one(player, i);
+ break;
+ }
+ player.gold += gold * rate;
+ resend(player, "reopen");
+ socket.emit("game_response", { response: "gold_received", gold: gold * rate });
+ }
+ if (cool) {
+ consume_skill(player, data.name);
+ }
+ if (player.to_resend) {
+ resend(player, player.to_resend);
+ }
+ if (reject) {
+ if (!reject.response) {
+ reject.response = "data";
+ }
+ socket.emit("game_response", reject);
+ } else if (resolve) {
+ socket.emit("game_response", resolve);
+ }
+ });
+ socket.on("click", function (data) {
+ // You'll be missed 'click' method, the 'click' method was the first method on this server, it was used as an attack method up until [17/06/18] - at this date, there were 3 simple conditions left which checked for data.button=="right" - the game matured so that all interactions were handled client-side rather than processed server-side
+ socket.emit("game_log", "'click' method is deprecated.");
+ });
+ socket.on("attack", function (data) {
+ return socket.fs.skill({ name: "attack", id: data.id });
+ });
+ socket.on("heal", function (data) {
+ return socket.fs.skill({ name: "heal", id: data.id });
+ });
+ socket.on("interaction", function (data) {
+ var player = players[socket.id];
+ if (!player) {
+ return;
+ }
+ if (data.type == "newyear_tree") {
+ var x = "";
+ if (
+ !G.maps[player.map].ref ||
+ !G.maps[player.map].ref[data.type] ||
+ distance(G.maps[player.map].ref[data.type], player, true) > 300
+ ) {
+ return socket.emit("game_response", "distance");
+ }
+ if (!player.s.holidayspirit && player.esize) {
+ add_item(player, "funtoken");
+ x = "+reopen";
+ }
+ add_condition(player, "holidayspirit");
+ resend(player, "u+cid" + x);
+ } else if (["redorb", "blueorb", "greenorb", "yelloworb"].includes(data.type)) {
+ if (
+ !G.maps[player.map].ref ||
+ !G.maps[player.map].ref[data.type] ||
+ distance(G.maps[player.map].ref[data.type], player, true) > 40
+ ) {
+ return socket.emit("game_response", "distance");
+ }
+ ["redorb", "blueorb", "greenorb", "yelloworb"].forEach(function (s) {
+ delete player.s[s];
});
- (chest.pvp_items||[]).forEach(function(item){
- item.v=new Date();
- if(can_add_item(player,item))
- {
- add_item(player,item,{found:1,v:B.v}); reopen=true;
- var ritem=cache_item(item); ritem.looter=player.name; ritem.pvp_loot=true; r.items.push(ritem);
- socket.emit("game_log",{message:"Looted "+item_to_phrase(item),color:"#4BAEAA"});
+ add_condition(player, data.type);
+ resend(player, "u+cid");
+ } else if (data == "the_lever") {
+ if (player.map != "resort_e") {
+ return socket.emit("game_response", "distance");
+ }
+ player.s.magiport = { ms: 300 };
+ player.s.magiport.x = player.x;
+ player.s.magiport.y = player.y;
+ player.s.magiport.f = player.name;
+ player.s.magiport.in = "resort";
+ player.s.magiport.map = "resort";
+ resend(player, "u+cid");
+ } else if (data.type == "dailytask") {
+ if (!G.maps.main.ref.dailytask || distance(G.maps.main.ref.dailytask, player, true) > 150) {
+ return socket.emit("game_response", "distance");
+ }
+ player.p.monsterhunt = { ms: 60 * 60 * 1000, m: "goo" };
+ socket.emit("game_response", { response: "monsterhunt", monster: "goo" });
+ } else if (data.key && player.konami) {
+ if (data.key == "B" && player.konami.length < 20) {
+ player.konami.push(data.key[0]);
+ } else if (data.key == "A") {
+ if (player.konami.join("") == "uuddlrlrB") {
+ player.tskin = "konami";
+ resend(player, "u+cid");
+ if (!player.p.target_lock || !G.monsters[player.p.target_lock] || hsince(player.p.dt.last_tl) > 15 * 24) {
+ var monsters = [];
+ for (var name in G.monsters) {
+ if (!G.monsters[name].special && !G.monsters[name].stationary && G.monsters[name].c) {
+ monsters.push(name);
+ }
+ }
+ player.p.target_lock = random_one(monsters);
+ player.p.dt.last_tl = new Date();
+ }
+ socket.emit("game_response", { response: "target_lock", monster: player.p.target_lock });
+ } else {
+ player.konami = [];
}
- else
- {
- lostandfound_logic(item);
- var ritem=cache_item(item); ritem.looter=null; ritem.lostandfound=true; r.items.push(ritem);
- socket.emit("game_log",{message:"Lost "+item_to_phrase(item),color:"#AB4E4F"});
- }
- });
- r.gold=round(chest.gold*r.goldm)+round(chest.egold||0);
- r.gold=server_tax(r.gold);
- player.gold+=r.gold;
- if(player.t) player.t.cgold+=r.gold;
- if(r.gold) socket.emit("game_log",{message:to_pretty_num(r.gold)+" gold",color:"gold"});
- socket.emit("disappearing_text",{"message":"+"+r.gold,"x":chest.x,"y":chest.y-10,"args":{color:"+gold","size":"large"}});
- if(!r.items.length) delete r.items;
- resend(player,reopen&&"reopen+nc+inv"||"");
- socket.emit("chest_opened",r);
+ }
}
- else if(chest)
- {
- // var gold=round(chest.gold/parties[player.party].length);
- r.party=true;
- var chest=chests[data.id],reopen={};
- delete chests[data.id];
- if(chest && chest.cash) add_shells(player,chest.cash,"chest",true,"override");
- chest.items.forEach(function(item){
+ });
+ socket.on("mreport", function (data) {
+ var player = players[socket.id];
+ if (!player) {
+ return;
+ }
+ var a = 0;
+ var b = 0;
+ a = parseFloat(data.x) || 0;
+ b = parseFloat(data.y) || 0;
+ // console.log(JSON.stringify(data));
+ socket.emit("game_log", "" + simple_distance({ x: player.x, y: player.y }, { x: a, y: b }));
+ });
+ socket.on("move", function (data) {
+ // if(observers[socket.id]) observers[socket.id].x=data.x,observers[socket.id].y=data.y; Old observer code [17/02/17]
+ var player = players[socket.id];
+ var current = -1;
+ var going = -1;
+ var actual = true;
+ var x = parseFloat(data.going_x) || 0;
+ var y = parseFloat(data.going_y) || 0;
+ if (data.pet) {
+ player = player.monster;
+ actual = false;
+ }
+ if (data.key && (!player.konami || player.konami.length < 20)) {
+ // console.log(data.key);
+ if (!player.konami) {
+ player.konami = [];
+ }
+ player.konami.push(data.key[0]);
+ }
+ if (player && player.m == data.m && can_walk(player) && (x != player.x || y != player.y)) {
+ // if(is_sdk) server_log("Player moving to: "+data.going_x+","+data.going_y);
+
+ // player.x=data.x; player.y=data.y; [03/08/16] Seems like a really bad idea to update x/y based on what players provide
+ data.x = parseFloat(data.x) || 0;
+ data.y = parseFloat(data.y) || 0;
+ player.going_x = x;
+ player.going_y = y;
+ if (smap_data[player.map] != -1 && mode.enforce_smap) {
+ current = smap_data[player.map][rphash(data.x, data.y)];
+ going = smap_data[player.map][rphash(player.going_x, player.going_y)];
+ // server_log("current:"+current+" going:"+going+" real:"+smap_data[player.map][phash(player.x,player.y)]);
+ if (current === undefined || current >= 2 || going === undefined || going >= 2) {
+ server_log(
+ "#C cheater: " +
+ player.name +
+ " current: " +
+ current +
+ "[" +
+ data.x +
+ "," +
+ data.x +
+ "] going: " +
+ going +
+ "[" +
+ player.going_x +
+ "," +
+ player.going_y +
+ "] at " +
+ player.map,
+ 1,
+ );
+ appengine_log("violation", "move_line: " + player.name + " afk: " + player.afk + " code: " + player.code);
+ player.socket.emit("game_log", "Line violation detected");
+ player.socket.emit("game_log", "Make sure you only move with the built-in move function");
+ defeat_player(player);
+ transport_player_to(player, "jail");
+ return;
+ }
+ }
+ // player.check_x=player.going_x; player.check_y=player.going_y; player.checked_xy=false;
+ start_moving_element(player);
+ if (
+ !player.pet &&
+ simple_distance(player, { x: data.x, y: data.y }) > 132 &&
+ current == 0 &&
+ mode.lcorrection
+ ) {
+ // server_log("Correction sent");
+ socket.emit("correction", { x: player.x, y: player.y });
+ }
+ if (actual) {
+ var change = false;
+ for (var id in player.c) {
+ if (G.conditions[id] && !G.conditions[id].can_move) {
+ change = true;
+ delete player.c[id];
+ }
+ }
+ if (change) {
+ resend(player, "u+cid");
+ }
+ }
+ //if(smap_data[player.map][rphash(player.x,player.y)]===0) push_xyh(player,player.x,player.y);
+ //else push_xyh(player,data.x,data.y);
+ }
+ });
+ socket.on("open_chest", function (data) {
+ var chest = chests[data.id];
+ var player = players[socket.id];
+ var reopen = false;
+ if (!player) {
+ return;
+ }
+ var r = { id: data.id, goldm: player.goldm, opener: player.name, items: [] };
+ if (chest && simple_distance(chest, player) > 400) {
+ r.goldm = 1;
+ r.dry = true;
+ }
+ if (chest && msince(chest.date) > 8) {
+ r.goldm = 1;
+ r.stale = true;
+ }
+ if (player.map == "woffice" || G.maps[player.map].mount || is_invis(player)) {
+ return fail_response("loot_failed");
+ }
+ try {
+ if (chest && !chest.pvp && chest.gold > 100000000 && !player.stealth) {
+ broadcast("server_message", {
+ message: player.name + " looted " + to_pretty_num(server_tax(round(chest.gold * r.goldm), true)) + " gold",
+ color: "gold",
+ type: "server_gold",
+ name: player.name,
+ });
+ }
+ if (chest && player.owner && chest.owners && !in_arr(player.owner, chest.owners) && !W.chest[player.owner]) {
+ W.chest[player.owner] = new Date();
+ server_log("SEVERE - Cross Loot from " + player.name + " not from " + chest.owners.toString());
+ }
+ if (chest && !player.party) {
+ var all_items = chest.items.slice(0);
+ all_items.concat(chest.pvp_items);
+ if (!can_add_items(player, all_items)) {
+ return fail_response("loot_no_space");
+ }
+ delete chests[data.id]; // The add_shells routine was at the top, so when inventory was full, attempting to open the chest gave shells infinitely, repeated lesson, always remove before adding, or exceptions [11/07/18]
+ if (chest && chest.cash) {
+ add_shells(player, chest.cash, "chest", true, "override");
+ }
+ chest.items.forEach(function (item) {
+ item.src = "pvp";
+ add_item(player, item, { found: 1, m: 1, v: B.v });
+ reopen = true;
+ var ritem = cache_item(item);
+ ritem.looter = player.name;
+ r.items.push(ritem);
+ socket.emit("game_log", { message: "Found " + item_to_phrase(item), color: "#4BAEAA" });
+ if (player.t) {
+ player.t.dgold += round(G.items[item.name].g * 0.6);
+ }
+ });
+ (chest.pvp_items || []).forEach(function (item) {
+ item.v = new Date();
+ if (can_add_item(player, item)) {
+ add_item(player, item, { found: 1, v: B.v });
+ reopen = true;
+ var ritem = cache_item(item);
+ ritem.looter = player.name;
+ ritem.pvp_loot = true;
+ r.items.push(ritem);
+ socket.emit("game_log", { message: "Looted " + item_to_phrase(item), color: "#4BAEAA" });
+ } else {
+ lostandfound_logic(item);
+ var ritem = cache_item(item);
+ ritem.looter = null;
+ ritem.lostandfound = true;
+ r.items.push(ritem);
+ socket.emit("game_log", { message: "Lost " + item_to_phrase(item), color: "#AB4E4F" });
+ }
+ });
+ r.gold = round(chest.gold * r.goldm) + round(chest.egold || 0);
+ r.gold = server_tax(r.gold);
+ player.gold += r.gold;
+ if (player.t) {
+ player.t.cgold += r.gold;
+ }
+ if (r.gold) {
+ socket.emit("game_log", { message: to_pretty_num(r.gold) + " gold", color: "gold" });
+ }
+ socket.emit("disappearing_text", {
+ message: "+" + r.gold,
+ x: chest.x,
+ y: chest.y - 10,
+ args: { color: "+gold", size: "large" },
+ });
+ if (!r.items.length) {
+ delete r.items;
+ }
+ resend(player, (reopen && "reopen+nc+inv") || "");
+ socket.emit("chest_opened", r);
+ } else if (chest) {
+ // var gold=round(chest.gold/parties[player.party].length);
+ r.party = true;
+ var chest = chests[data.id];
+ var reopen = {};
+ delete chests[data.id];
+ if (chest && chest.cash) {
+ add_shells(player, chest.cash, "chest", true, "override");
+ }
+ chest.items.forEach(function (item) {
// console.log(item);
- var pool=0,can={};
- parties[player.party].forEach(function(name){
- var current=players[name_to_id[name]];
- if(current && can_add_item(current,item)) pool+=current.share,can[name]=true;
- });
- var pool_winner=Math.random()*pool,pool_current=0,awarded=false;
- parties[player.party].forEach(function(name){
- if(awarded) return;
- var current=players[name_to_id[name]];
- if(current && can[name])
- {
- if(pool_winner<=pool_current+current.share)
- {
- awarded=true;
- add_item(current,item,{found:1,m:1,v:B.v}); reopen[current.id]=true;
- var ritem=cache_item(item); ritem.looter=current.name; r.items.push(ritem);
- party_emit(player.party,"game_log",{message:current.name+" found "+item_to_phrase(item),color:"#4BAEAA"});
- if(current.t) current.t.dgold+=round(G.items[item.name].g*0.6);
+ var pool = 0;
+ var can = {};
+ parties[player.party].forEach(function (name) {
+ var current = players[name_to_id[name]];
+ if (current && can_add_item(current, item)) {
+ pool += current.share;
+ can[name] = true;
}
- else pool_current+=current.share;
+ });
+ var pool_winner = Math.random() * pool;
+ var pool_current = 0;
+ var awarded = false;
+ parties[player.party].forEach(function (name) {
+ if (awarded) {
+ return;
+ }
+ var current = players[name_to_id[name]];
+ if (current && can[name]) {
+ if (pool_winner <= pool_current + current.share) {
+ awarded = true;
+ add_item(current, item, { found: 1, m: 1, v: B.v });
+ reopen[current.id] = true;
+ var ritem = cache_item(item);
+ ritem.looter = current.name;
+ r.items.push(ritem);
+ party_emit(player.party, "game_log", {
+ message: current.name + " found " + item_to_phrase(item),
+ color: "#4BAEAA",
+ });
+ if (current.t) {
+ current.t.dgold += round(G.items[item.name].g * 0.6);
+ }
+ } else {
+ pool_current += current.share;
+ }
+ }
+ });
+ if (!awarded) {
+ lostandfound_logic(item);
+ var ritem = cache_item(item);
+ ritem.looter = null;
+ ritem.lostandfound = true;
+ r.items.push(ritem);
+ party_emit(player.party, "game_log", { message: "Lost " + item_to_phrase(item), color: "#AB4E4F" });
}
});
- if(!awarded)
- {
- lostandfound_logic(item);
- var ritem=cache_item(item); ritem.looter=null; ritem.lostandfound=true; r.items.push(ritem);
- party_emit(player.party,"game_log",{message:"Lost "+item_to_phrase(item),color:"#AB4E4F"});
- }
- });
- (chest.pvp_items||[]).forEach(function(item){
- item.v=new Date();
- var pool=0,can={};
- parties[player.party].forEach(function(name){
- var current=players[name_to_id[name]];
- if(current && current.share && can_add_item(current,item)) pool+=current.share,can[name]=true;
- });
- var pool_winner=Math.random()*pool,pool_current=0,awarded=false;
- parties[player.party].forEach(function(name){
- if(awarded) return;
- var current=players[name_to_id[name]];
- if(current && can[name])
- {
- if(pool_winner<=pool_current+current.share)
- {
- awarded=true;
- add_item(current,item,{found:1,v:B.v}); reopen[current.id]=true;
- var ritem=cache_item(item); ritem.looter=current.name; ritem.pvp_loot=true; r.items.push(ritem);
- party_emit(player.party,"game_log",{message:current.name+" looted "+item_to_phrase(item),color:"#4BAEAA"});
+ (chest.pvp_items || []).forEach(function (item) {
+ item.v = new Date();
+ var pool = 0;
+ var can = {};
+ parties[player.party].forEach(function (name) {
+ var current = players[name_to_id[name]];
+ if (current && current.share && can_add_item(current, item)) {
+ pool += current.share;
+ can[name] = true;
}
- else pool_current+=current.share;
+ });
+ var pool_winner = Math.random() * pool;
+ var pool_current = 0;
+ var awarded = false;
+ parties[player.party].forEach(function (name) {
+ if (awarded) {
+ return;
+ }
+ var current = players[name_to_id[name]];
+ if (current && can[name]) {
+ if (pool_winner <= pool_current + current.share) {
+ awarded = true;
+ add_item(current, item, { found: 1, v: B.v });
+ reopen[current.id] = true;
+ var ritem = cache_item(item);
+ ritem.looter = current.name;
+ ritem.pvp_loot = true;
+ r.items.push(ritem);
+ party_emit(player.party, "game_log", {
+ message: current.name + " looted " + item_to_phrase(item),
+ color: "#4BAEAA",
+ });
+ } else {
+ pool_current += current.share;
+ }
+ }
+ });
+ if (!awarded) {
+ lostandfound_logic(item);
+ var ritem = cache_item(item);
+ ritem.looter = null;
+ ritem.pvp_loot = true;
+ ritem.lostandfound = true;
+ r.items.push(ritem);
+ party_emit(player.party, "game_log", { message: "Lost " + item_to_phrase(item), color: "#AB4E4F" });
}
});
- if(!awarded)
- {
- lostandfound_logic(item);
- var ritem=cache_item(item); ritem.looter=null; ritem.pvp_loot=true; ritem.lostandfound=true; r.items.push(ritem);
- party_emit(player.party,"game_log",{message:"Lost "+item_to_phrase(item),color:"#AB4E4F"});
+ parties[player.party].forEach(function (name) {
+ var current = players[name_to_id[name]];
+ var cgold =
+ round(chest.gold * (current.share || 0) * r.goldm) + round((chest.egold || 0) * (current.share || 0));
+ r.gold = cgold = server_tax(cgold);
+ current.gold += cgold;
+ if (current.t) {
+ current.t.cgold += cgold;
+ }
+ if (cgold) {
+ current.socket.emit("game_log", { message: to_pretty_num(cgold) + " gold", color: "gold" });
+ }
+ if (current.in == player.in) {
+ current.socket.emit("disappearing_text", {
+ message: "+" + cgold,
+ x: chest.x,
+ y: chest.y - 10,
+ args: { color: "gold", size: "large" },
+ });
+ }
+ resend(current, (reopen[current.id] && "reopen+nc+inv") || "");
+ current.socket.emit("chest_opened", r);
+ });
+ } else {
+ socket.emit("chest_opened", { id: data.id, gone: true });
+ }
+ } catch (e) {
+ delete chests[data.id]; // If this didn't exist, any exception would end up being a source for infinite gold and items
+ log_trace("#X chest_error", e);
+ return fail_response("error");
+ }
+ });
+ socket.on("auth", function (data) {
+ if (gameplay == "test" && data.passphrase != "potato salad") {
+ return socket.emit("game_log", "Wrong passphrase!");
+ }
+ if (observers[socket.id] && observers[socket.id].auth_engaged) {
+ return socket.emit("game_log", "Authorization in progress.");
+ }
+ if (dc_players[data.character]) {
+ return socket.emit("game_log", "Authorization in progress.");
+ }
+ if (!server.live || !observers[socket.id] || players[socket.id]) {
+ return;
+ }
+ if (Object.keys(players).length >= max_players) {
+ socket.emit("game_error", "Can't accept more than " + max_players + " players at this time");
+ return;
+ }
+ socket.observer_secret = randomStr(24);
+ observers[socket.id].auth_engaged = true;
+ appengine_call(
+ "start_character",
+ {
+ auth: data.user + "-" + data.auth,
+ secret: socket.observer_secret,
+ code_slot: data.code_slot,
+ character: data.character,
+ mode: gameplay,
+ ip: get_ip(socket),
+ suffix: "/" + data.character,
+ },
+ function (result) {
+ if (observers[socket.id]) {
+ observers[socket.id].auth_engaged = false;
+ }
+ if (result.failed) {
+ socket.emit("game_error", "Failed: " + result.reason);
+ return;
+ }
+ // console.log(JSON.stringify(result));
+ server_log("start_character: " + JSON.stringify(result.character.name), 1);
+ var player = { u: true, is_player: true, humanoid: true, secret: socket.observer_secret };
+ for (prop in result.character) {
+ player[prop] = result.character[prop];
+ }
+ if (!instances[player.map] || !instances[player.map].allow || instances[player.map].mount) {
+ var place = G.maps[player.map].on_exit || G.maps[B.start_map].on_exit || ["main", 0];
+ player.map = player.in = place[0];
+ player.x = G.maps[player.map].spawns[place[1]][0];
+ player.y = G.maps[player.map].spawns[place[1]][1];
+ } else {
+ player.in = player.map;
+ }
+ player.owner = data.user;
+ player.auth = data.user + "-" + data.auth;
+ player.last_sync = new Date();
+ player.socket = socket;
+ player.max_stats = result.stats;
+
+ if (data.bot == variables.bot_key) {
+ player.bot = true;
+ player.afk = "bot";
+ }
+ if (data.no_html) {
+ player.afk = "code";
+ try {
+ player.controller = (name_to_id[data.no_html] && data.no_html) || "";
+ } catch (e) {
+ player.controller = "";
+ }
+ }
+ if (!player.afk) {
+ player.afk = true;
+ }
+ if (gameplay == "test") {
+ player.name += parseInt(Math.random() * 10000);
+ }
+ player.real_id = player.id;
+ player.id = player.name;
+
+ player.total_ips = 1;
+ player.width = 26;
+ player.height = 36;
+ player.damage_type = G.classes[player.type].damage_type;
+ player.xrange = 25;
+ player.red_zone = 0;
+ player.targets = player.targets_p = player.targets_m = player.targets_u = 0;
+ player.cid = 1;
+ player.hits = 0;
+ player.kills = 0;
+ player.m = 0; // map number
+ /* party variables*/
+ player.pdps = 0;
+ player.party_length = 1;
+ player.party_luck = 0;
+ player.party_xp = 0;
+ player.party_gold = 0;
+ player.share = 0.1;
+ player.cx = player.cx || {};
+ if (!player.s) {
+ player.s = {};
+ }
+ player.t = { mdamage: 0, cgold: 0, dgold: 0, xp: 0, start: new Date() };
+ player.hitchhikers = []; // socket events to be registered after a resend
+ player.last = { attack: future_ms(-1200), attacked: really_old };
+ player.bets = {};
+ player.base = dbase;
+ player.age = parseInt(ceil(hsince(new Date(player.created)) / 24.0));
+ // player.vision=[round((data.width/2)/data.scale)+B.ext_vision,round((data.height/2)/data.scale)+B.ext_vision];
+ // player.vision[0]=min(1000,player.vision[0]);
+ // player.vision[1]=min(700,player.vision[1]);
+ player.vision = B.vision;
+
+ if (!player.verified) {
+ player.s.notverified = { ms: 30 * 60 * 1000 };
+ } else if (player.s.notverified) {
+ player.s.notverified = { ms: 100 };
+ }
+
+ if (player.guild) {
+ console.log(player.guild);
+ player.guild = player.guild.short;
+ }
+
+ if (gameplay == "hardcore") {
+ reset_player(player);
+ } // || gameplay=="test"
+
+ init_player(player);
+ if (!observers[socket.id]) {
+ // observer hang up before "auth"
+ server_log("Abrupt stop for " + result.character.name, 1);
+ if (gameplay != "hardcore" && gameplay != "test") {
+ dc_players[player.real_id] = player;
+ }
+ sync_loop();
+ return;
+ }
+ try {
+ delete_observer(socket);
+ } catch (e) {}
+
+ players[socket.id] = player;
+ resume_instance(instances[player.in]);
+ instances[player.in].players[player.id] = player;
+ pmap_add(player);
+
+ name_to_id[player.name] = socket.id;
+ id_to_id[player.id] = socket.id;
+
+ cache_player_items(player);
+ invincible_logic(player);
+ serverhop_logic(player);
+ calculate_player_stats(player);
+
+ if (data.epl == "mas" && data.receipt) {
+ player.platform = "mas";
+ verify_mas_receipt(player, data.receipt);
+ } else if (data.epl == "steam" && data.ticket) {
+ player.platform = "steam";
+ verify_steam_ticket(player, data.ticket);
+ } else {
+ player.platform = "web";
+ if (result.character.pid) {
+ player.auth_id = result.character.pid;
+ } // part of the new restriction system [02/05/19]
+ }
+
+ if (mode.drm_check) {
+ if (result.character.drm && !player.auth_id) {
+ player.s.authfail = { ms: 900000 * 1000 };
+ } else if (player.s.authfail) {
+ player.s.authfail = { ms: 100 };
+ }
+ }
+
+ if (!is_player_allowed(player)) {
+ socket.emit("disconnect_reason", "limits");
+ socket.disconnect();
+ } else {
+ var cdata = player_to_client(player);
+ player.ipass = cdata.ipass = randomStr(12);
+ player.last_ipass = new Date();
+ player.last.attack = future_ms(-10000);
+ player.last.transport = future_ms(-10000);
+ cdata.home = player.p.home;
+ cdata.friends = player.friends;
+ cdata.acx = player.p.acx;
+ cdata.xcx = player.p.xcx;
+ cdata.emx = player.p.emx;
+ cdata.info = instances[player.in].info;
+ cdata.base_gold = D.base_gold;
+ broadcast_e(true);
+ cdata.s_info = E;
+ if (result.code) {
+ cdata.code = result.code;
+ cdata.code_slot = result.code_slot;
+ cdata.code_version = result.code_version;
+ }
+ cdata.entities = send_all_xy(player, { raw: true });
+ socket.emit("start", cdata);
+ total_players++;
+ }
+ },
+ function (err) {
+ server_log("start_character_failed: " + data.character + " reason: " + err, 1);
+ if (observers[socket.id]) {
+ observers[socket.id].auth_engaged = false;
+ }
+ },
+ );
+ });
+ socket.on("use", function (data) {
+ var player = players[socket.id];
+ if (!player) {
+ return;
+ }
+ if (data.item == "hp" || data.item == "mp") {
+ if (player.last.potion && mssince(player.last.potion) < 0) {
+ return fail_response("not_ready");
+ }
+ player.last.potion = future_ms(4000);
+ if (data.item == "hp") {
+ player.hp += 50;
+ disappearing_text(socket, player, "+50", { color: "green", xy: 1, s: "hp", nohp: 1 });
+ }
+ if (data.item == "mp") {
+ player.mp += 100;
+ disappearing_text(socket, player, "+100", { color: "#006AA9", xy: 1, s: "mp", nomp: 1 });
+ }
+ player.hp = min(player.hp, player.max_hp);
+ player.mp = min(player.mp, player.max_mp);
+ // calculate_player_stats(player); [22/11/16]
+ player.cid++;
+ player.u = true;
+ socket.emit("player", player_to_client(player));
+ socket.emit("eval", { code: "pot_timeout(4000)" });
+ }
+ success_response({});
+ });
+ socket.on("friend", function (data) {
+ var player = players[socket.id];
+ if (!player) {
+ return;
+ }
+ server_log("friend: " + JSON.stringify(data));
+ if (data.event == "request") {
+ var friend = players[name_to_id[data.name || ""]];
+ if (!friend) {
+ return fail_response("friend_rleft");
+ }
+ if (in_arr(friend.owner, player.friends) || friend.owner == player.owner) {
+ return success_response("friend_already");
+ }
+ requests[player.name + "-" + friend.name] = { a: player.owner, b: friend.owner };
+ friend.socket.emit("friend", { event: "request", name: player.name });
+ return success_response("friend_rsent");
+ }
+ if (data.event == "accept") {
+ if (!requests[data.name + "-" + player.name]) {
+ return fail_response("friend_expired");
+ }
+ appengine_call(
+ "set_friends",
+ { user1: requests[data.name + "-" + player.name].a, user2: requests[data.name + "-" + player.name].b },
+ function (result) {
+ var player = players[socket.id];
+ if (result.failed) {
+ if (player) {
+ socket.emit("game_response", { response: "friend_failed", reason: result.reason });
+ }
+ return;
+ }
+ //var friend=players[name_to_id[data.name||""]];
+ //if(player)
+ //if(friend) friend.emit("friend",{event:"accepted",name:player.name});
+ },
+ function () {
+ var player = players[socket.id];
+ if (player) {
+ socket.emit("game_response", { response: "friend_failed", reason: "coms failure" });
+ }
+ },
+ );
+ requests[data.name + "-" + player.name] = false;
+ }
+ if (data.event == "unfriend") {
+ appengine_call(
+ "not_friends",
+ { user1: player.owner, user2: data.name },
+ function (result) {
+ var player = players[socket.id];
+ if (result.failed) {
+ if (player) {
+ socket.emit("game_response", { response: "unfriend_failed", reason: result.reason });
+ }
+ return;
+ }
+ },
+ function () {
+ var player = players[socket.id];
+ if (player) {
+ socket.emit("game_response", { response: "unfriend_failed", reason: "coms failure" });
+ }
+ },
+ );
+ }
+ success_response({ success: false, in_progress: true });
+ });
+ socket.on("duel", function (data) {
+ var player = players[socket.id];
+ if (!player) {
+ return;
+ }
+ if (data.event == "challenge") {
+ var invited = players[name_to_id[data.id || data.name]];
+ if (!invited || invited.id == player.id) {
+ return socket.emit("game_log", "Invalid");
+ }
+ if (invited.duel || player.duel) {
+ return socket.emit("game_log", "Already dueling");
+ }
+ invited.socket.emit("duel", { event: "chellenge", name: player.name });
+ socket.emit("game_response", { response: "challenge_sent", name: invited.name });
+ invited.socket.emit("game_response", { response: "challenge_received", name: player.name });
+ challenges[player.name] = invited.name;
+ } else if (data.event == "accept") {
+ var challenger = players[name_to_id[data.id || data.name]];
+ if (!challenger || challenges[challenger.name] != player.name) {
+ return socket.emit("game_log", "Challenge expired");
+ }
+ if (challenger.duel || player.duel) {
+ return socket.emit("game_log", "Already dueling");
+ }
+ if (is_in_pvp(challenger) || is_in_pvp(player)) {
+ return socket.emit("game_log", "Can't start a duel if any of the parties are already in a pvp zone");
+ }
+ delete challenges[challenger.name];
+ challenger.socket.emit("game_response", { response: "challenge_accepted", name: player.name });
+ var name = randomStr(20);
+ var a = [];
+ var b = [];
+ instance = create_instance(name, "duelland");
+ instance.info = {
+ seconds: (is_sdk && 20) || 60,
+ active: false,
+ A: [player_to_summary(challenger)],
+ B: [player_to_summary(player)],
+ id: name,
+ };
+ instance.info.A[0].active = true;
+ instance.info.B[0].active = true;
+ clean_slate(challenger);
+ transport_player_to(challenger, name, 1);
+ if (challenger.party) {
+ parties[challenger.party].forEach(function (p) {
+ a.push(p);
+ });
+ } else {
+ a = [challenger.name];
+ }
+ clean_slate(player);
+ transport_player_to(player, name, 2);
+ if (player.party) {
+ parties[player.party].forEach(function (p) {
+ b.push(p);
+ });
+ } else {
+ b = [player.name];
+ }
+ if (!E.duels) {
+ E.duels = {};
+ }
+ var duel = {
+ challenger: challenger.name,
+ a: a,
+ vs: player.name,
+ b: b,
+ instance: name,
+ seconds: (is_sdk && 20) || 60,
+ active: false,
+ id: name,
+ };
+ challenger.team = "A";
+ challenger.duel = duel;
+ challenger.s.stunned = { ms: 120000 };
+ resend(challenger, "u+cid");
+ player.team = "B";
+ player.duel = duel;
+ player.s.stunned = { ms: 120000 };
+ resend(player, "u+cid");
+ E.duels[name] = duel;
+ broadcast_e();
+ a.forEach(function (p) {
+ if (p != challenger.name && get_player(p)) {
+ get_player(p).socket.emit("game_response", {
+ response: "duel_started",
+ challenger: challenger.name,
+ vs: player.name,
+ id: name,
+ });
}
});
- parties[player.party].forEach(function(name){
- var current=players[name_to_id[name]],cgold=round(chest.gold*(current.share||0)*r.goldm)+round((chest.egold||0)*(current.share||0));
- r.gold=cgold=server_tax(cgold);
- current.gold+=cgold;
- if(current.t) current.t.cgold+=cgold;
- if(cgold) current.socket.emit("game_log",{message:to_pretty_num(cgold)+" gold",color:"gold"});
- if(current.in==player.in) current.socket.emit("disappearing_text",{"message":"+"+cgold,"x":chest.x,"y":chest.y-10,"args":{color:"gold","size":"large"}});
- resend(current,reopen[current.id]&&"reopen+nc+inv"||"");
- current.socket.emit("chest_opened",r);
+ b.forEach(function (p) {
+ if (p != player.name && get_player(p)) {
+ get_player(p).socket.emit("game_response", {
+ response: "duel_started",
+ challenger: challenger.name,
+ vs: player.name,
+ id: name,
+ });
+ }
});
+ } else if (data.event == "enter") {
+ if (is_in_pvp(player)) {
+ return socket.emit("game_log", "Can't join the duel from a pvp zone!");
+ }
+ if (player.duel) {
+ return socket.emit("game_log", "Already in a duel!");
+ }
+ if (!E.duels[data.id]) {
+ return socket.emit("game_log", "Duel expired");
+ }
+ if (E.duels[data.id].active) {
+ return socket.emit("game_log", "Duel already started");
+ }
+ if (!(E.duels[data.id].a.includes(player.name) || E.duels[data.id].b.includes(player.name))) {
+ return socket.emit("game_log", "Not your duel");
+ }
+ clean_slate(player);
+
+ if (E.duels[data.id].a.includes(player.name)) {
+ transport_player_to(player, data.id, 1);
+ player.team = "A";
+ } else {
+ transport_player_to(player, data.id, 2);
+ player.team = "B";
+ }
+
+ player.duel = E.duels[data.id];
+ if (player.duel.a.includes(player.name)) {
+ instances[data.id].info.A.push(player_to_summary(player));
+ instances[data.id].info.A[instances[data.id].info.A.length - 1].active = true;
+ } else {
+ instances[data.id].info.B.push(player_to_summary(player));
+ instances[data.id].info.B[instances[data.id].info.B.length - 1].active = true;
+ }
+ player.s.stunned = { ms: 120000 };
+
+ resend(player, "u+cid");
+ instance_emit(data.id, "game_chat", { message: player.name + " joined the duel!" });
}
- else
- {
- socket.emit("chest_opened",{id:data.id,gone:true});
- }
- }
- catch(e)
- {
- delete chests[data.id]; // If this didn't exist, any exception would end up being a source for infinite gold and items
- log_trace("#X chest_error",e);
- return fail_response("error");
- }
- })
- socket.on('auth',function(data){
- if(gameplay=="test" && data.passphrase!="potato salad") return socket.emit("game_log","Wrong passphrase!");
- if(observers[socket.id] && observers[socket.id].auth_engaged) return socket.emit("game_log","Authorization in progress.");
- if(dc_players[data.character]) return socket.emit("game_log","Authorization in progress.");
- if(!server.live || !observers[socket.id] || players[socket.id]) return;
- if(Object.keys(players).length>=max_players)
- {
- socket.emit("game_error","Can't accept more than "+max_players+" players at this time");
- return;
- }
- socket.observer_secret=randomStr(24);
- observers[socket.id].auth_engaged=true;
- appengine_call("start_character",{auth:data.user+'-'+data.auth,secret:socket.observer_secret,code_slot:data.code_slot,character:data.character,mode:gameplay,ip:get_ip(socket),suffix:"/"+data.character},function(result){
- if(observers[socket.id]) observers[socket.id].auth_engaged=false;
- if(result.failed){
- socket.emit("game_error","Failed: "+result.reason);
+ });
+ socket.on("party", function (data) {
+ var player = players[socket.id];
+ if (!player) {
return;
}
- // console.log(JSON.stringify(result));
- server_log('start_character: '+JSON.stringify(result.character.name),1);
- var player={u:true,is_player:true,humanoid:true,secret:socket.observer_secret};
- for(prop in result.character) player[prop]=result.character[prop];
- if(!instances[player.map] || !instances[player.map].allow || instances[player.map].mount)
- {
- var place=G.maps[player.map].on_exit||G.maps[B.start_map].on_exit||["main",0];
- player.map=player.in=place[0];
- player.x=G.maps[player.map].spawns[place[1]][0];
- player.y=G.maps[player.map].spawns[place[1]][1];
- }
- else player.in=player.map;
- player.owner=data.user;
- player.auth=data.user+'-'+data.auth;
- player.last_sync=new Date();
- player.socket=socket;
- player.max_stats=result.stats;
-
- if(data.bot==variables.bot_key) player.bot=true,player.afk="bot";
- if(data.no_html)
- {
- player.afk="code";
- try{player.controller=name_to_id[data.no_html]&&data.no_html||"";}catch(e){player.controller="";}
- }
- if(!player.afk) player.afk=true;
- if(gameplay=="test") player.name+=parseInt(Math.random()*10000);
- player.real_id=player.id; player.id=player.name;
-
- player.total_ips=1;
- player.width=26;
- player.height=36;
- player.damage_type=G.classes[player.type].damage_type;
- player.xrange=25;
- player.red_zone=0;
- player.targets=player.targets_p=player.targets_m=player.targets_u=0;
- player.cid=1;
- player.hits=0; player.kills=0;
- player.m=0; // map number
- /* party variables*/
- player.pdps=0;
- player.party_length=1;
- player.party_luck=0;
- player.party_xp=0;
- player.party_gold=0;
- player.share=0.1;
- player.cx=player.cx||{};
- if(!player.s) player.s={};
- player.t={mdamage:0,cgold:0,dgold:0,xp:0,start:new Date()};
- player.hitchhikers=[]; // socket events to be registered after a resend
- player.last={attack:future_ms(-1200),attacked:really_old};
- player.bets={};
- player.base=dbase;
- player.age=parseInt(ceil(hsince(new Date(player.created))/24.0));
- // player.vision=[round((data.width/2)/data.scale)+B.ext_vision,round((data.height/2)/data.scale)+B.ext_vision];
- // player.vision[0]=min(1000,player.vision[0]);
- // player.vision[1]=min(700,player.vision[1]);
- player.vision=B.vision;
-
- if(!player.verified) player.s.notverified={ms:30*60*1000};
- else if(player.s.notverified) player.s.notverified={ms:100};
-
- if(player.guild)
- {
- console.log(player.guild);
- player.guild=player.guild.short;
- }
-
- if(gameplay=="hardcore") reset_player(player); // || gameplay=="test"
-
- init_player(player);
- if(!observers[socket.id]) // observer hang up before "auth"
- {
- server_log("Abrupt stop for "+result.character.name,1);
- if(gameplay!="hardcore" && gameplay!="test") dc_players[player.real_id]=player;
- sync_loop();
- return;
- }
- try{delete_observer(socket)}catch(e){}
-
- players[socket.id]=player;
- resume_instance(instances[player.in]);
- instances[player.in].players[player.id]=player; pmap_add(player);
-
- name_to_id[player.name]=socket.id;
- id_to_id[player.id]=socket.id;
-
- cache_player_items(player);
- invincible_logic(player);
- serverhop_logic(player);
- calculate_player_stats(player);
-
- if(data.epl=="mas" && data.receipt)
- {
- player.platform="mas";
- verify_mas_receipt(player,data.receipt);
- }
- else if(data.epl=="steam" && data.ticket)
- {
- player.platform="steam";
- verify_steam_ticket(player,data.ticket);
- }
- else
- {
- player.platform="web";
- if(result.character.pid) player.auth_id=result.character.pid; // part of the new restriction system [02/05/19]
- }
-
- if(mode.drm_check)
- {
- if(result.character.drm && !player.auth_id) player.s.authfail={ms:900000*1000};
- else if(player.s.authfail) player.s.authfail={ms:100};
- }
-
- if(!is_player_allowed(player))
- {
- socket.emit("disconnect_reason","limits");
- socket.disconnect();
- }
- else
- {
- var cdata=player_to_client(player);
- player.ipass=cdata.ipass=randomStr(12);
- player.last_ipass=new Date();
- player.last.attack=future_ms(-10000);
- player.last.transport=future_ms(-10000);
- cdata.home=player.p.home;
- cdata.friends=player.friends;
- cdata.acx=player.p.acx;
- cdata.xcx=player.p.xcx;
- cdata.emx=player.p.emx;
- cdata.info=instances[player.in].info;
- cdata.base_gold=D.base_gold;
- broadcast_e(true);
- cdata.s_info=E;
- if(result.code)
- {
- cdata.code=result.code;
- cdata.code_slot=result.code_slot;
- cdata.code_version=result.code_version;
+ if (data.event == "invite") {
+ // if(player.party && player.party!=player.name) { socket.emit("game_log","Only the party leader can send invites"); return; }
+ if (player.party && (parties[player.party].length >= limits.party_max || player.party_length >= limits.party)) {
+ return fail_response("party_full");
}
- cdata.entities=send_all_xy(player,{raw:true});
- socket.emit('start',cdata);
- total_players++;
- }
-
- },function(err){
- server_log('start_character_failed: '+data.character+" reason: "+err,1);
- if(observers[socket.id]) observers[socket.id].auth_engaged=false;
- })
- });
- socket.on('use',function(data){
- var player=players[socket.id]; if(!player) return;
- if(data.item=="hp" || data.item=="mp")
- {
- if(player.last.potion && mssince(player.last.potion)<0) return fail_response("not_ready");
- player.last.potion=future_ms(4000);
- if(data.item=="hp") player.hp+=50,disappearing_text(socket,player,"+50",{color:"green",xy:1,s:"hp",nohp:1});
- if(data.item=="mp") player.mp+=100,disappearing_text(socket,player,"+100",{color:"#006AA9",xy:1,s:"mp",nomp:1});
- player.hp=min(player.hp,player.max_hp); player.mp=min(player.mp,player.max_mp);
- // calculate_player_stats(player); [22/11/16]
- player.cid++; player.u=true;
- socket.emit("player",player_to_client(player));
- socket.emit("eval",{code:"pot_timeout(4000)"});
- }
- success_response({})
- });
- socket.on('friend',function(data){
- var player=players[socket.id];
- if(!player) return;
- server_log("friend: "+JSON.stringify(data));
- if(data.event=="request")
- {
- var friend=players[name_to_id[data.name||""]];
- if(!friend) return fail_response("friend_rleft");
- if(in_arr(friend.owner,player.friends) || friend.owner==player.owner) return success_response("friend_already");
- requests[player.name+"-"+friend.name]={"a":player.owner,"b":friend.owner};
- friend.socket.emit("friend",{event:"request",name:player.name});
- return success_response("friend_rsent");
- }
- if(data.event=="accept")
- {
- if(!requests[data.name+"-"+player.name]) return fail_response("friend_expired");
- appengine_call("set_friends",{user1:requests[data.name+"-"+player.name].a,user2:requests[data.name+"-"+player.name].b},function(result){
- var player=players[socket.id];
- if(result.failed)
- {
- if(player) socket.emit("game_response",{response:"friend_failed",reason:result.reason});
- return;
+ var invited = players[name_to_id[data.id || data.name]];
+ if (!invited || invited.id == player.id) {
+ return fail_response("invalid");
}
- //var friend=players[name_to_id[data.name||""]];
- //if(player)
- //if(friend) friend.emit("friend",{event:"accepted",name:player.name});
- },function(){
- var player=players[socket.id];
- if(player) socket.emit("game_response",{response:"friend_failed",reason:"coms failure"});
- });
- requests[data.name+"-"+player.name]=false;
- }
- if(data.event=="unfriend")
- {
- appengine_call("not_friends",{user1:player.owner,user2:data.name},function(result){
- var player=players[socket.id];
- if(result.failed)
- {
- if(player) socket.emit("game_response",{response:"unfriend_failed",reason:result.reason});
- return;
+ if (player.party && player.party == invited.party) {
+ return success_response("already_in_party");
}
- },function(){
- var player=players[socket.id];
- if(player) socket.emit("game_response",{response:"unfriend_failed",reason:"coms failure"});
- });
- }
- success_response({success:false,in_progress:true});
- });
- socket.on('duel',function(data){
- var player=players[socket.id];
- if(!player) return;
- if(data.event=="challenge")
- {
- var invited=players[name_to_id[data.id||data.name]];
- if(!invited || invited.id==player.id) return socket.emit("game_log","Invalid");
- if(invited.duel || player.duel) return socket.emit("game_log","Already dueling");
- invited.socket.emit("duel",{event:"chellenge",name:player.name});
- socket.emit("game_response",{"response":"challenge_sent",name:invited.name});
- invited.socket.emit("game_response",{"response":"challenge_received",name:player.name});
- challenges[player.name]=invited.name;
- }
- else if(data.event=="accept")
- {
- var challenger=players[name_to_id[data.id||data.name]];
- if(!challenger || challenges[challenger.name]!=player.name) return socket.emit("game_log","Challenge expired");
- if(challenger.duel || player.duel) return socket.emit("game_log","Already dueling");
- if(is_in_pvp(challenger) || is_in_pvp(player)) return socket.emit("game_log","Can't start a duel if any of the parties are already in a pvp zone");
- delete challenges[challenger.name];
- challenger.socket.emit("game_response",{"response":"challenge_accepted",name:player.name});
- var name=randomStr(20),a=[],b=[];
- instance=create_instance(name,"duelland");
- instance.info={"seconds":is_sdk&&20||60,"active":false,"A":[player_to_summary(challenger)],"B":[player_to_summary(player)],"id":name};
- instance.info.A[0].active=true;
- instance.info.B[0].active=true;
- clean_slate(challenger); transport_player_to(challenger,name,1); if(challenger.party) parties[challenger.party].forEach(function(p){a.push(p)}); else a=[challenger.name];
- clean_slate(player); transport_player_to(player,name,2); if(player.party) parties[player.party].forEach(function(p){b.push(p)}); else b=[player.name];
- if(!E.duels) E.duels={};
- var duel={"challenger":challenger.name,a:a,"vs":player.name,b:b,"instance":name,"seconds":is_sdk&&20||60,"active":false,"id":name};
- challenger.team="A"; challenger.duel=duel; challenger.s.stunned={ms:120000}; resend(challenger,"u+cid");
- player.team="B"; player.duel=duel; player.s.stunned={ms:120000}; resend(player,"u+cid");
- E.duels[name]=duel;
- broadcast_e();
- a.forEach(function(p){ if(p!=challenger.name && get_player(p)) get_player(p).socket.emit("game_response",{response:"duel_started",challenger:challenger.name,vs:player.name,id:name}); });
- b.forEach(function(p){ if(p!=player.name && get_player(p)) get_player(p).socket.emit("game_response",{response:"duel_started",challenger:challenger.name,vs:player.name,id:name}); });
- }
- else if(data.event=="enter")
- {
- if(is_in_pvp(player)) return socket.emit("game_log","Can't join the duel from a pvp zone!");
- if(player.duel) return socket.emit("game_log","Already in a duel!");
- if(!E.duels[data.id]) return socket.emit("game_log","Duel expired");
- if(E.duels[data.id].active) return socket.emit("game_log","Duel already started");
- if(!(E.duels[data.id].a.includes(player.name) || E.duels[data.id].b.includes(player.name))) return socket.emit("game_log","Not your duel");
- clean_slate(player);
-
- if(E.duels[data.id].a.includes(player.name)) transport_player_to(player,data.id,1),player.team="A";
- else transport_player_to(player,data.id,2),player.team="B";
-
- player.duel=E.duels[data.id];
- if(player.duel.a.includes(player.name)) instances[data.id].info.A.push(player_to_summary(player)),instances[data.id].info.A[instances[data.id].info.A.length-1].active=true;
- else instances[data.id].info.B.push(player_to_summary(player)),instances[data.id].info.B[instances[data.id].info.B.length-1].active=true;
- player.s.stunned={ms:120000};
-
- resend(player,"u+cid");
- instance_emit(data.id,"game_chat",{message:player.name+" joined the duel!"});
- }
- });
- socket.on('party',function(data){
- var player=players[socket.id]; if(!player) return;
- if(data.event=="invite")
- {
- // if(player.party && player.party!=player.name) { socket.emit("game_log","Only the party leader can send invites"); return; }
- if(player.party && (parties[player.party].length>=limits.party_max || player.party_length>=limits.party)) return fail_response("party_full");
- var invited=players[name_to_id[data.id||data.name]];
- if(!invited || invited.id==player.id) return fail_response("invalid");
- if(player.party && player.party==invited.party) return success_response("already_in_party");
- // if(invited.party) { socket.emit("game_log",invited.name+" is already partying"); return; }
- invited.socket.emit("invite",{name:player.name});
- socket.emit("game_log","Invited "+invited.name+" to party");
- if(!invitations[player.name]) invitations[player.name]={};
- invitations[player.name][invited.id]=1;
- }
- if(data.event=="request")
- {
- // if(player.party) { return; }
- var invited=players[name_to_id[data.id||data.name]];
- if(!invited || invited.id==player.id) return fail_response("invalid");
- if(player.party && player.party==invited.party) return success_response("already_in_party");
- // if(!invited.party) { socket.emit("game_log",invited.name+" isn't partying"); return; }
- invited.socket.emit("request",{name:player.name});
- socket.emit("game_log","Requested to join "+invited.name+"'s party");
- if(!requests[player.name]) requests[player.name]={};
- requests[player.name][invited.id]=1;
- }
- if(data.event=="accept")
- {
- var inviter=players[name_to_id[data.name]];
- // if(player.party) { socket.emit("party_update",{list:parties[player.party],party:party_to_client(player.party)}); socket.emit("game_log","Already partying"); return; }
- // if(!inviter || (inviter.party && inviter.party!=inviter.name)) { socket.emit("game_log","Party was disbanded"); return; }
- if(!inviter) return fail_response("player_gone",{name:data.name})
- if(inviter.party && (parties[inviter.party].length>=limits.party_max || inviter.party_length>=limits.party)) return fail_response("party_full");
- if(!invitations[inviter.name] || !invitations[inviter.name][player.id]) return fail_response("invitation_expired");
- if(player.party && player.party==inviter.party) return success_response("already_in_party");
- if(player.party)
- {
- leave_party(player.party,player);
- socket.emit("party_update",{});
- socket.emit("game_log","Left your current party");
+ // if(invited.party) { socket.emit("game_log",invited.name+" is already partying"); return; }
+ invited.socket.emit("invite", { name: player.name });
+ socket.emit("game_log", "Invited " + invited.name + " to party");
+ if (!invitations[player.name]) {
+ invitations[player.name] = {};
+ }
+ invitations[player.name][invited.id] = 1;
}
- invitations[inviter.name][player.id]=0;
- if(!inviter.party)
- {
- inviter.party=inviter.name;
- parties[inviter.name]=[inviter.name];
- resend(inviter,"nc+u+cid");
- delete requests[inviter.name];
- if(!players[name_to_id[data.name]]) return fail_response("player_gone",{name:data.name}); // these repetitions are all because socket.emit's can cause in-line disconnects and disband parties right after creation [07/08/20]
+ if (data.event == "request") {
+ // if(player.party) { return; }
+ var invited = players[name_to_id[data.id || data.name]];
+ if (!invited || invited.id == player.id) {
+ return fail_response("invalid");
+ }
+ if (player.party && player.party == invited.party) {
+ return success_response("already_in_party");
+ }
+ // if(!invited.party) { socket.emit("game_log",invited.name+" isn't partying"); return; }
+ invited.socket.emit("request", { name: player.name });
+ socket.emit("game_log", "Requested to join " + invited.name + "'s party");
+ if (!requests[player.name]) {
+ requests[player.name] = {};
+ }
+ requests[player.name][invited.id] = 1;
}
- player.party=inviter.party;
- parties[inviter.party].push(player.name);
- party_emit(player.party,"party_update",{list:parties[inviter.party],party:party_to_client(inviter.party),message:player.name+" joined the party"+(inviter.party!=inviter.name && " with "+inviter.name+"'s invite" || "")});
- resend(player,"nc+u+cid");
- delete requests[player.name];
- delete requests[inviter.name]; // optional
- }
- if(data.event=="raccept")
- {
- var requester=players[name_to_id[data.name]];
- if(!requester) return fail_response("player_gone",{name:data.name});
- // if(requester.party) { socket.emit("game_log","Already partying"); return; }
- if(player.party && (parties[player.party].length>=limits.party_max || player.party_length>=limits.party)) return fail_response("party_full");
- if(!requests[requester.name] || !requests[requester.name][player.id]) return fail_response("request_expired");
- if(player.party && player.party==requester.party) return success_response("already_in_party");
- if(requester.party)
- {
- leave_party(requester.party,requester);
- requester.socket.emit("party_update",{});
- requester.socket.emit("game_log","Left the party");
- if(!players[name_to_id[data.name]]) return fail_response("player_gone",{name:data.name});
- }
- requests[requester.name][player.id]=0;
- if(!player.party)
- {
- player.party=player.name;
- parties[player.name]=[player.name];
- resend(player,"nc+u+cid");
+ if (data.event == "accept") {
+ var inviter = players[name_to_id[data.name]];
+ // if(player.party) { socket.emit("party_update",{list:parties[player.party],party:party_to_client(player.party)}); socket.emit("game_log","Already partying"); return; }
+ // if(!inviter || (inviter.party && inviter.party!=inviter.name)) { socket.emit("game_log","Party was disbanded"); return; }
+ if (!inviter) {
+ return fail_response("player_gone", { name: data.name });
+ }
+ if (
+ inviter.party &&
+ (parties[inviter.party].length >= limits.party_max || inviter.party_length >= limits.party)
+ ) {
+ return fail_response("party_full");
+ }
+ if (!invitations[inviter.name] || !invitations[inviter.name][player.id]) {
+ return fail_response("invitation_expired");
+ }
+ if (player.party && player.party == inviter.party) {
+ return success_response("already_in_party");
+ }
+ if (player.party) {
+ leave_party(player.party, player);
+ socket.emit("party_update", {});
+ socket.emit("game_log", "Left your current party");
+ }
+ invitations[inviter.name][player.id] = 0;
+ if (!inviter.party) {
+ inviter.party = inviter.name;
+ parties[inviter.name] = [inviter.name];
+ resend(inviter, "nc+u+cid");
+ delete requests[inviter.name];
+ if (!players[name_to_id[data.name]]) {
+ return fail_response("player_gone", { name: data.name });
+ } // these repetitions are all because socket.emit's can cause in-line disconnects and disband parties right after creation [07/08/20]
+ }
+ player.party = inviter.party;
+ parties[inviter.party].push(player.name);
+ party_emit(player.party, "party_update", {
+ list: parties[inviter.party],
+ party: party_to_client(inviter.party),
+ message:
+ player.name +
+ " joined the party" +
+ ((inviter.party != inviter.name && " with " + inviter.name + "'s invite") || ""),
+ });
+ resend(player, "nc+u+cid");
delete requests[player.name];
+ delete requests[inviter.name]; // optional
}
- requester.party=player.party;
- parties[player.party].push(requester.name);
- party_emit(requester.party,"party_update",{list:parties[player.party],party:party_to_client(player.party),message:requester.name+" joined the party"});
- resend(requester,"nc+u+cid");
- delete requests[requester.name];
- delete requests[player.name]; // optional
- }
- if(data.event=="leave")
- {
- if(!player.party) { socket.emit("party_update",{}); return success_response({}); }
- leave_party(player.party,player);
- socket.emit("party_update",{});
- socket.emit("game_log","Left the party");
- resend(player,"nc+u+cid");
- }
- if(data.event=="kick")
- {
- if(!player.party) return success_response({});
- // if(player.party && player.party!=player.name) { socket.emit("game_log","Only the party leader can kick someone"); return; }
- if(!in_arr(data.name,parties[player.party])) { socket.emit("party_update",{list:parties[player.party],party:party_to_client(player.party)}); return success_response({}); }
- if(parties[player.party].indexOf(player.name)>parties[player.party].indexOf(data.name)) return fail_response("cant_kick");
- var kicked=players[name_to_id[data.name]];
- if(!kicked) return fail_response("player_gone");
- leave_party(player.party,kicked);
- if(player.party) party_emit(player.party,"game_log",player.name+" kicked "+kicked.name);
- kicked.socket.emit("party_update",{});
- kicked.socket.emit("game_log","You've been removed from the party");
- resend(kicked,"nc+u+cid");
- }
- success_response({});
- });
- socket.on('magiport',function(data){
- var player=players[socket.id]; if(!player) return;
- if(magiportations[data.name] && magiportations[data.name][player.name] && get_player(data.name))
- {
- delete magiportations[data.name][player.name];
- if(instances[get_player(data.name).in].mount!=instances[player.in].mount) return fail_response("cant_in_bank");
- if(!magiport_someone(player,get_player(data.name))) return fail_response("invalid");
- return success_response({});
- }
- else
- {
- player.socket.emit("game_response",{response:"magiport_gone",name:data.name});
- return fail_response("inviter_gone");
- }
- });
- socket.on('trade',function(data){
- var player=players[socket.id];
- if(!player) return;
- if(data.event=="show" && player.p.trades!=1)
- {
- player.p.trades=1;
- reslot_player(player);
- resend(player,"nc+u+cid");
- }
- else if(data.event=="hide" && player.p.trades!=null)
- {
- player.p.trades=null;
- reslot_player(player);
- resend(player,"nc+u+cid");
- }
- });
- socket.on('signup',function(data){
- var player=players[socket.id]; if(!player) return;
- if(!signups[player.name]) disappearing_text(false_socket,npcs.bean,"+1",{color:"#4D9A59",xy:1});
- signups[player.name]=true;
- socket.emit("game_response",{response:"signed_up"});
- });
- socket.on('join',function(data){
- var player=players[socket.id]; if(!player) return;
- if(player.type=="merchant") return fail_response("no_merchants");
- if(player.s.hopsickness) return fail_response("cant_when_sick");
- if(player.user) return fail_response("cant_in_bank");
- if(data.name=="goobrawl" && events.goobrawl)
- {
- if(player.map!="goobrawl") transport_player_to(player,"goobrawl");
- }
- else if(data.name=="crabxx" && events.crabxx)
- {
- if(simple_distance(player,{map:"main",x:-1000,y:1700})>200) transport_player_to(player,"main",[-1000,1700,0,40]);
- }
- else if(data.name=="franky" && events.franky)
- {
- if(simple_distance(player,{map:"level2w",x:-300,y:150})>200) transport_player_to(player,"level2w",[-300,150,0,40]);
- }
- else if(data.name=="icegolem" && events.icegolem)
- {
- if(simple_distance(player,{map:"winterland",x:820,y:425})>100) transport_player_to(player,"winterland",[820,425,0,10]);
- }
- else if(data.name=="abtesting" && E.abtesting)
- {
- if(player.map!="abtesting" || !player.team)
- {
- if(ssince(timers.abtesting_start)>120 && (!player.p.abtesting || player.p.abtesting[0]!=E.abtesting.id))
- return fail_response("join_too_late");
-
- if(player.p.abtesting && player.p.abtesting[0]==E.abtesting.id) player.team=player.p.abtesting[1];
- else player.team=random_one(["A","B"]);
-
- player.p.abtesting=[E.abtesting.id,player.team];
-
- player.team=player.p.abtesting[1]; // transport does a restore ...
- save_state(player);
-
-
- if(player.team=="A") transport_player_to(player,"abtesting",2);
- else if(player.team=="B") transport_player_to(player,"abtesting",3);
-
- resend(player,"cid");
- }
- }
- else
- return fail_response("cant_join");
- success_response();
- });
- socket.on('stop',function(data){
- var player=players[socket.id],change=false;
- if(!player) return;
- if(!data || !data.action)
- {
- if(player.s.invis) step_out_of_invis(player),change=true;
- if(Object.keys(player.c).length) player.c={},change=true;
- }
- else if(data.action=="invis")
- {
- if(player.s.invis) step_out_of_invis(player),change=true;
- }
- else if(data.action=="channeling")
- {
- if(Object.keys(player.c).length) player.c={},change=true;
- }
- else if(data.action=="teleport" || data.action=="town")
- {
- if(player.c.town) { delete player.c.town; change=true;}
- }
- else if(data.action=="revival")
- {
- if(player.c.revival) { delete player.c.revival; change=true;}
- }
- if(change) resend(player,"u+cid");
- success_response();
- });
- socket.on('tarot',function(data){
- var player=players[socket.id]; if(!player) return;
- var npc=G.maps[player.map].ref.twitch;
- if(!npc || simple_distance(npc,player)>500) return socket.emit("game_response","distance");
- for(var name in player.s) if(name.startsWith("tarot")) return socket.emit("game_response","tarot_exists");
-
- });
- socket.on('bet',function(data){
- if(!instances.tavern) return;
- var player=players[socket.id];
- if(!player || player.user || player.map!="tavern" && !is_sdk) return;
- if(player.s.xshotted) return socket.emit("game_response","bet_xshot");
- if(data.type=="roulette")
- {
- if(!is_sdk) return; // Old routine [23/08/18]
- if(!data.odds) data.odds="black"; data.odds=""+data.odds;
- data.gold=max(1,parseInt(data.gold)||1);
- if(!tavern.roulette.odds[data.odds]) return;
- if(tavern.roulette.state!="bets") { socket.emit("game_log","Not taking bets yet!"); return; }
- if(Object.keys(player.bets).length>=5) { socket.emit("game_log","You already have 5 active bets"); return; }
- if(player.goldplayer.gold) return socket.emit("game_response","gold_not_enough");
- if(win-edge-gold>(S.gold-house_debt())*0.40) return socket.emit("game_response","tavern_gold_not_enough");
- if(Object.keys(player.bets).length) return socket.emit("game_response","tavern_dice_exist");
- // if(Object.keys(player.bets).length>=5) return socket.emit("game_response","tavern_too_many_bets");
- // socket.emit("game_log",{"message":"Bet accepted on "+num.toFixed(2)+" "+dir.toUpperCase(),"color":"white"});
- socket.emit("game_log",{"message":"Num: "+num.toFixed(2)+" "+dir.toUpperCase(),"color":"white"});
- socket.emit("game_log",{"message":"Bet: "+to_pretty_num(gold)+" gold","color":"gray"});
-
- var rid=randomStr(10);
- player.gold-=gold;
- player.bets[rid]={id:rid,type:"dice",num:num,gold:gold,dir:dir,pid:socket.id,state:"bet",win:win,edge:edge,odds:odds};
- tavern.dice.players[player.socket.id]=true;
- instance_emit(tavern,"tavern",{event:"bet",name:player.name,type:"dice",num:num,gold:gold,dir:dir});
- resend(player,"reopen+nc");
- }
- if(data.type=="slots")
- {
- var gold=1000000;
- if(gold>player.gold) return socket.emit("game_response","gold_not_enough");
- player.gold-=gold; S.gold+=gold;
- player.q.slots={ms:3000};
- xy_emit(player,"ui",{type:"slots",player:player.name});
- socket.emit("game_response",{response:"gold_use",gold:gold,game:data.type});
- resend(player,"u+cid+reopen+nc");
- }
- });
- socket.on('tavern',function(data){
- if(data.event=="info")
- {
- socket.emit("tavern",{event:"info",edge:house_edge(),"max":parseInt((S.gold-house_debt())*0.40)})
- }
- });
- socket.on('play',function(data){
-
- });
- socket.on('pet',function(data){
- var player=players[socket.id]; if(!player) return;
- if(!player.monster) player.monster=new_monster(player.in,{type:player.pet,stype:"pet",x:player.x,y:player.y,owner:player.name,name:"Skimpy"});
- })
- socket.on('whistle',function(data){
- if(!player.monster) return;
- xy_emit(player.monster,"disappear",{id:player.monster.id});
- player.monster.x=player.x;
- player.monster.y=player.y;
- player.monster.map=player.map;
- player.monster.in=player.in;
- player.monster.u=true;
- player.monster.cid++;
- });
- socket.on('list_pvp',function(data){
- var plist=[];
- for(var j=1;j<201;j++)
- {
- if(pend-j<0) break;
- plist.push(pwns[(pend-j)%200]);
- }
- socket.emit("pvp_list",{code:data && data.code,list:plist})
- });
- socket.on('players',function(data){
- var player=players[socket.id],sdata=[];
- if(!player) return; // || is_pvp
- for(var id in players)
- {
- var current=players[id],mapn=current.map;
- current.age=parseInt(ceil(hsince(new Date(current.created))/24.0));
- if(is_pvp)
- {
- mapn="Unknown";
- sdata.push({name:"Hidden",map:mapn,age:current.age,level:current.level,type:current.type,afk:current.afk&&1||0,party:current.party&&"Hidden"||'',kills:current.kills});
- }
- else if(!is_in_pvp(current)) sdata.push({name:current.name,map:mapn,age:current.age,level:current.level,type:current.type,afk:current.afk&&1||0,party:current.party||''});
- }
- socket.emit("players",sdata);
- });
- socket.on('pets',function(data){
- var player=players[socket.id],sdata=[];
- if(!player) return; // || is_pvp
- for(var id in player.p.pets||{})
- {
- sdata.push(player.p.pets[id]);
- }
- socket.emit("players",sdata);
- });
- socket.on('harakiri',function(data){
- var player=players[socket.id];
- if(!player || player.rip) return;
- defeat_player(player);
- if(!player.rip) rip(player);
- disappearing_text(player.socket,player,"SEPPUKU",{xy:1,size:"huge",color:"#6F76A6"});
- resend(player,"u+cid");
- });
- socket.on('deepsea',function(data){
- return;
- var player=players[socket.id];
- if(!player || player.rip || player.tskin=="deepsea") return;
- player.tskin="deepsea";
- disappearing_text(player.socket,player,"ROARRRRRRR",{xy:1,size:"huge",color:"#60A975"});
- resend(player,"u+cid");
- });
- socket.on('blend',function(data){
- var player=players[socket.id],min=99999,x=null;
- if(!player || player.rip) return;
- for(var id in instances[player.in].monsters||{})
- {
- var m=instances[player.in].monsters[id],c=distance(m,player,true);
- if(c= limits.party_max || player.party_length >= limits.party)) {
+ return fail_response("party_full");
}
- }catch(e){log_trace("#X DCERROR",e);}
- }
- if(observer)
- {
- server_log("Disconnected Observer: "+socket.id+" Calls: "+socket.total_calls);
- try{
- delete_observer(socket);
- }catch(e){log_trace("#X DCERRORO ",e);}
- }
- });
- socket.on('shutdown',function(data){
- if(data.pass!=variables.master) return;
- if(data.reason) broadcast("disconnect_reason",data.reason);
- setTimeout(shutdown_routine,10000);
- });
- socket.on('notice',function(data){
- if(data.pass!=variables.master) return;
- broadcast("notice",{message:data.message});
- });
- socket.on('render',function(data){
- if(data.pass!=variables.master) return;
- var player=players[socket.id];
- var output="",json_output=undefined,window=null,after="";
- try{
- eval(data.code);
- }
- catch(e)
- {
- output="Exception: "+e;
- }
- if(window) socket.emit('simple_eval',{window:window,after:after,code:'for(var id in data.window) window[id]=data.window[id]; eval(data.after);'});
- else if(json_output!==undefined) socket.emit('simple_eval',{output:output,json_output:json_output,code:'show_json(data.json_output)'});
- else socket.emit('simple_eval',{output:output,json_output:json_output,code:'show_modal("
"+data.output+"
")'});
- resend(player,"reopen+u+cid");
- });
- socket.on('error',function(data){
- // socket.emit("error") brings server down [16/02/22]
- });
- socket.on('eval',function(data){
- if(data.command)
- {
- var player=players[socket.id]; if(!player) return;
- if(player.map!="cyberland" || player.rip) return player.socket.emit("game_log","Not connected to the mainframe");
- if(data.command=="hello")
- {
- xy_emit({"in":"cyberland","map":"cyberland","x":0,"y":-100},"chat_log",{owner:"mainframe",message:"hi",id:"mainframe"});
- }
- else if(data.command=="give")
- {
- xy_emit({"in":"cyberland","map":"cyberland","x":0,"y":-100},"chat_log",{owner:"mainframe",message:"what?",id:"mainframe"});
- }
- else if(data.command.startsWith("swap"))
- {
- var numbers=data.command.split(" ");
- if(numbers.length!=3)
- xy_emit({"in":"cyberland","map":"cyberland","x":0,"y":-100},"chat_log",{owner:"mainframe",message:"...",id:"mainframe"});
- else
- {
- var a=parseInt(numbers[1]),b=parseInt(numbers[2]);
- if(0<=a && a<42 && 0<=b && b<42)
- {
- if(a==player.p.item_num) player.p.item_num=b;
- else if(b==player.p.item_num) player.p.item_num=a;
- xy_emit({"in":"cyberland","map":"cyberland","x":0,"y":-100},"chat_log",{owner:"mainframe",message:"done",id:"mainframe"});
- }
- else
- xy_emit({"in":"cyberland","map":"cyberland","x":0,"y":-100},"chat_log",{owner:"mainframe",message:"ugh, ok",id:"mainframe"});
+ if (!requests[requester.name] || !requests[requester.name][player.id]) {
+ return fail_response("request_expired");
+ }
+ if (player.party && player.party == requester.party) {
+ return success_response("already_in_party");
+ }
+ if (requester.party) {
+ leave_party(requester.party, requester);
+ requester.socket.emit("party_update", {});
+ requester.socket.emit("game_log", "Left the party");
+ if (!players[name_to_id[data.name]]) {
+ return fail_response("player_gone", { name: data.name });
}
+ }
+ requests[requester.name][player.id] = 0;
+ if (!player.party) {
+ player.party = player.name;
+ parties[player.name] = [player.name];
+ resend(player, "nc+u+cid");
+ delete requests[player.name];
+ }
+ requester.party = player.party;
+ parties[player.party].push(requester.name);
+ party_emit(requester.party, "party_update", {
+ list: parties[player.party],
+ party: party_to_client(player.party),
+ message: requester.name + " joined the party",
+ });
+ resend(requester, "nc+u+cid");
+ delete requests[requester.name];
+ delete requests[player.name]; // optional
}
- else if(data.command=="stop")
- {
- xy_emit({"in":"cyberland","map":"cyberland","x":0,"y":-100},"chat_log",{owner:"mainframe",message:"mechagnomes assemble",id:"mainframe"});
- get_monsters("mechagnome").forEach(function(m){
- if(m.target) stop_pursuit(m,{stop:1,cause:"stop()"});
- //else m.irregular=3;
+ if (data.event == "leave") {
+ if (!player.party) {
+ socket.emit("party_update", {});
+ return success_response({});
+ }
+ leave_party(player.party, player);
+ socket.emit("party_update", {});
+ socket.emit("game_log", "Left the party");
+ resend(player, "nc+u+cid");
+ }
+ if (data.event == "kick") {
+ if (!player.party) {
+ return success_response({});
+ }
+ // if(player.party && player.party!=player.name) { socket.emit("game_log","Only the party leader can kick someone"); return; }
+ if (!in_arr(data.name, parties[player.party])) {
+ socket.emit("party_update", { list: parties[player.party], party: party_to_client(player.party) });
+ return success_response({});
+ }
+ if (parties[player.party].indexOf(player.name) > parties[player.party].indexOf(data.name)) {
+ return fail_response("cant_kick");
+ }
+ var kicked = players[name_to_id[data.name]];
+ if (!kicked) {
+ return fail_response("player_gone");
+ }
+ leave_party(player.party, kicked);
+ if (player.party) {
+ party_emit(player.party, "game_log", player.name + " kicked " + kicked.name);
+ }
+ kicked.socket.emit("party_update", {});
+ kicked.socket.emit("game_log", "You've been removed from the party");
+ resend(kicked, "nc+u+cid");
+ }
+ success_response({});
+ });
+ socket.on("magiport", function (data) {
+ var player = players[socket.id];
+ if (!player) {
+ return;
+ }
+ if (magiportations[data.name] && magiportations[data.name][player.name] && get_player(data.name)) {
+ delete magiportations[data.name][player.name];
+ if (instances[get_player(data.name).in].mount != instances[player.in].mount) {
+ return fail_response("cant_in_bank");
+ }
+ if (!magiport_someone(player, get_player(data.name))) {
+ return fail_response("invalid");
+ }
+ return success_response({});
+ } else {
+ player.socket.emit("game_response", { response: "magiport_gone", name: data.name });
+ return fail_response("inviter_gone");
+ }
+ });
+ socket.on("trade", function (data) {
+ var player = players[socket.id];
+ if (!player) {
+ return;
+ }
+ if (data.event == "show" && player.p.trades != 1) {
+ player.p.trades = 1;
+ reslot_player(player);
+ resend(player, "nc+u+cid");
+ } else if (data.event == "hide" && player.p.trades != null) {
+ player.p.trades = null;
+ reslot_player(player);
+ resend(player, "nc+u+cid");
+ }
+ });
+ socket.on("signup", function (data) {
+ var player = players[socket.id];
+ if (!player) {
+ return;
+ }
+ if (!signups[player.name]) {
+ disappearing_text(false_socket, npcs.bean, "+1", { color: "#4D9A59", xy: 1 });
+ }
+ signups[player.name] = true;
+ socket.emit("game_response", { response: "signed_up" });
+ });
+ socket.on("join", function (data) {
+ var player = players[socket.id];
+ if (!player) {
+ return;
+ }
+ if (player.type == "merchant") {
+ return fail_response("no_merchants");
+ }
+ if (player.s.hopsickness) {
+ return fail_response("cant_when_sick");
+ }
+ if (player.user) {
+ return fail_response("cant_in_bank");
+ }
+ if (data.name == "goobrawl" && events.goobrawl) {
+ if (player.map != "goobrawl") {
+ transport_player_to(player, "goobrawl");
+ }
+ } else if (data.name == "crabxx" && events.crabxx) {
+ if (simple_distance(player, { map: "main", x: -1000, y: 1700 }) > 200) {
+ transport_player_to(player, "main", [-1000, 1700, 0, 40]);
+ }
+ } else if (data.name == "franky" && events.franky) {
+ if (simple_distance(player, { map: "level2w", x: -300, y: 150 }) > 200) {
+ transport_player_to(player, "level2w", [-300, 150, 0, 40]);
+ }
+ } else if (data.name == "icegolem" && events.icegolem) {
+ if (simple_distance(player, { map: "winterland", x: 820, y: 425 }) > 100) {
+ transport_player_to(player, "winterland", [820, 425, 0, 10]);
+ }
+ } else if (data.name == "abtesting" && E.abtesting) {
+ if (player.map != "abtesting" || !player.team) {
+ if (
+ ssince(timers.abtesting_start) > 120 &&
+ (!player.p.abtesting || player.p.abtesting[0] != E.abtesting.id)
+ ) {
+ return fail_response("join_too_late");
+ }
+
+ if (player.p.abtesting && player.p.abtesting[0] == E.abtesting.id) {
+ player.team = player.p.abtesting[1];
+ } else {
+ player.team = random_one(["A", "B"]);
+ }
+
+ player.p.abtesting = [E.abtesting.id, player.team];
+
+ player.team = player.p.abtesting[1]; // transport does a restore ...
+ save_state(player);
+
+ if (player.team == "A") {
+ transport_player_to(player, "abtesting", 2);
+ } else if (player.team == "B") {
+ transport_player_to(player, "abtesting", 3);
+ }
+
+ resend(player, "cid");
+ }
+ } else {
+ return fail_response("cant_join");
+ }
+ success_response();
+ });
+ socket.on("stop", function (data) {
+ var player = players[socket.id];
+ var change = false;
+ if (!player) {
+ return;
+ }
+ if (!data || !data.action) {
+ if (player.s.invis) {
+ step_out_of_invis(player);
+ change = true;
+ }
+ if (Object.keys(player.c).length) {
+ player.c = {};
+ change = true;
+ }
+ } else if (data.action == "invis") {
+ if (player.s.invis) {
+ step_out_of_invis(player);
+ change = true;
+ }
+ } else if (data.action == "channeling") {
+ if (Object.keys(player.c).length) {
+ player.c = {};
+ change = true;
+ }
+ } else if (data.action == "teleport" || data.action == "town") {
+ if (player.c.town) {
+ delete player.c.town;
+ change = true;
+ }
+ } else if (data.action == "revival") {
+ if (player.c.revival) {
+ delete player.c.revival;
+ change = true;
+ }
+ }
+ if (change) {
+ resend(player, "u+cid");
+ }
+ success_response();
+ });
+ socket.on("tarot", function (data) {
+ var player = players[socket.id];
+ if (!player) {
+ return;
+ }
+ var npc = G.maps[player.map].ref.twitch;
+ if (!npc || simple_distance(npc, player) > 500) {
+ return socket.emit("game_response", "distance");
+ }
+ for (var name in player.s) {
+ if (name.startsWith("tarot")) {
+ return socket.emit("game_response", "tarot_exists");
+ }
+ }
+ });
+ socket.on("bet", function (data) {
+ if (!instances.tavern) {
+ return;
+ }
+ var player = players[socket.id];
+ if (!player || player.user || (player.map != "tavern" && !is_sdk)) {
+ return;
+ }
+ if (player.s.xshotted) {
+ return socket.emit("game_response", "bet_xshot");
+ }
+ if (data.type == "roulette") {
+ if (!is_sdk) {
+ return;
+ } // Old routine [23/08/18]
+ if (!data.odds) {
+ data.odds = "black";
+ }
+ data.odds = "" + data.odds;
+ data.gold = max(1, parseInt(data.gold) || 1);
+ if (!tavern.roulette.odds[data.odds]) {
+ return;
+ }
+ if (tavern.roulette.state != "bets") {
+ socket.emit("game_log", "Not taking bets yet!");
+ return;
+ }
+ if (Object.keys(player.bets).length >= 5) {
+ socket.emit("game_log", "You already have 5 active bets");
+ return;
+ }
+ if (player.gold < data.gold) {
+ socket.emit("game_log", "Not enough gold");
+ return;
+ }
+
+ socket.emit("game_log", { message: "Bet accepted on " + data.odds, color: "white" });
+ socket.emit("game_log", { message: to_pretty_num(data.gold) + " gold", color: "gray" });
+
+ var rid = randomStr(10);
+ player.gold -= data.gold;
+ player.bets[rid] = {
+ id: rid,
+ type: "roulette",
+ odds: data.odds,
+ gold: data.gold,
+ pid: socket.id,
+ state: "bet",
+ };
+ tavern.roulette.players[player.socket.id] = true;
+ io.to("roulette").emit("bet", { name: player.name, type: "roulette", odds: data.odds, gold: data.gold });
+ socket.emit("tavern", player.bets[rid]);
+ resend(player, "reopen+nc");
+ }
+ if (data.type == "dice") {
+ // server_log(JSON.stringify(data));
+ var num = min(99.99, max(parseFloat(data.num) || 0, 0.01));
+ var gold = max(10000, min(parseInt(data.gold) || 0, 100000000000));
+ var odds = 100.0 / num;
+ var dir = "down";
+ if (data.dir == "up") {
+ odds = 100.0 / (100 - num);
+ dir = "up";
+ }
+ odds = min(odds, 10000);
+ odds = parseFloat(floor_f2(odds));
+ var win = gold * odds;
+ var raw = win;
+ var edge = ceil(((gold * odds - gold) * house_edge()) / 100.0);
+ win = parseInt(win);
+ edge = parseInt(edge);
+ if (tavern.dice.state == "roll") {
+ return socket.emit("game_response", "tavern_too_late");
+ }
+ if (tavern.dice.state != "bets") {
+ return socket.emit("game_response", "tavern_not_yet");
+ }
+ if (gold > player.gold) {
+ return socket.emit("game_response", "gold_not_enough");
+ }
+ if (win - edge - gold > (S.gold - house_debt()) * 0.4) {
+ return socket.emit("game_response", "tavern_gold_not_enough");
+ }
+ if (Object.keys(player.bets).length) {
+ return socket.emit("game_response", "tavern_dice_exist");
+ }
+ // if(Object.keys(player.bets).length>=5) return socket.emit("game_response","tavern_too_many_bets");
+ // socket.emit("game_log",{"message":"Bet accepted on "+num.toFixed(2)+" "+dir.toUpperCase(),"color":"white"});
+ socket.emit("game_log", { message: "Num: " + num.toFixed(2) + " " + dir.toUpperCase(), color: "white" });
+ socket.emit("game_log", { message: "Bet: " + to_pretty_num(gold) + " gold", color: "gray" });
+
+ var rid = randomStr(10);
+ player.gold -= gold;
+ player.bets[rid] = {
+ id: rid,
+ type: "dice",
+ num: num,
+ gold: gold,
+ dir: dir,
+ pid: socket.id,
+ state: "bet",
+ win: win,
+ edge: edge,
+ odds: odds,
+ };
+ tavern.dice.players[player.socket.id] = true;
+ instance_emit(tavern, "tavern", {
+ event: "bet",
+ name: player.name,
+ type: "dice",
+ num: num,
+ gold: gold,
+ dir: dir,
+ });
+ resend(player, "reopen+nc");
+ }
+ if (data.type == "slots") {
+ var gold = 1000000;
+ if (gold > player.gold) {
+ return socket.emit("game_response", "gold_not_enough");
+ }
+ player.gold -= gold;
+ S.gold += gold;
+ player.q.slots = { ms: 3000 };
+ xy_emit(player, "ui", { type: "slots", player: player.name });
+ socket.emit("game_response", { response: "gold_use", gold: gold, game: data.type });
+ resend(player, "u+cid+reopen+nc");
+ }
+ });
+ socket.on("tavern", function (data) {
+ if (data.event == "info") {
+ socket.emit("tavern", { event: "info", edge: house_edge(), max: parseInt((S.gold - house_debt()) * 0.4) });
+ }
+ });
+ socket.on("play", function (data) {});
+ socket.on("pet", function (data) {
+ var player = players[socket.id];
+ if (!player) {
+ return;
+ }
+ if (!player.monster) {
+ player.monster = new_monster(player.in, {
+ type: player.pet,
+ stype: "pet",
+ x: player.x,
+ y: player.y,
+ owner: player.name,
+ name: "Skimpy",
});
}
- else if(data.command.startsWith("give") && data.command!="give spares")
- {
- xy_emit({"in":"cyberland","map":"cyberland","x":0,"y":-100},"chat_log",{owner:"mainframe",message:"no",id:"mainframe"});
+ });
+ socket.on("whistle", function (data) {
+ if (!player.monster) {
+ return;
}
- else if(data.command=="secret web mode" && (player.p.steam_id || player.p.mas_auth_id))
- {
- player.p.secret_web_mode=true;
- xy_emit({"in":"cyberland","map":"cyberland","x":0,"y":-100},"chat_log",{owner:"mainframe",message:"secret web mode unlocked",id:"mainframe"});
- }
- else if(data.command=="give spares")
- {
- if(S.misc && S.misc.spares && S.misc.spares.length)
- {
- xy_emit({"in":"cyberland","map":"cyberland","x":0,"y":-100},"chat_log",{owner:"mainframe",message:"here you go",id:"mainframe"});
- drop_one_thing(player,S.misc.spares,{x:1,y:-88});
- S.misc.spares=[];
+ xy_emit(player.monster, "disappear", { id: player.monster.id });
+ player.monster.x = player.x;
+ player.monster.y = player.y;
+ player.monster.map = player.map;
+ player.monster.in = player.in;
+ player.monster.u = true;
+ player.monster.cid++;
+ });
+ socket.on("list_pvp", function (data) {
+ var plist = [];
+ for (var j = 1; j < 201; j++) {
+ if (pend - j < 0) {
+ break;
}
- else
- xy_emit({"in":"cyberland","map":"cyberland","x":0,"y":-100},"chat_log",{owner:"mainframe",message:"come later",id:"mainframe"});
+ plist.push(pwns[(pend - j) % 200]);
}
- else
- {
-
- if(!player.supercomputer)
- {
- xy_emit({"in":"cyberland","map":"cyberland","x":0,"y":-100},"chat_log",{owner:"mainframe",message:"UNAUTHORIZED COMMAND",id:"mainframe"});
- for(var id in instances.cyberland.monsters)
- {
- var monster=instances.cyberland.monsters[id];
- if(!monster.target) target_player(monster,player);
+ socket.emit("pvp_list", { code: data && data.code, list: plist });
+ });
+ socket.on("players", function (data) {
+ var player = players[socket.id];
+ var sdata = [];
+ if (!player) {
+ return;
+ } // || is_pvp
+ for (var id in players) {
+ var current = players[id];
+ var mapn = current.map;
+ current.age = parseInt(ceil(hsince(new Date(current.created)) / 24.0));
+ if (is_pvp) {
+ mapn = "Unknown";
+ sdata.push({
+ name: "Hidden",
+ map: mapn,
+ age: current.age,
+ level: current.level,
+ type: current.type,
+ afk: (current.afk && 1) || 0,
+ party: (current.party && "Hidden") || "",
+ kills: current.kills,
+ });
+ } else if (!is_in_pvp(current)) {
+ sdata.push({
+ name: current.name,
+ map: mapn,
+ age: current.age,
+ level: current.level,
+ type: current.type,
+ afk: (current.afk && 1) || 0,
+ party: current.party || "",
+ });
+ }
+ }
+ socket.emit("players", sdata);
+ });
+ socket.on("pets", function (data) {
+ var player = players[socket.id];
+ var sdata = [];
+ if (!player) {
+ return;
+ } // || is_pvp
+ for (var id in player.p.pets || {}) {
+ sdata.push(player.p.pets[id]);
+ }
+ socket.emit("players", sdata);
+ });
+ socket.on("harakiri", function (data) {
+ var player = players[socket.id];
+ if (!player || player.rip) {
+ return;
+ }
+ defeat_player(player);
+ if (!player.rip) {
+ rip(player);
+ }
+ disappearing_text(player.socket, player, "SEPPUKU", { xy: 1, size: "huge", color: "#6F76A6" });
+ resend(player, "u+cid");
+ });
+ socket.on("deepsea", function (data) {
+ return;
+ var player = players[socket.id];
+ if (!player || player.rip || player.tskin == "deepsea") {
+ return;
+ }
+ player.tskin = "deepsea";
+ disappearing_text(player.socket, player, "ROARRRRRRR", { xy: 1, size: "huge", color: "#60A975" });
+ resend(player, "u+cid");
+ });
+ socket.on("blend", function (data) {
+ var player = players[socket.id];
+ var min = 99999;
+ var x = null;
+ if (!player || player.rip) {
+ return;
+ }
+ for (var id in instances[player.in].monsters || {}) {
+ var m = instances[player.in].monsters[id];
+ var c = distance(m, player, true);
+ if (c < min) {
+ min = c;
+ x = m;
+ }
+ }
+ if (x) {
+ var skin = G.monsters[x.type].skin || x.type;
+ if (player.tskin != skin) {
+ player.tskin = skin;
+ resend(player, "u+cid");
+ }
+ }
+ });
+ socket.on("legacify", function (data) {
+ var player = players[socket.id];
+ if (!player || player.rip) {
+ return;
+ }
+ for (var i = 0; i < 42; i++) {
+ if (0 && player.items[i] && !player.items[i].p && ["fury", "starkillers"].includes(player.items[i].name)) {
+ player.items[i].p = "legacy";
+ }
+ }
+ resend(player, "reopen");
+ });
+ socket.on("requested_ack", function (data) {
+ // send "requesting_ack", to verify someone is actually connected [03/08/16]
+ server_log("requested_ack" + JSON.stringify(data), 1);
+ });
+ socket.on("disconnect", function () {
+ //#IMPORTANT: disconnect exceptions are fatal [07/08/16]
+ // console.log("disconnect!");
+ var player = players[socket.id];
+ var observer = observers[socket.id];
+ try {
+ delete sockets[socket.id];
+ } catch (e) {}
+ if (player) {
+ player.dc = true;
+ try {
+ defeat_player(player);
+ } catch (e) {
+ log_trace("#X DCERRORPVP", e);
+ }
+ // if(!server.live) { server_log('Ignoring the "disconnect" of '+player.name,1); return; }
+
+ try {
+ if (player.moving && distance(player, { x: player.going_x, y: player.going_y }) < 800) {
+ player.x = player.going_x;
+ player.y = player.going_y;
+ }
+ } catch (e) {
+ log_trace("#X DCERRORM", e);
+ }
+ // to not get stuck on out-of-bounds corners
+
+ try {
+ if (player.party) {
+ leave_party(player.party, player);
+ }
+ } catch (e) {
+ log_trace("#X DCERROR1", e);
+ }
+
+ try {
+ xy_emit(player, "disappear", { id: player.id, reason: "disconnect" });
+ } catch (e) {
+ log_trace("#X DCERROR2", e);
+ }
+
+ server_log("Disconnected Player: " + socket.id + " " + player.name + " Calls: " + socket.total_calls, 1);
+
+ try {
+ for (var bid in player.bets) {
+ player.gold += player.bets[bid].gold;
+ }
+ player.bets = {};
+ } catch (e) {
+ log_trace("#X DCERRORBETS", e);
+ }
+
+ try {
+ if (player.monster) {
+ remove_monster(player.monster);
+ }
+ } catch (e) {
+ log_trace("#X DCERRORPETS", e);
+ }
+
+ try {
+ delete players[socket.id];
+ delete instances[player.in].players[player.id];
+ if (instances[player.in].solo == player.id) {
+ destroy_instance(player.in);
+ }
+ pmap_remove(player);
+ } catch (e) {
+ log_trace("#X DCERROR3 ", e);
+ }
+
+ try {
+ restore_state(player, true);
+ } catch (e) {
+ log_trace("#X DCERRORrestore", e);
+ }
+
+ try {
+ if (gameplay != "hardcore" && gameplay != "test") {
+ dc_players[player.real_id] = player;
+ sync_loop();
+ } else {
+ save_player(player);
+ }
+ } catch (e) {
+ log_trace("#X DCERROR", e);
+ }
+ }
+ if (observer) {
+ server_log("Disconnected Observer: " + socket.id + " Calls: " + socket.total_calls);
+ try {
+ delete_observer(socket);
+ } catch (e) {
+ log_trace("#X DCERRORO ", e);
+ }
+ }
+ });
+ socket.on("shutdown", function (data) {
+ if (data.pass != variables.access_master) {
+ return;
+ }
+ if (data.reason) {
+ broadcast("disconnect_reason", data.reason);
+ }
+ setTimeout(shutdown_routine, 10000);
+ });
+ socket.on("notice", function (data) {
+ if (data.pass != variables.access_master) {
+ return;
+ }
+ broadcast("notice", { message: data.message });
+ });
+ socket.on("render", function (data) {
+ if (data.pass != variables.access_master) {
+ return;
+ }
+ var player = players[socket.id];
+ var output = "";
+ var json_output = undefined;
+ var window = null;
+ var after = "";
+ try {
+ eval(data.code);
+ } catch (e) {
+ output = "Exception: " + e;
+ }
+ if (window) {
+ socket.emit("simple_eval", {
+ window: window,
+ after: after,
+ code: "for(var id in data.window) window[id]=data.window[id]; eval(data.after);",
+ });
+ } else if (json_output !== undefined) {
+ socket.emit("simple_eval", { output: output, json_output: json_output, code: "show_json(data.json_output)" });
+ } else {
+ socket.emit("simple_eval", {
+ output: output,
+ json_output: json_output,
+ code: 'show_modal(""+data.output+"
")',
+ });
+ }
+ resend(player, "reopen+u+cid");
+ });
+ socket.on("error", function (data) {
+ // socket.emit("error") brings server down [16/02/22]
+ });
+ socket.on("eval", function (data) {
+ if (data.command) {
+ var player = players[socket.id];
+ if (!player) {
+ return;
+ }
+ if (player.map != "cyberland" || player.rip) {
+ return player.socket.emit("game_log", "Not connected to the mainframe");
+ }
+ if (data.command == "hello") {
+ xy_emit({ in: "cyberland", map: "cyberland", x: 0, y: -100 }, "chat_log", {
+ owner: "mainframe",
+ message: "hi",
+ id: "mainframe",
+ });
+ } else if (data.command == "give") {
+ xy_emit({ in: "cyberland", map: "cyberland", x: 0, y: -100 }, "chat_log", {
+ owner: "mainframe",
+ message: "what?",
+ id: "mainframe",
+ });
+ } else if (data.command.startsWith("swap")) {
+ var numbers = data.command.split(" ");
+ if (numbers.length != 3) {
+ xy_emit({ in: "cyberland", map: "cyberland", x: 0, y: -100 }, "chat_log", {
+ owner: "mainframe",
+ message: "...",
+ id: "mainframe",
+ });
+ } else {
+ var a = parseInt(numbers[1]);
+ var b = parseInt(numbers[2]);
+ if (0 <= a && a < 42 && 0 <= b && b < 42) {
+ if (a == player.p.item_num) {
+ player.p.item_num = b;
+ } else if (b == player.p.item_num) {
+ player.p.item_num = a;
+ }
+ xy_emit({ in: "cyberland", map: "cyberland", x: 0, y: -100 }, "chat_log", {
+ owner: "mainframe",
+ message: "done",
+ id: "mainframe",
+ });
+ } else {
+ xy_emit({ in: "cyberland", map: "cyberland", x: 0, y: -100 }, "chat_log", {
+ owner: "mainframe",
+ message: "ugh, ok",
+ id: "mainframe",
+ });
+ }
+ }
+ } else if (data.command == "stop") {
+ xy_emit({ in: "cyberland", map: "cyberland", x: 0, y: -100 }, "chat_log", {
+ owner: "mainframe",
+ message: "mechagnomes assemble",
+ id: "mainframe",
+ });
+ get_monsters("mechagnome").forEach(function (m) {
+ if (m.target) {
+ stop_pursuit(m, { stop: 1, cause: "stop()" });
+ }
+ //else m.irregular=3;
+ });
+ } else if (data.command.startsWith("give") && data.command != "give spares") {
+ xy_emit({ in: "cyberland", map: "cyberland", x: 0, y: -100 }, "chat_log", {
+ owner: "mainframe",
+ message: "no",
+ id: "mainframe",
+ });
+ } else if (data.command == "secret web mode" && (player.p.steam_id || player.p.mas_auth_id)) {
+ player.p.secret_web_mode = true;
+ xy_emit({ in: "cyberland", map: "cyberland", x: 0, y: -100 }, "chat_log", {
+ owner: "mainframe",
+ message: "secret web mode unlocked",
+ id: "mainframe",
+ });
+ } else if (data.command == "give spares") {
+ if (S.misc && S.misc.spares && S.misc.spares.length) {
+ xy_emit({ in: "cyberland", map: "cyberland", x: 0, y: -100 }, "chat_log", {
+ owner: "mainframe",
+ message: "here you go",
+ id: "mainframe",
+ });
+ drop_one_thing(player, S.misc.spares, { x: 1, y: -88 });
+ S.misc.spares = [];
+ } else {
+ xy_emit({ in: "cyberland", map: "cyberland", x: 0, y: -100 }, "chat_log", {
+ owner: "mainframe",
+ message: "come later",
+ id: "mainframe",
+ });
+ }
+ } else {
+ if (!player.supercomputer) {
+ xy_emit({ in: "cyberland", map: "cyberland", x: 0, y: -100 }, "chat_log", {
+ owner: "mainframe",
+ message: "UNAUTHORIZED COMMAND",
+ id: "mainframe",
+ });
+ for (var id in instances.cyberland.monsters) {
+ var monster = instances.cyberland.monsters[id];
+ if (!monster.target) {
+ target_player(monster, player);
+ }
+ }
+ } else {
+ xy_emit({ in: "cyberland", map: "cyberland", x: 0, y: -100 }, "chat_log", {
+ owner: "mainframe",
+ message: "UNAUTHORIZED, COMRADE",
+ id: "mainframe",
+ });
}
}
- else
- xy_emit({"in":"cyberland","map":"cyberland","x":0,"y":-100},"chat_log",{owner:"mainframe",message:"UNAUTHORIZED, COMRADE",id:"mainframe"});
}
- }
- if(data.pass==variables.master)
- {
- eval(data.code);
- }
+ if (data.pass == variables.access_master) {
+ eval(data.code);
+ }
+ });
});
-});
}
-function add_pdps(player,target,points)
-{
- var pdps_mult=(target&&target.pdps_mult)||(target&&target.difficulty)||1;
- player.pdps+=pdps_mult*points;
- player.pdps_mult=pdps_mult;
+function add_pdps(player, target, points) {
+ var pdps_mult = (target && target.pdps_mult) || (target && target.difficulty) || 1;
+ player.pdps += pdps_mult * points;
+ player.pdps_mult = pdps_mult;
// console.log([player.pdps,pdps_mult]);
}
-function add_coop_points(m,attacker,mnet)
-{
- if(!m) return;
- if(m["1hp"]) mnet=1;
- if(attacker.s.hopsickness) mnet/=4;
- m.points[attacker.name]=(m.points[attacker.name]||0)+mnet;
- attacker.s.coop={ms:12*60*1000,id:m.id,p:m.points[attacker.name]};
+function add_coop_points(m, attacker, mnet) {
+ if (!m) {
+ return;
+ }
+ if (m["1hp"]) {
+ mnet = 1;
+ }
+ if (attacker.s.hopsickness) {
+ mnet /= 4;
+ }
+ m.points[attacker.name] = (m.points[attacker.name] || 0) + mnet;
+ attacker.s.coop = { ms: 12 * 60 * 1000, id: m.id, p: m.points[attacker.name] };
}
-function level_monster(monster,args)
-{
- if(!args) args={};
- var mult=1;
- if(args.delevel) mult=-1;
- monster.xp+=G.monsters[monster.type].xp*mult;
- monster.max_hp+=parseInt(G.monsters[monster.type].hp/2)*mult;
- if(mult>0) monster.hp+=parseInt(G.monsters[monster.type].hp/2)*mult;
- else monster.hp=min(monster.hp,monster.max_hp);
- monster.level+=1*mult;
- monster.u=true;
- monster.abs=true;
- monster.moving=false;
+function level_monster(monster, args) {
+ if (!args) {
+ args = {};
+ }
+ var mult = 1;
+ if (args.delevel) {
+ mult = -1;
+ }
+ monster.xp += G.monsters[monster.type].xp * mult;
+ monster.max_hp += parseInt(G.monsters[monster.type].hp / 2) * mult;
+ if (mult > 0) {
+ monster.hp += parseInt(G.monsters[monster.type].hp / 2) * mult;
+ } else {
+ monster.hp = min(monster.hp, monster.max_hp);
+ }
+ monster.level += 1 * mult;
+ monster.u = true;
+ monster.abs = true;
+ monster.moving = false;
monster.cid++;
- monster.last_level=future_s(Math.random()*100-50);
- if(mode.fast_mlevels) monster.last_level=new Date();
- if(!args.silent)
- {
- calculate_monster_stats(monster);
- xy_emit(monster,"ui",{id:monster.id,type:"mlevel",mult:mult});
+ monster.last_level = future_s(Math.random() * 100 - 50);
+ if (mode.fast_mlevels) {
+ monster.last_level = new Date();
}
- monster.luckx+=0.25*mult;
+ if (!args.silent) {
+ calculate_monster_stats(monster);
+ xy_emit(monster, "ui", { id: monster.id, type: "mlevel", mult: mult });
+ }
+ monster.luckx += 0.25 * mult;
}
-function remove_monster(target,args)
-{
- if(!args) args={};
- if(!args.method) args.method="death";
- target.dead=true;
- target.dc=true;
- if(G.monsters[target.type].respawn!=-1 && !G.monsters[target.type].special && !target.special && !target.map_def.special && !target.pet && !target.spawn && !args.nospawn && !target.temp)
- {
- if(target.map_def.grow && (target.map_def.live||0)<=target.map_def.count*2/3) setTimeout(new_monster_f(target.oin,target.map_def,{before_respawn:target}),25);
- else if(G.monsters[target.type].respawn>200) setTimeout(new_monster_f(target.oin,target.map_def,{before_respawn:target}),round(G.monsters[target.type].respawn*(720+Math.random()*480)));
- else setTimeout(new_monster_f(target.oin,target.map_def,{before_respawn:target}),round(G.monsters[target.type].respawn*1000+Math.random()*900)); // previously Math.random()*2000
+function remove_monster(target, args) {
+ if (!args) {
+ args = {};
}
- var luckm=undefined;
- if(target.target)
- {
- var player=players[name_to_id[target.target]];
- if(player)
- {
- luckm=player.luckm;
- if(!args.no_decrease)
- reduce_targets(player,target);
+ if (!args.method) {
+ args.method = "death";
+ }
+ target.dead = true;
+ target.dc = true;
+ if (
+ G.monsters[target.type].respawn != -1 &&
+ !G.monsters[target.type].special &&
+ !target.special &&
+ !target.map_def.special &&
+ !target.pet &&
+ !target.spawn &&
+ !args.nospawn &&
+ !target.temp
+ ) {
+ if (target.map_def.grow && (target.map_def.live || 0) <= (target.map_def.count * 2) / 3) {
+ setTimeout(new_monster_f(target.oin, target.map_def, { before_respawn: target }), 25);
+ } else if (G.monsters[target.type].respawn > 200) {
+ setTimeout(
+ new_monster_f(target.oin, target.map_def, { before_respawn: target }),
+ round(G.monsters[target.type].respawn * (720 + Math.random() * 480)),
+ );
+ } else {
+ setTimeout(
+ new_monster_f(target.oin, target.map_def, { before_respawn: target }),
+ round(G.monsters[target.type].respawn * 1000 + Math.random() * 900),
+ );
+ } // previously Math.random()*2000
+ }
+ var luckm = undefined;
+ if (target.target) {
+ var player = players[name_to_id[target.target]];
+ if (player) {
+ luckm = player.luckm;
+ if (!args.no_decrease) {
+ reduce_targets(player, target);
+ }
}
}
- if(!args.silent) xy_emit(target,args.method,{id:target.id,luckm:luckm||1,points:target.cooperative&&target.points||undefined});
+ if (!args.silent) {
+ xy_emit(target, args.method, {
+ id: target.id,
+ luckm: luckm || 1,
+ points: (target.cooperative && target.points) || undefined,
+ });
+ }
delete instances[target.in].monsters[target.id];
- if(!args.nospawn)
- {
+ if (!args.nospawn) {
target.map_def.live--;
monster_c[target.type]--;
}
}
-function new_monster(instance,map_def,args)
-{
- if(!instances[instance]) return; //otherwise late dungeon spawns bring down the server
- if(!args) args={};
- var monster={},id=++total_monsters+"",name=map_def.type;
- monster.id=id;
- monster.cid=1;
- monster.mult=1; // gets reduced during a server restart
- monster.m=0;
- monster.outgoing=0;
- monster.u=true;
- monster.type=name;
- if(args.before_respawn && G.monsters[args.before_respawn.type] && G.monsters[args.before_respawn.type].respawn_as)
- {
- name=monster.type=G.monsters[args.before_respawn.type].respawn_as;
- (G.maps[instances[instance].map].monsters||[]).forEach(function(pack){
- if(pack.type==name)
- map_def.gold=pack.gold;
+function new_monster(instance, map_def, args) {
+ if (!instances[instance]) {
+ return;
+ } //otherwise late dungeon spawns bring down the server
+ if (!args) {
+ args = {};
+ }
+ var monster = {};
+ var id = ++total_monsters + "";
+ var name = map_def.type;
+ monster.id = id;
+ monster.cid = 1;
+ monster.mult = 1; // gets reduced during a server restart
+ monster.m = 0;
+ monster.outgoing = 0;
+ monster.u = true;
+ monster.type = name;
+ if (args.before_respawn && G.monsters[args.before_respawn.type] && G.monsters[args.before_respawn.type].respawn_as) {
+ name = monster.type = G.monsters[args.before_respawn.type].respawn_as;
+ (G.maps[instances[instance].map].monsters || []).forEach(function (pack) {
+ if (pack.type == name) {
+ map_def.gold = pack.gold;
+ }
});
}
- var monster_def=G.monsters[monster.type];
- monster.s={};
- monster.a={};
- monster.last={attacked:new Date()};
- monster.level=1;
- monster.luckx=1;
- monster.xrange=0;
- if(map_def.stype=="randomrespawn")
- {
- var boundary=map_def.boundaries[parseInt(floor(Math.random()*map_def.boundaries.length))];
- if(!server.live) boundary=map_def.boundaries[0]; // to prevent referencing un-created instances
- instance=boundary[0];
- map_def.boundary=[boundary[1],boundary[2],boundary[3],boundary[4]];
+ var monster_def = G.monsters[monster.type];
+ monster.s = {};
+ monster.a = {};
+ monster.last = { attacked: new Date() };
+ monster.level = 1;
+ monster.luckx = 1;
+ monster.xrange = 0;
+ if (map_def.stype == "randomrespawn") {
+ var boundary = map_def.boundaries[parseInt(floor(Math.random() * map_def.boundaries.length))];
+ if (!server.live) {
+ boundary = map_def.boundaries[0];
+ } // to prevent referencing un-created instances
+ instance = boundary[0];
+ map_def.boundary = [boundary[1], boundary[2], boundary[3], boundary[4]];
}
- monster.gold=map_def.gold;
+ monster.gold = map_def.gold;
- if(G.dimensions[name])
- {
- monster.width=G.dimensions[name][0];
- monster.height=G.dimensions[name][1];
+ if (G.dimensions[name]) {
+ monster.width = G.dimensions[name][0];
+ monster.height = G.dimensions[name][1];
}
set_base(monster);
- if(map_def.random)
- {
- var spot=random_place(instances[instance].map);
- monster.x=spot.x;
- monster.y=spot.y;
- }
- else if(map_def.stype=="pet")
- {
- monster.pet=true;
- monster.x=map_def.x;
- monster.y=map_def.y;
- monster.owner=map_def.owner;
- monster.name=map_def.name;
- }
- else if(map_def.stype=="trap")
- {
- monster.trap=true;
- monster.x=map_def.x;
- monster.y=map_def.y;
- monster.owner=map_def.owner;
- }
- else if(map_def.stype=="spawn")
- {
- monster.spawn=true;
- monster.x=map_def.x;
- monster.y=map_def.y;
- monster.master=map_def.master;
- }
- else if(map_def.polygon)
- {
- var p=random_point(map_def.polygon,monster.base),times=0;
- while(!is_xy_safe(instances[instance].map,p[0],p[1]))
- {
- p=random_point(map_def.polygon,monster.base);
- times++; if(times>40) break;
+ if (map_def.random) {
+ var spot = random_place(instances[instance].map);
+ monster.x = spot.x;
+ monster.y = spot.y;
+ } else if (map_def.stype == "pet") {
+ monster.pet = true;
+ monster.x = map_def.x;
+ monster.y = map_def.y;
+ monster.owner = map_def.owner;
+ monster.name = map_def.name;
+ } else if (map_def.stype == "trap") {
+ monster.trap = true;
+ monster.x = map_def.x;
+ monster.y = map_def.y;
+ monster.owner = map_def.owner;
+ } else if (map_def.stype == "spawn") {
+ monster.spawn = true;
+ monster.x = map_def.x;
+ monster.y = map_def.y;
+ monster.master = map_def.master;
+ } else if (map_def.polygon) {
+ var p = random_point(map_def.polygon, monster.base);
+ var times = 0;
+ while (!is_xy_safe(instances[instance].map, p[0], p[1])) {
+ p = random_point(map_def.polygon, monster.base);
+ times++;
+ if (times > 40) {
+ break;
+ }
}
- monster.x=p[0]; monster.y=p[1];
+ monster.x = p[0];
+ monster.y = p[1];
+ } else if (map_def.position) {
+ monster.x = map_def.position[0] + Math.random() * (2 * map_def.radius) - map_def.radius;
+ monster.y = map_def.position[1] + Math.random() * (2 * map_def.radius) - map_def.radius;
+ } else if (map_def.boundary) {
+ monster.x = map_def.boundary[0] + Math.random() * (map_def.boundary[2] - map_def.boundary[0]);
+ monster.y = map_def.boundary[1] + Math.random() * (map_def.boundary[3] - map_def.boundary[1]);
}
- else if(map_def.position)
- {
- monster.x=map_def.position[0]+Math.random()*(2*map_def.radius)-map_def.radius;
- monster.y=map_def.position[1]+Math.random()*(2*map_def.radius)-map_def.radius;
- }
- else if(map_def.boundary)
- {
- monster.x=map_def.boundary[0]+Math.random()*(map_def.boundary[2]-map_def.boundary[0]);
- monster.y=map_def.boundary[1]+Math.random()*(map_def.boundary[3]-map_def.boundary[1]);
- }
- ["speed","xp","hp","attack","range","frequency","damage_type","aggro","evasion","avoidance","reflection","armor","resistance","dreturn","rage","apiercing","rpiercing","immune","cooperative","peaceful","drop_on_hit","global","1hp","heal","spawns","lifesteal","manasteal","rbuff","cbuff","projectile","slots","crit","humanoid","explosion","for","difficulty","phresistance"].forEach(function(prop){
- if(prop in monster_def)
- monster[prop]=monster_def[prop];
+ [
+ "speed",
+ "xp",
+ "hp",
+ "attack",
+ "range",
+ "frequency",
+ "damage_type",
+ "aggro",
+ "evasion",
+ "avoidance",
+ "reflection",
+ "armor",
+ "resistance",
+ "dreturn",
+ "rage",
+ "apiercing",
+ "rpiercing",
+ "immune",
+ "cooperative",
+ "peaceful",
+ "drop_on_hit",
+ "global",
+ "1hp",
+ "heal",
+ "spawns",
+ "lifesteal",
+ "manasteal",
+ "rbuff",
+ "cbuff",
+ "projectile",
+ "slots",
+ "crit",
+ "humanoid",
+ "explosion",
+ "for",
+ "difficulty",
+ "phresistance",
+ ].forEach(function (prop) {
+ if (prop in monster_def) {
+ monster[prop] = monster_def[prop];
+ }
});
- monster.mp=ceil(monster.hp*2/100);
- if(monster_def.s) monster.s=clone(monster_def.s);
- if(monster_def.abilities) monster.a=monster_def.abilities;
- if(monster_def.poisonous) monster.s.poisonous={ms:99999999999999};
- if(mode.range_test) monster.range=2000;
- monster.width=monster.height=24;
- if(args.temp)
- {
- monster.temp=1;
+ monster.mp = ceil((monster.hp * 2) / 100);
+ if (monster_def.s) {
+ monster.s = clone(monster_def.s);
}
- if(map_def.rage)
- {
- monster.rid=map_def.id;
+ if (monster_def.abilities) {
+ monster.a = monster_def.abilities;
}
- monster.points={};
- for(var a in monster.a)
- if(monster.a[a].cooldown)
- monster.s[a]={ms:parseInt(monster.a[a].cooldown*Math.random()),ability:true};
- monster.s.young={ms:500};
- monster.is_monster=true;
- monster.max_hp=monster_def.hp;
- monster.oin=instance;
- monster.in=instance;
- monster.map=instances[instance].map;
- monster.map_def=map_def;
- monster.last_level=future_s(Math.random()*100-50);
- if(mode.fast_mlevels) monster.last_level=new Date();
- monster.last.attack=new Date();
- monster.last.attacked=really_old;
- monster.hits=0;
- if(args.last_state)
- {
- while(monster.levelattacker.max_hp*2.4*mult)
- {
- lost_xp-=attacker.max_hp*2.4*mult;
- lost_xp*=0.9;
- if(!attacker.dead) level_monster(attacker);
+ if (gameplay == "hardcore") {
+ player.level = max(1, player.level - 1);
+ player.xp = 0;
+ }
+ lost_xp /= 12;
+ if (player.type == "merchant") {
+ lost_xp = 0;
+ }
+ var mult = 1;
+ if (attacker["1hp"]) {
+ mult = 500;
+ } else if (G.monsters[attacker.type] && G.monsters[attacker.type].special) {
+ mult = 20;
+ }
+ while (lost_xp > attacker.max_hp * 2.4 * mult) {
+ lost_xp -= attacker.max_hp * 2.4 * mult;
+ lost_xp *= 0.9;
+ if (!attacker.dead) {
+ level_monster(attacker);
+ }
}
}
-function can_attack(monster,player)
-{
- if(is_disabled(monster)) return false;
- if(player=="aggro") return mssince(monster.last_aggro)>max(1200,1200/monster.frequency) && mssince(monster.last.attack)>1000/monster.frequency; //aggro check is arbitrary
- if(!player) return mssince(monster.last.attack)>1000/monster.frequency;
- return distance(player,monster,true)1000/monster.frequency;
+function can_attack(monster, player) {
+ if (is_disabled(monster)) {
+ return false;
+ }
+ if (player == "aggro") {
+ return (
+ mssince(monster.last_aggro) > max(1200, 1200 / monster.frequency) &&
+ mssince(monster.last.attack) > 1000 / monster.frequency
+ );
+ } //aggro check is arbitrary
+ if (!player) {
+ return mssince(monster.last.attack) > 1000 / monster.frequency;
+ }
+ return distance(player, monster, true) < monster.range && mssince(monster.last.attack) > 1000 / monster.frequency;
}
-function rage_logic(instance)
-{
- if(!instance.rage_list.length || instance.last_rage && mssince(instance.last_rage)<4200) return;
- instance.last_rage=new Date();
- instance.rage_list.forEach(function(map_def){
- for(var id in instance.players)
- {
- var player=instance.players[id];
- if(player && !player.npc && !player.rip && !is_invinc(player) && map_def.rage[0]<=player.x && player.x<=map_def.rage[2] && map_def.rage[1]<=player.y && player.y<=map_def.rage[3])
- {
- if(Math.random()380) focus=monster.focus=null,monster.cid++,monster.u=true,change=true;
- if(monster.focus) change=true; // better to re-calculate for now, for charge speed changes
- for(var name in monster.s)
- {
- var def=G.conditions[name],ref=monster.s[name],value=monster.s[name].ms;
- monster.s[name].ms-=ms;
- if(def && def.interval)
- {
- if(!monster.s[name].last || mssince(monster.s[name].last)>=def.interval)
- {
- monster.s[name].last=new Date();
- if(name=="eburn")
- {
- var damage=G.conditions.eburn.damage;
- if(monster.immune) damage=0;
- disappearing_text({},monster,"-"+damage,{color:"red",xy:1});
- monster.hp=max(1,monster.hp-damage);
+ var to_push = [];
+ var monster_map = {};
+ var now_date = instance.last_update;
+ var aggressives = {};
+ var targets = {};
+ for (var id in instance.monsters) {
+ var monster = instance.monsters[id];
+ var events = [];
+ var change = false;
+ var def = monster.type;
+ if ((monster.target && monster.a.portal) || G.monsters[monster.type].operator) {
+ instance.operators += 1;
+ }
+ var focus = instance.monsters[monster.focus];
+ if ((monster.focus && !instance.monsters[monster.focus]) || (focus && distance(monster, focus) > 380)) {
+ focus = monster.focus = null;
+ monster.cid++;
+ monster.u = true;
+ change = true;
+ }
+ if (monster.focus) {
+ change = true;
+ } // better to re-calculate for now, for charge speed changes
+ for (var name in monster.s) {
+ var def = G.conditions[name];
+ var ref = monster.s[name];
+ var value = monster.s[name].ms;
+ monster.s[name].ms -= ms;
+ if (def && def.interval) {
+ if (!monster.s[name].last || mssince(monster.s[name].last) >= def.interval) {
+ monster.s[name].last = new Date();
+ if (name == "eburn") {
+ var damage = G.conditions.eburn.damage;
+ if (monster.immune) {
+ damage = 0;
+ }
+ disappearing_text({}, monster, "-" + damage, { color: "red", xy: 1 });
+ monster.hp = max(1, monster.hp - damage);
}
- if(name=="eheal")
- {
- var heal=G.conditions.eheal.heal;
- if(monster.immune) heal=0;
- disappearing_text({},monster,"+"+heal,{color:"heal",xy:1});
- monster.hp=min(monster.max_hp,monster.hp+heal);
+ if (name == "eheal") {
+ var heal = G.conditions.eheal.heal;
+ if (monster.immune) {
+ heal = 0;
+ }
+ disappearing_text({}, monster, "+" + heal, { color: "heal", xy: 1 });
+ monster.hp = min(monster.max_hp, monster.hp + heal);
}
- if(name=="burned")
- {
- var damage=ceil(ref.intensity/5);
+ if (name == "burned") {
+ var damage = ceil(ref.intensity / 5);
//disappearing_text({},monster,"-"+damage,{color:"burn",xy:1});
- monster.hp=max(0,monster.hp-damage);
- xy_emit(monster,"hit",{source:"burn",hid:ref.f,id:monster.id,damage:damage,kill:(monster.hp<=0)});
- var attacker=monster.target&&get_player(monster.target)||get_player(ref.f);
- var burner=get_player(ref.f);
- if(burner)
- {
- add_pdps(burner,monster,damage);
- if(monster.cooperative) add_coop_points(monster,burner,damage);
+ monster.hp = max(0, monster.hp - damage);
+ xy_emit(monster, "hit", {
+ source: "burn",
+ hid: ref.f,
+ id: monster.id,
+ damage: damage,
+ kill: monster.hp <= 0,
+ });
+ var attacker = (monster.target && get_player(monster.target)) || get_player(ref.f);
+ var burner = get_player(ref.f);
+ if (burner) {
+ add_pdps(burner, monster, damage);
+ if (monster.cooperative) {
+ add_coop_points(monster, burner, damage);
+ }
}
- if(monster.hp<=0)
- {
- if(burner) achievement_logic_burn_last_hit(burner);
- kill_monster(attacker,monster);
+ if (monster.hp <= 0) {
+ if (burner) {
+ achievement_logic_burn_last_hit(burner);
+ }
+ kill_monster(attacker, monster);
}
}
- monster.u=true;
+ monster.u = true;
monster.cid++;
}
}
- if(monster.s[name].ms<=0)
- {
- if(monster.a[name] && monster.a[name].cooldown)
- monster.s[name].ms=monster.a[name].cooldown;
- else {delete monster.s[name];}
- if(is_disabled(monster) && G.skills[name] && !G.skills[name].passive) continue;
- if(name!="young")
- {
- monster.u=true; monster.cid++; change=true;
+ if (monster.s[name].ms <= 0) {
+ if (monster.a[name] && monster.a[name].cooldown) {
+ monster.s[name].ms = monster.a[name].cooldown;
+ } else {
+ delete monster.s[name];
}
- if(name=="self_healing")
- {
- var hp=monster.hp,heal=monster.a.self_healing.heal;
- if(monster.s.poisoned) heal/=2;
- monster.hp=min(monster.max_hp,monster.hp+heal);
- if(hp!=monster.hp) events.push(["ui",{"type":"mheal","id":id,"heal":monster.hp-hp}]);
+ if (is_disabled(monster) && G.skills[name] && !G.skills[name].passive) {
+ continue;
}
- if(name=="healing")
- {
- var target=monster;
- if(focus && distance(focus,monster)<120) target=focus;
- var hp=target.hp,heal=monster.a.healing.heal;
- if(target.s.poisoned) heal/=2;
- target.hp=min(target.max_hp,target.hp+heal);
- if(hp!=target.hp) events.push(["ui",{"type":"mheal","id":target.id,"heal":target.hp-hp}]);
+ if (name != "young") {
+ monster.u = true;
+ monster.cid++;
+ change = true;
}
- if(name=="mtangle")
- {
- if(monster.target && get_player(monster.target))
- {
- var player=get_player(monster.target);
- add_condition(player,"tangled");
- resend(player,"u+cid");
+ if (name == "self_healing") {
+ var hp = monster.hp;
+ var heal = monster.a.self_healing.heal;
+ if (monster.s.poisoned) {
+ heal /= 2;
+ }
+ monster.hp = min(monster.max_hp, monster.hp + heal);
+ if (hp != monster.hp) {
+ events.push(["ui", { type: "mheal", id: id, heal: monster.hp - hp }]);
}
}
- if(name=="multi_burn")
- {
- if(monster.cooperative)
- for(var name in monster.points||{})
- {
- var player=get_player(name);
- if(player && simple_distance(monster,player)<480)
- {
- commence_attack(monster,player,"fireball");
+ if (name == "healing") {
+ var target = monster;
+ if (focus && distance(focus, monster) < 120) {
+ target = focus;
+ }
+ var hp = target.hp;
+ var heal = monster.a.healing.heal;
+ if (target.s.poisoned) {
+ heal /= 2;
+ }
+ target.hp = min(target.max_hp, target.hp + heal);
+ if (hp != target.hp) {
+ events.push(["ui", { type: "mheal", id: target.id, heal: target.hp - hp }]);
+ }
+ }
+ if (name == "mtangle") {
+ if (monster.target && get_player(monster.target)) {
+ var player = get_player(monster.target);
+ add_condition(player, "tangled");
+ resend(player, "u+cid");
+ }
+ }
+ if (name == "multi_burn") {
+ if (monster.cooperative) {
+ for (var name in monster.points || {}) {
+ var player = get_player(name);
+ if (player && simple_distance(monster, player) < 480) {
+ commence_attack(monster, player, "fireball");
}
}
- else
- for(var id in instances[monster.in].players)
- {
- var player=instances[monster.in].players[id];
- if(distance(player,monster)<480)
- {
- commence_attack(monster,player,"fireball");
+ } else {
+ for (var id in instances[monster.in].players) {
+ var player = instances[monster.in].players[id];
+ if (distance(player, monster) < 480) {
+ commence_attack(monster, player, "fireball");
}
}
- monster.cid++; monster.u=true; change=true;
+ }
+ monster.cid++;
+ monster.u = true;
+ change = true;
}
- if(name=="multi_freeze")
- {
- for(var name in monster.points||{})
- {
- var player=get_player(name);
- if(player && simple_distance(monster,player)<480)
- {
- commence_attack(monster,player,"frostball");
+ if (name == "multi_freeze") {
+ for (var name in monster.points || {}) {
+ var player = get_player(name);
+ if (player && simple_distance(monster, player) < 480) {
+ commence_attack(monster, player, "frostball");
}
}
- monster.cid++; monster.u=true; change=true;
+ monster.cid++;
+ monster.u = true;
+ change = true;
}
- if(name=="degen")
- {
- monster.hp-=60;
- monster.cid++; monster.u=true; change=true;
- if(monster.hp<=0) monster.hp=0,remove_monster(monster);
+ if (name == "degen") {
+ monster.hp -= 60;
+ monster.cid++;
+ monster.u = true;
+ change = true;
+ if (monster.hp <= 0) {
+ monster.hp = 0;
+ remove_monster(monster);
+ }
}
- if(name=="zap")
- {
- for(var id in instances[monster.in].players)
- {
- var player=instances[monster.in].players[id];
- if(distance(player,monster)0.99 || Math.random()interval)
- {
- var pname=random_one(Object.keys(monster.points));
- var player=get_player(pname);
- if(!player || player.npc || distance(monster,player)>400) return;
- if(!is_same(player,get_player(monster.target),true)) return;
- monster.last[name]=new Date();
- var spot=safe_xy_nearby(player.map,player.x+Math.random()*20-10,player.y+Math.random()*20-10);
- if(!spot) return;
- new_monster(instance.name,{type:name,stype:"spawn",x:spot.x,y:spot.y,target:player.name,master:monster.id});
+ if (
+ !monster.pet &&
+ !monster.trap &&
+ mode.aggro &&
+ !monster.target &&
+ monster.aggro &&
+ can_attack(monster, "aggro")
+ ) {
+ monster.last_aggro = new Date();
+ if (monster.aggro > 0.99 || Math.random() < monster.aggro) {
+ set_ghash(aggressives, monster, 32);
+ }
+ }
+ if (monster.target && monster.spawns && get_player(monster.target) && !is_disabled(monster)) {
+ monster.spawns.forEach(function (spi) {
+ var interval = spi[0];
+ var name = spi[1];
+ if (!monster.last[name] || mssince(monster.last[name]) > interval) {
+ var pname = random_one(Object.keys(monster.points));
+ var player = get_player(pname);
+ if (!player || player.npc || distance(monster, player) > 400) {
+ return;
+ }
+ if (!is_same(player, get_player(monster.target), true)) {
+ return;
+ }
+ monster.last[name] = new Date();
+ var spot = safe_xy_nearby(player.map, player.x + Math.random() * 20 - 10, player.y + Math.random() * 20 - 10);
+ if (!spot) {
+ return;
+ }
+ new_monster(instance.name, {
+ type: name,
+ stype: "spawn",
+ x: spot.x,
+ y: spot.y,
+ target: player.name,
+ master: monster.id,
+ });
}
});
}
- function attack_target_or_move()
- {
- var player=players[name_to_id[monster.target]];
- if(player && ssince(monster.last.attacked)>20 && Math.random()>monster.rage*0.99)
- {
- stop_pursuit(monster,{force:true,cause:"bored"});
+ function attack_target_or_move() {
+ var player = players[name_to_id[monster.target]];
+ if (player && ssince(monster.last.attacked) > 20 && Math.random() > monster.rage * 0.99) {
+ stop_pursuit(monster, { force: true, cause: "bored" });
return;
}
- if(focus && distance(focus,monster)>40 && !monster.moving)
- {
- if(mode.all_smart)
- {
- if(!monster.worker)
- {
- monster.working=true;
- workers[(wlast++)%workers.length].postMessage({type:"fast_astar",in:monster.in,id:monster.id,map:monster.map,sx:monster.x,sy:monster.y,tx:focus.x,ty:focus.y});
+ if (focus && distance(focus, monster) > 40 && !monster.moving) {
+ if (mode.all_smart) {
+ if (!monster.worker) {
+ monster.working = true;
+ workers[wlast++ % workers.length].postMessage({
+ type: "fast_astar",
+ in: monster.in,
+ id: monster.id,
+ map: monster.map,
+ sx: monster.x,
+ sy: monster.y,
+ tx: focus.x,
+ ty: focus.y,
+ });
}
- }
- else
- {
- monster.ogoing_x=monster.going_x,monster.ogoing_y=monster.going_y;
- monster.going_x=monster.x+(focus.x-monster.x)/2;
- monster.going_y=monster.y+(focus.y-monster.y)/2;
- if(mode.path_checks && !can_move(monster))
- {
- monster.going_x=monster.ogoing_x,monster.going_y=monster.ogoing_y;
- }
- else
- {
+ } else {
+ monster.ogoing_x = monster.going_x;
+ monster.ogoing_y = monster.going_y;
+ monster.going_x = monster.x + (focus.x - monster.x) / 2;
+ monster.going_y = monster.y + (focus.y - monster.y) / 2;
+ if (mode.path_checks && !can_move(monster)) {
+ monster.going_x = monster.ogoing_x;
+ monster.going_y = monster.ogoing_y;
+ } else {
start_moving_element(monster);
}
}
}
- if(player && player.in==monster.in && !player.rip && !is_invis(player))
- {
- if(distance(player,monster,true)>min(monster.range/1.6,240)+min(100,monster.attack/5.0)+160+(mode.all_smart&&320||1) && !monster.walk_once) stop_pursuit(monster,{cause:"exceeds_range"});
- else if(can_attack(monster,player))
- {
- var attack=commence_attack(monster,player,"attack");
- if(attack && attack.events && attack.events.length) events.push(...attack.events);
- }
- else if(distance(monster,player,true)>12 && !mode.range_test && !(mode.all_smart && monster.moving) && !focus)
- {
- // console.log(monster.height);
- if(mode.all_smart)
- {
- if(!monster.worker)
- {
- monster.working=true;
- workers[(wlast++)%workers.length].postMessage({type:"fast_astar",in:monster.in,id:monster.id,map:monster.map,sx:monster.x,sy:monster.y,tx:player.x,ty:player.y});
- }
+ if (player && player.in == monster.in && !player.rip && !is_invis(player)) {
+ if (
+ distance(player, monster, true) >
+ min(monster.range / 1.6, 240) + min(100, monster.attack / 5.0) + 160 + ((mode.all_smart && 320) || 1) &&
+ !monster.walk_once
+ ) {
+ stop_pursuit(monster, { cause: "exceeds_range" });
+ } else if (can_attack(monster, player)) {
+ var attack = commence_attack(monster, player, "attack");
+ if (attack && attack.events && attack.events.length) {
+ events.push(...attack.events);
}
- else
- {
- monster.ogoing_x=monster.going_x,monster.ogoing_y=monster.going_y;
- monster.going_x=monster.x+(player.x-monster.x)/2;
- monster.going_y=monster.y+(player.y-monster.y)/2;
- if(mode.path_checks && !can_move(monster))
- {
- monster.going_x=monster.ogoing_x,monster.going_y=monster.ogoing_y;
- if(monster.attack<120 || distance(monster,player,true)>monster.range) stop_pursuit(monster,{cause:"cant_move"});
+ } else if (
+ distance(monster, player, true) > 12 &&
+ !mode.range_test &&
+ !(mode.all_smart && monster.moving) &&
+ !focus
+ ) {
+ // console.log(monster.height);
+ if (mode.all_smart) {
+ if (!monster.worker) {
+ monster.working = true;
+ workers[wlast++ % workers.length].postMessage({
+ type: "fast_astar",
+ in: monster.in,
+ id: monster.id,
+ map: monster.map,
+ sx: monster.x,
+ sy: monster.y,
+ tx: player.x,
+ ty: player.y,
+ });
}
- else
- {
+ } else {
+ monster.ogoing_x = monster.going_x;
+ monster.ogoing_y = monster.going_y;
+ monster.going_x = monster.x + (player.x - monster.x) / 2;
+ monster.going_y = monster.y + (player.y - monster.y) / 2;
+ if (mode.path_checks && !can_move(monster)) {
+ monster.going_x = monster.ogoing_x;
+ monster.going_y = monster.ogoing_y;
+ if (monster.attack < 120 || distance(monster, player, true) > monster.range) {
+ stop_pursuit(monster, { cause: "cant_move" });
+ }
+ } else {
// console.log("Moving to "+monster.going_x+" "+monster.going_y);
start_moving_element(monster);
}
}
}
+ } else if (monster.target) {
+ stop_pursuit(monster, { cause: "player_gone" });
+ }
+ if (monster.walk_once) {
+ monster.walk_once = false;
}
- else if(monster.target) stop_pursuit(monster,{cause:"player_gone"});
- if(monster.walk_once) monster.walk_once=false;
}
- if(monster.moving)
- {
- var ms=mssince(monster.last.move);
- ms=min(ms,2000); // to prevent monsters from jumping off the map when the machine sleeps
- monster.x+=monster.vx*ms/1000.0;
- monster.y+=monster.vy*ms/1000.0;
+ if (monster.moving) {
+ var ms = mssince(monster.last.move);
+ ms = min(ms, 2000); // to prevent monsters from jumping off the map when the machine sleeps
+ monster.x += (monster.vx * ms) / 1000.0;
+ monster.y += (monster.vy * ms) / 1000.0;
stop_logic(monster);
- monster.last.move=new Date();
+ monster.last.move = new Date();
xy_u_logic(monster);
- if(monster.moving && monster.attack>100 && monster.target)
- {
+ if (monster.moving && monster.attack > 100 && monster.target) {
attack_target_or_move();
}
- }
- else if(monster.s.sleeping || monster.working)
- {
-
- }
- else if(can_walk(monster)) // for the .s.stunned check
- {
- if(monster.s.magiport);
- else if(monster.target || focus)
- {
+ } else if (monster.s.sleeping || monster.working) {
+ } else if (can_walk(monster)) {
+ // for the .s.stunned check
+ if (monster.s.magiport) {
+ } else if (monster.target || focus) {
attack_target_or_move();
- }
- else if(!mode.upush_test)
- {
- if(monster.map_def.position && !mode.all_roam)
- {
- var position=monster.map_def.position,radius=monster.map_def.radius,dx=Math.random()*(radius)-radius/2,dy=Math.random()*(radius)-radius/2;
- if(abs(dx)+abs(dy)<80) // optimization to prevent short walks
- {
- if(dx<0 && dx>-60) dx=-60; if(dx>0 && dx<60) dx=60;
- if(dy<0 && dy>-60) dy=-60; if(dy>0 && dy<60) dy=60;
+ } else if (!mode.upush_test) {
+ if (monster.map_def.position && !mode.all_roam) {
+ var position = monster.map_def.position;
+ var radius = monster.map_def.radius;
+ var dx = Math.random() * radius - radius / 2;
+ var dy = Math.random() * radius - radius / 2;
+ if (abs(dx) + abs(dy) < 80) {
+ // optimization to prevent short walks
+ if (dx < 0 && dx > -60) {
+ dx = -60;
+ }
+ if (dx > 0 && dx < 60) {
+ dx = 60;
+ }
+ if (dy < 0 && dy > -60) {
+ dy = -60;
+ }
+ if (dy > 0 && dy < 60) {
+ dy = 60;
+ }
+ }
+ monster.going_x = monster.x + dx;
+ monster.going_y = monster.y + dy;
+ if (monster.going_x > position[0] + radius) {
+ monster.going_x = position[0] + radius;
+ }
+ if (monster.going_y > position[1] + radius) {
+ monster.going_y = position[1] + radius;
+ }
+ if (monster.going_x < position[0] - radius) {
+ monster.going_x = position[0] - radius;
+ }
+ if (monster.going_y < position[1] - radius) {
+ monster.going_y = position[1] - radius;
}
- monster.going_x=monster.x+dx;
- monster.going_y=monster.y+dy;
- if(monster.going_x>position[0]+radius) monster.going_x=position[0]+radius;
- if(monster.going_y>position[1]+radius) monster.going_y=position[1]+radius;
- if(monster.going_x1 && monster.map_def.polygon)
- {
- if(is_point_inside([monster.going_x,monster.going_y],monster.map_def.polygon)) break;
- else monster.rmove++,monster.dmove++;
+ } else if (
+ monster.map_def.roam ||
+ G.monsters[monster.type].roam ||
+ mode.all_roam ||
+ (monster.map_def.polygon && !monster.irregular)
+ ) {
+ perfc.roams += 1;
+ var map_def = monster.map_def;
+ var tries = 1;
+ if (!monster.map_def.roam && !mode.all_roam && monster.map_def.polygon) {
+ tries = 12;
+ }
+ if (!monster.rmove) {
+ monster.rmove = parseInt(Math.random() * 100);
+ }
+ monster.dmove = monster.dmove || 0;
+ for (var t = 0; t < tries; t++) {
+ var moves = [
+ [1, 0],
+ [0.8, 0.8],
+ [0, 1],
+ [-0.8, 0.8],
+ [-1, 0],
+ [-0.8, -0.8],
+ [0, -1],
+ [0.8, -0.8],
+ ];
+ var multipliers = [500, 200, 100, 50, 10];
+ if (Math.random() < 0.1) {
+ monster.rmove = parseInt(Math.random() * moves.length);
+ }
+ var move = moves[monster.rmove % moves.length];
+ var d = multipliers[monster.dmove % multipliers.length];
+ monster.going_x = monster.x + move[0] * d;
+ monster.going_y = monster.y + move[1] * d;
+ if (tries > 1 && monster.map_def.polygon) {
+ if (is_point_inside([monster.going_x, monster.going_y], monster.map_def.polygon)) {
+ break;
+ } else {
+ monster.rmove++;
+ monster.dmove++;
+ }
}
}
// console.log(monster.rmove+","+monster.dmove+" "+monster.going_x+","+monster.going_y);
- if(can_move(monster))
- {
+ if (can_move(monster)) {
start_moving_element(monster);
- monster.dmove=0;
+ monster.dmove = 0;
+ } else {
+ monster.rmove++;
+ monster.dmove++;
}
- else monster.rmove++,monster.dmove++;
- }
- else if(monster.map_def.stype!="pet" && monster.map_def.stype!="spawn" && monster.map_def.stype!="trap")
- {
- var map_def=monster.map_def,to_move=true;
- if(map_def.polygon)
- {
- var p=random_point(map_def.polygon,monster.base);
- monster.going_x=p[0];
- monster.going_y=p[1];
+ } else if (
+ monster.map_def.stype != "pet" &&
+ monster.map_def.stype != "spawn" &&
+ monster.map_def.stype != "trap"
+ ) {
+ var map_def = monster.map_def;
+ var to_move = true;
+ if (map_def.polygon) {
+ var p = random_point(map_def.polygon, monster.base);
+ monster.going_x = p[0];
+ monster.going_y = p[1];
+ } else {
+ monster.going_x = map_def.boundary[0] + Math.random() * (map_def.boundary[2] - map_def.boundary[0]);
+ monster.going_y = map_def.boundary[1] + Math.random() * (map_def.boundary[3] - map_def.boundary[1]);
}
- else
- {
- monster.going_x=map_def.boundary[0]+Math.random()*(map_def.boundary[2]-map_def.boundary[0]);
- monster.going_y=map_def.boundary[1]+Math.random()*(map_def.boundary[3]-map_def.boundary[1]);
- }
- if(monster.irregular==3) // new [01/03/19]
- {
+ if (monster.irregular == 3) {
+ // new [01/03/19]
monster.m++;
- setTimeout(new_monster_f(monster.oin,monster.map_def,{last_state:monster}),500);
- remove_monster(monster,{nospawn:true,method:"disappear"})
- }
- else if(monster.irregular==2)
- {
- server_log("Irregular2 move for "+monster.id);
- if(monster.in!=monster.oin) port_monster(monster,{map:monster.oin,x:monster.going_x,y:monster.going_y,in:monster.oin});
- else recalculate_move(monster);
- monster.irregular=1;
- }
- else if(monster.irregular==1)
- {
- if(!can_move(monster))
- {
- monster.m++;
- server_log("Irregular1 respawn: "+monster.id);
- setTimeout(new_monster_f(monster.oin,monster.map_def,{last_state:monster}),500);
- remove_monster(monster,{nospawn:true,method:"disappear"})
+ setTimeout(new_monster_f(monster.oin, monster.map_def, { last_state: monster }), 500);
+ remove_monster(monster, { nospawn: true, method: "disappear" });
+ } else if (monster.irregular == 2) {
+ server_log("Irregular2 move for " + monster.id);
+ if (monster.in != monster.oin) {
+ port_monster(monster, { map: monster.oin, x: monster.going_x, y: monster.going_y, in: monster.oin });
+ } else {
+ recalculate_move(monster);
}
- else
- {
- server_log("No longer irregular: "+monster.id);
+ monster.irregular = 1;
+ } else if (monster.irregular == 1) {
+ if (!can_move(monster)) {
+ monster.m++;
+ server_log("Irregular1 respawn: " + monster.id);
+ setTimeout(new_monster_f(monster.oin, monster.map_def, { last_state: monster }), 500);
+ remove_monster(monster, { nospawn: true, method: "disappear" });
+ } else {
+ server_log("No longer irregular: " + monster.id);
delete monster["irregular"];
}
}
- if(monster.going_x!=monster.x || monster.going_y!=monster.y) // so Automatron's don't move
+ if (monster.going_x != monster.x || monster.going_y != monster.y) {
+ // so Automatron's don't move
start_moving_element(monster);
+ }
}
}
}
- if(!monster.dead && (monster.u || events.length))
- {
- monster.u=false;
- to_push.push({id:id,entity:monster,data:monster_to_client(monster,events)});
- monster_map[id]=to_push[to_push.length-1];
+ if (!monster.dead && (monster.u || events.length)) {
+ monster.u = false;
+ to_push.push({ id: id, entity: monster, data: monster_to_client(monster, events) });
+ monster_map[id] = to_push[to_push.length - 1];
}
}
- for(var id in instance.players)
- {
- var player=instance.players[id];
- if(!player) continue;
- for(var name in player.s)
- {
- var def=G.conditions[name],ref=player.s[name],value=player.s[name].ms;
- player.s[name].ms-=ms;
- if(def && def.interval)
- {
- if(!player.s[name].last || mssince(player.s[name].last)>=def.interval)
- {
- player.s[name].last=new Date();
- if(name=="eburn")
- {
- disappearing_text(player.socket,player,"-50",{color:"red",xy:1});
- player.hp=max(1,player.hp-50);
+ for (var id in instance.players) {
+ var player = instance.players[id];
+ if (!player) {
+ continue;
+ }
+ for (var name in player.s) {
+ var def = G.conditions[name];
+ var ref = player.s[name];
+ var value = player.s[name].ms;
+ player.s[name].ms -= ms;
+ if (def && def.interval) {
+ if (!player.s[name].last || mssince(player.s[name].last) >= def.interval) {
+ player.s[name].last = new Date();
+ if (name == "eburn") {
+ disappearing_text(player.socket, player, "-50", { color: "red", xy: 1 });
+ player.hp = max(1, player.hp - 50);
}
- if(name=="eheal")
- {
- disappearing_text(player.socket,player,"+50",{color:"heal",xy:1});
- player.hp=min(player.max_hp,player.hp+50);
+ if (name == "eheal") {
+ disappearing_text(player.socket, player, "+50", { color: "heal", xy: 1 });
+ player.hp = min(player.max_hp, player.hp + 50);
}
- if(name=="burned")
- {
- var damage=ceil(ref.intensity/5);
- disappearing_text(player.socket,player,"-"+damage,{color:"red",xy:1});
- player.hp=max(0,player.hp-damage);
- xy_emit(player,"hit",{source:"burn",hid:ref.fid,id:player.name,damage:damage,kill:(player.hp<=0)});
+ if (name == "burned") {
+ var damage = ceil(ref.intensity / 5);
+ disappearing_text(player.socket, player, "-" + damage, { color: "red", xy: 1 });
+ player.hp = max(0, player.hp - damage);
+ xy_emit(player, "hit", {
+ source: "burn",
+ hid: ref.fid,
+ id: player.name,
+ damage: damage,
+ kill: player.hp <= 0,
+ });
player_rip_logic(player);
}
- resend(player,"u+cid+nc");
+ resend(player, "u+cid+nc");
}
}
- if(in_arr(name,["damage_received"]))
- {
- player.s[name].amount=max(0,player.s[name].amount*(4000-ms)/4000.0)
+ if (in_arr(name, ["damage_received"])) {
+ player.s[name].amount = max(0, (player.s[name].amount * (4000 - ms)) / 4000.0);
}
- if(player.s[name].ms<=0)
- {
+ if (player.s[name].ms <= 0) {
delete player.s[name];
- if(name=="blink")
- {
- if(player.s.dampened)
- {
- xy_emit(player,"ui",{type:"dampened",name:player.name});
- }
- else
- {
- decay_s(player,30000);
- transport_player_to(player,ref.in,[ref.x,ref.y,ref.d],"blink");
+ if (name == "blink") {
+ if (player.s.dampened) {
+ xy_emit(player, "ui", { type: "dampened", name: player.name });
+ } else {
+ decay_s(player, 30000);
+ transport_player_to(player, ref.in, [ref.x, ref.y, ref.d], "blink");
}
}
- if(name=="magiport")
- {
- var dampened=false;
- for(var id in instances[ref.in].monsters)
- {
- var m=instances[ref.in].monsters[id];
- if(m.type=="fieldgen0" && point_distance(ref.x,ref.y,m.x,m.y)<300)
- {
- xy_emit(player,"ui",{type:"dampened",name:player.name});
- dampened=true;
+ if (name == "magiport") {
+ var dampened = false;
+ for (var id in instances[ref.in].monsters) {
+ var m = instances[ref.in].monsters[id];
+ if (m.type == "fieldgen0" && point_distance(ref.x, ref.y, m.x, m.y) < 300) {
+ xy_emit(player, "ui", { type: "dampened", name: player.name });
+ dampened = true;
break;
}
}
- if(!dampened)
- {
- var skip=false;
- if(ref.map!=player.map) skip=true;
- decay_s(player,30000);
- transport_player_to(player,ref.in,[ref.x,ref.y],"magiport");
- if(skip)
- {
- resend(player,"u+cid");
+ if (!dampened) {
+ var skip = false;
+ if (ref.map != player.map) {
+ skip = true;
+ }
+ decay_s(player, 30000);
+ transport_player_to(player, ref.in, [ref.x, ref.y], "magiport");
+ if (skip) {
+ resend(player, "u+cid");
return; // player isn't in this instance any more
}
}
}
- if(def) player.socket.emit("game_response",{response:"ex_condition",name:name});
- if(def && def.ui) resend(player,"u+cid"); // +cid to update the UI's [23/10/18]
- else resend(player,"u"); // #TODO: don't need to resend actually, maybe reconsider [27/06/18]
-
+ if (def) {
+ player.socket.emit("game_response", { response: "ex_condition", name: name });
+ }
+ if (def && def.ui) {
+ resend(player, "u+cid");
+ } // +cid to update the UI's [23/10/18]
+ else {
+ resend(player, "u");
+ } // #TODO: don't need to resend actually, maybe reconsider [27/06/18]
}
}
- for(var name in player.q)
- {
- var value=player.q[name].ms,ref=player.q[name];
- player.q[name].ms-=ms;
- if(name=="upgrade")
- {
- if(player.items[ref.num] && player.items[ref.num].name=="placeholder")
- {
- var def=player.items[ref.num].p,change=false;
- if(value1800000 && !player.stealth)
- broadcast("server_message",{"message":player.name+" received "+item_to_phrase(item),"color":colors.server_success,item:cache_item(item),"type":"server_csuccess",name:player.name});
- xy_emit(G.maps.main.compound,"upgrade",{type:"compound",success:1});
- if(player.items[ref.num] && player.items[ref.num].name=="placeholder")
- {
- player.items[ref.num]=item;
- player.citems[ref.num]=cache_item(player.items[ref.num]);
+ if (name == "compound") {
+ if (player.p.c_item) {
+ var item = player.p.c_item;
+ var def = G.items[item.name];
+ player.hitchhikers.push([
+ "game_response",
+ {
+ response: "compound_success",
+ stale: ref.stale,
+ level: item.level,
+ num: data.num,
+ up: item.extra || undefined,
+ },
+ ]);
+ if (calculate_item_value(item) + (def.edge || 0) * 2000000 > 1800000 && !player.stealth) {
+ broadcast("server_message", {
+ message: player.name + " received " + item_to_phrase(item),
+ color: colors.server_success,
+ item: cache_item(item),
+ type: "server_csuccess",
+ name: player.name,
+ });
+ }
+ xy_emit(G.maps.main.compound, "upgrade", { type: "compound", success: 1 });
+ if (player.items[ref.num] && player.items[ref.num].name == "placeholder") {
+ player.items[ref.num] = item;
+ player.citems[ref.num] = cache_item(player.items[ref.num]);
+ }
+ achievement_logic_compound_success(player, item);
+ } else {
+ var item = player.p.c_itemx;
+ var def = G.items[item.name];
+ player.hitchhikers.push([
+ "game_response",
+ { response: "compound_fail", level: item.level, num: data.num, stale: ref.stale },
+ ]);
+ if (calculate_item_value(item) + (def.edge || 0) * 2000000 > 920000 && !player.stealth) {
+ broadcast("server_message", {
+ message: player.name + " lost " + item_to_phrase(item) + "'s",
+ color: colors.server_failure,
+ item: cache_item(item),
+ type: "server_cfail",
+ name: player.name,
+ });
+ }
+ xy_emit(G.maps.main.compound, "upgrade", { type: "compound", success: 0 });
+ if (player.items[ref.num] && player.items[ref.num].name == "placeholder") {
+ player.citems[ref.num] = player.items[ref.num] = null;
+ player.esize++;
}
- achievement_logic_compound_success(player,item);
}
- else
- {
- var item=player.p.c_itemx,def=G.items[item.name];
- player.hitchhikers.push(["game_response",{response:"compound_fail",level:item.level,num:data.num,stale:ref.stale}]);
- if(calculate_item_value(item)+(def.edge||0)*2000000>920000 && !player.stealth)
- broadcast("server_message",{"message":player.name+" lost "+item_to_phrase(item)+"'s","color":colors.server_failure,item:cache_item(item),"type":"server_cfail",name:player.name});
- xy_emit(G.maps.main.compound,"upgrade",{type:"compound",success:0});
- if(player.items[ref.num] && player.items[ref.num].name=="placeholder")
- player.citems[ref.num]=player.items[ref.num]=null,player.esize++;
- }
- delete player.p.c_item; delete player.p.c_itemx; delete player.p.c_roll;
- resend(player,"reopen+u+cid+nc+inv");
+ delete player.p.c_item;
+ delete player.p.c_itemx;
+ delete player.p.c_roll;
+ resend(player, "reopen+u+cid+nc+inv");
}
- if(name=="upgrade")
- {
- var success=false,announce=false,new_level=player.p.u_level+1;
- var item=player.p.u_item||player.p.u_itemx;
- var p=player.items[ref.num] && player.items[ref.num].p;
- if(player.p.u_item && player.items[ref.num] && player.items[ref.num].name=="placeholder")
- {
- success=true;
- player.items[ref.num]=player.p.u_item;
- player.citems[ref.num]=cache_item(player.items[ref.num]);
+ if (name == "upgrade") {
+ var success = false;
+ var announce = false;
+ var new_level = player.p.u_level + 1;
+ var item = player.p.u_item || player.p.u_itemx;
+ var p = player.items[ref.num] && player.items[ref.num].p;
+ if (player.p.u_item && player.items[ref.num] && player.items[ref.num].name == "placeholder") {
+ success = true;
+ player.items[ref.num] = player.p.u_item;
+ player.citems[ref.num] = cache_item(player.items[ref.num]);
+ } else if (player.items[ref.num] && player.items[ref.num].name == "placeholder") {
+ player.citems[ref.num] = player.items[ref.num] = null;
+ player.esize++;
}
- else if(player.items[ref.num] && player.items[ref.num].name=="placeholder")
- player.citems[ref.num]=player.items[ref.num]=null,player.esize++;
- if(player.p.u_type=="offering")
- {
- if(success) player.hitchhikers.push(["game_response",{response:"upgrade_offering_success",stale:ref.stale}]);
+ if (player.p.u_type == "offering") {
+ if (success) {
+ player.hitchhikers.push(["game_response", { response: "upgrade_offering_success", stale: ref.stale }]);
+ }
+ } else if (player.p.u_type == "stat") {
+ if (success) {
+ player.hitchhikers.push([
+ "game_response",
+ {
+ response: "upgrade_success_stat",
+ stale: ref.stale,
+ stat_type: p && G.items[p.scroll].stat,
+ num: ref.num,
+ },
+ ]);
+ }
+ } else if (!ref.silent) {
+ announce = true;
}
- else if(player.p.u_type=="stat")
- {
- if(success) player.hitchhikers.push(["game_response",{response:"upgrade_success_stat",stale:ref.stale,stat_type:p&&G.items[p.scroll].stat,num:ref.num}]);
+
+ if (success && !player.p.u_fail) {
+ if (announce) {
+ player.hitchhikers.push([
+ "game_response",
+ { response: "upgrade_success", level: new_level, num: ref.num, stale: ref.stale },
+ ]);
+ }
+ if (announce && calculate_item_value(item) > 4800000 && !player.stealth) {
+ broadcast("server_message", {
+ message: player.name + " received " + item_to_phrase(item),
+ color: colors.server_success,
+ item: cache_item(item),
+ type: "server_usuccess",
+ name: player.name,
+ });
+ }
+ xy_emit((instances.main && G.maps.main.upgrade) || player, "upgrade", { type: "upgrade", success: 1 });
+ achievement_logic_upgrade_success(player, item);
+ } else {
+ player.hitchhikers.push([
+ "game_response",
+ { response: "upgrade_fail", level: new_level, num: ref.num, stale: ref.stale },
+ ]);
+ if (announce && calculate_item_value(item) > 4800000 && !player.stealth) {
+ broadcast("server_message", {
+ message: player.name + " lost " + item_to_phrase(item),
+ color: colors.server_failure,
+ item: cache_item(item),
+ type: "server_ufail",
+ name: player.name,
+ });
+ }
+ xy_emit((instances.main && G.maps.main.upgrade) || player, "upgrade", { type: "upgrade", success: 0 });
}
- else if(!ref.silent)
- announce=true;
-
- if(success && !player.p.u_fail)
- {
- if(announce) player.hitchhikers.push(["game_response",{response:"upgrade_success",level:new_level,num:ref.num,stale:ref.stale}]);
- if(announce && calculate_item_value(item)>4800000 && !player.stealth)
- broadcast("server_message",{"message":player.name+" received "+item_to_phrase(item),"color":colors.server_success,item:cache_item(item),"type":"server_usuccess",name:player.name});
- xy_emit(instances.main&&G.maps.main.upgrade||player,"upgrade",{type:"upgrade",success:1});
- achievement_logic_upgrade_success(player,item);
- }
- else
- {
- player.hitchhikers.push(["game_response",{response:"upgrade_fail",level:new_level,num:ref.num,stale:ref.stale}]);
- if(announce && calculate_item_value(item)>4800000 && !player.stealth)
- broadcast("server_message",{"message":player.name+" lost "+item_to_phrase(item),"color":colors.server_failure,item:cache_item(item),"type":"server_ufail",name:player.name});
- xy_emit(instances.main&&G.maps.main.upgrade||player,"upgrade",{type:"upgrade",success:0});
- }
- delete player.p.u_item; delete player.p.u_type; delete player.p.u_itemx; delete player.p.u_roll; delete player.p.u_fail; delete player.p.u_level;
- resend(player,"reopen+u+cid+nc+inv");
+ delete player.p.u_item;
+ delete player.p.u_type;
+ delete player.p.u_itemx;
+ delete player.p.u_roll;
+ delete player.p.u_fail;
+ delete player.p.u_level;
+ resend(player, "reopen+u+cid+nc+inv");
}
- if(name=="slots")
- {
- if(Math.random()<((S.gold>500000000)&&D.odds.slots_good||D.odds.slots))
- {
- var gold=500000000;
- player.gold+=gold; S.gold-=gold;
- broadcast("server_message",{"message":player.name+" received "+to_pretty_num(gold)+" gold","color":"gold"});
- player.socket.emit("game_response","slots_success");
- player.socket.emit("game_log",{message:"Received "+to_pretty_num(gold)+" gold",color:"gold"});
+ if (name == "slots") {
+ if (Math.random() < ((S.gold > 500000000 && D.odds.slots_good) || D.odds.slots)) {
+ var gold = 500000000;
+ player.gold += gold;
+ S.gold -= gold;
+ broadcast("server_message", {
+ message: player.name + " received " + to_pretty_num(gold) + " gold",
+ color: "gold",
+ });
+ player.socket.emit("game_response", "slots_success");
+ player.socket.emit("game_log", { message: "Received " + to_pretty_num(gold) + " gold", color: "gold" });
// resend(player,"u+cid");
+ } else {
+ player.socket.emit("game_response", "slots_fail");
}
- else player.socket.emit("game_response","slots_fail");
}
}
}
- for(var name in player.c)
- {
- player.c[name].ms-=ms;
- if(player.c[name].ms<=0)
- {
- var ref=player.c[name];
+ for (var name in player.c) {
+ player.c[name].ms -= ms;
+ if (player.c[name].ms <= 0) {
+ var ref = player.c[name];
delete player.c[name];
- if(name=="town")
- {
- decay_s(player,4000);
- player.last.town=new Date();
- transport_player_to(player,player.in,undefined,1);
+ if (name == "town") {
+ decay_s(player, 4000);
+ player.last.town = new Date();
+ transport_player_to(player, player.in, undefined, 1);
resend(player);
}
- if(name=="pickpocket")
- {
- var target=get_player(ref.target);
- if(!target) player.socket.emit("game_response",{response:"pick_failed",cevent:true,reason:"player_gone"});
- else if(distance(player,target)>20) player.socket.emit("game_response",{response:"pick_failed",cevent:true,reason:"distance"});
- else
- {
- var num=floor(Math.random()*42);
- if(target.items[num] && target.items[num].v)
- {
- var item=target.items[num];
- if(item.q && item.q>1)
- {
- target.items[num].q-=1; target.citems[num].q-=1;
- item=create_new_item(item.name);
+ if (name == "pickpocket") {
+ var target = get_player(ref.target);
+ if (!target) {
+ player.socket.emit("game_response", { response: "pick_failed", cevent: true, reason: "player_gone" });
+ } else if (distance(player, target) > 20) {
+ player.socket.emit("game_response", { response: "pick_failed", cevent: true, reason: "distance" });
+ } else {
+ var num = floor(Math.random() * 42);
+ if (target.items[num] && target.items[num].v) {
+ var item = target.items[num];
+ if (item.q && item.q > 1) {
+ target.items[num].q -= 1;
+ target.citems[num].q -= 1;
+ item = create_new_item(item.name);
+ } else {
+ target.citems[num] = target.items[num] = null;
}
- else
- {
- target.citems[num]=target.items[num]=null;
- }
- item.v=new Date();
- add_item(player,item);
- player.socket.emit("game_response",{response:"picked",slot:"mainhand",cevent:true});
- consume_skill(player,"pickpocket",true);
- resend(player,"reopen"); resend(target,"reopen");
- target.socket.emit("game_response",{response:"got_picked",cevent:true});
- }
- else
- {
- player.socket.emit("game_response",{response:"pick_failed",cevent:true,reason:"misfortune"});
+ item.v = new Date();
+ add_item(player, item);
+ player.socket.emit("game_response", { response: "picked", slot: "mainhand", cevent: true });
+ consume_skill(player, "pickpocket", true);
+ resend(player, "reopen");
+ resend(target, "reopen");
+ target.socket.emit("game_response", { response: "got_picked", cevent: true });
+ } else {
+ player.socket.emit("game_response", { response: "pick_failed", cevent: true, reason: "misfortune" });
}
}
}
- if(name=="fishing")
- {
- if(Math.random()<0.1)
- {
- if(player.esize) exchange(player,ref.drop,{phrase:"Fished"});
- consume_skill(player,"fishing",true);
- if(player.slots.mainhand)
- {
- var prop=calculate_item_properties(player.slots.mainhand);
- if(prop.breaks && Math.random()player.slots.elixir.expires)
- {
- try{
- var def=G.items[player.slots.elixir.name];
- player.socket.emit("game_log",def.name+" wore off ...");
- if(def.withdrawal) add_condition(player,def.withdrawal);
- }catch(e){}
- player.slots.elixir=null;
- player.cslots.elixir=null;
- resend(player,"reopen+u+cid");
+ if (player.slots.elixir && player.slots.elixir.expires && now_date > player.slots.elixir.expires) {
+ try {
+ var def = G.items[player.slots.elixir.name];
+ player.socket.emit("game_log", def.name + " wore off ...");
+ if (def.withdrawal) {
+ add_condition(player, def.withdrawal);
+ }
+ } catch (e) {}
+ player.slots.elixir = null;
+ player.cslots.elixir = null;
+ resend(player, "reopen+u+cid");
}
- if(player.moving)
- {
- var ms=mssince(player.last.move);
- player.x+=player.vx*ms/1000.0;
- player.y+=player.vy*ms/1000.0;
- player.red_zone*=0.99;
- if(smap_data[player.map]!=-1 && !player.npc && mode.red_zone && !player.s.dash)
- {
- var current=smap_data[player.map][phash(player)];
- if(current===undefined) current=8;
- current=max(0,current-1); // 1 is the new 0 [01/08/18]
- player.red_zone+=current;
+ if (player.moving) {
+ var ms = mssince(player.last.move);
+ player.x += (player.vx * ms) / 1000.0;
+ player.y += (player.vy * ms) / 1000.0;
+ player.red_zone *= 0.99;
+ if (smap_data[player.map] != -1 && !player.npc && mode.red_zone && !player.s.dash) {
+ var current = smap_data[player.map][phash(player)];
+ if (current === undefined) {
+ current = 8;
+ }
+ current = max(0, current - 1); // 1 is the new 0 [01/08/18]
+ player.red_zone += current;
// console.log(player.red_zone);
- if(player.red_zone>smap_edge)
- {
- player.red_zone=0;
- player.hp-=parseInt(player.hp/2+1000);
- player.socket.emit("game_log","Received a movement penalty");
- player.socket.emit("game_log","This might have happened if your network is too slow");
- appengine_log("violation","red_zone: "+player.name+" afk: "+player.afk+" code: "+player.code);
- transport_player_to(player,player.map);
+ if (player.red_zone > smap_edge) {
+ player.red_zone = 0;
+ player.hp -= parseInt(player.hp / 2 + 1000);
+ player.socket.emit("game_log", "Received a movement penalty");
+ player.socket.emit("game_log", "This might have happened if your network is too slow");
+ appengine_log("violation", "red_zone: " + player.name + " afk: " + player.afk + " code: " + player.code);
+ transport_player_to(player, player.map);
defeat_player(player);
- if(player.hp<=0) rip(player);
- resend(player,"u+cid");
+ if (player.hp <= 0) {
+ rip(player);
+ }
+ resend(player, "u+cid");
}
}
stop_logic(player);
// if(!player.moving) player.check_x=player.x,player.check_y=player.y,player.checked_xy=false;
- player.last.move=new Date();
+ player.last.move = new Date();
xy_u_logic(player);
xy_upush_logic(player);
- if(!player.npc) pmap_move(player);
+ if (!player.npc) {
+ pmap_move(player);
+ }
+ } else {
+ player.red_zone *= 0.97;
}
- else
- {
- player.red_zone*=0.97;
- }
- if(mode.aggro && !player.rip && !is_invinc(player) && !player.npc)
- {
+ if (mode.aggro && !player.rip && !is_invinc(player) && !player.npc) {
//#GTODO: calculate an angle + compare against monster's .angle before attacking
- var l=get_nearby_ghash(aggressives,player,32);
- l.forEach(function(monster){
- if(is_in_front(monster,player) && can_attack(monster,player))
- {
- if(Math.random()=3) player.socket.disconnect();
+ if (player.u) {
+ player.u = false;
+ to_push.push({ id: id, entity: player, data: player_to_client(player, 1) });
+ }
+ if (player.violations >= 3) {
+ player.socket.disconnect();
+ }
}
- (G.maps[instance.map].traps||[]).forEach(function(trap){
- if(trap.type=="spikes")
- for(var id in pmap_get({x:trap.position[0],y:trap.position[1],in:instance.name}))
- {
- var player=players[id_to_id[id]];
- if(player && !player.npc)
- {
- disappearing_text(player.socket,player,"-50",{color:"red",xy:1});
- player.hp=max(0,player.hp-50);
+ (G.maps[instance.map].traps || []).forEach(function (trap) {
+ if (trap.type == "spikes") {
+ for (var id in pmap_get({ x: trap.position[0], y: trap.position[1], in: instance.name })) {
+ var player = players[id_to_id[id]];
+ if (player && !player.npc) {
+ disappearing_text(player.socket, player, "-50", { color: "red", xy: 1 });
+ player.hp = max(0, player.hp - 50);
player_rip_logic(player);
- resend(player,"u+cid");
+ resend(player, "u+cid");
}
}
- else if(trap.type=="debuff")
- for(var id in instance.players)
- {
- var player=instance.players[id];
- if(is_point_inside([player.x,player.y],trap.polygon))
- {
+ } else if (trap.type == "debuff") {
+ for (var id in instance.players) {
+ var player = instance.players[id];
+ if (is_point_inside([player.x, player.y], trap.polygon)) {
// player.s["debuffaura"]={"ms":200,"name":"Debuff","skin":"citizens","citizens":true,"speed":-40};
- add_condition(player,"slowness",{duration:200});
- resend(player,"u+cid");
+ add_condition(player, "slowness", { duration: 200 });
+ resend(player, "u+cid");
}
}
-
+ }
});
- for(var id in instance.players) send_xy_updates(instance.players[id],to_push);
- for(var id in instance.observers) send_xy_updates(instance.observers[id],to_push);
+ for (var id in instance.players) {
+ send_xy_updates(instance.players[id], to_push);
+ }
+ for (var id in instance.observers) {
+ send_xy_updates(instance.observers[id], to_push);
+ }
}
-function count_unique_users()
-{
- unique_players=0;
- var marked={};
- for(var id in players)
- {
- var ip=get_ip(players[id]);
- if(!marked[ip]) {marked[ip]=1; unique_players++;}
- }
- if(is_sdk) unique_players=9;
- for(name in instances)
- {
- var instance=instances[name];
- if(!instance.pvp) continue;
- var initial=instance.allow,npc=npcs.pvp;
- if(is_sdk && Object.keys(players).length>=2 || unique_players>=B.arena_limit || Object.keys(instance.players).length) // direction logic at game.js/update_sprite
- {
- if(instance.allow) continue;
- instance.allow=true;
- if(!npc) continue;
- npc.going_x=npc.positions[1][0];
- npc.going_y=npc.positions[1][1];
- npc.allow=true;
- npc.u=true;
- start_moving_element(npc);
+function count_unique_users() {
+ unique_players = 0;
+ var marked = {};
+ for (var id in players) {
+ var ip = get_ip(players[id]);
+ if (!marked[ip]) {
+ marked[ip] = 1;
+ unique_players++;
}
- else
- {
- if(!instance.allow) continue;
- instance.allow=false;
- if(!npc) continue;
- npc.going_x=npc.positions[0][0];
- npc.going_y=npc.positions[0][1];
- npc.allow=false;
- npc.u=true;
+ }
+ if (is_sdk) {
+ unique_players = 9;
+ }
+ for (name in instances) {
+ var instance = instances[name];
+ if (!instance.pvp) {
+ continue;
+ }
+ var initial = instance.allow;
+ var npc = npcs.pvp;
+ if (
+ (is_sdk && Object.keys(players).length >= 2) ||
+ unique_players >= B.arena_limit ||
+ Object.keys(instance.players).length
+ ) {
+ // direction logic at game.js/update_sprite
+ if (instance.allow) {
+ continue;
+ }
+ instance.allow = true;
+ if (!npc) {
+ continue;
+ }
+ npc.going_x = npc.positions[1][0];
+ npc.going_y = npc.positions[1][1];
+ npc.allow = true;
+ npc.u = true;
+ start_moving_element(npc);
+ } else {
+ if (!instance.allow) {
+ continue;
+ }
+ instance.allow = false;
+ if (!npc) {
+ continue;
+ }
+ npc.going_x = npc.positions[0][0];
+ npc.going_y = npc.positions[0][1];
+ npc.allow = false;
+ npc.u = true;
start_moving_element(npc);
}
}
}
-var last_iloop=new Date();
-function instance_loop()
-{
- var ms_since=32;
- try{
- var now_date=new Date();
+var last_iloop = new Date();
+function instance_loop() {
+ var ms_since = 32;
+ try {
+ var now_date = new Date();
- for(name in instances)
- {
- var instance=instances[name];
- if(mssince(instance.last_update)>75) update_instance(instance);
+ for (name in instances) {
+ var instance = instances[name];
+ if (mssince(instance.last_update) > 75) {
+ update_instance(instance);
+ }
}
- ms_since=mssince(now_date);
- if(ms_since>B.instance_loop_log_edge) server_log("Instance loop took "+mssince(now_date)+"ms",1);
- perfc.instance_loop[ms_since]=(perfc.instance_loop[ms_since]||0)+1;
- perfc.instance_loops+=1;
- var mss_since=mssince(last_iloop);
- perfc.instance_delay[mss_since]=(perfc.instance_delay[mss_since]||0)+1;
- if(mss_since/1000>15)
- console.log("Sleep detected: "+(mss_since/1000));
- last_iloop=new Date();
- }catch(e){log_trace("#X Instance loop error",e);};
- setTimeout(instance_loop,max(75,min(1000,ms_since*2+2)));
+ ms_since = mssince(now_date);
+ if (ms_since > B.instance_loop_log_edge) {
+ server_log("Instance loop took " + mssince(now_date) + "ms", 1);
+ }
+ perfc.instance_loop[ms_since] = (perfc.instance_loop[ms_since] || 0) + 1;
+ perfc.instance_loops += 1;
+ var mss_since = mssince(last_iloop);
+ perfc.instance_delay[mss_since] = (perfc.instance_delay[mss_since] || 0) + 1;
+ if (mss_since / 1000 > 15) {
+ console.log("Sleep detected: " + mss_since / 1000);
+ }
+ last_iloop = new Date();
+ } catch (e) {
+ log_trace("#X Instance loop error", e);
+ }
+ setTimeout(instance_loop, max(75, min(1000, ms_since * 2 + 2)));
}
-function npc_loop() // now mainly just NPC's, back in the day pretty much everything [11/08/22]
-{
- if(!server.live) return setTimeout(npc_loop,10);
- var ms_since=32;
- try{
- var now_date=new Date();
+function npc_loop() {
+ // now mainly just NPC's, back in the day pretty much everything [11/08/22]
+ if (!server.live) {
+ return setTimeout(npc_loop, 10);
+ }
+ var ms_since = 32;
+ try {
+ var now_date = new Date();
- for(var id in npcs)
- {
- var npc=npcs[id],delay=-npc.delay*npc.d_multiplier;
- if(npc.rip) continue;
- var def=G.npcs[npc.ntype]||{};
- if(def && instances[npc.in] && instances[npc.in].players && def.aura && (!npc.last_aura || mssince(npc.last_aura)>2000))
- {
- npc.last_aura=new Date();
- for(var pid in instances[npc.in].players)
- {
- var player=instances[npc.in].players[pid];
+ for (var id in npcs) {
+ var npc = npcs[id];
+ var delay = -npc.delay * npc.d_multiplier;
+ if (npc.rip) {
+ continue;
+ }
+ var def = G.npcs[npc.ntype] || {};
+ if (
+ def &&
+ instances[npc.in] &&
+ instances[npc.in].players &&
+ def.aura &&
+ (!npc.last_aura || mssince(npc.last_aura) > 2000)
+ ) {
+ npc.last_aura = new Date();
+ for (var pid in instances[npc.in].players) {
+ var player = instances[npc.in].players[pid];
// console.log(player);
- if(!player.npc && distance(player,npc)<320)
- {
- player.s[npc.ntype+"aura"]={"ms":6000,"name":"Citizen's Aura","skin":"citizens","citizens":true};
- for(var p in def.aura) player.s[npc.ntype+"aura"][p]=def.aura[p];
- resend(player,"u+cid");
+ if (!player.npc && distance(player, npc) < 320) {
+ player.s[npc.ntype + "aura"] = { ms: 6000, name: "Citizen's Aura", skin: "citizens", citizens: true };
+ for (var p in def.aura) {
+ player.s[npc.ntype + "aura"][p] = def.aura[p];
+ }
+ resend(player, "u+cid");
}
}
-
}
- if(def.attack && ssince(npc.last.attack)>1.5)
- {
- for(var id in instances[npc.in].monsters)
- {
- var monster=instances[npc.in].monsters[id];
- if(distance(npc,monster)5000
- {
- npc.last.attack=new Date();
- commence_attack(npc,monster,"attack");
+ if (def.attack && ssince(npc.last.attack) > 1.5) {
+ for (var id in instances[npc.in].monsters) {
+ var monster = instances[npc.in].monsters[id];
+ if (distance(npc, monster) < npc.range) {
+ // && monster.hp>5000
+ npc.last.attack = new Date();
+ commence_attack(npc, monster, "attack");
break;
}
}
}
- if(def.seek)
- {
- var target=npc.focus && get_player(npc.focus);
- if(target && def.transport && target.map!=npc.map && target.in==target.map)
- {
- var spot=safe_xy_nearby(target.map,target.x-8,target.y-6);
- if(spot)
- transport_player_to(npc,get_player(npc.focus).map,[spot.x,spot.y]);
+ if (def.seek) {
+ var target = npc.focus && get_player(npc.focus);
+ if (target && def.transport && target.map != npc.map && target.in == target.map) {
+ var spot = safe_xy_nearby(target.map, target.x - 8, target.y - 6);
+ if (spot) {
+ transport_player_to(npc, get_player(npc.focus).map, [spot.x, spot.y]);
+ }
}
- var target=null,old_focus=npc.focus,min_val=99999,max_val=-99999;
+ var target = null;
+ var old_focus = npc.focus;
+ var min_val = 99999;
+ var max_val = -99999;
- for(var pid in instances[npc.in].players)
- {
- var player=instances[npc.in].players[pid];
- if(def.seek=="low_hp" && player.hpmax_val)
- max_val=player.cuteness,target=player;
- if(def.seek=="thrill" && player.thrilling && player.thrilling>now_date && (!target || player.thrilling>target.thrilling))
- target=player;
- if(def.seek=="gold" && player.gold>1000000000*(!is_pvp&&10||1) && player.gold>max_val)
- max_val=player.gold,target=player;
- if(player.type=="merchant") continue;
- if(def.seek=="dragondagger" && player.slots.mainhand && player.slots.mainhand.name=="dragondagger" && player.level max_val) {
+ max_val = player.cuteness;
+ target = player;
+ }
+ if (
+ def.seek == "thrill" &&
+ player.thrilling &&
+ player.thrilling > now_date &&
+ (!target || player.thrilling > target.thrilling)
+ ) {
+ target = player;
+ }
+ if (def.seek == "gold" && player.gold > 1000000000 * ((!is_pvp && 10) || 1) && player.gold > max_val) {
+ max_val = player.gold;
+ target = player;
+ }
+ if (player.type == "merchant") {
+ continue;
+ }
+ if (
+ def.seek == "dragondagger" &&
+ player.slots.mainhand &&
+ player.slots.mainhand.name == "dragondagger" &&
+ player.level < min_val
+ ) {
+ min_val = player.level;
+ target = player;
+ }
}
- npc.focus=target&&target.name;
- if(old_focus!=npc.focus)
- npc.u=true,npc.cid++;
+ npc.focus = target && target.name;
+ if (old_focus != npc.focus) {
+ npc.u = true;
+ npc.cid++;
+ }
}
- if(!npc.movable) continue;
- var moves=[[1,0],[0,1],[-1,0],[0,-1],[0.8,0.8],[-0.8,-0.8],[0.8,-0.8],[-0.8,0.8]],multiplier=npc.steps; shuffle(moves);
- if(def.aura && G.maps[npc.map].ref.transporter && distance(npc,G.maps[npc.map].ref.transporter)<2000) delay=-2400,multiplier*=4;
- else if(def.aura) delay*=3;
- if(!npc.citizen || npc.moving || npc.last.move>future_ms(delay) || instances[npc.in].paused) continue;
- if(Math.random()<0.3) multiplier*=2;
- else if(Math.random()<0.3) multiplier*=4;
+ if (!npc.movable) {
+ continue;
+ }
+ var moves = [
+ [1, 0],
+ [0, 1],
+ [-1, 0],
+ [0, -1],
+ [0.8, 0.8],
+ [-0.8, -0.8],
+ [0.8, -0.8],
+ [-0.8, 0.8],
+ ];
+ var multiplier = npc.steps;
+ shuffle(moves);
+ if (def.aura && G.maps[npc.map].ref.transporter && distance(npc, G.maps[npc.map].ref.transporter) < 2000) {
+ delay = -2400;
+ multiplier *= 4;
+ } else if (def.aura) {
+ delay *= 3;
+ }
+ if (!npc.citizen || npc.moving || npc.last.move > future_ms(delay) || instances[npc.in].paused) {
+ continue;
+ }
+ if (Math.random() < 0.3) {
+ multiplier *= 2;
+ } else if (Math.random() < 0.3) {
+ multiplier *= 4;
+ }
- if(def.heal)
- {
- for(var id in instances[npc.in].players)
- {
- var player=instances[npc.in].players[id];
- if(distance(player,npc)<320 && player.hpnpc.boundary[2] || npc.going_ynpc.boundary[3]));
- else if(can_move(npc))
- {
- npc.u=true;
+ if (
+ npc.boundary &&
+ (npc.going_x < npc.boundary[0] ||
+ npc.going_x > npc.boundary[2] ||
+ npc.going_y < npc.boundary[1] ||
+ npc.going_y > npc.boundary[3])
+ ) {
+ } else if (can_move(npc)) {
+ npc.u = true;
start_moving_element(npc);
// server_log("Moving to "+npc.going_x+","+npc.going_y);
- }
- else
- {
- npc.going_x=npc.x; npc.going_y=npc.y;
- npc.last.move=new Date();
+ } else {
+ npc.going_x = npc.x;
+ npc.going_y = npc.y;
+ npc.last.move = new Date();
}
}
- ms_since=mssince(now_date);
- }catch(e){log_trace("#X NPC loop error",e);};
- setTimeout(npc_loop,max(28,min(1000,ms_since*2+2))); // originally 24
+ ms_since = mssince(now_date);
+ } catch (e) {
+ log_trace("#X NPC loop error", e);
+ }
+ setTimeout(npc_loop, max(28, min(1000, ms_since * 2 + 2))); // originally 24
}
-function game_loop() // back in the day pretty much everything was in here [11/08/22]
-{
- if(!server.live) return setTimeout(game_loop,10);
- var ms_since=32;
- try{
- var now_date=new Date();
+function game_loop() {
+ // back in the day pretty much everything was in here [11/08/22]
+ if (!server.live) {
+ return setTimeout(game_loop, 10);
+ }
+ var ms_since = 32;
+ try {
+ var now_date = new Date();
// for(name in instances)
// {
// var instance=instances[name];
// if(mssince(instance.last_update)>75) update_instance(instance);
// }
- for(var id in server.s)
- {
- server.s[id].ms-=10;
- if(server.s[id].ms<0) delete server.s[id];
+ for (var id in server.s) {
+ server.s[id].ms -= 10;
+ if (server.s[id].ms < 0) {
+ delete server.s[id];
+ }
}
- ms_since=mssince(now_date);
- if(ms_since>B.game_loop_log_edge) server_log("Main loop took "+mssince(now_date)+"ms",1);
- perfc.game_loop[ms_since]=(perfc.game_loop[ms_since]||0)+1;
- perfc.game_loops+=1;
- }catch(e){log_trace("#X Main loop error",e);};
- setTimeout(game_loop,max(28,min(1000,ms_since*2+2))); // originally 24
+ ms_since = mssince(now_date);
+ if (ms_since > B.game_loop_log_edge) {
+ server_log("Main loop took " + mssince(now_date) + "ms", 1);
+ }
+ perfc.game_loop[ms_since] = (perfc.game_loop[ms_since] || 0) + 1;
+ perfc.game_loops += 1;
+ } catch (e) {
+ log_trace("#X Main loop error", e);
+ }
+ setTimeout(game_loop, max(28, min(1000, ms_since * 2 + 2))); // originally 24
}
-var lrid=0;
-function aura_loop()
-{
- try{
+var lrid = 0;
+function aura_loop() {
+ try {
lrid++;
- for(var id in players)
- {
- var player=players[id];
- if(!player || !player.aura || (player.rid%5)!=(lrid%5)) continue;
- for(var aid in player.aura)
- {
- for(var pid in instances[player.in].players)
- {
- if(!is_same(instances[player.in].players[pid],player,3)) continue;
- if(distance(instances[player.in].players[pid],player)>200) continue;
- instances[player.in].players[pid].s[aid]={ms:G.conditions[aid].duration||30000,f:player.name};
- if(G.conditions[aid].attr0)
- instances[player.in].players[pid].s[aid][G.conditions[aid].attr0]=player.aura[aid].attr0;
- resend(instances[player.in].players[pid],"u+cid");
+ for (var id in players) {
+ var player = players[id];
+ if (!player || !player.aura || player.rid % 5 != lrid % 5) {
+ continue;
+ }
+ for (var aid in player.aura) {
+ for (var pid in instances[player.in].players) {
+ if (!is_same(instances[player.in].players[pid], player, 3)) {
+ continue;
+ }
+ if (distance(instances[player.in].players[pid], player) > 200) {
+ continue;
+ }
+ instances[player.in].players[pid].s[aid] = { ms: G.conditions[aid].duration || 30000, f: player.name };
+ if (G.conditions[aid].attr0) {
+ instances[player.in].players[pid].s[aid][G.conditions[aid].attr0] = player.aura[aid].attr0;
+ }
+ resend(instances[player.in].players[pid], "u+cid");
}
}
}
- }catch(e){log_trace("#X aura loop error",e);};
- setTimeout(aura_loop,1000);
+ } catch (e) {
+ log_trace("#X aura loop error", e);
+ }
+ setTimeout(aura_loop, 1000);
}
-setTimeout(game_loop,10);
-setTimeout(npc_loop,10);
-setTimeout(instance_loop,10);
-setTimeout(aura_loop,10);
-setInterval(count_unique_users,6000);
+setTimeout(game_loop, 10);
+setTimeout(npc_loop, 10);
+setTimeout(instance_loop, 10);
+setTimeout(aura_loop, 10);
+setInterval(count_unique_users, 6000);
-setInterval(function(){
- try{
- for(var id in observers)
- {
- var observer=observers[id];
- if(observer.player && get_player(observer.player.name))
- {
- var player=get_player(observer.player.name);
- if(simple_distance(observer,player)>200)
- transport_observer_to(observer,player.in,player.map,player.x,player.y+(observer.socket.desktop&&120||0));
- }
- else
- {
- if(simple_distance(observer,{map:observer_map,in:observer_map,x:observer_x,y:observer_y})>200)
- transport_observer_to(observer,observer_map,observer_map,observer_x,observer_y+(observer.socket.desktop&&120||0));
+setInterval(function () {
+ try {
+ for (var id in observers) {
+ var observer = observers[id];
+ if (observer.player && get_player(observer.player.name)) {
+ var player = get_player(observer.player.name);
+ if (simple_distance(observer, player) > 200) {
+ transport_observer_to(
+ observer,
+ player.in,
+ player.map,
+ player.x,
+ player.y + ((observer.socket.desktop && 120) || 0),
+ );
+ }
+ } else {
+ if (simple_distance(observer, { map: observer_map, in: observer_map, x: observer_x, y: observer_y }) > 200) {
+ transport_observer_to(
+ observer,
+ observer_map,
+ observer_map,
+ observer_x,
+ observer_y + ((observer.socket.desktop && 120) || 0),
+ );
+ }
}
}
- }catch(e){log_trace("#X observer loop2 error",e);};
-},13200);
+ } catch (e) {
+ log_trace("#X observer loop2 error", e);
+ }
+}, 13200);
-setInterval(function(){
- try{
- if(is_pvp) return;
- var names=[],player;
- total_merchants=0;
- for(var id in players)
- {
- player=players[id];
- if(!player.npc && player.last.attack && player.map==player.in && ssince(player.last.attack)<3 && !G.maps[player.map].pvp)
- {
+setInterval(function () {
+ try {
+ if (is_pvp) {
+ return;
+ }
+ var names = [];
+ var player;
+ total_merchants = 0;
+ for (var id in players) {
+ player = players[id];
+ if (
+ !player.npc &&
+ player.last.attack &&
+ player.map == player.in &&
+ ssince(player.last.attack) < 3 &&
+ !G.maps[player.map].pvp
+ ) {
names.push(player.name);
}
- if(player.p && player.p.stand) total_merchants+=1;
- }
- if(names.length)
- {
- player=get_player(names[floor(Math.random()*names.length)]);
- observer_map=player.map;
- observer_x=parseInt(player.x);
- observer_y=parseInt(player.y);
- server_log("Set the observer location: "+[observer_map,observer_x,observer_y]);
- }
- else
- {
- observer_map=merchant_map;
- observer_x=merchant_x;
- observer_y=merchant_y;
- }
-
- }catch(e){log_trace("#X observer loop error",e);};
-},4000);
-
-setTimeout(function(){
- setInterval(function(){
- for(var id in players)
- {
- var player=players[id];
- if(player.type=="merchant" && player.p.stand)
- {
- var xp=1000;
- if(player.level<=40) xp=G.levels[player.level]/100;
- else if(player.level<=60) xp=G.levels[player.level]/200;
- else if(player.level<=70) xp=G.levels[player.level]/400;
- else xp=G.levels[70]/400;
- xp=parseInt(Math.round(xp));
- player.xp+=xp;
- player.socket.emit("game_log","Gained "+to_pretty_num(xp)+" marketing XP");
- player.socket.emit("disappearing_text",{"message":"+"+xp,"x":player.x,"y":player.y-32,"args":{color:"gray","size":"large"}});
- resend(player,"reopen+u+cid");
+ if (player.p && player.p.stand) {
+ total_merchants += 1;
}
}
- },3*60*60*1000); //3
-},1*60*60*1000); //1
+ if (names.length) {
+ player = get_player(names[floor(Math.random() * names.length)]);
+ observer_map = player.map;
+ observer_x = parseInt(player.x);
+ observer_y = parseInt(player.y);
+ server_log("Set the observer location: " + [observer_map, observer_x, observer_y]);
+ } else {
+ observer_map = merchant_map;
+ observer_x = merchant_x;
+ observer_y = merchant_y;
+ }
+ } catch (e) {
+ log_trace("#X observer loop error", e);
+ }
+}, 4000);
-setInterval(function(){
- try{
- var edge=future_s(-120);
- for(var id in players)
- {
- if(0 && players[id].last_ipass50)
+setTimeout(function () {
+ setInterval(function () {
+ try {
+ for (var id in instances) {
+ var instance = instances[id];
+ if (
+ B.pause_instances &&
+ !instance.paused &&
+ !instance.operators &&
+ Object.keys(instance.players).length <= instance.npcs &&
+ !Object.keys(instance.observers).length &&
+ ssince(instance.last_player) > 50
+ ) {
pause_instance(instance);
- if(Object.keys(instance.players).length>instance.npcs || Object.keys(instance.observers).length)
- instance.last_player=new Date();
+ }
+ if (Object.keys(instance.players).length > instance.npcs || Object.keys(instance.observers).length) {
+ instance.last_player = new Date();
+ }
}
- }catch(e){log_trace("#X pause loop error",e);};
- },2000);
-},60000); // delay for a minute, so citizens move around
+ } catch (e) {
+ log_trace("#X pause loop error", e);
+ }
+ }, 2000);
+}, 60000); // delay for a minute, so citizens move around
-setInterval(function(){
- try{
- for(var oname in parties)
- {
+setInterval(function () {
+ try {
+ for (var oname in parties) {
send_party_update(oname);
}
- }catch(e){log_trace("#X party loop error",e);};
-},60000);
+ } catch (e) {
+ log_trace("#X party loop error", e);
+ }
+}, 60000);
-setInterval(function(){
- try{
- for(var id in players)
- {
- var player=players[id];
- players[id].pdps*=0.8;
+setInterval(function () {
+ try {
+ for (var id in players) {
+ var player = players[id];
+ players[id].pdps *= 0.8;
player.p.minutes++;
- trade_slots.forEach(function(slot){
- if(player.slots[slot] && player.slots[slot].giveaway)
- {
+ trade_slots.forEach(function (slot) {
+ if (player.slots[slot] && player.slots[slot].giveaway) {
player.slots[slot].giveaway--;
- if(!player.slots[slot].giveaway)
- {
- var list=[];
- player.slots[slot].list.forEach(function(p){
- var p=get_player(p);
- if(p && p.esize) list.push(p);
- else if(!mode.prevent_external) list.push({name:p});
- });
- if(!list.length) player.slots[slot].giveaway=5;
- else
- {
- if(!mode.prevent_external)
- {
-
- var winner=random_one(list);
- var item=player.slots[slot];
- player.slots[slot]=null;
- delete item.list; delete item.giveaway; delete item.registry;
- item.gf=player.name; item.src="gva";
- var mitem=JSON.stringify(item);
- add_to_trade_history(player,"giveaway",winner.name,cache_item(item,true));
- xy_emit(player,"game_log",{message:winner.name+" won "+player.name+"'s giveaway of "+G.items[item.name].name+"!",color:"#42A0DC",confetti:winner.name});
- appengine_call("send_mail",{fro:player.name,to:winner.name,subject:"You've won a giveaway!",message:"Congratulations, you won "+player.name+"'s giveaway. Participants were: "+list.join(", "),rid:randomStr(50),retries:5,item:mitem},function(result){
-
- },function(){
- console.log("#M unsent giveaway, lost item: "+mitem);
- });
+ if (!player.slots[slot].giveaway) {
+ var list = [];
+ player.slots[slot].list.forEach(function (p) {
+ var p = get_player(p);
+ if (p && p.esize) {
+ list.push(p);
+ } else if (!mode.prevent_external) {
+ list.push({ name: p });
}
- else
- {
- var winner=random_one(list);
- var item=player.slots[slot];
- player.slots[slot]=null;
- delete item.list; delete item.giveaway; delete item.registry;
- item.gf=player.name; item.src="gva";
- add_item(winner,item);
- add_to_trade_history(player,"giveaway",winner.name,cache_item(item,true));
- xy_emit(player,"game_log",{message:winner.name+" won "+player.name+"'s giveaway of "+G.items[item.name].name+"!",color:"#42A0DC",confetti:winner.name});
- resend(winner,"reopen");
+ });
+ if (!list.length) {
+ player.slots[slot].giveaway = 5;
+ } else {
+ if (!mode.prevent_external) {
+ var winner = random_one(list);
+ var item = player.slots[slot];
+ player.slots[slot] = null;
+ delete item.list;
+ delete item.giveaway;
+ delete item.registry;
+ item.gf = player.name;
+ item.src = "gva";
+ var mitem = JSON.stringify(item);
+ add_to_trade_history(player, "giveaway", winner.name, cache_item(item, true));
+ xy_emit(player, "game_log", {
+ message: winner.name + " won " + player.name + "'s giveaway of " + G.items[item.name].name + "!",
+ color: "#42A0DC",
+ confetti: winner.name,
+ });
+ appengine_call(
+ "send_mail",
+ {
+ fro: player.name,
+ to: winner.name,
+ subject: "You've won a giveaway!",
+ message:
+ "Congratulations, you won " + player.name + "'s giveaway. Participants were: " + list.join(", "),
+ rid: randomStr(50),
+ retries: 5,
+ item: mitem,
+ },
+ function (result) {},
+ function () {
+ console.log("#M unsent giveaway, lost item: " + mitem);
+ },
+ );
+ } else {
+ var winner = random_one(list);
+ var item = player.slots[slot];
+ player.slots[slot] = null;
+ delete item.list;
+ delete item.giveaway;
+ delete item.registry;
+ item.gf = player.name;
+ item.src = "gva";
+ add_item(winner, item);
+ add_to_trade_history(player, "giveaway", winner.name, cache_item(item, true));
+ xy_emit(player, "game_log", {
+ message: winner.name + " won " + player.name + "'s giveaway of " + G.items[item.name].name + "!",
+ color: "#42A0DC",
+ confetti: winner.name,
+ });
+ resend(winner, "reopen");
}
}
-
}
- player.cslots[slot]=cache_item(player.slots[slot],true);
- resend(player,"u+cid"+(!player.slots[slot]&&"+reopen"||""));
+ player.cslots[slot] = cache_item(player.slots[slot], true);
+ resend(player, "u+cid" + ((!player.slots[slot] && "+reopen") || ""));
}
});
}
- }catch(e){log_trace("#X decay loop error",e);};
-},60000);
+ } catch (e) {
+ log_trace("#X decay loop error", e);
+ }
+}, 60000);
-
-var a_score={}; // announcement score
-setInterval(function(){
- try{
- for(var id in a_score)
- {
- a_score[id]*=0.99;
+var a_score = {}; // announcement score
+setInterval(function () {
+ try {
+ for (var id in a_score) {
+ a_score[id] *= 0.99;
}
- }catch(e){log_trace("#X ascore loop error",e);};
-},10000);
+ } catch (e) {
+ log_trace("#X ascore loop error", e);
+ }
+}, 10000);
-setInterval(function(){
- try{
- for(var id in players)
- {
- var player=players[id];
- player.xrange=min(25,player.xrange+5);
+setInterval(function () {
+ try {
+ for (var id in players) {
+ var player = players[id];
+ player.xrange = min(25, player.xrange + 5);
}
- }catch(e){log_trace("#X xrange loop error",e);};
-},1000);
+ } catch (e) {
+ log_trace("#X xrange loop error", e);
+ }
+}, 1000);
-setInterval(function(){
- try{
- var c=new Date();
- for(var id in players)
- {
- var player=players[id];
- if(player.auth_id && player.p.first===undefined && !player.first_u_call)
- {
- function first_call(player)
- {
- player.first_u_call=appengine_call("is_first",{auth:player.auth,auth_id:player.auth_id,character:player.real_id,suffix:"/"+player.id},function(result){
- if(result.first) player.p.first=true;
- else player.p.first=false;
- },function(){
- delete player.first_u_call;
- });
+setInterval(function () {
+ try {
+ var c = new Date();
+ for (var id in players) {
+ var player = players[id];
+ if (player.auth_id && player.p.first === undefined && !player.first_u_call) {
+ function first_call(player) {
+ player.first_u_call = appengine_call(
+ "is_first",
+ { auth: player.auth, auth_id: player.auth_id, character: player.real_id, suffix: "/" + player.id },
+ function (result) {
+ if (result.first) {
+ player.p.first = true;
+ } else {
+ player.p.first = false;
+ }
+ },
+ function () {
+ delete player.first_u_call;
+ },
+ );
}
first_call(player);
}
- if(player.p.first && !player.p.dt.first)
- {
- realm_broadcast("server_message",{message:player.name+" joined Adventure Land!",color:"#24A2FA"});
- player.p.dt.first=future_h(24*7);
- }
- else if(player.p.dt.first && player.p.dt.first>c)
- {
- player.paura=player.paura||{};
- player.paura["newcomersblessing"]={attr0:0,attr1:0};
+ if (player.p.first && !player.p.dt.first) {
+ realm_broadcast("server_message", { message: player.name + " joined Adventure Land!", color: "#24A2FA" });
+ player.p.dt.first = future_h(24 * 7);
+ } else if (player.p.dt.first && player.p.dt.first > c) {
+ player.paura = player.paura || {};
+ player.paura["newcomersblessing"] = { attr0: 0, attr1: 0 };
}
}
- }catch(e){log_trace("#X first_character loop error",e);};
-},4000);
+ } catch (e) {
+ log_trace("#X first_character loop error", e);
+ }
+}, 4000);
-function projectiles_loop()
-{
- var now=new Date();
- for(var id in projectiles)
- {
- try{
- if(projectiles[id].eta<=now)
- {
- var projectile=projectiles[id];
+function projectiles_loop() {
+ var now = new Date();
+ for (var id in projectiles) {
+ try {
+ if (projectiles[id].eta <= now) {
+ var projectile = projectiles[id];
delete projectiles[id];
- complete_attack(projectile.attacker,projectile.target,projectile);
+ complete_attack(projectile.attacker, projectile.target, projectile);
}
- }catch(e){log_trace("#X projectile loop error",e);};
+ } catch (e) {
+ log_trace("#X projectile loop error", e);
+ }
}
}
-setInterval(projectiles_loop,7);
+setInterval(projectiles_loop, 7);
-var accel=1;
-if(mode.fast_mlevels) accel=100;
-setInterval(function(){
- try{
- for(var id in instances)
- {
- for(var mid in (instances[id].monsters||[]))
- {
- var monster=instances[id].monsters[mid];
- if(G.monsters[monster.type].cute || G.monsters[monster.type].peaceful || G.monsters[monster.type].stationary || monster.target) continue;
- var exp=Math.pow(2,(monster.level-1)*0.3),mult=1;
- if(monster["1hp"]) mult=200;
- else if(G.monsters[monster.type].special) mult=20;
- if(mssince(monster.last_level)>max(180000*exp*mult/accel,monster.max_hp*mult*30*exp/accel))
- {
- if(monster.temp) remove_monster(monster);
- else level_monster(monster);
+var accel = 1;
+if (mode.fast_mlevels) {
+ accel = 100;
+}
+setInterval(function () {
+ try {
+ for (var id in instances) {
+ for (var mid in instances[id].monsters || []) {
+ var monster = instances[id].monsters[mid];
+ if (
+ G.monsters[monster.type].cute ||
+ G.monsters[monster.type].peaceful ||
+ G.monsters[monster.type].stationary ||
+ monster.target
+ ) {
+ continue;
+ }
+ var exp = Math.pow(2, (monster.level - 1) * 0.3);
+ var mult = 1;
+ if (monster["1hp"]) {
+ mult = 200;
+ } else if (G.monsters[monster.type].special) {
+ mult = 20;
+ }
+ if (
+ mssince(monster.last_level) > max((180000 * exp * mult) / accel, (monster.max_hp * mult * 30 * exp) / accel)
+ ) {
+ if (monster.temp) {
+ remove_monster(monster);
+ } else {
+ level_monster(monster);
+ }
}
}
}
- }catch(e){log_trace("#X mlevel loop error",e);};
-},16000/accel);
+ } catch (e) {
+ log_trace("#X mlevel loop error", e);
+ }
+}, 16000 / accel);
-setInterval(function(){
- try{
- for(var id in instances)
- {
- for(var mid in (instances[id].monsters||[]))
- {
- var monster=instances[id].monsters[mid];
- if(G.monsters[monster.type].cute || G.monsters[monster.type].stationary || !monster.target) continue;
- var target=get_player(monster.target);
- if(!target || (target.targets>1 && monster.hp 1 && monster.hp < monster.max_hp * 0.23)) {
+ continue;
+ }
+ monster.extra_gold =
+ (monster.extra_gold || 0) +
+ ((min(min(2400, target.attack) / 220.0 + monster.attack / 1.2, 55) + 19) *
+ ((gameplay == "hardcore" && 100) || 1)) /
+ (max((target.targets - 1) * (target.targets - 1), 1) || 1);
}
}
- }catch(e){log_trace("#X mgold loop error",e);};
-},2000);
+ } catch (e) {
+ log_trace("#X mgold loop error", e);
+ }
+}, 2000);
-setInterval(function(){
- try{
- for(var id in players)
- {
- var player=players[id];
- if(Math.random()<1.0/(6*15)) // once every 15 hours
- {
- var slots=[];
- character_slots.forEach(function(slot){
- if(player.slots[slot] && (G.items[player.slots[slot].name].upgrade || G.items[player.slots[slot].name].compound))
+setInterval(function () {
+ try {
+ for (var id in players) {
+ var player = players[id];
+ if (Math.random() < 1.0 / (6 * 15)) {
+ // once every 15 hours
+ var slots = [];
+ character_slots.forEach(function (slot) {
+ if (
+ player.slots[slot] &&
+ (G.items[player.slots[slot].name].upgrade || G.items[player.slots[slot].name].compound)
+ ) {
slots.push(slot);
+ }
});
- if(!slots.length) continue;
- var slot=random_one(slots);
- player.slots[slot].grace=(player.slots[slot].grace||0)+0.4;
- console.log("random grace "+player.name+" "+slot+" "+player.slots[slot].grace);
+ if (!slots.length) {
+ continue;
+ }
+ var slot = random_one(slots);
+ player.slots[slot].grace = (player.slots[slot].grace || 0) + 0.4;
+ console.log("random grace " + player.name + " " + slot + " " + player.slots[slot].grace);
}
- if(player.computer && Math.random()<1.0/(6*1)) // once every hour
- {
- for(var s in player.slots)
- {
- if(player.slots[s] && G.items[player.slots[s].name].charge)
- {
- if(player.slots[s].charges>G.items[player.slots[s].name].charge && Math.random()<0.96) continue;
- player.slots[s].charges=(player.slots[s].charges||0)+1;
- player.cslots[s]=cache_item(player.slots[s]);
+ if (player.computer && Math.random() < 1.0 / (6 * 1)) {
+ // once every hour
+ for (var s in player.slots) {
+ if (player.slots[s] && G.items[player.slots[s].name].charge) {
+ if (player.slots[s].charges > G.items[player.slots[s].name].charge && Math.random() < 0.96) {
+ continue;
+ }
+ player.slots[s].charges = (player.slots[s].charges || 0) + 1;
+ player.cslots[s] = cache_item(player.slots[s]);
}
}
- for(var i=0;iG.items[player.items[i].name].charge && Math.random()<0.96) continue;
- player.items[i].charges=(player.items[i].charges||0)+1;
- player.citems[i]=cache_item(player.items[i]);
+ for (var i = 0; i < player.items.length; i++) {
+ if (player.items[i] && G.items[player.items[i].name].charge) {
+ if (player.items[i].charges > G.items[player.items[i].name].charge && Math.random() < 0.96) {
+ continue;
+ }
+ player.items[i].charges = (player.items[i].charges || 0) + 1;
+ player.citems[i] = cache_item(player.items[i]);
}
}
}
}
- }catch(e){log_trace("#X random grace loop error",e);};
-},10*60000); // every 10 minutes
+ } catch (e) {
+ log_trace("#X random grace loop error", e);
+ }
+}, 10 * 60000); // every 10 minutes
-setInterval(function(){
- try{
- server_loot();
- }catch(e){log_trace("#X server loot error",e);};
-},4*60*60*1000);
-
-setInterval(function(){
- try{
- if(server.live) broadcast_e();
- }catch(e){log_trace("#X broadcast error",e);};
-},24*1000);
-
-function sync_loop()
-{
- function check_for_delays(player)
- {
- var limit=6;
- if(player.mounting && msince(player.mounting)>limit && !player.mount_issue)
- {
- server_log("#X SEVERE: "+limit+" minutes and still mounting: "+player.name,1);
- player.mount_issue=new Date();
+setInterval(
+ function () {
+ try {
+ server_loot();
+ } catch (e) {
+ log_trace("#X server loot error", e);
}
- if(player.unmounting && msince(player.unmounting)>limit && !player.unmount_issue)
- {
- server_log("#X SEVERE: "+limit+" minutes and still unmounting: "+player.name,1);
- player.unmount_issue=new Date();
+ },
+ 4 * 60 * 60 * 1000,
+);
+
+setInterval(function () {
+ try {
+ if (server.live) {
+ broadcast_e();
}
- if(player.sync_call && msince(player.last_sync)>limit && !player.sync_issue)
- {
- server_log("#X SEVERE: "+limit+" minutes and still syncing: "+player.name,1);
+ } catch (e) {
+ log_trace("#X broadcast error", e);
+ }
+}, 24 * 1000);
+
+function sync_loop() {
+ function check_for_delays(player) {
+ var limit = 6;
+ if (player.mounting && msince(player.mounting) > limit && !player.mount_issue) {
+ server_log("#X SEVERE: " + limit + " minutes and still mounting: " + player.name, 1);
+ player.mount_issue = new Date();
+ }
+ if (player.unmounting && msince(player.unmounting) > limit && !player.unmount_issue) {
+ server_log("#X SEVERE: " + limit + " minutes and still unmounting: " + player.name, 1);
+ player.unmount_issue = new Date();
+ }
+ if (player.sync_call && msince(player.last_sync) > limit && !player.sync_issue) {
+ server_log("#X SEVERE: " + limit + " minutes and still syncing: " + player.name, 1);
// player.sync_issue=new Date();
delete player.sync_call;
}
- if(player.stopping && msince(player.stopping)>limit && !player.stop_issue)
- {
- server_log("#X SEVERE: "+limit+" minutes and still stopping: "+player.name,1);
- player.stop_issue=new Date();
+ if (player.stopping && msince(player.stopping) > limit && !player.stop_issue) {
+ server_log("#X SEVERE: " + limit + " minutes and still stopping: " + player.name, 1);
+ player.stop_issue = new Date();
}
}
- function mount_call(player)
- {
+ function mount_call(player) {
// player.last_sync=new Date(); - sync doesn't happen at mount - maybe it should [16/08/17]
- player.mount_call=appengine_call("mount_user",{auth:player.auth,character:player.real_id,suffix:"/"+player.id,to:player.mount_to},function(result){
- server_log("mount_user: "+player.name+" owner: "+player.owner,1);
- delete player.mounting;
- delete player.mount_call;
- if(result.failed)
- {
- server_log("mount_user[failed]: "+player.name+" in-bank: "+result.name+" result: "+JSON.stringify(result),1);
- player.socket.emit("game_response",{response:"bank_opx",name:result.name,reason:result.reason});
- return;
- }
- player.user=result.user;
- init_bank(player);
- if(players[player.socket.id])
- {
- transport_player_to(player,player.mount_to,player.mount_s);
- resend(player);
- }
- },function(){
- delete player.mounting;
- delete player.mount_call;
- server_log("#X SEVERE-ish: Mount failed for "+player.name,1);
- });
+ player.mount_call = appengine_call(
+ "mount_user",
+ { auth: player.auth, character: player.real_id, suffix: "/" + player.id, to: player.mount_to },
+ function (result) {
+ server_log("mount_user: " + player.name + " owner: " + player.owner, 1);
+ delete player.mounting;
+ delete player.mount_call;
+ if (result.failed) {
+ server_log(
+ "mount_user[failed]: " + player.name + " in-bank: " + result.name + " result: " + JSON.stringify(result),
+ 1,
+ );
+ player.socket.emit("game_response", { response: "bank_opx", name: result.name, reason: result.reason });
+ return;
+ }
+ player.user = result.user;
+ init_bank(player);
+ if (players[player.socket.id]) {
+ transport_player_to(player, player.mount_to, player.mount_s);
+ resend(player);
+ }
+ },
+ function () {
+ delete player.mounting;
+ delete player.mount_call;
+ server_log("#X SEVERE-ish: Mount failed for " + player.name, 1);
+ },
+ );
}
- function unmount_call(player)
- {
- player.last_sync=new Date();
+ function unmount_call(player) {
+ player.last_sync = new Date();
init_bank_exit(player);
- player.unmount_call=appengine_call("sync_character",{auth:player.auth,character:player.real_id,data:player_to_server(player,"sync"),user_data:player.user||"",retries:100,unmount:1,suffix:"/"+player.name+"/unmount"
- },function(result){
- server_log("unmount_user[sync]: "+player.name+" owner: "+player.owner+" result: "+JSON.stringify(result),1);
- delete player.unmount_call;
- if(result.failed) { server_log("unmount_user[failed]: "+player.name+" owner: "+player.owner,1); return; }
- delete player.unmounting;
- player.user=null; player.cuser=null;
- if(players[player.socket.id] && player.unmount_to)
+ player.unmount_call = appengine_call(
+ "sync_character",
{
- transport_player_to(player,player.unmount_to,player.unmount_s);
- }
- if(players[player.socket.id]) resend(player);
- },function(){
- server_log("#X SEVERE: Unmount failed for "+player.name,1);
- delete player.unmounting;
- delete player.unmount_call;
- if(players[player.socket.id]) players[socket.id].socket.disconnect();
- });
+ auth: player.auth,
+ character: player.real_id,
+ data: player_to_server(player, "sync"),
+ user_data: player.user || "",
+ retries: 100,
+ unmount: 1,
+ suffix: "/" + player.name + "/unmount",
+ },
+ function (result) {
+ server_log(
+ "unmount_user[sync]: " + player.name + " owner: " + player.owner + " result: " + JSON.stringify(result),
+ 1,
+ );
+ delete player.unmount_call;
+ if (result.failed) {
+ server_log("unmount_user[failed]: " + player.name + " owner: " + player.owner, 1);
+ return;
+ }
+ delete player.unmounting;
+ player.user = null;
+ player.cuser = null;
+ if (players[player.socket.id] && player.unmount_to) {
+ transport_player_to(player, player.unmount_to, player.unmount_s);
+ }
+ if (players[player.socket.id]) {
+ resend(player);
+ }
+ },
+ function () {
+ server_log("#X SEVERE: Unmount failed for " + player.name, 1);
+ delete player.unmounting;
+ delete player.unmount_call;
+ if (players[player.socket.id]) {
+ players[socket.id].socket.disconnect();
+ }
+ },
+ );
}
- function sync_call(player)
- {
- player.last_sync=new Date();
- player.sync_call=appengine_call("sync_character",{auth:player.auth,character:player.real_id,data:player_to_server(player,"sync"),user_data:player.user||"",retries:0,suffix:"/"+player.name},
- function(result){
- if(result && result.reason=="notingame")
- {
- server_log("#X SEVERE: sync notingame disconnect for "+player.name,1);
- try{player.socket.disconnect();}catch(e){};
+ function sync_call(player) {
+ player.last_sync = new Date();
+ player.sync_call = appengine_call(
+ "sync_character",
+ {
+ auth: player.auth,
+ character: player.real_id,
+ data: player_to_server(player, "sync"),
+ user_data: player.user || "",
+ retries: 0,
+ suffix: "/" + player.name,
+ },
+ function (result) {
+ if (result && result.reason == "notingame") {
+ server_log("#X SEVERE: sync notingame disconnect for " + player.name, 1);
+ try {
+ player.socket.disconnect();
+ } catch (e) {}
}
delete player.sync_call;
},
- function(){delete player.sync_call});
+ function () {
+ delete player.sync_call;
+ },
+ );
}
- function stop_call(player)
- {
- var bank=false;
- if(player.user) bank=true;
- player.stopping=new Date();
+ function stop_call(player) {
+ var bank = false;
+ if (player.user) {
+ bank = true;
+ }
+ player.stopping = new Date();
init_player_exit(player);
- if(player.unmount_call) player.unmount_call.retries=0;
- player.stop_call=appengine_call("stop_character",{auth:player.auth,character:player.real_id,data:player_to_server(player),user_data:player.user||"",retries:CINF,suffix:"/"+player.name},function(result){
- server_log("stop_character: "+player.name+" owner: "+player.owner+" bank: "+bank+" result: "+JSON.stringify(result),1);
- if(result.done) delete dc_players[player.real_id];
- delete player.stop_call;
- },function(){
- server_log("#X SEVERE: stop_character failed for "+player.name,1);
- delete player.stop_call;
- });
+ if (player.unmount_call) {
+ player.unmount_call.retries = 0;
+ }
+ player.stop_call = appengine_call(
+ "stop_character",
+ {
+ auth: player.auth,
+ character: player.real_id,
+ data: player_to_server(player),
+ user_data: player.user || "",
+ retries: CINF,
+ suffix: "/" + player.name,
+ },
+ function (result) {
+ server_log(
+ "stop_character: " +
+ player.name +
+ " owner: " +
+ player.owner +
+ " bank: " +
+ bank +
+ " result: " +
+ JSON.stringify(result),
+ 1,
+ );
+ if (result.done) {
+ delete dc_players[player.real_id];
+ }
+ delete player.stop_call;
+ },
+ function () {
+ server_log("#X SEVERE: stop_character failed for " + player.name, 1);
+ delete player.stop_call;
+ },
+ );
}
- for(var id in players)
- {
- if(gameplay=="hardcore" || gameplay=="test") return;
- var player=players[id];
- try{
-
+ for (var id in players) {
+ if (gameplay == "hardcore" || gameplay == "test") {
+ return;
+ }
+ var player = players[id];
+ try {
check_for_delays(player);
- if(player.unmount_call || player.mount_call || player.sync_call || player.stop_call);
- else if(!server.live) player.socket.disconnect();
- else if(player.unmounting) unmount_call(player);
- else if(player.mounting) mount_call(player);
- else if(msince(player.last_sync)>5 && !player.unmounting && !player.mounting) sync_call(player);
-
- }catch(e){log_trace("#X dc loop error1",e);};
+ if (player.unmount_call || player.mount_call || player.sync_call || player.stop_call) {
+ } else if (!server.live) {
+ player.socket.disconnect();
+ } else if (player.unmounting) {
+ unmount_call(player);
+ } else if (player.mounting) {
+ mount_call(player);
+ } else if (msince(player.last_sync) > 5 && !player.unmounting && !player.mounting) {
+ sync_call(player);
+ }
+ } catch (e) {
+ log_trace("#X dc loop error1", e);
+ }
}
- for(var id in dc_players)
- {
- if(gameplay=="hardcore" || gameplay=="test") return;
- var player=dc_players[id];
- try{
-
+ for (var id in dc_players) {
+ if (gameplay == "hardcore" || gameplay == "test") {
+ return;
+ }
+ var player = dc_players[id];
+ try {
check_for_delays(player);
- if(player.unmount_call || player.mount_call || player.sync_call || player.stop_call);
- else if(!player.stop_call) stop_call(player);
-
- }catch(e){log_trace("#X dc loop error2",e);};
+ if (player.unmount_call || player.mount_call || player.sync_call || player.stop_call) {
+ } else if (!player.stop_call) {
+ stop_call(player);
+ }
+ } catch (e) {
+ log_trace("#X dc loop error2", e);
+ }
}
}
-function server_loop()
-{
+function server_loop() {
// #IMPORTANT: sometimes none of the success/error callbacks trigger [20/08/19]
- if(server.update_call && msince(server.update_call.init)>4)
+ if (server.update_call && msince(server.update_call.init) > 4) {
delete server.update_call;
- if(server.update_call || server.stop_call);
- else if(server.live && ssince(server.last_update)>75)
- {
- server.update_call=appengine_call("update_server",{
- keyword:variables.keyword,
- id:server_id,
- players:Object.keys(players).length,
- observers:Object.keys(observers).length,
- merchants:total_merchants,
- total_players:total_players,
- data:S,
- retries:3,
- },function(result){
- server.last_update=new Date();
+ }
+ if (server.update_call || server.stop_call) {
+ } else if (server.live && ssince(server.last_update) > 75) {
+ server.update_call = appengine_call(
+ "update_server",
+ {
+ keyword: variables.keyword,
+ id: server_id,
+ players: Object.keys(players).length,
+ observers: Object.keys(observers).length,
+ merchants: total_merchants,
+ total_players: total_players,
+ data: S,
+ retries: 3,
+ },
+ function (result) {
+ server.last_update = new Date();
server_log("Server update sent");
delete server.update_call;
- },function(){
- server_log("Server update failed",1);
+ },
+ function () {
+ server_log("Server update failed", 1);
delete server.update_call;
- });
+ },
+ );
+ } else if (server.started && !server.live && !server.stopped) {
+ server.stop_call = appengine_call(
+ "stop_server",
+ { keyword: variables.keyword, id: server_id, retries: CINF, data: S },
+ function (result) {
+ server_log("stop_server success", 1);
+ // these are here as shutting the server first disrupts connections in actual servers
+ // io.close(); app.close(); - decided to comment these out, they don't do anything now [23/09/16]
+ server.stopped = true;
+ delete server.stop_call;
+ },
+ );
+ } else if (
+ server.stopped &&
+ ((!Object.keys(dc_players).length && !Object.keys(players).length) || gameplay == "hardcore" || gameplay == "test")
+ ) {
+ process.exit();
+ } else if (server.stopped) {
+ sync_loop();
}
- else if(server.started && !server.live && !server.stopped)
- {
- server.stop_call=appengine_call("stop_server",{keyword:variables.keyword,id:server_id,retries:CINF,data:S},function(result){
- server_log("stop_server success",1);
- // these are here as shutting the server first disrupts connections in actual servers
- // io.close(); app.close(); - decided to comment these out, they don't do anything now [23/09/16]
- server.stopped=true;
- delete server.stop_call;
- });
- }
- else if(server.stopped && (!Object.keys(dc_players).length && !Object.keys(players).length || (gameplay=="hardcore" || gameplay=="test"))) process.exit();
- else if(server.stopped) sync_loop();
}
-setInterval(sync_loop,24000);
-setInterval(server_loop,1000);
+setInterval(sync_loop, 24000);
+setInterval(server_loop, 1000);
-function shutdown()
-{
- server_log("shutdown",1);
- server.live=false;
- if(!server.exists) server_loot("all");
+function shutdown() {
+ server_log("shutdown", 1);
+ server.live = false;
+ if (!server.exists) {
+ server_loot("all");
+ }
sync_loop();
}
-function shutdown_routine()
-{
- server_log("shutdown_routine",1);
- server.shutdown=true;
- for(var name in instances)
- {
- for(var id in instances[name].monsters)
- {
- var monster=instances[name].monsters[id];
- if(monster.target)
- {
- monster.u=true;
+function shutdown_routine() {
+ server_log("shutdown_routine", 1);
+ server.shutdown = true;
+ for (var name in instances) {
+ for (var id in instances[name].monsters) {
+ var monster = instances[name].monsters[id];
+ if (monster.target) {
+ monster.u = true;
monster.cid++;
- monster.mult=(monster.max_hp-monster.hp)/monster.max_hp;
- monster.hp=1;
+ monster.mult = (monster.max_hp - monster.hp) / monster.max_hp;
+ monster.hp = 1;
}
}
}
- var seconds=20;
- if(is_sdk) seconds=1;
- else if(gameplay=="hardcore") seconds=240;
- workers.forEach(function(worker){
- try{worker.postMessage({type:"exit"});}
- catch(e){console.log(e);}
+ var seconds = 20;
+ if (is_sdk) {
+ seconds = 1;
+ } else if (gameplay == "hardcore") {
+ seconds = 240;
+ }
+ workers.forEach(function (worker) {
+ try {
+ worker.postMessage({ type: "exit" });
+ } catch (e) {
+ console.log(e);
+ }
});
- for(var i=0;itotal/D.drops[n].length) D.drops[n][i][0]/=12.0;
- else if(D.drops[n][i][0]/1.5>total/D.drops[n].length) D.drops[n][i][0]/=3.0;
+ for (var n in D.drops) {
+ if (!is_array(D.drops[n])) {
+ continue;
+ }
+ var total = 0;
+ for (var i = 0; i < D.drops[n].length; i++) {
+ total += D.drops[n][i][0];
+ }
+ for (var i = 0; i < D.drops[n].length; i++) {
+ if (D.drops[n][i][0] < 0.001) {
+ D.drops[n][i][0] *= 200;
+ }
+
+ if (D.drops[n][i][0] * 3 < total / D.drops[n].length) {
+ D.drops[n][i][0] *= 12.0;
+ } else if (D.drops[n][i][0] * 1.5 < total / D.drops[n].length) {
+ D.drops[n][i][0] *= 3.0;
+ } else if (D.drops[n][i][0] / 3 > total / D.drops[n].length) {
+ D.drops[n][i][0] /= 12.0;
+ } else if (D.drops[n][i][0] / 1.5 > total / D.drops[n].length) {
+ D.drops[n][i][0] /= 3.0;
+ }
}
}
- for(var mname in G.maps)
- {
- if(!D.drops.maps[mname]) D.drops.maps[mname]=[];
-
- for(var i=0;i0.08 && def.hp>900) pack.gold*=0.7;
// if(def.hp>=50000) pack.gold*=0.90; // better dps utilisation - don't punish this
- pack.gold*=def.difficulty||1;
- pack.gold=parseInt(ceil(pack.gold))||0;
- if(def.stationary || def.xp<0) pack.gold=D.monster_gold[pack.type]||0;
- D.base_gold[pack.type]=D.base_gold[pack.type]||{};
- D.base_gold[pack.type][mname]=pack.gold;
- console.log(mname+" "+pack.type+" gold: "+pack.gold+"["+parseInt(drop_value)+","+parseInt(map_value)+"] gold/hp: "+(pack.gold/def.hp)+" total%: "+((pack.gold+drop_value+map_value)/def.hp));
+ pack.gold *= def.difficulty || 1;
+ pack.gold = parseInt(ceil(pack.gold)) || 0;
+ if (def.stationary || def.xp < 0) {
+ pack.gold = D.monster_gold[pack.type] || 0;
+ }
+ D.base_gold[pack.type] = D.base_gold[pack.type] || {};
+ D.base_gold[pack.type][mname] = pack.gold;
+ console.log(
+ mname +
+ " " +
+ pack.type +
+ " gold: " +
+ pack.gold +
+ "[" +
+ parseInt(drop_value) +
+ "," +
+ parseInt(map_value) +
+ "] gold/hp: " +
+ pack.gold / def.hp +
+ " total%: " +
+ (pack.gold + drop_value + map_value) / def.hp,
+ );
});
}
- for(var sname in G.sets)
- {
- var set=G.sets[sname];
- for(var i=2;i<=set.items.length;i++)
- {
- set[i]=set[i]||{};
- for(var prop in set[i-1])
- {
- if(set[i][prop]) set[i][prop]+=set[i-1][prop];
- else set[i][prop]=set[i-1][prop];
+ for (var sname in G.sets) {
+ var set = G.sets[sname];
+ for (var i = 2; i <= set.items.length; i++) {
+ set[i] = set[i] || {};
+ for (var prop in set[i - 1]) {
+ if (set[i][prop]) {
+ set[i][prop] += set[i - 1][prop];
+ } else {
+ set[i][prop] = set[i - 1][prop];
+ }
}
}
}
- if(is_pvp)
- {
- D.drops.maps.global_static.push([1.0/(gameplay=="hardcore"&&1000||100000),"pvptoken"]);
+ if (is_pvp) {
+ D.drops.maps.global_static.push([1.0 / ((gameplay == "hardcore" && 1000) || 100000), "pvptoken"]);
}
- if(events.halloween)
- {
- G.monsters.jr.respawn=480;
- G.monsters.greenjr.respawn=480;
- D.drops.maps.global.push([0.00005,"candy0"]);
- D.drops.maps.global.push([0.00125,"candy1"]);
+ if (events.halloween) {
+ G.monsters.jr.respawn = 480;
+ G.monsters.greenjr.respawn = 480;
+ D.drops.maps.global.push([0.00005, "candy0"]);
+ D.drops.maps.global.push([0.00125, "candy1"]);
}
- if(events.holidayseason)
- {
- events.snowman=60;
+ if (events.holidayseason) {
+ events.snowman = 60;
}
}
-function calculate_xvalue(arr,rec,divide,mult)
-{
- var value=0,total=0;
+function calculate_xvalue(arr, rec, divide, mult) {
+ var value = 0;
+ var total = 0;
// console.log(arr);
- arr.forEach(function(drop){
- total+=drop[0];
+ arr.forEach(function (drop) {
+ total += drop[0];
});
- if(!mult) mult=1;
- if(!divide) total=1;
- else mult=1;
- arr.forEach(function(drop){
- if(drop[1]=="open") value+=min(1,drop[0]*mult/total)*calculate_xvalue(D.drops[drop[2]],1,1,mult);
- else if(drop[1]=="shells") value+=min(1,drop[0]*mult/total)*drop[2]*G.multipliers.shells_to_gold;
- else if(drop[1]=="empty");
- else if(drop[1]=="gold") value+=drop[2]*min(1,drop[0]*mult/total);
- else
- {
- var def=G.items[drop[1]],q=drop[2]||1;
- var g=def.g,avalue=def.g;
- if(def.e && !rec)
- {
- var suffix="";
- if(def.upgrade || def.compound) suffix="0";
- avalue=calculate_xvalue(D.drops[drop[1]+suffix],1,1,mult)/def.e;
+ if (!mult) {
+ mult = 1;
+ }
+ if (!divide) {
+ total = 1;
+ } else {
+ mult = 1;
+ }
+ arr.forEach(function (drop) {
+ if (drop[1] == "open") {
+ value += min(1, (drop[0] * mult) / total) * calculate_xvalue(D.drops[drop[2]], 1, 1, mult);
+ } else if (drop[1] == "shells") {
+ value += min(1, (drop[0] * mult) / total) * drop[2] * G.multipliers.shells_to_gold;
+ } else if (drop[1] == "empty") {
+ } else if (drop[1] == "gold") {
+ value += drop[2] * min(1, (drop[0] * mult) / total);
+ } else {
+ var def = G.items[drop[1]];
+ var q = drop[2] || 1;
+ var g = def.g;
+ var avalue = def.g;
+ if (def.e && !rec) {
+ var suffix = "";
+ if (def.upgrade || def.compound) {
+ suffix = "0";
+ }
+ avalue = calculate_xvalue(D.drops[drop[1] + suffix], 1, 1, mult) / def.e;
// console.log(drop[1]+" value: "+g+" actual: "+avalue);
}
- value+=q*min(1,drop[0]*mult/total)*(g+avalue)/2;
+ value += (q * min(1, (drop[0] * mult) / total) * (g + avalue)) / 2;
+ }
+ if (!value) {
+ console.log(drop);
}
- if(!value) console.log(drop);
});
return value;
}
-function add_to_trade_history(player,event,name,item,price)
-{
- if(!player.p.trade_history) player.p.trade_history=[];
- var last=player.p.trade_history[player.p.trade_history.length-1];
- if(last && last[0]==event && last[1]==name && last[2].name==item.name && last[2].level==item.level)
- {
- last[2].q=(last[2].q||1)+(item.q||1);
- last[3]+=price;
+function add_to_trade_history(player, event, name, item, price) {
+ if (!player.p.trade_history) {
+ player.p.trade_history = [];
+ }
+ var last = player.p.trade_history[player.p.trade_history.length - 1];
+ if (last && last[0] == event && last[1] == name && last[2].name == item.name && last[2].level == item.level) {
+ last[2].q = (last[2].q || 1) + (item.q || 1);
+ last[3] += price;
return;
}
- if(player.p.trade_history.length>=40) player.p.trade_history.shift();
- player.p.trade_history.push([event,name,item,price]);
+ if (player.p.trade_history.length >= 40) {
+ player.p.trade_history.shift();
+ }
+ player.p.trade_history.push([event, name, item, price]);
}
-function add_to_history(player,event)
-{
- if(!player.p.history) player.p.history=[];
- if(player.p.history.length>=400) player.p.history.shift();
+function add_to_history(player, event) {
+ if (!player.p.history) {
+ player.p.history = [];
+ }
+ if (player.p.history.length >= 400) {
+ player.p.history.shift();
+ }
player.p.history.push(event);
}
-function is_free(player)
-{
- if(player.bot || player.p.free || player.s.licenced || player.role=="gm") return true;
+function is_free(player) {
+ if (player.bot || player.p.free || player.s.licenced || player.role == "gm") {
+ return true;
+ }
return false;
}
-function is_player_allowed(player)
-{
- if(gameplay=="hardcore")
- {
+function is_player_allowed(player) {
+ if (gameplay == "hardcore") {
//if(player.type=="mage" || player.type=="priest") return false;
//if(player.type=="rogue") return false;
}
- var socket=player.socket,characters=0,ips=0,ipx=player.ipx||1,auths=0;
- if(player.temp_auth || player.auth_id) ipx=12;
- if(is_free(player) || player.stones && 0) return true;
- if(player.type=="merchant")
- {
- for(var id in players)
- {
- if(players[id].stones && 0 || id==player.socket.id || is_free(player)) continue;
- if(players[id].owner==player.owner && players[id].type=="merchant") return false;
+ var socket = player.socket;
+ var characters = 0;
+ var ips = 0;
+ var ipx = player.ipx || 1;
+ var auths = 0;
+ if (player.temp_auth || player.auth_id) {
+ ipx = 12;
+ }
+ if (is_free(player) || (player.stones && 0)) {
+ return true;
+ }
+ if (player.type == "merchant") {
+ for (var id in players) {
+ if ((players[id].stones && 0) || id == player.socket.id || is_free(player)) {
+ continue;
+ }
+ if (players[id].owner == player.owner && players[id].type == "merchant") {
+ return false;
+ }
}
return true;
}
- for(var id in players)
- {
- if(players[id].stones && 0 || is_free(players[id]) || players[id].type=="merchant") continue; // was requested [28/10/16]
- if(players[id].owner==player.owner) characters++;
- if(players[id].name==player.name && player!=players[id]) return false; // "hardcore"
- if(get_ip(players[id])==get_ip(player)) ips++;
- if(player.auth_id && players[id].auth_id==player.auth_id) auths++;
- if(auths>variables.character_limit) return false;
- if(characters>variables.character_limit) return false;
- if(ips>variables.ip_limit*ipx) return false;
+ for (var id in players) {
+ if ((players[id].stones && 0) || is_free(players[id]) || players[id].type == "merchant") {
+ continue;
+ } // was requested [28/10/16]
+ if (players[id].owner == player.owner) {
+ characters++;
+ }
+ if (players[id].name == player.name && player != players[id]) {
+ return false;
+ } // "hardcore"
+ if (get_ip(players[id]) == get_ip(player)) {
+ ips++;
+ }
+ if (player.auth_id && players[id].auth_id == player.auth_id) {
+ auths++;
+ }
+ if (auths > variables.character_limit) {
+ return false;
+ }
+ if (characters > variables.character_limit) {
+ return false;
+ }
+ if (ips > variables.ip_limit * ipx) {
+ return false;
+ }
}
return true;
}
-function rip(player)
-{
- player.hp=0;
- player.rip=true;
- player.rip_time=new Date();
- player.moving=false;
- player.abs=true;
- if(player.party) send_party_update(player.party);
+function rip(player) {
+ player.hp = 0;
+ player.rip = true;
+ player.rip_time = new Date();
+ player.moving = false;
+ player.abs = true;
+ if (player.party) {
+ send_party_update(player.party);
+ }
}
-function notify_friends(data)
-{
- data.list.forEach(function(name){
- var player=players[name_to_id[name]]; if(!player) return;
- player.socket.emit("online",{name:data.name,server:data.server});
+function notify_friends(data) {
+ data.list.forEach(function (name) {
+ var player = players[name_to_id[name]];
+ if (!player) {
+ return;
+ }
+ player.socket.emit("online", { name: data.name, server: data.server });
});
}
-function check_player(player) // to check players in setTimeout's
-{
- if(!player || !player.socket || player.dc || !players[player.socket.id]) return false;
+function check_player(player) {
+ // to check players in setTimeout's
+ if (!player || !player.socket || player.dc || !players[player.socket.id]) {
+ return false;
+ }
return true;
}
-function is_invis(player)
-{
- if(player.s && (player.s.invis || player.s.ethereal)) return true;
+function is_invis(player) {
+ if (player.s && (player.s.invis || player.s.ethereal)) {
+ return true;
+ }
return false;
}
-function is_invinc(player)
-{
- if(player.s && (player.s.invis || player.s.ethereal || player.s.invincible)) return true;
+function is_invinc(player) {
+ if (player.s && (player.s.invis || player.s.ethereal || player.s.invincible)) {
+ return true;
+ }
return false;
}
-function is_in_pvp(player,allow_safe)
-{
- if(allow_safe && G.maps[player.map].safe) return false;
- if(is_pvp || G.maps[player.map].pvp) return true;
+function is_in_pvp(player, allow_safe) {
+ if (allow_safe && G.maps[player.map].safe) {
+ return false;
+ }
+ if (is_pvp || G.maps[player.map].pvp) {
+ return true;
+ }
return false;
}
-function is_map_pvp(map,allow_safe)
-{
- if(allow_safe && G.maps[map].safe) return false;
- if(is_pvp || G.maps[map].pvp) return true;
+function is_map_pvp(map, allow_safe) {
+ if (allow_safe && G.maps[map].safe) {
+ return false;
+ }
+ if (is_pvp || G.maps[map].pvp) {
+ return true;
+ }
return false;
}
-function is_same(player1,player2,party)
-{
- if(is_sdk && player1.name!=player2.name) return false;
- if(player1.name==player2.name) return true;
- if(player1.owner && player1.owner==player2.owner || !is_sdk && get_ip(player1)==get_ip(player2)) return true;
- if(party==3 && !is_in_pvp(player1)) return true;
- if(party && player1.s && player1.s.coop && player2.s && player2.s.coop && player1.s.coop.id==player2.s.coop.id) return true; // previously party==2 [08/05/21]
- if(party && player1.party && player1.party==player2.party) return true;
- if(party && player1.team && player1.team==player2.team) return true;
+function is_same(player1, player2, party) {
+ if (is_sdk && player1.name != player2.name) {
+ return false;
+ }
+ if (player1.name == player2.name) {
+ return true;
+ }
+ if ((player1.owner && player1.owner == player2.owner) || (!is_sdk && get_ip(player1) == get_ip(player2))) {
+ return true;
+ }
+ if (party == 3 && !is_in_pvp(player1)) {
+ return true;
+ }
+ if (party && player1.s && player1.s.coop && player2.s && player2.s.coop && player1.s.coop.id == player2.s.coop.id) {
+ return true;
+ } // previously party==2 [08/05/21]
+ if (party && player1.party && player1.party == player2.party) {
+ return true;
+ }
+ if (party && player1.team && player1.team == player2.team) {
+ return true;
+ }
return false;
}
-function decay_s(player,ms)
-{
- for(var name in (player.s||{}))
- {
- if(G.conditions[name] && G.conditions[name].debuff) continue;
- if(player.s[name].ms<60000 || player.s[name].citizens)
- {
- if(player.s[name].citizens)
- {
- for(var p in player.s[name])
- {
- if(p!="ms" && is_number(player.s[name][p]))
- player.s[name][p]=round(player.s[name][p]/4.0);
+function decay_s(player, ms) {
+ for (var name in player.s || {}) {
+ if (G.conditions[name] && G.conditions[name].debuff) {
+ continue;
+ }
+ if (player.s[name].ms < 60000 || player.s[name].citizens) {
+ if (player.s[name].citizens) {
+ for (var p in player.s[name]) {
+ if (p != "ms" && is_number(player.s[name][p])) {
+ player.s[name][p] = round(player.s[name][p] / 4.0);
+ }
}
}
- player.s[name].ms-=ms;
+ player.s[name].ms -= ms;
}
}
}
-function reset_player(player,soft)
-{
- if(!player.p.hardcore)
- {
- player.p={hardcore:true,dt:{}};
- player.max_stats={monsters:{}};
+function reset_player(player, soft) {
+ if (!player.p.hardcore) {
+ player.p = { hardcore: true, dt: {} };
+ player.max_stats = { monsters: {} };
}
- player.xp=0;
- if(soft)
- {
+ player.xp = 0;
+ if (soft) {
// player.level=max(1,player.level-20);
- }
- else
- {
- player.level=1;
- player.xp=0;
- player.s={};
- player.slots={};
- player.items=[{"name":"computer"},{"name":"tracker"}];
- player.gold=0;
- if(P[player.real_id] && gameplay!="test")
- {
- for(var p in P[player.real_id]) player[p]=P[player.real_id][p];
- P[player.real_id]=null;
+ } else {
+ player.level = 1;
+ player.xp = 0;
+ player.s = {};
+ player.slots = {};
+ player.items = [{ name: "computer" }, { name: "tracker" }];
+ player.gold = 0;
+ if (P[player.real_id] && gameplay != "test") {
+ for (var p in P[player.real_id]) {
+ player[p] = P[player.real_id][p];
+ }
+ P[player.real_id] = null;
}
}
}
-function save_player(player)
-{
- P[player.real_id]={
- level:player.level,
- xp:player.xp,
- slots:player.slots,
- items:player.items,
- gold:player.gold,
- x:player.x,
- y:player.y,
- map:player.map,
- in:player.in,
- rip:player.rip,
- kills:player.kills,
- p:player.p,
- name:player.name,
- auth_id:player.auth_id,
+function save_player(player) {
+ P[player.real_id] = {
+ level: player.level,
+ xp: player.xp,
+ slots: player.slots,
+ items: player.items,
+ gold: player.gold,
+ x: player.x,
+ y: player.y,
+ map: player.map,
+ in: player.in,
+ rip: player.rip,
+ kills: player.kills,
+ p: player.p,
+ name: player.name,
+ auth_id: player.auth_id,
};
}
-function secondhands_logic(item,quantity)
-{
- var new_item=cache_item(item),done=false,count=0,replace=null;
- if(!(!G.items[item.name].buy || G.items[item.name].upgrade && item.level>=7 || G.items[item.name].compound && item.level>=2) || G.items[item.name].cash || item.expires || item.acl) return;
- if(item.grace!==undefined) new_item.grace=item.grace;
- if(new_item.q!==undefined) new_item.q=quantity;
+function secondhands_logic(item, quantity) {
+ var new_item = cache_item(item);
+ var done = false;
+ var count = 0;
+ var replace = null;
+ if (
+ !(
+ !G.items[item.name].buy ||
+ (G.items[item.name].upgrade && item.level >= 7) ||
+ (G.items[item.name].compound && item.level >= 2)
+ ) ||
+ G.items[item.name].cash ||
+ item.expires ||
+ item.acl
+ ) {
+ return;
+ }
+ if (item.grace !== undefined) {
+ new_item.grace = item.grace;
+ }
+ if (new_item.q !== undefined) {
+ new_item.q = quantity;
+ }
delete new_item.v;
- new_item.rid=randomStr(5);
- for(var i=0;i=5) current=replace;
- S.sold[current]=new_item;
- csold[current]=cache_item(S.sold[current],true);
+ if (!done && (count < 5 || (new_item.p && replace !== null))) {
+ var current = S.sold.length % 400;
+ if (count >= 5) {
+ current = replace;
+ }
+ S.sold[current] = new_item;
+ csold[current] = cache_item(S.sold[current], true);
}
}
-function lostandfound_logic(item)
-{
- var done=false,count=0,replace=null;
- item.rid=randomStr(5);
- for(var i=0;i=5) current=replace;
- S.found[current]=item;
- cfound[current]=cache_item(S.found[current],true);
+ if (!done && (count < 5 || (item.p && replace !== null))) {
+ var current = S.found.length % 400;
+ if (count >= 5) {
+ current = replace;
+ }
+ S.found[current] = item;
+ cfound[current] = cache_item(S.found[current], true);
}
}
-function server_loot(type)
-{
- if(type=="all")
- {
- for(var mtype in D.drops.monsters)
- for(var j=0;j0.1) D.drops.monsters[mtype][j][0]=0.05;
- for(var id in instances)
- {
- if(instances[id].map!=instances[id].name) continue;
- for(var mid in instances[id].monsters)
- if(instances[id].monsters[mid].frequency<4 && instances.main)
- drop_something(instances.main.players[NPC_prefix+"Kane"],instances[id].monsters[mid]);
+function server_loot(type) {
+ if (type == "all") {
+ for (var mtype in D.drops.monsters) {
+ for (var j = 0; j < D.drops.monsters[mtype].length; j++) {
+ if (D.drops.monsters[mtype][j][0] > 0.1) {
+ D.drops.monsters[mtype][j][0] = 0.05;
+ }
+ }
+ }
+ for (var id in instances) {
+ if (instances[id].map != instances[id].name) {
+ continue;
+ }
+ for (var mid in instances[id].monsters) {
+ if (instances[id].monsters[mid].frequency < 4 && instances.main) {
+ drop_something(instances.main.players[NPC_prefix + "Kane"], instances[id].monsters[mid]);
+ }
+ }
}
}
- for(var id in chests)
- {
- var chest=chests[id];
- if(type!="all" && hsince(chests[id].date)<48) return;
+ for (var id in chests) {
+ var chest = chests[id];
+ if (type != "all" && hsince(chests[id].date) < 48) {
+ return;
+ }
delete chests[id];
- S.gold+=chest.gold;
- if(chest.cash) S.cash+=chest.cash;
- if(chest.items) chest.items.forEach(function(item){
- lostandfound_logic(item);
- });
- if(chest.pvp_items) chest.pvp_items.forEach(function(item){
- lostandfound_logic(item);
- });
+ S.gold += chest.gold;
+ if (chest.cash) {
+ S.cash += chest.cash;
+ }
+ if (chest.items) {
+ chest.items.forEach(function (item) {
+ lostandfound_logic(item);
+ });
+ }
+ if (chest.pvp_items) {
+ chest.pvp_items.forEach(function (item) {
+ lostandfound_logic(item);
+ });
+ }
}
}
-function server_tax(gold,preview)
-{
- var tax=0;
- if(1) tax=parseInt(gold*0.1);
- else if(S.gold<500000000) tax=parseInt(gold*0.25);
- else if(S.gold<1000000000) tax=parseInt(gold*0.5);
- if(!preview) S.gold+=tax;
- return gold-tax;
+function server_tax(gold, preview) {
+ var tax = 0;
+ if (1) {
+ tax = parseInt(gold * 0.1);
+ } else if (S.gold < 500000000) {
+ tax = parseInt(gold * 0.25);
+ } else if (S.gold < 1000000000) {
+ tax = parseInt(gold * 0.5);
+ }
+ if (!preview) {
+ S.gold += tax;
+ }
+ return gold - tax;
}
-function merchant_xp_logic(player,seller,price,tax)
-{
- if(is_same(player,seller)) return;
- if(!player.p.xpcache || Object.keys(player.p.xpcache).length>120 || hsince(player.p.dt.last_xpcache)>5*24) player.p.xpcache={},player.p.dt.last_xpcache=new Date();
- if(!player.p.xpcache[seller.name]) player.p.xpcache[seller.name]=0;
- var initial=player.p.xpcache[seller.name];
- player.p.xpcache[seller.name]=min(120000000,player.p.xpcache[seller.name]+round(price/4));
- player.xp+=player.p.xpcache[seller.name]-initial;
+function merchant_xp_logic(player, seller, price, tax) {
+ if (is_same(player, seller)) {
+ return;
+ }
+ if (!player.p.xpcache || Object.keys(player.p.xpcache).length > 120 || hsince(player.p.dt.last_xpcache) > 5 * 24) {
+ player.p.xpcache = {};
+ player.p.dt.last_xpcache = new Date();
+ }
+ if (!player.p.xpcache[seller.name]) {
+ player.p.xpcache[seller.name] = 0;
+ }
+ var initial = player.p.xpcache[seller.name];
+ player.p.xpcache[seller.name] = min(120000000, player.p.xpcache[seller.name] + round(price / 4));
+ player.xp += player.p.xpcache[seller.name] - initial;
}
-function merchant_xp_logic(player,seller,price,tax)
-{
- if(is_same(player,seller)) return;
- player.xp+=tax*3.2;
+function merchant_xp_logic(player, seller, price, tax) {
+ if (is_same(player, seller)) {
+ return;
+ }
+ player.xp += tax * 3.2;
}
-function normalise(data) // normalise(data,["gold","gold"],["num","inv"])
-{
- for(var i=1;inew Date())
- {
- player.auth_type="mas";
- player.auth_id=player.p.mas_auth_id;
+function verify_mas_receipt(player, receipt) {
+ if (player.p.mas_hash == quick_hash(receipt) && player.p.dt.mas_expire > new Date()) {
+ player.auth_type = "mas";
+ player.auth_id = player.p.mas_auth_id;
delete player.s.authfail;
- }
- else
- {
- console.log("verify_mas_receipt for "+player.name);
- player.temp_auth="mas";
+ } else {
+ console.log("verify_mas_receipt for " + player.name);
+ player.temp_auth = "mas";
//player.mas_receipt=receipt;
- var content={'receipt-data':receipt,password:variables.apple_token};
- var url="https://buy.itunes.apple.com/verifyReceipt";
+ var content = { "receipt-data": receipt, password: variables.apple_token };
+ var url = "https://buy.itunes.apple.com/verifyReceipt";
request(
{
- url:url,
- method:"POST",
- json:content,
+ url: url,
+ method: "POST",
+ json: content,
},
- function(err,response,body){
- if(err)
- {
- console.log("#M: mas error: "+player.name+" - "+err);
+ function (err, response, body) {
+ if (err) {
+ console.log("#M: mas error: " + player.name + " - " + err);
}
- if(body && body.status==0 && body.receipt.download_id && body.receipt.original_purchase_date_ms)
- {
+ if (body && body.status == 0 && body.receipt.download_id && body.receipt.original_purchase_date_ms) {
delete player.temp_auth;
- player.auth_type="mas";
- player.auth_id=(""+body.receipt.download_id).substr(0,4)+body.receipt.original_purchase_date_ms;
- player.p.mas_auth_id=player.auth_id;
- player.p.mas_hash=quick_hash(receipt);
- player.p.dt.mas_expire=future_s(3*24*60*60);
+ player.auth_type = "mas";
+ player.auth_id = ("" + body.receipt.download_id).substr(0, 4) + body.receipt.original_purchase_date_ms;
+ player.p.mas_auth_id = player.auth_id;
+ player.p.mas_hash = quick_hash(receipt);
+ player.p.dt.mas_expire = future_s(3 * 24 * 60 * 60);
delete player.s.authfail;
- }
- else
- {
+ } else {
delete player.temp_auth;
- console.log("#M: mas declined: "+player.name+" "+(body&&body.status));
+ console.log("#M: mas declined: " + player.name + " " + (body && body.status));
}
- });
+ },
+ );
}
}
-function verify_steam_ownership(player)
-{
- var url="https://partner.steam-api.com/ISteamUser/CheckAppOwnership/v2/";
- data={
- key:variables.steam_partner_key,
- steamid:player.p.steam_id,
- appid:"777150",
- }
- request.get({url:url,qs:data},function(err,response,body){
+function verify_steam_ownership(player) {
+ var url = "https://partner.steam-api.com/ISteamUser/CheckAppOwnership/v2/";
+ data = {
+ key: variables.steam_partner_key,
+ steamid: player.p.steam_id,
+ appid: "777150",
+ };
+ request.get({ url: url, qs: data }, function (err, response, body) {
console.log(body);
});
}
-function initiate_steam_microtxn(player)
-{
- var url="https://partner.steam-api.com/ISteamMicroTxn/InitTxn/v3/";
- var orderid=parseInt(Math.random()*1000000000+1);
+function initiate_steam_microtxn(player) {
+ var url = "https://partner.steam-api.com/ISteamMicroTxn/InitTxn/v3/";
+ var orderid = parseInt(Math.random() * 1000000000 + 1);
console.log(orderid);
- data={
- key:variables.steam_partner_key,
- steamid:player.p.steam_id,
- appid:"777150",
- usersession:"web",
- ipaddress:"85.98.170.74",
- orderid:orderid,
- itemcount:1,
- language:"en",
- currency:"USD",
- "itemid[0]":"123",
- "qty[0]":1,
- "amount[0]":999, // $9.99
- "description[0]":"1000 Shells",
- }
- request.post({url:url,form:data},function(err,response,body){
+ data = {
+ key: variables.steam_partner_key,
+ steamid: player.p.steam_id,
+ appid: "777150",
+ usersession: "web",
+ ipaddress: "85.98.170.74",
+ orderid: orderid,
+ itemcount: 1,
+ language: "en",
+ currency: "USD",
+ "itemid[0]": "123",
+ "qty[0]": 1,
+ "amount[0]": 999, // $9.99
+ "description[0]": "1000 Shells",
+ };
+ request.post({ url: url, form: data }, function (err, response, body) {
console.log(body);
});
}
-function invincible_logic(player,place)
-{
- if(is_pvp || G.maps[player.map].pvp)
- {
- player.s.invincible={ms:max(6000,player.s.invincible&&player.s.invincible.ms||0)};
+function invincible_logic(player, place) {
+ if (is_pvp || G.maps[player.map].pvp) {
+ player.s.invincible = { ms: max(6000, (player.s.invincible && player.s.invincible.ms) || 0) };
}
}
-function serverhop_logic(player)
-{
+function serverhop_logic(player) {
delete player.s.hopsickness;
- player.p.entries=player.p.entries||[];
- var servers={},main=null,mx=0,hops=0;
- for(var i=player.p.entries.length-2;i>=0;i--)
- {
- var hours = Math.abs(new Date(player.p.entries[i+1][1])-new Date(player.p.entries[i][1])) / 36e5;
- servers[player.p.entries[i][0]]=(servers[player.p.entries[i][0]]||0)+hours;
+ player.p.entries = player.p.entries || [];
+ var servers = {};
+ var main = null;
+ var mx = 0;
+ var hops = 0;
+ for (var i = player.p.entries.length - 2; i >= 0; i--) {
+ var hours = Math.abs(new Date(player.p.entries[i + 1][1]) - new Date(player.p.entries[i][1])) / 36e5;
+ servers[player.p.entries[i][0]] = (servers[player.p.entries[i][0]] || 0) + hours;
}
- for(var id in servers)
- {
- if(servers[id]>mx) main=id,mx=servers[id];
+ for (var id in servers) {
+ if (servers[id] > mx) {
+ main = id;
+ mx = servers[id];
+ }
}
- for(var i=player.p.entries.length-1;i>=0;i--)
- {
- if(hsince(new Date(player.p.entries[i][1]))<4 && player.p.entries[i][0]!=main) hops++;
+ for (var i = player.p.entries.length - 1; i >= 0; i--) {
+ if (hsince(new Date(player.p.entries[i][1])) < 4 && player.p.entries[i][0] != main) {
+ hops++;
+ }
}
- if(main && hops && main!=region+server_name && player.level>=60)
- {
- player.s.hopsickness={ms:min(10000*hops*hops,3*60*60*1000)};
- if(hops>20) player.s.hopsickness.luck=-80,player.s.hopsickness.gold=-80,player.s.hopsickness.output=-50;
- else if(hops>15) player.s.hopsickness.luck=-60,player.s.hopsickness.gold=-60,player.s.hopsickness.output=-40;
- else if(hops>10) player.s.hopsickness.luck=-40,player.s.hopsickness.gold=-40,player.s.hopsickness.output=-30;
- else if(hops>5) player.s.hopsickness.luck=-30,player.s.hopsickness.gold=-30,player.s.hopsickness.output=-20;
- else if(hops>2) player.s.hopsickness.luck=-20,player.s.hopsickness.gold=-20,player.s.hopsickness.output=-10;
+ if (main && hops && main != region + server_name && player.level >= 60) {
+ player.s.hopsickness = { ms: min(10000 * hops * hops, 3 * 60 * 60 * 1000) };
+ if (hops > 20) {
+ player.s.hopsickness.luck = -80;
+ player.s.hopsickness.gold = -80;
+ player.s.hopsickness.output = -50;
+ } else if (hops > 15) {
+ player.s.hopsickness.luck = -60;
+ player.s.hopsickness.gold = -60;
+ player.s.hopsickness.output = -40;
+ } else if (hops > 10) {
+ player.s.hopsickness.luck = -40;
+ player.s.hopsickness.gold = -40;
+ player.s.hopsickness.output = -30;
+ } else if (hops > 5) {
+ player.s.hopsickness.luck = -30;
+ player.s.hopsickness.gold = -30;
+ player.s.hopsickness.output = -20;
+ } else if (hops > 2) {
+ player.s.hopsickness.luck = -20;
+ player.s.hopsickness.gold = -20;
+ player.s.hopsickness.output = -10;
+ }
calculate_player_stats(player);
}
- var c=[region+server_name,""+(new Date())];
+ var c = [region + server_name, "" + new Date()];
player.p.entries.push(c);
- if(player.p.entries.length>60) player.p.entries.shift();
+ if (player.p.entries.length > 60) {
+ player.p.entries.shift();
+ }
}
-function serverhop_logic(player)
-{
- if(player.p.entries && player.p.entries[0] && player.p.entries[0][0]==region+server_name) return;
+function serverhop_logic(player) {
+ if (player.p.entries && player.p.entries[0] && player.p.entries[0][0] == region + server_name) {
+ return;
+ }
delete player.s.hopsickness;
- if(!player.p.home) player.p.home=region+server_name;
- player.p.entries=[[region+server_name,""+(new Date())]];
- if(player.p.home!=region+server_name && player.level>=60 && server_name!="PVP")
- add_condition(player,"hopsickness");
+ if (!player.p.home) {
+ player.p.home = region + server_name;
+ }
+ player.p.entries = [[region + server_name, "" + new Date()]];
+ if (player.p.home != region + server_name && player.level >= 60 && server_name != "PVP") {
+ add_condition(player, "hopsickness");
+ }
}
-function ghash(entity,zone,a_d,b_d) //zone is the square's dimension, a_d, and b_d are displacements
-{
- var a=floor(1.0*entity.x/zone)+(a_d||0),b=floor(1.0*entity.y/zone)+(b_d||0);
- return a+"|"+b;
+function ghash(entity, zone, a_d, b_d) {
+ //zone is the square's dimension, a_d, and b_d are displacements
+ var a = floor((1.0 * entity.x) / zone) + (a_d || 0);
+ var b = floor((1.0 * entity.y) / zone) + (b_d || 0);
+ return a + "|" + b;
}
-function set_ghash(hash,entity,zone)
-{
- var h=ghash(entity,zone);
- if(!hash[h]) hash[h]={};
- hash[h][entity.id]=entity;
+function set_ghash(hash, entity, zone) {
+ var h = ghash(entity, zone);
+ if (!hash[h]) {
+ hash[h] = {};
+ }
+ hash[h][entity.id] = entity;
}
-function get_nearby_ghash(hash,entity,zone)
-{
- var d=[-1,0,1],l=[],h;
- for(var i=0;i<3;i++)
- for(var j=0;j<3;j++)
- {
- h=ghash(entity,zone,d[i],d[j]);
- for(var id in hash[h]) l.push(hash[h][id]);
+function get_nearby_ghash(hash, entity, zone) {
+ var d = [-1, 0, 1];
+ var l = [];
+ var h;
+ for (var i = 0; i < 3; i++) {
+ for (var j = 0; j < 3; j++) {
+ h = ghash(entity, zone, d[i], d[j]);
+ for (var id in hash[h]) {
+ l.push(hash[h][id]);
+ }
}
+ }
return l;
}
-function screenshot_npc(player,args)
-{
- if(!args) args={};
- if(!args.name) args.name=randomStr(10);
- instance=instances[player.in];
- var npc=create_npc({name:args.name,level:args.level||40,speed:1200,hp:100000000,skin:args.skin||"mranger",cx:args.cx||[]},{position:[player.x,player.y],id:args.name},instance);
- if(args.stand) npc.p.stand=args.stand;
- npc.screenshot=true;
- npc.direction=player.direction;
- npc.id=args.name;
- instance.players[NPC_prefix+npc.id]=npc;
+function screenshot_npc(player, args) {
+ if (!args) {
+ args = {};
+ }
+ if (!args.name) {
+ args.name = randomStr(10);
+ }
+ instance = instances[player.in];
+ var npc = create_npc(
+ {
+ name: args.name,
+ level: args.level || 40,
+ speed: 1200,
+ hp: 100000000,
+ skin: args.skin || "mranger",
+ cx: args.cx || [],
+ },
+ { position: [player.x, player.y], id: args.name },
+ instance,
+ );
+ if (args.stand) {
+ npc.p.stand = args.stand;
+ }
+ npc.screenshot = true;
+ npc.direction = player.direction;
+ npc.id = args.name;
+ instance.players[NPC_prefix + npc.id] = npc;
}
-function get_npc_coords(id)
-{
- for(var iid in instances)
- {
- if(G.maps[iid] && G.maps[iid].ref && G.maps[iid].ref[id])
+function get_npc_coords(id) {
+ for (var iid in instances) {
+ if (G.maps[iid] && G.maps[iid].ref && G.maps[iid].ref[id]) {
return G.maps[iid].ref[id];
+ }
}
- return {x:0,y:0,map:"main",in:"main"};
+ return { x: 0, y: 0, map: "main", in: "main" };
}
-function pmap_remove(player)
-{
- try{
+function pmap_remove(player) {
+ try {
delete instances[player.in].pmap[player.last_hash][player.id];
- if(!Object.keys(instances[player.in].pmap[player.last_hash]).length) delete instances[player.in].pmap[player.last_hash];
- }
- catch(e){}
+ if (!Object.keys(instances[player.in].pmap[player.last_hash]).length) {
+ delete instances[player.in].pmap[player.last_hash];
+ }
+ } catch (e) {}
}
-function pmap_get(player)
-{
- var hash=ghash(player,6);
- if(!instances[player.in].pmap[hash]) return {};
+function pmap_get(player) {
+ var hash = ghash(player, 6);
+ if (!instances[player.in].pmap[hash]) {
+ return {};
+ }
return instances[player.in].pmap[hash];
}
-function pmap_add(player)
-{
- var hash=ghash(player,6);
- if(!instances[player.in].pmap[hash]) instances[player.in].pmap[hash]={};
- instances[player.in].pmap[hash][player.id]=player;
- player.last_hash=hash;
+function pmap_add(player) {
+ var hash = ghash(player, 6);
+ if (!instances[player.in].pmap[hash]) {
+ instances[player.in].pmap[hash] = {};
+ }
+ instances[player.in].pmap[hash][player.id] = player;
+ player.last_hash = hash;
}
-function pmap_move(player)
-{
- var hash=ghash(player,6);
- if(player.last_hash==hash) return;
+function pmap_move(player) {
+ var hash = ghash(player, 6);
+ if (player.last_hash == hash) {
+ return;
+ }
pmap_remove(player);
pmap_add(player);
}
-function init_tavern()
-{
- if(!instances.tavern) return;
- tavern=instances.tavern;
- tavern.roulette={
- state:"bets",
- next:future_s(25),
- "odds":{
- "red":2,
- "black":2,
- "odd":2,
- "even":2,
- "1/3":3,
- "2/3":3,
- "3/3":3,
- "1/2":2,
- "2/2":2,
- "3n":3,
- "3n+1":3,
- "3n+2":3,
+function init_tavern() {
+ if (!instances.tavern) {
+ return;
+ }
+ tavern = instances.tavern;
+ tavern.roulette = {
+ state: "bets",
+ next: future_s(25),
+ odds: {
+ red: 2,
+ black: 2,
+ odd: 2,
+ even: 2,
+ "1/3": 3,
+ "2/3": 3,
+ "3/3": 3,
+ "1/2": 2,
+ "2/2": 2,
+ "3n": 3,
+ "3n+1": 3,
+ "3n+2": 3,
},
- gain:0,
- players:{},
+ gain: 0,
+ players: {},
};
- for(var i=0;i<=36;i++) tavern.roulette.odds[""+i]=36;
- tavern.poker={
- rooms:[],
- gain:0,
+ for (var i = 0; i <= 36; i++) {
+ tavern.roulette.odds["" + i] = 36;
+ }
+ tavern.poker = {
+ rooms: [],
+ gain: 0,
};
- tavern.dice={
- rolls:[],
- state:"lock",
- seconds:0,
- next:future_s(1),
- players:{},
- bets:[],
+ tavern.dice = {
+ rolls: [],
+ state: "lock",
+ seconds: 0,
+ next: future_s(1),
+ players: {},
+ bets: [],
};
- tavern.dice.num=""+parseInt(Math.random()*10)+""+parseInt(Math.random()*10)+"."+parseInt(Math.random()*10)+""+parseInt(Math.random()*10);
- tavern.info.dice="lock";
- tavern.info.num=tavern.dice.num;
- tavern.info.seconds=tavern.dice.seconds;
+ tavern.dice.num =
+ "" +
+ parseInt(Math.random() * 10) +
+ "" +
+ parseInt(Math.random() * 10) +
+ "." +
+ parseInt(Math.random() * 10) +
+ "" +
+ parseInt(Math.random() * 10);
+ tavern.info.dice = "lock";
+ tavern.info.num = tavern.dice.num;
+ tavern.info.seconds = tavern.dice.seconds;
}
-function house_debt()
-{
- var gold=0;
- for(var id in tavern.dice.players)
- {
- var player=players[id]; if(!player) continue;
- for(var b_id in player.bets||{})
- {
- var bet=player.bets[b_id]; if(bet.type!="dice") continue;
- gold+=bet.win-bet.edge-bet.gold;
+function house_debt() {
+ var gold = 0;
+ for (var id in tavern.dice.players) {
+ var player = players[id];
+ if (!player) {
+ continue;
+ }
+ for (var b_id in player.bets || {}) {
+ var bet = player.bets[b_id];
+ if (bet.type != "dice") {
+ continue;
+ }
+ gold += bet.win - bet.edge - bet.gold;
}
}
return gold;
}
-function house_edge()
-{
- var gold=S.gold-house_debt();
- if(gold>5000000000) return 0.5;
- if(gold>2000000000) return 1;
- if(gold>1000000000) return 1.5;
+function house_edge() {
+ var gold = S.gold - house_debt();
+ if (gold > 5000000000) {
+ return 0.5;
+ }
+ if (gold > 2000000000) {
+ return 1;
+ }
+ if (gold > 1000000000) {
+ return 1.5;
+ }
return 2;
}
-var dice_last_roll=0;
-function tavern_loop()
-{ try{
- if(!server.live || !instances.tavern) return;
- var c=new Date();
- if(c>tavern.dice.next)
- {
- if(tavern.dice.state=="bets")
- {
- tavern.dice.seconds+=1; tavern.info.seconds=tavern.dice.seconds;
- if(tavern.dice.seconds>=30)
- {
- tavern.info.dice=tavern.dice.state="roll";
- dice_last_roll=tavern.info.num;
- delete tavern.info.num;
- tavern.dice.next=future_s(10);
- instance_emit(tavern,"dice",{state:"roll"});
- //server_log("Dice: Bets Over");
- }
+var dice_last_roll = 0;
+function tavern_loop() {
+ try {
+ if (!server.live || !instances.tavern) {
+ return;
}
- else if(tavern.dice.state=="roll")
- {
- tavern.info.dice=tavern.dice.state="lock";
- tavern.info.num=tavern.dice.num;
- tavern.dice.next=future_s(1.6);
- for(var id in tavern.dice.players)
- {
- var player=players[id]; if(!player) continue;
- for(var b_id in player.bets||{})
- {
- var bet=player.bets[b_id]; if(bet.type!="dice") continue;
- delete players[bet.pid].bets[bet.id];
- tavern.dice.bets.push(bet);
- if(bet.dir=="up" && parseFloat(tavern.dice.num)>=bet.num || bet.dir=="down" && parseFloat(tavern.dice.num)<=bet.num)
- {
- if(player.type=="merchant") player.xp+=parseInt(bet.edge*7.2);
- player.gold+=bet.win-bet.edge,S.gold-=bet.win-bet.edge-bet.gold;
- if(bet.win-bet.edge-bet.gold>=12000000) lstack(S.logs.dice,{name:player.name,gold:bet.win-bet.edge-bet.gold,odds:bet.odds});
+ var c = new Date();
+ if (c > tavern.dice.next) {
+ if (tavern.dice.state == "bets") {
+ tavern.dice.seconds += 1;
+ tavern.info.seconds = tavern.dice.seconds;
+ if (tavern.dice.seconds >= 30) {
+ tavern.info.dice = tavern.dice.state = "roll";
+ dice_last_roll = tavern.info.num;
+ delete tavern.info.num;
+ tavern.dice.next = future_s(10);
+ instance_emit(tavern, "dice", { state: "roll" });
+ //server_log("Dice: Bets Over");
+ }
+ } else if (tavern.dice.state == "roll") {
+ tavern.info.dice = tavern.dice.state = "lock";
+ tavern.info.num = tavern.dice.num;
+ tavern.dice.next = future_s(1.6);
+ for (var id in tavern.dice.players) {
+ var player = players[id];
+ if (!player) {
+ continue;
}
- else
- {
- if(bet.gold>=10000000) lstack(S.logs.dice,{name:player.name,gold:-bet.gold,odds:bet.odds});
- S.gold+=bet.gold;
- }
- }
- }
- instance_emit(tavern,"dice",{state:"lock",num:tavern.dice.num,text:tavern.dice.text,key:tavern.dice.key});
- //server_log("Dice: Roll Over - Locking");
- }
- else if(tavern.dice.state=="lock")
- {
- tavern.dice.state="suspense";
- tavern.dice.bets.forEach(function(bet){
- var player=players[bet.pid]; if(!player) return;
- if(bet.dir=="up" && parseFloat(tavern.dice.num)>=bet.num || bet.dir=="down" && parseFloat(tavern.dice.num)<=bet.num)
- {
- player.socket.emit("game_log",{"message":"Won: "+to_pretty_num(bet.win)+" gold ["+tavern.dice.num+"]","color":"gold"});
- player.socket.emit("game_log",{"message":"House edge: "+to_pretty_num(bet.edge)+" gold","color":"gray"});
- instance_emit(tavern,"tavern",{event:"won",name:player.name,type:"dice",num:bet.num,gold:bet.win,dir:bet.dir,net:bet.win-bet.gold-bet.edge});
- }
- else
- {
- player.socket.emit("game_log",{"message":"Lost: "+to_pretty_num(bet.gold)+" gold ["+tavern.dice.num+"]","color":"gray"});
- instance_emit(tavern,"tavern",{event:"lost",name:player.name,type:"dice",num:bet.num,gold:bet.gold,dir:bet.dir});
- }
- if(player.xp>=player.max_xp) resend(player,"reopen");
- else resend(player,"reopen+nc");
- });
- tavern.dice.next=future_s(2);
- //server_log("Dice: Locked - Suspensing");
- }
- else if(tavern.dice.state=="suspense")
- {
- var timer=new Date();
- tavern.info.dice=tavern.dice.state="bets";
- tavern.info.seconds=tavern.dice.seconds=0;
- tavern.dice.players={}; tavern.dice.bets=[];
- tavern.dice.num=""+parseInt(Math.random()*10)+""+parseInt(Math.random()*10)+"."+parseInt(Math.random()*10)+""+parseInt(Math.random()*10);
- tavern.dice.key=randomStr(20+parseInt(Math.random()*20));
- var initials=""; for(var id in tavern.players) if(!tavern.players[id].npc) initials+=tavern.players[id].name[0];
- tavern.dice.text="Num: "+tavern.dice.num+" Initials: "+initials+" Random: "+randomStr(16+parseInt(Math.random()*16));
- var hmac=crypto.createHmac('sha256',tavern.dice.key);
- hmac.update(tavern.dice.text);
- tavern.dice.hex=hmac.digest('hex');
- hmac.end();
- instance_emit(tavern,"dice",{state:"bets",hex:tavern.dice.hex,algorithm:"hmac-sha256"});
- if(gameplay=="hardcore" && Math.random()<0.07 && dice_last_roll) tavern.dice.num=dice_last_roll;
- //server_log("Dice: Bets Starting For: "+tavern.dice.num+" in "+mssince(timer)+"ms");
- }
- }
- if(c>tavern.roulette.next && 0)
- {
- if(tavern.roulette.state=="bets")
- {
- server_log("Roulette: Bets Over");
- tavern.roulette.state="roll";
- tavern.roulette.next=future_s(10);
- }
- else if(tavern.roulette.state=="roll")
- {
- tavern.roulette.roll=floor(Math.random()*37);
- tavern.roulette.state="award";
- tavern.roulette.next=future_s(5);
- server_log("Roulette: Rolled "+tavern.roulette.roll);
- }
- else if(tavern.roulette.state=="award")
- {
- var winners={},roll=tavern.roulette.roll;
- if(roll==0) winners["0"]=1;
- else
- {
- if(roll%2) winners["odd"]=1;
- else winners["even"]=1;
-
- if([2,4,6,8,10,11,13,15,17,20,22,24,26,28,29,31,33,35].indexOf(roll)!=-1) winners["black"]=1;
- else winners["red"]=1;
-
- if(roll<=12) winners["1/3"]=1;
- else if(roll<=24) winners["2/3"]=1;
- else winners["3/3"]=1;
-
- if(roll<=18) winners["1/2"]=1;
- else winners["2/2"]=1;
-
- if((roll%3)==1) winners["3n+1"]=1;
- else if((roll%3)==2) winners["3n+2"]=1;
- else winners["3n"]=1;
- }
- var totals={};
- try{
- for(var id in tavern.roulette.players)
- {
- var player=players[id]; if(!player) continue;
- for(var b_id in player.bets||{})
- {
- var bet=player.bets[b_id]; if(bet.type!="roulette") continue;
- if(!totals[bet.pid]) totals[bet.pid]=0;
- if(winners[bet.odd]) totals[bet.pid]+=bet.gold*tavern.roulette.odds[bet.odd],tavern.roulette.gain-=bet.gold*tavern.roulette.odds[bet.odd];
- else tavern.roulette.gain+=bet.gold;
- // else totals[bet.pid]-=bet.gold;
- if(players[bet.pid])
- {
- delete players[bet.pid].bets[bet.id];
- if(winners[bet.odd]) players[bet.pid].gold+=bet.gold*tavern.roulette.odds[bet.odd];
+ for (var b_id in player.bets || {}) {
+ var bet = player.bets[b_id];
+ if (bet.type != "dice") {
+ continue;
+ }
+ delete players[bet.pid].bets[bet.id];
+ tavern.dice.bets.push(bet);
+ if (
+ (bet.dir == "up" && parseFloat(tavern.dice.num) >= bet.num) ||
+ (bet.dir == "down" && parseFloat(tavern.dice.num) <= bet.num)
+ ) {
+ if (player.type == "merchant") {
+ player.xp += parseInt(bet.edge * 7.2);
+ }
+ player.gold += bet.win - bet.edge;
+ S.gold -= bet.win - bet.edge - bet.gold;
+ if (bet.win - bet.edge - bet.gold >= 12000000) {
+ lstack(S.logs.dice, { name: player.name, gold: bet.win - bet.edge - bet.gold, odds: bet.odds });
+ }
+ } else {
+ if (bet.gold >= 10000000) {
+ lstack(S.logs.dice, { name: player.name, gold: -bet.gold, odds: bet.odds });
+ }
+ S.gold += bet.gold;
}
}
}
- }catch(e){ log_trace("Critical-roulette_win",e); }
- server_log("Roulette: Awards | Gain: "+to_pretty_num(tavern.roulette.gain));
- for(var id in totals)
- {
- var player=players[id]; if(!player) continue;
- if(winners["0"]) player.socket.emit("game_log",{message:"The lucky number is "+roll+" Green",color:"#2E7C2A"});
- else if(winners["red"]) player.socket.emit("game_log",{message:"The lucky number is "+roll+" Red",color:"#911609"});
- else player.socket.emit("game_log",{message:"The lucky number is "+roll+" Black",color:"#5C5D5D"});
- if(!totals[id])
- {
- player.socket.emit("game_log","Better luck next time");
+ instance_emit(tavern, "dice", {
+ state: "lock",
+ num: tavern.dice.num,
+ text: tavern.dice.text,
+ key: tavern.dice.key,
+ });
+ //server_log("Dice: Roll Over - Locking");
+ } else if (tavern.dice.state == "lock") {
+ tavern.dice.state = "suspense";
+ tavern.dice.bets.forEach(function (bet) {
+ var player = players[bet.pid];
+ if (!player) {
+ return;
+ }
+ if (
+ (bet.dir == "up" && parseFloat(tavern.dice.num) >= bet.num) ||
+ (bet.dir == "down" && parseFloat(tavern.dice.num) <= bet.num)
+ ) {
+ player.socket.emit("game_log", {
+ message: "Won: " + to_pretty_num(bet.win) + " gold [" + tavern.dice.num + "]",
+ color: "gold",
+ });
+ player.socket.emit("game_log", {
+ message: "House edge: " + to_pretty_num(bet.edge) + " gold",
+ color: "gray",
+ });
+ instance_emit(tavern, "tavern", {
+ event: "won",
+ name: player.name,
+ type: "dice",
+ num: bet.num,
+ gold: bet.win,
+ dir: bet.dir,
+ net: bet.win - bet.gold - bet.edge,
+ });
+ } else {
+ player.socket.emit("game_log", {
+ message: "Lost: " + to_pretty_num(bet.gold) + " gold [" + tavern.dice.num + "]",
+ color: "gray",
+ });
+ instance_emit(tavern, "tavern", {
+ event: "lost",
+ name: player.name,
+ type: "dice",
+ num: bet.num,
+ gold: bet.gold,
+ dir: bet.dir,
+ });
+ }
+ if (player.xp >= player.max_xp) {
+ resend(player, "reopen");
+ } else {
+ resend(player, "reopen+nc");
+ }
+ });
+ tavern.dice.next = future_s(2);
+ //server_log("Dice: Locked - Suspensing");
+ } else if (tavern.dice.state == "suspense") {
+ var timer = new Date();
+ tavern.info.dice = tavern.dice.state = "bets";
+ tavern.info.seconds = tavern.dice.seconds = 0;
+ tavern.dice.players = {};
+ tavern.dice.bets = [];
+ tavern.dice.num =
+ "" +
+ parseInt(Math.random() * 10) +
+ "" +
+ parseInt(Math.random() * 10) +
+ "." +
+ parseInt(Math.random() * 10) +
+ "" +
+ parseInt(Math.random() * 10);
+ tavern.dice.key = randomStr(20 + parseInt(Math.random() * 20));
+ var initials = "";
+ for (var id in tavern.players) {
+ if (!tavern.players[id].npc) {
+ initials += tavern.players[id].name[0];
+ }
}
- else
- {
- player.socket.emit("game_log",{message:"You've won "+to_pretty_num(totals[id])+" gold",color:"gold"});
+ tavern.dice.text =
+ "Num: " +
+ tavern.dice.num +
+ " Initials: " +
+ initials +
+ " Random: " +
+ randomStr(16 + parseInt(Math.random() * 16));
+ var hmac = crypto.createHmac("sha256", tavern.dice.key);
+ hmac.update(tavern.dice.text);
+ tavern.dice.hex = hmac.digest("hex");
+ hmac.end();
+ instance_emit(tavern, "dice", { state: "bets", hex: tavern.dice.hex, algorithm: "hmac-sha256" });
+ if (gameplay == "hardcore" && Math.random() < 0.07 && dice_last_roll) {
+ tavern.dice.num = dice_last_roll;
}
- resend(player,"reopen+nc");
+ //server_log("Dice: Bets Starting For: "+tavern.dice.num+" in "+mssince(timer)+"ms");
}
- tavern.roulette.state="bets";
- tavern.roulette.next=future_s(25);
- server_log("Roulette: Bets Open");
+ }
+ if (c > tavern.roulette.next && 0) {
+ if (tavern.roulette.state == "bets") {
+ server_log("Roulette: Bets Over");
+ tavern.roulette.state = "roll";
+ tavern.roulette.next = future_s(10);
+ } else if (tavern.roulette.state == "roll") {
+ tavern.roulette.roll = floor(Math.random() * 37);
+ tavern.roulette.state = "award";
+ tavern.roulette.next = future_s(5);
+ server_log("Roulette: Rolled " + tavern.roulette.roll);
+ } else if (tavern.roulette.state == "award") {
+ var winners = {};
+ var roll = tavern.roulette.roll;
+ if (roll == 0) {
+ winners["0"] = 1;
+ } else {
+ if (roll % 2) {
+ winners["odd"] = 1;
+ } else {
+ winners["even"] = 1;
+ }
+
+ if ([2, 4, 6, 8, 10, 11, 13, 15, 17, 20, 22, 24, 26, 28, 29, 31, 33, 35].indexOf(roll) != -1) {
+ winners["black"] = 1;
+ } else {
+ winners["red"] = 1;
+ }
+
+ if (roll <= 12) {
+ winners["1/3"] = 1;
+ } else if (roll <= 24) {
+ winners["2/3"] = 1;
+ } else {
+ winners["3/3"] = 1;
+ }
+
+ if (roll <= 18) {
+ winners["1/2"] = 1;
+ } else {
+ winners["2/2"] = 1;
+ }
+
+ if (roll % 3 == 1) {
+ winners["3n+1"] = 1;
+ } else if (roll % 3 == 2) {
+ winners["3n+2"] = 1;
+ } else {
+ winners["3n"] = 1;
+ }
+ }
+ var totals = {};
+ try {
+ for (var id in tavern.roulette.players) {
+ var player = players[id];
+ if (!player) {
+ continue;
+ }
+ for (var b_id in player.bets || {}) {
+ var bet = player.bets[b_id];
+ if (bet.type != "roulette") {
+ continue;
+ }
+ if (!totals[bet.pid]) {
+ totals[bet.pid] = 0;
+ }
+ if (winners[bet.odd]) {
+ totals[bet.pid] += bet.gold * tavern.roulette.odds[bet.odd];
+ tavern.roulette.gain -= bet.gold * tavern.roulette.odds[bet.odd];
+ } else {
+ tavern.roulette.gain += bet.gold;
+ }
+ // else totals[bet.pid]-=bet.gold;
+ if (players[bet.pid]) {
+ delete players[bet.pid].bets[bet.id];
+ if (winners[bet.odd]) {
+ players[bet.pid].gold += bet.gold * tavern.roulette.odds[bet.odd];
+ }
+ }
+ }
+ }
+ } catch (e) {
+ log_trace("Critical-roulette_win", e);
+ }
+ server_log("Roulette: Awards | Gain: " + to_pretty_num(tavern.roulette.gain));
+ for (var id in totals) {
+ var player = players[id];
+ if (!player) {
+ continue;
+ }
+ if (winners["0"]) {
+ player.socket.emit("game_log", { message: "The lucky number is " + roll + " Green", color: "#2E7C2A" });
+ } else if (winners["red"]) {
+ player.socket.emit("game_log", { message: "The lucky number is " + roll + " Red", color: "#911609" });
+ } else {
+ player.socket.emit("game_log", { message: "The lucky number is " + roll + " Black", color: "#5C5D5D" });
+ }
+ if (!totals[id]) {
+ player.socket.emit("game_log", "Better luck next time");
+ } else {
+ player.socket.emit("game_log", {
+ message: "You've won " + to_pretty_num(totals[id]) + " gold",
+ color: "gold",
+ });
+ }
+ resend(player, "reopen+nc");
+ }
+ tavern.roulette.state = "bets";
+ tavern.roulette.next = future_s(25);
+ server_log("Roulette: Bets Open");
+ }
+ }
+ tavern.poker.rooms.forEach(function (room) {
+ if (room.state == "shuffle") {
+ room.cards = [];
+ for (var i = 1; i <= 52; i++) {
+ room.cards.push(i);
+ }
+ shuffle(room.cards);
+ }
+ });
+ } catch (e) {
+ log_trace("Critical-tavern_loop", e);
+ }
+}
+
+function create_npc(npc, map_def, instance) {
+ var entity = {
+ speed: npc.speed || 20,
+ attack: npc.attack || 100,
+ range: npc.range || 40,
+ level: npc.level || 100,
+ hp: npc.hp || 1200,
+ max_hp: npc.hp || 1200,
+ armor: 500,
+ mp: 2000,
+ a: {},
+ xp: 0,
+ pdps: 0, // once got killed by a blaster ... [07/04/21]
+ skin: npc.skin,
+ name: npc.name,
+ red_zone: 0,
+ in: instance.name,
+ map: instance.map,
+ def: npc,
+ npc: map_def.id,
+ ntype: map_def.id,
+ is_player: true,
+ is_npc: true,
+ type: npc["class"] || "merchant",
+ id: "$" + npc.name,
+ gold: 0,
+ items: [],
+ citems: [],
+ cid: 0,
+ u: true,
+ citizen: true,
+ luckm: 1, // for loot_all_monsters
+ s: {},
+ c: {},
+ q: {},
+ p: {},
+ m: 0,
+ slots: {},
+ bets: {},
+ vision: [0, 0],
+ socket: false_socket,
+ cx: npc.cx || {},
+ base: { h: 8, v: 7, vn: 2 },
+ last: { move: new Date(), attack: really_old, attacked: really_old },
+ delay: npc.delay || 600,
+ d_multiplier: 1,
+ steps: npc.steps || 40,
+ };
+
+ if (npc.slots) {
+ entity.slots = npc.slots;
+ }
+ if (npc.projectile) {
+ entity.projectile = npc.projectile;
+ }
+
+ if (map_def.positions) {
+ entity.x = map_def.positions[0][0];
+ entity.y = map_def.positions[0][1];
+ entity.positions = map_def.positions;
+ } else {
+ entity.x = map_def.position[0];
+ entity.y = map_def.position[1];
+ if (npc.type == "fullstatic" && map_def.position.length == 3) {
+ entity.direction = map_def.position[2];
}
}
- tavern.poker.rooms.forEach(function(room){
- if(room.state=="shuffle")
- {
- room.cards=[];
- for(var i=1;i<=52;i++) room.cards.push(i);
- shuffle(room.cards);
- }
- });
-}catch(e){ log_trace("Critical-tavern_loop",e);} }
-
-function create_npc(npc,map_def,instance)
-{
- var entity={
- speed:npc.speed||20,
- attack:npc.attack||100,
- range:npc.range||40,
- level:npc.level||100,hp:npc.hp||1200,max_hp:npc.hp||1200,armor:500,mp:2000,
- a:{},
- xp:0, pdps:0, // once got killed by a blaster ... [07/04/21]
- skin:npc.skin,name:npc.name,
- red_zone:0,
- in:instance.name,map:instance.map,
- def:npc,
- npc:map_def.id,
- ntype:map_def.id,is_player:true,is_npc:true,
- type:npc['class']||"merchant",
- id:"$"+npc.name,
- gold:0,items:[],citems:[],
- cid:0,u:true,
- citizen:true,
- luckm:1, // for loot_all_monsters
- s:{},c:{},q:{},p:{},m:0,slots:{},bets:{},
- vision:[0,0],socket:false_socket,cx:npc.cx||{},
- base:{h:8,v:7,vn:2},
- last:{move:new Date(),attack:really_old,attacked:really_old},
- delay:npc.delay||600,d_multiplier:1,steps:npc.steps||40,
+ if (map_def.boundary) {
+ entity.boundary = map_def.boundary;
+ }
+ if (map_def.loop) {
+ entity.going_x = entity.x;
+ entity.going_y = entity.y;
+ start_moving_element(entity);
+ entity.loop = true;
+ entity.last_m = 0;
}
- if(npc.slots) entity.slots=npc.slots;
- if(npc.projectile) entity.projectile=npc.projectile;
-
- if(map_def.positions) entity.x=map_def.positions[0][0],entity.y=map_def.positions[0][1],entity.positions=map_def.positions;
- else
- {
- entity.x=map_def.position[0],entity.y=map_def.position[1];
- if(npc.type=="fullstatic" && map_def.position.length==3) entity.direction=map_def.position[2];
+ if (npc.role == "citizen" || npc.moving) {
+ entity.movable = true;
}
-
- if(map_def.boundary) entity.boundary=map_def.boundary;
- if(map_def.loop)
- {
- entity.going_x=entity.x,entity.going_y=entity.y; start_moving_element(entity);
- entity.loop=true,entity.last_m=0;
- }
-
- if(npc.role=="citizen" || npc.moving)
- entity.movable=true;
return entity;
}
-function create_instance(name,map_name,args)
-{
- if(!map_name) map_name=name;
- if(!smap_data[map_name] && smap_data[map_name]!=-1) server_bfs(map_name);
- if(!args) args={};
- var instance={players:{},monsters:{},observers:{},map:map_name,allow:true,name:name,pmap:{},rage_list:[],last_update:future_ms(parseInt(Math.random()*30)),last_player:future_s(240),npcs:0,paused:false,info:{},operators:1};
- instances[name]=instance;
- if(args.solo) instance.solo=args.solo;
- if(args.pvp) instance.pvp=true,instance.allow=false;
- if(args.event) instance.allow=false;
- var map=G.maps[map_name];
- if(map.mount && gameplay=="normal") instance.mount=true;
- for(var i=0;i<(map.monsters||[]).length;i++)
- {
- var map_def=map.monsters[i];
- if(map_def.special) continue;
- if(map_def.rage)
- {
- map_def.id=randomStr(5);
+function create_instance(name, map_name, args) {
+ if (!map_name) {
+ map_name = name;
+ }
+ if (!smap_data[map_name] && smap_data[map_name] != -1) {
+ server_bfs(map_name);
+ }
+ if (!args) {
+ args = {};
+ }
+ var instance = {
+ players: {},
+ monsters: {},
+ observers: {},
+ map: map_name,
+ allow: true,
+ name: name,
+ pmap: {},
+ rage_list: [],
+ last_update: future_ms(parseInt(Math.random() * 30)),
+ last_player: future_s(240),
+ npcs: 0,
+ paused: false,
+ info: {},
+ operators: 1,
+ };
+ instances[name] = instance;
+ if (args.solo) {
+ instance.solo = args.solo;
+ }
+ if (args.pvp) {
+ instance.pvp = true;
+ instance.allow = false;
+ }
+ if (args.event) {
+ instance.allow = false;
+ }
+ var map = G.maps[map_name];
+ if (map.mount && gameplay == "normal") {
+ instance.mount = true;
+ }
+ for (var i = 0; i < (map.monsters || []).length; i++) {
+ var map_def = map.monsters[i];
+ if (map_def.special) {
+ continue;
+ }
+ if (map_def.rage) {
+ map_def.id = randomStr(5);
instance.rage_list.push(map_def);
}
- for(var j=0;j=12 is a must.");
+ map.spawns.forEach(function (spawn) {
+ var cdist = closest_line(map_name, spawn[0], spawn[1]);
+ if (cdist < 12) {
+ console.log(
+ "Spawn [" + map_name + "," + spawn[0] + "," + spawn[1] + "] is " + cdist + " close to a line! >=12 is a must.",
+ );
+ }
});
- server_log("Created an instance of "+instances[name].map,1);
+ server_log("Created an instance of " + instances[name].map, 1);
return instance;
}
-function pause_instance(instance)
-{
- server_log("Paused: "+instance.name);
- instance.paused=true;
+function pause_instance(instance) {
+ server_log("Paused: " + instance.name);
+ instance.paused = true;
}
-function resume_instance(instance)
-{
- if(!instance.paused) return;
+function resume_instance(instance) {
+ if (!instance.paused) {
+ return;
+ }
// server_log("Resumed: "+instance.name);
- instance.paused=false;
+ instance.paused = false;
update_instance(instance);
}
-function destroy_instance(name)
-{
- for(var id in instances[name].players)
- {
- var player=instances[name].players[id];
- if(player.npc) continue;
- if(player.state && !player.state.restored && instances[player.state.map] && !instances[player.state.map].mount && player.in!=name)
- transport_player_to(player,player.state.map,[player.state.x,player.state.y]);
- else transport_player_to(player,"main");
+function destroy_instance(name) {
+ for (var id in instances[name].players) {
+ var player = instances[name].players[id];
+ if (player.npc) {
+ continue;
+ }
+ if (
+ player.state &&
+ !player.state.restored &&
+ instances[player.state.map] &&
+ !instances[player.state.map].mount &&
+ player.in != name
+ ) {
+ transport_player_to(player, player.state.map, [player.state.x, player.state.y]);
+ } else {
+ transport_player_to(player, "main");
+ }
restore_state(player);
- resend(player,"cid+reopen"); // reopen for abtesting
+ resend(player, "cid+reopen"); // reopen for abtesting
}
- for(var id in instances[name].monsters)
- {
- remove_monster(instances[name].monsters[id],{silent:true}); // to make sure targets are always updated
+ for (var id in instances[name].monsters) {
+ remove_monster(instances[name].monsters[id], { silent: true }); // to make sure targets are always updated
}
- server_log("Deleted an instance of "+instances[name].map,1);
+ server_log("Deleted an instance of " + instances[name].map, 1);
delete instances[name];
}
-function spawn_special_monster(type)
-{
- if(type=="pinkgoo")
- {
- var packs=[];
- ["main","cave","halloween","winterland"].forEach(function(m){
- G.maps[m].monsters.forEach(function(p){
- if(!p.boundaries) packs.push({"type":"pinkgoo",boundary:p.boundary,count:1,i:m}); // comment boundary out next year [09/02/19]
+function spawn_special_monster(type) {
+ if (type == "pinkgoo") {
+ var packs = [];
+ ["main", "cave", "halloween", "winterland"].forEach(function (m) {
+ G.maps[m].monsters.forEach(function (p) {
+ if (!p.boundaries) {
+ packs.push({ type: "pinkgoo", boundary: p.boundary, count: 1, i: m });
+ } // comment boundary out next year [09/02/19]
});
});
- var pack=packs[floor(Math.random()*packs.length)];
- pack.gold=D.monster_gold.pinkgoo;
- server_log("Love Goo: "+JSON.stringify(pack));
- new_monster(pack.i,pack);
- broadcast("game_event",{name:"pinkgoo",map:pack.i});
+ var pack = packs[floor(Math.random() * packs.length)];
+ pack.gold = D.monster_gold.pinkgoo;
+ server_log("Love Goo: " + JSON.stringify(pack));
+ new_monster(pack.i, pack);
+ broadcast("game_event", { name: "pinkgoo", map: pack.i });
}
- if(type=="crabxx")
- {
- var pack=null;
- ["main"].forEach(function(m){
- G.maps[m].monsters.forEach(function(p){
- if(p.type=="crabx") pack={"type":"crabxx",boundary:p.boundary,count:1,i:m};
+ if (type == "crabxx") {
+ var pack = null;
+ ["main"].forEach(function (m) {
+ G.maps[m].monsters.forEach(function (p) {
+ if (p.type == "crabx") {
+ pack = { type: "crabxx", boundary: p.boundary, count: 1, i: m };
+ }
});
});
- pack.gold=D.monster_gold.crabxx;
- server_log("Crab XX: "+JSON.stringify(pack));
- new_monster(pack.i,pack);
- broadcast("game_event",{name:"crabxx",map:pack.i});
+ pack.gold = D.monster_gold.crabxx;
+ server_log("Crab XX: " + JSON.stringify(pack));
+ new_monster(pack.i, pack);
+ broadcast("game_event", { name: "crabxx", map: pack.i });
}
- if(type=="snowman")
- {
- var packs=[];
- ["winterland"].forEach(function(m){
- G.maps[m].monsters.forEach(function(p){
- if(!p.boundaries) packs.push({"type":"snowman",boundary:p.boundary,count:1,i:m});
+ if (type == "snowman") {
+ var packs = [];
+ ["winterland"].forEach(function (m) {
+ G.maps[m].monsters.forEach(function (p) {
+ if (!p.boundaries) {
+ packs.push({ type: "snowman", boundary: p.boundary, count: 1, i: m });
+ }
});
});
- var pack=packs[floor(Math.random()*packs.length)];
- pack.gold=D.monster_gold.snowman;
- pack={"type":"snowman",boundary:[682,-967,1482,-779],count:1,i:"winterland"}
- server_log("Snowman: "+JSON.stringify(pack));
- new_monster(pack.i,pack);
- broadcast("game_event",{name:"snowman",map:pack.i,x:900,y:-800});
+ var pack = packs[floor(Math.random() * packs.length)];
+ pack.gold = D.monster_gold.snowman;
+ pack = { type: "snowman", boundary: [682, -967, 1482, -779], count: 1, i: "winterland" };
+ server_log("Snowman: " + JSON.stringify(pack));
+ new_monster(pack.i, pack);
+ broadcast("game_event", { name: "snowman", map: pack.i, x: 900, y: -800 });
}
- if(type=="dragold")
- {
- var packs=[];
- var pack=packs[floor(Math.random()*packs.length)];
- pack={"type":"dragold",boundary:[1018,-940,1385,-624],count:1,i:"cave"};
- pack.gold=100000;
- server_log("Dragold: "+JSON.stringify(pack));
- new_monster(pack.i,pack);
- broadcast("game_event",{name:"dragold",map:pack.i,x:900,y:-800});
+ if (type == "dragold") {
+ var packs = [];
+ var pack = packs[floor(Math.random() * packs.length)];
+ pack = { type: "dragold", boundary: [1018, -940, 1385, -624], count: 1, i: "cave" };
+ pack.gold = 100000;
+ server_log("Dragold: " + JSON.stringify(pack));
+ new_monster(pack.i, pack);
+ broadcast("game_event", { name: "dragold", map: pack.i, x: 900, y: -800 });
}
- if(type=="franky")
- {
- var map="level2w";
- var pack={"type":"franky",boundary:G.maps[map].monsters[0].boundary,count:1,i:map};
- pack.gold=D.monster_gold.franky;
- server_log("Franky: "+JSON.stringify(pack));
- new_monster(pack.i,pack);
- broadcast("game_event",{name:"franky",map:pack.i,x:G.maps[map].monsters[0].boundary[0],y:G.maps[map].monsters[0].boundary[1]});
+ if (type == "franky") {
+ var map = "level2w";
+ var pack = { type: "franky", boundary: G.maps[map].monsters[0].boundary, count: 1, i: map };
+ pack.gold = D.monster_gold.franky;
+ server_log("Franky: " + JSON.stringify(pack));
+ new_monster(pack.i, pack);
+ broadcast("game_event", {
+ name: "franky",
+ map: pack.i,
+ x: G.maps[map].monsters[0].boundary[0],
+ y: G.maps[map].monsters[0].boundary[1],
+ });
}
- if(type=="icegolem")
- {
- var map="winterland";
- var pack={"type":"icegolem",boundary:[782.25,395.96,888.71,450.28],count:1,i:map,roam:true};
- pack.gold=D.monster_gold.icegolem;
- server_log("Ice Golem: "+JSON.stringify(pack));
- new_monster(pack.i,pack);
- broadcast("game_event",{name:"icegolem",map:pack.i,x:pack.boundary[0],y:pack.boundary[1]});
+ if (type == "icegolem") {
+ var map = "winterland";
+ var pack = { type: "icegolem", boundary: [782.25, 395.96, 888.71, 450.28], count: 1, i: map, roam: true };
+ pack.gold = D.monster_gold.icegolem;
+ server_log("Ice Golem: " + JSON.stringify(pack));
+ new_monster(pack.i, pack);
+ broadcast("game_event", { name: "icegolem", map: pack.i, x: pack.boundary[0], y: pack.boundary[1] });
}
- if(type=="mrpumpkin" || type=="mrgreen" || type=="grinch")
- {
- var pack={},map="none";
- for(var mname in G.maps)
- {
- var def=G.maps[mname];
- if(def.ignore) continue;
- (def.monsters||[]).forEach(function(p)
- {
- if(p.type==type) pack=p,map=mname;
+ if (type == "mrpumpkin" || type == "mrgreen" || type == "grinch") {
+ var pack = {};
+ var map = "none";
+ for (var mname in G.maps) {
+ var def = G.maps[mname];
+ if (def.ignore) {
+ continue;
+ }
+ (def.monsters || []).forEach(function (p) {
+ if (p.type == type) {
+ pack = p;
+ map = mname;
+ }
});
}
- server_log(G.monsters[type].name+": "+JSON.stringify(pack));
- var monster=new_monster(map,pack);
- broadcast("game_event",{name:type,map:map,x:pack.boundary[0],y:pack.boundary[1]});
- if(type=="grinch") monster.extra_gold=12000000;
+ server_log(G.monsters[type].name + ": " + JSON.stringify(pack));
+ var monster = new_monster(map, pack);
+ broadcast("game_event", { name: type, map: map, x: pack.boundary[0], y: pack.boundary[1] });
+ if (type == "grinch") {
+ monster.extra_gold = 12000000;
+ }
}
- if(type=="slenderman")
- {
- var packs=[];
- var m=random_one(["cave","halloween","spookytown"])
- var p=random_place(m);
- var pack={"type":"slenderman",boundary:[p.x,p.y,p.x,p.y],count:1,i:m};
- pack.gold=D.monster_gold.slenderman;
+ if (type == "slenderman") {
+ var packs = [];
+ var m = random_one(["cave", "halloween", "spookytown"]);
+ var p = random_place(m);
+ var pack = { type: "slenderman", boundary: [p.x, p.y, p.x, p.y], count: 1, i: m };
+ pack.gold = D.monster_gold.slenderman;
//server_log("Love Goo: "+JSON.stringify(pack));
- var monster=new_monster(pack.i,pack);
- broadcast("game_event",{name:"slenderman",map:pack.i});
+ var monster = new_monster(pack.i, pack);
+ broadcast("game_event", { name: "slenderman", map: pack.i });
}
- if(type=="tiger")
- {
- var packs=[];
- var m=random_one(["cave","main"])
- var p=random_place(m);
- var pack={"type":"tiger",boundary:[p.x,p.y,p.x,p.y],count:1,i:m};
- pack.gold=D.monster_gold.tiger;
+ if (type == "tiger") {
+ var packs = [];
+ var m = random_one(["cave", "main"]);
+ var p = random_place(m);
+ var pack = { type: "tiger", boundary: [p.x, p.y, p.x, p.y], count: 1, i: m };
+ pack.gold = D.monster_gold.tiger;
//server_log("Love Goo: "+JSON.stringify(pack));
- var monster=new_monster(pack.i,pack);
- broadcast("game_event",{name:"tiger",map:pack.i});
+ var monster = new_monster(pack.i, pack);
+ broadcast("game_event", { name: "tiger", map: pack.i });
}
- if(type=="wabbit")
- {
- var packs=[];
- ["main","cave","halloween","winterland","tunnel","mansion","winter_cave"].forEach(function(m){
- G.maps[m].monsters.forEach(function(p){
- if(!p.boundaries) packs.push({"type":"wabbit",boundary:p.boundary,count:1,i:m,roam:true});
+ if (type == "wabbit") {
+ var packs = [];
+ ["main", "cave", "halloween", "winterland", "tunnel", "mansion", "winter_cave"].forEach(function (m) {
+ G.maps[m].monsters.forEach(function (p) {
+ if (!p.boundaries) {
+ packs.push({ type: "wabbit", boundary: p.boundary, count: 1, i: m, roam: true });
+ }
});
});
- var pack=packs[floor(Math.random()*packs.length)];
- pack.gold=D.monster_gold.wabbit;
+ var pack = packs[floor(Math.random() * packs.length)];
+ pack.gold = D.monster_gold.wabbit;
//server_log("Love Goo: "+JSON.stringify(pack));
- new_monster(pack.i,pack);
- broadcast("game_event",{name:"wabbit",map:pack.i});
+ new_monster(pack.i, pack);
+ broadcast("game_event", { name: "wabbit", map: pack.i });
}
- if(type=="goldenbat")
- {
- var packs=[];
- ["cave"].forEach(function(m){
- G.maps[m].monsters.forEach(function(p){
- if(!p.boundaries) packs.push({"type":"goldenbat",boundary:p.boundary,count:1,i:m,roam:true});
+ if (type == "goldenbat") {
+ var packs = [];
+ ["cave"].forEach(function (m) {
+ G.maps[m].monsters.forEach(function (p) {
+ if (!p.boundaries) {
+ packs.push({ type: "goldenbat", boundary: p.boundary, count: 1, i: m, roam: true });
+ }
});
});
- var pack=packs[floor(Math.random()*packs.length)];
- pack.gold=D.monster_gold.goldenbat;
+ var pack = packs[floor(Math.random() * packs.length)];
+ pack.gold = D.monster_gold.goldenbat;
//server_log("Love Goo: "+JSON.stringify(pack));
- new_monster(pack.i,pack);
+ new_monster(pack.i, pack);
// broadcast("game_event",{name:"goldenbat",map:pack.i});
}
- if(type=="cutebee")
- {
- var packs=[];
- ["main"].forEach(function(m){
- G.maps[m].monsters.forEach(function(p){
- if(!p.boundaries) packs.push({"type":"cutebee",boundary:p.boundary,count:1,i:m,roam:true});
+ if (type == "cutebee") {
+ var packs = [];
+ ["main"].forEach(function (m) {
+ G.maps[m].monsters.forEach(function (p) {
+ if (!p.boundaries) {
+ packs.push({ type: "cutebee", boundary: p.boundary, count: 1, i: m, roam: true });
+ }
});
});
- var pack=packs[floor(Math.random()*packs.length)];
- pack.gold=D.monster_gold.cutebee;
+ var pack = packs[floor(Math.random() * packs.length)];
+ pack.gold = D.monster_gold.cutebee;
//server_log("Love Goo: "+JSON.stringify(pack));
- new_monster(pack.i,pack);
+ new_monster(pack.i, pack);
}
}
-function collect_signups(event)
-{
- var names=[],toggle=0;
- for(var name in signups) names.push(name); shuffle(names);
- names.forEach(function(name){
- var player=players[name_to_id[name]]; if(!player) return;
+function collect_signups(event) {
+ var names = [];
+ var toggle = 0;
+ for (var name in signups) {
+ names.push(name);
+ }
+ shuffle(names);
+ names.forEach(function (name) {
+ var player = players[name_to_id[name]];
+ if (!player) {
+ return;
+ }
- if(event=="abtesting") player.team=(toggle==1&&"A")||"B",toggle=1-toggle;
+ if (event == "abtesting") {
+ player.team = (toggle == 1 && "A") || "B";
+ toggle = 1 - toggle;
+ }
- if(event=="abtesting" && player.team=="A") transport_player_to(player,event,2),resend(player,"cid");
- else if(event=="abtesting" && player.team=="B") transport_player_to(player,event,3),resend(player,"cid");
- else transport_player_to(player,event);
+ if (event == "abtesting" && player.team == "A") {
+ transport_player_to(player, event, 2);
+ resend(player, "cid");
+ } else if (event == "abtesting" && player.team == "B") {
+ transport_player_to(player, event, 3);
+ resend(player, "cid");
+ } else {
+ transport_player_to(player, event);
+ }
});
}
-var last_daily=null;
-function event_loop()
-{ try {
- var c=new Date(),ch=(c.getUTCHours()+24+E.schedule.time_offset)%24;
- var change=false;
- if(ch>=0 && ch<=5) E.schedule.night=true;
- else E.schedule.night=false;
-
- E.schedule.dailies.forEach(function(h){
- if(ch==h && last_daily!=h && msince(server_start)>2)
- {
- last_daily=h;
- var event=dailies.shift();
- dailies.push(event);
- events[event]=true;
+var last_daily = null;
+function event_loop() {
+ try {
+ var c = new Date();
+ var ch = (c.getUTCHours() + 24 + E.schedule.time_offset) % 24;
+ var change = false;
+ if (ch >= 0 && ch <= 5) {
+ E.schedule.night = true;
+ } else {
+ E.schedule.night = false;
}
- });
- E.schedule.nightlies.forEach(function(h){
- if(ch==h && last_daily!=h && msince(server_start)>2)
- {
- last_daily=h;
- var event=nightlies.shift();
- nightlies.push(event);
- events[event]=true;
- }
- });
-
- if(events.halloween)
- {
- var s=get_monster("slenderman");
- if(s)
- {
- var p=false;
- for(var id in projectiles)
- {
- if(projectiles[id].target==s) p=true;
+ E.schedule.dailies.forEach(function (h) {
+ if (ch == h && last_daily != h && msince(server_start) > 2) {
+ last_daily = h;
+ var event = dailies.shift();
+ dailies.push(event);
+ events[event] = true;
}
- if(!s.last_jump || msince(s.last_jump)>2) p=true;
- for(var name in instances[s.in].players)
- {
- var player=instances[s.in].players[name];
- if(p || !player.s.invis && distance(player,s)<600)
- {
- xy_emit(s,"disappear",{id:s.id});
- delete instances[s.in].monsters[s.id];
- s.oin=s.in=s.map=random_one(["spookytown","halloween","cave"]);
- instances[s.in].monsters[s.id]=s;
- var p=random_place(s.map);
- s.moving=false; s.abs=true;
- s.map_def.boundary=[p.x,p.y,p.x,p.y]; s.map_def.i=s.map;
- s.x=p.x;
- s.y=p.y;
- s.u=true; s.cid++;
- s.last_jump=new Date();
- break;
+ });
+
+ E.schedule.nightlies.forEach(function (h) {
+ if (ch == h && last_daily != h && msince(server_start) > 2) {
+ last_daily = h;
+ var event = nightlies.shift();
+ nightlies.push(event);
+ events[event] = true;
+ }
+ });
+
+ if (events.halloween) {
+ var s = get_monster("slenderman");
+ if (s) {
+ var p = false;
+ for (var id in projectiles) {
+ if (projectiles[id].target == s) {
+ p = true;
+ }
+ }
+ if (!s.last_jump || msince(s.last_jump) > 2) {
+ p = true;
+ }
+ for (var name in instances[s.in].players) {
+ var player = instances[s.in].players[name];
+ if (p || (!player.s.invis && distance(player, s) < 600)) {
+ xy_emit(s, "disappear", { id: s.id });
+ delete instances[s.in].monsters[s.id];
+ s.oin = s.in = s.map = random_one(["spookytown", "halloween", "cave"]);
+ instances[s.in].monsters[s.id] = s;
+ var p = random_place(s.map);
+ s.moving = false;
+ s.abs = true;
+ s.map_def.boundary = [p.x, p.y, p.x, p.y];
+ s.map_def.i = s.map;
+ s.x = p.x;
+ s.y = p.y;
+ s.u = true;
+ s.cid++;
+ s.last_jump = new Date();
+ break;
+ }
}
}
}
- }
- if(monster_c.tiger)
- {
- var m=get_monster("tiger");
- var ps=[];
- for(var id in players) ps.push(players[id]);
- var player=random_one(ps);
- var spot=null,p=false;
- for(var id in projectiles)
- {
- if(projectiles[id].target==m && projectiles[id].attack>999) p=true;
- }
- if(p || Math.random()<0.01)
- {
- if(player) spot=safe_xy_nearby(player.map,player.x,player.y);
- if(m && player && player.in==player.map && spot && !G.maps[player.map].mount && !player.s.hopsickness && player.p.home==region+server_name)
- {
- xy_emit(m,"disappear",{id:m.id});
- delete instances[m.in].monsters[m.id];
- m.oin=m.in=m.map=player.map;
- instances[m.in].monsters[m.id]=m;
- m.moving=false; m.abs=true;
- m.x=spot.x; m.y=spot.y;
- m.map_def.boundary=[m.x,m.y,m.x,m.y]; m.map_def.i=m.map;
- m.u=true; m.cid++;
- m.last_jump=new Date();
+ if (monster_c.tiger) {
+ var m = get_monster("tiger");
+ var ps = [];
+ for (var id in players) {
+ ps.push(players[id]);
}
- }
- }
- ["crabxx","franky","icegolem"].forEach(function(name){
- if(events[name])
- {
-
- var monster=get_monster(name);
- if(!monster && monster_c[name]) return; // irregular move
- if(!timers[name])
- {
- timers[name]=future_s(G.events[name].duration);
- spawn_special_monster(name);
- }
- else if(c>timers[name] && (!monster || !monster.last.attacked || ssince(monster.last.attacked)>20))
- {
- if(monster) remove_monster(monster,{method:"disappear"});
- broadcast("notice",{message:G.monsters[name].name+" Event is over ..."});
- events[name]=false; change=true; delete E[name]; delete timers[name];
- }
- else
- {
- var monster=get_monster(name)
- if(!monster)
- {
- broadcast("notice",{message:G.monsters[name].name+" has been defeated!"});
- events[name]=false; change=true; delete E[name]; delete timers[name];
+ var player = random_one(ps);
+ var spot = null;
+ var p = false;
+ for (var id in projectiles) {
+ if (projectiles[id].target == m && projectiles[id].attack > 999) {
+ p = true;
}
- else
- {
- if(!E[name]) change=true;
- E[name]={live:true,map:monster.map,hp:monster.hp,max_hp:monster.max_hp,target:monster.target,x:monster.x,y:monster.y,end:timers[name]};
- if(name=="crabxx")
- {
- var big=get_monster("crabx");
- if(monster && big && !monster["1hp"])
- {
- monster["1hp"]=true;
- monster.s={};
- monster.cid++; monster.u=true;
+ }
+ if (p || Math.random() < 0.01) {
+ if (player) {
+ spot = safe_xy_nearby(player.map, player.x, player.y);
+ }
+ if (
+ m &&
+ player &&
+ player.in == player.map &&
+ spot &&
+ !G.maps[player.map].mount &&
+ !player.s.hopsickness &&
+ player.p.home == region + server_name
+ ) {
+ xy_emit(m, "disappear", { id: m.id });
+ delete instances[m.in].monsters[m.id];
+ m.oin = m.in = m.map = player.map;
+ instances[m.in].monsters[m.id] = m;
+ m.moving = false;
+ m.abs = true;
+ m.x = spot.x;
+ m.y = spot.y;
+ m.map_def.boundary = [m.x, m.y, m.x, m.y];
+ m.map_def.i = m.map;
+ m.u = true;
+ m.cid++;
+ m.last_jump = new Date();
+ }
+ }
+ }
+ ["crabxx", "franky", "icegolem"].forEach(function (name) {
+ if (events[name]) {
+ var monster = get_monster(name);
+ if (!monster && monster_c[name]) {
+ return;
+ } // irregular move
+ if (!timers[name]) {
+ timers[name] = future_s(G.events[name].duration);
+ spawn_special_monster(name);
+ } else if (c > timers[name] && (!monster || !monster.last.attacked || ssince(monster.last.attacked) > 20)) {
+ if (monster) {
+ remove_monster(monster, { method: "disappear" });
+ }
+ broadcast("notice", { message: G.monsters[name].name + " Event is over ..." });
+ events[name] = false;
+ change = true;
+ delete E[name];
+ delete timers[name];
+ } else {
+ var monster = get_monster(name);
+ if (!monster) {
+ broadcast("notice", { message: G.monsters[name].name + " has been defeated!" });
+ events[name] = false;
+ change = true;
+ delete E[name];
+ delete timers[name];
+ } else {
+ if (!E[name]) {
+ change = true;
}
- else if(monster && !big && monster["1hp"])
- {
- monster["1hp"]=false;
- monster.cid++; monster.u=true;
+ E[name] = {
+ live: true,
+ map: monster.map,
+ hp: monster.hp,
+ max_hp: monster.max_hp,
+ target: monster.target,
+ x: monster.x,
+ y: monster.y,
+ end: timers[name],
+ };
+ if (name == "crabxx") {
+ var big = get_monster("crabx");
+ if (monster && big && !monster["1hp"]) {
+ monster["1hp"] = true;
+ monster.s = {};
+ monster.cid++;
+ monster.u = true;
+ } else if (monster && !big && monster["1hp"]) {
+ monster["1hp"] = false;
+ monster.cid++;
+ monster.u = true;
+ }
}
}
}
}
+ });
+
+ if (events.goobrawl) {
+ if (!timers.goobrawl) {
+ timers.goobrawl = future_s(G.events.goobrawl.duration);
+ E.goobrawl = { end: timers.goobrawl };
+ change = true;
+ //create_instance("goobrawl","goobrawl",{event:true});
+ // collect_signups("goobrawl");
+ broadcast("notice", { message: "Goo Brawl has begun!" });
+ } else if (c > timers.goobrawl) {
+ events.goobrawl = false;
+ delete E.goobrawl;
+ delete timers.goobrawl;
+ change = true;
+ //destroy_instance("goobrawl");
+ broadcast("notice", { message: "Goo Brawl is over, hope you had fun!" });
+ } else if (instances.goobrawl && Object.keys(instances.goobrawl.monsters).length < 6 && Math.random() < 0.3) {
+ if (Math.random() < 0.01) {
+ var data = clone(G.maps.goobrawl.monsters[0]);
+ data.type = "rgoo";
+ var m = new_monster("goobrawl", data);
+ //m.s.filter={ms:9999999,name:"scale",scale:2};
+ } else {
+ var data = clone(G.maps.goobrawl.monsters[0]);
+ data.type = "bgoo";
+ var m = new_monster("goobrawl", data);
+ m.skin = random_one(["goo0", "goo1", "goo2", "goo3", "goo4", "goo5", "goo6"]);
+ // m.drops=[[0.5,"funtoken"]];
+ m.u = true;
+ m.cid++;
+ }
+ }
+ }
+
+ if (gameplay == "hardcore" && ssince(timers.hardcore) > 64) {
+ timers.hardcore = new Date();
+ for (var id in instances.woffice.players) {
+ var player = instances.woffice.players[id];
+ var gold = 480000;
+ player.gold += gold;
+ player.socket.emit("game_log", "Received " + to_pretty_num(gold) + " gold");
+ player.socket.emit("disappearing_text", {
+ message: "+" + gold,
+ x: player.x,
+ y: player.y - 32,
+ args: { color: "+gold", size: "large" },
+ });
+ resend(player, "reopen");
+ }
+ }
+
+ if (events.goldenbat && stats.kills.bat > edges.next_goldenbat) {
+ edges.next_goldenbat += parseInt(events.goldenbat * Math.random());
+ spawn_special_monster("goldenbat");
+ }
+
+ if (events.cutebee && stats.kills.bee > edges.next_cutebee) {
+ edges.next_cutebee += parseInt(events.cutebee * Math.random());
+ spawn_special_monster("cutebee");
+ }
+
+ if (!events.holidayseason && events.snowman && !monster_c.snowman) {
+ if (!timers.snowman) {
+ timers.snowman = future_s(events.snowman * 60);
+ } else if (timers.snowman && c > timers.snowman) {
+ timers.snowman = 0;
+ spawn_special_monster("snowman");
+ }
+ }
+
+ var eventmap = [
+ ["halloween", "mrpumpkin"],
+ ["halloween", "mrgreen"],
+ ["halloween", "slenderman", true],
+ ["holidayseason", "grinch"],
+ ["holidayseason", "snowman"],
+ ["lunarnewyear", "dragold"],
+ ["lunarnewyear", "tiger", true],
+ ["valentines", "pinkgoo", true],
+ ["egghunt", "wabbit", true],
+ ];
+ eventmap.forEach(function (s) {
+ if (events[s[0]] && !monster_c[s[1]]) {
+ if (!timers[s[1]]) {
+ if (timers[s[1]] !== 0) {
+ timers[s[1]] = future_s(120);
+ } else {
+ timers[s[1]] = future_s(G.monsters[s[1]].respawn);
+ }
+ E[s[1]] = { live: false, spawn: timers[s[1]] };
+ broadcast_e();
+ } else if (timers[s[1]] && c > timers[s[1]]) {
+ timers[s[1]] = 0;
+ spawn_special_monster(s[1]);
+ var m = get_monsters(s[1])[0];
+ var data = { live: true, map: m.map, hp: m.hp, max_hp: m.max_hp, target: m.target };
+ if (!s[2]) {
+ data.x = m.x;
+ data.y = m.y;
+ }
+ E[s[1]] = data;
+ broadcast_e();
+ }
+ }
+ });
+ ["holidayseason", "halloween", "lunarnewyear", "valentines", "egghunt"].forEach(function (event) {
+ if (events[event]) {
+ E[event] = true;
+ } else if (E[event]) {
+ delete E[event];
+ }
+ });
+ ["snowman", "grinch", "dragold", "mrpumpkin", "mrgreen", "wabbit", "pinkgoo", "tiger"].forEach(function (type) {
+ if (E[type] && !monster_c[type]) {
+ delete E[type]; // [20/01/23]
+ change = true;
+ }
+ });
+ for (var name in instances) {
+ for (var id in instances[name].monsters) {
+ var monster = instances[name].monsters[id];
+ ["tiger"].forEach(function (type) {
+ if (monster.type == type) {
+ E[type] = { live: true, map: monster.map, hp: monster.hp, max_hp: monster.max_hp, target: monster.target };
+ }
+ });
+ ["snowman", "grinch", "dragold", "mrpumpkin", "mrgreen", "wabbit", "pinkgoo"].forEach(function (type) {
+ if (monster.type == type) {
+ if (!E[type]) {
+ change = true;
+ }
+ E[type] = {
+ live: true,
+ map: monster.map,
+ hp: monster.hp,
+ max_hp: monster.max_hp,
+ target: monster.target,
+ x: monster.x,
+ y: monster.y,
+ };
+ }
+ });
+ if (monster.type == "grinch") {
+ if (instances[monster.in].paused) {
+ resume_instance(instances[monster.in]);
+ }
+
+ var phrase = null;
+ var disengage = false;
+
+ if (Math.random() < 0.1) {
+ if (monster.target && !G.monsters.grinch.good) {
+ phrase = random_one([
+ "Come to papa",
+ "This is not a chew toy!",
+ "Give me that! Don't you know you're not supposed to take things that don't belong to you? What's the matter with you? You some kind of wild animal?",
+ "HELP ME…I'm FEELING.",
+ "It came without ribbons, it came without tags. It came without packages, boxes, or bags.",
+ "Poor, poor, " + monster.target,
+ "Innie, minnie, tiny " + monster.target + "innie",
+ ]);
+ } else if (!monster.target) {
+ phrase = random_one([
+ "That is not a chew toy!",
+ "Stupid. Ugly. Out of date. This is ridiculous. If I can't find something nice to wear I'm not going.",
+ "Kids today. So desensitized by movies and television.",
+ "Holiday who-be what-ee?",
+ "I could use a little social interaction.",
+ "It's because I'm green isn't it?",
+ "Social distancing what?",
+ ]);
+ }
+ }
+
+ if (
+ monster.target &&
+ get_player(monster.target) &&
+ get_player(monster.target).slots.chest &&
+ get_player(monster.target).slots.chest.name == "xmassweater" &&
+ !G.monsters.grinch.good
+ ) {
+ phrase = "Ugh. What's that ugly thing you are wearing?! I can't look at it. Stop.";
+ disengage = true;
+ }
+
+ if (phrase) {
+ xy_emit(monster, "chat_log", { owner: "Grinch", message: phrase, id: monster.id, color: "#418343" });
+ }
+
+ if (!monster.target && Math.random() < 0.1 * Object.keys(players).length) {
+ monster.last_attack = future_ms(1000);
+ var player = random_one(players);
+ if (
+ (player.level < 50 && Math.random() > 0.08) ||
+ (G.maps[player.map] &&
+ (G.maps[player.map].safe || G.maps[player.map].instance || G.maps[player.map].irregular))
+ ) {
+ player = null;
+ }
+ if (player && 0) {
+ // attack everyone
+ for (var pid in instances[player.in].players) {
+ if (!player) {
+ break;
+ }
+ var ally = instances[player.in].players[pid];
+ if (
+ ally.name != player.name &&
+ !ally.npc &&
+ (ally.type != "merchant" || player.type == "merchant") &&
+ simple_distance(ally, player) < 500
+ ) {
+ player = null;
+ break;
+ }
+ }
+ }
+ if (player) {
+ target_player(monster, player);
+ }
+ }
+ if ((monster.target && !is_disabled(monster) && Math.random() < 0.05) || disengage) {
+ stop_pursuit(monster, { force: true, cause: "disengage" });
+ }
+ }
+ }
+ }
+
+ eventmap.forEach(function (s) {
+ if (events[s[0]] && !E[s[1]]) {
+ E[s[1]] = { live: false, spawn: timers[s[1]] };
+ change = true;
+ }
+ });
+
+ if (events.goblin) {
+ }
+
+ if (events.hide_and_seek) {
+ }
+
+ if (events.abtesting) {
+ if (timers.abtesting && c > timers.abtesting) {
+ var winner = "A";
+ if (E.abtesting.B > E.abtesting.A) {
+ winner = "B";
+ }
+ events.abtesting = false;
+ timers.abtesting = false;
+ delete E.abtesting;
+ change = true;
+ broadcast("server_message", { message: "Team " + winner + " wins! Hope you all had fun!", color: "#4BB6E1" });
+ for (var id in instances.abtesting.players) {
+ var player = instances.abtesting.players[id];
+ var table = "abtesting";
+ if (!player.team) {
+ continue;
+ }
+ if (player.team != winner) {
+ table = "abtesting_loser";
+ }
+ if (!player.esize) {
+ socket.emit("game_log", "Full inventory. Unable to receive a prize.");
+ continue;
+ }
+ exchange(player, table);
+ }
+ destroy_instance("abtesting");
+ } else if (!timers.abtesting) {
+ timers.abtesting = future_s(G.events.abtesting.duration);
+ change = true;
+ timers.abtesting_start = c;
+ E.abtesting = { end: timers.abtesting, signup_end: future_s(60), A: 0, B: 0, id: randomStr(5) };
+ create_instance("abtesting", "abtesting", { event: true });
+ collect_signups("abtesting");
+ broadcast("server_message", { message: "A/B Testing has begun!", color: "#4BB6E1" });
+ // npcs.bean.s.invis={ms:999999999999}; xy_emit(npcs.bean,"disappear",{id:"Bean"});
+ }
+ }
+
+ if (instances.cyberland && ssince(timers.cyberland) > 10) {
+ var detected = false;
+ timers.cyberland = new Date();
+ for (var id in instances.cyberland.monsters) {
+ var monster = instances.cyberland.monsters[id];
+ if (monster.target) {
+ detected = get_player(monster.target);
+ }
+ }
+ if (detected) {
+ xy_emit({ in: "cyberland", map: "cyberland", x: 0, y: -100 }, "chat_log", {
+ owner: "mainframe",
+ message: "ALERT",
+ id: "mainframe",
+ });
+ for (var id in instances.cyberland.monsters) {
+ var monster = instances.cyberland.monsters[id];
+ if (!monster.target) {
+ target_player(monster, detected);
+ }
+ }
+ }
+ if (Math.random() < 1.0 / 1600) {
+ S.misc.spares.push("electronics");
+ if (Math.random() < 1.0 / 1020) {
+ S.misc.spares.push("networkcard");
+ }
+ if (S.misc.spares.length > 2000) {
+ S.misc.spares.length = 2000;
+ }
+ }
+ }
+
+ for (var id in E.duels || {}) {
+ var duel = E.duels[id];
+ var instance = instances[id];
+ var info = instance.info;
+ var a = 0;
+ var b = 0;
+ if (info.seconds) {
+ info.seconds--;
+ }
+ // console.log(info.A); console.log(info.B);
+ for (var i = 0; i < info.A.length; i++) {
+ var p = info.A[i];
+ var player = get_player(p.name);
+ //console.log(player.in+" "+player.duel.id+" "+player.rip);
+ if (!player || player.in != id || !player.duel || player.rip || !player.team) {
+ p.active = false;
+ }
+ if (p.active) {
+ info.A[i] = player_to_summary(player);
+ a++;
+ info.A[i].active = true;
+ }
+ }
+ for (var i = 0; i < info.B.length; i++) {
+ var p = info.B[i];
+ var player = get_player(p.name);
+ if (!player || player.in != id || !player.duel || player.rip || !player.team) {
+ p.active = false;
+ }
+ if (p.active) {
+ info.B[i] = player_to_summary(player);
+ b++;
+ info.B[i].active = true;
+ }
+ }
+ if (!info.seconds && !info.active) {
+ duel.a = [];
+ duel.b = [];
+ info.active = true;
+ info.A.forEach(function (p) {
+ var player = get_player(p.name);
+ if (player && p.active) {
+ player.s = {};
+ duel.a.push(p.name);
+ resend(player, "u+cid");
+ }
+ });
+ info.B.forEach(function (p) {
+ var player = get_player(p.name);
+ if (player && p.active) {
+ player.s = {};
+ duel.b.push(p.name);
+ resend(player, "u+cid");
+ }
+ });
+ }
+ if (!a || !b) {
+ var message = duel.challenger + " wins the duel!";
+ var chat = duel.challenger + " defeated " + duel.vs + "!";
+ var sent = {};
+ if (!a) {
+ message = duel.vs + " wins the duel!";
+ chat = duel.vs + " defeated " + duel.challenger + "!";
+ }
+ for (var pid in instance.players) {
+ sent[instance.players[pid].name] = true;
+ instance.players[pid].socket.emit("game_chat", { message: message, color: "#47C1AE" });
+ }
+ info.A.forEach(function (p) {
+ var player = get_player(p.name);
+ if (player && !sent[p.name]) {
+ player.socket.emit("game_chat", { message: message, color: "#47C1AE" });
+ }
+ });
+ info.B.forEach(function (p) {
+ var player = get_player(p.name);
+ if (player && !sent[p.name]) {
+ player.socket.emit("game_chat", { message: message, color: "#47C1AE" });
+ }
+ });
+
+ destroy_instance(id);
+
+ if (!a) {
+ info.B.forEach(function (p) {
+ var player = get_player(p.name);
+ if (player) {
+ xy_emit(player, "eval", "confetti_shower(get_player('" + player.name + "'),2)");
+ }
+ });
+ } else {
+ info.A.forEach(function (p) {
+ var player = get_player(p.name);
+ if (player) {
+ xy_emit(player, "eval", "confetti_shower(get_player('" + player.name + "'),2)");
+ }
+ });
+ }
+
+ if (!a && get_player(duel.vs)) {
+ xy_emit(get_player(duel.vs), "game_chat", { message: chat, color: "#47C1AE" });
+ }
+ if (!b && get_player(duel.challenger)) {
+ xy_emit(get_player(duel.challenger), "game_chat", { message: chat, color: "#47C1AE" });
+ }
+
+ delete E.duels[id];
+ broadcast_e();
+ continue;
+ }
+ duel.active = instance.active;
+ duel.seconds = instance.seconds;
+ instance_emit(id, "map_info", instance.info);
+ }
+
+ for (var e in E) {
+ if ((E[e] && E[e].target) || Object.keys(E.duels || {}).length) {
+ change = true;
+ break;
+ }
+ }
+ if (change) {
+ broadcast_e();
+ }
+ } catch (e) {
+ log_trace("Critical-event_loop: ", e);
+ }
+}
+
+function broadcast_e(dont_send) {
+ if (!dont_send) {
+ broadcast("server_info", E);
+ }
+}
+
+function start_event(name) {
+ if (name == "goblin") {
+ events.goblin = true;
+ } else if (name == "goobrawl") {
+ signups = {};
+ events.goobrawl = 1;
+ timers.goobrawl = future_s(45);
+ broadcast("notice", { message: "Goo Brawl is about to start!" });
+ } else if (name == "abtesting") {
+ signups = {};
+ events.abtesting = 1;
+ timers.abtesting = future_s(45);
+ // instances.main.players[NPC_prefix+"Bean"]=npcs.bean;
+ // npcs.bean.party="abtesting"; npcs.bean.last.move=new Date();
+ broadcast("server_message", { message: "A/B Testing is about to start!", color: "#4BB6E1" });
+ }
+}
+
+function new_worker(num) {
+ var worker = new Worker(variables.worker_path, {
+ workerData: { G: G, amap_data: amap_data, smap_data: smap_data },
+ env: SHARE_ENV,
+ execArgv: [],
+ });
+ worker.wnum = num;
+ worker.on("message", function (data) {
+ if (data.type == "monster_move") {
+ var monster = instances[data.in].monsters[data.id];
+ if (!monster) {
+ return;
+ }
+ monster.working = false;
+ if (data.move && (data.move[2] != "bad" || (monster.bmoves || 0) < 6)) {
+ if (data.move[2] == "bad") {
+ monster.bmoves = (monster.bmoves || 0) + 1;
+ } else {
+ monster.bmoves = 0;
+ }
+ monster.going_x = data.move[0];
+ monster.going_y = data.move[1];
+ start_moving_element(monster);
+ } else {
+ var player = monster.target && get_player(monster.target);
+ if (player) {
+ if (monster.attack < 120 || distance(monster, player, true) > monster.range) {
+ stop_pursuit(monster, { cause: "cant_move_smart" });
+ }
+ }
+ }
}
});
-
- if(events.goobrawl)
- {
- if(!timers.goobrawl)
- {
- timers.goobrawl=future_s(G.events.goobrawl.duration); E.goobrawl={end:timers.goobrawl}; change=true;
- //create_instance("goobrawl","goobrawl",{event:true});
- // collect_signups("goobrawl");
- broadcast("notice",{message:"Goo Brawl has begun!"});
- }
- else if(c>timers.goobrawl)
- {
- events.goobrawl=false; delete E.goobrawl; delete timers.goobrawl; change=true;
- //destroy_instance("goobrawl");
- broadcast("notice",{message:"Goo Brawl is over, hope you had fun!"});
- }
- else if(instances.goobrawl && Object.keys(instances.goobrawl.monsters).length<6 && Math.random()<0.3)
- {
- if(Math.random()<0.01)
- {
- var data=clone(G.maps.goobrawl.monsters[0]);
- data.type="rgoo";
- var m=new_monster("goobrawl",data);
- //m.s.filter={ms:9999999,name:"scale",scale:2};
- }
- else
- {
- var data=clone(G.maps.goobrawl.monsters[0]);
- data.type="bgoo";
- var m=new_monster("goobrawl",data);
- m.skin=random_one(["goo0","goo1","goo2","goo3","goo4","goo5","goo6"]);
- // m.drops=[[0.5,"funtoken"]];
- m.u=true; m.cid++;
- }
- }
- }
-
- if(gameplay=="hardcore" && ssince(timers.hardcore)>64)
- {
- timers.hardcore=new Date();
- for(var id in instances.woffice.players)
- {
- var player=instances.woffice.players[id],gold=480000;
- player.gold+=gold;
- player.socket.emit("game_log","Received "+to_pretty_num(gold)+" gold");
- player.socket.emit("disappearing_text",{"message":"+"+gold,"x":player.x,"y":player.y-32,"args":{color:"+gold","size":"large"}});
- resend(player,"reopen");
- }
- }
-
- if(events.goldenbat && stats.kills.bat>edges.next_goldenbat)
- {
- edges.next_goldenbat+=parseInt(events.goldenbat*Math.random());
- spawn_special_monster("goldenbat");
- }
-
- if(events.cutebee && stats.kills.bee>edges.next_cutebee)
- {
- edges.next_cutebee+=parseInt(events.cutebee*Math.random());
- spawn_special_monster("cutebee");
- }
-
- if(!events.holidayseason && events.snowman && !monster_c.snowman)
- {
- if(!timers.snowman) timers.snowman=future_s(events.snowman*60);
- else if(timers.snowman && c>timers.snowman) timers.snowman=0,spawn_special_monster("snowman");
- }
-
- var eventmap=[
- ["halloween","mrpumpkin"],
- ["halloween","mrgreen"],
- ["halloween","slenderman",true],
- ["holidayseason","grinch"],
- ["holidayseason","snowman"],
- ["lunarnewyear","dragold"],
- ["lunarnewyear","tiger",true],
- ["valentines","pinkgoo",true],
- ["egghunt","wabbit",true],
- ];
- eventmap.forEach(function(s){
- if(events[s[0]] && !monster_c[s[1]])
- {
- if(!timers[s[1]])
- {
- if(timers[s[1]]!==0) timers[s[1]]=future_s(120);
- else timers[s[1]]=future_s(G.monsters[s[1]].respawn);
- E[s[1]]={live:false,spawn:timers[s[1]]};
- broadcast_e();
- }
- else if(timers[s[1]] && c>timers[s[1]])
- {
- timers[s[1]]=0;
- spawn_special_monster(s[1]);
- var m=get_monsters(s[1])[0];
- var data={live:true,map:m.map,hp:m.hp,max_hp:m.max_hp,target:m.target};
- if(!s[2]) data.x=m.x,data.y=m.y;
- E[s[1]]=data;
- broadcast_e();
- }
- }
+ worker.on("error", function (data) {
+ console.log("#W Worker error: " + JSON.stringify(data));
});
- ["holidayseason","halloween","lunarnewyear","valentines","egghunt"].forEach(function(event){
- if(events[event]) E[event]=true;
- else if(E[event]) delete E[event];
- });
- ["snowman","grinch","dragold","mrpumpkin","mrgreen","wabbit","pinkgoo","tiger"].forEach(function(type){
- if(E[type] && !monster_c[type])
- {
- delete E[type]; // [20/01/23]
- change=true;
- }
- });
- for(var name in instances)
- {
- for(var id in instances[name].monsters)
- {
- var monster=instances[name].monsters[id];
- ["tiger"].forEach(function(type){
- if(monster.type==type)
- {
- E[type]={live:true,map:monster.map,hp:monster.hp,max_hp:monster.max_hp,target:monster.target};
- }
- });
- ["snowman","grinch","dragold","mrpumpkin","mrgreen","wabbit","pinkgoo"].forEach(function(type){
- if(monster.type==type)
- {
- if(!E[type]) change=true;
- E[type]={live:true,map:monster.map,hp:monster.hp,max_hp:monster.max_hp,target:monster.target,x:monster.x,y:monster.y};
- }
- });
- if(monster.type=="grinch")
- {
- if(instances[monster.in].paused) resume_instance(instances[monster.in]);
-
- var phrase=null,disengage=false;
-
- if(Math.random()<0.1)
- {
- if(monster.target && !G.monsters.grinch.good) phrase=random_one(["Come to papa","This is not a chew toy!","Give me that! Don't you know you're not supposed to take things that don't belong to you? What's the matter with you? You some kind of wild animal?","HELP ME…I'm FEELING.","It came without ribbons, it came without tags. It came without packages, boxes, or bags.","Poor, poor, "+monster.target,"Innie, minnie, tiny "+monster.target+"innie"]);
- else if(!monster.target) phrase=random_one(["That is not a chew toy!","Stupid. Ugly. Out of date. This is ridiculous. If I can't find something nice to wear I'm not going.","Kids today. So desensitized by movies and television.","Holiday who-be what-ee?","I could use a little social interaction.","It's because I'm green isn't it?","Social distancing what?"])
- }
-
- if(monster.target && get_player(monster.target) && get_player(monster.target).slots.chest && get_player(monster.target).slots.chest.name=="xmassweater" && !G.monsters.grinch.good)
- phrase="Ugh. What's that ugly thing you are wearing?! I can't look at it. Stop.",disengage=true;
-
- if(phrase) xy_emit(monster,"chat_log",{owner:"Grinch",message:phrase,id:monster.id,color:"#418343"});
-
-
- if(!monster.target && Math.random()<0.1*Object.keys(players).length)
- {
- monster.last_attack=future_ms(1000);
- var player=random_one(players);
- if(player.level<50 && Math.random()>0.08 || G.maps[player.map] && (G.maps[player.map].safe || G.maps[player.map].instance || G.maps[player.map].irregular)) player=null;
- if(player && 0) // attack everyone
- for(var pid in instances[player.in].players)
- {
- if(!player) break;
- var ally=instances[player.in].players[pid];
- if(ally.name!=player.name && !ally.npc && (ally.type!="merchant" || player.type=="merchant") && simple_distance(ally,player)<500)
- {
- player=null;
- break;
- }
- }
- if(player)
- target_player(monster,player);
- }
- if(monster.target && !is_disabled(monster) && Math.random()<0.05 || disengage)
- stop_pursuit(monster,{force:true,cause:"disengage"});
- }
- }
- }
-
- eventmap.forEach(function(s){
- if(events[s[0]] && !E[s[1]])
- E[s[1]]={live:false,spawn:timers[s[1]]},change=true;
- });
-
- if(events.goblin)
- {
-
- }
-
- if(events.hide_and_seek)
- {
-
- }
-
- if(events.abtesting)
- {
- if(timers.abtesting && c>timers.abtesting)
- {
- var winner="A";
- if(E.abtesting.B>E.abtesting.A) winner="B";
- events.abtesting=false; timers.abtesting=false; delete E.abtesting; change=true;
- broadcast("server_message",{message:"Team "+winner+" wins! Hope you all had fun!",color:"#4BB6E1"});
- for(var id in instances.abtesting.players)
- {
- var player=instances.abtesting.players[id],table="abtesting";
- if(!player.team) continue;
- if(player.team!=winner) table="abtesting_loser";
- if(!player.esize) { socket.emit("game_log","Full inventory. Unable to receive a prize."); continue;}
- exchange(player,table);
- }
- destroy_instance("abtesting");
- }
- else if(!timers.abtesting)
- {
- timers.abtesting=future_s(G.events.abtesting.duration); change=true;
- timers.abtesting_start=c;
- E.abtesting={end:timers.abtesting,signup_end:future_s(60),A:0,B:0,id:randomStr(5)};
- create_instance("abtesting","abtesting",{event:true});
- collect_signups("abtesting");
- broadcast("server_message",{message:"A/B Testing has begun!",color:"#4BB6E1"});
- // npcs.bean.s.invis={ms:999999999999}; xy_emit(npcs.bean,"disappear",{id:"Bean"});
- }
- }
-
- if(instances.cyberland && ssince(timers.cyberland)>10)
- {
- var detected=false;
- timers.cyberland=new Date();
- for(var id in instances.cyberland.monsters)
- {
- var monster=instances.cyberland.monsters[id];
- if(monster.target) detected=get_player(monster.target);
- }
- if(detected)
- {
- xy_emit({"in":"cyberland","map":"cyberland","x":0,"y":-100},"chat_log",{owner:"mainframe",message:"ALERT",id:"mainframe"});
- for(var id in instances.cyberland.monsters)
- {
- var monster=instances.cyberland.monsters[id];
- if(!monster.target) target_player(monster,detected);
- }
- }
- if(Math.random()<1.0/1600)
- {
- S.misc.spares.push("electronics");
- if(Math.random()<1.0/1020)
- S.misc.spares.push("networkcard");
- if(S.misc.spares.length>2000) S.misc.spares.length=2000;
- }
- }
-
- for(var id in (E.duels||{}))
- {
- var duel=E.duels[id];
- var instance=instances[id];
- var info=instance.info,a=0,b=0;
- if(info.seconds) info.seconds--;
- // console.log(info.A); console.log(info.B);
- for(var i=0;imonster.range) stop_pursuit(monster,{cause:"cant_move_smart"});
- }
- }
- });
- worker.on('error',function(data){
- console.log("#W Worker error: "+JSON.stringify(data));
- });
- worker.on('exit',function(code){
- workers[this.wnum]=new_worker(this.wnum);
+ worker.on("exit", function (code) {
+ workers[this.wnum] = new_worker(this.wnum);
});
return worker;
}
-function init_server()
-{
- if(gameplay=="hardcore")
- {
- E={
- "rewards":{
- "item8":null,
- "item9":null,
- "item10":null,
- "item11":null,
- "item12":null,
- "leader":null,
- "first_fvampire":null,
- "first_mvampire":null,
- "first_skeletor":null,
- "first_stompy":null,
- "first_franky":null,
- "first_ent":null,
- "first_wabbit":null,
- "accessory5":null,
- "accessory6":null,
- "first_warrior_70":null,
- "first_paladin_70":null,
- "first_priest_70":null,
- "first_mage_70":null,
- "first_ranger_70":null,
- "first_rogue_70":null,
- "!participation":"Every authorized account with a level 60+ character receives a participation award!",
+function init_server() {
+ if (gameplay == "hardcore") {
+ E = {
+ rewards: {
+ item8: null,
+ item9: null,
+ item10: null,
+ item11: null,
+ item12: null,
+ leader: null,
+ first_fvampire: null,
+ first_mvampire: null,
+ first_skeletor: null,
+ first_stompy: null,
+ first_franky: null,
+ first_ent: null,
+ first_wabbit: null,
+ accessory5: null,
+ accessory6: null,
+ first_warrior_70: null,
+ first_paladin_70: null,
+ first_priest_70: null,
+ first_mage_70: null,
+ first_ranger_70: null,
+ first_rogue_70: null,
+ "!participation": "Every authorized account with a level 60+ character receives a participation award!",
},
+ };
+ E.minutes = 340;
+ if (is_sdk) {
+ E.minutes = 12;
}
- E.minutes=340;
- if(is_sdk) E.minutes=12;
- setInterval(hardcore_loop,60*1000);
+ setInterval(hardcore_loop, 60 * 1000);
}
- setInterval(event_loop,1000);
- setInterval(tavern_loop,1000);
- workers=[
+ setInterval(event_loop, 1000);
+ setInterval(tavern_loop, 1000);
+ workers = [
new_worker(0),
new_worker(1),
new_worker(2),
@@ -1979,650 +2571,963 @@ function init_server()
];
}
-function init_server_data()
-{
- if(!S.dt) S.dt={};
- if(!S.sold) S.sold=[];
- if(!S.found) S.found=[];
- if(!S.gold) S.gold=0;
- if(!S.cash) S.cash=0;
- if(!S.logs) S.logs={"donate":[],"dice":[]};
- if(!S.misc) S.misc={spares:["electronics"]};
- ["sold","found"].forEach(function(store){
- for(var i=S[store].length-1;i>=0;i--)
- if(!S[store][i].name || !G.items[S[store][i].name] || in_arr(S[store][i].name,["cxjar","emotionjar"]) || G.items[S[store][i].name].cash)
- S[store].splice(i,1);
+function init_server_data() {
+ if (!S.dt) {
+ S.dt = {};
+ }
+ if (!S.sold) {
+ S.sold = [];
+ }
+ if (!S.found) {
+ S.found = [];
+ }
+ if (!S.gold) {
+ S.gold = 0;
+ }
+ if (!S.cash) {
+ S.cash = 0;
+ }
+ if (!S.logs) {
+ S.logs = { donate: [], dice: [] };
+ }
+ if (!S.misc) {
+ S.misc = { spares: ["electronics"] };
+ }
+ ["sold", "found"].forEach(function (store) {
+ for (var i = S[store].length - 1; i >= 0; i--) {
+ if (
+ !S[store][i].name ||
+ !G.items[S[store][i].name] ||
+ in_arr(S[store][i].name, ["cxjar", "emotionjar"]) ||
+ G.items[S[store][i].name].cash
+ ) {
+ S[store].splice(i, 1);
+ }
+ }
});
- for(var i=0;i=2) parties[newparty[0]]=newparty;
- if(newparty.length<2)
- {
- if(newparty.length)
- {
- var player=players[name_to_id[newparty[0]]];
- if(!player) { console.log("#X SHOULD'VE FOUND2 "+newparty[0]); }
- else player.party=null;
- }
+ if (newparty.length >= 2) {
+ parties[newparty[0]] = newparty;
}
- else
- {
- newparty.forEach(function(player_name){
- var player=players[name_to_id[player_name]];
- if(!player) { console.log("#X SHOULD'VE FOUND3 "+newparty[0]); return; }
- player.party=newparty[0];
+ if (newparty.length < 2) {
+ if (newparty.length) {
+ var player = players[name_to_id[newparty[0]]];
+ if (!player) {
+ console.log("#X SHOULD'VE FOUND2 " + newparty[0]);
+ } else {
+ player.party = null;
+ }
+ }
+ } else {
+ newparty.forEach(function (player_name) {
+ var player = players[name_to_id[player_name]];
+ if (!player) {
+ console.log("#X SHOULD'VE FOUND3 " + newparty[0]);
+ return;
+ }
+ player.party = newparty[0];
});
}
// Moved the socket routine to the end, after all party changes are made [10/07/18]
- oldparty.forEach(function(player_name){
- var player=players[name_to_id[player_name]];
- if(!player || player.name==leaver.name) return;
- newparty=newparty&&parties[newparty[0]]||[]; // During these .socket.emit's, "disconnect"'s happen, the parties can become empty, and party_to_client fails [21/08/18]
- player.socket.emit("party_update",{message:leaver.name+" left the party",leave:1,list:newparty.length>=2&&newparty,party:newparty.length>=2&&party_to_client(newparty[0])||{}});
- resend(player,"nc+u+cid");
+ oldparty.forEach(function (player_name) {
+ var player = players[name_to_id[player_name]];
+ if (!player || player.name == leaver.name) {
+ return;
+ }
+ newparty = (newparty && parties[newparty[0]]) || []; // During these .socket.emit's, "disconnect"'s happen, the parties can become empty, and party_to_client fails [21/08/18]
+ player.socket.emit("party_update", {
+ message: leaver.name + " left the party",
+ leave: 1,
+ list: newparty.length >= 2 && newparty,
+ party: (newparty.length >= 2 && party_to_client(newparty[0])) || {},
+ });
+ resend(player, "nc+u+cid");
});
}
-function delete_observer(socket)
-{
- var observer=observers[socket.id];
+function delete_observer(socket) {
+ var observer = observers[socket.id];
delete observers[socket.id];
delete instances[observer.in].observers[observer.id];
}
-function send_all_xy(observer,args)
-{
- var data={players:[],monsters:[],type:'all',in:observer.in,map:observer.map},instance=instances[observer.in];
- for(var id in instance.players) if(!instance.players[id].s.invis && within_xy_range(observer,instance.players[id])) data.players.push(player_to_client(instance.players[id],1));
- for(var id in instance.monsters) if(within_xy_range(observer,instance.monsters[id])) data.monsters.push(monster_to_client(instance.monsters[id]));
- observer.last_ux=observer.x;
- observer.last_uy=observer.y;
- if(observer.moving && mode.xyinf) data.xy={x:observer.x,y:observer.y};
- if(args && args.raw) return data;
- observer.socket.emit("entities",data);
+function send_all_xy(observer, args) {
+ var data = { players: [], monsters: [], type: "all", in: observer.in, map: observer.map };
+ var instance = instances[observer.in];
+ for (var id in instance.players) {
+ if (!instance.players[id].s.invis && within_xy_range(observer, instance.players[id])) {
+ data.players.push(player_to_client(instance.players[id], 1));
+ }
+ }
+ for (var id in instance.monsters) {
+ if (within_xy_range(observer, instance.monsters[id])) {
+ data.monsters.push(monster_to_client(instance.monsters[id]));
+ }
+ }
+ observer.last_ux = observer.x;
+ observer.last_uy = observer.y;
+ if (observer.moving && mode.xyinf) {
+ data.xy = { x: observer.x, y: observer.y };
+ }
+ if (args && args.raw) {
+ return data;
+ }
+ observer.socket.emit("entities", data);
}
-function xy_emit(entity,event,data,must)
-{
- var x=entity.x,y=entity.y,owners={};
- for(var id in instances[entity.in].players)
- {
- var player=instances[entity.in].players[id];
- if(player.npc) continue;
- if(player.x-player.vision[0]B.u_boundary) u=true;
- else if(abs(element.last_u[1]-element.y)>B.u_boundary) u=true;
-
- if(u)
- {
- element.last_u=[element.x,element.y];
- element.u=true;
+ if (event == "chat_log" && data.p) {
+ appengine_call("log_chat", {
+ to: Object.entries(owners),
+ type: "ambient",
+ message: data.message,
+ fro: entity.name,
+ author: entity.owner,
+ });
}
}
-function xy_upush_logic(element) // sets .push so new entities in that area are pushed to the user/element
-{
- var u=false;
-
- if(!element.last_upush) {element.last_upush=[element.x,element.y]; return;}
- else if(abs(element.last_upush[0]-element.x)>B.u_vision) u=true;
- else if(abs(element.last_upush[1]-element.y)>B.u_vision) u=true;
+function xy_u_logic(element) {
+ // sets .u so updates are sent - this element might enter someone's vision
+ var u = false;
- if(u)
- {
- element.push=element.last_upush;
- element.last_upush=[element.x,element.y];
+ if (!element.last_u) {
+ u = true;
+ } else if (abs(element.last_u[0] - element.x) > B.u_boundary) {
+ u = true;
+ } else if (abs(element.last_u[1] - element.y) > B.u_boundary) {
+ u = true;
+ }
+
+ if (u) {
+ element.last_u = [element.x, element.y];
+ element.u = true;
}
}
-function appengine_call(method,args,on_success,on_error)
-{
- var api_path="/api/"+method;
- if(mode.prevent_external && !in_arr(method,["create_server","update_server","stop_server","start_character","send_mail"])) return;
- function retry_call()
- {
- var t=1600;
- args.retried=(args.retried||0)+1;
+function xy_upush_logic(element) {
+ // sets .push so new entities in that area are pushed to the user/element
+ var u = false;
+
+ if (!element.last_upush) {
+ element.last_upush = [element.x, element.y];
+ return;
+ } else if (abs(element.last_upush[0] - element.x) > B.u_vision) {
+ u = true;
+ } else if (abs(element.last_upush[1] - element.y) > B.u_vision) {
+ u = true;
+ }
+
+ if (u) {
+ element.push = element.last_upush;
+ element.last_upush = [element.x, element.y];
+ }
+}
+
+function appengine_call(method, args, on_success, on_error) {
+ var api_path = "/api/" + method;
+ if (
+ mode.prevent_external &&
+ !in_arr(method, ["create_server", "update_server", "stop_server", "start_character", "send_mail"])
+ ) {
+ return;
+ }
+ function retry_call() {
+ var t = 1600;
+ args.retried = (args.retried || 0) + 1;
args.retries--;
- if(args.retried>20) t=240000;
- else if(args.retried>10) t=60000;
- else if(args.retried>5) t=20000;
- setTimeout(function(){ appengine_call(method,args,on_success,on_error); },t);
+ if (args.retried > 20) {
+ t = 240000;
+ } else if (args.retried > 10) {
+ t = 60000;
+ } else if (args.retried > 5) {
+ t = 20000;
+ }
+ setTimeout(function () {
+ appengine_call(method, args, on_success, on_error);
+ }, t);
// network retries, for "Error: socket hang up" etc. [09/09/16]
}
- if(!args) args={}; if(!on_success) on_success=function(){};
- if(args.suffix) { api_path+=args.suffix; delete args.suffix; }
- data={ 'method':method, 'arguments':JSON.stringify(args), 'server_auth':server_id+"-"+server_auth, 'auth':args.auth };
- try{
- request.post({url:base_url+api_path,form:data},function(err,response,body){
- try{
- if(err || !response || response.statusCode!=200) // node.request sends an undefined response when there is an issue ...
- {
- console.log("appengine_call - unknown error "+err+" or code: "+(response&&response.statusCode)+" retries: "+args.retries+(new Date())+" on "+api_path);
- if(method!="log_error")
- setTimeout(function(err,response,api_path,body){ return function(){
- try{
- appengine_call("log_error",{type:"appengine_call_error",err:(response&&response.statusCode)+" "+api_path,info:""+body+""+err+"\n"+JSON.stringify(response&&response.headers||{})});
- }catch(e)
- {
- log_trace("appengine_call's log_error "+api_path,e);
- }
- }}(err,response,api_path,body),120000);
- if(args.retries) retry_call();
- else if(on_error) on_error(""+err+" "+(response&&response.statusCode));
+ if (!args) {
+ args = {};
+ }
+ if (!on_success) {
+ on_success = function () {};
+ }
+ if (args.suffix) {
+ api_path += args.suffix;
+ delete args.suffix;
+ }
+ data = {
+ method: method,
+ arguments: JSON.stringify(args),
+ server_auth: server_id + "-" + server_auth,
+ auth: args.auth,
+ };
+ try {
+ request.post({ url: base_url + api_path, form: data }, function (err, response, body) {
+ try {
+ if (err || !response || response.statusCode != 200) {
+ // node.request sends an undefined response when there is an issue ...
+ console.log(
+ "appengine_call - unknown error " +
+ err +
+ " or code: " +
+ (response && response.statusCode) +
+ " retries: " +
+ args.retries +
+ new Date() +
+ " on " +
+ api_path,
+ );
+ if (method != "log_error") {
+ setTimeout(
+ (function (err, response, api_path, body) {
+ return function () {
+ try {
+ appengine_call("log_error", {
+ type: "appengine_call_error",
+ err: (response && response.statusCode) + " " + api_path,
+ info: "" + body + "" + err + "\n" + JSON.stringify((response && response.headers) || {}),
+ });
+ } catch (e) {
+ log_trace("appengine_call's log_error " + api_path, e);
+ }
+ };
+ })(err, response, api_path, body),
+ 120000,
+ );
+ }
+ if (args.retries) {
+ retry_call();
+ } else if (on_error) {
+ on_error("" + err + " " + (response && response.statusCode));
+ }
+ } else {
+ ct = JSON.parse(body);
+ if (on_success) {
+ on_success.apply(this, [ct]);
+ }
}
- else
- {
- ct=JSON.parse(body);
- if(on_success) on_success.apply(this,[ct]);
+ } catch (e) {
+ log_trace("appengine_call exception on " + api_path, e);
+ if (args.retries) {
+ retry_call();
+ } else if (on_error) {
+ on_error("" + err + " " + e + " " + (response && response.statusCode));
+ } else if (on_success) {
+ on_success.apply(this, [{ failed: 1, reason: "callbackfailed" }]);
}
- }catch(e){
- log_trace("appengine_call exception on "+api_path,e);
- if(args.retries) retry_call();
- else if(on_error) on_error(""+err+" "+e+" "+(response&&response.statusCode));
- else if(on_success) on_success.apply(this,[{"failed":1,"reason":"callbackfailed"}]);
}
});
- }catch(e){
- log_trace("appengine_call on "+api_path,e);
- if(args.retries) retry_call();
- else if(on_error) on_error(""+e+" "+(response&&response.statusCode));
- else if(on_success) on_success.apply(this,[{"failed":1,"reason":"callfailed"}]);
+ } catch (e) {
+ log_trace("appengine_call on " + api_path, e);
+ if (args.retries) {
+ retry_call();
+ } else if (on_error) {
+ on_error("" + e + " " + (response && response.statusCode));
+ } else if (on_success) {
+ on_success.apply(this, [{ failed: 1, reason: "callfailed" }]);
+ }
+ }
+ if (!args.init) {
+ args.init = new Date();
}
- if(!args.init) args.init=new Date();
return args;
}
-function discord_call(message)
-{
- if(gameplay=="hardcore" || gameplay=="test") return;
- if(is_sdk) return server_log("Discord: "+message);
- var url="https://discordapp.com/api/channels/404333059018719233/messages";
- if(message.search(" joined Adventure Land")!=-1) url="https://discordapp.com/api/channels/839163123499794481/messages"
+function discord_call(message) {
+ if (gameplay == "hardcore" || gameplay == "test") {
+ return;
+ }
+ if (is_sdk) {
+ return server_log("Discord: " + message);
+ }
+ var url = "https://discordapp.com/api/channels/404333059018719233/messages";
+ if (message.search(" joined Adventure Land") != -1) {
+ url = "https://discordapp.com/api/channels/839163123499794481/messages";
+ }
request(
{
- url:url,
- headers:{"Authorization":"Bot "+variables.discord_token},
- method:"POST",
- json:{
- "content":message,
- }
+ url: url,
+ headers: { Authorization: "Bot " + variables.discord_token },
+ method: "POST",
+ json: {
+ content: message,
+ },
},
- function(err,response,body){
+ function (err, response, body) {
//console.log(response);
- });
-
+ },
+ );
}
-function server_log(message,important)
-{
- if(is_sdk || important)
- {
-
- if(is_sdk) console.log(message);
- else console.log(message+" ("+new Date()+")");
- if(message && (message+"").indexOf("SEVERE")!=-1)
- {
- appengine_call("server_event",{
- event:"notice",
- keyword:variables.keyword,
- id:server_id,
- message:message,
- color:"red",
- },function(result){});
+function server_log(message, important) {
+ if (is_sdk || important) {
+ if (is_sdk) {
+ console.log(message);
+ } else {
+ console.log(message + " (" + new Date() + ")");
+ }
+ if (message && (message + "").indexOf("SEVERE") != -1) {
+ appengine_call(
+ "server_event",
+ {
+ event: "notice",
+ keyword: variables.keyword,
+ id: server_id,
+ message: message,
+ color: "red",
+ },
+ function (result) {},
+ );
}
}
}
-function appengine_log(event,message,color)
-{
- if(!color) color="gray";
- appengine_call("server_event",{
- event:event,
- keyword:variables.keyword,
- id:server_id,
- message:message,
- color:color,
- },function(result){});
+function appengine_log(event, message, color) {
+ if (!color) {
+ color = "gray";
+ }
+ appengine_call(
+ "server_event",
+ {
+ event: event,
+ keyword: variables.keyword,
+ id: server_id,
+ message: message,
+ color: color,
+ },
+ function (result) {},
+ );
}
-function disappearing_text(socket,entity,text,args)
-{
- var x=entity.x,y=entity.y-30,d_args={};
- if(!args) args={};
+function disappearing_text(socket, entity, text, args) {
+ var x = entity.x;
+ var y = entity.y - 30;
+ var d_args = {};
+ if (!args) {
+ args = {};
+ }
// if(!args.size) args.size=16;
- if(!args.color) args.color="";
+ if (!args.color) {
+ args.color = "";
+ }
- if(args.color) d_args.c=args.color; // color
- if(args.s) d_args.s=args.s; // sound
- if(args.size) d_args.sz=args.size;
- if(args.from) d_args.from=args.from; // for d_text + .evade + d_line
+ if (args.color) {
+ d_args.c = args.color;
+ } // color
+ if (args.s) {
+ d_args.s = args.s;
+ } // sound
+ if (args.size) {
+ d_args.sz = args.size;
+ }
+ if (args.from) {
+ d_args.from = args.from;
+ } // for d_text + .evade + d_line
- if(args.xy && args.nv) xy_emit(entity,"disappearing_text",{"message":text,"x":x,"y":y,"id":entity.id,"args":d_args,"nv":1});
- else if(args.xy) xy_emit(entity,"disappearing_text",{"message":text,"x":x,"y":y,"id":entity.id,"args":d_args});
- else if(args.party) party_emit(args.party,"disappearing_text",{"message":text,"x":x,"y":y,"id":entity.id,"args":d_args},{map:args.map});
- else socket.emit("disappearing_text",{"message":text,"x":x,"y":y,"id":entity.id,"args":d_args}); // volatile.
+ if (args.xy && args.nv) {
+ xy_emit(entity, "disappearing_text", { message: text, x: x, y: y, id: entity.id, args: d_args, nv: 1 });
+ } else if (args.xy) {
+ xy_emit(entity, "disappearing_text", { message: text, x: x, y: y, id: entity.id, args: d_args });
+ } else if (args.party) {
+ party_emit(
+ args.party,
+ "disappearing_text",
+ { message: text, x: x, y: y, id: entity.id, args: d_args },
+ { map: args.map },
+ );
+ } else {
+ socket.emit("disappearing_text", { message: text, x: x, y: y, id: entity.id, args: d_args });
+ } // volatile.
}
-function magiport_someone(pulled,player)
-{
- var spot=random_one([[-10,16],[10,16],[10,-16],[-10,-16],[0,-24],[-20,-32],[20,32],[-20,32],[20,-32]]);
- var spot=safe_xy_nearby(player.map,player.x+spot[0],player.y+spot[1]);
- if(!spot) return false;
- pulled.s.magiport={ms:400};
- pulled.s.magiport.x=spot.x;
- pulled.s.magiport.y=spot.y;
- pulled.s.magiport.f=player.name;
- pulled.s.magiport.in=player.in;
- pulled.s.magiport.map=player.map;
- if(player.party==pulled.party) player.pdps+=2000;
- resend(pulled,"u+cid")
+function magiport_someone(pulled, player) {
+ var spot = random_one([
+ [-10, 16],
+ [10, 16],
+ [10, -16],
+ [-10, -16],
+ [0, -24],
+ [-20, -32],
+ [20, 32],
+ [-20, 32],
+ [20, -32],
+ ]);
+ var spot = safe_xy_nearby(player.map, player.x + spot[0], player.y + spot[1]);
+ if (!spot) {
+ return false;
+ }
+ pulled.s.magiport = { ms: 400 };
+ pulled.s.magiport.x = spot.x;
+ pulled.s.magiport.y = spot.y;
+ pulled.s.magiport.f = player.name;
+ pulled.s.magiport.in = player.in;
+ pulled.s.magiport.map = player.map;
+ if (player.party == pulled.party) {
+ player.pdps += 2000;
+ }
+ resend(pulled, "u+cid");
return true;
}
-function exchange(player,name,args)
-{
- if(!args) args={};
- var socket=player.socket,done=false,total=0,current=0;
- var table=D.drops[name];
- if(is_array(name))
- {
- table=name;
- name=args.name;
+function exchange(player, name, args) {
+ if (!args) {
+ args = {};
}
- if(name.startsWith("cosmo"))
- {
- table=clone(table);
- table.forEach(function(drop){
- if(player.p.acx[drop[2]])
- drop[0]/=10**player.p.acx[drop[2]];
+ var socket = player.socket;
+ var done = false;
+ var total = 0;
+ var current = 0;
+ var table = D.drops[name];
+ if (is_array(name)) {
+ table = name;
+ name = args.name;
+ }
+ if (name.startsWith("cosmo")) {
+ table = clone(table);
+ table.forEach(function (drop) {
+ if (player.p.acx[drop[2]]) {
+ drop[0] /= 10 ** player.p.acx[drop[2]];
+ }
});
console.log(table);
}
- table.forEach(function(drop){ total+=drop[0]; });
- result=Math.random()*total;
- table.forEach(function(drop){
- if(done) return;
- current+=drop[0];
- if(result<=current)
- {
- done=true;
- if(drop[1]=="gold")
- {
- player.gold+=drop[2];
- socket.emit("game_log",{message:"Received "+to_pretty_num(drop[2])+" gold",color:"gold"});
- if(drop[2]>3000000 && !player.stealth) broadcast("server_message",{"message":player.name+" received "+to_pretty_num(drop[2])+" gold","color":"gold"});
- }
- else if(drop[1]=="shells")
- {
- add_shells(player,drop[2],name,true,"override");
- }
- else if(drop[1]=="empty")
- {
- socket.emit("game_log","Didn't receive anything");
- }
- else if(drop[1]=="cx" || drop[1]=="cxbundle")
- {
- player.p.acx[drop[2]]=(player.p.acx[drop[2]]||0)+1;
- socket.emit("game_response",{response:"cx_new",acx:player.p.acx,name:drop[2],from:name,bundle:drop[1]=="cxbundle"});
- }
- else if(drop[1]=="open")
- {
- exchange(player,drop[2]);
- }
- else
- {
- var item=create_new_item(drop[1],drop[2]),prop=undefined;
- if(name=="glitch" && (G.items[item.name].upgrade || G.items[item.name].compound || character_slots.includes(G.items[item.name].type))) item.p="glitched";
- if(name=="glitch") args.phrase="Glitched";
- if(args.v) item.v=args.v;
- if(drop[1]=="cxjar" || drop[1]=="emotionjar") item.data=drop[3];
- add_item(player,item,{r:1,phrase:args.phrase});
- socket.emit("game_log",{message:(args.phrase||"Received")+" "+item_to_phrase(item),color:colors.server_success});
+ table.forEach(function (drop) {
+ total += drop[0];
+ });
+ result = Math.random() * total;
+ table.forEach(function (drop) {
+ if (done) {
+ return;
+ }
+ current += drop[0];
+ if (result <= current) {
+ done = true;
+ if (drop[1] == "gold") {
+ player.gold += drop[2];
+ socket.emit("game_log", { message: "Received " + to_pretty_num(drop[2]) + " gold", color: "gold" });
+ if (drop[2] > 3000000 && !player.stealth) {
+ broadcast("server_message", {
+ message: player.name + " received " + to_pretty_num(drop[2]) + " gold",
+ color: "gold",
+ });
+ }
+ } else if (drop[1] == "shells") {
+ add_shells(player, drop[2], name, true, "override");
+ } else if (drop[1] == "empty") {
+ socket.emit("game_log", "Didn't receive anything");
+ } else if (drop[1] == "cx" || drop[1] == "cxbundle") {
+ player.p.acx[drop[2]] = (player.p.acx[drop[2]] || 0) + 1;
+ socket.emit("game_response", {
+ response: "cx_new",
+ acx: player.p.acx,
+ name: drop[2],
+ from: name,
+ bundle: drop[1] == "cxbundle",
+ });
+ } else if (drop[1] == "open") {
+ exchange(player, drop[2]);
+ } else {
+ var item = create_new_item(drop[1], drop[2]);
+ var prop = undefined;
+ if (
+ name == "glitch" &&
+ (G.items[item.name].upgrade ||
+ G.items[item.name].compound ||
+ character_slots.includes(G.items[item.name].type))
+ ) {
+ item.p = "glitched";
+ }
+ if (name == "glitch") {
+ args.phrase = "Glitched";
+ }
+ if (args.v) {
+ item.v = args.v;
+ }
+ if (drop[1] == "cxjar" || drop[1] == "emotionjar") {
+ item.data = drop[3];
+ }
+ add_item(player, item, { r: 1, phrase: args.phrase });
+ socket.emit("game_log", {
+ message: (args.phrase || "Received") + " " + item_to_phrase(item),
+ color: colors.server_success,
+ });
}
}
});
- if(!done) socket.emit("game_log","Didn't receive anything");
+ if (!done) {
+ socket.emit("game_log", "Didn't receive anything");
+ }
}
-function chest_exchange(chest,name)
-{
- var done=false,total=0,current=0;
- D.drops[name].forEach(function(drop){ total+=drop[0]; });
- result=Math.random()*total;
- D.drops[name].forEach(function(drop){
- if(done) return;
- current+=drop[0];
- if(result<=current)
- {
- done=true;
- if(drop[1]=="gold")
- {
- chest.gold+=drop[2];
- }
- else if(drop[1]=="shells")
- {
- chest.cash+=drop[2];
- }
- else if(drop[1]=="empty");
- else if(drop[1]=="open")
- {
- chest_exchange(chest,drop[2]);
- }
- else
- {
+function chest_exchange(chest, name) {
+ var done = false;
+ var total = 0;
+ var current = 0;
+ D.drops[name].forEach(function (drop) {
+ total += drop[0];
+ });
+ result = Math.random() * total;
+ D.drops[name].forEach(function (drop) {
+ if (done) {
+ return;
+ }
+ current += drop[0];
+ if (result <= current) {
+ done = true;
+ if (drop[1] == "gold") {
+ chest.gold += drop[2];
+ } else if (drop[1] == "shells") {
+ chest.cash += drop[2];
+ } else if (drop[1] == "empty") {
+ } else if (drop[1] == "open") {
+ chest_exchange(chest, drop[2]);
+ } else {
chest.items.push(create_new_item(drop[1]));
}
}
});
}
-var item_p_ignore={"grace":true,"giveaway":true,"gf":true,"price":true,"b":true,"rid":true,"list":true,"o":true,"oo":true,"src":true},item_trade_p_ignore={"grace":true,"o":true,"oo":true,"src":true};
+var item_p_ignore = {
+ grace: true,
+ giveaway: true,
+ gf: true,
+ price: true,
+ b: true,
+ rid: true,
+ list: true,
+ o: true,
+ oo: true,
+ src: true,
+};
+var item_trade_p_ignore = { grace: true, o: true, oo: true, src: true };
// DOC
// .name -> key from G.items
@@ -2652,730 +3557,1142 @@ var item_p_ignore={"grace":true,"giveaway":true,"gf":true,"price":true,"b":true,
// .giveaway
// .list -> the list for .giveaway
-function cache_item(current,trade,override)
-{
- if(!current) return null;
- var item={};
- if(trade)
- {
- for(var p in current)
- if(!item_trade_p_ignore[p]) item[p]=current[p];
- if(!item.giveaway) delete item.list;
+function cache_item(current, trade, override) {
+ if (!current) {
+ return null;
}
- else
- {
- for(var p in current)
- if(!item_p_ignore[p]) item[p]=current[p];
+ var item = {};
+ if (trade) {
+ for (var p in current) {
+ if (!item_trade_p_ignore[p]) {
+ item[p] = current[p];
+ }
+ }
+ if (!item.giveaway) {
+ delete item.list;
+ }
+ } else {
+ for (var p in current) {
+ if (!item_p_ignore[p]) {
+ item[p] = current[p];
+ }
+ }
+ }
+ if (override) {
+ for (var p in override) {
+ item[p] = override[p];
+ }
}
- if(override) for(var p in override) item[p]=override[p];
return item;
}
-function get_trade_slots(player)
-{
- if(player.p.stand)
- {
- var num=16,slots=[];
- if(player.type=="merchant" && player.level>=80) num=30;
- else if(player.type=="merchant" && (player.level>=70 || player.p.stand=="cstand")) num=24;
- for(var i=1;i<=num;i++) slots.push("trade"+i);
+function get_trade_slots(player) {
+ if (player.p.stand) {
+ var num = 16;
+ var slots = [];
+ if (player.type == "merchant" && player.level >= 80) {
+ num = 30;
+ } else if (player.type == "merchant" && (player.level >= 70 || player.p.stand == "cstand")) {
+ num = 24;
+ }
+ for (var i = 1; i <= num; i++) {
+ slots.push("trade" + i);
+ }
return slots;
+ } else if (player.p.trades) {
+ return ["trade1", "trade2", "trade3", "trade4"];
}
- else if(player.p.trades) return ["trade1","trade2","trade3","trade4"];
return [];
}
-function reslot_player(player)
-{
- trade_slots.forEach(function(slot){try{ delete player.cslots[slot]; }catch(e){}})
- get_trade_slots(player).forEach(function(slot){
- player.cslots[slot]=cache_item(player.slots[slot],1);
+function reslot_player(player) {
+ trade_slots.forEach(function (slot) {
+ try {
+ delete player.cslots[slot];
+ } catch (e) {}
+ });
+ get_trade_slots(player).forEach(function (slot) {
+ player.cslots[slot] = cache_item(player.slots[slot], 1);
});
}
-function cache_player_items(player)
-{
+function cache_player_items(player) {
// console.log("Cached "+player.name+"'s items");
- if(player.slots && player.slots.ring1 && player.slots.ring1.name=="tristone" && player.slots.ring1.level>=4) player.slots.ring1.name="darktristone";
- if(player.slots && player.slots.ring2 && player.slots.ring2.name=="tristone" && player.slots.ring2.level>=4) player.slots.ring2.name="darktristone";
- player.cslots={};
- player.citems=[];
- character_slots.forEach(function(slot){
- player.cslots[slot]=cache_item(player.slots[slot]);
+ if (player.slots && player.slots.ring1 && player.slots.ring1.name == "tristone" && player.slots.ring1.level >= 4) {
+ player.slots.ring1.name = "darktristone";
+ }
+ if (player.slots && player.slots.ring2 && player.slots.ring2.name == "tristone" && player.slots.ring2.level >= 4) {
+ player.slots.ring2.name = "darktristone";
+ }
+ player.cslots = {};
+ player.citems = [];
+ character_slots.forEach(function (slot) {
+ player.cslots[slot] = cache_item(player.slots[slot]);
});
- for(var i=0;i42) player.user[pack].length=42;
+function init_bank_exit(player) {
+ for (var pack in bank_packs) {
+ if (!player.user[pack]) {
+ continue;
+ }
+ if (player.user[pack].length > 42) {
+ player.user[pack].length = 42;
+ }
}
}
-function init_player(player)
-{
- var class_def=G.classes[player.type];
- player.citems=[];
- if(player.slots.mainhand && player.slots.offhand && G.classes[player.type].doublehand[G.items[player.slots.mainhand.name].wtype||G.items[player.slots.mainhand.name].type] || player.slots.mainhand && !G.classes[player.type].mainhand[G.items[player.slots.mainhand.name].wtype||G.items[player.slots.mainhand.name].type] && !G.classes[player.type].doublehand[G.items[player.slots.mainhand.name].wtype||G.items[player.slots.mainhand.name].type])
- {
- add_item(player,player.slots.mainhand,{announce:false});
- player.slots.mainhand=null;
+function init_player(player) {
+ var class_def = G.classes[player.type];
+ player.citems = [];
+ if (
+ (player.slots.mainhand &&
+ player.slots.offhand &&
+ G.classes[player.type].doublehand[
+ G.items[player.slots.mainhand.name].wtype || G.items[player.slots.mainhand.name].type
+ ]) ||
+ (player.slots.mainhand &&
+ !G.classes[player.type].mainhand[
+ G.items[player.slots.mainhand.name].wtype || G.items[player.slots.mainhand.name].type
+ ] &&
+ !G.classes[player.type].doublehand[
+ G.items[player.slots.mainhand.name].wtype || G.items[player.slots.mainhand.name].type
+ ])
+ ) {
+ add_item(player, player.slots.mainhand, { announce: false });
+ player.slots.mainhand = null;
}
- if(player.slots.offhand && !G.classes[player.type].offhand[G.items[player.slots.offhand.name].wtype||G.items[player.slots.offhand.name].type])
- {
- add_item(player,player.slots.offhand,{announce:false});
- player.slots.offhand=null;
+ if (
+ player.slots.offhand &&
+ !G.classes[player.type].offhand[G.items[player.slots.offhand.name].wtype || G.items[player.slots.offhand.name].type]
+ ) {
+ add_item(player, player.slots.offhand, { announce: false });
+ player.slots.offhand = null;
}
- for(var i=0;i60) delete player.items[i].v;
- if(player.items[i].expires) player.items[i].expires=new Date(player.items[i].expires);
- if(!Object.keys(player.q||{}).length && player.items[i].name=="placeholder") player.items[i]=null;
- }
- check_slots.forEach(function(slot){
- if(player.slots[slot] && player.slots[slot].expires) player.slots[slot].expires=new Date(player.slots[slot].expires);
- });
- if(player.p.item_num===undefined) player.p.item_num=parseInt(Math.random()*42)
- for(var s in player.s||{})
- {
- if(player.s[s] && player.s[s].last) player.s[s].last=new Date(player.s[s].last);
- }
- for(var dt in player.p.dt)
- {
- if(!is_string(player.p.dt[dt])) continue;
- player.p.dt[dt]=new Date(player.p.dt[dt]);
- }
- for(var id in G.skills)
- {
- if(G.skills[id]['class'] && G.skills[id]['class'].includes(player.type) && G.skills[id].persistent)
- {
- player.last[id]=player.p.dt[id]||(new Date());
- if((G.skills[id].cooldown||G.skills[id].reuse_cooldown)>mssince(player.last[id]))
- player.hitchhikers.push(["eval",{code:"skill_timeout('"+id+"',"+((G.skills[id].cooldown||G.skills[id].reuse_cooldown)-mssince(player.last[id]))+")"}]);
+ if (player.items[i].v && msince(new Date(player.items[i].v)) > 60) {
+ delete player.items[i].v;
+ }
+ if (player.items[i].expires) {
+ player.items[i].expires = new Date(player.items[i].expires);
+ }
+ if (!Object.keys(player.q || {}).length && player.items[i].name == "placeholder") {
+ player.items[i] = null;
}
}
- if(!player.skin || !T[player.skin]) player.skin=class_def.looks[0][0],player.cx=clone(class_def.looks[0][1]);
- prune_cx(player.cx||{});
- if(!player.p.acx)
- {
- player.p.acx={};
- player.p.xcx=[];
+ check_slots.forEach(function (slot) {
+ if (player.slots[slot] && player.slots[slot].expires) {
+ player.slots[slot].expires = new Date(player.slots[slot].expires);
+ }
+ });
+ if (player.p.item_num === undefined) {
+ player.p.item_num = parseInt(Math.random() * 42);
+ }
+ for (var s in player.s || {}) {
+ if (player.s[s] && player.s[s].last) {
+ player.s[s].last = new Date(player.s[s].last);
+ }
+ }
+ for (var dt in player.p.dt) {
+ if (!is_string(player.p.dt[dt])) {
+ continue;
+ }
+ player.p.dt[dt] = new Date(player.p.dt[dt]);
+ }
+ for (var id in G.skills) {
+ if (G.skills[id]["class"] && G.skills[id]["class"].includes(player.type) && G.skills[id].persistent) {
+ player.last[id] = player.p.dt[id] || new Date();
+ if ((G.skills[id].cooldown || G.skills[id].reuse_cooldown) > mssince(player.last[id])) {
+ player.hitchhikers.push([
+ "eval",
+ {
+ code:
+ "skill_timeout('" +
+ id +
+ "'," +
+ ((G.skills[id].cooldown || G.skills[id].reuse_cooldown) - mssince(player.last[id])) +
+ ")",
+ },
+ ]);
+ }
+ }
+ }
+ if (!player.skin || !T[player.skin]) {
+ player.skin = class_def.looks[0][0];
+ player.cx = clone(class_def.looks[0][1]);
+ }
+ prune_cx(player.cx || {});
+ if (!player.p.acx) {
+ player.p.acx = {};
+ player.p.xcx = [];
+ }
+ if (!player.p.emx) {
+ player.p.emx = {};
+ }
+ if (!player.p.ap) {
+ player.p.ap = {};
+ } // achievement progress
+ if (!player.p.achievements) {
+ player.p.achievements = {};
+ }
+ if (player.p.mute) {
+ player.mute = true;
+ }
+ if (player.p.role == "gm") {
+ player.gm = true;
+ }
+ if (player.p.role) {
+ player.role = player.p.role;
+ }
+ if (events.holidayseason && !player.p.firstbuff) {
+ add_condition(player, "holidayspirit");
+ player.p.firstbuff = true;
+ }
+ if (!player.p.ugrace || player.p.ugrace.length != 15) {
+ player.p.ugrace = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
+ } // first digit and some of the last aren't used [01/10/17]
+ if (!player.p.cgrace || player.p.cgrace.length != 15) {
+ player.p.cgrace = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
+ }
+ if (!player.p.ograce) {
+ player.p.ograce = 0;
+ }
+ if (!player.p.minutes) {
+ player.p.minutes = 0;
+ }
+ if (!player.p.stats) {
+ player.p.stats = { monsters: {} };
+ }
+ if (!player.p.stats.exchanges) {
+ player.p.stats.exchanges = {};
+ }
+ if (!player.p.stats.monsters_diff) {
+ player.p.stats.monsters_diff = {};
+ }
+ if (is_array(player.cx)) {
+ player.cx = {};
+ }
+ if (player.items.length < 42) {
+ player.items.length = 42;
}
- if(!player.p.emx) player.p.emx={};
- if(!player.p.ap) player.p.ap={}; // achievement progress
- if(!player.p.achievements) player.p.achievements={};
- if(player.p.mute) player.mute=true;
- if(player.p.role=="gm") player.gm=true;
- if(player.p.role) player.role=player.p.role;
- if(events.holidayseason && !player.p.firstbuff) add_condition(player,"holidayspirit"),player.p.firstbuff=true;
- if(!player.p.ugrace || player.p.ugrace.length!=15) player.p.ugrace=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]; // first digit and some of the last aren't used [01/10/17]
- if(!player.p.cgrace || player.p.cgrace.length!=15) player.p.cgrace=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0];
- if(!player.p.ograce) player.p.ograce=0;
- if(!player.p.minutes) player.p.minutes=0;
- if(!player.p.stats) player.p.stats={"monsters":{}};
- if(!player.p.stats.exchanges) player.p.stats.exchanges={};
- if(!player.p.stats.monsters_diff) player.p.stats.monsters_diff={};
- if(is_array(player.cx)) player.cx={};
- if(player.items.length<42) player.items.length=42;
//if(player.s.monsterhunt && player.s.monsterhunt.sn!=region+" "+server_name) delete player.s.monsterhunt;
- for(var n in player.s)
- {
- if(to_number(player.s[n])) player.s[n]={ms:to_number(player.s[n])};
+ for (var n in player.s) {
+ if (to_number(player.s[n])) {
+ player.s[n] = { ms: to_number(player.s[n]) };
+ }
}
- player.xyh=[{x:player.x,y:player.y,map:player.map,t:new Date()}]; // xy history
- player.rid=round(Math.random()*1000); // random number to randomise events
+ player.xyh = [{ x: player.x, y: player.y, map: player.map, t: new Date() }]; // xy history
+ player.rid = round(Math.random() * 1000); // random number to randomise events
}
-function init_player_exit(player) // these are safety routines, if a bug allows the inventory to grow infinitely, this prevents item duplication possibilities [18/10/18]
-{
- for(var id in player.q)
- player.q[id].stale=true;
- if(player.items.length>70) player.items.length=70;
- if(Object.keys(player.slots).length>500) player.slots={};
- for(var id in G.skills)
- {
- if(G.skills[id]['class'] && G.skills[id]['class'].includes(player.type) && G.skills[id].persistent && player.last[id])
- {
- player.p.dt[id]=player.last[id];
+function init_player_exit(player) {
+ // these are safety routines, if a bug allows the inventory to grow infinitely, this prevents item duplication possibilities [18/10/18]
+ for (var id in player.q) {
+ player.q[id].stale = true;
+ }
+ if (player.items.length > 70) {
+ player.items.length = 70;
+ }
+ if (Object.keys(player.slots).length > 500) {
+ player.slots = {};
+ }
+ for (var id in G.skills) {
+ if (
+ G.skills[id]["class"] &&
+ G.skills[id]["class"].includes(player.type) &&
+ G.skills[id].persistent &&
+ player.last[id]
+ ) {
+ player.p.dt[id] = player.last[id];
}
}
}
-function push_xyh(player,x,y)
-{
- if(!player.xyh) return;
- var last=player.xyh[player.xyh.length-1],current={x:x,y:y,map:player.map,t:new Date()};
- if(mssince(last.t)>50 || simple_distance(last,current)>1)
+function push_xyh(player, x, y) {
+ if (!player.xyh) {
+ return;
+ }
+ var last = player.xyh[player.xyh.length - 1];
+ var current = { x: x, y: y, map: player.map, t: new Date() };
+ if (mssince(last.t) > 50 || simple_distance(last, current) > 1) {
player.xyh.push(current);
- if(player.xyh.length>100) player.xyh.shift();
+ }
+ if (player.xyh.length > 100) {
+ player.xyh.shift();
+ }
}
-function item_name(item)
-{
- var def=G.items[item.name],name=def.name;
- if(item.level) name+=" +"+item.level;
+function item_name(item) {
+ var def = G.items[item.name];
+ var name = def.name;
+ if (item.level) {
+ name += " +" + item.level;
+ }
return name;
}
-function startswith_an(name)
-{
- if(in_arr(name.toLowerCase()[0],["a","e","o","u","i"])) return true;
+function startswith_an(name) {
+ if (in_arr(name.toLowerCase()[0], ["a", "e", "o", "u", "i"])) {
+ return true;
+ }
return false;
}
-function item_to_phrase(item)
-{
- if(item.q && item.q>1)
- return G.items[item.name].name+" [x"+item.q+"]";
- var prefix="";
- if(startswith_an(G.items[item.name].name)) prefix="an "
- else prefix="a ";
- if(item.p) prefix+=item.p.toTitleCase()+" ";
- if(item.level) return prefix+G.items[item.name].name+" +"+item.level;
- return prefix+G.items[item.name].name;
+function item_to_phrase(item) {
+ if (item.q && item.q > 1) {
+ return G.items[item.name].name + " [x" + item.q + "]";
+ }
+ var prefix = "";
+ if (startswith_an(G.items[item.name].name)) {
+ prefix = "an ";
+ } else {
+ prefix = "a ";
+ }
+ if (item.p) {
+ prefix += item.p.toTitleCase() + " ";
+ }
+ if (item.level) {
+ return prefix + G.items[item.name].name + " +" + item.level;
+ }
+ return prefix + G.items[item.name].name;
}
-function killed_message(type)
-{
- if(G.monsters[type].prefix==="the") return "killed the "+G.monsters[type].name;
- else if(G.monsters[type].prefix==="") return "killed "+G.monsters[type].name;
- else if(startswith_an(G.monsters[type].name)) return "killed an "+G.monsters[type].name;
- else return "killed a "+G.monsters[type].name;
+function killed_message(type) {
+ if (G.monsters[type].prefix === "the") {
+ return "killed the " + G.monsters[type].name;
+ } else if (G.monsters[type].prefix === "") {
+ return "killed " + G.monsters[type].name;
+ } else if (startswith_an(G.monsters[type].name)) {
+ return "killed an " + G.monsters[type].name;
+ } else {
+ return "killed a " + G.monsters[type].name;
+ }
}
-function is_xy_safe_old(map,x,y)
-{
- var safe=true;
- if(smap_data[map]==-1) return true;
- [[0,0],[0,smap_step+1],[0,-smap_step-1],[smap_step+1,0],[-smap_step-1,0],[0,smap_step/2],[smap_step/2,0],[0,-smap_step/2],[-smap_step/2,0]].forEach(function(m){
- var data=smap_data[map][phash(x+m[0],y+m[1])];
- if(data || data===undefined) safe=false;
+function is_xy_safe_old(map, x, y) {
+ var safe = true;
+ if (smap_data[map] == -1) {
+ return true;
+ }
+ [
+ [0, 0],
+ [0, smap_step + 1],
+ [0, -smap_step - 1],
+ [smap_step + 1, 0],
+ [-smap_step - 1, 0],
+ [0, smap_step / 2],
+ [smap_step / 2, 0],
+ [0, -smap_step / 2],
+ [-smap_step / 2, 0],
+ ].forEach(function (m) {
+ var data = smap_data[map][phash(x + m[0], y + m[1])];
+ if (data || data === undefined) {
+ safe = false;
+ }
});
return safe;
}
-function is_xy_safe(map,x,y)
-{
- var safe=true;
- if(smap_data[map]==-1) return true;
+function is_xy_safe(map, x, y) {
+ var safe = true;
+ if (smap_data[map] == -1) {
+ return true;
+ }
// x=parseInt(x)-(parseInt(x)%smap_step);
// y=parseInt(y)-(parseInt(y)%smap_step);
- [[0,0],[0,1],[0,-1],[1,0],[-1,0],[1,1],[-1,1],[1,-1],[-1,-1]].forEach(function(m){ // ,[2,2],[-2,-2],[2,-2],[-2,2]
- var data=smap_data[map][phash(x+m[0]*smap_step,y+m[1]*smap_step)];
- if(data || data===undefined) safe=false;
+ [
+ [0, 0],
+ [0, 1],
+ [0, -1],
+ [1, 0],
+ [-1, 0],
+ [1, 1],
+ [-1, 1],
+ [1, -1],
+ [-1, -1],
+ ].forEach(function (m) {
+ // ,[2,2],[-2,-2],[2,-2],[-2,2]
+ var data = smap_data[map][phash(x + m[0] * smap_step, y + m[1] * smap_step)];
+ if (data || data === undefined) {
+ safe = false;
+ }
});
return safe;
}
-function safe_xy_nearby(map,x,y)
-{
- var point=false;
+function safe_xy_nearby(map, x, y) {
+ var point = false;
// if(is_xy_safe(map,x,y)) return {x:x,y:y};
- x=smap_round(x); y=smap_round(y);
+ x = smap_round(x);
+ y = smap_round(y);
// [1,0],[0,1],[1,1],[-1,1],[1,-1],[-1,0],[0,-1],[-1,-1],[2,0],[0,2],[2,2],[-2,-2],[-2,0],[0,-2]
- [[0,0],[1,0],[0,1],[-1,0],[0,-1],[2,0],[0,2],[-2,0],[0,-2],[3,0],[0,3],[-3,0],[0,-3],].forEach(function(m){
- if(!point && is_xy_safe(map,x+m[0]*smap_step,y+m[1]*smap_step)) point={x:x+m[0]*smap_step,y:y+m[1]*smap_step};
+ [
+ [0, 0],
+ [1, 0],
+ [0, 1],
+ [-1, 0],
+ [0, -1],
+ [2, 0],
+ [0, 2],
+ [-2, 0],
+ [0, -2],
+ [3, 0],
+ [0, 3],
+ [-3, 0],
+ [0, -3],
+ ].forEach(function (m) {
+ if (!point && is_xy_safe(map, x + m[0] * smap_step, y + m[1] * smap_step)) {
+ point = { x: x + m[0] * smap_step, y: y + m[1] * smap_step };
+ }
});
return point;
-
}
-function smap_round(x) // for blink, port, magiport
-{
- var x1=parseInt(x)-(parseInt(x)%smap_step);
- var x2=x1+smap_step;
- if(x<0) x2=x1-smap_step;
- if(abs(x-x1)50000)
- {
- smap_data[map]=-1;
- server_log(map+" is either un-bounded or the spawn point is too close to an edge",1);
+ while (start < queue.length) {
+ if (queue.length > 50000) {
+ smap_data[map] = -1;
+ server_log(map + " is either un-bounded or the spawn point is too close to an edge", 1);
return;
}
- var current=queue[start++];
- [[0,smap_step],[0,-smap_step],[smap_step,0],[-smap_step,0]].forEach(function(m){
- if(level==0)
- {
- if(can_move({map:map,x:current[0],y:current[1],going_x:current[0]+m[0],going_y:current[1]+m[1]})) push(current[0]+m[0],current[1]+m[1],level);
- else push(current[0]+m[0],current[1]+m[1],level+1);
- }
- else
- {
- push(current[0]+m[0],current[1]+m[1],level+1);
+ var current = queue[start++];
+ [
+ [0, smap_step],
+ [0, -smap_step],
+ [smap_step, 0],
+ [-smap_step, 0],
+ ].forEach(function (m) {
+ if (level == 0) {
+ if (
+ can_move({ map: map, x: current[0], y: current[1], going_x: current[0] + m[0], going_y: current[1] + m[1] })
+ ) {
+ push(current[0] + m[0], current[1] + m[1], level);
+ } else {
+ push(current[0] + m[0], current[1] + m[1], level + 1);
+ }
+ } else {
+ push(current[0] + m[0], current[1] + m[1], level + 1);
}
});
}
- if(level==0 && 0) // In the new system, 1 is safe too [01/08/18]
- {
- for(var i=0;i<(G.maps[map].data.x_lines||[]).length;i++)
- {
- var current=G.maps[map].data.x_lines[i];
- push(current[0],current[1],0); push(current[0],current[2],0);
- for(var j=current[1];j120000)
- {
- amap_data[map]={};
- server_log(map+" is either un-bounded or the spawn point is too close to an edge [server_bfs2]",1);
+ x = parseInt(x) - (parseInt(x) % amap_step);
+ y = parseInt(y) - (parseInt(y) % amap_step);
+ return x + "|" + y;
+}
+
+function rphash2(x, y) {
+ if (x.x !== undefined) {
+ y = x.y;
+ x = x.x;
+ }
+ x = amap_round(x);
+ y = amap_round(y);
+ return x + "|" + y;
+}
+
+var amap_data = {};
+var amap_step = 8;
+function server_bfs2(map) {
+ var base = { h: 9, v: 9, vn: 2 };
+ var xmult = 1;
+ var vhmult = 1;
+ amap_data[map] = {}; //new Map(); - Map can't be sent to the Worker! :) [19/08/20]
+ var queue = [];
+ var visited = {};
+ var start = 0;
+ var level = 0;
+ var chiding_places = [];
+ function push(x, y, c) {
+ x = parseInt(x) - (parseInt(x) % amap_step);
+ y = parseInt(y) - (parseInt(y) % amap_step);
+ var hash = phash2(x, y);
+ if (visited[hash]) {
return;
}
- var current=queue[start++];
- [[amap_step,amap_step],[amap_step,-amap_step],[-amap_step,-amap_step],[-amap_step,amap_step],[0,amap_step],[0,-amap_step],[amap_step,0],[-amap_step,0]].forEach(function(m){
- if(can_move({map:map,x:current[0],y:current[1],going_x:current[0]+m[0]*xmult,going_y:current[1]+m[1]*xmult,base:base}))
- push(current[0]+m[0],current[1]+m[1]);
+ queue.push([x, y]);
+ visited[hash] = 1;
+ }
+ G.maps[map].spawns.forEach(function (s) {
+ var x = s[0];
+ var y = s[1];
+ var done = false;
+ x = parseInt(x) - (parseInt(x) % amap_step);
+ y = parseInt(y) - (parseInt(y) % amap_step);
+ var current = [x, y];
+ [
+ [0, 0],
+ [amap_step, amap_step],
+ [amap_step, -amap_step],
+ [-amap_step, -amap_step],
+ [-amap_step, amap_step],
+ [0, amap_step],
+ [0, -amap_step],
+ [amap_step, 0],
+ [-amap_step, 0],
+ ].forEach(function (m) {
+ if (
+ !done &&
+ can_move({
+ map: map,
+ x: x,
+ y: y,
+ going_x: current[0] + m[0] * xmult,
+ going_y: current[1] + m[1] * xmult,
+ base: base,
+ })
+ ) {
+ push(current[0] + m[0], current[1] + m[1], level);
+ done = true;
+ }
+ });
+ });
+ while (start < queue.length) {
+ if (queue.length > 120000) {
+ amap_data[map] = {};
+ server_log(map + " is either un-bounded or the spawn point is too close to an edge [server_bfs2]", 1);
+ return;
+ }
+ var current = queue[start++];
+ [
+ [amap_step, amap_step],
+ [amap_step, -amap_step],
+ [-amap_step, -amap_step],
+ [-amap_step, amap_step],
+ [0, amap_step],
+ [0, -amap_step],
+ [amap_step, 0],
+ [-amap_step, 0],
+ ].forEach(function (m) {
+ if (
+ can_move({
+ map: map,
+ x: current[0],
+ y: current[1],
+ going_x: current[0] + m[0] * xmult,
+ going_y: current[1] + m[1] * xmult,
+ base: base,
+ })
+ ) {
+ push(current[0] + m[0], current[1] + m[1]);
+ }
});
}
- for(var hash in visited)
- {
- var x=parseInt(hash.split("|")[0]);
- var y=parseInt(hash.split("|")[1]);
- var count=0;
- [[amap_step,amap_step],[amap_step,-amap_step],[-amap_step,-amap_step],[-amap_step,amap_step],[0,amap_step],[0,-amap_step],[amap_step,0],[-amap_step,0]].forEach(function(m){
- if(visited[(x+m[0])+"|"+(y+m[1])]) count+=1;
+ for (var hash in visited) {
+ var x = parseInt(hash.split("|")[0]);
+ var y = parseInt(hash.split("|")[1]);
+ var count = 0;
+ [
+ [amap_step, amap_step],
+ [amap_step, -amap_step],
+ [-amap_step, -amap_step],
+ [-amap_step, amap_step],
+ [0, amap_step],
+ [0, -amap_step],
+ [amap_step, 0],
+ [-amap_step, 0],
+ ].forEach(function (m) {
+ if (visited[x + m[0] + "|" + (y + m[1])]) {
+ count += 1;
+ }
});
- if(count>=2)
- {
- amap_data[map][hash]=1;
+ if (count >= 2) {
+ amap_data[map][hash] = 1;
}
}
- for(var hash in amap_data[map])
- {
- var x=parseInt(hash.split("|")[0]);
- var y=parseInt(hash.split("|")[1]);
- var count=0;
- [[amap_step,amap_step],[amap_step,-amap_step],[-amap_step,-amap_step],[-amap_step,amap_step],[0,amap_step],[0,-amap_step],[amap_step,0],[-amap_step,0]].forEach(function(m){
- if(amap_data[map][(x+m[0])+"|"+(y+m[1])]) count+=1;
+ for (var hash in amap_data[map]) {
+ var x = parseInt(hash.split("|")[0]);
+ var y = parseInt(hash.split("|")[1]);
+ var count = 0;
+ [
+ [amap_step, amap_step],
+ [amap_step, -amap_step],
+ [-amap_step, -amap_step],
+ [-amap_step, amap_step],
+ [0, amap_step],
+ [0, -amap_step],
+ [amap_step, 0],
+ [-amap_step, 0],
+ ].forEach(function (m) {
+ if (amap_data[map][x + m[0] + "|" + (y + m[1])]) {
+ count += 1;
+ }
});
- amap_data[map][hash]=count;
+ amap_data[map][hash] = count;
}
}
-function can_amove(map,sx,sy,tx,ty)
-{
- if(!amap_data[map][amap_round(tx)+"|"+amap_round(ty)]) return false;
-
- if(sy==ty)
- {
- var p=tx1200 || total>4000)
- {
- server_log(["heap","fast_astar"]);
- if(theone)
- {
- var result=finalise(theone);
+ while (heap.array.length) {
+ if (heap.array.length > 1200 || total > 4000) {
+ server_log(["heap", "fast_astar"]);
+ if (theone) {
+ var result = finalise(theone);
result.push("bad");
return result;
}
return null;
}
- var current=heap.removeTop(),dist=point_distance(current.x,current.y,tx,ty),rnd=Math.random()*100;
+ var current = heap.removeTop();
+ var dist = point_distance(current.x, current.y, tx, ty);
+ var rnd = Math.random() * 100;
// console.log([current.x,current.y,visited[current.x+"|"+current.y]]);
- if(dist<28)
- {
- good=true;
+ if (dist < 28) {
+ good = true;
return finalise(current);
}
- if(dist+current.bad-rnd1200 || last>4000)
- {
- server_log(["queue","fast_abfs"]);
- monster.bpath=(monster.bpath||0)+1;
- if(theone && monster.bpath<20)
- return finalise(theone);
+ if (!good && point_distance(sx, sy, dx, dy) < 30) {
return null;
}
- var current=queue[start++],dist=point_distance(current.x,current.y,tx,ty),rnd=Math.random()*100;
- if(dist<28)
- {
- monster.bpath=0; good=true;
- return finalise(current);
+ server_log([last, dx, dy, mssince(start_t)]);
+ return [dx, dy];
+ }
+ for (var step = 1; step <= 2; step++) {
+ if (last) {
+ break;
}
- if(dist+current.bad-rnd 1200 || last > 4000) {
+ server_log(["queue", "fast_abfs"]);
+ monster.bpath = (monster.bpath || 0) + 1;
+ if (theone && monster.bpath < 20) {
+ return finalise(theone);
+ }
+ return null;
+ }
+ var current = queue[start++];
+ var dist = point_distance(current.x, current.y, tx, ty);
+ var rnd = Math.random() * 100;
+ if (dist < 28) {
+ monster.bpath = 0;
+ good = true;
+ return finalise(current);
+ }
+ if (dist + current.bad - rnd < best) {
+ best = dist + current.bad - rnd;
+ theone = current;
+ }
+ [
+ [amap_step, amap_step, 0, amap_step * 1.41],
+ [amap_step, -amap_step, 1, amap_step * 1.41],
+ [-amap_step, -amap_step, 2, amap_step * 1.41],
+ [-amap_step, amap_step, 3, amap_step * 1.41],
+ [0, amap_step, 4, amap_step],
+ [0, -amap_step, 5, amap_step],
+ [amap_step, 0, 6, amap_step],
+ [-amap_step, 0, 7, amap_step],
+ ].forEach(function (m) {
+ var cx = current.x + m[0];
+ var cy = current.y + m[1];
+ if (amap_data[map][cx + "|" + cy] && !visited[cx + "|" + cy]) {
+ hpush(cx, cy, current.x + "|" + current.y, m[2], current.bad + m[3] + ((current.dir != m[2] && 0.5) || 0));
+ }
+ });
+ }
+ server_log(["no start", "fast_abfs"]);
}
-function add_call_cost(socket,num,method)
-{
- if(!socket) socket=1;
- if(is_number(socket)) num=socket,socket=current_socket;
- if(socket.socket) socket=socket.socket; // player
- if(!num) num=1;
- if(!method) method=ls_method;
+function add_call_cost(socket, num, method) {
+ if (!socket) {
+ socket = 1;
+ }
+ if (is_number(socket)) {
+ num = socket;
+ socket = current_socket;
+ }
+ if (socket.socket) {
+ socket = socket.socket;
+ } // player
+ if (!num) {
+ num = 1;
+ }
+ if (!method) {
+ method = ls_method;
+ }
+ while (socket.calls.length && mssince(socket.calls[0][0]) > 4000) {
+ socket.calls.shift();
+ } // #TODO: make one operation [27/02/23]
- while(socket.calls.length && mssince(socket.calls[0][0])>4000) socket.calls.shift(); // #TODO: make one operation [27/02/23]
-
- if(socket.calls.length && socket.calls[socket.calls.length-1][1]==method && num!=-1)
- socket.calls[socket.calls.length-1][2]+=num;
- else
- socket.calls.push([new Date(),method,num==-1?1:num]);
-}
-
-function reduce_call_cost(socket,num)
-{
- if(!socket) socket=1;
- if(is_number(socket)) num=socket,socket=current_socket;
- if(socket.socket) socket=socket.socket; // player
- if(!num) num=1;
-
- if(socket.calls.length && socket.calls[socket.calls.length-1][1]==ls_method)
- {
- socket.calls[socket.calls.length-1][2]-=num;
- if(socket.calls[socket.calls.length-1][2]<=0)
- socket.calls.pop();
+ if (socket.calls.length && socket.calls[socket.calls.length - 1][1] == method && num != -1) {
+ socket.calls[socket.calls.length - 1][2] += num;
+ } else {
+ socket.calls.push([new Date(), method, num == -1 ? 1 : num]);
}
}
-function get_call_cost(socket)
-{
- if(!socket) socket=current_socket;
- if(socket.socket) socket=socket.socket; // player
+function reduce_call_cost(socket, num) {
+ if (!socket) {
+ socket = 1;
+ }
+ if (is_number(socket)) {
+ num = socket;
+ socket = current_socket;
+ }
+ if (socket.socket) {
+ socket = socket.socket;
+ } // player
+ if (!num) {
+ num = 1;
+ }
- while(socket.calls.length && mssince(socket.calls[0][0])>4000) socket.calls.shift(); // #TODO: make one operation [27/02/23]
+ if (socket.calls.length && socket.calls[socket.calls.length - 1][1] == ls_method) {
+ socket.calls[socket.calls.length - 1][2] -= num;
+ if (socket.calls[socket.calls.length - 1][2] <= 0) {
+ socket.calls.pop();
+ }
+ }
+}
- var cost=0;
- socket.calls.forEach(function(c){cost+=c[2];});
+function get_call_cost(socket) {
+ if (!socket) {
+ socket = current_socket;
+ }
+ if (socket.socket) {
+ socket = socket.socket;
+ } // player
+
+ while (socket.calls.length && mssince(socket.calls[0][0]) > 4000) {
+ socket.calls.shift();
+ } // #TODO: make one operation [27/02/23]
+
+ var cost = 0;
+ socket.calls.forEach(function (c) {
+ cost += c[2];
+ });
return cost;
}
-
-function set_direction(){} // compatibility
+function set_direction() {} // compatibility
function symmetricDecrypt(input, key, checkHmac) {
- var aesIv = crypto.createDecipheriv('aes-256-ecb', key, '');
+ var aesIv = crypto.createDecipheriv("aes-256-ecb", key, "");
aesIv.setAutoPadding(false);
aesIv.end(input.slice(0, 16));
var iv = aesIv.read();
- var aesData = crypto.createDecipheriv('aes-256-cbc', key, iv);
+ var aesData = crypto.createDecipheriv("aes-256-cbc", key, iv);
aesData.end(input.slice(16));
var plaintext = aesData.read();
@@ -3392,7 +4709,7 @@ function symmetricDecrypt(input, key, checkHmac) {
}
return plaintext;
-};
+}
function parseAppTicket(ticket) {
// https://github.com/SteamRE/SteamKit/blob/master/Resources/Structs/steam3_appticket.hsl
@@ -3438,11 +4755,16 @@ function parseAppTicket(ticket) {
// Start reading the ownership ticket
let ownershipTicketOffset = ticket.offset;
let ownershipTicketLength = ticket.readUint32(); // including itself, for some reason
- if (ownershipTicketOffset + ownershipTicketLength != ticket.limit && ownershipTicketOffset + ownershipTicketLength + 128 != ticket.limit) {
+ if (
+ ownershipTicketOffset + ownershipTicketLength != ticket.limit &&
+ ownershipTicketOffset + ownershipTicketLength + 128 != ticket.limit
+ ) {
return null;
}
- let i, j, dlc;
+ let i;
+ let j;
+ let dlc;
details.version = ticket.readUint32();
details.steamID = ticket.readUint64().toString();
@@ -3485,27 +4807,40 @@ function parseAppTicket(ticket) {
let date = new Date();
details.isExpired = details.ownershipTicketExpires < date;
- details.hasValidSignature = !!details.signature && SteamCrypto.verifySignature(ticket.slice(ownershipTicketOffset, ownershipTicketOffset + ownershipTicketLength).toBuffer(), details.signature);
+ details.hasValidSignature =
+ !!details.signature &&
+ SteamCrypto.verifySignature(
+ ticket.slice(ownershipTicketOffset, ownershipTicketOffset + ownershipTicketLength).toBuffer(),
+ details.signature,
+ );
details.isValid = !details.isExpired && (!details.signature || details.hasValidSignature);
} catch (ex) {
- console.log("parseAppTicket: "+ex);
+ console.log("parseAppTicket: " + ex);
return details;
return null; // not a valid ticket
}
return details;
+}
+
+var proto = {
+ nested: {
+ EncryptedAppTicket: {
+ fields: {
+ ticketVersionNo: { type: "uint32", id: 1 },
+ crcEncryptedticket: { type: "uint32", id: 2 },
+ cbEncrypteduserdata: { type: "uint32", id: 3 },
+ cbEncryptedAppownershipticket: { type: "uint32", id: 4 },
+ encryptedTicket: { type: "bytes", id: 5 },
+ },
+ },
+ },
};
+var proto_root = protobuf.Root.fromJSON(proto);
+var EncryptedAppTicket = proto_root.lookupType("EncryptedAppTicket");
-var proto={ "nested": {EncryptedAppTicket: { fields:
- { ticketVersionNo: { type: 'uint32', id: 1 },
- crcEncryptedticket: { type: 'uint32', id: 2 },
- cbEncrypteduserdata: { type: 'uint32', id: 3 },
- cbEncryptedAppownershipticket: { type: 'uint32', id: 4 },
- encryptedTicket: { type: 'bytes', id: 5 } } }}};
-var proto_root=protobuf.Root.fromJSON(proto);
-var EncryptedAppTicket=proto_root.lookupType("EncryptedAppTicket");
-
-function getClientIp(req) { //https://github.com/pbojinov/request-ip/blob/master/index.js
+function getClientIp(req) {
+ //https://github.com/pbojinov/request-ip/blob/master/index.js
// NOTE: Back in the day, we had a system called ipass - for some weird and unexplainable reason, no Node server, mainly Socket.io, can track the current IP of a client
// So the clients needed to ping the game every 40 seconds, at a secondary, http-only handler just to get their IP - and, again, for some extremely weird reason, Node servers, don't let you just easily disconnect a client
// Rather than auto Keep-Alive, so it had a hacky disconnect routine - all in all, decided to move this system to App Engine, while the SSL refactoring was happening [17/11/18]
@@ -3515,20 +4850,21 @@ function getClientIp(req) { //https://github.com/pbojinov/request-ip/blob/master
// workaround to get real client IP
// most likely because our app will be behind a [reverse] proxy or load balancer
- var clientIp = req.headers['x-client-ip'];
- var forwardedForAlt = req.headers['x-forwarded-for'];
- var realIp = req.headers['x-real-ip'];
-
+ var clientIp = req.headers["x-client-ip"];
+ var forwardedForAlt = req.headers["x-forwarded-for"];
+ var realIp = req.headers["x-real-ip"];
+
// more obsure ones below
- var clusterClientIp = req.headers['x-cluster-client-ip'];
- var forwardedAlt = req.headers['x-forwarded'];
- var forwardedFor = req.headers['forwarded-for'];
- var forwarded = req.headers['forwarded'];
-
+ var clusterClientIp = req.headers["x-cluster-client-ip"];
+ var forwardedAlt = req.headers["x-forwarded"];
+ var forwardedFor = req.headers["forwarded-for"];
+ var forwarded = req.headers["forwarded"];
+
// remote address check
var reqConnectionRemoteAddress = req.connection ? req.connection.remoteAddress : null;
var reqSocketRemoteAddress = req.socket ? req.socket.remoteAddress : null;
- var reqConnectionSocketRemoteAddress = (req.connection && req.connection.socket) ? req.connection.socket.remoteAddress : null;
+ var reqConnectionSocketRemoteAddress =
+ req.connection && req.connection.socket ? req.connection.socket.remoteAddress : null;
var reqInfoRemoteAddress = req.info ? req.info.remoteAddress : null;
// x-client-ip
@@ -3539,23 +4875,23 @@ function getClientIp(req) { //https://github.com/pbojinov/request-ip/blob/master
// x-forwarded-for
// (typically when your node app is behind a load-balancer (eg. AWS ELB) or proxy)
else if (forwardedForAlt) {
- // x-forwarded-for may return multiple IP addresses in the format:
- // "client IP, proxy 1 IP, proxy 2 IP"
- // Therefore, the right-most IP address is the IP address of the most recent proxy
+ // x-forwarded-for may return multiple IP addresses in the format:
+ // "client IP, proxy 1 IP, proxy 2 IP"
+ // Therefore, the right-most IP address is the IP address of the most recent proxy
// and the left-most IP address is the IP address of the originating client.
// source: http://docs.aws.amazon.com/elasticloadbalancing/latest/classic/x-forwarded-headers.html
- var forwardedIps = forwardedForAlt.split(',');
+ var forwardedIps = forwardedForAlt.split(",");
ipAddress = forwardedIps[0];
}
- // x-real-ip
+ // x-real-ip
// (default nginx proxy/fcgi)
else if (realIp) {
// alternative to x-forwarded-for, used by some proxies
ipAddress = realIp;
}
- // x-cluster-client-ip
+ // x-cluster-client-ip
// (Rackspace LB and Riverbed's Stingray)
// http://www.rackspace.com/knowledge_center/article/controlling-access-to-linux-cloud-sites-based-on-the-client-ip-address
// https://splash.riverbed.com/docs/DOC-1926
@@ -3581,84 +4917,133 @@ function getClientIp(req) { //https://github.com/pbojinov/request-ip/blob/master
// remote address checks
else if (reqConnectionRemoteAddress) {
ipAddress = reqConnectionRemoteAddress;
+ } else if (reqSocketRemoteAddress) {
+ ipAddress = reqSocketRemoteAddress;
+ } else if (reqConnectionSocketRemoteAddress) {
+ ipAddress = reqConnectionSocketRemoteAddress;
+ } else if (reqInfoRemoteAddress) {
+ ipAddress = reqInfoRemoteAddress;
}
- else if (reqSocketRemoteAddress) {
- ipAddress = reqSocketRemoteAddress
- }
- else if (reqConnectionSocketRemoteAddress) {
- ipAddress = reqConnectionSocketRemoteAddress
- }
- else if (reqInfoRemoteAddress) {
- ipAddress = reqInfoRemoteAddress
- }
// return null if we cannot find an address
else {
ipAddress = null;
}
-
+
return ipAddress;
}
-function deduct_gender(player)
-{
- if(player.cx && player.cx.head && player.cx.head[0]=="f") return "female";
+function deduct_gender(player) {
+ if (player.cx && player.cx.head && player.cx.head[0] == "f") {
+ return "female";
+ }
return "male";
}
-function safe_search(obj,phrase)
-{
- obj=JSON.parse(safe_stringify(obj));
- for(l1 in obj)
- {
- var c1=obj[l1];
- if(c1 && is_string(c1) && c1.indexOf(phrase)!=-1 || l1.indexOf(phrase)!=-1) console.log(l1+" ");
- if(!is_object(c1)) continue;
- for(l2 in c1)
- {
- var c2=c1[l2];
- if(c2 && is_string(c2) && c2.indexOf(phrase)!=-1 || l2.indexOf(phrase)!=-1) console.log(l1+" "+l2);
- if(!is_object(c2)) continue;
- for(l3 in c2)
- {
- var c3=c2[l3];
- if(c3 && is_string(c3) && c3.indexOf(phrase)!=-1 || l3.indexOf(phrase)!=-1) console.log(l1+" "+l2+" "+l3);
- if(!is_object(c3)) continue;
- for(l4 in c3)
- {
- var c4=c3[l4];
- if(c4 && is_string(c4) && c4.indexOf(phrase)!=-1 || l4.indexOf(phrase)!=-1) console.log(l1+" "+l2+" "+l3+" "+l4);
- if(!is_object(c4)) continue;
- for(l5 in c4)
- {
- var c5=c4[l5];
- if(c5 && is_string(c5) && c5.indexOf(phrase)!=-1 || l5.indexOf(phrase)!=-1) console.log(l1+" "+l2+" "+l3+" "+l4+" "+l5);
- if(!is_object(c5)) continue;
- for(l6 in c5)
- {
- var c6=c5[l6];
- if(c6 && is_string(c6) && c6.indexOf(phrase)!=-1 || l6.indexOf(phrase)!=-1) console.log(l1+" "+l2+" "+l3+" "+l4+" "+l5+" "+l6);
- if(!is_object(c6)) continue;
- for(l7 in c6)
- {
- var c7=c6[l7];
- if(c7 && is_string(c7) && c7.indexOf(phrase)!=-1 || l7.indexOf(phrase)!=-1) console.log(l1+" "+l2+" "+l3+" "+l4+" "+l5+" "+l6+" "+l7);
- if(!is_object(c7)) continue;
- for(l8 in c7)
- {
- var c8=c7[l8];
- if(c8 && is_string(c8) && c8.indexOf(phrase)!=-1 || l8.indexOf(phrase)!=-1) console.log(l1+" "+l2+" "+l3+" "+l4+" "+l5+" "+l6+" "+l7+" "+l8);
- if(!is_object(c8)) continue;
- for(l9 in c8)
- {
- var c9=c8[l9];
- if(c9 && is_string(c9) && c9.indexOf(phrase)!=-1 || l9.indexOf(phrase)!=-1) console.log(l1+" "+l2+" "+l3+" "+l4+" "+l5+" "+l6+" "+l7+" "+l8+" "+l9);
- if(!is_object(c9)) continue;
- for(l10 in c9)
- {
- var c10=c9[l10];
- if(c10 && is_string(c10) && c10.indexOf(phrase)!=-1 || l10.indexOf(phrase)!=-1) console.log(l1+" "+l2+" "+l3+" "+l4+" "+l5+" "+l6+" "+l7+" "+l8+" "+l9+" "+l10);
- if(!is_object(c10)) continue;
+function safe_search(obj, phrase) {
+ obj = JSON.parse(safe_stringify(obj));
+ for (l1 in obj) {
+ var c1 = obj[l1];
+ if ((c1 && is_string(c1) && c1.indexOf(phrase) != -1) || l1.indexOf(phrase) != -1) {
+ console.log(l1 + " ");
+ }
+ if (!is_object(c1)) {
+ continue;
+ }
+ for (l2 in c1) {
+ var c2 = c1[l2];
+ if ((c2 && is_string(c2) && c2.indexOf(phrase) != -1) || l2.indexOf(phrase) != -1) {
+ console.log(l1 + " " + l2);
+ }
+ if (!is_object(c2)) {
+ continue;
+ }
+ for (l3 in c2) {
+ var c3 = c2[l3];
+ if ((c3 && is_string(c3) && c3.indexOf(phrase) != -1) || l3.indexOf(phrase) != -1) {
+ console.log(l1 + " " + l2 + " " + l3);
+ }
+ if (!is_object(c3)) {
+ continue;
+ }
+ for (l4 in c3) {
+ var c4 = c3[l4];
+ if ((c4 && is_string(c4) && c4.indexOf(phrase) != -1) || l4.indexOf(phrase) != -1) {
+ console.log(l1 + " " + l2 + " " + l3 + " " + l4);
+ }
+ if (!is_object(c4)) {
+ continue;
+ }
+ for (l5 in c4) {
+ var c5 = c4[l5];
+ if ((c5 && is_string(c5) && c5.indexOf(phrase) != -1) || l5.indexOf(phrase) != -1) {
+ console.log(l1 + " " + l2 + " " + l3 + " " + l4 + " " + l5);
+ }
+ if (!is_object(c5)) {
+ continue;
+ }
+ for (l6 in c5) {
+ var c6 = c5[l6];
+ if ((c6 && is_string(c6) && c6.indexOf(phrase) != -1) || l6.indexOf(phrase) != -1) {
+ console.log(l1 + " " + l2 + " " + l3 + " " + l4 + " " + l5 + " " + l6);
+ }
+ if (!is_object(c6)) {
+ continue;
+ }
+ for (l7 in c6) {
+ var c7 = c6[l7];
+ if ((c7 && is_string(c7) && c7.indexOf(phrase) != -1) || l7.indexOf(phrase) != -1) {
+ console.log(l1 + " " + l2 + " " + l3 + " " + l4 + " " + l5 + " " + l6 + " " + l7);
+ }
+ if (!is_object(c7)) {
+ continue;
+ }
+ for (l8 in c7) {
+ var c8 = c7[l8];
+ if ((c8 && is_string(c8) && c8.indexOf(phrase) != -1) || l8.indexOf(phrase) != -1) {
+ console.log(l1 + " " + l2 + " " + l3 + " " + l4 + " " + l5 + " " + l6 + " " + l7 + " " + l8);
+ }
+ if (!is_object(c8)) {
+ continue;
+ }
+ for (l9 in c8) {
+ var c9 = c8[l9];
+ if ((c9 && is_string(c9) && c9.indexOf(phrase) != -1) || l9.indexOf(phrase) != -1) {
+ console.log(
+ l1 + " " + l2 + " " + l3 + " " + l4 + " " + l5 + " " + l6 + " " + l7 + " " + l8 + " " + l9,
+ );
+ }
+ if (!is_object(c9)) {
+ continue;
+ }
+ for (l10 in c9) {
+ var c10 = c9[l10];
+ if ((c10 && is_string(c10) && c10.indexOf(phrase) != -1) || l10.indexOf(phrase) != -1) {
+ console.log(
+ l1 +
+ " " +
+ l2 +
+ " " +
+ l3 +
+ " " +
+ l4 +
+ " " +
+ l5 +
+ " " +
+ l6 +
+ " " +
+ l7 +
+ " " +
+ l8 +
+ " " +
+ l9 +
+ " " +
+ l10,
+ );
+ }
+ if (!is_object(c10)) {
+ continue;
+ }
}
}
}
@@ -3671,207 +5056,277 @@ function safe_search(obj,phrase)
}
}
-function strip_string(str)
-{
- var regexSymbolWithCombiningMarks = /([\0-\u02FF\u0370-\u1AAF\u1B00-\u1DBF\u1E00-\u20CF\u2100-\uD7FF\uE000-\uFE1F\uFE30-\uFFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])([\u0300-\u036F\u1AB0-\u1AFF\u1DC0-\u1DFF\u20D0-\u20FF\uFE20-\uFE2F]+)/g;
- var regexLineBreakCombiningMarks = /[\0-\x08\x0E-\x1F\x7F-\x84\x86-\x9F\u0300-\u034E\u0350-\u035B\u0363-\u036F\u0483-\u0489\u0591-\u05BD\u05BF\u05C1\u05C2\u05C4\u05C5\u05C7\u0610-\u061A\u061C\u064B-\u065F\u0670\u06D6-\u06DC\u06DF-\u06E4\u06E7\u06E8\u06EA-\u06ED\u0711\u0730-\u074A\u07A6-\u07B0\u07EB-\u07F3\u0816-\u0819\u081B-\u0823\u0825-\u0827\u0829-\u082D\u0859-\u085B\u08D4-\u08E1\u08E3-\u0903\u093A-\u093C\u093E-\u094F\u0951-\u0957\u0962\u0963\u0981-\u0983\u09BC\u09BE-\u09C4\u09C7\u09C8\u09CB-\u09CD\u09D7\u09E2\u09E3\u0A01-\u0A03\u0A3C\u0A3E-\u0A42\u0A47\u0A48\u0A4B-\u0A4D\u0A51\u0A70\u0A71\u0A75\u0A81-\u0A83\u0ABC\u0ABE-\u0AC5\u0AC7-\u0AC9\u0ACB-\u0ACD\u0AE2\u0AE3\u0B01-\u0B03\u0B3C\u0B3E-\u0B44\u0B47\u0B48\u0B4B-\u0B4D\u0B56\u0B57\u0B62\u0B63\u0B82\u0BBE-\u0BC2\u0BC6-\u0BC8\u0BCA-\u0BCD\u0BD7\u0C00-\u0C03\u0C3E-\u0C44\u0C46-\u0C48\u0C4A-\u0C4D\u0C55\u0C56\u0C62\u0C63\u0C81-\u0C83\u0CBC\u0CBE-\u0CC4\u0CC6-\u0CC8\u0CCA-\u0CCD\u0CD5\u0CD6\u0CE2\u0CE3\u0D01-\u0D03\u0D3E-\u0D44\u0D46-\u0D48\u0D4A-\u0D4D\u0D57\u0D62\u0D63\u0D82\u0D83\u0DCA\u0DCF-\u0DD4\u0DD6\u0DD8-\u0DDF\u0DF2\u0DF3\u0F18\u0F19\u0F35\u0F37\u0F39\u0F3E\u0F3F\u0F71-\u0F7E\u0F80-\u0F84\u0F86\u0F87\u0F8D-\u0F97\u0F99-\u0FBC\u0FC6\u135D-\u135F\u1712-\u1714\u1732-\u1734\u1752\u1753\u1772\u1773\u180B-\u180D\u1885\u1886\u18A9\u1920-\u192B\u1930-\u193B\u1A17-\u1A1B\u1A7F\u1AB0-\u1ABE\u1B00-\u1B04\u1B34-\u1B44\u1B6B-\u1B73\u1B80-\u1B82\u1BA1-\u1BAD\u1BE6-\u1BF3\u1C24-\u1C37\u1CD0-\u1CD2\u1CD4-\u1CE8\u1CED\u1CF2-\u1CF4\u1CF8\u1CF9\u1DC0-\u1DF5\u1DFB-\u1DFF\u200C\u200E\u200F\u202A-\u202E\u2066-\u206F\u20D0-\u20F0\u2CEF-\u2CF1\u2D7F\u2DE0-\u2DFF\u302A-\u302F\u3035\u3099\u309A\uA66F-\uA672\uA674-\uA67D\uA69E\uA69F\uA6F0\uA6F1\uA802\uA806\uA80B\uA823-\uA827\uA880\uA881\uA8B4-\uA8C5\uA8E0-\uA8F1\uA926-\uA92D\uA947-\uA953\uA980-\uA983\uA9B3-\uA9C0\uAA29-\uAA36\uAA43\uAA4C\uAA4D\uAAEB-\uAAEF\uAAF5\uAAF6\uABE3-\uABEA\uABEC\uABED\uFB1E\uFE00-\uFE0F\uFE20-\uFE2F\uFFF9-\uFFFB]|\uD800[\uDDFD\uDEE0\uDF76-\uDF7A]|\uD802[\uDE01-\uDE03\uDE05\uDE06\uDE0C-\uDE0F\uDE38-\uDE3A\uDE3F\uDEE5\uDEE6]|\uD804[\uDC00-\uDC02\uDC38-\uDC46\uDC7F-\uDC82\uDCB0-\uDCBA\uDD00-\uDD02\uDD27-\uDD34\uDD73\uDD80-\uDD82\uDDB3-\uDDC0\uDDCA-\uDDCC\uDE2C-\uDE37\uDE3E\uDEDF-\uDEEA\uDF00-\uDF03\uDF3C\uDF3E-\uDF44\uDF47\uDF48\uDF4B-\uDF4D\uDF57\uDF62\uDF63\uDF66-\uDF6C\uDF70-\uDF74]|\uD805[\uDC35-\uDC46\uDCB0-\uDCC3\uDDAF-\uDDB5\uDDB8-\uDDC0\uDDDC\uDDDD\uDE30-\uDE40\uDEAB-\uDEB7]|\uD807[\uDC2F-\uDC36\uDC38-\uDC3F\uDC92-\uDCA7\uDCA9-\uDCB6]|\uD81A[\uDEF0-\uDEF4\uDF30-\uDF36]|\uD81B[\uDF51-\uDF7E\uDF8F-\uDF92]|\uD82F[\uDC9D\uDC9E\uDCA0-\uDCA3]|\uD834[\uDD65-\uDD69\uDD6D-\uDD82\uDD85-\uDD8B\uDDAA-\uDDAD\uDE42-\uDE44]|\uD836[\uDE00-\uDE36\uDE3B-\uDE6C\uDE75\uDE84\uDE9B-\uDE9F\uDEA1-\uDEAF]|\uD838[\uDC00-\uDC06\uDC08-\uDC18\uDC1B-\uDC21\uDC23\uDC24\uDC26-\uDC2A]|\uD83A[\uDCD0-\uDCD6\uDD44-\uDD4A]|\uDB40[\uDC01\uDC20-\uDC7F\uDD00-\uDDEF]/g;
+/* eslint-disable no-misleading-character-class,no-control-regex */
+function strip_string(str) {
+ var regexSymbolWithCombiningMarks =
+ /([\0-\u02FF\u0370-\u1AAF\u1B00-\u1DBF\u1E00-\u20CF\u2100-\uD7FF\uE000-\uFE1F\uFE30-\uFFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])([\u0300-\u036F\u1AB0-\u1AFF\u1DC0-\u1DFF\u20D0-\u20FF\uFE20-\uFE2F]+)/g;
+ var regexLineBreakCombiningMarks =
+ /[\0-\x08\x0E-\x1F\x7F-\x84\x86-\x9F\u0300-\u034E\u0350-\u035B\u0363-\u036F\u0483-\u0489\u0591-\u05BD\u05BF\u05C1\u05C2\u05C4\u05C5\u05C7\u0610-\u061A\u061C\u064B-\u065F\u0670\u06D6-\u06DC\u06DF-\u06E4\u06E7\u06E8\u06EA-\u06ED\u0711\u0730-\u074A\u07A6-\u07B0\u07EB-\u07F3\u0816-\u0819\u081B-\u0823\u0825-\u0827\u0829-\u082D\u0859-\u085B\u08D4-\u08E1\u08E3-\u0903\u093A-\u093C\u093E-\u094F\u0951-\u0957\u0962\u0963\u0981-\u0983\u09BC\u09BE-\u09C4\u09C7\u09C8\u09CB-\u09CD\u09D7\u09E2\u09E3\u0A01-\u0A03\u0A3C\u0A3E-\u0A42\u0A47\u0A48\u0A4B-\u0A4D\u0A51\u0A70\u0A71\u0A75\u0A81-\u0A83\u0ABC\u0ABE-\u0AC5\u0AC7-\u0AC9\u0ACB-\u0ACD\u0AE2\u0AE3\u0B01-\u0B03\u0B3C\u0B3E-\u0B44\u0B47\u0B48\u0B4B-\u0B4D\u0B56\u0B57\u0B62\u0B63\u0B82\u0BBE-\u0BC2\u0BC6-\u0BC8\u0BCA-\u0BCD\u0BD7\u0C00-\u0C03\u0C3E-\u0C44\u0C46-\u0C48\u0C4A-\u0C4D\u0C55\u0C56\u0C62\u0C63\u0C81-\u0C83\u0CBC\u0CBE-\u0CC4\u0CC6-\u0CC8\u0CCA-\u0CCD\u0CD5\u0CD6\u0CE2\u0CE3\u0D01-\u0D03\u0D3E-\u0D44\u0D46-\u0D48\u0D4A-\u0D4D\u0D57\u0D62\u0D63\u0D82\u0D83\u0DCA\u0DCF-\u0DD4\u0DD6\u0DD8-\u0DDF\u0DF2\u0DF3\u0F18\u0F19\u0F35\u0F37\u0F39\u0F3E\u0F3F\u0F71-\u0F7E\u0F80-\u0F84\u0F86\u0F87\u0F8D-\u0F97\u0F99-\u0FBC\u0FC6\u135D-\u135F\u1712-\u1714\u1732-\u1734\u1752\u1753\u1772\u1773\u180B-\u180D\u1885\u1886\u18A9\u1920-\u192B\u1930-\u193B\u1A17-\u1A1B\u1A7F\u1AB0-\u1ABE\u1B00-\u1B04\u1B34-\u1B44\u1B6B-\u1B73\u1B80-\u1B82\u1BA1-\u1BAD\u1BE6-\u1BF3\u1C24-\u1C37\u1CD0-\u1CD2\u1CD4-\u1CE8\u1CED\u1CF2-\u1CF4\u1CF8\u1CF9\u1DC0-\u1DF5\u1DFB-\u1DFF\u200C\u200E\u200F\u202A-\u202E\u2066-\u206F\u20D0-\u20F0\u2CEF-\u2CF1\u2D7F\u2DE0-\u2DFF\u302A-\u302F\u3035\u3099\u309A\uA66F-\uA672\uA674-\uA67D\uA69E\uA69F\uA6F0\uA6F1\uA802\uA806\uA80B\uA823-\uA827\uA880\uA881\uA8B4-\uA8C5\uA8E0-\uA8F1\uA926-\uA92D\uA947-\uA953\uA980-\uA983\uA9B3-\uA9C0\uAA29-\uAA36\uAA43\uAA4C\uAA4D\uAAEB-\uAAEF\uAAF5\uAAF6\uABE3-\uABEA\uABEC\uABED\uFB1E\uFE00-\uFE0F\uFE20-\uFE2F\uFFF9-\uFFFB]|\uD800[\uDDFD\uDEE0\uDF76-\uDF7A]|\uD802[\uDE01-\uDE03\uDE05\uDE06\uDE0C-\uDE0F\uDE38-\uDE3A\uDE3F\uDEE5\uDEE6]|\uD804[\uDC00-\uDC02\uDC38-\uDC46\uDC7F-\uDC82\uDCB0-\uDCBA\uDD00-\uDD02\uDD27-\uDD34\uDD73\uDD80-\uDD82\uDDB3-\uDDC0\uDDCA-\uDDCC\uDE2C-\uDE37\uDE3E\uDEDF-\uDEEA\uDF00-\uDF03\uDF3C\uDF3E-\uDF44\uDF47\uDF48\uDF4B-\uDF4D\uDF57\uDF62\uDF63\uDF66-\uDF6C\uDF70-\uDF74]|\uD805[\uDC35-\uDC46\uDCB0-\uDCC3\uDDAF-\uDDB5\uDDB8-\uDDC0\uDDDC\uDDDD\uDE30-\uDE40\uDEAB-\uDEB7]|\uD807[\uDC2F-\uDC36\uDC38-\uDC3F\uDC92-\uDCA7\uDCA9-\uDCB6]|\uD81A[\uDEF0-\uDEF4\uDF30-\uDF36]|\uD81B[\uDF51-\uDF7E\uDF8F-\uDF92]|\uD82F[\uDC9D\uDC9E\uDCA0-\uDCA3]|\uD834[\uDD65-\uDD69\uDD6D-\uDD82\uDD85-\uDD8B\uDDAA-\uDDAD\uDE42-\uDE44]|\uD836[\uDE00-\uDE36\uDE3B-\uDE6C\uDE75\uDE84\uDE9B-\uDE9F\uDEA1-\uDEAF]|\uD838[\uDC00-\uDC06\uDC08-\uDC18\uDC1B-\uDC21\uDC23\uDC24\uDC26-\uDC2A]|\uD83A[\uDCD0-\uDCD6\uDD44-\uDD4A]|\uDB40[\uDC01\uDC20-\uDC7F\uDD00-\uDDEF]/g;
// https://github.com/mathiasbynens/strip-combining-marks/blob/master/strip-combining-marks.js
- return str.replace(regexLineBreakCombiningMarks, '').replace(regexSymbolWithCombiningMarks, '$1').replace(/[^\p{L}\p{N}\p{S}\p{P}\p{Z}]/gu, ''); // https://stackoverflow.com/a/63464318/914546
+ return str
+ .replace(regexLineBreakCombiningMarks, "")
+ .replace(regexSymbolWithCombiningMarks, "$1")
+ .replace(/[^\p{L}\p{N}\p{S}\p{P}\p{Z}]/gu, ""); // https://stackoverflow.com/a/63464318/914546
}
+/* eslint-enable no-misleading-character-class,no-control-regex */
// #HARDCORE
-var hardcore_done=false;
-function hardcore_loop()
-{
- if(hardcore_done) return;
- var m=0;
- for(var id in players)
- if(players[id].level>m)
- E.rewards.leader=players[id].name,m=players[id].level;
- if(E.minutes)
- E.minutes-=1;
- else
- {
- hardcore_done=true;
+var hardcore_done = false;
+function hardcore_loop() {
+ if (hardcore_done) {
+ return;
+ }
+ var m = 0;
+ for (var id in players) {
+ if (players[id].level > m) {
+ E.rewards.leader = players[id].name;
+ m = players[id].level;
+ }
+ }
+ if (E.minutes) {
+ E.minutes -= 1;
+ } else {
+ hardcore_done = true;
send_hardcore_rewards();
shutdown_routine();
}
- broadcast("hardcore_info",{E:E});
+ broadcast("hardcore_info", { E: E });
}
// #ACHIEVEMENTS
-function send_hardcore_rewards()
-{
- rd=[
- ["leader","Leadership",{"name":"xbox",q:1}],
- ["item8","First +8 Item",{"name":"armorbox",q:10}],
- ["item9","First +9 Item",{"name":"weaponbox",q:10}],
- ["item10","First +X Item",{"name":"armorbox",q:100}],
- ["item11","First +Y Item",{"name":"armorbox",q:100}],
- ["item12","First +Z Item",{"name":"scroll3",q:1}],
- ["accessory5","First +V Accessory",{"name":"armorbox",q:50}],
- ["accessory6","First +S Accessory",{"name":"cscroll3",q:1}],
- ["first_warrior_70","First Warrior to Level 70",{"name":(Math.random()<0.1&&"gift0"||"gift1"),q:1}],
- ["first_paladin_70","First Paladin to Level 70",{"name":(Math.random()<0.1&&"gift0"||"gift1"),q:1}],
- ["first_priest_70","First Priest to Level 70",{"name":(Math.random()<0.1&&"gift0"||"gift1"),q:1}],
- ["first_mage_70","First Mage to Level 70",{"name":(Math.random()<0.1&&"gift0"||"gift1"),q:1}],
- ["first_rogue_70","First Rogue to Level 70",{"name":(Math.random()<0.1&&"gift0"||"gift1"),q:1}],
- ["first_ranger_70","First Ranger to Level 70",{"name":(Math.random()<0.1&&"gift0"||"gift1"),q:1}],
- ["first_franky","First Franky Kill",{"name":"brownegg",q:1}],
- ["first_stompy","First Stompy Kill",{"name":(Math.random()<0.1&&"gift0"||"gift1"),q:1}],
- ["first_ent","First Ent Kill",{"name":(Math.random()<0.1&&"gift0"||"gift1"),q:1}],
- ["first_wabbit","First Wabbit Kill",{"name":(Math.random()<0.1&&"gift0"||"gift1"),q:1}],
- ["first_fvampire","First Ms.Vampire Kill",{"name":(Math.random()<0.1&&"gift0"||"gift1"),q:1}],
- ["first_mvampire","First Mr.Vampire Kill",{"name":(Math.random()<0.1&&"gift0"||"gift1"),q:1}],
- ["first_skeletor","First Skeletor Kill",{"name":(Math.random()<0.1&&"gift0"||"gift1"),q:1}],
- ["first_goo","First Goo Kill",{"name":(Math.random()<0.1&&"gift0"||"gift1"),q:1}],
+function send_hardcore_rewards() {
+ rd = [
+ ["leader", "Leadership", { name: "xbox", q: 1 }],
+ ["item8", "First +8 Item", { name: "armorbox", q: 10 }],
+ ["item9", "First +9 Item", { name: "weaponbox", q: 10 }],
+ ["item10", "First +X Item", { name: "armorbox", q: 100 }],
+ ["item11", "First +Y Item", { name: "armorbox", q: 100 }],
+ ["item12", "First +Z Item", { name: "scroll3", q: 1 }],
+ ["accessory5", "First +V Accessory", { name: "armorbox", q: 50 }],
+ ["accessory6", "First +S Accessory", { name: "cscroll3", q: 1 }],
+ ["first_warrior_70", "First Warrior to Level 70", { name: (Math.random() < 0.1 && "gift0") || "gift1", q: 1 }],
+ ["first_paladin_70", "First Paladin to Level 70", { name: (Math.random() < 0.1 && "gift0") || "gift1", q: 1 }],
+ ["first_priest_70", "First Priest to Level 70", { name: (Math.random() < 0.1 && "gift0") || "gift1", q: 1 }],
+ ["first_mage_70", "First Mage to Level 70", { name: (Math.random() < 0.1 && "gift0") || "gift1", q: 1 }],
+ ["first_rogue_70", "First Rogue to Level 70", { name: (Math.random() < 0.1 && "gift0") || "gift1", q: 1 }],
+ ["first_ranger_70", "First Ranger to Level 70", { name: (Math.random() < 0.1 && "gift0") || "gift1", q: 1 }],
+ ["first_franky", "First Franky Kill", { name: "brownegg", q: 1 }],
+ ["first_stompy", "First Stompy Kill", { name: (Math.random() < 0.1 && "gift0") || "gift1", q: 1 }],
+ ["first_ent", "First Ent Kill", { name: (Math.random() < 0.1 && "gift0") || "gift1", q: 1 }],
+ ["first_wabbit", "First Wabbit Kill", { name: (Math.random() < 0.1 && "gift0") || "gift1", q: 1 }],
+ ["first_fvampire", "First Ms.Vampire Kill", { name: (Math.random() < 0.1 && "gift0") || "gift1", q: 1 }],
+ ["first_mvampire", "First Mr.Vampire Kill", { name: (Math.random() < 0.1 && "gift0") || "gift1", q: 1 }],
+ ["first_skeletor", "First Skeletor Kill", { name: (Math.random() < 0.1 && "gift0") || "gift1", q: 1 }],
+ ["first_goo", "First Goo Kill", { name: (Math.random() < 0.1 && "gift0") || "gift1", q: 1 }],
];
- rd.forEach(function(r){
- if(E.rewards[r[0]])
- appengine_call("send_mail",{subject:"HARDCORE: Congratulations!",message:"Reward for "+r[1],type:"system",rid:randomStr(50),to:E.rewards[r[0]],item:JSON.stringify(r[2]),retries:8});
+ rd.forEach(function (r) {
+ if (E.rewards[r[0]]) {
+ appengine_call("send_mail", {
+ subject: "HARDCORE: Congratulations!",
+ message: "Reward for " + r[1],
+ type: "system",
+ rid: randomStr(50),
+ to: E.rewards[r[0]],
+ item: JSON.stringify(r[2]),
+ retries: 8,
+ });
+ }
});
- for(var id in players)
+ for (var id in players) {
save_player(players[id]);
- var sent={};
- for(var id in P)
- {
- var p=P[id];
- if(p.auth_id && p.level>=60 && !sent[p.auth_id])
- {
- sent[p.auth_id]=true;
- appengine_call("send_mail",{subject:"HARDCORE: Congratulations!",message:"Reward for Participation",type:"system",rid:randomStr(50),to:p.name,item:JSON.stringify({"name":(Math.random()<0.1&&"gift0"||"gift1"),q:1})});
+ }
+ var sent = {};
+ for (var id in P) {
+ var p = P[id];
+ if (p.auth_id && p.level >= 60 && !sent[p.auth_id]) {
+ sent[p.auth_id] = true;
+ appengine_call("send_mail", {
+ subject: "HARDCORE: Congratulations!",
+ message: "Reward for Participation",
+ type: "system",
+ rid: randomStr(50),
+ to: p.name,
+ item: JSON.stringify({ name: (Math.random() < 0.1 && "gift0") || "gift1", q: 1 }),
+ });
}
}
}
-function add_achievement(player,name)
-{
- player.p.achievements[name]=(player.p.achievements[name]||0)+1;
- player.socket.emit("achievement_success",{name:name});
+function add_achievement(player, name) {
+ player.p.achievements[name] = (player.p.achievements[name] || 0) + 1;
+ player.socket.emit("achievement_success", { name: name });
}
-function item_achievement_increment(player,item,ach,amount)
-{
- if(!G.achievements[ach] || !item) return;
- if(item.ach!=ach || !item.acc)
- item.acc=0;
- var needed=G.achievements[ach].count,old=item.acc,rr=G.achievements[ach].rr||1;
- item.ach=ach;
- item.acc+=(amount||1);
- if(item.acc=70 && !E.rewards['first_'+c+'_70'] && E.minutes) E.rewards['first_'+c+'_70']=player.name,announce=true;
- });
- if(announce)
- broadcast("hardcore_info",{E:E,achiever:player.name});
- }
- else
- {
-
- }
-}catch(e){console.log("#A: "+e);}}
-
-function achievement_logic_compound_success(player,item)
-{try{
- if(gameplay=="hardcore")
- {
- var announce=false;
- if(item.level==5 && !E.rewards.accessory5 && E.minutes) E.rewards.accessory5=player.name,announce=true;
- if(item.level==6 && !E.rewards.accessory6 && E.minutes) E.rewards.accessory6=player.name,announce=true;
- if(announce)
- broadcast("hardcore_info",{E:E,achiever:player.name});
- }
- else
- {
-
- }
-}catch(e){console.log("#A: "+e);}}
-
-function achievement_logic_upgrade_success(player,item)
-{try{
- if(gameplay=="hardcore")
- {
- var announce=false;
- if(item.level==8 && !E.rewards.item8 && E.minutes) E.rewards.item8=player.name,announce=true;
- if(item.level==9 && !E.rewards.item9 && E.minutes) E.rewards.item9=player.name,announce=true;
- if(item.level==10 && !E.rewards.item10 && E.minutes) E.rewards.item10=player.name,announce=true;
- if(item.level==11 && !E.rewards.item11 && E.minutes) E.rewards.item11=player.name,announce=true;
- if(item.level==12 && !E.rewards.item12 && E.minutes) E.rewards.item12=player.name,announce=true;
- if(announce)
- {
- broadcast("hardcore_info",{E:E,achiever:player.name});
+function achievement_logic_monster_damage(player, monster, damage) {
+ try {
+ if (monster.type == "grinch") {
+ item_achievement_increment(player, player.slots.cape, "festive", damage);
}
+ } catch (e) {
+ console.log("#A: " + e);
}
- else
- {
+}
+function achievement_logic_monster_kill(player, monster) {
+ try {
+ if (gameplay == "hardcore") {
+ var announce = false;
+ ["ent", "stompy", "franky", "fvampire", "mvampire", "skeletor", "goo"].forEach(function (m) {
+ if (monster.type == m && !E.rewards["first_" + m] && E.minutes) {
+ E.rewards["first_" + m] = player.name;
+ announce = true;
+ }
+ });
+ if (announce) {
+ broadcast("hardcore_info", { E: E, achiever: player.name });
+ }
+ } else {
+ }
+ } catch (e) {
+ console.log("#A: " + e);
}
-}catch(e){console.log("#A: "+e);}}
+}
-function achievement_logic_monster_last_hit(player,monster)
-{try{
- if(server.shutdown) return;
- if(player.slots.mainhand) delete player.slots.mainhand.ach;
-}catch(e){console.log("#A: "+e);}}
+function achievement_logic_level(player) {
+ try {
+ if (gameplay == "hardcore") {
+ var announce = false;
+ ["warrior", "paladin", "priest", "mage", "ranger", "rogue", "wabbit"].forEach(function (c) {
+ if (player.type == c && player.level >= 70 && !E.rewards["first_" + c + "_70"] && E.minutes) {
+ E.rewards["first_" + c + "_70"] = player.name;
+ announce = true;
+ }
+ });
+ if (announce) {
+ broadcast("hardcore_info", { E: E, achiever: player.name });
+ }
+ } else {
+ }
+ } catch (e) {
+ console.log("#A: " + e);
+ }
+}
-function achievement_logic_monster_hit(monster,player,attack)
-{try{
- if(monster.type=="stompy" && !monster.target)
- item_achievement_increment(player,player.slots.helmet,"stomped");
- else if(monster.type!="stompy" && player.slots.helmet)
- delete player.slots.helmet.ach;
+function achievement_logic_compound_success(player, item) {
+ try {
+ if (gameplay == "hardcore") {
+ var announce = false;
+ if (item.level == 5 && !E.rewards.accessory5 && E.minutes) {
+ E.rewards.accessory5 = player.name;
+ announce = true;
+ }
+ if (item.level == 6 && !E.rewards.accessory6 && E.minutes) {
+ E.rewards.accessory6 = player.name;
+ announce = true;
+ }
+ if (announce) {
+ broadcast("hardcore_info", { E: E, achiever: player.name });
+ }
+ } else {
+ }
+ } catch (e) {
+ console.log("#A: " + e);
+ }
+}
- if(monster.type=="goo" || monster.type=="cgoo")
- item_achievement_increment(player,player.slots.pants,"gooped",attack);
+function achievement_logic_upgrade_success(player, item) {
+ try {
+ if (gameplay == "hardcore") {
+ var announce = false;
+ if (item.level == 8 && !E.rewards.item8 && E.minutes) {
+ E.rewards.item8 = player.name;
+ announce = true;
+ }
+ if (item.level == 9 && !E.rewards.item9 && E.minutes) {
+ E.rewards.item9 = player.name;
+ announce = true;
+ }
+ if (item.level == 10 && !E.rewards.item10 && E.minutes) {
+ E.rewards.item10 = player.name;
+ announce = true;
+ }
+ if (item.level == 11 && !E.rewards.item11 && E.minutes) {
+ E.rewards.item11 = player.name;
+ announce = true;
+ }
+ if (item.level == 12 && !E.rewards.item12 && E.minutes) {
+ E.rewards.item12 = player.name;
+ announce = true;
+ }
+ if (announce) {
+ broadcast("hardcore_info", { E: E, achiever: player.name });
+ }
+ } else {
+ }
+ } catch (e) {
+ console.log("#A: " + e);
+ }
+}
-}catch(e){console.log("#A: "+e);}}
+function achievement_logic_monster_last_hit(player, monster) {
+ try {
+ if (server.shutdown) {
+ return;
+ }
+ if (player.slots.mainhand) {
+ delete player.slots.mainhand.ach;
+ }
+ } catch (e) {
+ console.log("#A: " + e);
+ }
+}
-function achievement_logic_burn_last_hit(player)
-{try{
- if(server.shutdown) return;
- item_achievement_increment(player,player.slots.mainhand,"firehazard");
-}catch(e){console.log("#A: "+e);}}
\ No newline at end of file
+function achievement_logic_monster_hit(monster, player, attack) {
+ try {
+ if (monster.type == "stompy" && !monster.target) {
+ item_achievement_increment(player, player.slots.helmet, "stomped");
+ } else if (monster.type != "stompy" && player.slots.helmet) {
+ delete player.slots.helmet.ach;
+ }
+
+ if (monster.type == "goo" || monster.type == "cgoo") {
+ item_achievement_increment(player, player.slots.pants, "gooped", attack);
+ }
+ } catch (e) {
+ console.log("#A: " + e);
+ }
+}
+
+function achievement_logic_burn_last_hit(player) {
+ try {
+ if (server.shutdown) {
+ return;
+ }
+ item_achievement_increment(player, player.slots.mainhand, "firehazard");
+ } catch (e) {
+ console.log("#A: " + e);
+ }
+}
diff --git a/node/server_worker.js b/node/server_worker.js
index 0e98fff..69d837f 100644
--- a/node/server_worker.js
+++ b/node/server_worker.js
@@ -1,23 +1,28 @@
-var is_game=0,is_server=1,is_code=0;
-var variables=require('./variables');
-var is_sdk=variables.is_sdk;
-var fs=require('fs');
-eval(""+fs.readFileSync(variables.cfunctions_path));
-eval(""+fs.readFileSync(variables.functions_path));
-var {workerData,parentPort}=require('worker_threads');
-var G=workerData.G,smap_data=workerData.smap_data,amap_data=workerData.amap_data;
+var is_game = 0;
+var is_server = 1;
+var is_code = 0;
+var variables = require("./variables");
+var is_sdk = variables.is_sdk;
+var fs = require("fs");
+eval("" + fs.readFileSync(variables.cfunctions_path));
+eval("" + fs.readFileSync(variables.functions_path));
+var { workerData, parentPort } = require("worker_threads");
+var G = workerData.G;
+var smap_data = workerData.smap_data;
+var amap_data = workerData.amap_data;
-parentPort.on("message",function(data){
- try{
+parentPort.on("message", function (data) {
+ try {
//console.log(data);
- if(data.type=="fast_astar")
- parentPort.postMessage({type:"monster_move",move:fast_astar(data),id:data.id,in:data.in});
- if(data.type=="exit") process.exit();
- }catch(e){
+ if (data.type == "fast_astar") {
+ parentPort.postMessage({ type: "monster_move", move: fast_astar(data), id: data.id, in: data.in });
+ }
+ if (data.type == "exit") {
+ process.exit();
+ }
+ } catch (e) {
console.log(e);
}
});
-setInterval(function(){
-
-},10);
\ No newline at end of file
+setInterval(function () {}, 10);
diff --git a/node/test.js b/node/test.js
index d2f5910..363e692 100644
--- a/node/test.js
+++ b/node/test.js
@@ -1,13 +1,14 @@
-var crypto=require('crypto');
-var protobuf=require('protobufjs'),ByteBuffer=require('bytebuffer');
+var crypto = require("crypto");
+var protobuf = require("protobufjs");
+var ByteBuffer = require("bytebuffer");
function symmetricDecrypt(input, key, checkHmac) {
- var aesIv = crypto.createDecipheriv('aes-256-ecb', key, '');
+ var aesIv = crypto.createDecipheriv("aes-256-ecb", key, "");
aesIv.setAutoPadding(false);
aesIv.end(input.slice(0, 16));
var iv = aesIv.read();
- var aesData = crypto.createDecipheriv('aes-256-cbc', key, iv);
+ var aesData = crypto.createDecipheriv("aes-256-cbc", key, iv);
aesData.end(input.slice(16));
var plaintext = aesData.read();
@@ -24,7 +25,7 @@ function symmetricDecrypt(input, key, checkHmac) {
}
return plaintext;
-};
+}
function parseAppTicket(ticket) {
// https://github.com/SteamRE/SteamKit/blob/master/Resources/Structs/steam3_appticket.hsl
@@ -70,11 +71,16 @@ function parseAppTicket(ticket) {
// Start reading the ownership ticket
let ownershipTicketOffset = ticket.offset;
let ownershipTicketLength = ticket.readUint32(); // including itself, for some reason
- if (ownershipTicketOffset + ownershipTicketLength != ticket.limit && ownershipTicketOffset + ownershipTicketLength + 128 != ticket.limit) {
+ if (
+ ownershipTicketOffset + ownershipTicketLength != ticket.limit &&
+ ownershipTicketOffset + ownershipTicketLength + 128 != ticket.limit
+ ) {
return null;
}
- let i, j, dlc;
+ let i;
+ let j;
+ let dlc;
details.version = ticket.readUint32();
details.steamID = ticket.readUint64().toString();
@@ -117,34 +123,54 @@ function parseAppTicket(ticket) {
let date = new Date();
details.isExpired = details.ownershipTicketExpires < date;
- details.hasValidSignature = !!details.signature && SteamCrypto.verifySignature(ticket.slice(ownershipTicketOffset, ownershipTicketOffset + ownershipTicketLength).toBuffer(), details.signature);
+ details.hasValidSignature =
+ !!details.signature &&
+ SteamCrypto.verifySignature(
+ ticket.slice(ownershipTicketOffset, ownershipTicketOffset + ownershipTicketLength).toBuffer(),
+ details.signature,
+ );
details.isValid = !details.isExpired && (!details.signature || details.hasValidSignature);
} catch (ex) {
- console.log("parseAppTicket: "+ex);
+ console.log("parseAppTicket: " + ex);
return details;
return null; // not a valid ticket
}
return details;
+}
+
+var proto = {
+ nested: {
+ EncryptedAppTicket: {
+ fields: {
+ ticketVersionNo: { type: "uint32", id: 1 },
+ crcEncryptedticket: { type: "uint32", id: 2 },
+ cbEncrypteduserdata: { type: "uint32", id: 3 },
+ cbEncryptedAppownershipticket: { type: "uint32", id: 4 },
+ encryptedTicket: { type: "bytes", id: 5 },
+ },
+ },
+ },
};
+var proto_root = protobuf.Root.fromJSON(proto);
+var EncryptedAppTicket = proto_root.lookupType("EncryptedAppTicket");
-var proto={ "nested": {EncryptedAppTicket: { fields:
- { ticketVersionNo: { type: 'uint32', id: 1 },
- crcEncryptedticket: { type: 'uint32', id: 2 },
- cbEncrypteduserdata: { type: 'uint32', id: 3 },
- cbEncryptedAppownershipticket: { type: 'uint32', id: 4 },
- encryptedTicket: { type: 'bytes', id: 5 } } }}};
-var proto_root=protobuf.Root.fromJSON(proto);
-var EncryptedAppTicket=proto_root.lookupType("EncryptedAppTicket");
-
-
-var outer=EncryptedAppTicket.decode(new Buffer("080110a7e59890031815204f2a80014527ad8cccd8cd9b7d3260529556004ddf0454a1c2e8543495b1eb72b3dff44d9d67555798ef44b7e3f97cf86d3bf1bc3f84a91de415c382b0d96033c8e5398f2b775bcb004f5487c651d81ef410d7d2917cbb407713397d2c29a455b6852eac7db1a0e52248585bd5440ef07de54b7519f67eefbad5420d97b77ef7e35450af","hex"));
-var decrypted=symmetricDecrypt(outer.encryptedTicket,new Buffer("8af5c487af6c7709ef1a4e6e2275fcc0a90f57ae4319de793fca3d7ed8655520","hex"));
+var outer = EncryptedAppTicket.decode(
+ new Buffer(
+ "080110a7e59890031815204f2a80014527ad8cccd8cd9b7d3260529556004ddf0454a1c2e8543495b1eb72b3dff44d9d67555798ef44b7e3f97cf86d3bf1bc3f84a91de415c382b0d96033c8e5398f2b775bcb004f5487c651d81ef410d7d2917cbb407713397d2c29a455b6852eac7db1a0e52248585bd5440ef07de54b7519f67eefbad5420d97b77ef7e35450af",
+ "hex",
+ ),
+);
+var decrypted = symmetricDecrypt(
+ outer.encryptedTicket,
+ new Buffer("8af5c487af6c7709ef1a4e6e2275fcc0a90f57ae4319de793fca3d7ed8655520", "hex"),
+);
let userData = decrypted.slice(0, outer.cbEncrypteduserdata);
let ownershipTicketLength = decrypted.readUInt32LE(outer.cbEncrypteduserdata);
-let ownershipTicket = parseAppTicket(decrypted.slice(outer.cbEncrypteduserdata, outer.cbEncrypteduserdata + ownershipTicketLength));
+let ownershipTicket = parseAppTicket(
+ decrypted.slice(outer.cbEncrypteduserdata, outer.cbEncrypteduserdata + ownershipTicketLength),
+);
if (ownershipTicket) {
ownershipTicket.userData = userData.toString();
}
console.log(ownershipTicket);
-
diff --git a/node/variables.js b/node/variables.js
deleted file mode 100644
index cd53910..0000000
--- a/node/variables.js
+++ /dev/null
@@ -1,23 +0,0 @@
-const path = require("node:path")
-
-module.exports={
- "cfunctions_path":path.resolve(__dirname, "../js/common_functions.js"),
- "functions_path":path.resolve(__dirname, "server_functions.js"),
- "worker_path":path.resolve(__dirname, "server_worker.js"),
- "data_path":path.resolve(__dirname, "data.js"),
- "base_url":"http://thegame.com",
- "keyword":"123",
- "master":"123",
- "server_master":"123",
- "bot_key":"123",
- "discord_token":"NDXXXXXXXXXXX...",
- "apple_token":"acXXXXXXXX...",
- "steam_key":"8aXXXXXXXXX...",
- "steam_web_key":"B4XXXXXXX...",
- "steam_partner_key":"F9XXXXXXX...",
- "is_sdk":1,
- "close_timeout":4000,
- "ip_limit":3,
- "character_limit":3,
- "fast_sdk":0,
-}
diff --git a/useful/template.live_variables.js b/useful/template.live_variables.js
new file mode 100644
index 0000000..c622edd
--- /dev/null
+++ b/useful/template.live_variables.js
@@ -0,0 +1,18 @@
+module.exports = {
+ cfunctions_path: "./server/common_functions.js",
+ functions_path: "./server/server_functions.js",
+ worker_path: "./server/server_worker.js",
+ data_path: "./server/data.js",
+ base_url: "https://yourappspoturldontincludedashes.appspot.com",
+ keyword: "123",
+ access_master: "123",
+ bot_key: "123",
+ discord_token: "NDXXXXXXXXXXX...",
+ apple_token: "acXXXXXXXX...",
+ steam_key: "8aXXXXXXXXX...",
+ steam_web_key: "B4XXXXXXX...",
+ steam_partner_key: "F9XXXXXXX...",
+ close_timeout: 24000,
+ ip_limit: 3,
+ character_limit: 3,
+};
diff --git a/secrets.py b/useful/template.secrets.py
similarity index 100%
rename from secrets.py
rename to useful/template.secrets.py
diff --git a/useful/template.variables.js b/useful/template.variables.js
new file mode 100644
index 0000000..c44d461
--- /dev/null
+++ b/useful/template.variables.js
@@ -0,0 +1,22 @@
+const path = require("node:path");
+
+module.exports = {
+ cfunctions_path: path.resolve(__dirname, "../js/common_functions.js"),
+ functions_path: path.resolve(__dirname, "server_functions.js"),
+ worker_path: path.resolve(__dirname, "server_worker.js"),
+ data_path: path.resolve(__dirname, "data.js"),
+ base_url: "http://thegame.com",
+ keyword: "123",
+ access_master: "123",
+ bot_key: "123",
+ discord_token: "NDXXXXXXXXXXX...",
+ apple_token: "acXXXXXXXX...",
+ steam_key: "8aXXXXXXXXX...",
+ steam_web_key: "B4XXXXXXX...",
+ steam_partner_key: "F9XXXXXXX...",
+ is_sdk: 1,
+ close_timeout: 4000,
+ ip_limit: 3,
+ character_limit: 3,
+ fast_sdk: 0,
+};