implemented more towers

This commit is contained in:
Koneko 2025-02-17 23:39:36 +01:00 committed by GitHub
commit 8267ade858
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
55 changed files with 1179 additions and 123 deletions

584
package-lock.json generated
View File

@ -8,6 +8,7 @@
"name": "bastion", "name": "bastion",
"version": "0.0.0", "version": "0.0.0",
"dependencies": { "dependencies": {
"pixi-spine": "^4.0.4",
"pixi-viewport": "^6.0.3", "pixi-viewport": "^6.0.3",
"pixi.js": "^8.4.0" "pixi.js": "^8.4.0"
}, },
@ -407,12 +408,268 @@
"node": ">=12" "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": { "node_modules/@pixi/colord": {
"version": "2.9.6", "version": "2.9.6",
"resolved": "https://registry.npmjs.org/@pixi/colord/-/colord-2.9.6.tgz", "resolved": "https://registry.npmjs.org/@pixi/colord/-/colord-2.9.6.tgz",
"integrity": "sha512-nezytU2pw587fQstUu1AsJZDVEynjskwOL+kibwcdxsMBFqPsFFNA7xl0ii/gXuDi6M0xj3mfRJj8pBSc2jCfA==", "integrity": "sha512-nezytU2pw587fQstUu1AsJZDVEynjskwOL+kibwcdxsMBFqPsFFNA7xl0ii/gXuDi6M0xj3mfRJj8pBSc2jCfA==",
"license": "MIT" "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": { "node_modules/@rollup/rollup-android-arm-eabi": {
"version": "4.21.3", "version": "4.21.3",
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.21.3.tgz", "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": ">=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": { "node_modules/earcut": {
"version": "2.2.4", "version": "2.2.4",
"resolved": "https://registry.npmjs.org/earcut/-/earcut-2.2.4.tgz", "resolved": "https://registry.npmjs.org/earcut/-/earcut-2.2.4.tgz",
"integrity": "sha512-/pjZsA1b4RPHbeWZQn66SWS8nZZWLQQ23oE3Eam7aroEFGEvwKAsJfZ9ytiEMycfzXWpca4FA9QIOehf7PocBQ==", "integrity": "sha512-/pjZsA1b4RPHbeWZQn66SWS8nZZWLQQ23oE3Eam7aroEFGEvwKAsJfZ9ytiEMycfzXWpca4FA9QIOehf7PocBQ==",
"license": "ISC" "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": { "node_modules/esbuild": {
"version": "0.21.5", "version": "0.21.5",
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", "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": "^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": { "node_modules/ismobilejs": {
"version": "1.1.1", "version": "1.1.1",
"resolved": "https://registry.npmjs.org/ismobilejs/-/ismobilejs-1.1.1.tgz", "resolved": "https://registry.npmjs.org/ismobilejs/-/ismobilejs-1.1.1.tgz",
"integrity": "sha512-VaFW53yt8QO61k2WJui0dHf4SlL8lxBofUuUmwBo0ljPk0Drz2TiuDW4jo3wDcv41qy/SxrJ+VAzJ/qYqsmzRw==", "integrity": "sha512-VaFW53yt8QO61k2WJui0dHf4SlL8lxBofUuUmwBo0ljPk0Drz2TiuDW4jo3wDcv41qy/SxrJ+VAzJ/qYqsmzRw==",
"license": "MIT" "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": { "node_modules/nanoid": {
"version": "3.3.7", "version": "3.3.7",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", "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": "^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": { "node_modules/parse-svg-path": {
"version": "0.1.2", "version": "0.1.2",
"resolved": "https://registry.npmjs.org/parse-svg-path/-/parse-svg-path-0.1.2.tgz", "resolved": "https://registry.npmjs.org/parse-svg-path/-/parse-svg-path-0.1.2.tgz",
@ -775,6 +1222,30 @@
"dev": true, "dev": true,
"license": "ISC" "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": { "node_modules/pixi-viewport": {
"version": "6.0.3", "version": "6.0.3",
"resolved": "https://registry.npmjs.org/pixi-viewport/-/pixi-viewport-6.0.3.tgz", "resolved": "https://registry.npmjs.org/pixi-viewport/-/pixi-viewport-6.0.3.tgz",
@ -830,6 +1301,29 @@
"node": "^10 || ^12 || >=14" "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": { "node_modules/rollup": {
"version": "4.21.3", "version": "4.21.3",
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.21.3.tgz", "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.21.3.tgz",
@ -866,6 +1360,82 @@
"fsevents": "~2.3.2" "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": { "node_modules/source-map-js": {
"version": "1.2.1", "version": "1.2.1",
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
@ -890,6 +1460,20 @@
"node": ">=14.17" "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": { "node_modules/vite": {
"version": "5.4.5", "version": "5.4.5",
"resolved": "https://registry.npmjs.org/vite/-/vite-5.4.5.tgz", "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.5.tgz",

View File

@ -13,6 +13,7 @@
"vite": "^5.4.1" "vite": "^5.4.1"
}, },
"dependencies": { "dependencies": {
"pixi-spine": "^4.0.4",
"pixi-viewport": "^6.0.3", "pixi-viewport": "^6.0.3",
"pixi.js": "^8.4.0" "pixi.js": "^8.4.0"
} }

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

View File

@ -8,7 +8,7 @@
"textures": [], "textures": [],
"cantCombineWith": [], "cantCombineWith": [],
"specialCombine": [], "specialCombine": [],
"initialGemValue": 10, "initialGemValue": 100,
"genericImprovements": [ "genericImprovements": [
{ {
"damageUp": 2, "damageUp": 2,
@ -16,7 +16,7 @@
"rangeUp": 0, "rangeUp": 0,
"timeToLiveUp": 0, "timeToLiveUp": 0,
"pierceUp": 1, "pierceUp": 1,
"gemValueUp": 0 "gemValueUp": 50
}, },
{ {
"damageUp": 2, "damageUp": 2,
@ -24,14 +24,14 @@
"rangeUp": 0, "rangeUp": 0,
"timeToLiveUp": 0, "timeToLiveUp": 0,
"pierceUp": 1, "pierceUp": 1,
"gemValueUp": 10 "gemValueUp": 100
} }
], ],
"gemResistanceModifications": [ "gemResistanceModifications": [
{ {
"physical": 0, "physical": 0,
"divine": 0, "divine": 0,
"fire": 0.25, "fire": 0.1,
"ice": 0, "ice": 0,
"frostfire": 0 "frostfire": 0
}, },
@ -77,14 +77,14 @@
"physical": 0, "physical": 0,
"divine": 0, "divine": 0,
"fire": 0, "fire": 0,
"ice": 0, "ice": 0.1,
"frostfire": 0 "frostfire": 0
}, },
{ {
"physical": 0, "physical": 0,
"divine": 0, "divine": 0,
"fire": 0, "fire": 0,
"ice": 0, "ice": 0.2,
"frostfire": 0 "frostfire": 0
} }
] ]
@ -127,21 +127,21 @@
], ],
"gemResistanceModifications": [ "gemResistanceModifications": [
{ {
"physical": 0, "physical": 0.1,
"divine": 0, "divine": 0,
"fire": 0, "fire": 0,
"ice": 0, "ice": 0,
"frostfire": 0 "frostfire": 0
}, },
{ {
"physical": 0, "physical": 0.1,
"divine": 0, "divine": 0,
"fire": 0, "fire": 0,
"ice": 0, "ice": 0,
"frostfire": 0 "frostfire": 0
}, },
{ {
"physical": 0, "physical": 0.25,
"divine": 0, "divine": 0,
"fire": 0, "fire": 0,
"ice": 0, "ice": 0,
@ -179,18 +179,18 @@
], ],
"gemResistanceModifications": [ "gemResistanceModifications": [
{ {
"physical": 0, "physical": 0.05,
"divine": 0, "divine": 0.05,
"fire": 0, "fire": 0.05,
"ice": 0, "ice": 0.05,
"frostfire": 0 "frostfire": 0.05
}, },
{ {
"physical": 0, "physical": 0.05,
"divine": 0, "divine": 0.05,
"fire": 0, "fire": 0.05,
"ice": 0, "ice": 0.05,
"frostfire": 0 "frostfire": 0.05
} }
] ]
} }

View File

@ -4,17 +4,18 @@
"behaviour": "BasicTowerBehaviour", "behaviour": "BasicTowerBehaviour",
"sprite": "basic_tower", "sprite": "basic_tower",
"texture": null, "texture": null,
"projectile": "white",
"projectileTextures": [], "projectileTextures": [],
"projectileTexturesArrayLength": 5, "projectileTexturesArrayLength": 5,
"description": "The building block of society, nothing more basic exists.", "description": "The building block of society, nothing more basic exists.",
"stats": { "stats": {
"damage": 2, "damage": 2,
"cooldown": 2000, "cooldown": 1500,
"gemSlotsAmount": 2, "gemSlotsAmount": 1,
"cost": 100, "cost": 50,
"range": 4, "range": 3,
"timeToLive": 20, "timeToLive": 20,
"pierce": 1 "pierce": 2
} }
}, },
{ {
@ -22,6 +23,121 @@
"behaviour": "CircleTowerBehaviour", "behaviour": "CircleTowerBehaviour",
"sprite": "circle_tower", "sprite": "circle_tower",
"texture": null, "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": [], "projectileTextures": [],
"projectileTexturesArrayLength": 4, "projectileTexturesArrayLength": 4,
"description": "If you feel a little circular.", "description": "If you feel a little circular.",

View File

@ -98,8 +98,8 @@
"waves": [ "waves": [
{ {
"firstCreepSpawnTick": 500, "firstCreepSpawnTick": 500,
"spawnIntervalTicks": 1000, "spawnIntervalTicks": 500,
"creeps": [0, 0, 0, 0, 0] "creeps": [0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 2]
} }
], ],
"offeredGems": [0, 0, 0, 0] "offeredGems": [0, 0, 0, 0]
@ -109,10 +109,35 @@
{ {
"firstCreepSpawnTick": 500, "firstCreepSpawnTick": 500,
"spawnIntervalTicks": 1000, "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": [ "waves": [
@ -122,7 +147,7 @@
"creeps": [2, 2, 2, 2, 2] "creeps": [2, 2, 2, 2, 2]
} }
], ],
"offeredGems": [0, 1, 2, 3] "offeredGems": [0, 1, 3, 3]
} }
] ]
} }

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

Before

Width:  |  Height:  |  Size: 6.1 KiB

After

Width:  |  Height:  |  Size: 6.1 KiB

View File

Before

Width:  |  Height:  |  Size: 6.0 KiB

After

Width:  |  Height:  |  Size: 6.0 KiB

View File

Before

Width:  |  Height:  |  Size: 5.7 KiB

After

Width:  |  Height:  |  Size: 5.7 KiB

View File

Before

Width:  |  Height:  |  Size: 6.1 KiB

After

Width:  |  Height:  |  Size: 6.1 KiB

View File

Before

Width:  |  Height:  |  Size: 6.1 KiB

After

Width:  |  Height:  |  Size: 6.1 KiB

View File

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 18 KiB

View File

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 18 KiB

View File

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 18 KiB

View File

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.1 KiB

After

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

View File

@ -17,6 +17,7 @@ export default class GameAssets {
public static RedBackground: PIXI.Texture; public static RedBackground: PIXI.Texture;
public static GreenBackground: PIXI.Texture; public static GreenBackground: PIXI.Texture;
public static BlueBackground: PIXI.Texture; public static BlueBackground: PIXI.Texture;
public static YellowBackground: PIXI.Texture;
public static Button01Texture: PIXI.Texture; public static Button01Texture: PIXI.Texture;
public static Button02Texture: PIXI.Texture; public static Button02Texture: PIXI.Texture;
public static ButtonSmallTexture: PIXI.Texture; public static ButtonSmallTexture: PIXI.Texture;
@ -27,6 +28,7 @@ export default class GameAssets {
public static TitleTexture: PIXI.Texture; public static TitleTexture: PIXI.Texture;
public static BannerGemsmith: PIXI.Texture; public static BannerGemsmith: PIXI.Texture;
public static EndScreenDialog: PIXI.Texture; public static EndScreenDialog: PIXI.Texture;
public static SpecialLightning: PIXI.Texture[] = [];
public static Tutorial01: PIXI.Texture; public static Tutorial01: PIXI.Texture;
public static Tutorial02: 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_red.png').then((texture) => (this.RedBackground = texture)),
this.Load('./assets/gui/frame_green.png').then((texture) => (this.GreenBackground = 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_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/banner_01.png').then((texture) => (this.BannerGemsmith = texture)),
this.Load('./assets/gui/note.png').then((texture) => (this.EndScreenDialog = texture)), this.Load('./assets/gui/note.png').then((texture) => (this.EndScreenDialog = texture)),
this.Load('./assets/gui/main_background.jpg').then((texture) => (this.MainBackground = 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++) { for (let idx = 0; idx < this.Towers.length; idx++) {
const tower = this.Towers[idx]; const tower = this.Towers[idx];
for (let i = 0; i < tower.projectileTexturesArrayLength; i++) { 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.projectileTextures[i] = projTexture;
} }
tower.texture = await this.Load(`./assets/towers/${tower.sprite}.png`); 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) { private static async LoadMission(missionUrl: string) {

View File

@ -9,6 +9,8 @@ import { AnimationManager } from './game/AnimationManager';
import NotificationManager from './game/NotificationManager'; import NotificationManager from './game/NotificationManager';
import Gem from './game/Gem'; import Gem from './game/Gem';
import GameAssets from './Assets'; import GameAssets from './Assets';
import { TowerType } from './Definitions';
import DebrisManager from './game/DebrisManager';
export class Engine { export class Engine {
public static app: PIXI.Application; public static app: PIXI.Application;
@ -18,6 +20,7 @@ export class Engine {
public static TowerManager: TowerManager; public static TowerManager: TowerManager;
public static AnimationManager: AnimationManager; public static AnimationManager: AnimationManager;
public static NotificationManager: NotificationManager; public static NotificationManager: NotificationManager;
public static DebrisManager: DebrisManager;
public static GameScene: GameScene; public static GameScene: GameScene;
public static latestCommit: string; public static latestCommit: string;
public static latestGemId = 0; public static latestGemId = 0;
@ -32,7 +35,7 @@ export class Engine {
let params = new URLSearchParams(location.href); let params = new URLSearchParams(location.href);
if (params.entries().next().value[1] != 'game') return; if (params.entries().next().value[1] != 'game') return;
Engine.NotificationManager.Notify('Loaded testing suite.', 'danger'); Engine.NotificationManager.Notify('Loaded testing suite.', 'danger');
let tower = GameAssets.Towers[0]; let tower = GameAssets.Towers[TowerType.Electric];
Engine.TowerManager.ToggleChoosingTowerLocation('RESET'); Engine.TowerManager.ToggleChoosingTowerLocation('RESET');
Engine.TowerManager.PlaceTower(tower, 6, 10, tower.behaviour, true); Engine.TowerManager.PlaceTower(tower, 6, 10, tower.behaviour, true);
for (let i = 0; i < 29; i++) { for (let i = 0; i < 29; i++) {

View File

@ -56,6 +56,7 @@ export type TowerDefinition = {
behaviour: string; behaviour: string;
sprite: string; sprite: string;
description: string; description: string;
projectile: string;
texture: PIXI.Texture; texture: PIXI.Texture;
projectileTextures: PIXI.Texture[]; projectileTextures: PIXI.Texture[];
projectileTexturesArrayLength: number; projectileTexturesArrayLength: number;
@ -123,4 +124,10 @@ export enum GemType {
export enum TowerType { export enum TowerType {
Basic = 0, Basic = 0,
Circle = 1, Circle = 1,
Electric = 2,
Buff = 3,
Strong = 4,
Rail = 5,
Trapper = 6,
Debuff = 7,
} }

View File

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

View File

@ -1,10 +1,11 @@
import * as PIXI from 'pixi.js'; import * as PIXI from 'pixi.js';
import GameObject from '../GameObject'; import GameObject from '../GameObject';
import { GameMapDefinition, TerrainType } from '../Definitions'; import { GameMapDefinition, TerrainType, TowerType } from '../Definitions';
import GameAssets from '../Assets'; import GameAssets from '../Assets';
import { Engine } from '../Bastion'; import { Engine } from '../Bastion';
import Creep from './Creep'; import Creep from './Creep';
import { CreepEvents, TowerEvents, GridEvents } from '../Events'; import { CreepEvents, TowerEvents, GridEvents } from '../Events';
import { distance, Tower } from './Tower';
let genPath = []; let genPath = [];
@ -15,6 +16,7 @@ export class Cell extends GameObject {
public isPath: boolean = false; public isPath: boolean = false;
public g: PIXI.Graphics; public g: PIXI.Graphics;
public hasTowerPlaced: boolean = false; public hasTowerPlaced: boolean = false;
public isBuffedBy: Tower[] = [];
public clickDetector: PIXI.Graphics; public clickDetector: PIXI.Graphics;
constructor(type: TerrainType, row: number, column: number, isPath: boolean) { constructor(type: TerrainType, row: number, column: number, isPath: boolean) {
@ -55,59 +57,35 @@ export class Cell extends GameObject {
this.clickDetector.on('pointerleave', (e) => { this.clickDetector.on('pointerleave', (e) => {
if (!Engine.Grid.gridInteractionEnabled || Engine.GameScene.towerPanel.isShown) return; if (!Engine.Grid.gridInteractionEnabled || Engine.GameScene.towerPanel.isShown) return;
Engine.GameScene.events.emit(GridEvents.CellMouseLeave, this); 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) { if (row == this.row && col == this.column) {
this.hasTowerPlaced = true; this.hasTowerPlaced = true;
Engine.Grid.rangePreview.clear(); 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) { if (row == this.row && col == this.column) {
this.hasTowerPlaced = false; this.hasTowerPlaced = false;
Engine.Grid.rangePreview.clear(); 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. // See commit f84108847b6ba6c337954a742f4dc1a38a2c925b
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));
});
} }
public showRangePreview(invalid, range) { public showRangePreview(invalid, range) {
let color = 0xffffff; let color = 0xffffff;
@ -182,6 +160,10 @@ export class Grid extends GameObject {
} }
this.rangePreview = new PIXI.Graphics({ this.rangePreview = new PIXI.Graphics({
zIndex: 10, zIndex: 10,
x: 0,
y: 0,
width: Engine.app.canvas.width,
height: Engine.app.canvas.height,
}); });
this.container.addChild(this.rangePreview); this.container.addChild(this.rangePreview);
} }
@ -211,6 +193,17 @@ export class Grid extends GameObject {
console.log(JSON.stringify(newGrid)); 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') { public toggleGrid(force?: 'hide' | 'show') {
this.cells.forEach((cell) => { this.cells.forEach((cell) => {
if (force) { if (force) {

View File

@ -3,8 +3,9 @@ import GameObject from '../GameObject';
import { Engine } from '../Bastion'; import { Engine } from '../Bastion';
import Creep from './Creep'; import Creep from './Creep';
import { CreepEvents } from '../Events'; import { CreepEvents } from '../Events';
import { Tower } from './Tower'; import { distance, Tower } from './Tower';
import { CreepResistancesDefinition } from '../Definitions'; import { CreepResistancesDefinition } from '../Definitions';
import GameAssets from '../Assets';
export function calculateAngleToPoint(x, y, targetX, targetY) { export function calculateAngleToPoint(x, y, targetX, targetY) {
const dx = targetX - x; const dx = targetX - x;
@ -48,13 +49,14 @@ export default class Projectile extends GameObject {
this.sprite.play(); this.sprite.play();
this.container.x = this.x; this.container.x = this.x;
this.container.y = this.y; this.container.y = this.y;
this.sprite.tint = tint; // this.sprite.tint = tint;
this.container.addChild(this.sprite); this.container.addChild(this.sprite);
Engine.GameMaster.currentScene.stage.addChild(this.container); Engine.GameMaster.currentScene.stage.addChild(this.container);
this.angle = angle; this.angle = angle;
this.speed = 0.9; this.speed = 0.9;
} }
public destroy(): void { public destroy(): void {
super.destroy(); super.destroy();
this.deleteMe = true; this.deleteMe = true;
@ -72,7 +74,7 @@ export default class Projectile extends GameObject {
if (!exists) { if (!exists) {
this.collidedCreepIDs.push(creep); this.collidedCreepIDs.push(creep);
this.pierce--; this.pierce--;
this.onCollide(creep); this.onCollide(creep, this);
return; return;
} }
} }
@ -84,14 +86,14 @@ export default class Projectile extends GameObject {
this.container.y = this.y; this.container.y = this.y;
} }
public onCollide(creep) { public onCollide(creep, proj) {
/* /*
Note: 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 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'). 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. 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) { public checkCollision(creep: Creep) {
@ -102,3 +104,42 @@ export default class Projectile extends GameObject {
return mybb.getBounds().intersects(otherbb.getBounds()); 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);
}
}

View File

@ -1,13 +1,21 @@
import { Engine } from '../Bastion'; import { Engine } from '../Bastion';
import * as PIXI from 'pixi.js'; import * as PIXI from 'pixi.js';
import GameObject from '../GameObject'; import GameObject from '../GameObject';
import { CreepResistancesDefinition, GemType, TowerDefinition } from '../Definitions'; import { CreepResistancesDefinition, TowerDefinition } from '../Definitions';
import { Cell } from './Grid'; import { Cell } from './Grid';
import { TowerBehaviours } from './TowerManager'; import { TowerBehaviours } from './TowerManager';
import Projectile, { calculateAngleToPoint } from './Projectile'; import Projectile from './Projectile';
import Creep from './Creep';
import Gem from './Gem'; 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) { export function distance(x1, y1, x2, y2) {
return Math.sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1)); 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 sprite: PIXI.Sprite;
public millisecondsUntilNextShot: number; public millisecondsUntilNextShot: number;
public graphics: PIXI.Graphics = new PIXI.Graphics(); public graphics: PIXI.Graphics = new PIXI.Graphics();
public computedDamageToDeal: number; public computedDamageToDeal: number = 0;
public computedCooldown: number; public computedCooldown: number = 0;
public computedRange: number; public computedRange: number = 0;
public computedTimeToLive: number; public computedTimeToLive: number = 0;
public computedPierce: number; public computedPierce: number = 0;
public totalGemResistanceModifications: CreepResistancesDefinition; public totalGemResistanceModifications: CreepResistancesDefinition = {
fire: 0,
frostfire: 0,
divine: 0,
ice: 0,
physical: 0,
};
public parent: Cell; public parent: Cell;
constructor(row, column, texture, definition, behaviour) { constructor(row, column, texture, definition, behaviour) {
@ -50,6 +64,7 @@ export class Tower extends GameObject {
}); });
this.container.addChild(this.sprite); this.container.addChild(this.sprite);
this.computedDamageToDeal = this.definition.stats.damage; this.computedDamageToDeal = this.definition.stats.damage;
this.computedRange = this.definition.stats.range;
this.parent.container.addChild(this.container); this.parent.container.addChild(this.container);
this.container.interactiveChildren = true; this.container.interactiveChildren = true;
this.parent.clickDetector.on('pointerenter', this.onParentCellEnter); this.parent.clickDetector.on('pointerenter', this.onParentCellEnter);
@ -104,6 +119,7 @@ export class Tower extends GameObject {
return d < radius + (Engine.GridCellSize * 2) / 3; return d < radius + (Engine.GridCellSize * 2) / 3;
}); });
} }
public Shoot(angle) { public Shoot(angle) {
let x = this.column * Engine.GridCellSize + Engine.GridCellSize / 2; let x = this.column * Engine.GridCellSize + Engine.GridCellSize / 2;
let y = this.row * 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 this.totalGemResistanceModifications
); );
const time = new Date().toISOString(); 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); this.projectiles.push(proj);
return proj; return proj;
} }
public Sell() { public Sell() {
this.setAsSold = true;
// Selling logic is handled in TowerManager.update() // Selling logic is handled in TowerManager.update()
this.setAsSold = true;
} }
public update(elapsedMS: any): void { public update(elapsedMS: any): void {
if (this.sold) return; 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.BasicTowerBehaviour) BasicTowerBehaviour(this, elapsedMS);
if (this.behaviour == TowerBehaviours.CircleTowerBehaviour) CircleTowerBehaviour(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 { public destroy(): void {

View File

@ -1,6 +1,11 @@
import GameAssets from '../Assets';
import { Engine } from '../Bastion'; import { Engine } from '../Bastion';
import { calculateAngleToPoint } from './Projectile'; import { TowerType } from '../Definitions';
import { Tower } from './Tower'; 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. * 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, physical: 0,
}; };
tower.slottedGems.forEach((gem) => { tower.slottedGems.forEach((gem) => {
let ccurrentGemImprovements = gem.currentGemImprovement(); let improvements = gem.currentGemImprovement();
gemDamage += ccurrentGemImprovements.damageUp; gemDamage += improvements.damageUp;
gemAttackSpeedUp += ccurrentGemImprovements.attackSpeedUp; gemAttackSpeedUp += improvements.attackSpeedUp;
gemRangeUp += ccurrentGemImprovements.rangeUp; gemRangeUp += improvements.rangeUp;
gemTimeToLiveUp += ccurrentGemImprovements.timeToLiveUp; gemTimeToLiveUp += improvements.timeToLiveUp;
gemPierceUp += ccurrentGemImprovements.pierceUp; gemPierceUp += improvements.pierceUp;
let gemResMod = gem.currentGemResistanceModifications(); let resistances = gem.currentGemResistanceModifications();
tower.totalGemResistanceModifications.physical += gemResMod.physical; tower.totalGemResistanceModifications.physical += resistances.physical;
tower.totalGemResistanceModifications.ice += gemResMod.ice; tower.totalGemResistanceModifications.ice += resistances.ice;
tower.totalGemResistanceModifications.fire += gemResMod.fire; tower.totalGemResistanceModifications.fire += resistances.fire;
tower.totalGemResistanceModifications.divine += gemResMod.divine; tower.totalGemResistanceModifications.divine += resistances.divine;
tower.totalGemResistanceModifications.frostfire += gemResMod.frostfire; tower.totalGemResistanceModifications.frostfire += resistances.frostfire;
}); });
tower.computedDamageToDeal = tower.definition.stats.damage + gemDamage; tower.computedDamageToDeal = tower.definition.stats.damage + gemDamage;
tower.computedCooldown = tower.definition.stats.cooldown - gemAttackSpeedUp; tower.computedCooldown = tower.definition.stats.cooldown - gemAttackSpeedUp;
tower.computedRange = tower.definition.stats.range + gemRangeUp; tower.computedRange = tower.definition.stats.range + gemRangeUp;
tower.computedTimeToLive = tower.definition.stats.timeToLive + gemTimeToLiveUp; tower.computedTimeToLive = tower.definition.stats.timeToLive + gemTimeToLiveUp;
tower.computedPierce = tower.definition.stats.pierce + gemPierceUp; 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) { export function BasicTowerBehaviour(tower: Tower, elapsedMS: number) {
computeGemImprovements(tower); computeGemImprovements(tower);
projectileCheck(tower, elapsedMS); projectileCheck(tower, elapsedMS);
@ -96,7 +114,6 @@ export function CircleTowerBehaviour(tower: Tower, elapsedMS: number) {
tower.millisecondsUntilNextShot -= elapsedMS * Engine.GameScene.gameSpeedMultiplier; tower.millisecondsUntilNextShot -= elapsedMS * Engine.GameScene.gameSpeedMultiplier;
let creepsInRange = tower.GetCreepsInRange(); let creepsInRange = tower.GetCreepsInRange();
if (creepsInRange.length > 0) { if (creepsInRange.length > 0) {
let focus = creepsInRange[0];
if (tower.millisecondsUntilNextShot <= 0) { if (tower.millisecondsUntilNextShot <= 0) {
tower.millisecondsUntilNextShot = tower.computedCooldown; tower.millisecondsUntilNextShot = tower.computedCooldown;
let x = tower.column * Engine.GridCellSize + Engine.GridCellSize / 2; 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));
}
}
}

View File

@ -9,6 +9,12 @@ import { GridEvents, TowerEvents } from '../Events';
export enum TowerBehaviours { export enum TowerBehaviours {
BasicTowerBehaviour = 'BasicTowerBehaviour', BasicTowerBehaviour = 'BasicTowerBehaviour',
CircleTowerBehaviour = 'CircleTowerBehaviour', CircleTowerBehaviour = 'CircleTowerBehaviour',
ElectricTowerBehaviour = 'ElectricTowerBehaviour',
BuffTowerBehaviour = 'BuffTowerBehaviour',
StrongTowerBehaviour = 'StrongTowerBehaviour',
RailTowerBehaviour = 'RailTowerBehaviour',
TrapperTowerBehaviour = 'TrapperTowerBehaviour',
DebuffTowerBehaviour = 'DebuffTowerBehaviour',
} }
export default class TowerManager { export default class TowerManager {
@ -43,6 +49,7 @@ export default class TowerManager {
}); });
Engine.GameScene.events.on(GridEvents.CellMouseLeave, (cell: Cell) => { Engine.GameScene.events.on(GridEvents.CellMouseLeave, (cell: Cell) => {
this.previewSprite.texture = null; this.previewSprite.texture = null;
Engine.Grid.rangePreview.clear();
}); });
} }
public ResetChooseTower() { public ResetChooseTower() {
@ -86,7 +93,6 @@ export default class TowerManager {
this.towers.forEach((tower) => { this.towers.forEach((tower) => {
if (tower.row == row && tower.column == col) returnTower = tower; if (tower.row == row && tower.column == col) returnTower = tower;
}); });
// console.log(returnTower, row, col);
return returnTower; return returnTower;
} }
public PlaceTower(definition: TowerDefinition, row, column, behaviour: string, ignoreCost?) { 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.', 'Can not place tower on path or other tower, choose another spot.',
'warn' 'warn'
); );
console.warn('Can not place tower on occupied spot or path. Try again.');
} }
} }
public update(elapsedMS) { public update(elapsedMS) {
@ -120,10 +125,10 @@ export default class TowerManager {
while (twr.slottedGems.length > 0) { while (twr.slottedGems.length > 0) {
twr.UnslotGem(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); Engine.GameScene.MissionStats.earnGold(twr.definition.stats.cost);
twr.destroy(); twr.destroy();
this.towers.splice(idx, 1); this.towers.splice(idx, 1);
Engine.GameScene.events.emit(TowerEvents.TowerSoldEvent, twr.name, twr.row, twr.column);
} else twr.update(elapsedMS); } else twr.update(elapsedMS);
}); });
} }

View File

@ -341,7 +341,7 @@ export default class TowerPanel extends GuiObject {
this.damageText.text = 'Deals ' + tower.computedDamageToDeal + ' damage'; this.damageText.text = 'Deals ' + tower.computedDamageToDeal + ' damage';
this.totalDamage.text = 'Damage dealt: ' + tower.damageDealt + ' damage'; this.totalDamage.text = 'Damage dealt: ' + tower.damageDealt + ' damage';
this.attackSpeedText.x = this.damageText.width + 10; 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.fireResDamage.text = `+${tower.totalGemResistanceModifications.fire * 100}% Fire damage`;
this.iceResDamage.text = `+${tower.totalGemResistanceModifications.ice * 100}% Ice damage`; this.iceResDamage.text = `+${tower.totalGemResistanceModifications.ice * 100}% Ice damage`;

View File

@ -122,10 +122,82 @@ export default class TowerTab extends GuiObject {
70, 70,
this.container, this.container,
GameAssets.RedBackground, GameAssets.RedBackground,
'Basic Tower', GameAssets.Towers[0].name,
GameAssets.Towers[0].texture 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( this.towerButtons.push(
new TowerButton( new TowerButton(
3, 3,
@ -133,9 +205,9 @@ export default class TowerTab extends GuiObject {
70, 70,
70, 70,
this.container, this.container,
GameAssets.GreenBackground, GameAssets.YellowBackground,
'Circle Tower', GameAssets.Towers[7].name,
GameAssets.Towers[1].texture GameAssets.Towers[7].texture
) )
); );
} }

View File

@ -7,7 +7,7 @@ import { AnimationManager } from './classes/game/AnimationManager';
import NotificationManager from './classes/game/NotificationManager'; import NotificationManager from './classes/game/NotificationManager';
import GameUIConstants from './classes/GameUIConstants'; import GameUIConstants from './classes/GameUIConstants';
import KeyboardManager from './classes/game/KeyboardManager'; import KeyboardManager from './classes/game/KeyboardManager';
import { GemType } from './classes/Definitions'; import DebrisManager from './classes/game/DebrisManager';
(async () => { (async () => {
const app = new PIXI.Application(); const app = new PIXI.Application();
@ -44,7 +44,7 @@ import { GemType } from './classes/Definitions';
app.canvas.style.marginBottom = `0`; app.canvas.style.marginBottom = `0`;
app.canvas.style.display = 'block'; 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); window.addEventListener('resize', resize);
resize(); resize();
@ -54,10 +54,12 @@ import { GemType } from './classes/Definitions';
new GameMaster(); new GameMaster();
Engine.AnimationManager = new AnimationManager(); Engine.AnimationManager = new AnimationManager();
Engine.NotificationManager = new NotificationManager(); Engine.NotificationManager = new NotificationManager();
Engine.DebrisManager = new DebrisManager();
globalThis.Engine = Engine; globalThis.Engine = Engine;
PIXI.Ticker.shared.add((ticker) => { PIXI.Ticker.shared.add((ticker) => {
Engine.NotificationManager.update(ticker.elapsedMS); Engine.NotificationManager.update(ticker.elapsedMS);
Engine.AnimationManager.update(ticker.elapsedMS); Engine.AnimationManager.update(ticker.elapsedMS);
Engine.DebrisManager.update(ticker.elapsedMS);
}); });
app.canvas.addEventListener('pointermove', function (event) { app.canvas.addEventListener('pointermove', function (event) {
Engine.MouseX = ((event.clientX - app.canvas.offsetLeft) / app.canvas.offsetWidth) * 1920; Engine.MouseX = ((event.clientX - app.canvas.offsetLeft) / app.canvas.offsetWidth) * 1920;
@ -76,14 +78,12 @@ import { GemType } from './classes/Definitions';
let gamePausedDueToBlur = false; let gamePausedDueToBlur = false;
window.addEventListener('blur', () => { window.addEventListener('blur', () => {
console.log('blur');
if (Engine.GameScene && !Engine.GameScene.isPaused) { if (Engine.GameScene && !Engine.GameScene.isPaused) {
Engine.GameScene.PauseGame(); Engine.GameScene.PauseGame();
gamePausedDueToBlur = true; gamePausedDueToBlur = true;
} }
}); });
window.addEventListener('focus', () => { window.addEventListener('focus', () => {
console.log('focus');
if (Engine.GameScene && gamePausedDueToBlur && Engine.GameScene.isPaused) { if (Engine.GameScene && gamePausedDueToBlur && Engine.GameScene.isPaused) {
gamePausedDueToBlur = false; gamePausedDueToBlur = false;
Engine.GameScene.UnpauseGame(); Engine.GameScene.UnpauseGame();