From b725671dffa6fadb00d1f219bcc7f263812d6d75 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 14 Feb 2026 19:24:21 +0000 Subject: [PATCH 01/17] Initial plan From d8d8a8750acd62f41d66cb22308dc137fa16fa9f Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 14 Feb 2026 19:26:10 +0000 Subject: [PATCH 02/17] Make drawEnemyResistanceIndicator resilient to missing resistance fields Co-authored-by: Linkatplug <36280686+Linkatplug@users.noreply.github.com> --- js/systems/RenderSystem.js | 30 +++++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/js/systems/RenderSystem.js b/js/systems/RenderSystem.js index 9285e1c..30be335 100644 --- a/js/systems/RenderSystem.js +++ b/js/systems/RenderSystem.js @@ -318,21 +318,33 @@ class RenderSystem { let layerCount = 0; if (defense.shield.current > 0) { - const base = defense.shield.baseResistances[damageType] || 0; - const bonus = defense.shield.bonusResistances && defense.shield.bonusResistances[damageType] || 0; - totalResist += base + bonus; + const layerData = defense.shield; + const baseRes = layerData.baseResistances || layerData.resistances || {}; + const bonusRes = layerData.bonusResistances || {}; + const base = baseRes[damageType] || 0; + const bonus = bonusRes[damageType] || 0; + const total = base + bonus; + totalResist += total; layerCount++; } if (defense.armor.current > 0) { - const base = defense.armor.baseResistances[damageType] || 0; - const bonus = defense.armor.bonusResistances && defense.armor.bonusResistances[damageType] || 0; - totalResist += base + bonus; + const layerData = defense.armor; + const baseRes = layerData.baseResistances || layerData.resistances || {}; + const bonusRes = layerData.bonusResistances || {}; + const base = baseRes[damageType] || 0; + const bonus = bonusRes[damageType] || 0; + const total = base + bonus; + totalResist += total; layerCount++; } if (defense.structure.current > 0) { - const base = defense.structure.baseResistances[damageType] || 0; - const bonus = defense.structure.bonusResistances && defense.structure.bonusResistances[damageType] || 0; - totalResist += base + bonus; + const layerData = defense.structure; + const baseRes = layerData.baseResistances || layerData.resistances || {}; + const bonusRes = layerData.bonusResistances || {}; + const base = baseRes[damageType] || 0; + const bonus = bonusRes[damageType] || 0; + const total = base + bonus; + totalResist += total; layerCount++; } From f76a9461a4bca3f5f452193f458650d46546df0d Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 14 Feb 2026 19:28:07 +0000 Subject: [PATCH 03/17] Apply code review feedback: remove unnecessary total variable Co-authored-by: Linkatplug <36280686+Linkatplug@users.noreply.github.com> --- js/systems/RenderSystem.js | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/js/systems/RenderSystem.js b/js/systems/RenderSystem.js index 30be335..3e84b3e 100644 --- a/js/systems/RenderSystem.js +++ b/js/systems/RenderSystem.js @@ -323,8 +323,7 @@ class RenderSystem { const bonusRes = layerData.bonusResistances || {}; const base = baseRes[damageType] || 0; const bonus = bonusRes[damageType] || 0; - const total = base + bonus; - totalResist += total; + totalResist += base + bonus; layerCount++; } if (defense.armor.current > 0) { @@ -333,8 +332,7 @@ class RenderSystem { const bonusRes = layerData.bonusResistances || {}; const base = baseRes[damageType] || 0; const bonus = bonusRes[damageType] || 0; - const total = base + bonus; - totalResist += total; + totalResist += base + bonus; layerCount++; } if (defense.structure.current > 0) { @@ -343,8 +341,7 @@ class RenderSystem { const bonusRes = layerData.bonusResistances || {}; const base = baseRes[damageType] || 0; const bonus = bonusRes[damageType] || 0; - const total = base + bonus; - totalResist += total; + totalResist += base + bonus; layerCount++; } From 9740fde512e37327db0220444dc20ce390bf0dc9 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 14 Feb 2026 19:45:37 +0000 Subject: [PATCH 04/17] Gate all debug logs behind COLLISION_DEBUG flag Co-authored-by: Linkatplug <36280686+Linkatplug@users.noreply.github.com> --- js/systems/CollisionSystem.js | 193 +++++++++++++++++++++------------- 1 file changed, 119 insertions(+), 74 deletions(-) diff --git a/js/systems/CollisionSystem.js b/js/systems/CollisionSystem.js index 0c3db4e..bdff7a6 100644 --- a/js/systems/CollisionSystem.js +++ b/js/systems/CollisionSystem.js @@ -3,6 +3,9 @@ * @description Handles collision detection between entities */ +// Debug flag to control collision debug logging +const COLLISION_DEBUG = false; + // Hit cooldown constant (200ms to prevent instant melt from tick collisions) const HIT_COOLDOWN_MS = 200; @@ -238,7 +241,9 @@ class CollisionSystem { const projectiles = this.world.getEntitiesByType('projectile'); // 🔍 DEBUG: Log player and projectile counts - console.log(`[DEBUG COLLISION] Players found: ${players.length}, Projectiles found: ${projectiles.length}`); + if (COLLISION_DEBUG) { + console.log(`[DEBUG COLLISION] Players found: ${players.length}, Projectiles found: ${projectiles.length}`); + } for (const player of players) { const playerPos = player.getComponent('position'); @@ -246,27 +251,35 @@ class CollisionSystem { const playerHealth = player.getComponent('health'); const playerDefense = player.getComponent('defense'); - console.log(`[DEBUG COLLISION] Player entity:`, { - id: player.id, - type: player.type, - hasPos: !!playerPos, - hasCol: !!playerCol, - hasHealth: !!playerHealth, - hasDefense: !!playerDefense - }); + if (COLLISION_DEBUG) { + console.log(`[DEBUG COLLISION] Player entity:`, { + id: player.id, + type: player.type, + hasPos: !!playerPos, + hasCol: !!playerCol, + hasHealth: !!playerHealth, + hasDefense: !!playerDefense + }); + } if (!playerPos || !playerCol || (!playerHealth && !playerDefense)) { - console.log(`[DEBUG COLLISION] ❌ Player missing required components, skipping`); + if (COLLISION_DEBUG) { + console.log(`[DEBUG COLLISION] ❌ Player missing required components, skipping`); + } continue; } // BUG FIX: Check invulnerability on defense component (player uses defense, not health) if (playerDefense && (playerDefense.invulnerable || playerDefense.godMode)) { - console.log(`[DEBUG COLLISION] ❌ Player invulnerable (defense), skipping all projectiles`); + if (COLLISION_DEBUG) { + console.log(`[DEBUG COLLISION] ❌ Player invulnerable (defense), skipping all projectiles`); + } continue; } if (playerHealth && (playerHealth.invulnerable || playerHealth.godMode)) { - console.log(`[DEBUG COLLISION] ❌ Player invulnerable (health), skipping all projectiles`); + if (COLLISION_DEBUG) { + console.log(`[DEBUG COLLISION] ❌ Player invulnerable (health), skipping all projectiles`); + } continue; } @@ -276,41 +289,51 @@ class CollisionSystem { const projComp = projectile.getComponent('projectile'); if (!projPos || !projCol || !projComp) { - console.log(`[DEBUG COLLISION] ⚠️ Projectile ${projectile.id} missing components`); + if (COLLISION_DEBUG) { + console.log(`[DEBUG COLLISION] ⚠️ Projectile ${projectile.id} missing components`); + } continue; } // 🔍 REQUESTED DEBUG: Log collision check details BEFORE ANY filtering - console.log( - "[DEBUG COLLISION CHECK]", - { - projectileId: projectile.id, - projectileOwner: projComp.owner, - projectileTag: projectile.type, - playerId: player.id, - playerTags: player.type, - projectilePos: { x: projPos.x, y: projPos.y }, - playerPos: { x: playerPos.x, y: playerPos.y } - } - ); + if (COLLISION_DEBUG) { + console.log( + "[DEBUG COLLISION CHECK]", + { + projectileId: projectile.id, + projectileOwner: projComp.owner, + projectileTag: projectile.type, + playerId: player.id, + playerTags: player.type, + projectilePos: { x: projPos.x, y: projPos.y }, + playerPos: { x: playerPos.x, y: playerPos.y } + } + ); + } // 🔍 DEBUG: Log projectile details BEFORE owner check - console.log(`[DEBUG COLLISION] Checking projectile ${projectile.id}:`, { - owner: projComp.owner, - damage: projComp.damage, - damageType: projComp.damageType, - pos: { x: projPos.x.toFixed(1), y: projPos.y.toFixed(1) } - }); + if (COLLISION_DEBUG) { + console.log(`[DEBUG COLLISION] Checking projectile ${projectile.id}:`, { + owner: projComp.owner, + damage: projComp.damage, + damageType: projComp.damageType, + pos: { x: projPos.x.toFixed(1), y: projPos.y.toFixed(1) } + }); + } // Check if projectile is from enemy (owner is an enemy entity or 'enemy' string) const ownerEntity = this.world.getEntity(projComp.owner); - console.log(`[DEBUG COLLISION] Owner entity lookup for ${projComp.owner}:`, { - found: !!ownerEntity, - type: ownerEntity?.type - }); + if (COLLISION_DEBUG) { + console.log(`[DEBUG COLLISION] Owner entity lookup for ${projComp.owner}:`, { + found: !!ownerEntity, + type: ownerEntity?.type + }); + } if (!ownerEntity || ownerEntity.type !== 'enemy') { - console.log(`[DEBUG COLLISION] ❌ Projectile ${projectile.id} not from enemy, skipping`); + if (COLLISION_DEBUG) { + console.log(`[DEBUG COLLISION] ❌ Projectile ${projectile.id} not from enemy, skipping`); + } continue; } @@ -321,26 +344,32 @@ class CollisionSystem { const collisionThreshold = playerCol.radius + projCol.radius; // 🔍 REQUESTED DEBUG: Log distance and radius details - console.log( - "[DEBUG DISTANCE]", - { - distance: distance, - projectileRadius: projCol.radius, - playerRadius: playerCol.radius, - sum: projCol.radius + playerCol.radius - } - ); + if (COLLISION_DEBUG) { + console.log( + "[DEBUG DISTANCE]", + { + distance: distance, + projectileRadius: projCol.radius, + playerRadius: playerCol.radius, + sum: projCol.radius + playerCol.radius + } + ); + } - console.log(`[DEBUG COLLISION] Distance check:`, { - distance: distance.toFixed(1), - threshold: collisionThreshold.toFixed(1), - willCollide: distance <= collisionThreshold - }); + if (COLLISION_DEBUG) { + console.log(`[DEBUG COLLISION] Distance check:`, { + distance: distance.toFixed(1), + threshold: collisionThreshold.toFixed(1), + willCollide: distance <= collisionThreshold + }); + } // FIX: Check hit cooldown for this projectile const sourceId = `projectile_${projectile.id}`; if (this.hitCooldowns.has(sourceId)) { - console.log(`[DEBUG COLLISION] ❌ Projectile ${projectile.id} on cooldown, skipping`); + if (COLLISION_DEBUG) { + console.log(`[DEBUG COLLISION] ❌ Projectile ${projectile.id} on cooldown, skipping`); + } continue; // Still on cooldown } @@ -348,8 +377,10 @@ class CollisionSystem { playerPos.x, playerPos.y, playerCol.radius, projPos.x, projPos.y, projCol.radius )) { - console.log(`[DEBUG COLLISION] ✅ COLLISION DETECTED! Projectile ${projectile.id} hit player ${player.id}`); - console.log(`[DEBUG COLLISION] ✅ COLLISION DETECTED! Projectile ${projectile.id} hit player ${player.id}`); + if (COLLISION_DEBUG) { + console.log(`[DEBUG COLLISION] ✅ COLLISION DETECTED! Projectile ${projectile.id} hit player ${player.id}`); + console.log(`[DEBUG COLLISION] ✅ COLLISION DETECTED! Projectile ${projectile.id} hit player ${player.id}`); + } // Check hit cooldown to prevent instant melt from tick collisions const now = performance.now(); @@ -360,20 +391,26 @@ class CollisionSystem { const lastHitTime = this.hitCooldowns.get(cooldownKey) || 0; const timeSinceLastHit = now - lastHitTime; - console.log(`[DEBUG COLLISION] Hit cooldown check:`, { - cooldownKey, - timeSinceLastHit: timeSinceLastHit.toFixed(0), - cooldownThreshold: HIT_COOLDOWN_MS, - willDamage: timeSinceLastHit >= HIT_COOLDOWN_MS - }); + if (COLLISION_DEBUG) { + console.log(`[DEBUG COLLISION] Hit cooldown check:`, { + cooldownKey, + timeSinceLastHit: timeSinceLastHit.toFixed(0), + cooldownThreshold: HIT_COOLDOWN_MS, + willDamage: timeSinceLastHit >= HIT_COOLDOWN_MS + }); + } if (timeSinceLastHit < HIT_COOLDOWN_MS) { // Still in cooldown, ignore this hit - console.log(`[DEBUG COLLISION] ❌ Hit cooldown active, ignoring damage`); + if (COLLISION_DEBUG) { + console.log(`[DEBUG COLLISION] ❌ Hit cooldown active, ignoring damage`); + } logger.debug('Collision', `Hit cooldown active (${timeSinceLastHit.toFixed(0)}ms < ${HIT_COOLDOWN_MS}ms) - ignoring damage`); } else { // Cooldown expired or first hit, deal damage - console.log(`[DEBUG COLLISION] ✅ Calling damagePlayer() with damage: ${projComp.damage}, type: ${damageType}`); + if (COLLISION_DEBUG) { + console.log(`[DEBUG COLLISION] ✅ Calling damagePlayer() with damage: ${projComp.damage}, type: ${damageType}`); + } this.damagePlayer(player, projComp.damage, damageType); // Update cooldown timestamp @@ -470,22 +507,26 @@ class CollisionSystem { } damagePlayer(player, damage, damageType = 'kinetic') { - console.log(`[DEBUG DAMAGE] damagePlayer() called:`, { - playerId: player?.id, - damage, - damageType - }); + if (COLLISION_DEBUG) { + console.log(`[DEBUG DAMAGE] damagePlayer() called:`, { + playerId: player?.id, + damage, + damageType + }); + } const playerComp = player.getComponent('player'); const defense = player.getComponent('defense'); const health = player.getComponent('health'); - console.log(`[DEBUG DAMAGE] Player components:`, { - hasPlayerComp: !!playerComp, - hasDefense: !!defense, - hasHealth: !!health, - defenseSystemExists: !!(this.world && this.world.defenseSystem) - }); + if (COLLISION_DEBUG) { + console.log(`[DEBUG DAMAGE] Player components:`, { + hasPlayerComp: !!playerComp, + hasDefense: !!defense, + hasHealth: !!health, + defenseSystemExists: !!(this.world && this.world.defenseSystem) + }); + } if (!playerComp) { console.error('[CollisionSystem] damagePlayer: Missing player component'); @@ -503,11 +544,15 @@ class CollisionSystem { // Apply damage through DefenseSystem (the only authority for defense modifications) // Use DamagePacket for proper structure if (defense && this.world && this.world.defenseSystem) { - console.log(`[DEBUG DAMAGE] Calling DefenseSystem.applyDamage()...`); + if (COLLISION_DEBUG) { + console.log(`[DEBUG DAMAGE] Calling DefenseSystem.applyDamage()...`); + } const damagePacket = DamagePacket.simple(damage, damageType); const result = this.world.defenseSystem.applyDamage(player, damagePacket); - console.log(`[DEBUG DAMAGE] DefenseSystem.applyDamage() result:`, result); + if (COLLISION_DEBUG) { + console.log(`[DEBUG DAMAGE] DefenseSystem.applyDamage() result:`, result); + } // Validate result if (!result || typeof result.dealt !== 'number') { From cd11c4a87838c4f66e173a532079745c678ad53f Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 14 Feb 2026 20:07:56 +0000 Subject: [PATCH 05/17] Add Combat Dev Sandbox page for testing combat mechanics Co-authored-by: Linkatplug <36280686+Linkatplug@users.noreply.github.com> --- dev/test-combat-sandbox.html | 749 +++++++++++++++++++++++++++++++++++ 1 file changed, 749 insertions(+) create mode 100644 dev/test-combat-sandbox.html diff --git a/dev/test-combat-sandbox.html b/dev/test-combat-sandbox.html new file mode 100644 index 0000000..5ef5fe0 --- /dev/null +++ b/dev/test-combat-sandbox.html @@ -0,0 +1,749 @@ + + + + + + Combat Dev Sandbox + + + +
+

⚔️ Combat Dev Sandbox

+
Press WASD to move • Click to fire
+
+ +
+ +
+ +
+
+

Spawn Controls

+
+ + + + + +
+
+ +
+

Player Status

+
+
+ Shield: + 0/0 +
+
+ Armor: + 0/0 +
+
+ Structure: + 0/0 +
+
+ Total HP: + 0/0 +
+
+ Enemies: + 0 +
+
+
+ +
+

Combat Stats & Debug

+
+ Shots/sec: + 0 +
+
+ Damage/sec: + 0 +
+
+
+ + +
+
+ + +
+
+ + +
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + From a4805a8b1aad3c8717ac3a8cb1a4c3978822f516 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 14 Feb 2026 20:22:01 +0000 Subject: [PATCH 06/17] Fix Combat Loop and System Wiring in Combat Dev Sandbox Co-authored-by: Linkatplug <36280686+Linkatplug@users.noreply.github.com> --- dev/test-combat-sandbox.html | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/dev/test-combat-sandbox.html b/dev/test-combat-sandbox.html index 5ef5fe0..b9b67d7 100644 --- a/dev/test-combat-sandbox.html +++ b/dev/test-combat-sandbox.html @@ -300,6 +300,10 @@

Combat Stats & Debug

// Initialize systems const gameState = new GameState(); + // Configure GameState minimally + gameState.isPaused = false; + gameState.isGameOver = false; + systems = { defense: new DefenseSystem(world), ai: new AISystem(world, canvas), @@ -317,6 +321,15 @@

Combat Stats & Debug

// Setup input setupInput(); + // Wrap DefenseSystem.applyDamage to track player damage + const originalApplyDamage = systems.defense.applyDamage.bind(systems.defense); + systems.defense.applyDamage = function(entity, damagePacket) { + if (entity === player) { + damageTaken += damagePacket.amount || damagePacket.damage || 0; + } + return originalApplyDamage(entity, damagePacket); + }; + // Start game loop running = true; requestAnimationFrame(gameLoop); @@ -380,6 +393,7 @@

Combat Stats & Debug

const playerComp = { speed: 250, level: 1, + weapons: [], // Empty weapons array for CombatSystem currentWeapon: { damageType: 'kinetic', damage: 10, @@ -498,6 +512,7 @@

Combat Stats & Debug

console.log('[Sandbox] Clearing all enemies'); const enemies = world.getEntitiesByType('enemy'); enemies.forEach(enemy => world.removeEntity(enemy.id)); + world.processPendingRemovals(); updateStats(); } @@ -512,6 +527,7 @@

Combat Stats & Debug

defense.armor.regenDelay = 0; defense.structure.regenDelay = 0; } + world.processPendingRemovals(); updateStats(); } @@ -643,12 +659,16 @@

Combat Stats & Debug

if (keys['d'] || keys['arrowright']) vel.vx = playerComp.speed; } - // Update systems + // Update systems (correct order) systems.movement.update(dt); systems.ai.update(dt); + systems.combat.update(dt); systems.defense.update(dt); systems.collision.update(dt); + // Process pending entity removals + world.processPendingRemovals(); + // Update projectile lifetimes const projectiles = world.getEntitiesByType('projectile'); projectiles.forEach(proj => { From b540b675ee1d5f7af325d315d6ef42e12e890fed Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 14 Feb 2026 20:35:03 +0000 Subject: [PATCH 07/17] Create Professional Combat Dev Sandbox with Real Game Architecture Co-authored-by: Linkatplug <36280686+Linkatplug@users.noreply.github.com> --- dev/combat-sandbox-pro.html | 804 ++++++++++++++++++++++++++++++++++++ 1 file changed, 804 insertions(+) create mode 100644 dev/combat-sandbox-pro.html diff --git a/dev/combat-sandbox-pro.html b/dev/combat-sandbox-pro.html new file mode 100644 index 0000000..19bbb71 --- /dev/null +++ b/dev/combat-sandbox-pro.html @@ -0,0 +1,804 @@ + + + + + + Combat Dev Sandbox - Professional + + + +
Combat Dev Sandbox - Professional
+ +
+ +
+ + +
+
+ + + + + + + + + +
+
+ +
+
+

