Enable pirate friendly fire

This commit is contained in:
Admin 2026-09-20 07:54:25 +00:00
parent b0b88f432c
commit aff9f3f276
2 changed files with 24 additions and 3 deletions

View File

@ -120,6 +120,7 @@ class GameScene extends Phaser.Scene {
this.createEnvironmentPhysics(); this.createEnvironmentPhysics();
this.physics.add.overlap(this.playerShots, this.pirates, this.hitPirate, null, this); this.physics.add.overlap(this.playerShots, this.pirates, this.hitPirate, null, this);
this.physics.add.overlap(this.pirateShots, this.pirates, this.hitPirate, null, this);
this.physics.add.overlap(this.pirateShots, this.player, this.hitPlayer, null, this); this.physics.add.overlap(this.pirateShots, this.player, this.hitPlayer, null, this);
registerDebugSnapshot(() => ({ registerDebugSnapshot(() => ({
@ -798,6 +799,7 @@ class GameScene extends Phaser.Scene {
shot.setData('bornAt', this.time.now); shot.setData('bornAt', this.time.now);
shot.setData('damage', projectileDamage); shot.setData('damage', projectileDamage);
shot.setData('projectileOwner', actor); shot.setData('projectileOwner', actor);
shot.setData('sourceShip', ship);
if (actor === 'pirate') shot.setData('playerHitQueued', false); if (actor === 'pirate') shot.setData('playerHitQueued', false);
const shotWind = environmentWindAt({ const shotWind = environmentWindAt({
x, x,
@ -817,10 +819,16 @@ class GameScene extends Phaser.Scene {
hitPirate(first, second) { hitPirate(first, second) {
if (this.gameState !== 'playing') return; if (this.gameState !== 'playing') return;
const shot = resolveTaggedProjectile(first, second, 'player'); const playerShot = resolveTaggedProjectile(first, second, 'player');
const pirateShot = playerShot ? null : resolveTaggedProjectile(first, second, 'pirate');
const shot = playerShot || pirateShot;
const pirate = shot === first ? second : first; const pirate = shot === first ? second : first;
if (!shot?.active || !pirate?.active || pirate === this.player) return; if (!shot?.active || !pirate?.active || pirate === this.player) return;
const projectileOwner = shot.getData('projectileOwner');
const sourceShip = shot.getData('sourceShip');
if (projectileOwner === 'pirate' && sourceShip === pirate) return;
const damage = shot.getData('damage') || 10; const damage = shot.getData('damage') || 10;
const { x, y } = shot; const { x, y } = shot;
shot.destroy(); shot.destroy();
@ -834,12 +842,14 @@ class GameScene extends Phaser.Scene {
damage, damage,
hullBefore: previousHull, hullBefore: previousHull,
hullAfter: hull, hullAfter: hull,
projectileOwner,
friendlyFire: projectileOwner === 'pirate',
}); });
if (hull <= 0) { if (hull <= 0) {
this.spawnExplosion(pirate.x, pirate.y, 1.25); this.spawnExplosion(pirate.x, pirate.y, 1.25);
pirate.destroy(); pirate.destroy();
this.defeated += 1; if (projectileOwner === 'player') this.defeated += 1;
if (this.pirates.countActive(true) === 0) { if (this.pirates.countActive(true) === 0) {
this.wave += 1; this.wave += 1;
@ -852,7 +862,7 @@ class GameScene extends Phaser.Scene {
return; return;
} }
this.flashShip(pirate, 0xffcccc); this.flashShip(pirate, projectileOwner === 'pirate' ? 0xffd29a : 0xffcccc);
} }
hitPlayer(first, second) { hitPlayer(first, second) {

View File

@ -194,6 +194,17 @@ test('player and pirate broadsides use the cannonball image asset', async () =>
assert.doesNotMatch(source, /generateTexture\('pirate-shot'/); assert.doesNotMatch(source, /generateTexture\('pirate-shot'/);
}); });
test('pirate cannonballs damage other pirates but ignore their source ship', async () => {
const source = await read('src/game-v4.js');
assert.match(source, /this\.physics\.add\.overlap\(this\.pirateShots, this\.pirates, this\.hitPirate/);
assert.match(source, /shot\.setData\('sourceShip', ship\)/);
assert.match(source, /const pirateShot = playerShot \? null : resolveTaggedProjectile\(first, second, 'pirate'\)/);
assert.match(source, /if \(projectileOwner === 'pirate' && sourceShip === pirate\) return/);
assert.match(source, /friendlyFire: projectileOwner === 'pirate'/);
assert.match(source, /if \(projectileOwner === 'player'\) this\.defeated \+= 1/);
});
test('player uses the four-frame north-facing sheet as a forward propulsion animation', async () => { test('player uses the four-frame north-facing sheet as a forward propulsion animation', async () => {
const source = await read('src/game-v4.js'); const source = await read('src/game-v4.js');