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", "name": "pokemon-rogue-battle",
"version": "0.0.1", "version": "0.0.1",
"dependencies": { "dependencies": {
"phaser": "^3.61.0-beta.2", "phaser": "^3.70.0",
"phaser3-rex-plugins": "^1.1.84" "phaser3-rex-plugins": "^1.1.84"
}, },
"devDependencies": { "devDependencies": {
@ -29,9 +29,9 @@
} }
}, },
"node_modules/@babel/runtime": { "node_modules/@babel/runtime": {
"version": "7.23.1", "version": "7.23.2",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.1.tgz", "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.2.tgz",
"integrity": "sha512-hC2v6p8ZSI/W0HUzh3V8C5g+NwSKzKPtJwSpTjwl0o297GP9+ZLQSkdvHz46CM3LqyoXxq+5G9komY+eSqSO0g==", "integrity": "sha512-mM8eg4yl5D6i3lu2QKPuPH4FArvJ8KhTofbE7jwMUv9KX5mBvwPAqnV3MlyBNqdp9RyRKP6Yck8TrfYrPvX3bg==",
"dependencies": { "dependencies": {
"regenerator-runtime": "^0.14.0" "regenerator-runtime": "^0.14.0"
}, },
@ -407,9 +407,9 @@
} }
}, },
"node_modules/@eslint-community/regexpp": { "node_modules/@eslint-community/regexpp": {
"version": "4.9.1", "version": "4.10.0",
"resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.9.1.tgz", "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz",
"integrity": "sha512-Y27x+MBLjXa+0JWDhykM3+JE+il3kHKAEqabfEWq3SDhZjLYb6/BHL/JKFnH3fe207JaXkyDo685Oc2Glt6ifA==", "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==",
"dev": true, "dev": true,
"engines": { "engines": {
"node": "^12.0.0 || ^14.0.0 || >=16.0.0" "node": "^12.0.0 || ^14.0.0 || >=16.0.0"
@ -439,21 +439,21 @@
} }
}, },
"node_modules/@eslint/js": { "node_modules/@eslint/js": {
"version": "8.50.0", "version": "8.52.0",
"resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.50.0.tgz", "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.52.0.tgz",
"integrity": "sha512-NCC3zz2+nvYd+Ckfh87rA47zfu2QsQpvc6k1yzTk+b9KzRj0wkGa8LSoGOXN6Zv4lRf/EIoZ80biDh9HOI+RNQ==", "integrity": "sha512-mjZVbpaeMZludF2fsWLD0Z9gCref1Tk4i9+wddjRvpUNqqcndPkBD09N/Mapey0b3jaXbLm2kICwFv2E64QinA==",
"dev": true, "dev": true,
"engines": { "engines": {
"node": "^12.22.0 || ^14.17.0 || >=16.0.0" "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
} }
}, },
"node_modules/@humanwhocodes/config-array": { "node_modules/@humanwhocodes/config-array": {
"version": "0.11.11", "version": "0.11.13",
"resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.11.tgz", "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.13.tgz",
"integrity": "sha512-N2brEuAadi0CcdeMXUkhbZB84eskAc8MEX1By6qEchoVywSgXPIjou4rYsl0V3Hj0ZnuGycGCjdNgockbzeWNA==", "integrity": "sha512-JSBDMiDKSzQVngfRjOdFXgFfklaXI4K9nLF49Auh21lmBWRLIK3+xTErTWD4KU54pb6coM6ESE7Awz/FNU3zgQ==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@humanwhocodes/object-schema": "^1.2.1", "@humanwhocodes/object-schema": "^2.0.1",
"debug": "^4.1.1", "debug": "^4.1.1",
"minimatch": "^3.0.5" "minimatch": "^3.0.5"
}, },
@ -475,9 +475,9 @@
} }
}, },
"node_modules/@humanwhocodes/object-schema": { "node_modules/@humanwhocodes/object-schema": {
"version": "1.2.1", "version": "2.0.1",
"resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.1.tgz",
"integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", "integrity": "sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw==",
"dev": true "dev": true
}, },
"node_modules/@koa/cors": { "node_modules/@koa/cors": {
@ -527,6 +527,12 @@
"node": ">= 8" "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": { "node_modules/accepts": {
"version": "1.3.8", "version": "1.3.8",
"resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz",
@ -541,9 +547,9 @@
} }
}, },
"node_modules/acorn": { "node_modules/acorn": {
"version": "8.10.0", "version": "8.11.1",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.1.tgz",
"integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==", "integrity": "sha512-IJTNCJMRHfRfb8un89z1QtS0x890C2QUrUxFMK8zy+RizcId6mfnqOf68Bu9YkDgpLYuvCm6aYbwDatXVZPjMQ==",
"dev": true, "dev": true,
"bin": { "bin": {
"acorn": "bin/acorn" "acorn": "bin/acorn"
@ -645,13 +651,14 @@
} }
}, },
"node_modules/call-bind": { "node_modules/call-bind": {
"version": "1.0.2", "version": "1.0.5",
"resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.5.tgz",
"integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", "integrity": "sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"function-bind": "^1.1.1", "function-bind": "^1.1.2",
"get-intrinsic": "^1.0.2" "get-intrinsic": "^1.2.1",
"set-function-length": "^1.1.1"
}, },
"funding": { "funding": {
"url": "https://github.com/sponsors/ljharb" "url": "https://github.com/sponsors/ljharb"
@ -769,11 +776,11 @@
"dev": true "dev": true
}, },
"node_modules/cross-fetch": { "node_modules/cross-fetch": {
"version": "3.1.6", "version": "4.0.0",
"resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.6.tgz", "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-4.0.0.tgz",
"integrity": "sha512-riRvo06crlE8HiqOwIpQhxwdOk4fOeR7FVM/wXoxchFEqMNUjvbs3bfo4OTgMEMHzppd4DxFBDbyySj8Cv781g==", "integrity": "sha512-e4a5N8lVvuLgAWgnCrLr2PP0YyDOTHa9H/Rj54dirp61qXnNq46m82bRhNqIA5VccJtWBvPTFRV3TtvHUKPB1g==",
"dependencies": { "dependencies": {
"node-fetch": "^2.6.11" "node-fetch": "^2.6.12"
} }
}, },
"node_modules/cross-spawn": { "node_modules/cross-spawn": {
@ -819,6 +826,20 @@
"integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
"dev": true "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": { "node_modules/delegates": {
"version": "1.0.0", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz",
@ -927,18 +948,19 @@
} }
}, },
"node_modules/eslint": { "node_modules/eslint": {
"version": "8.50.0", "version": "8.52.0",
"resolved": "https://registry.npmjs.org/eslint/-/eslint-8.50.0.tgz", "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.52.0.tgz",
"integrity": "sha512-FOnOGSuFuFLv/Sa+FDVRZl4GGVAAFFi8LecRsI5a1tMO5HIE8nCm4ivAlzt4dT3ol/PaaGC0rJEEXQmHJBGoOg==", "integrity": "sha512-zh/JHnaixqHZsolRB/w9/02akBk9EPrOs9JwcTP2ek7yL5bVvXuRariiaAjjoJ5DvuwQ1WAE/HsMz+w17YgBCg==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/eslint-utils": "^4.2.0",
"@eslint-community/regexpp": "^4.6.1", "@eslint-community/regexpp": "^4.6.1",
"@eslint/eslintrc": "^2.1.2", "@eslint/eslintrc": "^2.1.2",
"@eslint/js": "8.50.0", "@eslint/js": "8.52.0",
"@humanwhocodes/config-array": "^0.11.11", "@humanwhocodes/config-array": "^0.11.13",
"@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/module-importer": "^1.0.1",
"@nodelib/fs.walk": "^1.2.8", "@nodelib/fs.walk": "^1.2.8",
"@ungap/structured-clone": "^1.2.0",
"ajv": "^6.12.4", "ajv": "^6.12.4",
"chalk": "^4.0.0", "chalk": "^4.0.0",
"cross-spawn": "^7.0.2", "cross-spawn": "^7.0.2",
@ -1128,12 +1150,12 @@
} }
}, },
"node_modules/flat-cache": { "node_modules/flat-cache": {
"version": "3.1.0", "version": "3.1.1",
"resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.1.0.tgz", "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.1.1.tgz",
"integrity": "sha512-OHx4Qwrrt0E4jEIcI5/Xb+f+QmJYNj2rrK8wiIdQOIrB9WrrJL8cjZvXdXuBTkkEwEqLycb5BeZDV1o2i9bTew==", "integrity": "sha512-/qM2b3LUIaIgviBQovTLvijfyOQXPtSRnRK26ksj2J7rzPIecePUIpJsZ4T02Qg+xiAEKIs5K8dsHEd+VaKa/Q==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"flatted": "^3.2.7", "flatted": "^3.2.9",
"keyv": "^4.5.3", "keyv": "^4.5.3",
"rimraf": "^3.0.2" "rimraf": "^3.0.2"
}, },
@ -1177,21 +1199,24 @@
} }
}, },
"node_modules/function-bind": { "node_modules/function-bind": {
"version": "1.1.1", "version": "1.1.2",
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
"integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
"dev": true "dev": true,
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
}, },
"node_modules/get-intrinsic": { "node_modules/get-intrinsic": {
"version": "1.2.1", "version": "1.2.2",
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.2.tgz",
"integrity": "sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==", "integrity": "sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"function-bind": "^1.1.1", "function-bind": "^1.1.2",
"has": "^1.0.3",
"has-proto": "^1.0.1", "has-proto": "^1.0.1",
"has-symbols": "^1.0.3" "has-symbols": "^1.0.3",
"hasown": "^2.0.0"
}, },
"funding": { "funding": {
"url": "https://github.com/sponsors/ljharb" "url": "https://github.com/sponsors/ljharb"
@ -1242,9 +1267,9 @@
} }
}, },
"node_modules/globals": { "node_modules/globals": {
"version": "13.22.0", "version": "13.23.0",
"resolved": "https://registry.npmjs.org/globals/-/globals-13.22.0.tgz", "resolved": "https://registry.npmjs.org/globals/-/globals-13.23.0.tgz",
"integrity": "sha512-H1Ddc/PbZHTDVJSnj8kWptIRSD6AM3pK+mKytuIVF4uoBV7rshFlhhvA58ceJ5wp3Er58w6zj7bykMpYXt3ETw==", "integrity": "sha512-XAmF0RjlrjY23MA51q3HltdlGxUpXPvg0GioKiD9X6HD28iMjo2dKC8Vqwm7lne4GNr78+RHTfliktR6ZH09wA==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"type-fest": "^0.20.2" "type-fest": "^0.20.2"
@ -1256,6 +1281,18 @@
"url": "https://github.com/sponsors/sindresorhus" "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": { "node_modules/graphemer": {
"version": "1.4.0", "version": "1.4.0",
"resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz",
@ -1282,18 +1319,6 @@
"uglify-js": "^3.1.4" "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": { "node_modules/has-flag": {
"version": "4.0.0", "version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
@ -1303,6 +1328,18 @@
"node": ">=8" "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": { "node_modules/has-proto": {
"version": "1.0.1", "version": "1.0.1",
"resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz",
@ -1342,6 +1379,18 @@
"url": "https://github.com/sponsors/ljharb" "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": { "node_modules/http-assert": {
"version": "1.5.0", "version": "1.5.0",
"resolved": "https://registry.npmjs.org/http-assert/-/http-assert-1.5.0.tgz", "resolved": "https://registry.npmjs.org/http-assert/-/http-assert-1.5.0.tgz",
@ -1403,11 +1452,11 @@
} }
}, },
"node_modules/i18next-http-backend": { "node_modules/i18next-http-backend": {
"version": "2.2.2", "version": "2.3.0",
"resolved": "https://registry.npmjs.org/i18next-http-backend/-/i18next-http-backend-2.2.2.tgz", "resolved": "https://registry.npmjs.org/i18next-http-backend/-/i18next-http-backend-2.3.0.tgz",
"integrity": "sha512-mJu4ZqzDtBiU3O4GV9AbK5ekEqoDMdMnCl3pkdXmb5b8yoIH//u8FsmIe6C5qXb3teZu+j6VMi20tjUgzeABiw==", "integrity": "sha512-9m34IcWdS3r43cgq/7O5IsDxTvSQ7pePwk2eQIH5q6Em6OjDCsSjboRWg2jqVdeIoCtHwzTN/byDHPStMsKsPQ==",
"dependencies": { "dependencies": {
"cross-fetch": "3.1.6" "cross-fetch": "4.0.0"
} }
}, },
"node_modules/iconv-lite": { "node_modules/iconv-lite": {
@ -1457,9 +1506,9 @@
} }
}, },
"node_modules/inflation": { "node_modules/inflation": {
"version": "2.0.0", "version": "2.1.0",
"resolved": "https://registry.npmjs.org/inflation/-/inflation-2.0.0.tgz", "resolved": "https://registry.npmjs.org/inflation/-/inflation-2.1.0.tgz",
"integrity": "sha512-m3xv4hJYR2oXw4o4Y5l6P5P16WYmazYof+el6Al3f+YlggGj6qT9kImBAnzDelRALnP5d3h4jGBPKzYCizjZZw==", "integrity": "sha512-t54PPJHG1Pp7VQvxyVCJ9mBbjG3Hqryges9bXoOO6GExCPa+//i/d5GSuFtpx3ALLd7lgIAur6zrIlBQyJuMlQ==",
"dev": true, "dev": true,
"engines": { "engines": {
"node": ">= 0.8.0" "node": ">= 0.8.0"
@ -1583,9 +1632,9 @@
} }
}, },
"node_modules/keyv": { "node_modules/keyv": {
"version": "4.5.3", "version": "4.5.4",
"resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.3.tgz", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz",
"integrity": "sha512-QCiSav9WaX1PgETJ+SpNnx2PRRapJ/oRSXM4VO5OGYGSjrxbKPVFVhB3l2OCbLCk329N8qyAtsJjSjvVBWzEug==", "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"json-buffer": "3.0.1" "json-buffer": "3.0.1"
@ -1662,6 +1711,7 @@
"version": "10.1.1", "version": "10.1.1",
"resolved": "https://registry.npmjs.org/koa-router/-/koa-router-10.1.1.tgz", "resolved": "https://registry.npmjs.org/koa-router/-/koa-router-10.1.1.tgz",
"integrity": "sha512-z/OzxVjf5NyuNO3t9nJpx7e1oR3FSBAauiwXtMQu4ppcnuNZzTaQ4p21P8A6r2Es8uJJM339oc4oVW+qX7SqnQ==", "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, "dev": true,
"dependencies": { "dependencies": {
"debug": "^4.1.1", "debug": "^4.1.1",
@ -1839,9 +1889,9 @@
} }
}, },
"node_modules/object-inspect": { "node_modules/object-inspect": {
"version": "1.12.3", "version": "1.13.1",
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz",
"integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==", "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==",
"dev": true, "dev": true,
"funding": { "funding": {
"url": "https://github.com/sponsors/ljharb" "url": "https://github.com/sponsors/ljharb"
@ -1981,11 +2031,11 @@
"dev": true "dev": true
}, },
"node_modules/phaser": { "node_modules/phaser": {
"version": "3.61.0-beta.2", "version": "3.70.0",
"resolved": "https://registry.npmjs.org/phaser/-/phaser-3.61.0-beta.2.tgz", "resolved": "https://registry.npmjs.org/phaser/-/phaser-3.70.0.tgz",
"integrity": "sha512-nXEGqIORZe1ygijKi8iqqA2OHT5l4DVkVxc1HWhApg0lhXzH/p0ErHecS1j9UGB75G3beF+qd9AzBkgwNJ9QsQ==", "integrity": "sha512-2g+gh+Jp9f/Ho9FOXOYbIJMGf3UZXyMbW2iLScFaLQw11e/LqVyxj/YmaBauWbHabeTnZjiWkPklDnxhesMH0g==",
"dependencies": { "dependencies": {
"eventemitter3": "^5.0.0" "eventemitter3": "^5.0.1"
} }
}, },
"node_modules/phaser3-rex-plugins": { "node_modules/phaser3-rex-plugins": {
@ -2239,6 +2289,21 @@
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
"dev": true "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": { "node_modules/setprototypeof": {
"version": "1.2.0", "version": "1.2.0",
"resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
@ -2516,9 +2581,9 @@
} }
}, },
"node_modules/vite-plugin-fs": { "node_modules/vite-plugin-fs": {
"version": "1.0.0-beta.6", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/vite-plugin-fs/-/vite-plugin-fs-1.0.0-beta.6.tgz", "resolved": "https://registry.npmjs.org/vite-plugin-fs/-/vite-plugin-fs-1.0.0.tgz",
"integrity": "sha512-WKvlZ7S+5wdJp0Mut5C15rH89iJxL4xUHkjBvKfhPPKWKBIQBPvFA1jM9Y64Ns2kF/92TI9i8+DRAgHklKgPBw==", "integrity": "sha512-iVWZaPNDyAXxRgLg2dM0M3j3eQT0vFPpvjeCoVdWa+S9Kx1DFmOkeBBnTSez7D335IfwrlKbThxx9Gwh5cF3YA==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@koa/cors": "^3.4.3", "@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 { BattleType, BattlerIndex, TurnCommand } from "./battle";
import { GameMode } from "./game-mode"; import { GameMode } from "./game-mode";
import { Species } from "./data/species"; import { Species } from "./data/species";
import { HealAchv, LevelAchv, MoneyAchv, achvs } from "./system/achv";
export class CheckLoadPhase extends BattlePhase { export class CheckLoadPhase extends BattlePhase {
private loaded: boolean; private loaded: boolean;
@ -329,6 +330,8 @@ export class EncounterPhase extends BattlePhase {
enemyPokemon.untint(100, 'Sine.easeOut'); enemyPokemon.untint(100, 'Sine.easeOut');
enemyPokemon.cry(); enemyPokemon.cry();
enemyPokemon.showInfo(); enemyPokemon.showInfo();
if (enemyPokemon.isShiny())
this.scene.validateAchv(achvs.SEE_SHINY);
}); });
let text = enemyField.length === 1 let text = enemyField.length === 1
? `A wild ${enemyField[0].name} appeared!` ? `A wild ${enemyField[0].name} appeared!`
@ -2259,6 +2262,8 @@ export class MoneyRewardPhase extends BattlePhase {
this.scene.money += moneyAmount.value; this.scene.money += moneyAmount.value;
this.scene.updateMoneyText(); 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); 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.gameData.clearSession();
this.scene.time.delayedCall(1000, () => { this.scene.time.delayedCall(1000, () => {
if (this.victory)
this.scene.validateAchv(achvs.CLASSIC_VICTORY);
const fadeDuration = this.victory ? 10000 : 5000; const fadeDuration = this.victory ? 10000 : 5000;
this.scene.fadeOutBgm(fadeDuration, true); this.scene.fadeOutBgm(fadeDuration, true);
this.scene.ui.fadeOut(fadeDuration).then(() => { this.scene.ui.fadeOut(fadeDuration).then(() => {
@ -2464,6 +2471,8 @@ export class LevelUpPhase extends PlayerPartyMemberPokemonPhase {
start() { start() {
super.start(); super.start();
this.scene.validateAchvs(LevelAchv, new Utils.IntegerHolder(this.level));
const pokemon = this.getPokemon(); const pokemon = this.getPokemon();
const prevStats = pokemon.stats.slice(0); const prevStats = pokemon.stats.slice(0);
pokemon.calculateStats(); pokemon.calculateStats();
@ -2633,7 +2642,9 @@ export class PokemonHealPhase extends CommonAnimPhase {
const hpRestoreMultiplier = new Utils.IntegerHolder(1); const hpRestoreMultiplier = new Utils.IntegerHolder(1);
if (!this.revive) if (!this.revive)
this.scene.applyModifiers(HealingBoosterModifier, this.player, hpRestoreMultiplier); 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()); pokemon.updateInfo().then(() => super.end());
} else if (this.showFullHpMessage) } else if (this.showFullHpMessage)
this.message = getPokemonMessage(pokemon, `'s\nHP is full!`); this.message = getPokemonMessage(pokemon, `'s\nHP is full!`);
@ -2783,6 +2794,16 @@ export class AttemptCapturePhase extends PokemonPhase {
catch() { catch() {
const pokemon = this.getPokemon() as EnemyPokemon; const pokemon = this.getPokemon() as EnemyPokemon;
this.scene.unshiftPhase(new VictoryPhase(this.scene, this.battlerIndex)); 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, () => { this.scene.ui.showText(`${pokemon.name} was caught!`, null, () => {
const end = () => { const end = () => {
this.removePb(); this.removePb();

View File

@ -16,7 +16,7 @@ import { GameData } from './system/game-data';
import StarterSelectUiHandler from './ui/starter-select-ui-handler'; import StarterSelectUiHandler from './ui/starter-select-ui-handler';
import { TextStyle, addTextObject } from './ui/text'; import { TextStyle, addTextObject } from './ui/text';
import { Moves, initMoves } from './data/move'; 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 AbilityBar from './ui/ability-bar';
import { BlockItemTheftAbAttr, DoubleBattleChanceAbAttr, applyAbAttrs, initAbilities } from './data/ability'; import { BlockItemTheftAbAttr, DoubleBattleChanceAbAttr, applyAbAttrs, initAbilities } from './data/ability';
import Battle, { BattleType, FixedBattleConfig, fixedBattles } from './battle'; 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 MessageUiHandler from './ui/message-ui-handler';
import { Species } from './data/species'; import { Species } from './data/species';
import InvertPostFX from './pipelines/invert'; import InvertPostFX from './pipelines/invert';
import { Achv, achvs } from './system/achv';
const enableAuto = true; const enableAuto = true;
const quickStart = false; const quickStart = false;
@ -199,6 +200,10 @@ export default class BattleScene extends Phaser.Scene {
this.loadImage('icon_owned', 'ui'); this.loadImage('icon_owned', 'ui');
this.loadImage('ability_bar', 'ui'); this.loadImage('ability_bar', 'ui');
this.loadImage('party_exp_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('shiny_star', 'ui', 'shiny.png');
this.loadImage('icon_spliced', 'ui'); this.loadImage('icon_spliced', 'ui');
@ -306,6 +311,7 @@ export default class BattleScene extends Phaser.Scene {
this.loadSe('beam'); this.loadSe('beam');
this.loadSe('upgrade'); this.loadSe('upgrade');
this.loadSe('buy'); this.loadSe('buy');
this.loadSe('achv');
this.loadSe('error'); this.loadSe('error');
this.loadSe('pb_rel'); 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.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.moneyText.setY(this.waveCountText.y + 10);
this.partyExpBar.setY(this.moneyText.y + 15); this.partyExpBar.setY(this.moneyText.y + 15);
this.ui?.achvBar.setY((this.game.canvas.height / 6 + this.moneyText.y + 15));
} }
getMaxExpLevel(ignoreLevelCap?: boolean): integer { getMaxExpLevel(ignoreLevelCap?: boolean): integer {
@ -867,18 +874,19 @@ export default class BattleScene extends Phaser.Scene {
checkInput(): boolean { checkInput(): boolean {
if (this.blockInput) if (this.blockInput)
return; return;
let inputSuccess = false;
if (this.isButtonPressed(Button.UP)) if (this.isButtonPressed(Button.UP))
this.ui.processInput(Button.UP); inputSuccess = this.ui.processInput(Button.UP);
else if (this.isButtonPressed(Button.DOWN)) else if (this.isButtonPressed(Button.DOWN))
this.ui.processInput(Button.DOWN); inputSuccess = this.ui.processInput(Button.DOWN);
else if (this.isButtonPressed(Button.LEFT)) else if (this.isButtonPressed(Button.LEFT))
this.ui.processInput(Button.LEFT); inputSuccess = this.ui.processInput(Button.LEFT);
else if (this.isButtonPressed(Button.RIGHT)) else if (this.isButtonPressed(Button.RIGHT))
this.ui.processInput(Button.RIGHT); inputSuccess = this.ui.processInput(Button.RIGHT);
else if (this.isButtonPressed(Button.ACTION)) else if (this.isButtonPressed(Button.ACTION))
this.ui.processInput(Button.ACTION); inputSuccess = this.ui.processInput(Button.ACTION);
else if (this.isButtonPressed(Button.CANCEL)) else if (this.isButtonPressed(Button.CANCEL))
this.ui.processInput(Button.CANCEL); inputSuccess = this.ui.processInput(Button.CANCEL);
else if (this.isButtonPressed(Button.MENU)) { else if (this.isButtonPressed(Button.MENU)) {
switch (this.ui.getMode()) { switch (this.ui.getMode()) {
case Mode.MESSAGE: case Mode.MESSAGE:
@ -894,8 +902,7 @@ export default class BattleScene extends Phaser.Scene {
case Mode.STARTER_SELECT: case Mode.STARTER_SELECT:
case Mode.CONFIRM: case Mode.CONFIRM:
case Mode.GAME_MODE_SELECT: case Mode.GAME_MODE_SELECT:
this.ui.setModeWithoutClear(Mode.SETTINGS); this.ui.setOverlayMode(Mode.MENU);
this.playSound('menu_open');
break; break;
case Mode.SETTINGS: case Mode.SETTINGS:
this.ui.revertMode(); this.ui.revertMode();
@ -904,16 +911,15 @@ export default class BattleScene extends Phaser.Scene {
default: default:
return; return;
} }
} } else if (this.ui?.getHandler() instanceof StarterSelectUiHandler) {
else if (this.ui?.getHandler() instanceof StarterSelectUiHandler) {
if (this.isButtonPressed(Button.CYCLE_SHINY)) 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)) 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)) 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)) else if (this.isButtonPressed(Button.CYCLE_ABILITY))
this.ui.processInput(Button.CYCLE_ABILITY); inputSuccess = this.ui.processInput(Button.CYCLE_ABILITY);
else else
return; return;
} }
@ -1413,4 +1419,28 @@ export default class BattleScene extends Phaser.Scene {
return null; 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); 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); const attr = new AttrType(...args);
this.attrs.push(attr); this.attrs.push(attr);
const attrCondition = attr.getCondition(); const attrCondition = attr.getCondition();
@ -111,7 +111,7 @@ export default class Move {
return this; return this;
} }
addAttr(attr: MoveAttr): Move { addAttr(attr: MoveAttr): this {
this.attrs.push(attr); this.attrs.push(attr);
const attrCondition = attr.getCondition(); const attrCondition = attr.getCondition();
if (attrCondition) if (attrCondition)
@ -120,7 +120,7 @@ export default class Move {
return this; return this;
} }
target(moveTarget: MoveTarget): Move { target(moveTarget: MoveTarget): this {
this.moveTarget = moveTarget; this.moveTarget = moveTarget;
return this; return this;
} }
@ -129,7 +129,7 @@ export default class Move {
return !!(this.flags & flag); return !!(this.flags & flag);
} }
condition(condition: MoveCondition): Move { condition(condition: MoveCondition): this {
this.conditions.push(condition); this.conditions.push(condition);
return this; return this;
@ -142,32 +142,32 @@ export default class Move {
this.flags ^= flag; this.flags ^= flag;
} }
makesContact(makesContact?: boolean): Move { makesContact(makesContact?: boolean): this {
this.setFlag(MoveFlags.MAKES_CONTACT, makesContact); this.setFlag(MoveFlags.MAKES_CONTACT, makesContact);
return this; return this;
} }
ignoresProtect(ignoresProtect?: boolean): Move { ignoresProtect(ignoresProtect?: boolean): this {
this.setFlag(MoveFlags.IGNORE_PROTECT, ignoresProtect); this.setFlag(MoveFlags.IGNORE_PROTECT, ignoresProtect);
return this; return this;
} }
ignoresVirtual(ignoresVirtual?: boolean): Move { ignoresVirtual(ignoresVirtual?: boolean): this {
this.setFlag(MoveFlags.IGNORE_VIRTUAL, ignoresVirtual); this.setFlag(MoveFlags.IGNORE_VIRTUAL, ignoresVirtual);
return this; return this;
} }
soundBased(soundBased?: boolean): Move { soundBased(soundBased?: boolean): this {
this.setFlag(MoveFlags.SOUND_BASED, soundBased); this.setFlag(MoveFlags.SOUND_BASED, soundBased);
return this; return this;
} }
hidesUser(hidesUser?: boolean): Move { hidesUser(hidesUser?: boolean): this {
this.setFlag(MoveFlags.HIDE_USER, hidesUser); this.setFlag(MoveFlags.HIDE_USER, hidesUser);
return this; return this;
} }
hidesTarget(hidesTarget?: boolean): Move { hidesTarget(hidesTarget?: boolean): this {
this.setFlag(MoveFlags.HIDE_TARGET, hidesTarget); this.setFlag(MoveFlags.HIDE_TARGET, hidesTarget);
return this; 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() { function getSession() {
const sessionStr = localStorage.getItem('sessionData'); const sessionStr = localStorage.getItem('sessionData');
if (!sessionStr) if (!sessionStr)

View File

@ -6,7 +6,7 @@ import { EvolutionItem, pokemonEvolutions } from '../data/pokemon-evolutions';
import { Stat, getStatName } from '../data/pokemon-stat'; import { Stat, getStatName } from '../data/pokemon-stat';
import { tmPoolTiers, tmSpecies } from '../data/tms'; import { tmPoolTiers, tmSpecies } from '../data/tms';
import { Type } from '../data/type'; 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 * as Utils from '../utils';
import { TempBattleStat, getTempBattleStatBoosterItemName, getTempBattleStatName } from '../data/temp-battle-stat'; import { TempBattleStat, getTempBattleStatBoosterItemName, getTempBattleStatName } from '../data/temp-battle-stat';
import { BerryType, getBerryEffectDescription, getBerryName } from '../data/berry'; 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 { BerryType, getBerryEffectFunc, getBerryPredicate } from '../data/berry';
import { Species } from '../data/species'; import { Species } from '../data/species';
import { StatusEffect, getStatusEffectDescriptor } from '../data/status-effect'; import { StatusEffect, getStatusEffectDescriptor } from '../data/status-effect';
import { MoneyAchv } from '../system/achv';
type ModifierType = ModifierTypes.ModifierType; type ModifierType = ModifierTypes.ModifierType;
export type ModifierPredicate = (modifier: Modifier) => boolean; export type ModifierPredicate = (modifier: Modifier) => boolean;
@ -1171,6 +1172,7 @@ export class DamageMoneyRewardModifier extends PokemonHeldItemModifier {
scene.applyModifiers(MoneyMultiplierModifier, true, moneyAmount); scene.applyModifiers(MoneyMultiplierModifier, true, moneyAmount);
scene.money += moneyAmount.value; scene.money += moneyAmount.value;
scene.updateMoneyText(); scene.updateMoneyText();
scene.validateAchvs(MoneyAchv);
return true; return true;
} }
@ -1194,6 +1196,7 @@ export class MoneyInterestModifier extends PersistentModifier {
const interestAmount = Math.floor(scene.money * 0.2 * this.getStackCount()); const interestAmount = Math.floor(scene.money * 0.2 * this.getStackCount());
scene.money += interestAmount; scene.money += interestAmount;
scene.updateMoneyText(); scene.updateMoneyText();
scene.validateAchvs(MoneyAchv);
scene.queueMessage(`You received interest of ₽${interestAmount.toLocaleString('en-US')}\nfrom the ${this.type.name}!`, null, true); 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 SoundFade from 'phaser3-rex-plugins/plugins/soundfade';
import { GameMode } from './game-mode'; import { GameMode } from './game-mode';
import { LevelMoves } from './data/pokemon-level-moves'; import { LevelMoves } from './data/pokemon-level-moves';
import { DamageAchv, achvs } from './system/achv';
export enum FieldPosition { export enum FieldPosition {
CENTER, CENTER,
@ -867,6 +868,8 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
this.scene.setPhaseQueueSplice(); this.scene.setPhaseQueueSplice();
damage.value = Math.min(damage.value, this.hp); damage.value = Math.min(damage.value, this.hp);
this.damage(damage.value); this.damage(damage.value);
if (source.isPlayer())
this.scene.validateAchvs(DamageAchv, damage);
source.turnData.damageDealt += damage.value; source.turnData.damageDealt += damage.value;
this.turnData.attacksReceived.unshift({ move: move.id, result: result as DamageResult, damage: damage.value, critical: isCritical, sourceId: source.id }); this.turnData.attacksReceived.unshift({ move: move.id, result: result as DamageResult, damage: damage.value, critical: isCritical, sourceId: source.id });
if (source.isPlayer() && !this.isPlayer()) 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]; this.summonData.battleStats[stat] = source.summonData.battleStats[stat];
for (let tag of source.summonData.tags) for (let tag of source.summonData.tags)
this.summonData.tags.push(tag); this.summonData.tags.push(tag);
if (battleStats.filter(bs => bs === 6).length)
this.scene.validateAchv(achvs.TRANSFER_MAX_BATTLE_STAT);
} }
getMoveHistory(): TurnMove[] { 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 * as Utils from "../utils";
import PokemonData from "./pokemon-data"; import PokemonData from "./pokemon-data";
import PersistentModifierData from "./modifier-data"; import PersistentModifierData from "./modifier-data";
import { PokemonHeldItemModifier } from "../modifier/modifier";
import ArenaData from "./arena-data"; import ArenaData from "./arena-data";
import { Unlockables } from "./unlockables"; import { Unlockables } from "./unlockables";
import { GameMode } from "../game-mode"; import { GameMode } from "../game-mode";
@ -15,12 +14,14 @@ import { BattleType } from "../battle";
import TrainerData from "./trainer-data"; import TrainerData from "./trainer-data";
import { trainerConfigs } from "../data/trainer-type"; import { trainerConfigs } from "../data/trainer-type";
import { Setting, setSetting, settingDefaults } from "./settings"; import { Setting, setSetting, settingDefaults } from "./settings";
import { achvs } from "./achv";
interface SystemSaveData { interface SystemSaveData {
trainerId: integer; trainerId: integer;
secretId: integer; secretId: integer;
dexData: DexData; dexData: DexData;
unlocks: Unlocks; unlocks: Unlocks;
achvUnlocks: AchvUnlocks;
timestamp: integer; timestamp: integer;
} }
@ -45,6 +46,10 @@ interface Unlocks {
[key: integer]: boolean; [key: integer]: boolean;
} }
interface AchvUnlocks {
[key: string]: integer
}
export interface DexData { export interface DexData {
[key: integer]: DexData | DexEntry [key: integer]: DexData | DexEntry
} }
@ -81,6 +86,8 @@ export class GameData {
public unlocks: Unlocks; public unlocks: Unlocks;
public achvUnlocks: AchvUnlocks;
constructor(scene: BattleScene) { constructor(scene: BattleScene) {
this.scene = scene; this.scene = scene;
this.loadSettings(); this.loadSettings();
@ -91,6 +98,7 @@ export class GameData {
[Unlockables.MINI_BLACK_HOLE]: false, [Unlockables.MINI_BLACK_HOLE]: false,
[Unlockables.SPLICED_ENDLESS_MODE]: false [Unlockables.SPLICED_ENDLESS_MODE]: false
}; };
this.achvUnlocks = {};
this.initDexData(); this.initDexData();
this.loadSystem(); this.loadSystem();
} }
@ -99,11 +107,14 @@ export class GameData {
if (this.scene.quickStart) if (this.scene.quickStart)
return false; return false;
console.log(this.achvUnlocks, "wah")
const data: SystemSaveData = { const data: SystemSaveData = {
trainerId: this.trainerId, trainerId: this.trainerId,
secretId: this.secretId, secretId: this.secretId,
dexData: this.dexData, dexData: this.dexData,
unlocks: this.unlocks, unlocks: this.unlocks,
achvUnlocks: this.achvUnlocks,
timestamp: new Date().getTime() 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) if (data.timestamp === undefined)
this.convertDexData(data.dexData); 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); this.setCursor(this.cursor);
} }
processInput(button: Button) { processInput(button: Button): boolean {
const ui = this.getUi(); const ui = this.getUi();
let success = false; let success = false;
@ -91,6 +91,8 @@ export default class BallUiHandler extends UiHandler {
if (success) if (success)
ui.playSelect(); ui.playSelect();
return success;
} }
updateCounts() { updateCounts() {

View File

@ -102,7 +102,7 @@ export default class BattleMessageUiHandler extends MessageUiHandler {
this.message.setWordWrapWidth(1780); this.message.setWordWrapWidth(1780);
} }
processInput(button: Button): void { processInput(button: Button): boolean {
const ui = this.getUi(); const ui = this.getUi();
if (this.awaitingActionInput) { if (this.awaitingActionInput) {
if (button === Button.CANCEL || button === Button.ACTION) { if (button === Button.CANCEL || button === Button.ACTION) {
@ -111,6 +111,7 @@ export default class BattleMessageUiHandler extends MessageUiHandler {
const originalOnActionInput = this.onActionInput; const originalOnActionInput = this.onActionInput;
this.onActionInput = null; this.onActionInput = null;
originalOnActionInput(); 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(); const ui = this.getUi();
let success = false; let success = false;
@ -78,6 +78,8 @@ export default class BiomeSelectUiHandler extends UiHandler {
if (success) if (success)
ui.playSelect(); ui.playSelect();
return success;
} }
setCursor(cursor: integer): boolean { setCursor(cursor: integer): boolean {

View File

@ -51,7 +51,7 @@ export default class CommandUiHandler extends UiHandler {
this.setCursor(this.getCursor()); this.setCursor(this.getCursor());
} }
processInput(button: Button) { processInput(button: Button): boolean {
const ui = this.getUi(); const ui = this.getUi();
let success = false; let success = false;
@ -104,6 +104,8 @@ export default class CommandUiHandler extends UiHandler {
if (success) if (success)
ui.playSelect(); ui.playSelect();
return success;
} }
getCursor(): integer { getCursor(): integer {

View File

@ -20,8 +20,8 @@ export default class EvolutionSceneHandler extends UiHandler {
this.scene.fieldUI.bringToTop(this.evolutionContainer); this.scene.fieldUI.bringToTop(this.evolutionContainer);
} }
processInput(button: Button) { processInput(button: Button): boolean {
this.scene.ui.getMessageHandler().processInput(button); return this.scene.ui.getMessageHandler().processInput(button);
} }
setCursor(_cursor: integer): boolean { setCursor(_cursor: integer): boolean {

View File

@ -47,7 +47,7 @@ export default class FightUiHandler extends UiHandler {
this.displayMoves(); this.displayMoves();
} }
processInput(button: Button) { processInput(button: Button): boolean {
const ui = this.getUi(); const ui = this.getUi();
let success = false; let success = false;
@ -87,6 +87,8 @@ export default class FightUiHandler extends UiHandler {
if (success) if (success)
ui.playSelect(); ui.playSelect();
return success;
} }
getCursor(): integer { 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 ui = this.getUi();
const options = this.getOptions(); const options = this.getOptions();
@ -59,5 +59,7 @@ export default class GameModeSelectUiHandler extends OptionSelectUiHandler {
ui.playSelect(); ui.playSelect();
} else } else
return super.processInput(button); 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(); const ui = this.getUi();
if (!this.awaitingActionInput) if (!this.awaitingActionInput)
return; return false;
let success = false; let success = false;
@ -193,6 +193,8 @@ export default class ModifierSelectUiHandler extends AwaitableUiHandler {
if (success) if (success)
ui.playSelect(); ui.playSelect();
return success;
} }
setCursor(cursor: integer): boolean { 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(); const ui = this.getUi();
let success = false; let success = false;
@ -94,6 +94,8 @@ export default abstract class OptionSelectUiHandler extends UiHandler {
if (success) if (success)
ui.playSelect(); ui.playSelect();
return success;
} }
setCursor(cursor: integer): boolean { setCursor(cursor: integer): boolean {

View File

@ -177,23 +177,22 @@ export default class PartyUiHandler extends MessageUiHandler {
this.setCursor(this.cursor < 6 ? this.cursor : 0); this.setCursor(this.cursor < 6 ? this.cursor : 0);
} }
processInput(button: Button) { processInput(button: Button): boolean {
const ui = this.getUi(); const ui = this.getUi();
if (this.pendingPrompt) if (this.pendingPrompt)
return; return false;
if (this.awaitingActionInput) { if (this.awaitingActionInput) {
if (button === Button.ACTION || button === Button.CANCEL) { if ((button === Button.ACTION || button === Button.CANCEL) && this.onActionInput) {
if (this.onActionInput) { ui.playSelect();
ui.playSelect(); const originalOnActionInput = this.onActionInput;
const originalOnActionInput = this.onActionInput; this.onActionInput = null;
this.onActionInput = null; originalOnActionInput();
originalOnActionInput(); this.awaitingActionInput = false;
this.awaitingActionInput = false; return true;
}
} }
return; return false;
} }
let success = false; let success = false;
@ -206,6 +205,7 @@ export default class PartyUiHandler extends MessageUiHandler {
this.startTransfer(); this.startTransfer();
this.clearOptions(); this.clearOptions();
ui.playSelect(); ui.playSelect();
return true;
} else if (this.partyUiMode === PartyUiMode.REMEMBER_MOVE_MODIFIER && option !== PartyOption.CANCEL) { } else if (this.partyUiMode === PartyUiMode.REMEMBER_MOVE_MODIFIER && option !== PartyOption.CANCEL) {
let filterResult = (this.selectFilter as PokemonSelectFilter)(pokemon); let filterResult = (this.selectFilter as PokemonSelectFilter)(pokemon);
if (filterResult === null) { 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); this.showText(filterResult as string, null, () => this.showText(null, 0), null, true);
} }
ui.playSelect(); ui.playSelect();
return true;
} else if ((option !== PartyOption.SUMMARY && option !== PartyOption.RELEASE && option !== PartyOption.CANCEL) } else if ((option !== PartyOption.SUMMARY && option !== PartyOption.RELEASE && option !== PartyOption.CANCEL)
|| (option === PartyOption.RELEASE && this.partyUiMode === PartyUiMode.RELEASE)) { || (option === PartyOption.RELEASE && this.partyUiMode === PartyUiMode.RELEASE)) {
let filterResult: string; 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); (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) if (this.partyUiMode !== PartyUiMode.MODIFIER && this.partyUiMode !== PartyUiMode.TM_MODIFIER && this.partyUiMode !== PartyUiMode.MOVE_MODIFIER)
ui.playSelect(); ui.playSelect();
return; return true;
} else { } else {
this.clearOptions(); this.clearOptions();
this.showText(filterResult as string, null, () => this.showText(null, 0), null, true); 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) { } else if (option === PartyOption.SUMMARY) {
ui.playSelect(); ui.playSelect();
ui.setModeWithoutClear(Mode.SUMMARY, pokemon).then(() => this.clearOptions()); ui.setModeWithoutClear(Mode.SUMMARY, pokemon).then(() => this.clearOptions());
return true;
} else if (option === PartyOption.RELEASE) { } else if (option === PartyOption.RELEASE) {
this.clearOptions(); this.clearOptions();
ui.playSelect(); ui.playSelect();
@ -277,11 +279,13 @@ export default class PartyUiHandler extends MessageUiHandler {
}); });
} else } else
this.showText('You can\'t release a Pokémon that\'s in battle!', null, () => this.showText(null, 0), null, true); 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) } else if (option === PartyOption.CANCEL)
this.processInput(Button.CANCEL); return this.processInput(Button.CANCEL);
} else if (button === Button.CANCEL) { } else if (button === Button.CANCEL) {
this.clearOptions(); this.clearOptions();
ui.playSelect(); ui.playSelect();
return true;
} else { } else {
switch (button) { switch (button) {
case Button.UP: case Button.UP:
@ -300,8 +304,8 @@ export default class PartyUiHandler extends MessageUiHandler {
} else if (this.partyUiMode === PartyUiMode.FAINT_SWITCH) } else if (this.partyUiMode === PartyUiMode.FAINT_SWITCH)
ui.playError(); ui.playError();
else else
this.processInput(Button.CANCEL); return this.processInput(Button.CANCEL);
return; return true;
} else if (button === Button.CANCEL) { } else if (button === Button.CANCEL) {
if ((this.partyUiMode === PartyUiMode.MODIFIER_TRANSFER || this.partyUiMode === PartyUiMode.SPLICE) && this.transferMode) { if ((this.partyUiMode === PartyUiMode.MODIFIER_TRANSFER || this.partyUiMode === PartyUiMode.SPLICE) && this.transferMode) {
this.clearTransfer(); this.clearTransfer();
@ -317,7 +321,8 @@ export default class PartyUiHandler extends MessageUiHandler {
ui.playSelect(); ui.playSelect();
} }
} }
return;
return true;
} }
const slotCount = this.partySlots.length; const slotCount = this.partySlots.length;
@ -343,6 +348,8 @@ export default class PartyUiHandler extends MessageUiHandler {
if (success) if (success)
ui.playSelect(); ui.playSelect();
return success;
} }
populatePartySlots() { populatePartySlots() {

View File

@ -91,9 +91,7 @@ export default class SettingsUiHandler extends UiHandler {
const settings: object = localStorage.hasOwnProperty('settings') ? JSON.parse(localStorage.getItem('settings')) : {}; const settings: object = localStorage.hasOwnProperty('settings') ? JSON.parse(localStorage.getItem('settings')) : {};
Object.keys(settingDefaults).forEach((setting, s) => { Object.keys(settingDefaults).forEach((setting, s) => this.setOptionCursor(s, settings.hasOwnProperty(setting) ? settings[setting] : settingDefaults[setting]));
this.setOptionCursor(s, settings.hasOwnProperty(setting) ? settings[setting] : settingDefaults[setting]);
});
this.settingsContainer.setVisible(true); this.settingsContainer.setVisible(true);
this.setCursor(0); this.setCursor(0);
@ -103,7 +101,7 @@ export default class SettingsUiHandler extends UiHandler {
this.getUi().hideTooltip(); this.getUi().hideTooltip();
} }
processInput(button: Button) { processInput(button: Button): boolean {
const ui = this.getUi(); const ui = this.getUi();
let success = false; let success = false;
@ -134,6 +132,8 @@ export default class SettingsUiHandler extends UiHandler {
if (success) if (success)
ui.playSelect(); ui.playSelect();
return success;
} }
setCursor(cursor: integer): boolean { setCursor(cursor: integer): boolean {

View File

@ -301,10 +301,11 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
this.starterSelectMessageBoxContainer.setVisible(true); this.starterSelectMessageBoxContainer.setVisible(true);
} }
processInput(button: Button): void { processInput(button: Button): boolean {
const ui = this.getUi(); const ui = this.getUi();
let success = false; let success = false;
let error = false;
if (this.genMode) { if (this.genMode) {
switch (button) { switch (button) {
@ -323,7 +324,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
} else { } else {
if (button === Button.ACTION) { if (button === Button.ACTION) {
if (!this.speciesStarterDexEntry) if (!this.speciesStarterDexEntry)
ui.playError(); error = true;
else if (this.starterCursors.length < 3) { else if (this.starterCursors.length < 3) {
let isDupe = false; let isDupe = false;
for (let s = 0; s < this.starterCursors.length; s++) { for (let s = 0; s < this.starterCursors.length; s++) {
@ -380,7 +381,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
success = true; success = true;
this.updateInstructions(); this.updateInstructions();
} else } else
ui.playError(); error = true;
} }
} else if (button === Button.CANCEL) { } else if (button === Button.CANCEL) {
if (this.starterCursors.length) { if (this.starterCursors.length) {
@ -388,7 +389,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
success = true; success = true;
this.updateInstructions(); this.updateInstructions();
} else } else
ui.playError(); error = true;
} else { } else {
const genStarters = this.starterSelectGenIconContainers[this.genCursor].getAll().length; const genStarters = this.starterSelectGenIconContainers[this.genCursor].getAll().length;
const rows = Math.ceil(genStarters / 9); const rows = Math.ceil(genStarters / 9);
@ -446,6 +447,10 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
if (success) if (success)
ui.playSelect(); ui.playSelect();
else if (error)
ui.playError();
return success || error;
} }
updateInstructions(): void { updateInstructions(): void {

View File

@ -241,13 +241,14 @@ export default class SummaryUiHandler extends UiHandler {
this.hideStatus(!fromSummary); this.hideStatus(!fromSummary);
} }
processInput(button: Button) { processInput(button: Button): boolean {
if (this.transitioning) if (this.transitioning)
return; return false;
const ui = this.getUi(); const ui = this.getUi();
let success = false; let success = false;
let error = false;
if (this.moveSelect) { if (this.moveSelect) {
if (button === Button.ACTION) { if (button === Button.ACTION) {
@ -283,9 +284,9 @@ export default class SummaryUiHandler extends UiHandler {
} }
success = true; success = true;
} else if (this.moveCursor === 4) } else if (this.moveCursor === 4)
this.processInput(Button.CANCEL); return this.processInput(Button.CANCEL);
else else
ui.playError(); error = true;
} else if (button === Button.CANCEL) { } else if (button === Button.CANCEL) {
this.hideMoveSelect(); this.hideMoveSelect();
success = true; success = true;
@ -336,6 +337,10 @@ export default class SummaryUiHandler extends UiHandler {
if (success) if (success)
ui.playSelect(); ui.playSelect();
else if (error)
ui.playError();
return success || error;
} }
setCursor(cursor: integer): boolean { 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]); this.setCursor(this.targets.indexOf(this.cursor) > -1 ? this.cursor : this.targets[0]);
} }
processInput(button: Button) { processInput(button: Button): boolean {
const ui = this.getUi(); const ui = this.getUi();
let success = false; let success = false;
@ -72,6 +72,8 @@ export default class TargetSelectUiHandler extends UiHandler {
if (success) if (success)
ui.playSelect(); ui.playSelect();
return success;
} }
setCursor(cursor: integer): boolean { setCursor(cursor: integer): boolean {

View File

@ -107,7 +107,7 @@ export function getModifierTierTextTint(tier: integer): integer {
case 1: // ModifierTier.GREAT: case 1: // ModifierTier.GREAT:
return 0x3890f8; return 0x3890f8;
case 2: // ModifierTier.ULTRA: case 2: // ModifierTier.ULTRA:
return 0xf8d038 return 0xf8d038;
case 3: // ModifierTier.MASTER: case 3: // ModifierTier.MASTER:
return 0xe020c0; return 0xe020c0;
case 4: // ModifierTier.LUXURY: 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 TargetSelectUiHandler from './target-select-ui-handler';
import GameModeSelectUiHandler from './game-mode-select-ui-handler'; import GameModeSelectUiHandler from './game-mode-select-ui-handler';
import SettingsUiHandler from './settings-ui-handler'; import SettingsUiHandler from './settings-ui-handler';
import { TextStyle, addTextObject, getTextColor } from './text'; import { TextStyle, addTextObject } from './text';
import { getPokeballTintColor } from '../data/pokeball'; import AchvBar from './achv-bar';
import MenuUiHandler from './menu-ui-handler';
import AchvsUiHandler from './achvs-ui-handler';
export enum Mode { export enum Mode {
MESSAGE, MESSAGE,
@ -32,7 +34,9 @@ export enum Mode {
EVOLUTION_SCENE, EVOLUTION_SCENE,
CONFIRM, CONFIRM,
GAME_MODE_SELECT, GAME_MODE_SELECT,
SETTINGS MENU,
SETTINGS,
ACHIEVEMENTS
}; };
const transitionModes = [ const transitionModes = [
@ -45,14 +49,21 @@ const transitionModes = [
const noTransitionModes = [ const noTransitionModes = [
Mode.CONFIRM, Mode.CONFIRM,
Mode.GAME_MODE_SELECT, Mode.GAME_MODE_SELECT,
Mode.MENU,
Mode.SETTINGS
];
const menuModes = [
Mode.MENU,
Mode.SETTINGS Mode.SETTINGS
]; ];
export default class UI extends Phaser.GameObjects.Container { export default class UI extends Phaser.GameObjects.Container {
private mode: Mode; private mode: Mode;
private lastMode: Mode; private modeChain: Mode[];
private handlers: UiHandler[]; private handlers: UiHandler[];
private overlay: Phaser.GameObjects.Rectangle; private overlay: Phaser.GameObjects.Rectangle;
public achvBar: AchvBar;
private tooltipContainer: Phaser.GameObjects.Container; private tooltipContainer: Phaser.GameObjects.Container;
private tooltipBg: Phaser.GameObjects.NineSlice; 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); super(scene, 0, scene.game.canvas.height / 6);
this.mode = Mode.MESSAGE; this.mode = Mode.MESSAGE;
this.modeChain = [];
this.handlers = [ this.handlers = [
new BattleMessageUiHandler(scene), new BattleMessageUiHandler(scene),
new CommandUiHandler(scene), new CommandUiHandler(scene),
@ -79,7 +91,9 @@ export default class UI extends Phaser.GameObjects.Container {
new EvolutionSceneHandler(scene), new EvolutionSceneHandler(scene),
new ConfirmUiHandler(scene), new ConfirmUiHandler(scene),
new GameModeSelectUiHandler(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.scene as BattleScene).uiContainer.add(this.overlay);
this.overlay.setVisible(false); this.overlay.setVisible(false);
this.setupTooltip(); this.setupTooltip();
this.achvBar = new AchvBar(this.scene as BattleScene);
this.achvBar.setup();
(this.scene as BattleScene).uiContainer.add(this.achvBar);
} }
private setupTooltip() { private setupTooltip() {
@ -121,11 +139,11 @@ export default class UI extends Phaser.GameObjects.Container {
return this.handlers[Mode.MESSAGE] as BattleMessageUiHandler; return this.handlers[Mode.MESSAGE] as BattleMessageUiHandler;
} }
processInput(button: Button): void { processInput(button: Button): boolean {
if (this.overlayActive) 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 { 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 => { return new Promise(resolve => {
if (this.mode === mode && !forceTransition) { if (this.mode === mode && !forceTransition) {
resolve(); resolve();
@ -239,7 +257,8 @@ export default class UI extends Phaser.GameObjects.Container {
if (this.mode !== mode) { if (this.mode !== mode) {
if (clear) if (clear)
this.getHandler().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.mode = mode;
this.getHandler().show(args); this.getHandler().show(args);
} }
@ -263,23 +282,26 @@ export default class UI extends Phaser.GameObjects.Container {
} }
setMode(mode: Mode, ...args: any[]): Promise<void> { 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> { 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> { 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 { revertMode(): void {
if (!this.lastMode) if (!this.modeChain.length)
return; return;
this.getHandler().clear(); this.getHandler().clear();
this.mode = this.lastMode; this.mode = this.modeChain.pop();
this.lastMode = undefined;
} }
} }

View File

@ -18,7 +18,7 @@ export default abstract class UiHandler {
this.active = true; this.active = true;
} }
abstract processInput(button: Button): void; abstract processInput(button: Button): boolean;
getUi() { getUi() {
return this.scene.ui; return this.scene.ui;

View File

@ -134,11 +134,9 @@ export class NumberHolder {
} }
} }
export class IntegerHolder { export class IntegerHolder extends NumberHolder {
public value: integer;
constructor(value: integer) { constructor(value: integer) {
this.value = value; super(value);
} }
} }