61 lines
2.9 KiB
JavaScript
61 lines
2.9 KiB
JavaScript
import { NeutralShip } from './NeutralShip.js';
|
||
|
||
/**
|
||
* The ESCORT CONTRACT's transport (data/combat.json → transport — the
|
||
* neutral freighter from assets/images/ships-transport.png): a PERSISTENT
|
||
* player-side craft the player rendevouses with at a local waypoint and
|
||
* leads through the jump gates to a planet / space station (js/scenes/
|
||
* GameScene.js → the escort's updateEscort).
|
||
*
|
||
* It rides the NeutralShip's escort/engage AI verbatim (hold the ring
|
||
* around the player, fight the NEAREST pirate up with its own volley,
|
||
* never aim at the player — js/combat/NeutralShip.js) with ONE difference
|
||
* that makes it a convoy member instead of a passing escort: the break-off
|
||
* window is lapsed (escortMs = Infinity), so it never peels off. It stays
|
||
* for the life of the contract — the contract's reset (GameScene's
|
||
* landing hook) is what ends it, not the escort clock.
|
||
*
|
||
* PLAYER-SAFE BY CONSTRUCTION (inherited): the target pool is the enemy
|
||
* roster, the collide passes never route an 'ally' bolt into the player,
|
||
* and the player's auto-fire never targets this roster.
|
||
*
|
||
* THE PERSISTENT FLAG (`persistent = true`) is the seam the CombatSystem
|
||
* reads (its `active` + `_neutralOnly` gates skip a persistent ally): a
|
||
* standing convoy must NOT hold the jump gate open or keep the
|
||
* encounter's "active" flag up — the fight is over the moment the last
|
||
* pirate is down, even with the convoy still flying.
|
||
*
|
||
* ART + SCALE: the transport sheet is 180×320 with the art facing north
|
||
* (the LONG side is the ship's length). EnemyShip's scale rule assumes a
|
||
* square sheet (scale = size / frameWidth) — wrong for a portrait
|
||
* freighter. So `size` (data → transport.size, 135) reads as the hull's
|
||
* WORLD LENGTH: ~2.5× a fighter's 54. We re-scale by the sheet's long
|
||
* side (320) and re-anchor the hit circle to the new scale.
|
||
*/
|
||
export class TransportShip extends NeutralShip {
|
||
/**
|
||
* @param {object} scene the combat scene
|
||
* @param {number} x spawn
|
||
* @param {number} y spawn
|
||
* @param {number} index slot (orbit direction alternates)
|
||
* @param {object} [c] the transport's FULL config (data → transport)
|
||
* @param {object} [o] NeutralShip's options (escortMs is lapsed below)
|
||
*/
|
||
constructor(scene, x, y, index, c = null, o = {}) {
|
||
// The break-off window is lapsed (Infinity) — a convoy member stays.
|
||
super(scene, x, y, index, c, { ...o, escortMs: Number.POSITIVE_INFINITY });
|
||
this.persistent = true; // CombatSystem's active/neutralOnly gates skip this
|
||
this.isTransport = true;
|
||
|
||
// Portrait-sheet re-scale (see the class doc): size = world length.
|
||
const fw = Number(c?.frameWidth) || 128;
|
||
const fh = Number(c?.frameHeight) || 128;
|
||
const longSide = Math.max(fw, fh);
|
||
const size = Number(this.size) || 54;
|
||
const s = size / longSide;
|
||
this.setScale(s);
|
||
const body = this.body;
|
||
if (body && typeof body.setCircle === 'function') body.setCircle(this.hitRadius / s);
|
||
}
|
||
}
|