2017-09-24 22:23:22 +00:00
|
|
|
module TK.SpaceTac {
|
2017-02-06 21:46:55 +00:00
|
|
|
/**
|
|
|
|
* Drones are static objects that apply effects in a circular zone around themselves.
|
|
|
|
*/
|
2017-11-14 00:07:06 +00:00
|
|
|
export class Drone extends RObject {
|
|
|
|
// ID of the owning ship
|
|
|
|
owner: RObjectId
|
2017-02-06 21:46:55 +00:00
|
|
|
|
2017-05-10 22:52:16 +00:00
|
|
|
// Code of the drone
|
2017-11-14 00:07:06 +00:00
|
|
|
code: string
|
2017-05-10 22:52:16 +00:00
|
|
|
|
2017-02-06 21:46:55 +00:00
|
|
|
// Location in arena
|
2017-11-14 00:07:06 +00:00
|
|
|
x: number
|
|
|
|
y: number
|
|
|
|
radius: number
|
2017-02-06 21:46:55 +00:00
|
|
|
|
2017-05-10 22:52:16 +00:00
|
|
|
// Remaining lifetime in number of turns
|
2017-11-14 00:07:06 +00:00
|
|
|
duration: number
|
2017-02-06 21:46:55 +00:00
|
|
|
|
|
|
|
// Effects to apply
|
2017-11-14 00:07:06 +00:00
|
|
|
effects: BaseEffect[] = []
|
2017-02-06 21:46:55 +00:00
|
|
|
|
2017-05-10 22:52:16 +00:00
|
|
|
constructor(owner: Ship, code = "drone", base_duration = 1) {
|
2017-11-14 00:07:06 +00:00
|
|
|
super();
|
|
|
|
|
|
|
|
this.owner = owner.id;
|
2017-02-08 18:54:02 +00:00
|
|
|
this.code = code;
|
2017-05-22 23:00:02 +00:00
|
|
|
this.duration = base_duration;
|
2017-02-06 21:46:55 +00:00
|
|
|
}
|
|
|
|
|
2017-08-17 17:51:22 +00:00
|
|
|
/**
|
|
|
|
* Return the current location of the drone
|
|
|
|
*/
|
|
|
|
get location(): ArenaLocation {
|
|
|
|
return new ArenaLocation(this.x, this.y);
|
|
|
|
}
|
|
|
|
|
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-06-12 22:28:54 +00:00
|
|
|
/**
|
|
|
|
* Check if a location is in range
|
|
|
|
*/
|
|
|
|
isInRange(x: number, y: number): boolean {
|
|
|
|
return Target.newFromLocation(x, y).getDistanceTo(this) <= this.radius;
|
|
|
|
}
|
|
|
|
|
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-11-14 00:07:06 +00:00
|
|
|
getAffectedShips(battle: Battle): Ship[] {
|
|
|
|
let ships = ifilter(battle.iships(), ship => ship.alive && ship.isInCircle(this.x, this.y, this.radius));
|
2017-05-10 22:52:16 +00:00
|
|
|
return imaterialize(ships);
|
2017-02-06 21:46:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2017-11-14 00:07:06 +00:00
|
|
|
* Get the list of diffs needed to apply the drone effects on a list of ships.
|
2017-05-10 22:52:16 +00:00
|
|
|
*
|
|
|
|
* This does not check if the ships are in range.
|
2017-02-06 21:46:55 +00:00
|
|
|
*/
|
2017-11-14 00:07:06 +00:00
|
|
|
getDiffs(battle: Battle, ships: Ship[]): BaseBattleDiff[] {
|
|
|
|
let result: BaseBattleDiff[] = [];
|
|
|
|
|
|
|
|
if (this.duration >= 1 && ships.length > 0) {
|
|
|
|
result.push(new DroneAppliedDiff(this, ships));
|
2017-02-06 21:46:55 +00:00
|
|
|
|
2017-05-10 22:52:16 +00:00
|
|
|
ships.forEach(ship => {
|
2017-11-14 00:07:06 +00:00
|
|
|
result = result.concat(flatten(this.effects.map(effect => effect.getOnDiffs(ship, this))));
|
2017-05-10 22:52:16 +00:00
|
|
|
});
|
2017-02-06 21:46:55 +00:00
|
|
|
}
|
2017-11-14 00:07:06 +00:00
|
|
|
|
|
|
|
if (this.duration <= 1) {
|
|
|
|
result.push(new DroneDestroyedDiff(this));
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
2017-02-06 21:46:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2017-11-14 00:07:06 +00:00
|
|
|
* Apply one drone "activation"
|
2017-02-06 21:46:55 +00:00
|
|
|
*/
|
2017-11-14 00:07:06 +00:00
|
|
|
activate(battle: Battle) {
|
|
|
|
let diffs = this.getDiffs(battle, this.getAffectedShips(battle));
|
|
|
|
battle.applyDiffs(diffs);
|
2017-02-06 21:46:55 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|