106 lines
2.8 KiB
TypeScript
106 lines
2.8 KiB
TypeScript
/// <reference path="Serializable.ts"/>
|
|
|
|
module TS.SpaceTac.Game {
|
|
/**
|
|
* Drones are static objects that apply effects in a circular zone around themselves.
|
|
*/
|
|
export class Drone extends Serializable {
|
|
// Ship that deployed the drone
|
|
owner: Ship;
|
|
|
|
// Location in arena
|
|
x: number;
|
|
y: number;
|
|
radius: number;
|
|
|
|
// Lifetime in number of turns (not including the initial effect on deployment)
|
|
duration: number = 1;
|
|
|
|
// Effects to apply
|
|
effects: BaseEffect[] = [];
|
|
|
|
// Ships registered inside the radius
|
|
inside: Ship[] = [];
|
|
|
|
// Ships starting their turn the radius
|
|
inside_at_start: Ship[] = [];
|
|
|
|
constructor(owner: Ship) {
|
|
super();
|
|
|
|
this.owner = owner;
|
|
}
|
|
|
|
/**
|
|
* Call a function for each ship in radius.
|
|
*/
|
|
forEachInRadius(ships: Ship[], callback: (ship: Ship) => any) {
|
|
ships.forEach(ship => {
|
|
if (ship.isInCircle(this.x, this.y, this.radius)) {
|
|
callback(ship);
|
|
}
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Apply the effects on a single ship.
|
|
*
|
|
* This does not check if the ship is in range.
|
|
*/
|
|
singleApply(ship: Ship) {
|
|
this.effects.forEach(effect => effect.applyOnShip(ship));
|
|
}
|
|
|
|
/**
|
|
* Called when the drone is first deployed.
|
|
*/
|
|
onDeploy(ships: Ship[]) {
|
|
this.forEachInRadius(ships, ship => this.singleApply(ship));
|
|
}
|
|
|
|
/**
|
|
* Called when a ship turn starts
|
|
*
|
|
* Returns false if the drone should be destroyed
|
|
*/
|
|
onTurnStart(ship: Ship): boolean {
|
|
if (ship == this.owner) {
|
|
if (this.duration <= 1) {
|
|
return false;
|
|
} else {
|
|
this.duration--;
|
|
}
|
|
}
|
|
|
|
if (ship.isInCircle(this.x, this.y, this.radius)) {
|
|
add(this.inside, ship);
|
|
add(this.inside_at_start, ship);
|
|
} else {
|
|
remove(this.inside_at_start, ship);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Called when a ship turn ends
|
|
*/
|
|
onTurnEnd(ship: Ship) {
|
|
if (ship.isInCircle(this.x, this.y, this.radius) && contains(this.inside_at_start, ship)) {
|
|
this.singleApply(ship);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Called after a ship moved
|
|
*/
|
|
onShipMove(ship: Ship) {
|
|
if (ship.isInCircle(this.x, this.y, this.radius)) {
|
|
if (add(this.inside, ship)) {
|
|
this.singleApply(ship);
|
|
}
|
|
} else {
|
|
remove(this.inside, ship);
|
|
}
|
|
}
|
|
}
|
|
} |