module TK.SpaceTac { // Target for a capability // This could be a location in space, or a ship export class Target { // Coordinates of the target x: number y: number // If the target is a ship, this attribute will be set ship_id: RObjectId | null // Standard constructor constructor(x: number, y: number, ship: Ship | RObjectId | null = null) { this.x = x; this.y = y; this.ship_id = (ship === null) ? null : rid(ship); } jasmineToString() { if (this.ship_id) { return `(${this.x},${this.y}) ship_id=${this.ship_id}}`; } else { return `(${this.x},${this.y})`; } } // Constructor to target a single ship static newFromShip(ship: Ship): Target { return new Target(ship.arena_x, ship.arena_y, ship); } // Constructor to target a location in space static newFromLocation(x: number, y: number): Target { return new Target(x, y, null); } /** * Snap to battle grid */ snap(grid: ArenaGrid): Target { let location = grid.snap(this); return new Target(location.x, location.y, this.ship_id); } // Get distance to another target getDistanceTo(other: { x: number, y: number }): number { var dx = other.x - this.x; var dy = other.y - this.y; return Math.sqrt(dx * dx + dy * dy); } // Get the normalized angle, in radians, to another target getAngleTo(other: { x: number, y: number }): number { var dx = other.x - this.x; var dy = other.y - this.y; return Math.atan2(dy, dx); } /** * Returns true if the target is a ship * * If a ship or ship id is passed, also check that it is the targetted one */ isShip(ship?: Ship | RObject): boolean { return this.ship_id !== null && (typeof ship == "undefined" || rid(ship) == this.ship_id); } /** * Get the targetted ship in a battle */ getShip(battle: Battle): Ship | null { if (this.isShip()) { return battle.getShip(this.ship_id); } else { return null; } } } }