61 lines
2.1 KiB
JavaScript
61 lines
2.1 KiB
JavaScript
/**
|
|
* Combat rules — the pure arithmetic shared by the sandbox's actors
|
|
* (the player's armor, the enemy craft, and whatever system ports out of
|
|
* the range into the real game). No Phaser, no scene, so it runs in bare
|
|
* Node: dev/combat.test.mjs exercises exactly this file.
|
|
*
|
|
* An armor block is `{ shields, hull }` (both ≥ 0): a hit spends the
|
|
* shields first, then the hull, and the craft is dead at hull ≤ 0 — the
|
|
* same rule for the player (data/combat.json → playerShip) and the
|
|
* hostiles (→ enemy).
|
|
*/
|
|
|
|
/**
|
|
* Spend damage off an armor block (mutates it).
|
|
*
|
|
* @param {{shields: number, hull: number}} armor the block to hit
|
|
* @param {number} amount damage (negative/NaN treated as 0)
|
|
* @returns {{shieldHit: number, hullHit: number, dead: boolean}}
|
|
* shieldHit/hullHit = how much each layer absorbed; dead = hull ≤ 0.
|
|
*/
|
|
export function applyDamage(armor, amount) {
|
|
let rem = Math.max(0, Number(amount) || 0);
|
|
|
|
const shields = Math.max(0, armor.shields ?? 0);
|
|
const shieldHit = Math.min(shields, rem);
|
|
rem -= shieldHit;
|
|
|
|
const hull = Math.max(0, armor.hull ?? 0);
|
|
const hullHit = Math.min(hull, rem);
|
|
rem -= hullHit;
|
|
|
|
armor.shields = shields - shieldHit;
|
|
armor.hull = hull - hullHit;
|
|
return { shieldHit, hullHit, dead: armor.hull <= 0 };
|
|
}
|
|
|
|
/**
|
|
* The render heading (rad) of a ship sprite: its rotation minus the
|
|
* art's facing offset (ship.artOffset — the sheet art may not face east,
|
|
* js/entities/Ship.js). A plain object with a .rotation is fine.
|
|
*/
|
|
export function headingOf(ship) {
|
|
return ship.rotation - (ship.artOffset || 0);
|
|
}
|
|
|
|
/**
|
|
* One step of the standoff-ring AI: advance the craft's orbit angle and
|
|
* return the point on the ring it should steer to (pure — the craft
|
|
* does the steering, js/combat/EnemyShip.js).
|
|
*
|
|
* @returns {{angle: number, x: number, y: number}} the new orbit angle + target
|
|
*/
|
|
export function orbitStep(px, py, orbitAngle, orbitDir, orbitSpeed, dt, orbitRadius) {
|
|
const angle = orbitAngle + orbitDir * orbitSpeed * dt;
|
|
return {
|
|
angle,
|
|
x: px + Math.cos(angle) * orbitRadius,
|
|
y: py + Math.sin(angle) * orbitRadius,
|
|
};
|
|
}
|