System Toggles

+
+ AI System + +
+
+ Enemy Fire + +
+
+ Player Fire + +
+
+ Collision + +
+
+ Defense Update + +
+
+ Movement + +
+
+ +
+

Spawn Control

+ + + + + +
+ +
+

Runtime Modifiers

+
+
+ Player Damage + 1.0x +
+ +
+
+
+ Enemy Damage + 1.0x +
+ +
+
+
+ Enemy Fire Cooldown + 1.0x +
+ +
+
+ +
+

Live Stats

+
+ Total Enemies + 0 +
+
+ Damage/sec + 0 +
+
+ Shots/sec + 0 +
+
+
+ Shield: + 0/0 +
+
+ Armor: + 0/0 +
+
+ Structure: + 0/0 +
+
+ Total HP: + 0/0 +
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From eefb9eebf223b31656f7dcd7dd4c5c1cb227437a Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 14 Feb 2026 20:42:54 +0000 Subject: [PATCH 08/17] Disable UI and Audio systems in combat sandbox to prevent DOM crashes Co-authored-by: Linkatplug <36280686+Linkatplug@users.noreply.github.com> --- dev/combat-sandbox-pro.html | 40 +++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/dev/combat-sandbox-pro.html b/dev/combat-sandbox-pro.html index 19bbb71..9574540 100644 --- a/dev/combat-sandbox-pro.html +++ b/dev/combat-sandbox-pro.html @@ -463,6 +463,46 @@

