Add achievement system and UI

Add achievement system and UI; fix counting invalid inputs in UI handlers for input delay
pull/2/head
Flashfyre 2023-11-12 00:31:40 -05:00
parent ff93e6233f
commit cbbb8e972b
49 changed files with 4920 additions and 3764 deletions

231
package-lock.json generated
View File

@ -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

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 56 KiB

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 275 B

View 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>

View File

@ -0,0 +1 @@
cmd /c TexturePacker ./ ./configuration.tps --sheet ../items.png --data ../items.json --replace .png=

Binary file not shown.

After

Width:  |  Height:  |  Size: 468 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 469 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 466 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 220 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 340 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 178 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 885 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 159 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 399 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 437 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 433 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 433 B

View File

@ -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();

View File

@ -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;
}
}

View File

@ -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;
}

View File

@ -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)

View File

@ -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';

View File

@ -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);

View File

@ -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
View 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];
});
})();
}

View File

@ -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();
}
@ -98,12 +106,15 @@ export class GameData {
public saveSystem(): boolean {
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
View 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
View 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;
}
}

View File

@ -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() {

View File

@ -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;
}
}
}

View File

@ -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 {

View File

@ -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 {

View File

@ -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 {

View File

@ -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 {

View File

@ -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
View 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;
}
}

View File

@ -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 {

View File

@ -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 {

View File

@ -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) {
ui.playSelect();
const originalOnActionInput = this.onActionInput;
this.onActionInput = null;
originalOnActionInput();
this.awaitingActionInput = false;
}
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() {

View File

@ -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 {

View File

@ -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 {

View File

@ -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 {

View File

@ -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 {

View File

@ -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:

View File

@ -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();
}
}

View File

@ -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;

View File

@ -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);
}
}