From 9d998a45e18d5abdf375d1337ebcbf5e351b5e3d Mon Sep 17 00:00:00 2001 From: koneko <67551503+koneko@users.noreply.github.com> Date: Mon, 17 Feb 2025 11:49:44 +0100 Subject: [PATCH] electric tower chains properly --- public/assets/json/Gems.json | 8 ++-- public/assets/json/Towers.json | 44 ++++++++--------- public/assets/missions/02_the_turn.json | 35 ++++++++++++-- src/classes/game/Grid.ts | 54 ++------------------- src/classes/game/Projectile.ts | 2 +- src/classes/game/Tower.ts | 9 ++-- src/classes/game/TowerBehaviours.ts | 63 ++++++++++++------------- src/classes/game/TowerManager.ts | 4 +- src/main.ts | 4 +- 9 files changed, 98 insertions(+), 125 deletions(-) diff --git a/public/assets/json/Gems.json b/public/assets/json/Gems.json index 4a96e43..c50e244 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 }, diff --git a/public/assets/json/Towers.json b/public/assets/json/Towers.json index 9e1d93c..9b34a7c 100644 --- a/public/assets/json/Towers.json +++ b/public/assets/json/Towers.json @@ -10,12 +10,12 @@ "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 } }, { @@ -28,10 +28,10 @@ "projectileTexturesArrayLength": 4, "description": "If you feel a little circular.", "stats": { - "damage": 2, - "cooldown": 2000, - "gemSlotsAmount": 3, - "cost": 125, + "damage": 3, + "cooldown": 4000, + "gemSlotsAmount": 2, + "cost": 100, "range": 2.5, "timeToLive": 12, "pierce": 30 @@ -45,15 +45,15 @@ "projectile": "yellow", "projectileTextures": [], "projectileTexturesArrayLength": 4, - "description": "Think of something", + "description": "Zap zap zap!", "stats": { - "damage": 2, - "cooldown": 2000, - "gemSlotsAmount": 3, - "cost": 125, - "range": 2.5, + "damage": 3, + "cooldown": 3500, + "gemSlotsAmount": 2, + "cost": 150, + "range": 3, "timeToLive": 12, - "pierce": 30 + "pierce": 10 } }, { @@ -66,13 +66,13 @@ "projectileTexturesArrayLength": 4, "description": "", "stats": { - "damage": 2, - "cooldown": 2000, + "damage": 4, + "cooldown": 1000, "gemSlotsAmount": 3, - "cost": 125, - "range": 2.5, - "timeToLive": 12, - "pierce": 30 + "cost": 200, + "range": 2, + "timeToLive": 15, + "pierce": 5 } }, { 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/src/classes/game/Grid.ts b/src/classes/game/Grid.ts index af0635d..0ce25ef 100644 --- a/src/classes/game/Grid.ts +++ b/src/classes/game/Grid.ts @@ -76,7 +76,6 @@ export class Cell extends GameObject { this.hasTowerPlaced = false; Engine.Grid.rangePreview.clear(); } else if (towerName == GameAssets.Towers[TowerType.Buff].name) { - console.log('TRIpped!'); let twr = Engine.TowerManager.GetTowerByRowAndCol(row, col); if (Engine.Grid.IsCellInRangeOfOtherCell(row, col, twr.computedRange, this)) { console.log('REMOVED!'); @@ -86,59 +85,16 @@ export class Cell extends GameObject { } }); - // 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; if (invalid) color = 0xff0000; Engine.Grid.rangePreview.clear(); - console.log( - `Showing range preview ${this.column * Engine.GridCellSize + Engine.GridCellSize / 2}x - ${ - this.row * Engine.GridCellSize + Engine.GridCellSize / 2 - }y` - ); - console.log( - Engine.Grid.rangePreview.circle( - this.column * Engine.GridCellSize + Engine.GridCellSize / 2, - this.row * Engine.GridCellSize + Engine.GridCellSize / 2, - range * Engine.GridCellSize - ) + Engine.Grid.rangePreview.circle( + this.column * Engine.GridCellSize + Engine.GridCellSize / 2, + this.row * Engine.GridCellSize + Engine.GridCellSize / 2, + range * Engine.GridCellSize ); Engine.Grid.rangePreview.fill({ color: color, alpha: 0.3 }); } diff --git a/src/classes/game/Projectile.ts b/src/classes/game/Projectile.ts index e8f5cd8..6ebf97d 100644 --- a/src/classes/game/Projectile.ts +++ b/src/classes/game/Projectile.ts @@ -49,7 +49,7 @@ 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); diff --git a/src/classes/game/Tower.ts b/src/classes/game/Tower.ts index ae6384c..3443383 100644 --- a/src/classes/game/Tower.ts +++ b/src/classes/game/Tower.ts @@ -1,11 +1,10 @@ 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 { DebuffTowerBehaviour, @@ -145,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; diff --git a/src/classes/game/TowerBehaviours.ts b/src/classes/game/TowerBehaviours.ts index 63fa894..396d299 100644 --- a/src/classes/game/TowerBehaviours.ts +++ b/src/classes/game/TowerBehaviours.ts @@ -73,11 +73,11 @@ export function computeGemImprovements(tower: Tower) { // Buff tower if (tower.parent.isBuffedBy.length > 0 && tower.definition.name != GameAssets.Towers[TowerType.Buff].name) { let buffedBy = tower.parent.isBuffedBy[0]; - tower.computedDamageToDeal += Math.ceil(buffedBy.computedDamageToDeal / 3); - tower.computedCooldown -= Math.ceil(buffedBy.computedCooldown / 5); - tower.computedRange += Math.ceil(buffedBy.computedRange / 10); - tower.computedTimeToLive += Math.ceil(buffedBy.computedTimeToLive / 5); - tower.computedPierce += Math.ceil(buffedBy.computedPierce / 4); + 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; @@ -147,25 +147,32 @@ export function ElectricTowerBehaviour(tower: Tower, elapsedMS: number) { 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; - let nearByCreeps = Engine.Grid.creeps.filter((nCreep) => { - if (nCreep.id != creep.id) { - const x = nCreep.x; - const y = nCreep.y; - const radius = 3.5 * Engine.GridCellSize; - const d = distance(creep.x, creep.y, x, y); - return d < radius; - } - }); - nearByCreeps.forEach((nearCreep) => { - new VisualLightning(creep, nearCreep); - Engine.GameScene.events.emit( - CreepEvents.TakenDamage, - nearCreep.id, - proj.damage / 2, - proj.gemResistanceModifications - ); - }); + 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, @@ -226,16 +233,6 @@ export function TrapperTowerBehaviour(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) { - 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 DebuffTowerBehaviour(tower: Tower, elapsedMS: number) { diff --git a/src/classes/game/TowerManager.ts b/src/classes/game/TowerManager.ts index 3936eec..8f5cc6f 100644 --- a/src/classes/game/TowerManager.ts +++ b/src/classes/game/TowerManager.ts @@ -2,7 +2,7 @@ import * as PIXI from 'pixi.js'; import { Engine } from '../Bastion'; import { TerrainType, TowerDefinition } from '../Definitions'; import GameAssets from '../Assets'; -import { distance, Tower } from './Tower'; +import { Tower } from './Tower'; import { Cell } from './Grid'; import { GridEvents, TowerEvents } from '../Events'; @@ -93,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?) { @@ -117,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) { diff --git a/src/main.ts b/src/main.ts index 49ca147..13f012f 100644 --- a/src/main.ts +++ b/src/main.ts @@ -44,7 +44,7 @@ import DebrisManager from './classes/game/DebrisManager'; 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(); @@ -78,14 +78,12 @@ import DebrisManager from './classes/game/DebrisManager'; 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();