Simplified drones behavior
This commit is contained in:
parent
d1f1c1281d
commit
5d4315f1ca
14
README.md
14
README.md
|
@ -96,18 +96,14 @@ item is then temporarily disabled (no more effects and cannot be used), until th
|
|||
## Drones
|
||||
|
||||
Drones are static objects, deployed by ships, that apply effects in a circular zone around themselves.
|
||||
|
||||
Drone effects are applied :
|
||||
|
||||
* On all ships in the zone at the time the drone is deployed
|
||||
* On any ship entering the zone
|
||||
* On any ship inside the zone at the start and end of its turn (there and staying there)
|
||||
A drone lasts for a given number of battle cycles. For example, if there are 8 ships in play, a 2-cycles
|
||||
drone will try to activate 16 times, before being destroyed.
|
||||
|
||||
All drones activate between two ship turns. At each activation, the drone effects are applied to any ship
|
||||
in the surrounding zone, except if less than a battle cycle passed since last activation for this ship.
|
||||
|
||||
Drones are fully autonomous, and once deployed, are not controlled by their owner ship.
|
||||
|
||||
They are small and cannot be the direct target of weapons. They are not affected by area effects,
|
||||
except for area damage and area effects specifically designed for drones.
|
||||
|
||||
A drone lasts for a given number of turns, counting down each time its owner's turn starts.
|
||||
When reaching the number of turns, the drone is destroyed (before the owner's turn is started).
|
||||
For example, a drone with 1-turn duration will destroy just before the next turn of its owner.
|
||||
|
|
|
@ -252,7 +252,6 @@ module TS.SpaceTac {
|
|||
let battle = new Battle();
|
||||
let ship = new Ship();
|
||||
let drone = new Drone(ship);
|
||||
let onDeploy = spyOn(drone, "onDeploy");
|
||||
|
||||
expect(battle.drones).toEqual([]);
|
||||
expect(battle.log.events).toEqual([]);
|
||||
|
@ -261,13 +260,11 @@ module TS.SpaceTac {
|
|||
|
||||
expect(battle.drones).toEqual([drone]);
|
||||
expect(battle.log.events).toEqual([new DroneDeployedEvent(drone)]);
|
||||
expect(onDeploy).toHaveBeenCalledTimes(1);
|
||||
|
||||
battle.addDrone(drone);
|
||||
|
||||
expect(battle.drones).toEqual([drone]);
|
||||
expect(battle.log.events).toEqual([new DroneDeployedEvent(drone)]);
|
||||
expect(onDeploy).toHaveBeenCalledTimes(1);
|
||||
|
||||
battle.removeDrone(drone);
|
||||
|
||||
|
|
|
@ -61,6 +61,13 @@ module TS.SpaceTac {
|
|||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of turns in a game cycle.
|
||||
*/
|
||||
getCycleLength(): number {
|
||||
return this.play_order.length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an iterator over all ships engaged in the battle
|
||||
*/
|
||||
|
@ -178,13 +185,15 @@ module TS.SpaceTac {
|
|||
advanceToNextShip(log: boolean = true): void {
|
||||
var previous_ship = this.playing_ship;
|
||||
|
||||
if (this.playing_ship && this.playing_ship.playing) {
|
||||
this.playing_ship.endTurn();
|
||||
}
|
||||
|
||||
if (this.checkEndBattle(log)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.playing_ship && this.playing_ship.playing) {
|
||||
this.playing_ship.endTurn();
|
||||
}
|
||||
this.drones.forEach(drone => drone.activate());
|
||||
|
||||
if (this.play_order.length === 0) {
|
||||
this.playing_ship_index = null;
|
||||
|
@ -298,7 +307,6 @@ module TS.SpaceTac {
|
|||
if (log) {
|
||||
this.log.add(new DroneDeployedEvent(drone));
|
||||
}
|
||||
drone.onDeploy(this.play_order);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -34,94 +34,78 @@ module TS.SpaceTac {
|
|||
}
|
||||
|
||||
describe("Drone", function () {
|
||||
it("applies effects on deployment", function () {
|
||||
let ship1 = new Ship(null, "ship1");
|
||||
it("applies effects on all ships inside the radius", function () {
|
||||
let battle = new Battle();
|
||||
let ship1 = new Ship(battle.fleets[0], "ship1");
|
||||
ship1.setArenaPosition(0, 0);
|
||||
let ship2 = new Ship(null, "ship2");
|
||||
let ship2 = new Ship(battle.fleets[0], "ship2");
|
||||
ship2.setArenaPosition(5, 5);
|
||||
let ship3 = new Ship(null, "ship3");
|
||||
let ship3 = new Ship(battle.fleets[0], "ship3");
|
||||
ship3.setArenaPosition(10, 10);
|
||||
let ship4 = new Ship(battle.fleets[0], "ship4");
|
||||
ship4.setArenaPosition(0, 0);
|
||||
ship4.setDead();
|
||||
let [drone, effect] = newTestDrone(2, 2, 8, ship1);
|
||||
|
||||
expect(effect.getApplyCalls()).toEqual([]);
|
||||
|
||||
drone.onDeploy([ship1, ship2, ship3]);
|
||||
drone.activate();
|
||||
expect(effect.getApplyCalls()).toEqual([ship1, ship2]);
|
||||
});
|
||||
|
||||
it("applies effects on ships entering the radius", function () {
|
||||
let owner = new Ship(null, "owner");
|
||||
let target = new Ship(null, "target");
|
||||
target.setArenaPosition(10, 10);
|
||||
let [drone, effect] = newTestDrone(0, 0, 5, owner);
|
||||
it("maintains ship application countdown", function () {
|
||||
let battle = new Battle();
|
||||
spyOn(battle, "getCycleLength").and.returnValue(7);
|
||||
let ship = new Ship(battle.fleets[0]);
|
||||
let drone = new Drone(ship, "test", 2);
|
||||
|
||||
expect(effect.getApplyCalls()).toEqual([], "initial");
|
||||
|
||||
drone.onTurnStart(target);
|
||||
expect(effect.getApplyCalls()).toEqual([], "turn start");
|
||||
|
||||
target.setArenaPosition(2, 3);
|
||||
drone.onShipMove(target);
|
||||
expect(effect.getApplyCalls()).toEqual([target], "enter");
|
||||
|
||||
target.setArenaPosition(1, 1);
|
||||
drone.onShipMove(target);
|
||||
expect(effect.getApplyCalls()).toEqual([], "move inside");
|
||||
|
||||
target.setArenaPosition(12, 12);
|
||||
drone.onShipMove(target);
|
||||
expect(effect.getApplyCalls()).toEqual([], "exit");
|
||||
|
||||
target.setArenaPosition(1, 1);
|
||||
drone.onShipMove(target);
|
||||
expect(effect.getApplyCalls()).toEqual([target], "re-enter");
|
||||
expect(drone.getShipCountdown(ship)).toBe(0);
|
||||
drone.startShipCountdown(ship);
|
||||
expect(drone.getShipCountdown(ship)).toBe(7);
|
||||
});
|
||||
|
||||
it("applies effects on ships remaining in the radius", function () {
|
||||
let owner = new Ship(null, "owner");
|
||||
let target = new Ship(null, "target");
|
||||
let [drone, effect] = newTestDrone(0, 0, 5, owner);
|
||||
it("applies at most once per battle cycle", function () {
|
||||
let battle = new Battle();
|
||||
let ship1 = new Ship(battle.fleets[0], "ship1");
|
||||
ship1.setArenaPosition(0, 0);
|
||||
let ship2 = new Ship(battle.fleets[1], "ship2");
|
||||
ship2.setArenaPosition(100, 100);
|
||||
battle.throwInitiative();
|
||||
expect(battle.getCycleLength()).toEqual(2);
|
||||
|
||||
target.setArenaPosition(1, 2);
|
||||
drone.onTurnStart(target);
|
||||
expect(effect.getApplyCalls()).toEqual([], "start inside");
|
||||
let [drone, effect] = newTestDrone(2, 2, 8, ship1);
|
||||
expect(effect.getApplyCalls()).toEqual([]);
|
||||
|
||||
target.setArenaPosition(2, 2);
|
||||
drone.onShipMove(target);
|
||||
expect(effect.getApplyCalls()).toEqual([], "move inside");
|
||||
drone.activate();
|
||||
expect(effect.getApplyCalls()).toEqual([ship1]);
|
||||
|
||||
drone.onTurnEnd(target);
|
||||
expect(effect.getApplyCalls()).toEqual([target], "turn end");
|
||||
drone.activate();
|
||||
expect(effect.getApplyCalls()).toEqual([]);
|
||||
|
||||
drone.onTurnStart(target);
|
||||
expect(effect.getApplyCalls()).toEqual([], "second turn start");
|
||||
drone.activate();
|
||||
expect(effect.getApplyCalls()).toEqual([ship1]);
|
||||
|
||||
target.setArenaPosition(12, 12);
|
||||
drone.onShipMove(target);
|
||||
expect(effect.getApplyCalls()).toEqual([], "move out");
|
||||
drone.activate();
|
||||
expect(effect.getApplyCalls()).toEqual([]);
|
||||
|
||||
drone.onTurnEnd(target);
|
||||
expect(effect.getApplyCalls()).toEqual([], "second turn end");
|
||||
drone.activate();
|
||||
expect(effect.getApplyCalls()).toEqual([ship1]);
|
||||
});
|
||||
|
||||
it("signals the need for destruction after its lifetime", function () {
|
||||
let owner = new Ship(null, "owner");
|
||||
let other = new Ship(null, "other");
|
||||
let [drone, effect] = newTestDrone(0, 0, 5, owner);
|
||||
drone.duration = 2;
|
||||
|
||||
let battle = new Battle();
|
||||
spyOn(owner, "getBattle").and.returnValue(battle);
|
||||
let owner = new Ship(battle.fleets[0]);
|
||||
let [drone, effect] = newTestDrone(0, 0, 5, owner);
|
||||
drone.duration = 3;
|
||||
|
||||
let removeDrone = spyOn(battle, "removeDrone").and.callThrough();
|
||||
|
||||
drone.onTurnStart(other);
|
||||
drone.activate();
|
||||
expect(removeDrone).not.toHaveBeenCalled();
|
||||
drone.onTurnStart(owner);
|
||||
drone.activate();
|
||||
expect(removeDrone).not.toHaveBeenCalled();
|
||||
drone.onTurnStart(other);
|
||||
expect(removeDrone).not.toHaveBeenCalled();
|
||||
drone.onTurnStart(owner);
|
||||
expect(removeDrone).toHaveBeenCalledWith(drone);
|
||||
drone.activate();
|
||||
expect(removeDrone).toHaveBeenCalledWith(drone, true);
|
||||
});
|
||||
|
||||
it("logs each activation", function () {
|
||||
|
@ -144,14 +128,14 @@ module TS.SpaceTac {
|
|||
it("builds a textual description", function () {
|
||||
let drone = new Drone(new Ship());
|
||||
drone.duration = 1;
|
||||
expect(drone.getDescription()).toEqual("For 1 turn:\n• do nothing");
|
||||
expect(drone.getDescription()).toEqual("For 1 activation:\n• do nothing");
|
||||
|
||||
drone.duration = 3;
|
||||
drone.effects = [
|
||||
new DamageEffect(5),
|
||||
new AttributeEffect("skill_human", 1)
|
||||
]
|
||||
expect(drone.getDescription()).toEqual("For 3 turns:\n• do 5 damage\n• human skill +1");
|
||||
expect(drone.getDescription()).toEqual("For 3 activations:\n• do 5 damage\n• human skill +1");
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
|
@ -3,32 +3,34 @@ module TS.SpaceTac {
|
|||
* Drones are static objects that apply effects in a circular zone around themselves.
|
||||
*/
|
||||
export class Drone {
|
||||
// Battle in which the drone is deployed
|
||||
battle: Battle;
|
||||
|
||||
// Ship that launched the drone (informative, a drone is autonomous)
|
||||
owner: Ship;
|
||||
|
||||
// Code of the drone
|
||||
code: string;
|
||||
|
||||
// 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;
|
||||
// Remaining lifetime in number of turns
|
||||
duration: number;
|
||||
|
||||
// Effects to apply
|
||||
effects: BaseEffect[] = [];
|
||||
|
||||
// Ships registered inside the radius
|
||||
inside: Ship[] = [];
|
||||
// Cycle countdown for ships
|
||||
countdown: [Ship, number][] = [];
|
||||
|
||||
// Ships starting their turn the radius
|
||||
inside_at_start: Ship[] = [];
|
||||
|
||||
constructor(owner: Ship, code = "drone") {
|
||||
constructor(owner: Ship, code = "drone", base_duration = 1) {
|
||||
this.battle = owner.getBattle() || new Battle();
|
||||
this.owner = owner;
|
||||
this.code = code;
|
||||
this.duration = base_duration * this.battle.getCycleLength();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -39,14 +41,46 @@ module TS.SpaceTac {
|
|||
if (effects.length == 0) {
|
||||
effects = "• do nothing";
|
||||
}
|
||||
return `For ${this.duration} turn${this.duration > 1 ? "s" : ""}:\n${effects}`;
|
||||
return `For ${this.duration} activation${this.duration > 1 ? "s" : ""}:\n${effects}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter the list of ships in radius.
|
||||
* Get countdown until next activation for a given ship
|
||||
*/
|
||||
filterShipsInRadius(ships: Ship[]): Ship[] {
|
||||
return ships.filter(ship => ship.isInCircle(this.x, this.y, this.radius));
|
||||
getShipCountdown(ship: Ship): number {
|
||||
let countdown = 0;
|
||||
this.countdown.forEach(([iship, icountdown]) => {
|
||||
if (iship === ship) {
|
||||
countdown = icountdown;
|
||||
}
|
||||
});
|
||||
return countdown;
|
||||
}
|
||||
|
||||
/**
|
||||
* Start the countdown for a given ship
|
||||
*/
|
||||
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];
|
||||
}
|
||||
});
|
||||
if (!found) {
|
||||
this.countdown.push([ship, this.battle.getCycleLength()]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the list of affected ships.
|
||||
*/
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -55,68 +89,29 @@ module TS.SpaceTac {
|
|||
* This does not check if the ships are in range.
|
||||
*/
|
||||
apply(ships: Ship[], log = true) {
|
||||
ships = ships.filter(ship => ship.alive);
|
||||
if (ships.length > 0) {
|
||||
let battle = this.owner.getBattle();
|
||||
if (battle && log) {
|
||||
battle.log.add(new DroneAppliedEvent(this, ships));
|
||||
if (log) {
|
||||
this.battle.log.add(new DroneAppliedEvent(this, ships));
|
||||
}
|
||||
ships.forEach(ship => this.effects.forEach(effect => effect.applyOnShip(ship)));
|
||||
|
||||
ships.forEach(ship => {
|
||||
this.startShipCountdown(ship);
|
||||
this.effects.forEach(effect => effect.applyOnShip(ship));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the drone is first deployed.
|
||||
* Activate the drone
|
||||
*/
|
||||
onDeploy(ships: Ship[]) {
|
||||
this.apply(this.filterShipsInRadius(ships));
|
||||
}
|
||||
activate(log = true) {
|
||||
this.apply(this.getAffectedShips(), log);
|
||||
|
||||
/**
|
||||
* Called when a ship turn starts
|
||||
*/
|
||||
onTurnStart(ship: Ship) {
|
||||
if (ship == this.owner) {
|
||||
this.duration--;
|
||||
}
|
||||
this.countdown = this.countdown.map(([ship, countdown]): [Ship, number] => [ship, countdown - 1]).filter(([ship, countdown]) => countdown > 0);
|
||||
|
||||
if (this.duration <= 0) {
|
||||
if (this.owner) {
|
||||
let battle = this.owner.getBattle();
|
||||
if (battle) {
|
||||
battle.removeDrone(this);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a ship turn ends
|
||||
*/
|
||||
onTurnEnd(ship: Ship) {
|
||||
if (this.duration > 0 && ship.isInCircle(this.x, this.y, this.radius) && contains(this.inside_at_start, ship)) {
|
||||
this.apply([ship]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called after a ship moved
|
||||
*/
|
||||
onShipMove(ship: Ship) {
|
||||
if (this.duration > 0 && ship.isInCircle(this.x, this.y, this.radius)) {
|
||||
if (add(this.inside, ship)) {
|
||||
this.apply([ship]);
|
||||
}
|
||||
} else {
|
||||
remove(this.inside, ship);
|
||||
this.duration--;
|
||||
if (this.duration == 0) {
|
||||
this.battle.removeDrone(this, log);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -283,53 +283,6 @@ module TS.SpaceTac.Specs {
|
|||
expect(ship.isInCircle(12, -4, 5)).toBe(false);
|
||||
});
|
||||
|
||||
it("broadcasts to drones", function () {
|
||||
let battle = new Battle();
|
||||
let fleet = new Fleet();
|
||||
fleet.setBattle(battle);
|
||||
let ship = new Ship(fleet);
|
||||
let drone = new Drone(ship);
|
||||
|
||||
let onTurnStart = spyOn(drone, "onTurnStart");
|
||||
let onTurnEnd = spyOn(drone, "onTurnEnd");
|
||||
let onShipMove = spyOn(drone, "onShipMove");
|
||||
|
||||
battle.addDrone(drone);
|
||||
|
||||
expect(onTurnStart).toHaveBeenCalledTimes(0);
|
||||
expect(onTurnEnd).toHaveBeenCalledTimes(0);
|
||||
expect(onShipMove).toHaveBeenCalledTimes(0);
|
||||
|
||||
ship.startTurn();
|
||||
|
||||
expect(onTurnStart).toHaveBeenCalledTimes(1);
|
||||
expect(onTurnStart).toHaveBeenCalledWith(ship);
|
||||
expect(onTurnEnd).toHaveBeenCalledTimes(0);
|
||||
expect(onShipMove).toHaveBeenCalledTimes(0);
|
||||
|
||||
ship.moveTo(10, 10);
|
||||
|
||||
expect(onTurnStart).toHaveBeenCalledTimes(1);
|
||||
expect(onTurnEnd).toHaveBeenCalledTimes(0);
|
||||
expect(onShipMove).toHaveBeenCalledTimes(1);
|
||||
expect(onShipMove).toHaveBeenCalledWith(ship);
|
||||
|
||||
ship.endTurn();
|
||||
|
||||
expect(onTurnStart).toHaveBeenCalledTimes(1);
|
||||
expect(onTurnEnd).toHaveBeenCalledTimes(1);
|
||||
expect(onTurnEnd).toHaveBeenCalledWith(ship);
|
||||
expect(onShipMove).toHaveBeenCalledTimes(1);
|
||||
|
||||
ship.setDead();
|
||||
ship.startTurn();
|
||||
ship.endTurn();
|
||||
|
||||
expect(onTurnStart).toHaveBeenCalledTimes(2);
|
||||
expect(onTurnEnd).toHaveBeenCalledTimes(2);
|
||||
expect(onShipMove).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it("stores items in cargo space", function () {
|
||||
let ship = new Ship();
|
||||
let equipment1 = new Equipment();
|
||||
|
|
|
@ -313,14 +313,6 @@ module TS.SpaceTac {
|
|||
}
|
||||
}
|
||||
|
||||
// Call a method for each drone of the battlefield
|
||||
forEachDrone(callback: (drone: Drone) => any) {
|
||||
let battle = this.getBattle();
|
||||
if (battle) {
|
||||
battle.drones.forEach(callback);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method called at the start of battle
|
||||
*/
|
||||
|
@ -361,9 +353,6 @@ module TS.SpaceTac {
|
|||
this.sticky_effects.forEach(effect => effect.startTurn(this));
|
||||
this.cleanStickyEffects();
|
||||
}
|
||||
|
||||
// Broadcast to drones
|
||||
this.forEachDrone(drone => drone.onTurnStart(this));
|
||||
}
|
||||
|
||||
// Method called at the end of this ship turn
|
||||
|
@ -374,9 +363,6 @@ module TS.SpaceTac {
|
|||
}
|
||||
this.playing = false;
|
||||
|
||||
// Broadcast to drones
|
||||
this.forEachDrone(drone => drone.onTurnEnd(this));
|
||||
|
||||
if (this.alive) {
|
||||
// Recover action points for next turn
|
||||
this.updateAttributes();
|
||||
|
@ -446,9 +432,6 @@ module TS.SpaceTac {
|
|||
if (log) {
|
||||
this.addBattleEvent(new MoveEvent(this, x, y));
|
||||
}
|
||||
|
||||
// Broadcast to drones
|
||||
this.forEachDrone(drone => drone.onShipMove(this));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -30,6 +30,7 @@ module TS.SpaceTac {
|
|||
let ship = battle.fleets[0].addShip();
|
||||
ship.setArenaPosition(0, 0);
|
||||
battle.playing_ship = ship;
|
||||
spyOn(battle, "getCycleLength").and.returnValue(4);
|
||||
TestTools.setShipAP(ship, 3);
|
||||
let equipment = new Equipment(SlotType.Weapon, "testdrone");
|
||||
let action = new DeployDroneAction(equipment, 2, 8, 2, 4, [new DamageEffect(50)]);
|
||||
|
@ -43,7 +44,7 @@ module TS.SpaceTac {
|
|||
|
||||
let drone = battle.drones[0];
|
||||
expect(drone.code).toEqual("testdrone");
|
||||
expect(drone.duration).toEqual(2);
|
||||
expect(drone.duration).toEqual(8);
|
||||
expect(drone.owner).toBe(ship);
|
||||
expect(drone.x).toEqual(5);
|
||||
expect(drone.y).toEqual(0);
|
||||
|
|
|
@ -52,12 +52,11 @@ module TS.SpaceTac {
|
|||
}
|
||||
|
||||
protected customApply(ship: Ship, target: Target) {
|
||||
let drone = new Drone(ship, this.equipment.code);
|
||||
let drone = new Drone(ship, this.equipment.code, this.lifetime);
|
||||
drone.x = target.x;
|
||||
drone.y = target.y;
|
||||
drone.radius = this.effect_radius;
|
||||
drone.effects = this.effects;
|
||||
drone.duration = this.lifetime;
|
||||
|
||||
let battle = ship.getBattle();
|
||||
if (battle) {
|
||||
|
@ -66,7 +65,7 @@ module TS.SpaceTac {
|
|||
}
|
||||
|
||||
getEffectsDescription(): string {
|
||||
let desc = `Deploy drone for ${this.lifetime} turn${this.lifetime > 1 ? "s" : ""} (power usage ${this.power}, max range ${this.deploy_distance}km)`;
|
||||
let desc = `Deploy drone for ${this.lifetime} cycle${this.lifetime > 1 ? "s" : ""} (power usage ${this.power}, max range ${this.deploy_distance}km)`;
|
||||
let effects = this.effects.map(effect => {
|
||||
let suffix = `for ships in ${this.effect_radius}km radius`;
|
||||
if (effect instanceof StickyEffect) {
|
||||
|
|
|
@ -29,6 +29,7 @@ module TS.SpaceTac.Equipments {
|
|||
let battle = new Battle();
|
||||
let ship = battle.fleets[0].addShip();
|
||||
battle.playing_ship = ship;
|
||||
battle.play_order = [ship];
|
||||
TestTools.setShipAP(ship, 10);
|
||||
let result = equipment.action.apply(ship, new Target(5, 5, null));
|
||||
expect(result).toBe(true);
|
||||
|
|
Loading…
Reference in a new issue