Live Stats

// Create game instance game = new Game(); + // Disable UI and Audio initialization methods BEFORE startGame + console.log('[DevSandbox] Disabling UI and Audio systems...'); + + // Override methods that touch DOM elements + game.setupUIListeners = function() { + console.log('[DevSandbox] UI listeners disabled'); + }; + + // Replace UI system with stub that does nothing + game.systems.ui = { + showScreen: () => {}, + showWaveAnnouncement: () => {}, + showLevelUp: () => {}, + showGameOver: () => {}, + showPauseMenu: () => {}, + hidePauseMenu: () => {}, + showScoreboard: () => {}, + hideScoreboard: () => {}, + showNameEntryDialog: () => {}, + hideNameEntryDialog: () => {}, + updateHUD: () => {}, + update: () => {}, + waveSystem: null + }; + + // Disable audio initialization + const originalAudioManager = game.audioManager; + game.audioManager = { + playSound: () => {}, + playMusic: () => {}, + stopMusic: () => {}, + setMusicVolume: () => {}, + setSFXVolume: () => {}, + playWaveStart: () => {}, + playLevelUp: () => {}, + playGameOver: () => {}, + startBackgroundMusic: () => {}, + stopBackgroundMusic: () => {} + }; + // Store original update method originalUpdate = game.update.bind(game); From fb2e06fadd866234280d8dd1664501966c98502b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 14 Feb 2026 20:50:38 +0000 Subject: [PATCH 09/17] Clean up combat sandbox to use real damage pipeline Co-authored-by: Linkatplug <36280686+Linkatplug@users.noreply.github.com> --- dev/combat-sandbox-pro.html | 45 +++---------------------------------- 1 file changed, 3 insertions(+), 42 deletions(-) diff --git a/dev/combat-sandbox-pro.html b/dev/combat-sandbox-pro.html index 9574540..190d218 100644 --- a/dev/combat-sandbox-pro.html +++ b/dev/combat-sandbox-pro.html @@ -489,16 +489,13 @@

