From 32beb97557b4cf64c128fe0b9bcc84d8390073e3 Mon Sep 17 00:00:00 2001 From: koneko <67551503+koneko@users.noreply.github.com> Date: Sat, 22 Feb 2025 15:12:17 +0100 Subject: [PATCH] implemented trapper tower --- docs/linecount.md | 27 +++---- public/assets/json/Towers.json | 6 +- public/assets/projectiles/stone/0.png | Bin 1087 -> 7869 bytes public/assets/projectiles/stone/1.png | Bin 1293 -> 0 bytes src/classes/game/Grid.ts | 11 +++ src/classes/game/Projectile.ts | 55 +++++++++++++++ src/classes/game/TowerBehaviours.ts | 98 +++++++++++++++++++------- src/scenes/Game.ts | 2 +- 8 files changed, 157 insertions(+), 42 deletions(-) delete mode 100644 public/assets/projectiles/stone/1.png diff --git a/docs/linecount.md b/docs/linecount.md index bf1b6a8..6c13e68 100644 --- a/docs/linecount.md +++ b/docs/linecount.md @@ -2,7 +2,7 @@ Generated by: `find ./src -name '*.ts' | xargs wc -l` 92 ./src/main.ts 1 ./src/vite-env.d.ts 17 ./src/classes/GameUIConstants.ts -145 ./src/classes/gui/TowerTab.ts +217 ./src/classes/gui/TowerTab.ts 375 ./src/classes/gui/TowerPanel.ts 52 ./src/classes/gui/TextInput.ts 211 ./src/classes/gui/ModalDialog.ts @@ -15,29 +15,30 @@ Generated by: `find ./src -name '*.ts' | xargs wc -l` 59 ./src/classes/gui/GamePausedDialog.ts 36 ./src/classes/gui/MessageBox.ts 205 ./src/classes/gui/Tooltip.ts -126 ./src/classes/Definitions.ts +133 ./src/classes/Definitions.ts 77 ./src/classes/game/WaveManager.ts -260 ./src/classes/game/Grid.ts +264 ./src/classes/game/Grid.ts 51 ./src/classes/game/Gem.ts -114 ./src/classes/game/TowerBehaviours.ts -154 ./src/classes/game/Tower.ts +324 ./src/classes/game/TowerBehaviours.ts +192 ./src/classes/game/Tower.ts 180 ./src/classes/game/MissionStats.ts 100 ./src/classes/game/AnimationManager.ts -177 ./src/classes/game/Creep.ts +239 ./src/classes/game/Creep.ts 47 ./src/classes/game/KeyboardManager.ts -104 ./src/classes/game/Projectile.ts +251 ./src/classes/game/Projectile.ts 86 ./src/classes/game/NotificationManager.ts -130 ./src/classes/game/TowerManager.ts +40 ./src/classes/game/DebrisManager.ts +135 ./src/classes/game/TowerManager.ts 71 ./src/classes/game/HighScoreManager.ts 76 ./src/classes/GuiObject.ts -203 ./src/classes/Assets.ts +209 ./src/classes/Assets.ts 52 ./src/classes/GameObject.ts -68 ./src/classes/Bastion.ts -30 ./src/classes/Events.ts +71 ./src/classes/Bastion.ts +31 ./src/classes/Events.ts 37 ./src/scenes/Scene.ts 17 ./src/scenes/Settings.ts 67 ./src/scenes/HowToPlay.ts 59 ./src/scenes/Main.ts -353 ./src/scenes/Game.ts +352 ./src/scenes/Game.ts 27 ./src/scenes/MissionPicker.ts -`4536 total` +`5130 total` diff --git a/public/assets/json/Towers.json b/public/assets/json/Towers.json index 6b43daa..e69c100 100644 --- a/public/assets/json/Towers.json +++ b/public/assets/json/Towers.json @@ -120,7 +120,7 @@ "texture": null, "projectile": "stone", "projectileTextures": [], - "projectileTexturesArrayLength": 2, + "projectileTexturesArrayLength": 1, "description": "If you feel a little circular.", "stats": { "damage": 2, @@ -128,8 +128,8 @@ "gemSlotsAmount": 3, "cost": 125, "range": 2.5, - "timeToLive": 12, - "pierce": 30 + "timeToLive": 400, + "pierce": 2 } }, { diff --git a/public/assets/projectiles/stone/0.png b/public/assets/projectiles/stone/0.png index 774f9303579cdda58ecb81abe2622779eea7d26d..923d96831d657f057da5728df7055251e87a6b18 100644 GIT binary patch literal 7869 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 IC|kVwKe(_XEC2ui literal 1087 zcmV-F1i<@=P)lmt5A)meq((oUFW`Xf0r#FN&GzsIWMrWMXnF_?B(dc7ylR!TL0a|Mw zS(ZoF*48lI5Xj#qAoBSv!#ST zu*2={7aacOMqjthc-)oN`E)XB*SvMiHIrRcc#CwKg50B(1`;N-+m z52b0^sHSPBf-@Si+wEAbRs=yn5QLWKXnJ}YMNue~N?3dc*QZYu#Q@+xyRTF#WV2ba z*=%i$APCs)b~-vba5x+k3I$4~k}e>d&4$zItm&vysqixGgohV~#V&t+qk49l$z<5y z-^Xk=)~#C&b>w!t+1lEw`79O-`?8DZx4p!FdyQYEH)FonpMQBd zeedf{Lnf0UlgV80_4oJV^Z5WM7K;>%MUIY+C>D!&yY# zN$Q!V#sR<0biXBER-sU!P$;msw^!3qPfrhuqL50Z8cmy!Bq?@Y=ud!2r)A*UNF5w4 z^E~$r(Wt9ART`IFegdUg|cp(3KIj~C{>gpV4@0HXEh)I z$1iN}e9z|Q=8d9QsZ{XX-QkWu&E2>E0EkJFG;w7~mQz$3Vlm2qKjGVOcU>J^z78Mw4`iw4$V(54EQTVu`h5$6x#r6;H(c9Zg z_t19~%1I8AAMjS!r*w67)y?<$e8l5%78e&eJUpaaE@QLVhL)F?uWTN4ou`7q;FHfE zsh?DL_VvzB4_5~U26jhAMkrNI1)VLV8>Tap$<)qEE|&|h*E`V&=-N}lRW=o7^|S+t z0#QU!40w+}4DY}EJ4E)LUytyw5_Vgf(R073vo1Ms#dBm?j!BX<^s2SYt%3>$gE1fm zd?AXWzX}*W12h;64TasdNL>>_KM+bLldF@Hle${>e*g$k#ra4_8~^|S002ovPDHLk FV1frE_YnX9 diff --git a/public/assets/projectiles/stone/1.png b/public/assets/projectiles/stone/1.png deleted file mode 100644 index 553f4633395d54812b820ec0da9a8543657315d1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1293 zcmV+o1@iidP)oyFrlWcw{F99jJUiMXebK_X_I)6 z9p+}FBx!8Nd89~jp0}^R{yfj~`#CK%sc4#Z0T>2;0aQRA92``wjM35rkwM@Z5U$ch z1@z6Eh(@F8`Sa)XN)5#(xcNCC*Ju_pKO^yYoM<#U4IFKnSWVMHrkkO9`^4jMMn^}f z@dOZD5PAt%up%@Xjcy7B;MlQaVOO2C<0in^*ch|3vs-@-1Jex`t7)2Sa(Tf@zt+}P z#>dAi3B}ws8tbg4X<^gNpp|~@?d{02%}Tw{KT% zSBYC&&fdR&|5|%{`-sQm!Rz(n@px!!YeNwJyLU;F@OV5JhC#7d#4rp10)YU2zn`mD zuM&&JwwvZHZY_(AL?UuNpC8HR^Ho{w>+7StyPH5D@K$}DLMw7>$Jvoum4;!ENF+!k z5+#=ozL{VgUdD+rLTe%giBCwsa6}KEwM3N-S zVz;_0G!lVorK6(*z>e5qCt^?75!>0>NivyaeSN(-&e}y_(^(s?zQwKJHUa<(3k!^o zkK65TOY8}|vn?(z+IIF$ZUwgy09aXBaT0=9c6P+cY|oxOa}?Qaax1uvKqix+P$)Q! zMC%jl6oH|kA@=Oq<5cW$z0RJtJA){S^z`)L^ZAEsey4g7K%fEUTGGIvEccY$Ow$>ijuC83AHKbOR=>iyiEJyPOUa0>x|wY4>C z9lTFULIHLLA8dZrfs2A$2-p#udY&u0&S!m?sm+k0D5~fd0(K6A^qQZgg>HJ^eZhL# zOAFF>ilUsUC#^Z=`$yn;+^ZD@kd^&Ja zQ53b_9IWXGn5D$0l{Yeu5qSLgan(A%oMuPw6P`cXO*U0Z*RLpwafk3UrWf%s}pSA(e(o$4`ql%(T)OBdMfk3Ur)zQ(x zom=nm*WBPlXJ_XbMNv|9pKx0c2)T&>fFKBTb#+}<6y=iTDDKPa$iNRkC|$Uv2fQEr zABeoV$Ag#OV!VEekB`Va{Fnm=4&e2A?JlkqaHihJUWwV$X1pj%;@&b>mos0Gdv%Xj z#VncPBzISCGBq_-S9VaLSmLvqSRFv}4B!=Zmb3S|{AI7F)j-$vignvyFkuQ+o#5s9 zX#(w&lU(nTK6~MBJ*=CLDhTkpm}UK+I{;);0d(~cyLa~!=#TN><<~rXbeFY9JJ_{r zSJ|L5Gc#{qURD(4+|trg&goicsS$OBfZ*!J_o21?k4OHP`ZO4P=U{06{{1BRimb6n zI@!f<(;ss7?AfxkI}(XF=F`dv#_{9FRg*JwvYVxw*w{E6`aAvSk$dy+hxYB;7vzms z_2&MnnnG0?SQ_?sXe1H|1HrkuxnMjVzhY(othf9NeQEvy7dK6e00000NkvXXu0mjf D?#O}F diff --git a/src/classes/game/Grid.ts b/src/classes/game/Grid.ts index 0ce25ef..b8ee63d 100644 --- a/src/classes/game/Grid.ts +++ b/src/classes/game/Grid.ts @@ -204,6 +204,17 @@ export class Grid extends GameObject { if (d < range + Engine.GridCellSize / 2) return true; else return false; } + public GetPathCellsInRange(row, col, range) { + let result = []; + this.cells.forEach((cell) => { + if (cell.isPath) { + if (this.IsCellInRangeOfOtherCell(row, col, range, cell)) { + result.push(cell); + } + } + }); + return result; + } 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 d59e5d1..52ee524 100644 --- a/src/classes/game/Projectile.ts +++ b/src/classes/game/Projectile.ts @@ -6,6 +6,7 @@ import { CreepEvents } from '../Events'; import { distance, Tower } from './Tower'; import { CreepResistancesDefinition } from '../Definitions'; import GameAssets from '../Assets'; +import { RoundMode } from '../../scenes/Game'; export function calculateAngleToPoint(x, y, targetX, targetY) { const dx = targetX - x; @@ -156,6 +157,60 @@ export class RailProjectile extends Projectile { } } +export class TrapProjectile extends Projectile { + public visuals: PIXI.Sprite[] = []; + public counter: number = 0; + private goalX: number; + private goalY: number; + constructor( + x, + y, + textures, + angle, + goalX, + goalY, + damage, + tint, + timeToLive, + pierce, + gemResistanceModifications: CreepResistancesDefinition + ) { + super(x, y, textures, angle, damage, tint, timeToLive, pierce, gemResistanceModifications); + this.sprite.scale = 0.5; + this.goalX = goalX; + this.goalY = goalY; + } + + public destroy(): void { + super.destroy(); + this.visuals.forEach((visual) => visual.destroy()); + this.visuals = []; + } + public update(elapsedMS) { + if (this.deleteMe) return; + if (this.x > 1720 || this.x < 0 || this.y > 2000 || this.y < 0 || this.pierce <= 0 || this.timeToLive <= 0) + return this.destroy(); + if (distance(this.x, this.y, this.goalX, this.goalY) < 25) { + this.timeToLive -= Engine.GameScene.gameSpeedMultiplier; + Engine.Grid.creeps.forEach((creep) => { + if (this.pierce <= 0) return; + if (creep && creep.container && this.checkCollision(creep)) { + this.collidedCreepIDs.push(creep); + this.pierce--; + this.onCollide(creep, this); + return; + } + }); + } else { + this.x += Math.cos(this.angle) * this.speed * elapsedMS * Engine.GameScene.gameSpeedMultiplier; + this.y += Math.sin(this.angle) * this.speed * elapsedMS * Engine.GameScene.gameSpeedMultiplier; + + this.container.x = this.x; + this.container.y = this.y; + } + } +} + export class VisualLightning extends GameObject { public deleteMe: boolean = false; private c: Creep; diff --git a/src/classes/game/TowerBehaviours.ts b/src/classes/game/TowerBehaviours.ts index b1b9ce5..16bf6b4 100644 --- a/src/classes/game/TowerBehaviours.ts +++ b/src/classes/game/TowerBehaviours.ts @@ -1,9 +1,10 @@ +import { RoundMode } from '../../scenes/Game'; import GameAssets from '../Assets'; import { Engine } from '../Bastion'; import { TowerType } from '../Definitions'; import { CreepEvents } from '../Events'; import Creep, { CreepEffects } from './Creep'; -import Projectile, { calculateAngleToPoint, VisualLightning } from './Projectile'; +import Projectile, { calculateAngleToPoint, TrapProjectile, VisualLightning } from './Projectile'; import { distance, Tower } from './Tower'; import * as PIXI from 'pixi.js'; @@ -78,10 +79,10 @@ export function computeGemImprovements(tower: 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.computedCooldown -= Number((buffedBy.computedCooldown / 5).toFixed(1)); tower.computedRange += Number((buffedBy.computedRange / 10).toFixed(1)); - tower.computedTimeToLive += (buffedBy.computedTimeToLive * 100) / 5 / 100; - tower.computedPierce += (buffedBy.computedPierce * 100) / 4 / 100; + tower.computedTimeToLive += Number((buffedBy.computedTimeToLive / 5).toFixed(1)); + tower.computedPierce += Number((buffedBy.computedPierce / 4).toFixed(1)); tower.totalGemResistanceModifications.physical += (buffedBy.totalGemResistanceModifications.physical * 100) / 2 / 100; @@ -99,10 +100,10 @@ export function BasicTowerBehaviour(tower: Tower, elapsedMS: number) { 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) { + else { + let creepsInRange = tower.GetCreepsInRange(); + if (creepsInRange.length > 0) { + let focus = creepsInRange[0]; let x = tower.column * Engine.GridCellSize + Engine.GridCellSize / 2; let y = tower.row * Engine.GridCellSize + Engine.GridCellSize / 2; tower.millisecondsUntilNextShot = tower.computedCooldown; @@ -116,9 +117,9 @@ export function CircleTowerBehaviour(tower: Tower, elapsedMS: number) { projectileCheck(tower, elapsedMS); if (tower.millisecondsUntilNextShot > 0) tower.millisecondsUntilNextShot -= elapsedMS * Engine.GameScene.gameSpeedMultiplier; - let creepsInRange = tower.GetCreepsInRange(); - if (creepsInRange.length > 0) { - if (tower.millisecondsUntilNextShot <= 0) { + else { + let creepsInRange = tower.GetCreepsInRange(); + if (creepsInRange.length > 0) { tower.millisecondsUntilNextShot = tower.computedCooldown; let x = tower.column * Engine.GridCellSize + Engine.GridCellSize / 2; let y = tower.row * Engine.GridCellSize + Engine.GridCellSize / 2; @@ -140,12 +141,11 @@ export function ElectricTowerBehaviour(tower: Tower, elapsedMS: number) { if (tower.millisecondsUntilNextShot > 0) tower.millisecondsUntilNextShot -= elapsedMS * Engine.GameScene.gameSpeedMultiplier; + else { + let creepsInRange = tower.GetCreepsInRange(); - let creepsInRange = tower.GetCreepsInRange(); - - if (creepsInRange.length > 0) { - let focus = creepsInRange[0]; - if (tower.millisecondsUntilNextShot <= 0) { + if (creepsInRange.length > 0) { + let focus = creepsInRange[0]; let x = tower.column * Engine.GridCellSize + Engine.GridCellSize / 2; let y = tower.row * Engine.GridCellSize + Engine.GridCellSize / 2; tower.millisecondsUntilNextShot = tower.computedCooldown; @@ -212,16 +212,22 @@ export function StrongTowerBehaviour(tower: Tower, elapsedMS: number) { 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) { + else { + let creepsInRange = tower.GetCreepsInRange(); + if (creepsInRange.length > 0) { + let focus = creepsInRange[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) => { - Engine.GameScene.events.emit(CreepEvents.GiveEffect, creep.id, CreepEffects.MovingBackwards, 500); + Engine.GameScene.events.emit(CreepEvents.GiveEffect, creep.id, CreepEffects.MovingBackwards, 750); + Engine.GameScene.events.emit( + CreepEvents.TakenDamage, + creep.id, + proj.damage / 2, + proj.gemResistanceModifications + ); }; } } @@ -233,10 +239,10 @@ export function RailTowerBehaviour(tower: Tower, elapsedMS: number) { 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) { + else { + let creepsInRange = tower.GetCreepsInRange(); + if (creepsInRange.length > 0) { + let focus = creepsInRange[0]; let x = tower.column * Engine.GridCellSize + Engine.GridCellSize / 2; let y = tower.row * Engine.GridCellSize + Engine.GridCellSize / 2; tower.millisecondsUntilNextShot = tower.computedCooldown; @@ -252,6 +258,42 @@ export function TrapperTowerBehaviour(tower: Tower, elapsedMS: number) { if (tower.millisecondsUntilNextShot > 0) tower.millisecondsUntilNextShot -= elapsedMS * Engine.GameScene.gameSpeedMultiplier; + else { + if (Engine.GameScene.roundMode != RoundMode.Combat) return; + let x = tower.column * Engine.GridCellSize + Engine.GridCellSize / 2; + let y = tower.row * Engine.GridCellSize + Engine.GridCellSize / 2; + let cells = Engine.Grid.GetPathCellsInRange(tower.row, tower.column, tower.computedRange); + if (cells.length > 0) { + let idx = Math.floor(Math.random() * cells.length); + let cell = cells[idx]; + let cellx = cell.column * Engine.GridCellSize + Engine.GridCellSize / 2; + let celly = cell.row * Engine.GridCellSize + Engine.GridCellSize / 2; + let combinedTint = new PIXI.Color('white'); + if (tower.slottedGems.length > 0) { + let color = new PIXI.Color(tower.slottedGems[0].definition.color); + for (let i = 1; i < tower.slottedGems.length; i++) { + const element = tower.slottedGems[i]; + color.multiply(element.definition.color); + } + combinedTint = color; + } + let proj = new TrapProjectile( + x, + y, + tower.definition.projectileTextures, + calculateAngleToPoint(x, y, cellx, celly), + cellx, + celly, + tower.computedDamageToDeal, + combinedTint, + tower.computedTimeToLive, + tower.computedPierce, + tower.totalGemResistanceModifications + ); + tower.projectiles.push(proj); + tower.millisecondsUntilNextShot = tower.computedCooldown; + } + } } export function DebuffTowerBehaviour(tower: Tower, elapsedMS: number) { @@ -270,6 +312,12 @@ export function DebuffTowerBehaviour(tower: Tower, elapsedMS: number) { let proj = tower.Shoot(calculateAngleToPoint(x, y, focus.x, focus.y)); proj.onCollide = (creep: Creep, proj: Projectile) => { Engine.GameScene.events.emit(CreepEvents.GiveEffect, creep.id, CreepEffects.DebuffTowerDebuff, 5000); + Engine.GameScene.events.emit( + CreepEvents.TakenDamage, + creep.id, + proj.damage / 1.5, + proj.gemResistanceModifications + ); }; } } diff --git a/src/scenes/Game.ts b/src/scenes/Game.ts index 2b2f7dc..eba63bb 100644 --- a/src/scenes/Game.ts +++ b/src/scenes/Game.ts @@ -20,7 +20,7 @@ import EndGameDialog from '../classes/gui/EndGameDialog'; import HighScoreDialog, { HighScoreDialogButtons } from '../classes/gui/HighScoreDialog'; import GamePausedDialog from '../classes/gui/GamePausedDialog'; -enum RoundMode { +export enum RoundMode { Purchase = 0, Combat = 1, Misc = 2,