2017-02-09 00:00:35 +00:00
|
|
|
module TS.SpaceTac {
|
2017-02-06 21:46:55 +00:00
|
|
|
/**
|
|
|
|
* Drones are static objects that apply effects in a circular zone around themselves.
|
|
|
|
*/
|
2017-02-07 18:54:53 +00:00
|
|
|
export class Drone {
|
2017-05-10 22:52:16 +00:00
|
|
|
// Battle in which the drone is deployed
|
|
|
|
battle: Battle;
|
2017-02-08 18:54:02 +00:00
|
|
|
|
2017-05-10 22:52:16 +00:00
|
|
|
// Ship that launched the drone (informative, a drone is autonomous)
|
2017-02-06 21:46:55 +00:00
|
|
|
owner: Ship;
|
|
|
|
|
2017-05-10 22:52:16 +00:00
|
|
|
// Code of the drone
|
|
|
|
code: string;
|
|
|
|
|
2017-02-06 21:46:55 +00:00
|
|
|
// Location in arena
|
|
|
|
x: number;
|
|
|
|
y: number;
|
|
|
|
radius: number;
|
|
|
|
|
2017-05-10 22:52:16 +00:00
|
|
|
// Remaining lifetime in number of turns
|
|
|
|
duration: number;
|
2017-02-06 21:46:55 +00:00
|
|
|
|
|
|
|
// Effects to apply
|
|
|
|
effects: BaseEffect[] = [];
|
|
|
|
|
2017-05-10 22:52:16 +00:00
|
|
|
// Cycle countdown for ships
|
|
|
|
countdown: [Ship, number][] = [];
|
2017-02-06 21:46:55 +00:00
|
|
|
|
2017-05-10 22:52:16 +00:00
|
|
|
constructor(owner: Ship, code = "drone", base_duration = 1) {
|
|
|
|
this.battle = owner.getBattle() || new Battle();
|
2017-02-06 21:46:55 +00:00
|
|
|
this.owner = owner;
|
2017-02-08 18:54:02 +00:00
|
|
|
this.code = code;
|
2017-05-10 22:52:16 +00:00
|
|
|
this.duration = base_duration * this.battle.getCycleLength();
|
2017-02-06 21:46:55 +00:00
|
|
|
}
|
|
|
|
|
2017-05-10 17:48:28 +00:00
|
|
|
/**
|
|
|
|
* Get a textual description of this drone
|
|
|
|
*/
|
|
|
|
getDescription(): string {
|
|
|
|
let effects = this.effects.map(effect => "• " + effect.getDescription()).join("\n");
|
|
|
|
if (effects.length == 0) {
|
|
|
|
effects = "• do nothing";
|
|
|
|
}
|
2017-05-10 22:52:16 +00:00
|
|
|
return `For ${this.duration} activation${this.duration > 1 ? "s" : ""}:\n${effects}`;
|
2017-05-10 17:48:28 +00:00
|
|
|
}
|
|
|
|
|
2017-02-06 21:46:55 +00:00
|
|
|
/**
|
2017-05-10 22:52:16 +00:00
|
|
|
* Get countdown until next activation for a given ship
|
2017-02-06 21:46:55 +00:00
|
|
|
*/
|
2017-05-10 22:52:16 +00:00
|
|
|
getShipCountdown(ship: Ship): number {
|
|
|
|
let countdown = 0;
|
|
|
|
this.countdown.forEach(([iship, icountdown]) => {
|
|
|
|
if (iship === ship) {
|
|
|
|
countdown = icountdown;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
return countdown;
|
2017-02-06 21:46:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2017-05-10 22:52:16 +00:00
|
|
|
* Start the countdown for a given ship
|
2017-02-06 21:46:55 +00:00
|
|
|
*/
|
2017-05-10 22:52:16 +00:00
|
|
|
startShipCountdown(ship: Ship): void {
|
|
|
|
let found = false;
|
|
|
|
this.countdown = this.countdown.map(([iship, countdown]): [Ship, number] => {
|
|
|
|
if (iship === ship) {
|
|
|
|
found = true;
|
|
|
|
return [iship, this.battle.getCycleLength()];
|
|
|
|
} else {
|
|
|
|
return [iship, countdown];
|
2017-02-15 21:15:31 +00:00
|
|
|
}
|
2017-05-10 22:52:16 +00:00
|
|
|
});
|
|
|
|
if (!found) {
|
|
|
|
this.countdown.push([ship, this.battle.getCycleLength()]);
|
2017-02-15 21:15:31 +00:00
|
|
|
}
|
2017-02-06 21:46:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2017-05-10 22:52:16 +00:00
|
|
|
* Get the list of affected ships.
|
2017-02-06 21:46:55 +00:00
|
|
|
*/
|
2017-05-10 22:52:16 +00:00
|
|
|
getAffectedShips(): Ship[] {
|
|
|
|
let ships = ifilter(this.battle.iships(), ship => ship.alive && ship.isInCircle(this.x, this.y, this.radius) && this.getShipCountdown(ship) == 0);
|
|
|
|
return imaterialize(ships);
|
2017-02-06 21:46:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2017-05-10 22:52:16 +00:00
|
|
|
* Apply the effects on a list of ships
|
|
|
|
*
|
|
|
|
* This does not check if the ships are in range.
|
2017-02-06 21:46:55 +00:00
|
|
|
*/
|
2017-05-10 22:52:16 +00:00
|
|
|
apply(ships: Ship[], log = true) {
|
|
|
|
if (ships.length > 0) {
|
|
|
|
if (log) {
|
|
|
|
this.battle.log.add(new DroneAppliedEvent(this, ships));
|
2017-02-06 21:46:55 +00:00
|
|
|
}
|
|
|
|
|
2017-05-10 22:52:16 +00:00
|
|
|
ships.forEach(ship => {
|
|
|
|
this.startShipCountdown(ship);
|
|
|
|
this.effects.forEach(effect => effect.applyOnShip(ship));
|
|
|
|
});
|
2017-02-06 21:46:55 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2017-05-10 22:52:16 +00:00
|
|
|
* Activate the drone
|
2017-02-06 21:46:55 +00:00
|
|
|
*/
|
2017-05-10 22:52:16 +00:00
|
|
|
activate(log = true) {
|
|
|
|
this.apply(this.getAffectedShips(), log);
|
2017-02-06 21:46:55 +00:00
|
|
|
|
2017-05-10 22:52:16 +00:00
|
|
|
this.countdown = this.countdown.map(([ship, countdown]): [Ship, number] => [ship, countdown - 1]).filter(([ship, countdown]) => countdown > 0);
|
|
|
|
|
|
|
|
this.duration--;
|
|
|
|
if (this.duration == 0) {
|
|
|
|
this.battle.removeDrone(this, log);
|
2017-02-06 21:46:55 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|