Live Stats

}; // Disable audio initialization - const originalAudioManager = game.audioManager; game.audioManager = { + init: () => {}, playSound: () => {}, playMusic: () => {}, stopMusic: () => {}, - setMusicVolume: () => {}, - setSFXVolume: () => {}, - playWaveStart: () => {}, - playLevelUp: () => {}, - playGameOver: () => {}, + stopAll: () => {}, + setVolume: () => {}, startBackgroundMusic: () => {}, stopBackgroundMusic: () => {} }; @@ -581,45 +578,9 @@

Live Stats

console.log('[DevSandbox] Game started in dev mode'); console.log('[DevSandbox] Player:', game.player); console.log('[DevSandbox] Systems:', game.systems); - - // Setup damage tracking - setupDamageTracking(); }, 100); } - // Setup damage tracking wrapper - function setupDamageTracking() { - if (!game || !game.systems.defense) return; - - const originalApplyDamage = game.systems.defense.applyDamage.bind(game.systems.defense); - - game.systems.defense.applyDamage = function(entity, damagePacket) { - // Track player damage - if (entity === game.player) { - const amount = damagePacket.amount || damagePacket.damage || 0; - statsTracking.damageTaken += amount * modifiers.enemyDamage; - } - - // Apply enemy damage modifier - if (entity.type === 'enemy') { - const modifiedPacket = {...damagePacket}; - if (modifiedPacket.amount) modifiedPacket.amount *= modifiers.playerDamage; - if (modifiedPacket.damage) modifiedPacket.damage *= modifiers.playerDamage; - return originalApplyDamage(entity, modifiedPacket); - } - - // Apply player damage modifier - if (entity === game.player) { - const modifiedPacket = {...damagePacket}; - if (modifiedPacket.amount) modifiedPacket.amount *= modifiers.enemyDamage; - if (modifiedPacket.damage) modifiedPacket.damage *= modifiers.enemyDamage; - return originalApplyDamage(entity, modifiedPacket); - } - - return originalApplyDamage(entity, damagePacket); - }; - } - // Toggle system on/off function toggleSystem(systemName) { const flagMap = { From fbea8a62cf0f9fff8869eacc95045321c30c1c96 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 14 Feb 2026 21:03:19 +0000 Subject: [PATCH 10/17] Create clean combat sandbox without Game class Co-authored-by: Linkatplug <36280686+Linkatplug@users.noreply.github.com> --- dev/combat-sandbox-clean.html | 563 ++++++++++++++++++++++++++++++++++ 1 file changed, 563 insertions(+) create mode 100644 dev/combat-sandbox-clean.html diff --git a/dev/combat-sandbox-clean.html b/dev/combat-sandbox-clean.html new file mode 100644 index 0000000..42f1426 --- /dev/null +++ b/dev/combat-sandbox-clean.html @@ -0,0 +1,563 @@ + + + + + + Combat Sandbox - Clean (No Game Class) + + + + + +
+
+

