diff --git a/package-lock.json b/package-lock.json index 684dd4c..15fda54 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,6 +8,7 @@ "name": "bastion", "version": "0.0.0", "dependencies": { + "pixi-spine": "^4.0.4", "pixi-viewport": "^6.0.3", "pixi.js": "^8.4.0" }, @@ -407,12 +408,268 @@ "node": ">=12" } }, + "node_modules/@pixi-spine/base": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/@pixi-spine/base/-/base-4.0.3.tgz", + "integrity": "sha512-0bunaWebaDswLFtYZ6whV+ZvgLQ7oANcvbPmIOoVpS/1pOY3Y/GAnWOFbgp3qt9Q/ntLYqNjGve6xq0IqpsTAA==", + "peerDependencies": { + "@pixi/core": "^7.0.0", + "@pixi/display": "^7.0.0", + "@pixi/graphics": "^7.0.0", + "@pixi/mesh": "^7.0.0", + "@pixi/mesh-extras": "^7.0.0", + "@pixi/sprite": "^7.0.0" + } + }, + "node_modules/@pixi-spine/loader-base": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@pixi-spine/loader-base/-/loader-base-4.0.4.tgz", + "integrity": "sha512-Grgu+PxiUpgYWpuMRr3h5jrN3ZTnwyXfu3HuYdFb6mbJTTMub4xBPALeui+O+tw0k9RNRAr99pUzu9Rc9XTbAw==", + "peerDependencies": { + "@pixi-spine/base": "^4.0.0", + "@pixi/assets": " ^7.0.0", + "@pixi/core": "^7.0.0" + } + }, + "node_modules/@pixi-spine/loader-uni": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/@pixi-spine/loader-uni/-/loader-uni-4.0.3.tgz", + "integrity": "sha512-tfhTJrnuog8ObKbbiSG1wV/nIUc3O98WfwS6lCmewaupoMIKF0ujg21MCqXUXJvljQJzU9tbURI+DWu4w9dnnA==", + "peerDependencies": { + "@pixi-spine/base": "^4.0.0", + "@pixi-spine/loader-base": "^4.0.0", + "@pixi-spine/runtime-3.7": "^4.0.0", + "@pixi-spine/runtime-3.8": "^4.0.0", + "@pixi-spine/runtime-4.1": "^4.0.0", + "@pixi/assets": " ^7.0.0", + "@pixi/core": "^7.0.0", + "@pixi/display": "^7.0.0", + "@pixi/graphics": "^7.0.0", + "@pixi/mesh": "^7.0.0", + "@pixi/mesh-extras": "^7.0.0", + "@pixi/sprite": "^7.0.0" + } + }, + "node_modules/@pixi-spine/runtime-3.7": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/@pixi-spine/runtime-3.7/-/runtime-3.7-4.0.3.tgz", + "integrity": "sha512-zuopKtSqjRc37wjW5xJ64j9DbiBB7rkPMFeldeWBPCbfZiCcFcwSZwZnrcgC+f4HIGo0NeviAvJGM8Hcf3AyeA==", + "license": "SEE SPINE-LICENSE", + "peerDependencies": { + "@pixi-spine/base": "^4.0.0", + "@pixi/core": "^7.0.0" + } + }, + "node_modules/@pixi-spine/runtime-3.8": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/@pixi-spine/runtime-3.8/-/runtime-3.8-4.0.3.tgz", + "integrity": "sha512-lIhb4jOTon+FVYLO9AIgcB6jf9hC+RLEn8PesaDRibDocQ1htVCkEIhCIU3Mc00fuqIby7lMBsINeS/Th0q3bw==", + "license": "SEE SPINE-LICENSE", + "peerDependencies": { + "@pixi-spine/base": "^4.0.0", + "@pixi/core": "^7.0.0" + } + }, + "node_modules/@pixi-spine/runtime-4.0": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/@pixi-spine/runtime-4.0/-/runtime-4.0-4.0.3.tgz", + "integrity": "sha512-2Y8qhxRkg/yH/9VylGsRVAd5W+dXVPhHTjFk0RR9wEUzTCkdZ17pE+56s2nESi2X3sYNKkz8FowfaqIvXnVGxw==", + "license": "SEE SPINE-LICENSE", + "peerDependencies": { + "@pixi-spine/base": "^4.0.0", + "@pixi/core": "^7.0.0" + } + }, + "node_modules/@pixi-spine/runtime-4.1": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/@pixi-spine/runtime-4.1/-/runtime-4.1-4.0.3.tgz", + "integrity": "sha512-jK433snCQMC4FUPiDgyIcxhiatvRNSxqgs0CgHjjQ0l8GlY6gPpkkdThQ6GsFNme1SUZ4uvnWwawXFIGjW1IpQ==", + "license": "SEE SPINE-LICENSE", + "peerDependencies": { + "@pixi-spine/base": "^4.0.0", + "@pixi/core": "^7.0.0" + } + }, + "node_modules/@pixi/assets": { + "version": "7.4.2", + "resolved": "https://registry.npmjs.org/@pixi/assets/-/assets-7.4.2.tgz", + "integrity": "sha512-anxho59H9egZwoaEdM5aLvYyxoz6NCy3CaQIvNHD1bbGg8L16Ih0e26QSBR5fu53jl8OjT6M7s+p6n7uu4+fGA==", + "license": "MIT", + "peer": true, + "dependencies": { + "@types/css-font-loading-module": "^0.0.12" + }, + "peerDependencies": { + "@pixi/core": "7.4.2" + } + }, + "node_modules/@pixi/color": { + "version": "7.4.2", + "resolved": "https://registry.npmjs.org/@pixi/color/-/color-7.4.2.tgz", + "integrity": "sha512-av1LOvhHsiaW8+T4n/FgnOKHby55/w7VcA1HzPIHRBtEcsmxvSCDanT1HU2LslNhrxLPzyVx18nlmalOyt5OBg==", + "license": "MIT", + "peer": true, + "dependencies": { + "@pixi/colord": "^2.9.6" + } + }, "node_modules/@pixi/colord": { "version": "2.9.6", "resolved": "https://registry.npmjs.org/@pixi/colord/-/colord-2.9.6.tgz", "integrity": "sha512-nezytU2pw587fQstUu1AsJZDVEynjskwOL+kibwcdxsMBFqPsFFNA7xl0ii/gXuDi6M0xj3mfRJj8pBSc2jCfA==", "license": "MIT" }, + "node_modules/@pixi/constants": { + "version": "7.4.2", + "resolved": "https://registry.npmjs.org/@pixi/constants/-/constants-7.4.2.tgz", + "integrity": "sha512-N9vn6Wpz5WIQg7ugUg2+SdqD2u2+NM0QthE8YzLJ4tLH2Iz+/TrnPKUJzeyIqbg3sxJG5ZpGGPiacqIBpy1KyA==", + "license": "MIT", + "peer": true + }, + "node_modules/@pixi/core": { + "version": "7.4.2", + "resolved": "https://registry.npmjs.org/@pixi/core/-/core-7.4.2.tgz", + "integrity": "sha512-UbMtgSEnyCOFPzbE6ThB9qopXxbZ5GCof2ArB4FXOC5Xi/83MOIIYg5kf5M8689C5HJMhg2SrJu3xLKppF+CMg==", + "license": "MIT", + "peer": true, + "dependencies": { + "@pixi/color": "7.4.2", + "@pixi/constants": "7.4.2", + "@pixi/extensions": "7.4.2", + "@pixi/math": "7.4.2", + "@pixi/runner": "7.4.2", + "@pixi/settings": "7.4.2", + "@pixi/ticker": "7.4.2", + "@pixi/utils": "7.4.2" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/pixijs" + } + }, + "node_modules/@pixi/display": { + "version": "7.4.2", + "resolved": "https://registry.npmjs.org/@pixi/display/-/display-7.4.2.tgz", + "integrity": "sha512-DaD0J7gIlNlzO0Fdlby/0OH+tB5LtCY6rgFeCBKVDnzmn8wKW3zYZRenWBSFJ0Psx6vLqXYkSIM/rcokaKviIw==", + "license": "MIT", + "peer": true, + "peerDependencies": { + "@pixi/core": "7.4.2" + } + }, + "node_modules/@pixi/extensions": { + "version": "7.4.2", + "resolved": "https://registry.npmjs.org/@pixi/extensions/-/extensions-7.4.2.tgz", + "integrity": "sha512-Hmx2+O0yZ8XIvgomHM9GZEGcy9S9Dd8flmtOK5Aa3fXs/8v7xD08+ANQpN9ZqWU2Xs+C6UBlpqlt2BWALvKKKA==", + "license": "MIT", + "peer": true + }, + "node_modules/@pixi/graphics": { + "version": "7.4.2", + "resolved": "https://registry.npmjs.org/@pixi/graphics/-/graphics-7.4.2.tgz", + "integrity": "sha512-jH4/Tum2RqWzHGzvlwEr7HIVduoLO57Ze705N2zQPkUD57TInn5911aGUeoua7f/wK8cTLGzgB9BzSo2kTdcHw==", + "license": "MIT", + "peer": true, + "peerDependencies": { + "@pixi/core": "7.4.2", + "@pixi/display": "7.4.2", + "@pixi/sprite": "7.4.2" + } + }, + "node_modules/@pixi/math": { + "version": "7.4.2", + "resolved": "https://registry.npmjs.org/@pixi/math/-/math-7.4.2.tgz", + "integrity": "sha512-7jHmCQoYk6e0rfSKjdNFOPl0wCcdgoraxgteXJTTHv3r0bMNx2pHD9FJ0VvocEUG7XHfj55O3+u7yItOAx0JaQ==", + "license": "MIT", + "peer": true + }, + "node_modules/@pixi/mesh": { + "version": "7.4.2", + "resolved": "https://registry.npmjs.org/@pixi/mesh/-/mesh-7.4.2.tgz", + "integrity": "sha512-mEkKyQvvMrYXC3pahvH5WBIKtrtB63WixRr91ANFI7zXD+ESG6Ap6XtxMCJmXDQPwBDNk7SWVMiCflYuchG7kA==", + "license": "MIT", + "peer": true, + "peerDependencies": { + "@pixi/core": "7.4.2", + "@pixi/display": "7.4.2" + } + }, + "node_modules/@pixi/mesh-extras": { + "version": "7.4.2", + "resolved": "https://registry.npmjs.org/@pixi/mesh-extras/-/mesh-extras-7.4.2.tgz", + "integrity": "sha512-vNR/7wjxjs7sv9fGoKkHyU91ZAD+7EnMHBS5F3CVISlOIFxLi96NNZCB81oUIdky/90pHw40johd/4izR5zTyw==", + "license": "MIT", + "peer": true, + "peerDependencies": { + "@pixi/core": "7.4.2", + "@pixi/mesh": "7.4.2" + } + }, + "node_modules/@pixi/runner": { + "version": "7.4.2", + "resolved": "https://registry.npmjs.org/@pixi/runner/-/runner-7.4.2.tgz", + "integrity": "sha512-LPBpwym4vdyyDY5ucF4INQccaGyxztERyLTY1YN6aqJyyMmnc7iqXlIKt+a0euMBtNoLoxy6MWMvIuZj0JfFPA==", + "license": "MIT", + "peer": true + }, + "node_modules/@pixi/settings": { + "version": "7.4.2", + "resolved": "https://registry.npmjs.org/@pixi/settings/-/settings-7.4.2.tgz", + "integrity": "sha512-pMN+L6aWgvUbwhFIL/BTHKe2ShYGPZ8h9wlVBnFHMtUcJcFLMF1B3lzuvCayZRepOphs6RY0TqvnDvVb585JhQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "@pixi/constants": "7.4.2", + "@types/css-font-loading-module": "^0.0.12", + "ismobilejs": "^1.1.0" + } + }, + "node_modules/@pixi/sprite": { + "version": "7.4.2", + "resolved": "https://registry.npmjs.org/@pixi/sprite/-/sprite-7.4.2.tgz", + "integrity": "sha512-Ccf/OVQsB+HQV0Fyf5lwD+jk1jeU7uSIqEjbxenNNssmEdB7S5qlkTBV2EJTHT83+T6Z9OMOHsreJZerydpjeg==", + "license": "MIT", + "peer": true, + "peerDependencies": { + "@pixi/core": "7.4.2", + "@pixi/display": "7.4.2" + } + }, + "node_modules/@pixi/ticker": { + "version": "7.4.2", + "resolved": "https://registry.npmjs.org/@pixi/ticker/-/ticker-7.4.2.tgz", + "integrity": "sha512-cAvxCh/KI6IW4m3tp2b+GQIf+DoSj9NNmPJmsOeEJ7LzvruG8Ps7SKI6CdjQob5WbceL1apBTDbqZ/f77hFDiQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "@pixi/extensions": "7.4.2", + "@pixi/settings": "7.4.2", + "@pixi/utils": "7.4.2" + } + }, + "node_modules/@pixi/utils": { + "version": "7.4.2", + "resolved": "https://registry.npmjs.org/@pixi/utils/-/utils-7.4.2.tgz", + "integrity": "sha512-aU/itcyMC4TxFbmdngmak6ey4kC5c16Y5ntIYob9QnjNAfD/7GTsYIBnP6FqEAyO1eq0MjkAALxdONuay1BG3g==", + "license": "MIT", + "peer": true, + "dependencies": { + "@pixi/color": "7.4.2", + "@pixi/constants": "7.4.2", + "@pixi/settings": "7.4.2", + "@types/earcut": "^2.1.0", + "earcut": "^2.2.4", + "eventemitter3": "^4.0.0", + "url": "^0.11.0" + } + }, + "node_modules/@pixi/utils/node_modules/eventemitter3": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", + "license": "MIT", + "peer": true + }, "node_modules/@rollup/rollup-android-arm-eabi": { "version": "4.21.3", "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.21.3.tgz", @@ -671,12 +928,91 @@ "node": ">=10.0.0" } }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.1.tgz", + "integrity": "sha512-BhYE+WDaywFg2TBWYNXAE+8B1ATnThNBqXHP5nQu0jWJdVvY2hvkpyB3qOmtmDePiS5/BDQ8wASEWGMWRG148g==", + "license": "MIT", + "peer": true, + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.3.tgz", + "integrity": "sha512-YTd+6wGlNlPxSuri7Y6X8tY2dmm12UMH66RpKMhiX6rsk5wXXnYgbUcOt8kiS31/AjfoTOvCsE+w8nZQLQnzHA==", + "license": "MIT", + "peer": true, + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "license": "MIT", + "peer": true, + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/earcut": { "version": "2.2.4", "resolved": "https://registry.npmjs.org/earcut/-/earcut-2.2.4.tgz", "integrity": "sha512-/pjZsA1b4RPHbeWZQn66SWS8nZZWLQQ23oE3Eam7aroEFGEvwKAsJfZ9ytiEMycfzXWpca4FA9QIOehf7PocBQ==", "license": "ISC" }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "license": "MIT", + "peer": true, + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/esbuild": { "version": "0.21.5", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", @@ -737,12 +1073,110 @@ "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", + "peer": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-intrinsic": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.7.tgz", + "integrity": "sha512-VW6Pxhsrk0KAOqs3WEd0klDiF/+V7gQOpAvY1jVU/LHmaD/kQO4523aiJuikX/QAKYiW6x8Jh+RJej1almdtCA==", + "license": "MIT", + "peer": true, + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "function-bind": "^1.1.2", + "get-proto": "^1.0.0", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "license": "MIT", + "peer": true, + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/ismobilejs": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ismobilejs/-/ismobilejs-1.1.1.tgz", "integrity": "sha512-VaFW53yt8QO61k2WJui0dHf4SlL8lxBofUuUmwBo0ljPk0Drz2TiuDW4jo3wDcv41qy/SxrJ+VAzJ/qYqsmzRw==", "license": "MIT" }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/nanoid": { "version": "3.3.7", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", @@ -762,6 +1196,19 @@ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, + "node_modules/object-inspect": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/parse-svg-path": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/parse-svg-path/-/parse-svg-path-0.1.2.tgz", @@ -775,6 +1222,30 @@ "dev": true, "license": "ISC" }, + "node_modules/pixi-spine": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/pixi-spine/-/pixi-spine-4.0.4.tgz", + "integrity": "sha512-XRq1yARVoi4av7RXnd9+P37SWI9+e4/f5yTScZPJGB+sY5VcRYN6BYkBQ+y8nUKI1aJIjlms9z+pGxqikm+eFQ==", + "license": "SEE SPINE-LICENSE", + "dependencies": { + "@pixi-spine/base": "^4.0.3", + "@pixi-spine/loader-base": "^4.0.4", + "@pixi-spine/loader-uni": "^4.0.3", + "@pixi-spine/runtime-3.7": "^4.0.3", + "@pixi-spine/runtime-3.8": "^4.0.3", + "@pixi-spine/runtime-4.0": "^4.0.3", + "@pixi-spine/runtime-4.1": "^4.0.3" + }, + "peerDependencies": { + "@pixi/assets": "^7.0.0", + "@pixi/core": "^7.0.0", + "@pixi/display": "^7.0.0", + "@pixi/graphics": "^7.0.0", + "@pixi/mesh": "^7.0.0", + "@pixi/mesh-extras": "^7.0.0", + "@pixi/sprite": "^7.0.0" + } + }, "node_modules/pixi-viewport": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/pixi-viewport/-/pixi-viewport-6.0.3.tgz", @@ -830,6 +1301,29 @@ "node": "^10 || ^12 || >=14" } }, + "node_modules/punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==", + "license": "MIT", + "peer": true + }, + "node_modules/qs": { + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz", + "integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==", + "license": "BSD-3-Clause", + "peer": true, + "dependencies": { + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/rollup": { "version": "4.21.3", "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.21.3.tgz", @@ -866,6 +1360,82 @@ "fsevents": "~2.3.2" } }, + "node_modules/side-channel": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", + "license": "MIT", + "peer": true, + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", + "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "license": "MIT", + "peer": true, + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "license": "MIT", + "peer": true, + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "license": "MIT", + "peer": true, + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/source-map-js": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", @@ -890,6 +1460,20 @@ "node": ">=14.17" } }, + "node_modules/url": { + "version": "0.11.4", + "resolved": "https://registry.npmjs.org/url/-/url-0.11.4.tgz", + "integrity": "sha512-oCwdVC7mTuWiPyjLUz/COz5TLk6wgp0RCsN+wHZ2Ekneac9w8uuV0njcbbie2ME+Vs+d6duwmYuR3HgQXs1fOg==", + "license": "MIT", + "peer": true, + "dependencies": { + "punycode": "^1.4.1", + "qs": "^6.12.3" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/vite": { "version": "5.4.5", "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.5.tgz", diff --git a/package.json b/package.json index 7ea34d0..9862bc7 100644 --- a/package.json +++ b/package.json @@ -13,6 +13,7 @@ "vite": "^5.4.1" }, "dependencies": { + "pixi-spine": "^4.0.4", "pixi-viewport": "^6.0.3", "pixi.js": "^8.4.0" } diff --git a/public/assets/gems/Fire/3.png b/public/assets/gems/Fire/3.png new file mode 100644 index 0000000..4736ff3 Binary files /dev/null and b/public/assets/gems/Fire/3.png differ diff --git a/public/assets/gems/Fire/4.png b/public/assets/gems/Fire/4.png new file mode 100644 index 0000000..25a9f06 Binary files /dev/null and b/public/assets/gems/Fire/4.png differ diff --git a/public/assets/gems/Fire/5.png b/public/assets/gems/Fire/5.png new file mode 100644 index 0000000..f40d840 Binary files /dev/null and b/public/assets/gems/Fire/5.png differ diff --git a/public/assets/gems/Fire/6.png b/public/assets/gems/Fire/6.png new file mode 100644 index 0000000..ad0e01b Binary files /dev/null and b/public/assets/gems/Fire/6.png differ diff --git a/public/assets/gems/Fire/7.png b/public/assets/gems/Fire/7.png new file mode 100644 index 0000000..3879e55 Binary files /dev/null and b/public/assets/gems/Fire/7.png differ diff --git a/public/assets/gems/Fire/8.png b/public/assets/gems/Fire/8.png new file mode 100644 index 0000000..5c2f95c Binary files /dev/null and b/public/assets/gems/Fire/8.png differ diff --git a/public/assets/gems/Fire/9.png b/public/assets/gems/Fire/9.png new file mode 100644 index 0000000..e8f5448 Binary files /dev/null and b/public/assets/gems/Fire/9.png differ diff --git a/public/assets/gui/frame_yellow.png b/public/assets/gui/frame_yellow.png new file mode 100644 index 0000000..48de567 Binary files /dev/null and b/public/assets/gui/frame_yellow.png differ diff --git a/public/assets/json/Gems.json b/public/assets/json/Gems.json index 4a96e43..1407ee7 100644 --- a/public/assets/json/Gems.json +++ b/public/assets/json/Gems.json @@ -8,7 +8,7 @@ "textures": [], "cantCombineWith": [], "specialCombine": [], - "initialGemValue": 10, + "initialGemValue": 100, "genericImprovements": [ { "damageUp": 2, @@ -16,7 +16,7 @@ "rangeUp": 0, "timeToLiveUp": 0, "pierceUp": 1, - "gemValueUp": 0 + "gemValueUp": 50 }, { "damageUp": 2, @@ -24,14 +24,14 @@ "rangeUp": 0, "timeToLiveUp": 0, "pierceUp": 1, - "gemValueUp": 10 + "gemValueUp": 100 } ], "gemResistanceModifications": [ { "physical": 0, "divine": 0, - "fire": 0.25, + "fire": 0.1, "ice": 0, "frostfire": 0 }, @@ -77,14 +77,14 @@ "physical": 0, "divine": 0, "fire": 0, - "ice": 0, + "ice": 0.1, "frostfire": 0 }, { "physical": 0, "divine": 0, "fire": 0, - "ice": 0, + "ice": 0.2, "frostfire": 0 } ] @@ -127,21 +127,21 @@ ], "gemResistanceModifications": [ { - "physical": 0, + "physical": 0.1, "divine": 0, "fire": 0, "ice": 0, "frostfire": 0 }, { - "physical": 0, + "physical": 0.1, "divine": 0, "fire": 0, "ice": 0, "frostfire": 0 }, { - "physical": 0, + "physical": 0.25, "divine": 0, "fire": 0, "ice": 0, @@ -179,18 +179,18 @@ ], "gemResistanceModifications": [ { - "physical": 0, - "divine": 0, - "fire": 0, - "ice": 0, - "frostfire": 0 + "physical": 0.05, + "divine": 0.05, + "fire": 0.05, + "ice": 0.05, + "frostfire": 0.05 }, { - "physical": 0, - "divine": 0, - "fire": 0, - "ice": 0, - "frostfire": 0 + "physical": 0.05, + "divine": 0.05, + "fire": 0.05, + "ice": 0.05, + "frostfire": 0.05 } ] } diff --git a/public/assets/json/Towers.json b/public/assets/json/Towers.json index 02ad5a8..9b34a7c 100644 --- a/public/assets/json/Towers.json +++ b/public/assets/json/Towers.json @@ -4,17 +4,18 @@ "behaviour": "BasicTowerBehaviour", "sprite": "basic_tower", "texture": null, + "projectile": "white", "projectileTextures": [], "projectileTexturesArrayLength": 5, "description": "The building block of society, nothing more basic exists.", "stats": { "damage": 2, - "cooldown": 2000, - "gemSlotsAmount": 2, - "cost": 100, - "range": 4, + "cooldown": 1500, + "gemSlotsAmount": 1, + "cost": 50, + "range": 3, "timeToLive": 20, - "pierce": 1 + "pierce": 2 } }, { @@ -22,6 +23,121 @@ "behaviour": "CircleTowerBehaviour", "sprite": "circle_tower", "texture": null, + "projectile": "blue", + "projectileTextures": [], + "projectileTexturesArrayLength": 4, + "description": "If you feel a little circular.", + "stats": { + "damage": 3, + "cooldown": 4000, + "gemSlotsAmount": 2, + "cost": 100, + "range": 2.5, + "timeToLive": 12, + "pierce": 30 + } + }, + { + "name": "Electric Tower", + "behaviour": "ElectricTowerBehaviour", + "sprite": "electric_tower", + "texture": null, + "projectile": "yellow", + "projectileTextures": [], + "projectileTexturesArrayLength": 4, + "description": "Zap zap zap!", + "stats": { + "damage": 3, + "cooldown": 3500, + "gemSlotsAmount": 2, + "cost": 150, + "range": 3, + "timeToLive": 12, + "pierce": 10 + } + }, + { + "name": "Buff Tower", + "behaviour": "BuffTowerBehaviour", + "sprite": "buff_tower", + "texture": null, + "projectile": "blue", + "projectileTextures": [], + "projectileTexturesArrayLength": 4, + "description": "", + "stats": { + "damage": 4, + "cooldown": 1000, + "gemSlotsAmount": 3, + "cost": 200, + "range": 2, + "timeToLive": 15, + "pierce": 5 + } + }, + { + "name": "Strong Tower", + "behaviour": "StrongTowerBehaviour", + "sprite": "strong_tower", + "texture": null, + "projectile": "white", + "projectileTextures": [], + "projectileTexturesArrayLength": 5, + "description": "", + "stats": { + "damage": 2, + "cooldown": 2000, + "gemSlotsAmount": 3, + "cost": 125, + "range": 2.5, + "timeToLive": 12, + "pierce": 30 + } + }, + { + "name": "Rail Tower", + "behaviour": "RailTowerBehaviour", + "sprite": "rail_tower", + "texture": null, + "projectile": "red", + "projectileTextures": [], + "projectileTexturesArrayLength": 4, + "description": "If you feel a little circular.", + "stats": { + "damage": 2, + "cooldown": 2000, + "gemSlotsAmount": 3, + "cost": 125, + "range": 2.5, + "timeToLive": 12, + "pierce": 30 + } + }, + { + "name": "Trapper Tower", + "behaviour": "TrapperTowerBehaviour", + "sprite": "trapper_tower", + "texture": null, + "projectile": "stone", + "projectileTextures": [], + "projectileTexturesArrayLength": 2, + "description": "If you feel a little circular.", + "stats": { + "damage": 2, + "cooldown": 2000, + "gemSlotsAmount": 3, + "cost": 125, + "range": 2.5, + "timeToLive": 12, + "pierce": 30 + } + }, + { + "name": "Debuff Tower", + "behaviour": "DebuffTowerBehaviour", + "sprite": "debuff_tower", + "texture": null, + "projectile": "red", "projectileTextures": [], "projectileTexturesArrayLength": 4, "description": "If you feel a little circular.", diff --git a/public/assets/missions/02_the_turn.json b/public/assets/missions/02_the_turn.json index 1cb273f..e404c94 100644 --- a/public/assets/missions/02_the_turn.json +++ b/public/assets/missions/02_the_turn.json @@ -98,8 +98,8 @@ "waves": [ { "firstCreepSpawnTick": 500, - "spawnIntervalTicks": 1000, - "creeps": [0, 0, 0, 0, 0] + "spawnIntervalTicks": 500, + "creeps": [0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 2] } ], "offeredGems": [0, 0, 0, 0] @@ -109,10 +109,35 @@ { "firstCreepSpawnTick": 500, "spawnIntervalTicks": 1000, - "creeps": [1, 1, 1, 1, 1] + "creeps": [0, 0, 1, 1, 1, 4, 5, 5, 5, 1, 1, 0, 0] } ], - "offeredGems": [0, 1, 2, 3] + "offeredGems": [1, 1, 1, 0] + }, + { + "waves": [ + { + "firstCreepSpawnTick": 500, + "spawnIntervalTicks": 1000, + "creeps": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] + }, + { + "firstCreepSpawnTick": 500, + "spawnIntervalTicks": 500, + "creeps": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] + } + ], + "offeredGems": [0, 2, 2, 3] + }, + { + "waves": [ + { + "firstCreepSpawnTick": 500, + "spawnIntervalTicks": 100, + "creeps": [1, 1, 1, 1, 1, 1, 1, 1, 1] + } + ], + "offeredGems": [0, 2, 2, 3] }, { "waves": [ @@ -122,7 +147,7 @@ "creeps": [2, 2, 2, 2, 2] } ], - "offeredGems": [0, 1, 2, 3] + "offeredGems": [0, 1, 3, 3] } ] } diff --git a/public/assets/projectiles/blue/0.png b/public/assets/projectiles/blue/0.png new file mode 100644 index 0000000..5a6892c Binary files /dev/null and b/public/assets/projectiles/blue/0.png differ diff --git a/public/assets/projectiles/blue/1.png b/public/assets/projectiles/blue/1.png new file mode 100644 index 0000000..32ac758 Binary files /dev/null and b/public/assets/projectiles/blue/1.png differ diff --git a/public/assets/projectiles/blue/2.png b/public/assets/projectiles/blue/2.png new file mode 100644 index 0000000..8f646e3 Binary files /dev/null and b/public/assets/projectiles/blue/2.png differ diff --git a/public/assets/projectiles/blue/3.png b/public/assets/projectiles/blue/3.png new file mode 100644 index 0000000..5a6892c Binary files /dev/null and b/public/assets/projectiles/blue/3.png differ diff --git a/public/assets/projectiles/lightning/0.png b/public/assets/projectiles/lightning/0.png new file mode 100644 index 0000000..5dcca96 Binary files /dev/null and b/public/assets/projectiles/lightning/0.png differ diff --git a/public/assets/projectiles/lightning/1.png b/public/assets/projectiles/lightning/1.png new file mode 100644 index 0000000..f9e06a2 Binary files /dev/null and b/public/assets/projectiles/lightning/1.png differ diff --git a/public/assets/projectiles/lightning/2.png b/public/assets/projectiles/lightning/2.png new file mode 100644 index 0000000..b43f8de Binary files /dev/null and b/public/assets/projectiles/lightning/2.png differ diff --git a/public/assets/projectiles/lightning/3.png b/public/assets/projectiles/lightning/3.png new file mode 100644 index 0000000..4a1e18a Binary files /dev/null and b/public/assets/projectiles/lightning/3.png differ diff --git a/public/assets/projectiles/red/0.png b/public/assets/projectiles/red/0.png new file mode 100644 index 0000000..a707566 Binary files /dev/null and b/public/assets/projectiles/red/0.png differ diff --git a/public/assets/projectiles/red/1.png b/public/assets/projectiles/red/1.png new file mode 100644 index 0000000..6fa70ad Binary files /dev/null and b/public/assets/projectiles/red/1.png differ diff --git a/public/assets/projectiles/red/2.png b/public/assets/projectiles/red/2.png new file mode 100644 index 0000000..488b1f0 Binary files /dev/null and b/public/assets/projectiles/red/2.png differ diff --git a/public/assets/projectiles/red/3.png b/public/assets/projectiles/red/3.png new file mode 100644 index 0000000..a707566 Binary files /dev/null and b/public/assets/projectiles/red/3.png differ diff --git a/public/assets/projectiles/stone/0.png b/public/assets/projectiles/stone/0.png new file mode 100644 index 0000000..774f930 Binary files /dev/null and b/public/assets/projectiles/stone/0.png differ diff --git a/public/assets/projectiles/stone/1.png b/public/assets/projectiles/stone/1.png new file mode 100644 index 0000000..553f463 Binary files /dev/null and b/public/assets/projectiles/stone/1.png differ diff --git a/public/assets/projectiles/basic_tower/0.png b/public/assets/projectiles/white/0.png similarity index 100% rename from public/assets/projectiles/basic_tower/0.png rename to public/assets/projectiles/white/0.png diff --git a/public/assets/projectiles/basic_tower/1.png b/public/assets/projectiles/white/1.png similarity index 100% rename from public/assets/projectiles/basic_tower/1.png rename to public/assets/projectiles/white/1.png diff --git a/public/assets/projectiles/basic_tower/2.png b/public/assets/projectiles/white/2.png similarity index 100% rename from public/assets/projectiles/basic_tower/2.png rename to public/assets/projectiles/white/2.png diff --git a/public/assets/projectiles/basic_tower/3.png b/public/assets/projectiles/white/3.png similarity index 100% rename from public/assets/projectiles/basic_tower/3.png rename to public/assets/projectiles/white/3.png diff --git a/public/assets/projectiles/basic_tower/4.png b/public/assets/projectiles/white/4.png similarity index 100% rename from public/assets/projectiles/basic_tower/4.png rename to public/assets/projectiles/white/4.png diff --git a/public/assets/projectiles/circle_tower/0.png b/public/assets/projectiles/yellow/0.png similarity index 100% rename from public/assets/projectiles/circle_tower/0.png rename to public/assets/projectiles/yellow/0.png diff --git a/public/assets/projectiles/circle_tower/1.png b/public/assets/projectiles/yellow/1.png similarity index 100% rename from public/assets/projectiles/circle_tower/1.png rename to public/assets/projectiles/yellow/1.png diff --git a/public/assets/projectiles/circle_tower/2.png b/public/assets/projectiles/yellow/2.png similarity index 100% rename from public/assets/projectiles/circle_tower/2.png rename to public/assets/projectiles/yellow/2.png diff --git a/public/assets/projectiles/circle_tower/3.png b/public/assets/projectiles/yellow/3.png similarity index 100% rename from public/assets/projectiles/circle_tower/3.png rename to public/assets/projectiles/yellow/3.png diff --git a/public/assets/towers/buff_tower.png b/public/assets/towers/buff_tower.png new file mode 100644 index 0000000..1f9e89f Binary files /dev/null and b/public/assets/towers/buff_tower.png differ diff --git a/public/assets/towers/circle_tower.png b/public/assets/towers/circle_tower.png index 4ec30e0..1265739 100644 Binary files a/public/assets/towers/circle_tower.png and b/public/assets/towers/circle_tower.png differ diff --git a/public/assets/towers/debuff_tower.png b/public/assets/towers/debuff_tower.png new file mode 100644 index 0000000..50f838b Binary files /dev/null and b/public/assets/towers/debuff_tower.png differ diff --git a/public/assets/towers/electric_tower.png b/public/assets/towers/electric_tower.png new file mode 100644 index 0000000..072dec4 Binary files /dev/null and b/public/assets/towers/electric_tower.png differ diff --git a/public/assets/towers/rail_tower.png b/public/assets/towers/rail_tower.png new file mode 100644 index 0000000..535d2a0 Binary files /dev/null and b/public/assets/towers/rail_tower.png differ diff --git a/public/assets/towers/strong_tower.png b/public/assets/towers/strong_tower.png new file mode 100644 index 0000000..ffefec4 Binary files /dev/null and b/public/assets/towers/strong_tower.png differ diff --git a/public/assets/towers/trapper_tower.png b/public/assets/towers/trapper_tower.png new file mode 100644 index 0000000..4ca9dd9 Binary files /dev/null and b/public/assets/towers/trapper_tower.png differ diff --git a/src/classes/Assets.ts b/src/classes/Assets.ts index 0212684..3eede0d 100644 --- a/src/classes/Assets.ts +++ b/src/classes/Assets.ts @@ -17,6 +17,7 @@ export default class GameAssets { public static RedBackground: PIXI.Texture; public static GreenBackground: PIXI.Texture; public static BlueBackground: PIXI.Texture; + public static YellowBackground: PIXI.Texture; public static Button01Texture: PIXI.Texture; public static Button02Texture: PIXI.Texture; public static ButtonSmallTexture: PIXI.Texture; @@ -27,6 +28,7 @@ export default class GameAssets { public static TitleTexture: PIXI.Texture; public static BannerGemsmith: PIXI.Texture; public static EndScreenDialog: PIXI.Texture; + public static SpecialLightning: PIXI.Texture[] = []; public static Tutorial01: PIXI.Texture; public static Tutorial02: PIXI.Texture; @@ -105,6 +107,7 @@ export default class GameAssets { this.Load('./assets/gui/frame_red.png').then((texture) => (this.RedBackground = texture)), this.Load('./assets/gui/frame_green.png').then((texture) => (this.GreenBackground = texture)), this.Load('./assets/gui/frame_blue.png').then((texture) => (this.BlueBackground = texture)), + this.Load('./assets/gui/frame_yellow.png').then((texture) => (this.YellowBackground = texture)), this.Load('./assets/gui/banner_01.png').then((texture) => (this.BannerGemsmith = texture)), this.Load('./assets/gui/note.png').then((texture) => (this.EndScreenDialog = texture)), this.Load('./assets/gui/main_background.jpg').then((texture) => (this.MainBackground = texture)), @@ -186,11 +189,14 @@ export default class GameAssets { for (let idx = 0; idx < this.Towers.length; idx++) { const tower = this.Towers[idx]; for (let i = 0; i < tower.projectileTexturesArrayLength; i++) { - const projTexture = await this.Load(`./assets/projectiles/${tower.sprite}/${i}.png`); + const projTexture = await this.Load(`./assets/projectiles/${tower.projectile}/${i}.png`); tower.projectileTextures[i] = projTexture; } tower.texture = await this.Load(`./assets/towers/${tower.sprite}.png`); } + for (let idx = 0; idx < 4; idx++) { + this.SpecialLightning[idx] = await this.Load(`./assets/projectiles/lightning/${idx}.png`); + } } private static async LoadMission(missionUrl: string) { diff --git a/src/classes/Bastion.ts b/src/classes/Bastion.ts index 3256e32..9957f7a 100644 --- a/src/classes/Bastion.ts +++ b/src/classes/Bastion.ts @@ -9,6 +9,8 @@ import { AnimationManager } from './game/AnimationManager'; import NotificationManager from './game/NotificationManager'; import Gem from './game/Gem'; import GameAssets from './Assets'; +import { TowerType } from './Definitions'; +import DebrisManager from './game/DebrisManager'; export class Engine { public static app: PIXI.Application; @@ -18,6 +20,7 @@ export class Engine { public static TowerManager: TowerManager; public static AnimationManager: AnimationManager; public static NotificationManager: NotificationManager; + public static DebrisManager: DebrisManager; public static GameScene: GameScene; public static latestCommit: string; public static latestGemId = 0; @@ -32,7 +35,7 @@ export class Engine { let params = new URLSearchParams(location.href); if (params.entries().next().value[1] != 'game') return; Engine.NotificationManager.Notify('Loaded testing suite.', 'danger'); - let tower = GameAssets.Towers[0]; + let tower = GameAssets.Towers[TowerType.Electric]; Engine.TowerManager.ToggleChoosingTowerLocation('RESET'); Engine.TowerManager.PlaceTower(tower, 6, 10, tower.behaviour, true); for (let i = 0; i < 29; i++) { diff --git a/src/classes/Definitions.ts b/src/classes/Definitions.ts index 4af3c63..7e64e71 100644 --- a/src/classes/Definitions.ts +++ b/src/classes/Definitions.ts @@ -56,6 +56,7 @@ export type TowerDefinition = { behaviour: string; sprite: string; description: string; + projectile: string; texture: PIXI.Texture; projectileTextures: PIXI.Texture[]; projectileTexturesArrayLength: number; @@ -123,4 +124,10 @@ export enum GemType { export enum TowerType { Basic = 0, Circle = 1, + Electric = 2, + Buff = 3, + Strong = 4, + Rail = 5, + Trapper = 6, + Debuff = 7, } diff --git a/src/classes/game/DebrisManager.ts b/src/classes/game/DebrisManager.ts new file mode 100644 index 0000000..b226ca5 --- /dev/null +++ b/src/classes/game/DebrisManager.ts @@ -0,0 +1,41 @@ +import GameObject from '../GameObject'; +import { Container } from 'pixi.js'; + +class Debris { + public ticksToDestroyAt: number; + private debris: Container | GameObject; + constructor(debris: Container | GameObject, ticksToDestroyAt) { + this.debris = debris; + this.ticksToDestroyAt = ticksToDestroyAt; + } + public destroy() { + this.debris.destroy(); + } + public update(elapsedMS) { + console.log(this.debris instanceof GameObject); + if (this.debris instanceof GameObject) { + this.debris.update(elapsedMS); + } + } +} + +export default class DebrisManager extends GameObject { + private ticks: number = 0; + private debris: Debris[] = []; + public update(elapsedMS) { + this.ticks++; + for (let idx = this.debris.length - 1; idx >= 0; idx--) { + const db = this.debris[idx]; + if (this.ticks >= db.ticksToDestroyAt) { + db.destroy(); + this.debris.splice(idx, 1); + } else { + db.update(elapsedMS); + } + } + } + public CreateDebris(affectedObject: Container | GameObject, ticksToDestroyAt?: number) { + if (!ticksToDestroyAt) ticksToDestroyAt = 120; + this.debris.push(new Debris(affectedObject, this.ticks + ticksToDestroyAt)); + } +} diff --git a/src/classes/game/Grid.ts b/src/classes/game/Grid.ts index 3a30768..0ce25ef 100644 --- a/src/classes/game/Grid.ts +++ b/src/classes/game/Grid.ts @@ -1,10 +1,11 @@ import * as PIXI from 'pixi.js'; import GameObject from '../GameObject'; -import { GameMapDefinition, TerrainType } from '../Definitions'; +import { GameMapDefinition, TerrainType, TowerType } from '../Definitions'; import GameAssets from '../Assets'; import { Engine } from '../Bastion'; import Creep from './Creep'; import { CreepEvents, TowerEvents, GridEvents } from '../Events'; +import { distance, Tower } from './Tower'; let genPath = []; @@ -15,6 +16,7 @@ export class Cell extends GameObject { public isPath: boolean = false; public g: PIXI.Graphics; public hasTowerPlaced: boolean = false; + public isBuffedBy: Tower[] = []; public clickDetector: PIXI.Graphics; constructor(type: TerrainType, row: number, column: number, isPath: boolean) { @@ -55,59 +57,35 @@ export class Cell extends GameObject { this.clickDetector.on('pointerleave', (e) => { if (!Engine.Grid.gridInteractionEnabled || Engine.GameScene.towerPanel.isShown) return; Engine.GameScene.events.emit(GridEvents.CellMouseLeave, this); - Engine.Grid.rangePreview.clear(); }); - Engine.GameScene.events.on(TowerEvents.TowerPlacedEvent, (_, row, col) => { + Engine.GameScene.events.on(TowerEvents.TowerPlacedEvent, (towerName, row, col) => { if (row == this.row && col == this.column) { this.hasTowerPlaced = true; Engine.Grid.rangePreview.clear(); + } else if (towerName == GameAssets.Towers[TowerType.Buff].name) { + let twr = Engine.TowerManager.GetTowerByRowAndCol(row, col); + if (Engine.Grid.IsCellInRangeOfOtherCell(row, col, twr.computedRange, this)) { + this.isBuffedBy.push(twr); + } } }); - Engine.GameScene.events.on(TowerEvents.TowerSoldEvent, (_, row, col) => { + Engine.GameScene.events.on(TowerEvents.TowerSoldEvent, (towerName, row, col) => { + console.log(towerName, row, col); if (row == this.row && col == this.column) { this.hasTowerPlaced = false; Engine.Grid.rangePreview.clear(); + } else if (towerName == GameAssets.Towers[TowerType.Buff].name) { + let twr = Engine.TowerManager.GetTowerByRowAndCol(row, col); + if (Engine.Grid.IsCellInRangeOfOtherCell(row, col, twr.computedRange, this)) { + console.log('REMOVED!'); + this.isBuffedBy.splice(this.isBuffedBy.indexOf(twr), 1); + console.log(this.isBuffedBy); + } } }); - // Disable this if you want to add new maps. - if (true) return; - - const text = new PIXI.Text({ - text: `${this.column}|${this.row}`, - style: new PIXI.TextStyle({ - fill: 0xffffff, - fontSize: 16, - stroke: { - color: 0x000000, - width: 2, - }, - }), - }); - this.container.addChild(text); - text.anchor.set(0.5, 0.5); - text.x = this.bb.width / 2; - text.y = this.bb.height / 2; - if (this.type == TerrainType.Path) { - text.style.fill = 'green'; - text.style.fontWeight = 'bold'; - } - if (this.type == TerrainType.Restricted) { - text.style.fill = 'gold'; - } - this.clickDetector.on('pointerup', () => { - const cellIndex = genPath.findIndex(([col, row]) => col === this.column && row === this.row); - if (cellIndex !== -1) { - text.style.fill = 0xffffff; - genPath.splice(cellIndex, 1); - } else { - text.style.fill = 0xff0000; - genPath.push([this.column, this.row]); - } - console.log('updated gen path'); - console.log(JSON.stringify(genPath)); - }); + // See commit f84108847b6ba6c337954a742f4dc1a38a2c925b } public showRangePreview(invalid, range) { let color = 0xffffff; @@ -182,6 +160,10 @@ export class Grid extends GameObject { } this.rangePreview = new PIXI.Graphics({ zIndex: 10, + x: 0, + y: 0, + width: Engine.app.canvas.width, + height: Engine.app.canvas.height, }); this.container.addChild(this.rangePreview); } @@ -211,6 +193,17 @@ export class Grid extends GameObject { console.log(JSON.stringify(newGrid)); } + + public IsCellInRangeOfOtherCell(row, col, range, otherCell) { + range = range * Engine.GridCellSize; + const x = otherCell.column * Engine.GridCellSize + Engine.GridCellSize / 2; + const y = otherCell.row * Engine.GridCellSize + Engine.GridCellSize / 2; + const cellX = col * Engine.GridCellSize + Engine.GridCellSize / 2; + const cellY = row * Engine.GridCellSize + Engine.GridCellSize / 2; + const d = distance(cellX, cellY, x, y); + if (d < range + Engine.GridCellSize / 2) return true; + else return false; + } public toggleGrid(force?: 'hide' | 'show') { this.cells.forEach((cell) => { if (force) { diff --git a/src/classes/game/Projectile.ts b/src/classes/game/Projectile.ts index 210d257..6ebf97d 100644 --- a/src/classes/game/Projectile.ts +++ b/src/classes/game/Projectile.ts @@ -3,8 +3,9 @@ import GameObject from '../GameObject'; import { Engine } from '../Bastion'; import Creep from './Creep'; import { CreepEvents } from '../Events'; -import { Tower } from './Tower'; +import { distance, Tower } from './Tower'; import { CreepResistancesDefinition } from '../Definitions'; +import GameAssets from '../Assets'; export function calculateAngleToPoint(x, y, targetX, targetY) { const dx = targetX - x; @@ -48,13 +49,14 @@ export default class Projectile extends GameObject { this.sprite.play(); this.container.x = this.x; this.container.y = this.y; - this.sprite.tint = tint; + // this.sprite.tint = tint; this.container.addChild(this.sprite); Engine.GameMaster.currentScene.stage.addChild(this.container); this.angle = angle; this.speed = 0.9; } + public destroy(): void { super.destroy(); this.deleteMe = true; @@ -72,7 +74,7 @@ export default class Projectile extends GameObject { if (!exists) { this.collidedCreepIDs.push(creep); this.pierce--; - this.onCollide(creep); + this.onCollide(creep, this); return; } } @@ -84,14 +86,14 @@ export default class Projectile extends GameObject { this.container.y = this.y; } - public onCollide(creep) { + public onCollide(creep, proj) { /* Note: Right now it is possible for the bullet to 'overshoot' the creep if the bullet speed is too fast and the position is updated so that the new position is beyond the creep (i.e. the bullet is never 'in the creep'). This should be fixed so that we calculate the hit if the creep is in a line from the previous position to the new position. */ - Engine.GameScene.events.emit(CreepEvents.TakenDamage, creep.id, this.damage, this.gemResistanceModifications); + Engine.GameScene.events.emit(CreepEvents.TakenDamage, creep.id, proj.damage, proj.gemResistanceModifications); } public checkCollision(creep: Creep) { @@ -102,3 +104,42 @@ export default class Projectile extends GameObject { return mybb.getBounds().intersects(otherbb.getBounds()); } } + +export class VisualLightning extends GameObject { + public deleteMe: boolean = false; + private c: Creep; + private oc: Creep; + private Lightning: PIXI.AnimatedSprite; + constructor(creep: Creep, otherCreep: Creep) { + super(); + this.c = creep; + this.oc = otherCreep; + let lightningAngle = calculateAngleToPoint(creep.x, creep.y, otherCreep.x, otherCreep.y); + this.Lightning = new PIXI.AnimatedSprite({ + textures: GameAssets.SpecialLightning, + x: creep.x, + y: creep.y, + width: distance(this.c.x, this.c.y, this.oc.x, this.oc.y), + height: 64, + scale: 1.2, + rotation: lightningAngle, + }); + this.Lightning.anchor.set(0, 0.5); + this.Lightning.play(); + Engine.GameMaster.currentScene.stage.addChild(this.Lightning); + Engine.DebrisManager.CreateDebris(this, 30); + } + public destroy(): void { + this.deleteMe = true; + this.container.destroy(); + this.Lightning.destroy(); + } + public update() { + if (this.deleteMe) { + return; + } + this.Lightning.x = this.c.x; + this.Lightning.y = this.c.y; + this.Lightning.width = distance(this.c.x, this.c.y, this.oc.x, this.oc.y); + } +} diff --git a/src/classes/game/Tower.ts b/src/classes/game/Tower.ts index 265b4e3..3443383 100644 --- a/src/classes/game/Tower.ts +++ b/src/classes/game/Tower.ts @@ -1,13 +1,21 @@ import { Engine } from '../Bastion'; import * as PIXI from 'pixi.js'; import GameObject from '../GameObject'; -import { CreepResistancesDefinition, GemType, TowerDefinition } from '../Definitions'; +import { CreepResistancesDefinition, TowerDefinition } from '../Definitions'; import { Cell } from './Grid'; import { TowerBehaviours } from './TowerManager'; -import Projectile, { calculateAngleToPoint } from './Projectile'; -import Creep from './Creep'; +import Projectile from './Projectile'; import Gem from './Gem'; -import { BasicTowerBehaviour, CircleTowerBehaviour } from './TowerBehaviours'; +import { + DebuffTowerBehaviour, + BasicTowerBehaviour, + CircleTowerBehaviour, + ElectricTowerBehaviour, + BuffTowerBehaviour, + RailTowerBehaviour, + StrongTowerBehaviour, + TrapperTowerBehaviour, +} from './TowerBehaviours'; export function distance(x1, y1, x2, y2) { return Math.sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1)); @@ -26,12 +34,18 @@ export class Tower extends GameObject { public sprite: PIXI.Sprite; public millisecondsUntilNextShot: number; public graphics: PIXI.Graphics = new PIXI.Graphics(); - public computedDamageToDeal: number; - public computedCooldown: number; - public computedRange: number; - public computedTimeToLive: number; - public computedPierce: number; - public totalGemResistanceModifications: CreepResistancesDefinition; + public computedDamageToDeal: number = 0; + public computedCooldown: number = 0; + public computedRange: number = 0; + public computedTimeToLive: number = 0; + public computedPierce: number = 0; + public totalGemResistanceModifications: CreepResistancesDefinition = { + fire: 0, + frostfire: 0, + divine: 0, + ice: 0, + physical: 0, + }; public parent: Cell; constructor(row, column, texture, definition, behaviour) { @@ -50,6 +64,7 @@ export class Tower extends GameObject { }); this.container.addChild(this.sprite); this.computedDamageToDeal = this.definition.stats.damage; + this.computedRange = this.definition.stats.range; this.parent.container.addChild(this.container); this.container.interactiveChildren = true; this.parent.clickDetector.on('pointerenter', this.onParentCellEnter); @@ -104,6 +119,7 @@ export class Tower extends GameObject { return d < radius + (Engine.GridCellSize * 2) / 3; }); } + public Shoot(angle) { let x = this.column * Engine.GridCellSize + Engine.GridCellSize / 2; let y = this.row * Engine.GridCellSize + Engine.GridCellSize / 2; @@ -128,13 +144,13 @@ export class Tower extends GameObject { this.totalGemResistanceModifications ); const time = new Date().toISOString(); - console.log(`${time} ${this.definition.name} shot at ${angle} degrees`); + // console.log(`${time} ${this.definition.name} shot at ${angle} degrees`); this.projectiles.push(proj); return proj; } public Sell() { - this.setAsSold = true; // Selling logic is handled in TowerManager.update() + this.setAsSold = true; } public update(elapsedMS: any): void { if (this.sold) return; @@ -143,6 +159,12 @@ export class Tower extends GameObject { } if (this.behaviour == TowerBehaviours.BasicTowerBehaviour) BasicTowerBehaviour(this, elapsedMS); if (this.behaviour == TowerBehaviours.CircleTowerBehaviour) CircleTowerBehaviour(this, elapsedMS); + if (this.behaviour == TowerBehaviours.ElectricTowerBehaviour) ElectricTowerBehaviour(this, elapsedMS); + if (this.behaviour == TowerBehaviours.BuffTowerBehaviour) BuffTowerBehaviour(this, elapsedMS); + if (this.behaviour == TowerBehaviours.StrongTowerBehaviour) StrongTowerBehaviour(this, elapsedMS); + if (this.behaviour == TowerBehaviours.RailTowerBehaviour) RailTowerBehaviour(this, elapsedMS); + if (this.behaviour == TowerBehaviours.TrapperTowerBehaviour) TrapperTowerBehaviour(this, elapsedMS); + if (this.behaviour == TowerBehaviours.DebuffTowerBehaviour) DebuffTowerBehaviour(this, elapsedMS); } public destroy(): void { diff --git a/src/classes/game/TowerBehaviours.ts b/src/classes/game/TowerBehaviours.ts index 8867844..396d299 100644 --- a/src/classes/game/TowerBehaviours.ts +++ b/src/classes/game/TowerBehaviours.ts @@ -1,6 +1,11 @@ +import GameAssets from '../Assets'; import { Engine } from '../Bastion'; -import { calculateAngleToPoint } from './Projectile'; -import { Tower } from './Tower'; +import { TowerType } from '../Definitions'; +import { CreepEvents } from '../Events'; +import Creep from './Creep'; +import Projectile, { calculateAngleToPoint, VisualLightning } from './Projectile'; +import { distance, Tower } from './Tower'; +import * as PIXI from 'pixi.js'; /** * Checks the projectiles of the tower and updates or removes them based on their state. @@ -44,34 +49,47 @@ export function computeGemImprovements(tower: Tower) { physical: 0, }; tower.slottedGems.forEach((gem) => { - let ccurrentGemImprovements = gem.currentGemImprovement(); - gemDamage += ccurrentGemImprovements.damageUp; - gemAttackSpeedUp += ccurrentGemImprovements.attackSpeedUp; - gemRangeUp += ccurrentGemImprovements.rangeUp; - gemTimeToLiveUp += ccurrentGemImprovements.timeToLiveUp; - gemPierceUp += ccurrentGemImprovements.pierceUp; + let improvements = gem.currentGemImprovement(); + gemDamage += improvements.damageUp; + gemAttackSpeedUp += improvements.attackSpeedUp; + gemRangeUp += improvements.rangeUp; + gemTimeToLiveUp += improvements.timeToLiveUp; + gemPierceUp += improvements.pierceUp; - let gemResMod = gem.currentGemResistanceModifications(); - tower.totalGemResistanceModifications.physical += gemResMod.physical; - tower.totalGemResistanceModifications.ice += gemResMod.ice; - tower.totalGemResistanceModifications.fire += gemResMod.fire; - tower.totalGemResistanceModifications.divine += gemResMod.divine; - tower.totalGemResistanceModifications.frostfire += gemResMod.frostfire; + let resistances = gem.currentGemResistanceModifications(); + tower.totalGemResistanceModifications.physical += resistances.physical; + tower.totalGemResistanceModifications.ice += resistances.ice; + tower.totalGemResistanceModifications.fire += resistances.fire; + tower.totalGemResistanceModifications.divine += resistances.divine; + tower.totalGemResistanceModifications.frostfire += resistances.frostfire; }); + tower.computedDamageToDeal = tower.definition.stats.damage + gemDamage; tower.computedCooldown = tower.definition.stats.cooldown - gemAttackSpeedUp; tower.computedRange = tower.definition.stats.range + gemRangeUp; tower.computedTimeToLive = tower.definition.stats.timeToLive + gemTimeToLiveUp; tower.computedPierce = tower.definition.stats.pierce + gemPierceUp; + + // Buff tower + if (tower.parent.isBuffedBy.length > 0 && tower.definition.name != GameAssets.Towers[TowerType.Buff].name) { + let buffedBy = tower.parent.isBuffedBy[0]; + tower.computedDamageToDeal += Number((buffedBy.computedDamageToDeal / 2).toFixed(1)); + tower.computedCooldown -= (buffedBy.computedCooldown * 100) / 5 / 100; + tower.computedRange += Number((buffedBy.computedRange / 10).toFixed(1)); + tower.computedTimeToLive += (buffedBy.computedTimeToLive * 100) / 5 / 100; + tower.computedPierce += (buffedBy.computedPierce * 100) / 4 / 100; + + tower.totalGemResistanceModifications.physical += + (buffedBy.totalGemResistanceModifications.physical * 100) / 2 / 100; + tower.totalGemResistanceModifications.ice += (buffedBy.totalGemResistanceModifications.ice * 100) / 2 / 100; + tower.totalGemResistanceModifications.fire += (buffedBy.totalGemResistanceModifications.fire * 100) / 2 / 100; + tower.totalGemResistanceModifications.divine += + (buffedBy.totalGemResistanceModifications.divine * 100) / 2 / 100; + tower.totalGemResistanceModifications.frostfire += + (buffedBy.totalGemResistanceModifications.frostfire * 100) / 2 / 100; + } } -/** - * Defines the basic behavior of a tower, including computing damage, checking projectiles, - * and handling shooting at creeps within range. - * - * @param tower - The tower whose behavior is being defined. - * @param elapsedMS - The elapsed time in milliseconds since the last update. - */ export function BasicTowerBehaviour(tower: Tower, elapsedMS: number) { computeGemImprovements(tower); projectileCheck(tower, elapsedMS); @@ -96,7 +114,6 @@ export function CircleTowerBehaviour(tower: Tower, elapsedMS: number) { tower.millisecondsUntilNextShot -= elapsedMS * Engine.GameScene.gameSpeedMultiplier; let creepsInRange = tower.GetCreepsInRange(); if (creepsInRange.length > 0) { - let focus = creepsInRange[0]; if (tower.millisecondsUntilNextShot <= 0) { tower.millisecondsUntilNextShot = tower.computedCooldown; let x = tower.column * Engine.GridCellSize + Engine.GridCellSize / 2; @@ -112,3 +129,126 @@ export function CircleTowerBehaviour(tower: Tower, elapsedMS: number) { } } } + +export function ElectricTowerBehaviour(tower: Tower, elapsedMS: number) { + computeGemImprovements(tower); + projectileCheck(tower, elapsedMS); + + if (tower.millisecondsUntilNextShot > 0) + tower.millisecondsUntilNextShot -= elapsedMS * Engine.GameScene.gameSpeedMultiplier; + + let creepsInRange = tower.GetCreepsInRange(); + + if (creepsInRange.length > 0) { + let focus = creepsInRange[0]; + if (tower.millisecondsUntilNextShot <= 0) { + let x = tower.column * Engine.GridCellSize + Engine.GridCellSize / 2; + let y = tower.row * Engine.GridCellSize + Engine.GridCellSize / 2; + tower.millisecondsUntilNextShot = tower.computedCooldown; + let proj = tower.Shoot(calculateAngleToPoint(x, y, focus.x, focus.y)); + proj.onCollide = (creep: Creep, proj: Projectile) => { + let chainedCreepIds = []; + proj.pierce = 0; + function checkNearBy(c) { + let nearByCreeps = Engine.Grid.creeps.filter((nCreep) => { + if (nCreep.id != creep.id) { + const x = nCreep.x; + const y = nCreep.y; + const radius = 1.5 * Engine.GridCellSize; + const d = distance(c.x, c.y, x, y); + return d < radius; + } + }); + nearByCreeps.forEach((nearCreep) => { + if (!chainedCreepIds.find((crID) => crID == nearCreep.id)) chainedCreepIds.push(nearCreep.id); + else return; + checkNearBy(nearCreep); + new VisualLightning(c, nearCreep); + Engine.GameScene.events.emit( + CreepEvents.TakenDamage, + nearCreep.id, + Math.round(proj.damage / 2), + proj.gemResistanceModifications + ); + }); + } + checkNearBy(creep); + Engine.GameScene.events.emit( + CreepEvents.TakenDamage, + creep.id, + proj.damage, + proj.gemResistanceModifications + ); + }; + } + } +} + +export function BuffTowerBehaviour(tower: Tower, elapsedMS: number) { + computeGemImprovements(tower); + // Buff tower does not do anything and doesn't have a behaviour. + // For how its implemented, Cell tracks when it's placed and removed (via event) + // and tower takes improvements via computeGemImprovements() +} + +export function StrongTowerBehaviour(tower: Tower, elapsedMS: number) { + computeGemImprovements(tower); + projectileCheck(tower, elapsedMS); + + if (tower.millisecondsUntilNextShot > 0) + tower.millisecondsUntilNextShot -= elapsedMS * Engine.GameScene.gameSpeedMultiplier; + let creepsInRange = tower.GetCreepsInRange(); + if (creepsInRange.length > 0) { + let focus = creepsInRange[0]; + if (tower.millisecondsUntilNextShot <= 0) { + let x = tower.column * Engine.GridCellSize + Engine.GridCellSize / 2; + let y = tower.row * Engine.GridCellSize + Engine.GridCellSize / 2; + tower.millisecondsUntilNextShot = tower.computedCooldown; + tower.Shoot(calculateAngleToPoint(x, y, focus.x, focus.y)); + } + } +} + +export function RailTowerBehaviour(tower: Tower, elapsedMS: number) { + computeGemImprovements(tower); + projectileCheck(tower, elapsedMS); + + if (tower.millisecondsUntilNextShot > 0) + tower.millisecondsUntilNextShot -= elapsedMS * Engine.GameScene.gameSpeedMultiplier; + let creepsInRange = tower.GetCreepsInRange(); + if (creepsInRange.length > 0) { + let focus = creepsInRange[0]; + if (tower.millisecondsUntilNextShot <= 0) { + let x = tower.column * Engine.GridCellSize + Engine.GridCellSize / 2; + let y = tower.row * Engine.GridCellSize + Engine.GridCellSize / 2; + tower.millisecondsUntilNextShot = tower.computedCooldown; + tower.Shoot(calculateAngleToPoint(x, y, focus.x, focus.y)); + } + } +} + +export function TrapperTowerBehaviour(tower: Tower, elapsedMS: number) { + computeGemImprovements(tower); + projectileCheck(tower, elapsedMS); + + if (tower.millisecondsUntilNextShot > 0) + tower.millisecondsUntilNextShot -= elapsedMS * Engine.GameScene.gameSpeedMultiplier; +} + +export function DebuffTowerBehaviour(tower: Tower, elapsedMS: number) { + computeGemImprovements(tower); + projectileCheck(tower, elapsedMS); + + if (tower.millisecondsUntilNextShot > 0) + tower.millisecondsUntilNextShot -= elapsedMS * Engine.GameScene.gameSpeedMultiplier; + let creepsInRange = tower.GetCreepsInRange(); + if (creepsInRange.length > 0) { + let focus = creepsInRange[0]; + if (tower.millisecondsUntilNextShot <= 0) { + let x = tower.column * Engine.GridCellSize + Engine.GridCellSize / 2; + let y = tower.row * Engine.GridCellSize + Engine.GridCellSize / 2; + tower.millisecondsUntilNextShot = tower.computedCooldown; + tower.Shoot(calculateAngleToPoint(x, y, focus.x, focus.y)); + } + } +} diff --git a/src/classes/game/TowerManager.ts b/src/classes/game/TowerManager.ts index 1a31cd5..8f5cc6f 100644 --- a/src/classes/game/TowerManager.ts +++ b/src/classes/game/TowerManager.ts @@ -9,6 +9,12 @@ import { GridEvents, TowerEvents } from '../Events'; export enum TowerBehaviours { BasicTowerBehaviour = 'BasicTowerBehaviour', CircleTowerBehaviour = 'CircleTowerBehaviour', + ElectricTowerBehaviour = 'ElectricTowerBehaviour', + BuffTowerBehaviour = 'BuffTowerBehaviour', + StrongTowerBehaviour = 'StrongTowerBehaviour', + RailTowerBehaviour = 'RailTowerBehaviour', + TrapperTowerBehaviour = 'TrapperTowerBehaviour', + DebuffTowerBehaviour = 'DebuffTowerBehaviour', } export default class TowerManager { @@ -43,6 +49,7 @@ export default class TowerManager { }); Engine.GameScene.events.on(GridEvents.CellMouseLeave, (cell: Cell) => { this.previewSprite.texture = null; + Engine.Grid.rangePreview.clear(); }); } public ResetChooseTower() { @@ -86,7 +93,6 @@ export default class TowerManager { this.towers.forEach((tower) => { if (tower.row == row && tower.column == col) returnTower = tower; }); - // console.log(returnTower, row, col); return returnTower; } public PlaceTower(definition: TowerDefinition, row, column, behaviour: string, ignoreCost?) { @@ -110,7 +116,6 @@ export default class TowerManager { 'Can not place tower on path or other tower, choose another spot.', 'warn' ); - console.warn('Can not place tower on occupied spot or path. Try again.'); } } public update(elapsedMS) { @@ -120,10 +125,10 @@ export default class TowerManager { while (twr.slottedGems.length > 0) { twr.UnslotGem(0); } + Engine.GameScene.events.emit(TowerEvents.TowerSoldEvent, twr.definition.name, twr.row, twr.column); Engine.GameScene.MissionStats.earnGold(twr.definition.stats.cost); twr.destroy(); this.towers.splice(idx, 1); - Engine.GameScene.events.emit(TowerEvents.TowerSoldEvent, twr.name, twr.row, twr.column); } else twr.update(elapsedMS); }); } diff --git a/src/classes/gui/TowerPanel.ts b/src/classes/gui/TowerPanel.ts index a6fe3b7..d6ccef4 100644 --- a/src/classes/gui/TowerPanel.ts +++ b/src/classes/gui/TowerPanel.ts @@ -341,7 +341,7 @@ export default class TowerPanel extends GuiObject { this.damageText.text = 'Deals ' + tower.computedDamageToDeal + ' damage'; this.totalDamage.text = 'Damage dealt: ' + tower.damageDealt + ' damage'; this.attackSpeedText.x = this.damageText.width + 10; - this.attackSpeedText.text = ` every ${Math.floor((tower.computedCooldown / 60) * 100) / 100}s`; + this.attackSpeedText.text = ` every ${Math.floor((tower.computedCooldown / 1000) * 100) / 100}s`; this.fireResDamage.text = `+${tower.totalGemResistanceModifications.fire * 100}% Fire damage`; this.iceResDamage.text = `+${tower.totalGemResistanceModifications.ice * 100}% Ice damage`; diff --git a/src/classes/gui/TowerTab.ts b/src/classes/gui/TowerTab.ts index fefd096..d0c7d03 100644 --- a/src/classes/gui/TowerTab.ts +++ b/src/classes/gui/TowerTab.ts @@ -122,10 +122,82 @@ export default class TowerTab extends GuiObject { 70, this.container, GameAssets.RedBackground, - 'Basic Tower', + GameAssets.Towers[0].name, GameAssets.Towers[0].texture ) ); + this.towerButtons.push( + new TowerButton( + 1, + 0, + 70, + 70, + this.container, + GameAssets.RedBackground, + GameAssets.Towers[1].name, + GameAssets.Towers[1].texture + ) + ); + this.towerButtons.push( + new TowerButton( + 2, + 0, + 70, + 70, + this.container, + GameAssets.BlueBackground, + GameAssets.Towers[2].name, + GameAssets.Towers[2].texture + ) + ); + this.towerButtons.push( + new TowerButton( + 3, + 0, + 70, + 70, + this.container, + GameAssets.BlueBackground, + GameAssets.Towers[3].name, + GameAssets.Towers[3].texture + ) + ); + this.towerButtons.push( + new TowerButton( + 0, + 1, + 70, + 70, + this.container, + GameAssets.GreenBackground, + GameAssets.Towers[4].name, + GameAssets.Towers[4].texture + ) + ); + this.towerButtons.push( + new TowerButton( + 1, + 1, + 70, + 70, + this.container, + GameAssets.GreenBackground, + GameAssets.Towers[5].name, + GameAssets.Towers[5].texture + ) + ); + this.towerButtons.push( + new TowerButton( + 2, + 1, + 70, + 70, + this.container, + GameAssets.YellowBackground, + GameAssets.Towers[6].name, + GameAssets.Towers[6].texture + ) + ); this.towerButtons.push( new TowerButton( 3, @@ -133,9 +205,9 @@ export default class TowerTab extends GuiObject { 70, 70, this.container, - GameAssets.GreenBackground, - 'Circle Tower', - GameAssets.Towers[1].texture + GameAssets.YellowBackground, + GameAssets.Towers[7].name, + GameAssets.Towers[7].texture ) ); } diff --git a/src/main.ts b/src/main.ts index 3543950..13f012f 100644 --- a/src/main.ts +++ b/src/main.ts @@ -7,7 +7,7 @@ import { AnimationManager } from './classes/game/AnimationManager'; import NotificationManager from './classes/game/NotificationManager'; import GameUIConstants from './classes/GameUIConstants'; import KeyboardManager from './classes/game/KeyboardManager'; -import { GemType } from './classes/Definitions'; +import DebrisManager from './classes/game/DebrisManager'; (async () => { const app = new PIXI.Application(); @@ -44,7 +44,7 @@ import { GemType } from './classes/Definitions'; app.canvas.style.marginBottom = `0`; app.canvas.style.display = 'block'; } - Engine.latestCommit = await fetch('/latest_commit').then((res) => res.text()); + Engine.latestCommit = await fetch('./latest_commit').then((res) => res.text()); window.addEventListener('resize', resize); resize(); @@ -54,10 +54,12 @@ import { GemType } from './classes/Definitions'; new GameMaster(); Engine.AnimationManager = new AnimationManager(); Engine.NotificationManager = new NotificationManager(); + Engine.DebrisManager = new DebrisManager(); globalThis.Engine = Engine; PIXI.Ticker.shared.add((ticker) => { Engine.NotificationManager.update(ticker.elapsedMS); Engine.AnimationManager.update(ticker.elapsedMS); + Engine.DebrisManager.update(ticker.elapsedMS); }); app.canvas.addEventListener('pointermove', function (event) { Engine.MouseX = ((event.clientX - app.canvas.offsetLeft) / app.canvas.offsetWidth) * 1920; @@ -76,14 +78,12 @@ import { GemType } from './classes/Definitions'; let gamePausedDueToBlur = false; window.addEventListener('blur', () => { - console.log('blur'); if (Engine.GameScene && !Engine.GameScene.isPaused) { Engine.GameScene.PauseGame(); gamePausedDueToBlur = true; } }); window.addEventListener('focus', () => { - console.log('focus'); if (Engine.GameScene && gamePausedDueToBlur && Engine.GameScene.isPaused) { gamePausedDueToBlur = false; Engine.GameScene.UnpauseGame();