Add achievement system and UI
Add achievement system and UI; fix counting invalid inputs in UI handlers for input delay
231
package-lock.json
generated
@ -8,7 +8,7 @@
|
||||
"name": "pokemon-rogue-battle",
|
||||
"version": "0.0.1",
|
||||
"dependencies": {
|
||||
"phaser": "^3.61.0-beta.2",
|
||||
"phaser": "^3.70.0",
|
||||
"phaser3-rex-plugins": "^1.1.84"
|
||||
},
|
||||
"devDependencies": {
|
||||
@ -29,9 +29,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/runtime": {
|
||||
"version": "7.23.1",
|
||||
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.1.tgz",
|
||||
"integrity": "sha512-hC2v6p8ZSI/W0HUzh3V8C5g+NwSKzKPtJwSpTjwl0o297GP9+ZLQSkdvHz46CM3LqyoXxq+5G9komY+eSqSO0g==",
|
||||
"version": "7.23.2",
|
||||
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.2.tgz",
|
||||
"integrity": "sha512-mM8eg4yl5D6i3lu2QKPuPH4FArvJ8KhTofbE7jwMUv9KX5mBvwPAqnV3MlyBNqdp9RyRKP6Yck8TrfYrPvX3bg==",
|
||||
"dependencies": {
|
||||
"regenerator-runtime": "^0.14.0"
|
||||
},
|
||||
@ -407,9 +407,9 @@
|
||||
}
|
||||
},
|
||||
"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==",
|
||||
"version": "4.10.0",
|
||||
"resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz",
|
||||
"integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": "^12.0.0 || ^14.0.0 || >=16.0.0"
|
||||
@ -439,21 +439,21 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@eslint/js": {
|
||||
"version": "8.50.0",
|
||||
"resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.50.0.tgz",
|
||||
"integrity": "sha512-NCC3zz2+nvYd+Ckfh87rA47zfu2QsQpvc6k1yzTk+b9KzRj0wkGa8LSoGOXN6Zv4lRf/EIoZ80biDh9HOI+RNQ==",
|
||||
"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.11",
|
||||
"resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.11.tgz",
|
||||
"integrity": "sha512-N2brEuAadi0CcdeMXUkhbZB84eskAc8MEX1By6qEchoVywSgXPIjou4rYsl0V3Hj0ZnuGycGCjdNgockbzeWNA==",
|
||||
"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": "^1.2.1",
|
||||
"@humanwhocodes/object-schema": "^2.0.1",
|
||||
"debug": "^4.1.1",
|
||||
"minimatch": "^3.0.5"
|
||||
},
|
||||
@ -475,9 +475,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@humanwhocodes/object-schema": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz",
|
||||
"integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==",
|
||||
"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/@koa/cors": {
|
||||
@ -527,6 +527,12 @@
|
||||
"node": ">= 8"
|
||||
}
|
||||
},
|
||||
"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",
|
||||
@ -541,9 +547,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/acorn": {
|
||||
"version": "8.10.0",
|
||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz",
|
||||
"integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==",
|
||||
"version": "8.11.1",
|
||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.1.tgz",
|
||||
"integrity": "sha512-IJTNCJMRHfRfb8un89z1QtS0x890C2QUrUxFMK8zy+RizcId6mfnqOf68Bu9YkDgpLYuvCm6aYbwDatXVZPjMQ==",
|
||||
"dev": true,
|
||||
"bin": {
|
||||
"acorn": "bin/acorn"
|
||||
@ -645,13 +651,14 @@
|
||||
}
|
||||
},
|
||||
"node_modules/call-bind": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz",
|
||||
"integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==",
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.5.tgz",
|
||||
"integrity": "sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"function-bind": "^1.1.1",
|
||||
"get-intrinsic": "^1.0.2"
|
||||
"function-bind": "^1.1.2",
|
||||
"get-intrinsic": "^1.2.1",
|
||||
"set-function-length": "^1.1.1"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
@ -769,11 +776,11 @@
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/cross-fetch": {
|
||||
"version": "3.1.6",
|
||||
"resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.6.tgz",
|
||||
"integrity": "sha512-riRvo06crlE8HiqOwIpQhxwdOk4fOeR7FVM/wXoxchFEqMNUjvbs3bfo4OTgMEMHzppd4DxFBDbyySj8Cv781g==",
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-4.0.0.tgz",
|
||||
"integrity": "sha512-e4a5N8lVvuLgAWgnCrLr2PP0YyDOTHa9H/Rj54dirp61qXnNq46m82bRhNqIA5VccJtWBvPTFRV3TtvHUKPB1g==",
|
||||
"dependencies": {
|
||||
"node-fetch": "^2.6.11"
|
||||
"node-fetch": "^2.6.12"
|
||||
}
|
||||
},
|
||||
"node_modules/cross-spawn": {
|
||||
@ -819,6 +826,20 @@
|
||||
"integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/define-data-property": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.1.tgz",
|
||||
"integrity": "sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"get-intrinsic": "^1.2.1",
|
||||
"gopd": "^1.0.1",
|
||||
"has-property-descriptors": "^1.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/delegates": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz",
|
||||
@ -927,18 +948,19 @@
|
||||
}
|
||||
},
|
||||
"node_modules/eslint": {
|
||||
"version": "8.50.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint/-/eslint-8.50.0.tgz",
|
||||
"integrity": "sha512-FOnOGSuFuFLv/Sa+FDVRZl4GGVAAFFi8LecRsI5a1tMO5HIE8nCm4ivAlzt4dT3ol/PaaGC0rJEEXQmHJBGoOg==",
|
||||
"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.50.0",
|
||||
"@humanwhocodes/config-array": "^0.11.11",
|
||||
"@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",
|
||||
@ -1128,12 +1150,12 @@
|
||||
}
|
||||
},
|
||||
"node_modules/flat-cache": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.1.0.tgz",
|
||||
"integrity": "sha512-OHx4Qwrrt0E4jEIcI5/Xb+f+QmJYNj2rrK8wiIdQOIrB9WrrJL8cjZvXdXuBTkkEwEqLycb5BeZDV1o2i9bTew==",
|
||||
"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.7",
|
||||
"flatted": "^3.2.9",
|
||||
"keyv": "^4.5.3",
|
||||
"rimraf": "^3.0.2"
|
||||
},
|
||||
@ -1177,21 +1199,24 @@
|
||||
}
|
||||
},
|
||||
"node_modules/function-bind": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
|
||||
"integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
|
||||
"dev": true
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
|
||||
"integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
|
||||
"dev": true,
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/get-intrinsic": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz",
|
||||
"integrity": "sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==",
|
||||
"version": "1.2.2",
|
||||
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.2.tgz",
|
||||
"integrity": "sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"function-bind": "^1.1.1",
|
||||
"has": "^1.0.3",
|
||||
"function-bind": "^1.1.2",
|
||||
"has-proto": "^1.0.1",
|
||||
"has-symbols": "^1.0.3"
|
||||
"has-symbols": "^1.0.3",
|
||||
"hasown": "^2.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
@ -1242,9 +1267,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/globals": {
|
||||
"version": "13.22.0",
|
||||
"resolved": "https://registry.npmjs.org/globals/-/globals-13.22.0.tgz",
|
||||
"integrity": "sha512-H1Ddc/PbZHTDVJSnj8kWptIRSD6AM3pK+mKytuIVF4uoBV7rshFlhhvA58ceJ5wp3Er58w6zj7bykMpYXt3ETw==",
|
||||
"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"
|
||||
@ -1256,6 +1281,18 @@
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/gopd": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz",
|
||||
"integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"get-intrinsic": "^1.1.3"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/graphemer": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz",
|
||||
@ -1282,18 +1319,6 @@
|
||||
"uglify-js": "^3.1.4"
|
||||
}
|
||||
},
|
||||
"node_modules/has": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
|
||||
"integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"function-bind": "^1.1.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/has-flag": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
|
||||
@ -1303,6 +1328,18 @@
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/has-property-descriptors": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.1.tgz",
|
||||
"integrity": "sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"get-intrinsic": "^1.2.2"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/has-proto": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz",
|
||||
@ -1342,6 +1379,18 @@
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/hasown": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz",
|
||||
"integrity": "sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"function-bind": "^1.1.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/http-assert": {
|
||||
"version": "1.5.0",
|
||||
"resolved": "https://registry.npmjs.org/http-assert/-/http-assert-1.5.0.tgz",
|
||||
@ -1403,11 +1452,11 @@
|
||||
}
|
||||
},
|
||||
"node_modules/i18next-http-backend": {
|
||||
"version": "2.2.2",
|
||||
"resolved": "https://registry.npmjs.org/i18next-http-backend/-/i18next-http-backend-2.2.2.tgz",
|
||||
"integrity": "sha512-mJu4ZqzDtBiU3O4GV9AbK5ekEqoDMdMnCl3pkdXmb5b8yoIH//u8FsmIe6C5qXb3teZu+j6VMi20tjUgzeABiw==",
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/i18next-http-backend/-/i18next-http-backend-2.3.0.tgz",
|
||||
"integrity": "sha512-9m34IcWdS3r43cgq/7O5IsDxTvSQ7pePwk2eQIH5q6Em6OjDCsSjboRWg2jqVdeIoCtHwzTN/byDHPStMsKsPQ==",
|
||||
"dependencies": {
|
||||
"cross-fetch": "3.1.6"
|
||||
"cross-fetch": "4.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/iconv-lite": {
|
||||
@ -1457,9 +1506,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/inflation": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/inflation/-/inflation-2.0.0.tgz",
|
||||
"integrity": "sha512-m3xv4hJYR2oXw4o4Y5l6P5P16WYmazYof+el6Al3f+YlggGj6qT9kImBAnzDelRALnP5d3h4jGBPKzYCizjZZw==",
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/inflation/-/inflation-2.1.0.tgz",
|
||||
"integrity": "sha512-t54PPJHG1Pp7VQvxyVCJ9mBbjG3Hqryges9bXoOO6GExCPa+//i/d5GSuFtpx3ALLd7lgIAur6zrIlBQyJuMlQ==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">= 0.8.0"
|
||||
@ -1583,9 +1632,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/keyv": {
|
||||
"version": "4.5.3",
|
||||
"resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.3.tgz",
|
||||
"integrity": "sha512-QCiSav9WaX1PgETJ+SpNnx2PRRapJ/oRSXM4VO5OGYGSjrxbKPVFVhB3l2OCbLCk329N8qyAtsJjSjvVBWzEug==",
|
||||
"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"
|
||||
@ -1662,6 +1711,7 @@
|
||||
"version": "10.1.1",
|
||||
"resolved": "https://registry.npmjs.org/koa-router/-/koa-router-10.1.1.tgz",
|
||||
"integrity": "sha512-z/OzxVjf5NyuNO3t9nJpx7e1oR3FSBAauiwXtMQu4ppcnuNZzTaQ4p21P8A6r2Es8uJJM339oc4oVW+qX7SqnQ==",
|
||||
"deprecated": "**IMPORTANT 10x+ PERFORMANCE UPGRADE**: Please upgrade to v12.0.1+ as we have fixed an issue with debuglog causing 10x slower router benchmark performance, see https://github.com/koajs/router/pull/173",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"debug": "^4.1.1",
|
||||
@ -1839,9 +1889,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/object-inspect": {
|
||||
"version": "1.12.3",
|
||||
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz",
|
||||
"integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==",
|
||||
"version": "1.13.1",
|
||||
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz",
|
||||
"integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==",
|
||||
"dev": true,
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
@ -1981,11 +2031,11 @@
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/phaser": {
|
||||
"version": "3.61.0-beta.2",
|
||||
"resolved": "https://registry.npmjs.org/phaser/-/phaser-3.61.0-beta.2.tgz",
|
||||
"integrity": "sha512-nXEGqIORZe1ygijKi8iqqA2OHT5l4DVkVxc1HWhApg0lhXzH/p0ErHecS1j9UGB75G3beF+qd9AzBkgwNJ9QsQ==",
|
||||
"version": "3.70.0",
|
||||
"resolved": "https://registry.npmjs.org/phaser/-/phaser-3.70.0.tgz",
|
||||
"integrity": "sha512-2g+gh+Jp9f/Ho9FOXOYbIJMGf3UZXyMbW2iLScFaLQw11e/LqVyxj/YmaBauWbHabeTnZjiWkPklDnxhesMH0g==",
|
||||
"dependencies": {
|
||||
"eventemitter3": "^5.0.0"
|
||||
"eventemitter3": "^5.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/phaser3-rex-plugins": {
|
||||
@ -2239,6 +2289,21 @@
|
||||
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/set-function-length": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.1.1.tgz",
|
||||
"integrity": "sha512-VoaqjbBJKiWtg4yRcKBQ7g7wnGnLV3M8oLvVWwOk2PdYY6PEFegR1vezXR0tw6fZGF9csVakIRjrJiy2veSBFQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"define-data-property": "^1.1.1",
|
||||
"get-intrinsic": "^1.2.1",
|
||||
"gopd": "^1.0.1",
|
||||
"has-property-descriptors": "^1.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/setprototypeof": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
|
||||
@ -2516,9 +2581,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/vite-plugin-fs": {
|
||||
"version": "1.0.0-beta.6",
|
||||
"resolved": "https://registry.npmjs.org/vite-plugin-fs/-/vite-plugin-fs-1.0.0-beta.6.tgz",
|
||||
"integrity": "sha512-WKvlZ7S+5wdJp0Mut5C15rH89iJxL4xUHkjBvKfhPPKWKBIQBPvFA1jM9Y64Ns2kF/92TI9i8+DRAgHklKgPBw==",
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/vite-plugin-fs/-/vite-plugin-fs-1.0.0.tgz",
|
||||
"integrity": "sha512-iVWZaPNDyAXxRgLg2dM0M3j3eQT0vFPpvjeCoVdWa+S9Kx1DFmOkeBBnTSez7D335IfwrlKbThxx9Gwh5cF3YA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@koa/cors": "^3.4.3",
|
||||
|
BIN
public/audio/se/achv.wav
Normal file
Before Width: | Height: | Size: 56 KiB After Width: | Height: | Size: 26 KiB |
BIN
public/images/items/big_nugget.png
Normal file
After Width: | Height: | Size: 275 B |
207
public/images/items/configuration.tps
Normal file
@ -0,0 +1,207 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<data version="1.0">
|
||||
<struct type="Settings">
|
||||
<key>fileFormatVersion</key>
|
||||
<int>6</int>
|
||||
<key>texturePackerVersion</key>
|
||||
<string>7.1.0</string>
|
||||
<key>autoSDSettings</key>
|
||||
<array>
|
||||
<struct type="AutoSDSettings">
|
||||
<key>scale</key>
|
||||
<double>1</double>
|
||||
<key>extension</key>
|
||||
<string></string>
|
||||
<key>spriteFilter</key>
|
||||
<string></string>
|
||||
<key>acceptFractionalValues</key>
|
||||
<false/>
|
||||
<key>maxTextureSize</key>
|
||||
<QSize>
|
||||
<key>width</key>
|
||||
<int>-1</int>
|
||||
<key>height</key>
|
||||
<int>-1</int>
|
||||
</QSize>
|
||||
</struct>
|
||||
</array>
|
||||
<key>allowRotation</key>
|
||||
<false/>
|
||||
<key>shapeDebug</key>
|
||||
<false/>
|
||||
<key>dpi</key>
|
||||
<uint>72</uint>
|
||||
<key>dataFormat</key>
|
||||
<string>phaser</string>
|
||||
<key>textureFileName</key>
|
||||
<filename></filename>
|
||||
<key>flipPVR</key>
|
||||
<false/>
|
||||
<key>pvrQualityLevel</key>
|
||||
<uint>3</uint>
|
||||
<key>astcQualityLevel</key>
|
||||
<uint>2</uint>
|
||||
<key>basisUniversalQualityLevel</key>
|
||||
<uint>2</uint>
|
||||
<key>etc1QualityLevel</key>
|
||||
<uint>70</uint>
|
||||
<key>etc2QualityLevel</key>
|
||||
<uint>70</uint>
|
||||
<key>dxtCompressionMode</key>
|
||||
<enum type="SettingsBase::DxtCompressionMode">DXT_PERCEPTUAL</enum>
|
||||
<key>ditherType</key>
|
||||
<enum type="SettingsBase::DitherType">PngQuantLow</enum>
|
||||
<key>backgroundColor</key>
|
||||
<uint>0</uint>
|
||||
<key>libGdx</key>
|
||||
<struct type="LibGDX">
|
||||
<key>filtering</key>
|
||||
<struct type="LibGDXFiltering">
|
||||
<key>x</key>
|
||||
<enum type="LibGDXFiltering::Filtering">Linear</enum>
|
||||
<key>y</key>
|
||||
<enum type="LibGDXFiltering::Filtering">Linear</enum>
|
||||
</struct>
|
||||
</struct>
|
||||
<key>shapePadding</key>
|
||||
<uint>0</uint>
|
||||
<key>jpgQuality</key>
|
||||
<uint>80</uint>
|
||||
<key>pngOptimizationLevel</key>
|
||||
<uint>1</uint>
|
||||
<key>webpQualityLevel</key>
|
||||
<uint>101</uint>
|
||||
<key>textureSubPath</key>
|
||||
<string></string>
|
||||
<key>textureFormat</key>
|
||||
<enum type="SettingsBase::TextureFormat">png8</enum>
|
||||
<key>borderPadding</key>
|
||||
<uint>0</uint>
|
||||
<key>maxTextureSize</key>
|
||||
<QSize>
|
||||
<key>width</key>
|
||||
<int>2048</int>
|
||||
<key>height</key>
|
||||
<int>2048</int>
|
||||
</QSize>
|
||||
<key>fixedTextureSize</key>
|
||||
<QSize>
|
||||
<key>width</key>
|
||||
<int>-1</int>
|
||||
<key>height</key>
|
||||
<int>-1</int>
|
||||
</QSize>
|
||||
<key>algorithmSettings</key>
|
||||
<struct type="AlgorithmSettings">
|
||||
<key>algorithm</key>
|
||||
<enum type="AlgorithmSettings::AlgorithmId">MaxRects</enum>
|
||||
<key>freeSizeMode</key>
|
||||
<enum type="AlgorithmSettings::AlgorithmFreeSizeMode">Best</enum>
|
||||
<key>sizeConstraints</key>
|
||||
<enum type="AlgorithmSettings::SizeConstraints">AnySize</enum>
|
||||
<key>forceSquared</key>
|
||||
<true/>
|
||||
<key>maxRects</key>
|
||||
<struct type="AlgorithmMaxRectsSettings">
|
||||
<key>heuristic</key>
|
||||
<enum type="AlgorithmMaxRectsSettings::Heuristic">Best</enum>
|
||||
</struct>
|
||||
<key>basic</key>
|
||||
<struct type="AlgorithmBasicSettings">
|
||||
<key>sortBy</key>
|
||||
<enum type="AlgorithmBasicSettings::SortBy">Best</enum>
|
||||
<key>order</key>
|
||||
<enum type="AlgorithmBasicSettings::Order">Ascending</enum>
|
||||
</struct>
|
||||
<key>polygon</key>
|
||||
<struct type="AlgorithmPolygonSettings">
|
||||
<key>alignToGrid</key>
|
||||
<uint>1</uint>
|
||||
</struct>
|
||||
</struct>
|
||||
<key>dataFileNames</key>
|
||||
<map type="GFileNameMap">
|
||||
<key>json</key>
|
||||
<struct type="DataFile">
|
||||
<key>name</key>
|
||||
<filename>../items.json</filename>
|
||||
</struct>
|
||||
</map>
|
||||
<key>multiPackMode</key>
|
||||
<enum type="SettingsBase::MultiPackMode">MultiPackOff</enum>
|
||||
<key>forceIdenticalLayout</key>
|
||||
<false/>
|
||||
<key>outputFormat</key>
|
||||
<enum type="SettingsBase::OutputFormat">RGBA8888</enum>
|
||||
<key>alphaHandling</key>
|
||||
<enum type="SettingsBase::AlphaHandling">ClearTransparentPixels</enum>
|
||||
<key>contentProtection</key>
|
||||
<struct type="ContentProtection">
|
||||
<key>key</key>
|
||||
<string></string>
|
||||
</struct>
|
||||
<key>autoAliasEnabled</key>
|
||||
<true/>
|
||||
<key>trimSpriteNames</key>
|
||||
<false/>
|
||||
<key>prependSmartFolderName</key>
|
||||
<false/>
|
||||
<key>autodetectAnimations</key>
|
||||
<true/>
|
||||
<key>globalSpriteSettings</key>
|
||||
<struct type="SpriteSettings">
|
||||
<key>scale</key>
|
||||
<double>1</double>
|
||||
<key>scaleMode</key>
|
||||
<enum type="ScaleMode">Smooth</enum>
|
||||
<key>extrude</key>
|
||||
<uint>0</uint>
|
||||
<key>trimThreshold</key>
|
||||
<uint>1</uint>
|
||||
<key>trimMargin</key>
|
||||
<uint>1</uint>
|
||||
<key>trimMode</key>
|
||||
<enum type="SpriteSettings::TrimMode">Trim</enum>
|
||||
<key>tracerTolerance</key>
|
||||
<int>200</int>
|
||||
<key>heuristicMask</key>
|
||||
<false/>
|
||||
<key>defaultPivotPoint</key>
|
||||
<point_f>0.5,0.5</point_f>
|
||||
<key>writePivotPoints</key>
|
||||
<false/>
|
||||
</struct>
|
||||
<key>individualSpriteSettings</key>
|
||||
<map type="IndividualSpriteSettingsMap"/>
|
||||
<key>fileLists</key>
|
||||
<map type="SpriteSheetMap">
|
||||
<key>default</key>
|
||||
<struct type="SpriteSheet">
|
||||
<key>files</key>
|
||||
<array/>
|
||||
</struct>
|
||||
</map>
|
||||
<key>ignoreFileList</key>
|
||||
<array/>
|
||||
<key>replaceList</key>
|
||||
<array/>
|
||||
<key>ignoredWarnings</key>
|
||||
<array/>
|
||||
<key>commonDivisorX</key>
|
||||
<uint>1</uint>
|
||||
<key>commonDivisorY</key>
|
||||
<uint>1</uint>
|
||||
<key>packNormalMaps</key>
|
||||
<false/>
|
||||
<key>autodetectNormalMaps</key>
|
||||
<true/>
|
||||
<key>normalMapFilter</key>
|
||||
<string></string>
|
||||
<key>normalMapSuffix</key>
|
||||
<string></string>
|
||||
<key>normalMapSheetFileName</key>
|
||||
<filename></filename>
|
||||
<key>exporterProperties</key>
|
||||
<map type="ExporterProperties"/>
|
||||
</struct>
|
||||
</data>
|
1
public/images/items/items.bat
Normal file
@ -0,0 +1 @@
|
||||
cmd /c TexturePacker ./ ./configuration.tps --sheet ../items.png --data ../items.json --replace .png=
|
BIN
public/images/items/lucky_punch_great.png
Normal file
After Width: | Height: | Size: 468 B |
BIN
public/images/items/lucky_punch_master.png
Normal file
After Width: | Height: | Size: 469 B |
BIN
public/images/items/lucky_punch_ultra.png
Normal file
After Width: | Height: | Size: 466 B |
BIN
public/images/items/nugget.png
Normal file
After Width: | Height: | Size: 220 B |
BIN
public/images/items/relic_crown.png
Normal file
After Width: | Height: | Size: 340 B |
BIN
public/images/items/relic_gold.png
Normal file
After Width: | Height: | Size: 178 B |
BIN
public/images/items/strange_ball.png
Normal file
After Width: | Height: | Size: 885 B |
BIN
public/images/items/unknown.png
Normal file
After Width: | Height: | Size: 159 B |
BIN
public/images/ui/achv_bar.png
Normal file
After Width: | Height: | Size: 399 B |
BIN
public/images/ui/achv_bar_2.png
Normal file
After Width: | Height: | Size: 437 B |
BIN
public/images/ui/achv_bar_3.png
Normal file
After Width: | Height: | Size: 433 B |
BIN
public/images/ui/achv_bar_4.png
Normal file
After Width: | Height: | Size: 433 B |
@ -31,6 +31,7 @@ import { getBiomeKey } from "./arena";
|
||||
import { BattleType, BattlerIndex, TurnCommand } from "./battle";
|
||||
import { GameMode } from "./game-mode";
|
||||
import { Species } from "./data/species";
|
||||
import { HealAchv, LevelAchv, MoneyAchv, achvs } from "./system/achv";
|
||||
|
||||
export class CheckLoadPhase extends BattlePhase {
|
||||
private loaded: boolean;
|
||||
@ -329,6 +330,8 @@ export class EncounterPhase extends BattlePhase {
|
||||
enemyPokemon.untint(100, 'Sine.easeOut');
|
||||
enemyPokemon.cry();
|
||||
enemyPokemon.showInfo();
|
||||
if (enemyPokemon.isShiny())
|
||||
this.scene.validateAchv(achvs.SEE_SHINY);
|
||||
});
|
||||
let text = enemyField.length === 1
|
||||
? `A wild ${enemyField[0].name} appeared!`
|
||||
@ -2259,6 +2262,8 @@ export class MoneyRewardPhase extends BattlePhase {
|
||||
this.scene.money += moneyAmount.value;
|
||||
this.scene.updateMoneyText();
|
||||
|
||||
this.scene.validateAchvs(MoneyAchv);
|
||||
|
||||
this.scene.ui.showText(`You got ₽${moneyAmount.value.toLocaleString('en-US')}\nfor winning!`, null, () => this.end(), null, true);
|
||||
}
|
||||
}
|
||||
@ -2299,6 +2304,8 @@ export class GameOverPhase extends BattlePhase {
|
||||
this.scene.gameData.clearSession();
|
||||
|
||||
this.scene.time.delayedCall(1000, () => {
|
||||
if (this.victory)
|
||||
this.scene.validateAchv(achvs.CLASSIC_VICTORY);
|
||||
const fadeDuration = this.victory ? 10000 : 5000;
|
||||
this.scene.fadeOutBgm(fadeDuration, true);
|
||||
this.scene.ui.fadeOut(fadeDuration).then(() => {
|
||||
@ -2464,6 +2471,8 @@ export class LevelUpPhase extends PlayerPartyMemberPokemonPhase {
|
||||
start() {
|
||||
super.start();
|
||||
|
||||
this.scene.validateAchvs(LevelAchv, new Utils.IntegerHolder(this.level));
|
||||
|
||||
const pokemon = this.getPokemon();
|
||||
const prevStats = pokemon.stats.slice(0);
|
||||
pokemon.calculateStats();
|
||||
@ -2633,7 +2642,9 @@ export class PokemonHealPhase extends CommonAnimPhase {
|
||||
const hpRestoreMultiplier = new Utils.IntegerHolder(1);
|
||||
if (!this.revive)
|
||||
this.scene.applyModifiers(HealingBoosterModifier, this.player, hpRestoreMultiplier);
|
||||
pokemon.heal(this.hpHealed * hpRestoreMultiplier.value);
|
||||
const healAmount = new Utils.NumberHolder(this.hpHealed * hpRestoreMultiplier.value);
|
||||
pokemon.heal(healAmount.value);
|
||||
this.scene.validateAchvs(HealAchv, healAmount)
|
||||
pokemon.updateInfo().then(() => super.end());
|
||||
} else if (this.showFullHpMessage)
|
||||
this.message = getPokemonMessage(pokemon, `'s\nHP is full!`);
|
||||
@ -2783,6 +2794,16 @@ export class AttemptCapturePhase extends PokemonPhase {
|
||||
catch() {
|
||||
const pokemon = this.getPokemon() as EnemyPokemon;
|
||||
this.scene.unshiftPhase(new VictoryPhase(this.scene, this.battlerIndex));
|
||||
|
||||
if (pokemon.getAbility().id === (!pokemon.fusionSpecies ? pokemon.getSpeciesForm() : pokemon.getFusionSpeciesForm()).abilityHidden)
|
||||
this.scene.validateAchv(achvs.HIDDEN_ABILITY);
|
||||
|
||||
if (pokemon.species.pseudoLegendary || pokemon.species.legendary)
|
||||
this.scene.validateAchv(achvs.CATCH_LEGENDARY);
|
||||
|
||||
if (pokemon.species.mythical)
|
||||
this.scene.validateAchv(achvs.CATCH_MYTHICAL);
|
||||
|
||||
this.scene.ui.showText(`${pokemon.name} was caught!`, null, () => {
|
||||
const end = () => {
|
||||
this.removePb();
|
||||
|
@ -16,7 +16,7 @@ import { GameData } from './system/game-data';
|
||||
import StarterSelectUiHandler from './ui/starter-select-ui-handler';
|
||||
import { TextStyle, addTextObject } from './ui/text';
|
||||
import { Moves, initMoves } from './data/move';
|
||||
import { ModifierPoolType, getDefaultModifierTypeForTier, getEnemyModifierTypesForWave, getModifierType, modifierTypes } from './modifier/modifier-type';
|
||||
import { ModifierPoolType, getDefaultModifierTypeForTier, getEnemyModifierTypesForWave } from './modifier/modifier-type';
|
||||
import AbilityBar from './ui/ability-bar';
|
||||
import { BlockItemTheftAbAttr, DoubleBattleChanceAbAttr, applyAbAttrs, initAbilities } from './data/ability';
|
||||
import Battle, { BattleType, FixedBattleConfig, fixedBattles } from './battle';
|
||||
@ -34,6 +34,7 @@ import SettingsUiHandler from './ui/settings-ui-handler';
|
||||
import MessageUiHandler from './ui/message-ui-handler';
|
||||
import { Species } from './data/species';
|
||||
import InvertPostFX from './pipelines/invert';
|
||||
import { Achv, achvs } from './system/achv';
|
||||
|
||||
const enableAuto = true;
|
||||
const quickStart = false;
|
||||
@ -199,6 +200,10 @@ export default class BattleScene extends Phaser.Scene {
|
||||
this.loadImage('icon_owned', 'ui');
|
||||
this.loadImage('ability_bar', 'ui');
|
||||
this.loadImage('party_exp_bar', 'ui');
|
||||
this.loadImage('achv_bar', 'ui');
|
||||
this.loadImage('achv_bar_2', 'ui');
|
||||
this.loadImage('achv_bar_3', 'ui');
|
||||
this.loadImage('achv_bar_4', 'ui');
|
||||
this.loadImage('shiny_star', 'ui', 'shiny.png');
|
||||
this.loadImage('icon_spliced', 'ui');
|
||||
|
||||
@ -306,6 +311,7 @@ export default class BattleScene extends Phaser.Scene {
|
||||
this.loadSe('beam');
|
||||
this.loadSe('upgrade');
|
||||
this.loadSe('buy');
|
||||
this.loadSe('achv');
|
||||
this.loadSe('error');
|
||||
|
||||
this.loadSe('pb_rel');
|
||||
@ -838,6 +844,7 @@ export default class BattleScene extends Phaser.Scene {
|
||||
this.waveCountText.setY(-(this.game.canvas.height / 6) + (this.enemyModifiers.filter(m => m.isIconVisible(this)).length ? 15 : 0));
|
||||
this.moneyText.setY(this.waveCountText.y + 10);
|
||||
this.partyExpBar.setY(this.moneyText.y + 15);
|
||||
this.ui?.achvBar.setY((this.game.canvas.height / 6 + this.moneyText.y + 15));
|
||||
}
|
||||
|
||||
getMaxExpLevel(ignoreLevelCap?: boolean): integer {
|
||||
@ -867,18 +874,19 @@ export default class BattleScene extends Phaser.Scene {
|
||||
checkInput(): boolean {
|
||||
if (this.blockInput)
|
||||
return;
|
||||
let inputSuccess = false;
|
||||
if (this.isButtonPressed(Button.UP))
|
||||
this.ui.processInput(Button.UP);
|
||||
inputSuccess = this.ui.processInput(Button.UP);
|
||||
else if (this.isButtonPressed(Button.DOWN))
|
||||
this.ui.processInput(Button.DOWN);
|
||||
inputSuccess = this.ui.processInput(Button.DOWN);
|
||||
else if (this.isButtonPressed(Button.LEFT))
|
||||
this.ui.processInput(Button.LEFT);
|
||||
inputSuccess = this.ui.processInput(Button.LEFT);
|
||||
else if (this.isButtonPressed(Button.RIGHT))
|
||||
this.ui.processInput(Button.RIGHT);
|
||||
inputSuccess = this.ui.processInput(Button.RIGHT);
|
||||
else if (this.isButtonPressed(Button.ACTION))
|
||||
this.ui.processInput(Button.ACTION);
|
||||
inputSuccess = this.ui.processInput(Button.ACTION);
|
||||
else if (this.isButtonPressed(Button.CANCEL))
|
||||
this.ui.processInput(Button.CANCEL);
|
||||
inputSuccess = this.ui.processInput(Button.CANCEL);
|
||||
else if (this.isButtonPressed(Button.MENU)) {
|
||||
switch (this.ui.getMode()) {
|
||||
case Mode.MESSAGE:
|
||||
@ -894,8 +902,7 @@ export default class BattleScene extends Phaser.Scene {
|
||||
case Mode.STARTER_SELECT:
|
||||
case Mode.CONFIRM:
|
||||
case Mode.GAME_MODE_SELECT:
|
||||
this.ui.setModeWithoutClear(Mode.SETTINGS);
|
||||
this.playSound('menu_open');
|
||||
this.ui.setOverlayMode(Mode.MENU);
|
||||
break;
|
||||
case Mode.SETTINGS:
|
||||
this.ui.revertMode();
|
||||
@ -904,16 +911,15 @@ export default class BattleScene extends Phaser.Scene {
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (this.ui?.getHandler() instanceof StarterSelectUiHandler) {
|
||||
} else if (this.ui?.getHandler() instanceof StarterSelectUiHandler) {
|
||||
if (this.isButtonPressed(Button.CYCLE_SHINY))
|
||||
this.ui.processInput(Button.CYCLE_SHINY);
|
||||
inputSuccess = this.ui.processInput(Button.CYCLE_SHINY);
|
||||
else if (this.isButtonPressed(Button.CYCLE_FORM))
|
||||
this.ui.processInput(Button.CYCLE_FORM);
|
||||
inputSuccess = this.ui.processInput(Button.CYCLE_FORM);
|
||||
else if (this.isButtonPressed(Button.CYCLE_GENDER))
|
||||
this.ui.processInput(Button.CYCLE_GENDER);
|
||||
inputSuccess = this.ui.processInput(Button.CYCLE_GENDER);
|
||||
else if (this.isButtonPressed(Button.CYCLE_ABILITY))
|
||||
this.ui.processInput(Button.CYCLE_ABILITY);
|
||||
inputSuccess = this.ui.processInput(Button.CYCLE_ABILITY);
|
||||
else
|
||||
return;
|
||||
}
|
||||
@ -1413,4 +1419,28 @@ export default class BattleScene extends Phaser.Scene {
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
validateAchvs(achvType: { new(...args: any[]): Achv }, ...args: any[]): void {
|
||||
const filteredAchvs = Object.values(achvs).filter(a => a instanceof achvType);
|
||||
let newAchv = false;
|
||||
for (let achv of filteredAchvs) {
|
||||
if (this.validateAchv(achv, args, false))
|
||||
newAchv = true;
|
||||
}
|
||||
|
||||
if (newAchv)
|
||||
this.gameData.saveSystem();
|
||||
}
|
||||
|
||||
validateAchv(achv: Achv, args?: any[], save: boolean = true): boolean {
|
||||
if (!this.gameData.achvUnlocks.hasOwnProperty(achv.id) && achv.validate(this, args)) {
|
||||
this.gameData.achvUnlocks[achv.id] = new Date().getTime();
|
||||
this.ui.achvBar.showAchv(achv);
|
||||
if (save)
|
||||
this.gameData.saveSystem();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
@ -101,7 +101,7 @@ export default class Move {
|
||||
return this.attrs.filter(a => a instanceof attrType);
|
||||
}
|
||||
|
||||
attr<T extends new (...args: any[]) => MoveAttr>(AttrType: T, ...args: ConstructorParameters<T>): Move {
|
||||
attr<T extends new (...args: any[]) => MoveAttr>(AttrType: T, ...args: ConstructorParameters<T>): this {
|
||||
const attr = new AttrType(...args);
|
||||
this.attrs.push(attr);
|
||||
const attrCondition = attr.getCondition();
|
||||
@ -111,7 +111,7 @@ export default class Move {
|
||||
return this;
|
||||
}
|
||||
|
||||
addAttr(attr: MoveAttr): Move {
|
||||
addAttr(attr: MoveAttr): this {
|
||||
this.attrs.push(attr);
|
||||
const attrCondition = attr.getCondition();
|
||||
if (attrCondition)
|
||||
@ -120,7 +120,7 @@ export default class Move {
|
||||
return this;
|
||||
}
|
||||
|
||||
target(moveTarget: MoveTarget): Move {
|
||||
target(moveTarget: MoveTarget): this {
|
||||
this.moveTarget = moveTarget;
|
||||
return this;
|
||||
}
|
||||
@ -129,7 +129,7 @@ export default class Move {
|
||||
return !!(this.flags & flag);
|
||||
}
|
||||
|
||||
condition(condition: MoveCondition): Move {
|
||||
condition(condition: MoveCondition): this {
|
||||
this.conditions.push(condition);
|
||||
|
||||
return this;
|
||||
@ -142,32 +142,32 @@ export default class Move {
|
||||
this.flags ^= flag;
|
||||
}
|
||||
|
||||
makesContact(makesContact?: boolean): Move {
|
||||
makesContact(makesContact?: boolean): this {
|
||||
this.setFlag(MoveFlags.MAKES_CONTACT, makesContact);
|
||||
return this;
|
||||
}
|
||||
|
||||
ignoresProtect(ignoresProtect?: boolean): Move {
|
||||
ignoresProtect(ignoresProtect?: boolean): this {
|
||||
this.setFlag(MoveFlags.IGNORE_PROTECT, ignoresProtect);
|
||||
return this;
|
||||
}
|
||||
|
||||
ignoresVirtual(ignoresVirtual?: boolean): Move {
|
||||
ignoresVirtual(ignoresVirtual?: boolean): this {
|
||||
this.setFlag(MoveFlags.IGNORE_VIRTUAL, ignoresVirtual);
|
||||
return this;
|
||||
}
|
||||
|
||||
soundBased(soundBased?: boolean): Move {
|
||||
soundBased(soundBased?: boolean): this {
|
||||
this.setFlag(MoveFlags.SOUND_BASED, soundBased);
|
||||
return this;
|
||||
}
|
||||
|
||||
hidesUser(hidesUser?: boolean): Move {
|
||||
hidesUser(hidesUser?: boolean): this {
|
||||
this.setFlag(MoveFlags.HIDE_USER, hidesUser);
|
||||
return this;
|
||||
}
|
||||
|
||||
hidesTarget(hidesTarget?: boolean): Move {
|
||||
hidesTarget(hidesTarget?: boolean): this {
|
||||
this.setFlag(MoveFlags.HIDE_TARGET, hidesTarget);
|
||||
return this;
|
||||
}
|
||||
|
@ -1,3 +1,10 @@
|
||||
function getData() {
|
||||
const dataStr = localStorage.getItem('data');
|
||||
if (!dataStr)
|
||||
return null;
|
||||
return JSON.parse(atob(dataStr));
|
||||
}
|
||||
|
||||
function getSession() {
|
||||
const sessionStr = localStorage.getItem('sessionData');
|
||||
if (!sessionStr)
|
||||
|
@ -6,7 +6,7 @@ import { EvolutionItem, pokemonEvolutions } from '../data/pokemon-evolutions';
|
||||
import { Stat, getStatName } from '../data/pokemon-stat';
|
||||
import { tmPoolTiers, tmSpecies } from '../data/tms';
|
||||
import { Type } from '../data/type';
|
||||
import PartyUiHandler, { PokemonMoveSelectFilter, PokemonRememberMoveSelectFilter, PokemonSelectFilter } from '../ui/party-ui-handler';
|
||||
import PartyUiHandler, { PokemonMoveSelectFilter, PokemonSelectFilter } from '../ui/party-ui-handler';
|
||||
import * as Utils from '../utils';
|
||||
import { TempBattleStat, getTempBattleStatBoosterItemName, getTempBattleStatName } from '../data/temp-battle-stat';
|
||||
import { BerryType, getBerryEffectDescription, getBerryName } from '../data/berry';
|
||||
|
@ -15,6 +15,7 @@ import { TempBattleStat } from '../data/temp-battle-stat';
|
||||
import { BerryType, getBerryEffectFunc, getBerryPredicate } from '../data/berry';
|
||||
import { Species } from '../data/species';
|
||||
import { StatusEffect, getStatusEffectDescriptor } from '../data/status-effect';
|
||||
import { MoneyAchv } from '../system/achv';
|
||||
|
||||
type ModifierType = ModifierTypes.ModifierType;
|
||||
export type ModifierPredicate = (modifier: Modifier) => boolean;
|
||||
@ -1171,6 +1172,7 @@ export class DamageMoneyRewardModifier extends PokemonHeldItemModifier {
|
||||
scene.applyModifiers(MoneyMultiplierModifier, true, moneyAmount);
|
||||
scene.money += moneyAmount.value;
|
||||
scene.updateMoneyText();
|
||||
scene.validateAchvs(MoneyAchv);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -1194,6 +1196,7 @@ export class MoneyInterestModifier extends PersistentModifier {
|
||||
const interestAmount = Math.floor(scene.money * 0.2 * this.getStackCount());
|
||||
scene.money += interestAmount;
|
||||
scene.updateMoneyText();
|
||||
scene.validateAchvs(MoneyAchv);
|
||||
|
||||
scene.queueMessage(`You received interest of ₽${interestAmount.toLocaleString('en-US')}\nfrom the ${this.type.name}!`, null, true);
|
||||
|
||||
|
@ -30,6 +30,7 @@ import PartyUiHandler, { PartyOption, PartyUiMode } from './ui/party-ui-handler'
|
||||
import SoundFade from 'phaser3-rex-plugins/plugins/soundfade';
|
||||
import { GameMode } from './game-mode';
|
||||
import { LevelMoves } from './data/pokemon-level-moves';
|
||||
import { DamageAchv, achvs } from './system/achv';
|
||||
|
||||
export enum FieldPosition {
|
||||
CENTER,
|
||||
@ -867,6 +868,8 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
this.scene.setPhaseQueueSplice();
|
||||
damage.value = Math.min(damage.value, this.hp);
|
||||
this.damage(damage.value);
|
||||
if (source.isPlayer())
|
||||
this.scene.validateAchvs(DamageAchv, damage);
|
||||
source.turnData.damageDealt += damage.value;
|
||||
this.turnData.attacksReceived.unshift({ move: move.id, result: result as DamageResult, damage: damage.value, critical: isCritical, sourceId: source.id });
|
||||
if (source.isPlayer() && !this.isPlayer())
|
||||
@ -1013,6 +1016,8 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
this.summonData.battleStats[stat] = source.summonData.battleStats[stat];
|
||||
for (let tag of source.summonData.tags)
|
||||
this.summonData.tags.push(tag);
|
||||
if (battleStats.filter(bs => bs === 6).length)
|
||||
this.scene.validateAchv(achvs.TRANSFER_MAX_BATTLE_STAT);
|
||||
}
|
||||
|
||||
getMoveHistory(): TurnMove[] {
|
||||
|
126
src/system/achv.ts
Normal file
@ -0,0 +1,126 @@
|
||||
import BattleScene from "../battle-scene";
|
||||
import * as Utils from "../utils";
|
||||
|
||||
export enum AchvTier {
|
||||
COMMON,
|
||||
GREAT,
|
||||
ULTRA,
|
||||
MASTER
|
||||
}
|
||||
|
||||
export class Achv {
|
||||
public id: string;
|
||||
public name: string;
|
||||
public description: string;
|
||||
public iconImage: string;
|
||||
public score: integer;
|
||||
|
||||
public secret: boolean;
|
||||
public hasParent: boolean;
|
||||
public parentId: string;
|
||||
|
||||
private conditionFunc: (scene: BattleScene, args: any[]) => boolean;
|
||||
|
||||
constructor(name: string, description: string, iconImage: string, score: integer, conditionFunc?: (scene: BattleScene, args: any[]) => boolean) {
|
||||
this.name = name;
|
||||
this.description = description;
|
||||
this.iconImage = iconImage;
|
||||
this.score = score;
|
||||
this.conditionFunc = conditionFunc;
|
||||
}
|
||||
|
||||
setSecret(hasParent?: boolean): this {
|
||||
this.secret = true;
|
||||
this.hasParent = !!hasParent;
|
||||
return this;
|
||||
}
|
||||
|
||||
validate(scene: BattleScene, args: any[]): boolean {
|
||||
return !this.conditionFunc || this.conditionFunc(scene, args);
|
||||
}
|
||||
|
||||
getTier(): AchvTier {
|
||||
if (this.score >= 250)
|
||||
return AchvTier.MASTER;
|
||||
if (this.score >= 100)
|
||||
return AchvTier.ULTRA;
|
||||
if (this.score >= 25)
|
||||
return AchvTier.GREAT;
|
||||
return AchvTier.COMMON;
|
||||
}
|
||||
}
|
||||
|
||||
export class MoneyAchv extends Achv {
|
||||
private moneyAmount: integer;
|
||||
|
||||
constructor(name: string, moneyAmount: integer, iconImage: string, score: integer) {
|
||||
super(name, `Accumulate a total of ₽${moneyAmount.toLocaleString('en-US')}`, iconImage, score, (scene: BattleScene, _args: any[]) => scene.money >= this.moneyAmount);
|
||||
|
||||
this.moneyAmount = moneyAmount;
|
||||
}
|
||||
}
|
||||
|
||||
export class DamageAchv extends Achv {
|
||||
private damageAmount: integer;
|
||||
|
||||
constructor(name: string, damageAmount: integer, iconImage: string, score: integer) {
|
||||
super(name, `Inflict ${damageAmount.toLocaleString('en-US')} damage in one hit`, iconImage, score, (_scene: BattleScene, args: any[]) => (args[0] as Utils.NumberHolder).value >= this.damageAmount);
|
||||
|
||||
this.damageAmount = damageAmount;
|
||||
}
|
||||
}
|
||||
|
||||
export class HealAchv extends Achv {
|
||||
private healAmount: integer;
|
||||
|
||||
constructor(name: string, healAmount: integer, iconImage: string, score: integer) {
|
||||
super(name, `Heal ${healAmount.toLocaleString('en-US')} HP at once with a move, ability, or held item`, iconImage, score, (_scene: BattleScene, args: any[]) => (args[0] as Utils.NumberHolder).value >= this.healAmount);
|
||||
|
||||
this.healAmount = healAmount;
|
||||
}
|
||||
}
|
||||
|
||||
export class LevelAchv extends Achv {
|
||||
private level: integer;
|
||||
|
||||
constructor(name: string, level: integer, iconImage: string, score: integer) {
|
||||
super(name, `Level up a Pokémon to Lv${level}`, iconImage, score, (scene: BattleScene, args: any[]) => (args[0] as Utils.IntegerHolder).value >= this.level);
|
||||
|
||||
this.level = level;
|
||||
}
|
||||
}
|
||||
|
||||
export const achvs = {
|
||||
_10K_MONEY: new MoneyAchv('Money Haver', 10000, 'nugget', 10),
|
||||
_100K_MONEY: new MoneyAchv('Rich', 100000, 'big_nugget', 25).setSecret(true),
|
||||
_1M_MONEY: new MoneyAchv('Millionaire', 1000000, 'relic_gold', 100).setSecret(true),
|
||||
_10M_MONEY: new MoneyAchv('One Percenter', 10000000, 'coin_case', 250).setSecret(true),
|
||||
_250_DMG: new DamageAchv('Hard Hitter', 1000, 'lucky_punch', 10),
|
||||
_1000_DMG: new DamageAchv('Harder Hitter', 1000, 'lucky_punch_great', 25).setSecret(true),
|
||||
_2500_DMG: new DamageAchv('That\'s a Lotta Damage!', 2500, 'lucky_punch_ultra', 100).setSecret(true),
|
||||
_10000_DMG: new DamageAchv('One Punch Man', 10000, 'lucky_punch_master', 250).setSecret(true),
|
||||
_250_HEAL: new HealAchv('Novice Healer', 250, 'potion', 10),
|
||||
_1000_HEAL: new HealAchv('Big Healer', 1000, 'super_potion', 25).setSecret(true),
|
||||
_2500_HEAL: new HealAchv('Cleric', 2500, 'hyper_potion', 100).setSecret(true),
|
||||
_10000_HEAL: new HealAchv('Recovery Master', 10000, 'max_potion', 250).setSecret(true),
|
||||
LV_100: new LevelAchv('But Wait, There\'s More!', 50, 'rare_candy', 50).setSecret(),
|
||||
LV_250: new LevelAchv('Elite', 250, 'rarer_candy', 150).setSecret(true),
|
||||
LV_1000: new LevelAchv('To Go Even Further Beyond', 250, 'candy_jar', 400).setSecret(true),
|
||||
TRANSFER_MAX_BATTLE_STAT: new Achv('Teamwork', 'Baton pass to another party member with at least one stat maxed out', 'stick', 25),
|
||||
CATCH_LEGENDARY: new Achv('Legendary', 'Catch a legendary Pokémon', 'mb', 100).setSecret(),
|
||||
CATCH_MYTHICAL: new Achv('Mythical', 'Catch a mythical Pokémon', 'strange_ball', 100).setSecret(),
|
||||
SEE_SHINY: new Achv('Shiny', 'Find a shiny Pokémon in the wild', 'pb_gold', 150).setSecret(),
|
||||
HIDDEN_ABILITY: new Achv('Hidden Potential', 'Catch a Pokémon with a hidden ability', 'ability_charm', 150).setSecret(),
|
||||
CLASSIC_VICTORY: new Achv('Undefeated', 'Beat the game in classic mode', 'relic_crown', 250)
|
||||
};
|
||||
|
||||
{
|
||||
(function() {
|
||||
const achvKeys = Object.keys(achvs);
|
||||
achvKeys.forEach((a: string, i: integer) => {
|
||||
achvs[a].id = a;
|
||||
if (achvs[a].hasParent)
|
||||
achvs[a].parentId = achvKeys[i - 1];
|
||||
});
|
||||
})();
|
||||
}
|
@ -7,7 +7,6 @@ import { Species } from "../data/species";
|
||||
import * as Utils from "../utils";
|
||||
import PokemonData from "./pokemon-data";
|
||||
import PersistentModifierData from "./modifier-data";
|
||||
import { PokemonHeldItemModifier } from "../modifier/modifier";
|
||||
import ArenaData from "./arena-data";
|
||||
import { Unlockables } from "./unlockables";
|
||||
import { GameMode } from "../game-mode";
|
||||
@ -15,12 +14,14 @@ import { BattleType } from "../battle";
|
||||
import TrainerData from "./trainer-data";
|
||||
import { trainerConfigs } from "../data/trainer-type";
|
||||
import { Setting, setSetting, settingDefaults } from "./settings";
|
||||
import { achvs } from "./achv";
|
||||
|
||||
interface SystemSaveData {
|
||||
trainerId: integer;
|
||||
secretId: integer;
|
||||
dexData: DexData;
|
||||
unlocks: Unlocks;
|
||||
achvUnlocks: AchvUnlocks;
|
||||
timestamp: integer;
|
||||
}
|
||||
|
||||
@ -45,6 +46,10 @@ interface Unlocks {
|
||||
[key: integer]: boolean;
|
||||
}
|
||||
|
||||
interface AchvUnlocks {
|
||||
[key: string]: integer
|
||||
}
|
||||
|
||||
export interface DexData {
|
||||
[key: integer]: DexData | DexEntry
|
||||
}
|
||||
@ -81,6 +86,8 @@ export class GameData {
|
||||
|
||||
public unlocks: Unlocks;
|
||||
|
||||
public achvUnlocks: AchvUnlocks;
|
||||
|
||||
constructor(scene: BattleScene) {
|
||||
this.scene = scene;
|
||||
this.loadSettings();
|
||||
@ -91,6 +98,7 @@ export class GameData {
|
||||
[Unlockables.MINI_BLACK_HOLE]: false,
|
||||
[Unlockables.SPLICED_ENDLESS_MODE]: false
|
||||
};
|
||||
this.achvUnlocks = {};
|
||||
this.initDexData();
|
||||
this.loadSystem();
|
||||
}
|
||||
@ -99,11 +107,14 @@ export class GameData {
|
||||
if (this.scene.quickStart)
|
||||
return false;
|
||||
|
||||
console.log(this.achvUnlocks, "wah")
|
||||
|
||||
const data: SystemSaveData = {
|
||||
trainerId: this.trainerId,
|
||||
secretId: this.secretId,
|
||||
dexData: this.dexData,
|
||||
unlocks: this.unlocks,
|
||||
achvUnlocks: this.achvUnlocks,
|
||||
timestamp: new Date().getTime()
|
||||
};
|
||||
|
||||
@ -129,6 +140,13 @@ export class GameData {
|
||||
}
|
||||
}
|
||||
|
||||
if (data.achvUnlocks) {
|
||||
for (let a of Object.keys(data.achvUnlocks)) {
|
||||
if (achvs.hasOwnProperty(a))
|
||||
this.achvUnlocks[a] = data.achvUnlocks[a];
|
||||
}
|
||||
}
|
||||
|
||||
if (data.timestamp === undefined)
|
||||
this.convertDexData(data.dexData);
|
||||
|
||||
|
96
src/ui/achv-bar.ts
Normal file
@ -0,0 +1,96 @@
|
||||
import BattleScene from "../battle-scene";
|
||||
import { Achv } from "../system/achv";
|
||||
import { TextStyle, addTextObject } from "./text";
|
||||
|
||||
export default class AchvBar extends Phaser.GameObjects.Container {
|
||||
private bg: Phaser.GameObjects.NineSlice;
|
||||
private icon: Phaser.GameObjects.Sprite;
|
||||
private titleText: Phaser.GameObjects.Text;
|
||||
private scoreText: Phaser.GameObjects.Text;
|
||||
private descriptionText: Phaser.GameObjects.Text;
|
||||
|
||||
private queue: Achv[] = [];
|
||||
|
||||
public shown: boolean;
|
||||
|
||||
constructor(scene: BattleScene) {
|
||||
super(scene, scene.game.canvas.width / 6, 0);
|
||||
}
|
||||
|
||||
setup(): void {
|
||||
this.bg = this.scene.add.nineslice(0, 0, 'achv_bar', null, 160, 40, 41, 6, 16, 4);
|
||||
this.bg.setOrigin(0, 0);
|
||||
|
||||
this.add(this.bg);
|
||||
|
||||
this.icon = this.scene.add.sprite(4, 4, 'items');
|
||||
this.icon.setOrigin(0, 0);
|
||||
this.add(this.icon);
|
||||
|
||||
this.titleText = addTextObject(this.scene, 40, 3, '', TextStyle.MESSAGE, { fontSize: '72px' });
|
||||
this.titleText.setOrigin(0, 0);
|
||||
this.add(this.titleText);
|
||||
|
||||
this.scoreText = addTextObject(this.scene, 150, 3, '', TextStyle.MESSAGE, { fontSize: '72px' });
|
||||
this.scoreText.setOrigin(1, 0);
|
||||
this.add(this.scoreText);
|
||||
|
||||
this.descriptionText = addTextObject(this.scene, 43, 16, '', TextStyle.WINDOW, { fontSize: '72px' });
|
||||
this.descriptionText.setOrigin(0, 0);
|
||||
this.add(this.descriptionText);
|
||||
|
||||
this.descriptionText.setWordWrapWidth(664);
|
||||
this.descriptionText.setLineSpacing(-5);
|
||||
|
||||
this.setScale(0.5);
|
||||
|
||||
this.shown = false;
|
||||
}
|
||||
|
||||
showAchv(achv: Achv): void {
|
||||
if (this.shown) {
|
||||
this.queue.push(achv);
|
||||
return;
|
||||
}
|
||||
|
||||
const tier = achv.getTier();
|
||||
|
||||
this.bg.setTexture(`achv_bar${tier ? `_${tier + 1}` : ''}`);
|
||||
this.icon.setFrame(achv.iconImage);
|
||||
this.titleText.setText(achv.name);
|
||||
this.descriptionText.setText(achv.description);
|
||||
this.scoreText.setText(`+${achv.score}pt`);
|
||||
|
||||
(this.scene as BattleScene).playSound('achv');
|
||||
|
||||
this.scene.tweens.add({
|
||||
targets: this,
|
||||
x: (this.scene.game.canvas.width / 6) - 76,
|
||||
duration: 500,
|
||||
ease: 'Sine.easeOut'
|
||||
});
|
||||
|
||||
this.scene.time.delayedCall(10000, () => this.hide());
|
||||
|
||||
this.setVisible(true);
|
||||
this.shown = true;
|
||||
}
|
||||
|
||||
protected hide(): void {
|
||||
if (!this.shown)
|
||||
return;
|
||||
|
||||
this.scene.tweens.add({
|
||||
targets: this,
|
||||
x: (this.scene.game.canvas.width / 6),
|
||||
duration: 500,
|
||||
ease: 'Sine.easeIn',
|
||||
onComplete: () => {
|
||||
this.shown = false;
|
||||
this.setVisible(false);
|
||||
if (this.queue.length)
|
||||
this.showAchv(this.queue.shift());
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
210
src/ui/achvs-ui-handler.ts
Normal file
@ -0,0 +1,210 @@
|
||||
import BattleScene, { Button } from "../battle-scene";
|
||||
import { Achv, achvs } from "../system/achv";
|
||||
import MessageUiHandler from "./message-ui-handler";
|
||||
import { TextStyle, addTextObject } from "./text";
|
||||
import { Mode } from "./ui";
|
||||
|
||||
export default class AchvsUiHandler extends MessageUiHandler {
|
||||
private achvsContainer: Phaser.GameObjects.Container;
|
||||
private achvIconsContainer: Phaser.GameObjects.Container;
|
||||
|
||||
private achvIconsBg: Phaser.GameObjects.NineSlice;
|
||||
private achvIcons: Phaser.GameObjects.Sprite[];
|
||||
private titleText: Phaser.GameObjects.Text;
|
||||
private scoreText: Phaser.GameObjects.Text;
|
||||
private unlockText: Phaser.GameObjects.Text;
|
||||
|
||||
private cursorObj: Phaser.GameObjects.NineSlice;
|
||||
|
||||
constructor(scene: BattleScene, mode?: Mode) {
|
||||
super(scene, mode);
|
||||
}
|
||||
|
||||
setup() {
|
||||
const ui = this.getUi();
|
||||
|
||||
this.achvsContainer = this.scene.add.container(1, -(this.scene.game.canvas.height / 6) + 1);
|
||||
|
||||
this.achvsContainer.setInteractive(new Phaser.Geom.Rectangle(0, 0, this.scene.game.canvas.width / 6, this.scene.game.canvas.height / 6), Phaser.Geom.Rectangle.Contains);
|
||||
|
||||
const headerBg = this.scene.add.nineslice(0, 0, 'window', null, (this.scene.game.canvas.width / 6) - 2, 24, 6, 6, 6, 6);
|
||||
headerBg.setOrigin(0, 0);
|
||||
|
||||
const headerText = addTextObject(this.scene, 0, 0, 'Achievements', TextStyle.SETTINGS_LABEL);
|
||||
headerText.setOrigin(0, 0);
|
||||
headerText.setPositionRelative(headerBg, 8, 4);
|
||||
|
||||
this.achvIconsBg = this.scene.add.nineslice(0, headerBg.height, 'window', null, (this.scene.game.canvas.width / 6) - 2, (this.scene.game.canvas.height / 6) - headerBg.height - 68, 6, 6, 6, 6);
|
||||
this.achvIconsBg.setOrigin(0, 0);
|
||||
|
||||
this.achvIconsContainer = this.scene.add.container(6, headerBg.height + 6);
|
||||
|
||||
this.achvIcons = [];
|
||||
|
||||
for (let a = 0; a < Object.keys(achvs).length; a++) {
|
||||
const x = (a % 17) * 18;
|
||||
const y = Math.floor(a / 17) * 18;
|
||||
|
||||
const icon = this.scene.add.sprite(x, y, 'items', 'unknown');
|
||||
icon.setOrigin(0, 0);
|
||||
icon.setScale(0.5);
|
||||
|
||||
this.achvIcons.push(icon);
|
||||
this.achvIconsContainer.add(icon);
|
||||
}
|
||||
|
||||
const titleBg = this.scene.add.nineslice(0, headerBg.height + this.achvIconsBg.height, 'window', null, 174, 24, 6, 6, 6, 6);
|
||||
titleBg.setOrigin(0, 0);
|
||||
|
||||
this.titleText = addTextObject(this.scene, 0, 0, '', TextStyle.WINDOW);
|
||||
this.titleText.setOrigin(0, 0);
|
||||
this.titleText.setPositionRelative(titleBg, 8, 4);
|
||||
|
||||
const scoreBg = this.scene.add.nineslice(titleBg.x + titleBg.width, titleBg.y, 'window', null, 46, 24, 6, 6, 6, 6);
|
||||
scoreBg.setOrigin(0, 0);
|
||||
|
||||
this.scoreText = addTextObject(this.scene, 0, 0, '', TextStyle.WINDOW);
|
||||
this.scoreText.setOrigin(0, 0);
|
||||
this.scoreText.setPositionRelative(scoreBg, 8, 4);
|
||||
|
||||
const unlockBg = this.scene.add.nineslice(scoreBg.x + scoreBg.width, scoreBg.y, 'window', null, 98, 24, 6, 6, 6, 6);
|
||||
unlockBg.setOrigin(0, 0);
|
||||
|
||||
this.unlockText = addTextObject(this.scene, 0, 0, '', TextStyle.WINDOW);
|
||||
this.unlockText.setOrigin(0, 0);
|
||||
this.unlockText.setPositionRelative(unlockBg, 8, 4);
|
||||
|
||||
const descriptionBg = this.scene.add.nineslice(0, titleBg.y + titleBg.height, 'window', null, (this.scene.game.canvas.width / 6) - 2, 42, 6, 6, 6, 6);
|
||||
descriptionBg.setOrigin(0, 0);
|
||||
|
||||
const descriptionText = addTextObject(this.scene, 0, 0, '', TextStyle.WINDOW, { maxLines: 2 });
|
||||
descriptionText.setWordWrapWidth(1870);
|
||||
descriptionText.setOrigin(0, 0);
|
||||
descriptionText.setPositionRelative(descriptionBg, 8, 4);
|
||||
|
||||
this.message = descriptionText;
|
||||
|
||||
this.achvsContainer.add(headerBg);
|
||||
this.achvsContainer.add(headerText);
|
||||
this.achvsContainer.add(this.achvIconsBg);
|
||||
this.achvsContainer.add(this.achvIconsContainer);
|
||||
this.achvsContainer.add(titleBg);
|
||||
this.achvsContainer.add(this.titleText);
|
||||
this.achvsContainer.add(scoreBg);
|
||||
this.achvsContainer.add(this.scoreText);
|
||||
this.achvsContainer.add(unlockBg);
|
||||
this.achvsContainer.add(this.unlockText);
|
||||
this.achvsContainer.add(descriptionBg);
|
||||
this.achvsContainer.add(descriptionText);
|
||||
|
||||
ui.add(this.achvsContainer);
|
||||
|
||||
this.setCursor(0);
|
||||
|
||||
this.achvsContainer.setVisible(false);
|
||||
}
|
||||
|
||||
show(args: any[]) {
|
||||
super.show(args);
|
||||
|
||||
const achvUnlocks = this.scene.gameData.achvUnlocks;
|
||||
|
||||
Object.values(achvs).forEach((achv: Achv, i: integer) => {
|
||||
const icon = this.achvIcons[i];
|
||||
const unlocked = achvUnlocks.hasOwnProperty(achv.id);
|
||||
const hidden = achv.secret && (!achv.parentId || !achvUnlocks.hasOwnProperty(achv.parentId));
|
||||
const tinted = !hidden && !unlocked;
|
||||
|
||||
icon.setFrame(!hidden ? achv.iconImage : 'unknown');
|
||||
if (tinted)
|
||||
icon.setTintFill(0);
|
||||
else
|
||||
icon.clearTint();
|
||||
});
|
||||
|
||||
this.achvsContainer.setVisible(true);
|
||||
this.setCursor(0);
|
||||
|
||||
this.getUi().moveTo(this.achvsContainer, this.getUi().length - 1);
|
||||
|
||||
this.getUi().hideTooltip();
|
||||
}
|
||||
|
||||
protected showAchv(achv: Achv) {
|
||||
const achvUnlocks = this.scene.gameData.achvUnlocks;
|
||||
const unlocked = achvUnlocks.hasOwnProperty(achv.id);
|
||||
const hidden = achv.secret && (!achv.parentId || !achvUnlocks.hasOwnProperty(achv.parentId));
|
||||
|
||||
this.titleText.setText(unlocked ? achv.name : '???');
|
||||
this.showText(!hidden ? achv.description : '');
|
||||
this.scoreText.setText(`${achv.score}pt`);
|
||||
this.unlockText.setText(unlocked ? new Date(achvUnlocks[achv.id]).toLocaleDateString() : 'Locked');
|
||||
}
|
||||
|
||||
processInput(button: Button): boolean {
|
||||
const ui = this.getUi();
|
||||
|
||||
let success = false;
|
||||
|
||||
if (button === Button.CANCEL) {
|
||||
success = true;
|
||||
this.scene.ui.revertMode();
|
||||
} else {
|
||||
switch (button) {
|
||||
case Button.UP:
|
||||
if (this.cursor >= 17)
|
||||
success = this.setCursor(this.cursor - 17);
|
||||
break;
|
||||
case Button.DOWN:
|
||||
if (this.cursor + 17 < Object.keys(achvs).length)
|
||||
success = this.setCursor(this.cursor + 17);
|
||||
break;
|
||||
case Button.LEFT:
|
||||
if (this.cursor % 17)
|
||||
success = this.setCursor(this.cursor - 1);
|
||||
break;
|
||||
case Button.RIGHT:
|
||||
if (this.cursor % 17 < 16 && this.cursor < Object.keys(achvs).length - 1)
|
||||
success = this.setCursor(this.cursor + 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (success)
|
||||
ui.playSelect();
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
setCursor(cursor: integer): boolean {
|
||||
let ret = super.setCursor(cursor);
|
||||
|
||||
let updateAchv = ret;
|
||||
|
||||
if (!this.cursorObj) {
|
||||
this.cursorObj = this.scene.add.nineslice(0, 0, 'starter_select_cursor_highlight', null, 16, 16, 1, 1, 1, 1);
|
||||
this.cursorObj.setOrigin(0, 0);
|
||||
this.achvIconsContainer.add(this.cursorObj);
|
||||
updateAchv = true;
|
||||
}
|
||||
|
||||
this.cursorObj.setPositionRelative(this.achvIcons[this.cursor], 0, 0);
|
||||
|
||||
if (updateAchv)
|
||||
this.showAchv(achvs[Object.keys(achvs)[cursor]]);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
clear() {
|
||||
super.clear();
|
||||
this.achvsContainer.setVisible(false);
|
||||
this.eraseCursor();
|
||||
}
|
||||
|
||||
eraseCursor() {
|
||||
if (this.cursorObj)
|
||||
this.cursorObj.destroy();
|
||||
this.cursorObj = null;
|
||||
}
|
||||
}
|
@ -55,7 +55,7 @@ export default class BallUiHandler extends UiHandler {
|
||||
this.setCursor(this.cursor);
|
||||
}
|
||||
|
||||
processInput(button: Button) {
|
||||
processInput(button: Button): boolean {
|
||||
const ui = this.getUi();
|
||||
|
||||
let success = false;
|
||||
@ -91,6 +91,8 @@ export default class BallUiHandler extends UiHandler {
|
||||
|
||||
if (success)
|
||||
ui.playSelect();
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
updateCounts() {
|
||||
|
@ -102,7 +102,7 @@ export default class BattleMessageUiHandler extends MessageUiHandler {
|
||||
this.message.setWordWrapWidth(1780);
|
||||
}
|
||||
|
||||
processInput(button: Button): void {
|
||||
processInput(button: Button): boolean {
|
||||
const ui = this.getUi();
|
||||
if (this.awaitingActionInput) {
|
||||
if (button === Button.CANCEL || button === Button.ACTION) {
|
||||
@ -111,6 +111,7 @@ export default class BattleMessageUiHandler extends MessageUiHandler {
|
||||
const originalOnActionInput = this.onActionInput;
|
||||
this.onActionInput = null;
|
||||
originalOnActionInput();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -52,7 +52,7 @@ export default class BiomeSelectUiHandler extends UiHandler {
|
||||
}
|
||||
}
|
||||
|
||||
processInput(button: Button) {
|
||||
processInput(button: Button): boolean {
|
||||
const ui = this.getUi();
|
||||
|
||||
let success = false;
|
||||
@ -78,6 +78,8 @@ export default class BiomeSelectUiHandler extends UiHandler {
|
||||
|
||||
if (success)
|
||||
ui.playSelect();
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
setCursor(cursor: integer): boolean {
|
||||
|
@ -51,7 +51,7 @@ export default class CommandUiHandler extends UiHandler {
|
||||
this.setCursor(this.getCursor());
|
||||
}
|
||||
|
||||
processInput(button: Button) {
|
||||
processInput(button: Button): boolean {
|
||||
const ui = this.getUi();
|
||||
|
||||
let success = false;
|
||||
@ -104,6 +104,8 @@ export default class CommandUiHandler extends UiHandler {
|
||||
|
||||
if (success)
|
||||
ui.playSelect();
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
getCursor(): integer {
|
||||
|
@ -20,8 +20,8 @@ export default class EvolutionSceneHandler extends UiHandler {
|
||||
this.scene.fieldUI.bringToTop(this.evolutionContainer);
|
||||
}
|
||||
|
||||
processInput(button: Button) {
|
||||
this.scene.ui.getMessageHandler().processInput(button);
|
||||
processInput(button: Button): boolean {
|
||||
return this.scene.ui.getMessageHandler().processInput(button);
|
||||
}
|
||||
|
||||
setCursor(_cursor: integer): boolean {
|
||||
|
@ -47,7 +47,7 @@ export default class FightUiHandler extends UiHandler {
|
||||
this.displayMoves();
|
||||
}
|
||||
|
||||
processInput(button: Button) {
|
||||
processInput(button: Button): boolean {
|
||||
const ui = this.getUi();
|
||||
|
||||
let success = false;
|
||||
@ -87,6 +87,8 @@ export default class FightUiHandler extends UiHandler {
|
||||
|
||||
if (success)
|
||||
ui.playSelect();
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
getCursor(): integer {
|
||||
|
@ -42,7 +42,7 @@ export default class GameModeSelectUiHandler extends OptionSelectUiHandler {
|
||||
}
|
||||
}
|
||||
|
||||
processInput(button: Button) {
|
||||
processInput(button: Button): boolean {
|
||||
const ui = this.getUi();
|
||||
|
||||
const options = this.getOptions();
|
||||
@ -59,5 +59,7 @@ export default class GameModeSelectUiHandler extends OptionSelectUiHandler {
|
||||
ui.playSelect();
|
||||
} else
|
||||
return super.processInput(button);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
124
src/ui/menu-ui-handler.ts
Normal file
@ -0,0 +1,124 @@
|
||||
import BattleScene, { Button } from "../battle-scene";
|
||||
import { TextStyle, addTextObject } from "./text";
|
||||
import { Mode } from "./ui";
|
||||
import UiHandler from "./uiHandler";
|
||||
import * as Utils from "../utils";
|
||||
|
||||
export enum MenuOptions {
|
||||
SETTINGS,
|
||||
ACHIEVEMENTS
|
||||
}
|
||||
|
||||
export default class MenuUiHandler extends UiHandler {
|
||||
private menuContainer: Phaser.GameObjects.Container;
|
||||
|
||||
private menuBg: Phaser.GameObjects.NineSlice;
|
||||
protected optionSelectText: Phaser.GameObjects.Text;
|
||||
|
||||
private cursorObj: Phaser.GameObjects.Image;
|
||||
|
||||
constructor(scene: BattleScene, mode?: Mode) {
|
||||
super(scene, mode);
|
||||
}
|
||||
|
||||
setup() {
|
||||
const ui = this.getUi();
|
||||
|
||||
this.menuContainer = this.scene.add.container(1, -(this.scene.game.canvas.height / 6) + 1);
|
||||
|
||||
this.menuContainer.setInteractive(new Phaser.Geom.Rectangle(0, 0, this.scene.game.canvas.width / 6, this.scene.game.canvas.height / 6), Phaser.Geom.Rectangle.Contains);
|
||||
|
||||
this.menuBg = this.scene.add.nineslice((this.scene.game.canvas.width / 6) - 92, 0, 'window', null, 90, (this.scene.game.canvas.height / 6) - 2, 6, 6, 6, 6);
|
||||
this.menuBg.setOrigin(0, 0);
|
||||
|
||||
this.menuContainer.add(this.menuBg);
|
||||
|
||||
this.optionSelectText = addTextObject(this.scene, 0, 0, Utils.getEnumKeys(MenuOptions).map(o => Utils.toReadableString(o)).join('\n'), TextStyle.WINDOW, { maxLines: Utils.getEnumKeys(MenuOptions).length });
|
||||
this.optionSelectText.setPositionRelative(this.menuBg, 14, 6);
|
||||
this.optionSelectText.setLineSpacing(12);
|
||||
this.menuContainer.add(this.optionSelectText);
|
||||
|
||||
ui.add(this.menuContainer);
|
||||
|
||||
this.setCursor(0);
|
||||
|
||||
this.menuContainer.setVisible(false);
|
||||
}
|
||||
|
||||
show(args: any[]) {
|
||||
super.show(args);
|
||||
|
||||
this.menuContainer.setVisible(true);
|
||||
this.setCursor(0);
|
||||
|
||||
this.getUi().moveTo(this.menuContainer, this.getUi().length - 1);
|
||||
|
||||
this.getUi().hideTooltip();
|
||||
|
||||
this.scene.playSound('menu_open');
|
||||
}
|
||||
|
||||
processInput(button: Button): boolean {
|
||||
const ui = this.getUi();
|
||||
|
||||
let success = false;
|
||||
|
||||
if (button === Button.ACTION) {
|
||||
switch (this.cursor as MenuOptions) {
|
||||
case MenuOptions.SETTINGS:
|
||||
this.scene.ui.setOverlayMode(Mode.SETTINGS);
|
||||
success = true;
|
||||
break;
|
||||
case MenuOptions.ACHIEVEMENTS:
|
||||
this.scene.ui.setOverlayMode(Mode.ACHIEVEMENTS);
|
||||
success = true;
|
||||
break;
|
||||
}
|
||||
} else if (button === Button.CANCEL) {
|
||||
success = true;
|
||||
this.scene.ui.revertMode();
|
||||
} else {
|
||||
switch (button) {
|
||||
case Button.UP:
|
||||
if (this.cursor)
|
||||
success = this.setCursor(this.cursor - 1);
|
||||
break;
|
||||
case Button.DOWN:
|
||||
if (this.cursor < Utils.getEnumKeys(MenuOptions).length)
|
||||
success = this.setCursor(this.cursor + 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (success)
|
||||
ui.playSelect();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
setCursor(cursor: integer): boolean {
|
||||
const ret = super.setCursor(cursor);
|
||||
|
||||
if (!this.cursorObj) {
|
||||
this.cursorObj = this.scene.add.image(0, 0, 'cursor');
|
||||
this.cursorObj.setOrigin(0, 0);
|
||||
this.menuContainer.add(this.cursorObj);
|
||||
}
|
||||
|
||||
this.cursorObj.setPositionRelative(this.menuBg, 7, 9 + this.cursor * 16);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
clear() {
|
||||
super.clear();
|
||||
this.menuContainer.setVisible(false);
|
||||
this.eraseCursor();
|
||||
}
|
||||
|
||||
eraseCursor() {
|
||||
if (this.cursorObj)
|
||||
this.cursorObj.destroy();
|
||||
this.cursorObj = null;
|
||||
}
|
||||
}
|
@ -137,11 +137,11 @@ export default class ModifierSelectUiHandler extends AwaitableUiHandler {
|
||||
});
|
||||
}
|
||||
|
||||
processInput(button: Button) {
|
||||
processInput(button: Button): boolean {
|
||||
const ui = this.getUi();
|
||||
|
||||
if (!this.awaitingActionInput)
|
||||
return;
|
||||
return false;
|
||||
|
||||
let success = false;
|
||||
|
||||
@ -193,6 +193,8 @@ export default class ModifierSelectUiHandler extends AwaitableUiHandler {
|
||||
|
||||
if (success)
|
||||
ui.playSelect();
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
setCursor(cursor: integer): boolean {
|
||||
|
@ -65,7 +65,7 @@ export default abstract class OptionSelectUiHandler extends UiHandler {
|
||||
}
|
||||
}
|
||||
|
||||
processInput(button: Button) {
|
||||
processInput(button: Button): boolean {
|
||||
const ui = this.getUi();
|
||||
|
||||
let success = false;
|
||||
@ -94,6 +94,8 @@ export default abstract class OptionSelectUiHandler extends UiHandler {
|
||||
|
||||
if (success)
|
||||
ui.playSelect();
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
setCursor(cursor: integer): boolean {
|
||||
|
@ -177,23 +177,22 @@ export default class PartyUiHandler extends MessageUiHandler {
|
||||
this.setCursor(this.cursor < 6 ? this.cursor : 0);
|
||||
}
|
||||
|
||||
processInput(button: Button) {
|
||||
processInput(button: Button): boolean {
|
||||
const ui = this.getUi();
|
||||
|
||||
if (this.pendingPrompt)
|
||||
return;
|
||||
return false;
|
||||
|
||||
if (this.awaitingActionInput) {
|
||||
if (button === Button.ACTION || button === Button.CANCEL) {
|
||||
if (this.onActionInput) {
|
||||
if ((button === Button.ACTION || button === Button.CANCEL) && this.onActionInput) {
|
||||
ui.playSelect();
|
||||
const originalOnActionInput = this.onActionInput;
|
||||
this.onActionInput = null;
|
||||
originalOnActionInput();
|
||||
this.awaitingActionInput = false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
let success = false;
|
||||
@ -206,6 +205,7 @@ export default class PartyUiHandler extends MessageUiHandler {
|
||||
this.startTransfer();
|
||||
this.clearOptions();
|
||||
ui.playSelect();
|
||||
return true;
|
||||
} else if (this.partyUiMode === PartyUiMode.REMEMBER_MOVE_MODIFIER && option !== PartyOption.CANCEL) {
|
||||
let filterResult = (this.selectFilter as PokemonSelectFilter)(pokemon);
|
||||
if (filterResult === null) {
|
||||
@ -216,6 +216,7 @@ export default class PartyUiHandler extends MessageUiHandler {
|
||||
this.showText(filterResult as string, null, () => this.showText(null, 0), null, true);
|
||||
}
|
||||
ui.playSelect();
|
||||
return true;
|
||||
} else if ((option !== PartyOption.SUMMARY && option !== PartyOption.RELEASE && option !== PartyOption.CANCEL)
|
||||
|| (option === PartyOption.RELEASE && this.partyUiMode === PartyUiMode.RELEASE)) {
|
||||
let filterResult: string;
|
||||
@ -254,7 +255,7 @@ export default class PartyUiHandler extends MessageUiHandler {
|
||||
(this.scene.getCurrentPhase() as CommandPhase).handleCommand(Command.POKEMON, this.cursor, option === PartyOption.PASS_BATON);
|
||||
if (this.partyUiMode !== PartyUiMode.MODIFIER && this.partyUiMode !== PartyUiMode.TM_MODIFIER && this.partyUiMode !== PartyUiMode.MOVE_MODIFIER)
|
||||
ui.playSelect();
|
||||
return;
|
||||
return true;
|
||||
} else {
|
||||
this.clearOptions();
|
||||
this.showText(filterResult as string, null, () => this.showText(null, 0), null, true);
|
||||
@ -262,6 +263,7 @@ export default class PartyUiHandler extends MessageUiHandler {
|
||||
} else if (option === PartyOption.SUMMARY) {
|
||||
ui.playSelect();
|
||||
ui.setModeWithoutClear(Mode.SUMMARY, pokemon).then(() => this.clearOptions());
|
||||
return true;
|
||||
} else if (option === PartyOption.RELEASE) {
|
||||
this.clearOptions();
|
||||
ui.playSelect();
|
||||
@ -277,11 +279,13 @@ export default class PartyUiHandler extends MessageUiHandler {
|
||||
});
|
||||
} else
|
||||
this.showText('You can\'t release a Pokémon that\'s in battle!', null, () => this.showText(null, 0), null, true);
|
||||
return true;
|
||||
} else if (option === PartyOption.CANCEL)
|
||||
this.processInput(Button.CANCEL);
|
||||
return this.processInput(Button.CANCEL);
|
||||
} else if (button === Button.CANCEL) {
|
||||
this.clearOptions();
|
||||
ui.playSelect();
|
||||
return true;
|
||||
} else {
|
||||
switch (button) {
|
||||
case Button.UP:
|
||||
@ -300,8 +304,8 @@ export default class PartyUiHandler extends MessageUiHandler {
|
||||
} else if (this.partyUiMode === PartyUiMode.FAINT_SWITCH)
|
||||
ui.playError();
|
||||
else
|
||||
this.processInput(Button.CANCEL);
|
||||
return;
|
||||
return this.processInput(Button.CANCEL);
|
||||
return true;
|
||||
} else if (button === Button.CANCEL) {
|
||||
if ((this.partyUiMode === PartyUiMode.MODIFIER_TRANSFER || this.partyUiMode === PartyUiMode.SPLICE) && this.transferMode) {
|
||||
this.clearTransfer();
|
||||
@ -317,7 +321,8 @@ export default class PartyUiHandler extends MessageUiHandler {
|
||||
ui.playSelect();
|
||||
}
|
||||
}
|
||||
return;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
const slotCount = this.partySlots.length;
|
||||
@ -343,6 +348,8 @@ export default class PartyUiHandler extends MessageUiHandler {
|
||||
|
||||
if (success)
|
||||
ui.playSelect();
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
populatePartySlots() {
|
||||
|
@ -91,9 +91,7 @@ export default class SettingsUiHandler extends UiHandler {
|
||||
|
||||
const settings: object = localStorage.hasOwnProperty('settings') ? JSON.parse(localStorage.getItem('settings')) : {};
|
||||
|
||||
Object.keys(settingDefaults).forEach((setting, s) => {
|
||||
this.setOptionCursor(s, settings.hasOwnProperty(setting) ? settings[setting] : settingDefaults[setting]);
|
||||
});
|
||||
Object.keys(settingDefaults).forEach((setting, s) => this.setOptionCursor(s, settings.hasOwnProperty(setting) ? settings[setting] : settingDefaults[setting]));
|
||||
|
||||
this.settingsContainer.setVisible(true);
|
||||
this.setCursor(0);
|
||||
@ -103,7 +101,7 @@ export default class SettingsUiHandler extends UiHandler {
|
||||
this.getUi().hideTooltip();
|
||||
}
|
||||
|
||||
processInput(button: Button) {
|
||||
processInput(button: Button): boolean {
|
||||
const ui = this.getUi();
|
||||
|
||||
let success = false;
|
||||
@ -134,6 +132,8 @@ export default class SettingsUiHandler extends UiHandler {
|
||||
|
||||
if (success)
|
||||
ui.playSelect();
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
setCursor(cursor: integer): boolean {
|
||||
|
@ -301,10 +301,11 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
||||
this.starterSelectMessageBoxContainer.setVisible(true);
|
||||
}
|
||||
|
||||
processInput(button: Button): void {
|
||||
processInput(button: Button): boolean {
|
||||
const ui = this.getUi();
|
||||
|
||||
let success = false;
|
||||
let error = false;
|
||||
|
||||
if (this.genMode) {
|
||||
switch (button) {
|
||||
@ -323,7 +324,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
||||
} else {
|
||||
if (button === Button.ACTION) {
|
||||
if (!this.speciesStarterDexEntry)
|
||||
ui.playError();
|
||||
error = true;
|
||||
else if (this.starterCursors.length < 3) {
|
||||
let isDupe = false;
|
||||
for (let s = 0; s < this.starterCursors.length; s++) {
|
||||
@ -380,7 +381,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
||||
success = true;
|
||||
this.updateInstructions();
|
||||
} else
|
||||
ui.playError();
|
||||
error = true;
|
||||
}
|
||||
} else if (button === Button.CANCEL) {
|
||||
if (this.starterCursors.length) {
|
||||
@ -388,7 +389,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
||||
success = true;
|
||||
this.updateInstructions();
|
||||
} else
|
||||
ui.playError();
|
||||
error = true;
|
||||
} else {
|
||||
const genStarters = this.starterSelectGenIconContainers[this.genCursor].getAll().length;
|
||||
const rows = Math.ceil(genStarters / 9);
|
||||
@ -446,6 +447,10 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
||||
|
||||
if (success)
|
||||
ui.playSelect();
|
||||
else if (error)
|
||||
ui.playError();
|
||||
|
||||
return success || error;
|
||||
}
|
||||
|
||||
updateInstructions(): void {
|
||||
|
@ -241,13 +241,14 @@ export default class SummaryUiHandler extends UiHandler {
|
||||
this.hideStatus(!fromSummary);
|
||||
}
|
||||
|
||||
processInput(button: Button) {
|
||||
processInput(button: Button): boolean {
|
||||
if (this.transitioning)
|
||||
return;
|
||||
return false;
|
||||
|
||||
const ui = this.getUi();
|
||||
|
||||
let success = false;
|
||||
let error = false;
|
||||
|
||||
if (this.moveSelect) {
|
||||
if (button === Button.ACTION) {
|
||||
@ -283,9 +284,9 @@ export default class SummaryUiHandler extends UiHandler {
|
||||
}
|
||||
success = true;
|
||||
} else if (this.moveCursor === 4)
|
||||
this.processInput(Button.CANCEL);
|
||||
return this.processInput(Button.CANCEL);
|
||||
else
|
||||
ui.playError();
|
||||
error = true;
|
||||
} else if (button === Button.CANCEL) {
|
||||
this.hideMoveSelect();
|
||||
success = true;
|
||||
@ -336,6 +337,10 @@ export default class SummaryUiHandler extends UiHandler {
|
||||
|
||||
if (success)
|
||||
ui.playSelect();
|
||||
else if (error)
|
||||
ui.playError();
|
||||
|
||||
return success || error;
|
||||
}
|
||||
|
||||
setCursor(cursor: integer): boolean {
|
||||
|
@ -41,7 +41,7 @@ export default class TargetSelectUiHandler extends UiHandler {
|
||||
this.setCursor(this.targets.indexOf(this.cursor) > -1 ? this.cursor : this.targets[0]);
|
||||
}
|
||||
|
||||
processInput(button: Button) {
|
||||
processInput(button: Button): boolean {
|
||||
const ui = this.getUi();
|
||||
|
||||
let success = false;
|
||||
@ -72,6 +72,8 @@ export default class TargetSelectUiHandler extends UiHandler {
|
||||
|
||||
if (success)
|
||||
ui.playSelect();
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
setCursor(cursor: integer): boolean {
|
||||
|
@ -107,7 +107,7 @@ export function getModifierTierTextTint(tier: integer): integer {
|
||||
case 1: // ModifierTier.GREAT:
|
||||
return 0x3890f8;
|
||||
case 2: // ModifierTier.ULTRA:
|
||||
return 0xf8d038
|
||||
return 0xf8d038;
|
||||
case 3: // ModifierTier.MASTER:
|
||||
return 0xe020c0;
|
||||
case 4: // ModifierTier.LUXURY:
|
||||
|
54
src/ui/ui.ts
@ -15,8 +15,10 @@ import BiomeSelectUiHandler from './biome-select-ui-handler';
|
||||
import TargetSelectUiHandler from './target-select-ui-handler';
|
||||
import GameModeSelectUiHandler from './game-mode-select-ui-handler';
|
||||
import SettingsUiHandler from './settings-ui-handler';
|
||||
import { TextStyle, addTextObject, getTextColor } from './text';
|
||||
import { getPokeballTintColor } from '../data/pokeball';
|
||||
import { TextStyle, addTextObject } from './text';
|
||||
import AchvBar from './achv-bar';
|
||||
import MenuUiHandler from './menu-ui-handler';
|
||||
import AchvsUiHandler from './achvs-ui-handler';
|
||||
|
||||
export enum Mode {
|
||||
MESSAGE,
|
||||
@ -32,7 +34,9 @@ export enum Mode {
|
||||
EVOLUTION_SCENE,
|
||||
CONFIRM,
|
||||
GAME_MODE_SELECT,
|
||||
SETTINGS
|
||||
MENU,
|
||||
SETTINGS,
|
||||
ACHIEVEMENTS
|
||||
};
|
||||
|
||||
const transitionModes = [
|
||||
@ -45,14 +49,21 @@ const transitionModes = [
|
||||
const noTransitionModes = [
|
||||
Mode.CONFIRM,
|
||||
Mode.GAME_MODE_SELECT,
|
||||
Mode.MENU,
|
||||
Mode.SETTINGS
|
||||
];
|
||||
|
||||
const menuModes = [
|
||||
Mode.MENU,
|
||||
Mode.SETTINGS
|
||||
];
|
||||
|
||||
export default class UI extends Phaser.GameObjects.Container {
|
||||
private mode: Mode;
|
||||
private lastMode: Mode;
|
||||
private modeChain: Mode[];
|
||||
private handlers: UiHandler[];
|
||||
private overlay: Phaser.GameObjects.Rectangle;
|
||||
public achvBar: AchvBar;
|
||||
|
||||
private tooltipContainer: Phaser.GameObjects.Container;
|
||||
private tooltipBg: Phaser.GameObjects.NineSlice;
|
||||
@ -65,6 +76,7 @@ export default class UI extends Phaser.GameObjects.Container {
|
||||
super(scene, 0, scene.game.canvas.height / 6);
|
||||
|
||||
this.mode = Mode.MESSAGE;
|
||||
this.modeChain = [];
|
||||
this.handlers = [
|
||||
new BattleMessageUiHandler(scene),
|
||||
new CommandUiHandler(scene),
|
||||
@ -79,7 +91,9 @@ export default class UI extends Phaser.GameObjects.Container {
|
||||
new EvolutionSceneHandler(scene),
|
||||
new ConfirmUiHandler(scene),
|
||||
new GameModeSelectUiHandler(scene),
|
||||
new SettingsUiHandler(scene)
|
||||
new MenuUiHandler(scene),
|
||||
new SettingsUiHandler(scene),
|
||||
new AchvsUiHandler(scene)
|
||||
];
|
||||
}
|
||||
|
||||
@ -91,6 +105,10 @@ export default class UI extends Phaser.GameObjects.Container {
|
||||
(this.scene as BattleScene).uiContainer.add(this.overlay);
|
||||
this.overlay.setVisible(false);
|
||||
this.setupTooltip();
|
||||
|
||||
this.achvBar = new AchvBar(this.scene as BattleScene);
|
||||
this.achvBar.setup();
|
||||
(this.scene as BattleScene).uiContainer.add(this.achvBar);
|
||||
}
|
||||
|
||||
private setupTooltip() {
|
||||
@ -121,11 +139,11 @@ export default class UI extends Phaser.GameObjects.Container {
|
||||
return this.handlers[Mode.MESSAGE] as BattleMessageUiHandler;
|
||||
}
|
||||
|
||||
processInput(button: Button): void {
|
||||
processInput(button: Button): boolean {
|
||||
if (this.overlayActive)
|
||||
return;
|
||||
return false;
|
||||
|
||||
this.getHandler().processInput(button);
|
||||
return this.getHandler().processInput(button);
|
||||
}
|
||||
|
||||
showText(text: string, delay?: integer, callback?: Function, callbackDelay?: integer, prompt?: boolean, promptDelay?: integer): void {
|
||||
@ -229,7 +247,7 @@ export default class UI extends Phaser.GameObjects.Container {
|
||||
});
|
||||
}
|
||||
|
||||
private setModeInternal(mode: Mode, clear: boolean, forceTransition: boolean, args: any[]): Promise<void> {
|
||||
private setModeInternal(mode: Mode, clear: boolean, forceTransition: boolean, chainMode: boolean, args: any[]): Promise<void> {
|
||||
return new Promise(resolve => {
|
||||
if (this.mode === mode && !forceTransition) {
|
||||
resolve();
|
||||
@ -239,7 +257,8 @@ export default class UI extends Phaser.GameObjects.Container {
|
||||
if (this.mode !== mode) {
|
||||
if (clear)
|
||||
this.getHandler().clear();
|
||||
this.lastMode = this.mode && !clear ? this.mode : undefined;
|
||||
if (chainMode && this.mode && !clear)
|
||||
this.modeChain.push(this.mode);
|
||||
this.mode = mode;
|
||||
this.getHandler().show(args);
|
||||
}
|
||||
@ -263,23 +282,26 @@ export default class UI extends Phaser.GameObjects.Container {
|
||||
}
|
||||
|
||||
setMode(mode: Mode, ...args: any[]): Promise<void> {
|
||||
return this.setModeInternal(mode, true, false, args);
|
||||
return this.setModeInternal(mode, true, false, false, args);
|
||||
}
|
||||
|
||||
setModeForceTransition(mode: Mode, ...args: any[]): Promise<void> {
|
||||
return this.setModeInternal(mode, true, true, args);
|
||||
return this.setModeInternal(mode, true, true, false, args);
|
||||
}
|
||||
|
||||
setModeWithoutClear(mode: Mode, ...args: any[]): Promise<void> {
|
||||
return this.setModeInternal(mode, false, false, args);
|
||||
return this.setModeInternal(mode, false, false, false, args);
|
||||
}
|
||||
|
||||
setOverlayMode(mode: Mode, ...args: any[]): Promise<void> {
|
||||
return this.setModeInternal(mode, false, false, true, args);
|
||||
}
|
||||
|
||||
revertMode(): void {
|
||||
if (!this.lastMode)
|
||||
if (!this.modeChain.length)
|
||||
return;
|
||||
|
||||
this.getHandler().clear();
|
||||
this.mode = this.lastMode;
|
||||
this.lastMode = undefined;
|
||||
this.mode = this.modeChain.pop();
|
||||
}
|
||||
}
|
@ -18,7 +18,7 @@ export default abstract class UiHandler {
|
||||
this.active = true;
|
||||
}
|
||||
|
||||
abstract processInput(button: Button): void;
|
||||
abstract processInput(button: Button): boolean;
|
||||
|
||||
getUi() {
|
||||
return this.scene.ui;
|
||||
|
@ -134,11 +134,9 @@ export class NumberHolder {
|
||||
}
|
||||
}
|
||||
|
||||
export class IntegerHolder {
|
||||
public value: integer;
|
||||
|
||||
export class IntegerHolder extends NumberHolder {
|
||||
constructor(value: integer) {
|
||||
this.value = value;
|
||||
super(value);
|
||||
}
|
||||
}
|
||||
|
||||
|