System Toggles

+
+ Movement + +
+
+ AI + +
+
+ Combat + +
+
+ Defense + +
+
+ Collision + +
+
+ +
+

Spawn Control

+ + + + + +
+ +
+

Live Stats

+
+ Total Enemies: + 0 +
+
+ Shield: + 0/0 +
+
+ Armor: + 0/0 +
+
+ Structure: + 0/0 +
+
+ Total HP: + 0/0 +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + From 699cf7c9d610b4fce4e28bebc7285b27d38e2037 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 14 Feb 2026 21:09:20 +0000 Subject: [PATCH 11/17] Fix combat-sandbox-clean.html dependencies and script loading order Co-authored-by: Linkatplug <36280686+Linkatplug@users.noreply.github.com> --- dev/combat-sandbox-clean.html | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/dev/combat-sandbox-clean.html b/dev/combat-sandbox-clean.html index 42f1426..53be44d 100644 --- a/dev/combat-sandbox-clean.html +++ b/dev/combat-sandbox-clean.html @@ -172,16 +172,15 @@

Live Stats

+ + + + - - - - - @@ -195,6 +194,12 @@

Live Stats

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From d324fd1f78f09efe4a10bd67df8a9221f1eeb7cf Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 14 Feb 2026 22:09:27 +0000 Subject: [PATCH 17/17] Add position validation guard to prevent NaN distance calculations in combat sandbox Co-authored-by: Linkatplug <36280686+Linkatplug@users.noreply.github.com> --- dev/combat-sandbox.html | 45 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/dev/combat-sandbox.html b/dev/combat-sandbox.html index 08c69a9..f7ce4fb 100644 --- a/dev/combat-sandbox.html +++ b/dev/combat-sandbox.html @@ -287,6 +287,51 @@

