orbit/js/combat/TransportShip.js

61 lines
2.9 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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);
}
}