Info

console.log('[Combat Sandbox] World:', game.world); console.log('[Combat Sandbox] Systems:', game.systems); + // Add position validation guard to prevent NaN calculations + if (game.systems.combat) { + console.log('[Combat Sandbox] Adding position validation guard to CombatSystem'); + + // Helper function to validate entity position + function hasValidPosition(entity) { + if (!entity) return false; + const pos = entity.getComponent('position'); + if (!pos) return false; + if (typeof pos.x !== 'number' || typeof pos.y !== 'number') return false; + if (isNaN(pos.x) || isNaN(pos.y)) return false; + return true; + } + + // Save original update method + const originalCombatUpdate = game.systems.combat.update.bind(game.systems.combat); + + // Override with validation wrapper + game.systems.combat.update = function(deltaTime) { + // Validate player position + const players = game.world.getEntitiesByType('player'); + if (players.length > 0) { + const player = players[0]; + if (!hasValidPosition(player)) { + console.warn('[Sandbox] Invalid position detected on player entity', player.id); + return; // Skip combat update this frame + } + } + + // Validate all enemy positions + const enemies = game.world.getEntitiesByType('enemy'); + for (const enemy of enemies) { + if (!hasValidPosition(enemy)) { + console.warn('[Sandbox] Invalid position detected on enemy entity', enemy.id); + // Remove this enemy to prevent future errors + game.world.removeEntity(enemy.id); + continue; + } + } + + // All positions valid, call original update + originalCombatUpdate(deltaTime); + }; + } + // Start stats update loop setInterval(updateStats, 100); }