Allow to select any ship to plan its turn
This commit is contained in:
parent
906322003f
commit
0b71a531cc
Before Width: | Height: | Size: 8.6 KiB After Width: | Height: | Size: 8.6 KiB |
Before Width: | Height: | Size: 8.8 KiB After Width: | Height: | Size: 8.8 KiB |
|
@ -1,30 +1,5 @@
|
|||
module TK.SpaceTac {
|
||||
testing("Battle", test => {
|
||||
test.case("defines play order by initiative throws", check => {
|
||||
var fleet1 = new Fleet();
|
||||
var fleet2 = new Fleet();
|
||||
|
||||
var ship1 = new Ship(fleet1, "F1S1");
|
||||
TestTools.setAttribute(ship1, "initiative", 2);
|
||||
var ship2 = new Ship(fleet1, "F1S2");
|
||||
TestTools.setAttribute(ship2, "initiative", 4);
|
||||
var ship3 = new Ship(fleet1, "F1S3");
|
||||
TestTools.setAttribute(ship3, "initiative", 1);
|
||||
var ship4 = new Ship(fleet2, "F2S1");
|
||||
TestTools.setAttribute(ship4, "initiative", 8);
|
||||
var ship5 = new Ship(fleet2, "F2S2");
|
||||
TestTools.setAttribute(ship5, "initiative", 2);
|
||||
|
||||
var battle = new Battle(fleet1, fleet2);
|
||||
check.equals(battle.play_order.length, 0);
|
||||
|
||||
var gen = new SkewedRandomGenerator([1.0, 0.1, 1.0, 0.2, 0.6]);
|
||||
battle.throwInitiative(gen);
|
||||
|
||||
check.equals(battle.play_order.length, 5);
|
||||
check.equals(battle.play_order, [ship1, ship4, ship5, ship3, ship2]);
|
||||
});
|
||||
|
||||
test.case("places ships on lines, facing the arena center", check => {
|
||||
var fleet1 = new Fleet();
|
||||
var fleet2 = new Fleet();
|
||||
|
@ -59,74 +34,7 @@ module TK.SpaceTac {
|
|||
check.nears(ship5.arena_angle, Math.PI);
|
||||
});
|
||||
|
||||
test.case("advances to next ship in play order", check => {
|
||||
var fleet1 = new Fleet();
|
||||
var fleet2 = new Fleet();
|
||||
|
||||
var ship1 = new Ship(fleet1, "ship1");
|
||||
var ship2 = new Ship(fleet1, "ship2");
|
||||
var ship3 = new Ship(fleet2, "ship3");
|
||||
|
||||
var battle = new Battle(fleet1, fleet2);
|
||||
battle.ships.list().forEach(ship => TestTools.setShipModel(ship, 10, 0));
|
||||
|
||||
// Check empty play_order case
|
||||
check.equals(battle.playing_ship, null);
|
||||
battle.advanceToNextShip();
|
||||
check.equals(battle.playing_ship, null);
|
||||
|
||||
// Force play order
|
||||
iforeach(battle.iships(), ship => TestTools.setAttribute(ship, "initiative", 1));
|
||||
var gen = new SkewedRandomGenerator([0.1, 0.2, 0.0]);
|
||||
battle.throwInitiative(gen);
|
||||
check.equals(battle.playing_ship, null);
|
||||
|
||||
battle.advanceToNextShip();
|
||||
check.same(battle.playing_ship, ship2);
|
||||
|
||||
battle.advanceToNextShip();
|
||||
check.same(battle.playing_ship, ship1);
|
||||
|
||||
battle.advanceToNextShip();
|
||||
check.same(battle.playing_ship, ship3);
|
||||
|
||||
battle.advanceToNextShip();
|
||||
check.same(battle.playing_ship, ship2);
|
||||
|
||||
// A dead ship is skipped
|
||||
ship1.setDead();
|
||||
battle.advanceToNextShip();
|
||||
check.same(battle.playing_ship, ship3);
|
||||
|
||||
// Playing ship dies
|
||||
ship3.setDead();
|
||||
battle.advanceToNextShip();
|
||||
check.same(battle.playing_ship, ship2);
|
||||
});
|
||||
|
||||
test.case("handles the suicide case (playing ship dies because of its action)", check => {
|
||||
let battle = TestTools.createBattle(3, 1);
|
||||
let [ship1, ship2, ship3, ship4] = battle.play_order;
|
||||
ship1.setArenaPosition(0, 0);
|
||||
ship2.setArenaPosition(0, 0);
|
||||
ship3.setArenaPosition(1000, 1000);
|
||||
ship4.setArenaPosition(1000, 1000);
|
||||
let weapon = TestTools.addWeapon(ship1, 8000, 0, 50, 100);
|
||||
|
||||
check.in("initially", check => {
|
||||
check.same(battle.playing_ship, ship1, "playing ship");
|
||||
check.equals(battle.ships.list().filter(ship => ship.alive), [ship1, ship2, ship3, ship4], "alive ships");
|
||||
});
|
||||
|
||||
let result = battle.applyOneAction(weapon.id, Target.newFromLocation(0, 0));
|
||||
check.equals(result, true, "action applied successfully");
|
||||
check.in("after weapon", check => {
|
||||
check.same(battle.playing_ship, ship3, "playing ship");
|
||||
check.equals(battle.ships.list().filter(ship => ship.alive), [ship3, ship4], "alive ships");
|
||||
});
|
||||
});
|
||||
|
||||
test.case("detects victory condition and logs a final EndBattleEvent", check => {
|
||||
test.case("detects victory condition and logs a final EndBattleDiff", check => {
|
||||
var fleet1 = new Fleet();
|
||||
var fleet2 = new Fleet();
|
||||
|
||||
|
@ -137,12 +45,11 @@ module TK.SpaceTac {
|
|||
var battle = new Battle(fleet1, fleet2);
|
||||
battle.ships.list().forEach(ship => TestTools.setShipModel(ship, 10, 0));
|
||||
battle.start();
|
||||
battle.play_order = [ship3, ship2, ship1];
|
||||
check.equals(battle.ended, false);
|
||||
|
||||
ship1.setDead();
|
||||
ship2.setDead();
|
||||
battle.advanceToNextShip();
|
||||
battle.applyTurnPlan({ fleets: [] });
|
||||
|
||||
check.equals(battle.ended, true);
|
||||
let diff = battle.log.get(battle.log.count() - 1);
|
||||
|
@ -197,10 +104,9 @@ module TK.SpaceTac {
|
|||
ship4.setArenaPosition(12, 12);
|
||||
|
||||
var battle = new Battle(fleet1);
|
||||
battle.throwInitiative(new SkewedRandomGenerator([5, 4, 3, 2]));
|
||||
|
||||
var result = battle.collectShipsInCircle(Target.newFromLocation(5, 8), 3);
|
||||
check.equals(result, [ship2, ship3]);
|
||||
check.equals(sortedBy(result, ship => ship.name), [ship2, ship3]);
|
||||
});
|
||||
|
||||
test.case("adds and remove drones", check => {
|
||||
|
@ -223,60 +129,6 @@ module TK.SpaceTac {
|
|||
check.equals(battle.drones.count(), 0);
|
||||
});
|
||||
|
||||
test.case("checks if a player is able to play", check => {
|
||||
let battle = new Battle();
|
||||
let player = new Player();
|
||||
|
||||
check.equals(battle.canPlay(player), false);
|
||||
|
||||
let ship = new Ship();
|
||||
TestTools.setShipPlaying(battle, ship);
|
||||
|
||||
check.equals(battle.canPlay(player), false);
|
||||
|
||||
ship.fleet.setPlayer(player);
|
||||
|
||||
check.equals(battle.canPlay(player), true);
|
||||
});
|
||||
|
||||
test.case("gets the number of turns before a specific ship plays", check => {
|
||||
let battle = TestTools.createBattle(2, 1);
|
||||
|
||||
check.in("initial", check => {
|
||||
check.same(battle.playing_ship, battle.play_order[0], "first ship playing");
|
||||
check.equals(battle.getPlayOrder(battle.play_order[0]), 0);
|
||||
check.equals(battle.getPlayOrder(battle.play_order[1]), 1);
|
||||
check.equals(battle.getPlayOrder(battle.play_order[2]), 2);
|
||||
});
|
||||
|
||||
battle.advanceToNextShip();
|
||||
|
||||
check.in("1 step", check => {
|
||||
check.same(battle.playing_ship, battle.play_order[1], "second ship playing");
|
||||
check.equals(battle.getPlayOrder(battle.play_order[0]), 2);
|
||||
check.equals(battle.getPlayOrder(battle.play_order[1]), 0);
|
||||
check.equals(battle.getPlayOrder(battle.play_order[2]), 1);
|
||||
});
|
||||
|
||||
battle.advanceToNextShip();
|
||||
|
||||
check.in("2 steps", check => {
|
||||
check.same(battle.playing_ship, battle.play_order[2], "third ship playing");
|
||||
check.equals(battle.getPlayOrder(battle.play_order[0]), 1);
|
||||
check.equals(battle.getPlayOrder(battle.play_order[1]), 2);
|
||||
check.equals(battle.getPlayOrder(battle.play_order[2]), 0);
|
||||
});
|
||||
|
||||
battle.advanceToNextShip();
|
||||
|
||||
check.in("3 steps", check => {
|
||||
check.same(battle.playing_ship, battle.play_order[0], "first ship playing");
|
||||
check.equals(battle.getPlayOrder(battle.play_order[0]), 0);
|
||||
check.equals(battle.getPlayOrder(battle.play_order[1]), 1);
|
||||
check.equals(battle.getPlayOrder(battle.play_order[2]), 2);
|
||||
});
|
||||
});
|
||||
|
||||
test.case("lists area effects", check => {
|
||||
let battle = new Battle();
|
||||
let ship = battle.fleets[0].addShip();
|
||||
|
@ -318,15 +170,12 @@ module TK.SpaceTac {
|
|||
|
||||
test.case("is serializable", check => {
|
||||
let battle = Battle.newQuickRandom();
|
||||
battle.ai_playing = true;
|
||||
|
||||
let serializer = new Serializer(TK.SpaceTac);
|
||||
let data = serializer.serialize(battle);
|
||||
|
||||
let loaded = serializer.unserialize(data);
|
||||
|
||||
check.equals(loaded.ai_playing, false, "ai playing is reset");
|
||||
battle.ai_playing = false;
|
||||
check.equals(loaded, battle, "unserialized == initial");
|
||||
|
||||
let session = new GameSession();
|
||||
|
@ -340,15 +189,15 @@ module TK.SpaceTac {
|
|||
check.greaterorequal(ratio, 1.2, `quick battle serialized size (${data.length}) should be larger than campaign's (${data1.length})`);
|
||||
});
|
||||
|
||||
test.case("can revert the last action", check => {
|
||||
test.case("can revert the last turn", check => {
|
||||
let battle = new Battle();
|
||||
let ship = battle.fleets[0].addShip();
|
||||
ship.setValue("hull", 13);
|
||||
battle.log.clear();
|
||||
battle.log.add(new ShipValueDiff(ship, "hull", 4));
|
||||
battle.log.add(new ShipActionUsedDiff(ship, EndTurnAction.SINGLETON, Target.newFromShip(ship)));
|
||||
battle.log.add(new TurnStartDiff([]));
|
||||
battle.log.add(new ShipValueDiff(ship, "hull", 7));
|
||||
battle.log.add(new ShipActionUsedDiff(ship, EndTurnAction.SINGLETON, Target.newFromShip(ship)));
|
||||
battle.log.add(new TurnStartDiff([]));
|
||||
battle.log.add(new ShipValueDiff(ship, "hull", 2));
|
||||
|
||||
check.in("initial state", check => {
|
||||
|
@ -356,23 +205,23 @@ module TK.SpaceTac {
|
|||
check.equals(battle.log.count(), 5, "log count=5");
|
||||
});
|
||||
|
||||
battle.revertOneAction();
|
||||
battle.revertOneTurn();
|
||||
|
||||
check.in("revert 1 action", check => {
|
||||
check.in("revert 1 turn", check => {
|
||||
check.equals(ship.getValue("hull"), 11, "hull=11");
|
||||
check.equals(battle.log.count(), 3, "log count=3");
|
||||
});
|
||||
|
||||
battle.revertOneAction();
|
||||
battle.revertOneTurn();
|
||||
|
||||
check.in("revert 2 actions", check => {
|
||||
check.in("revert 2 turns", check => {
|
||||
check.equals(ship.getValue("hull"), 4, "hull=4");
|
||||
check.equals(battle.log.count(), 1, "log count=1");
|
||||
});
|
||||
|
||||
battle.revertOneAction();
|
||||
battle.revertOneTurn();
|
||||
|
||||
check.in("revert 3 actions", check => {
|
||||
check.in("revert 3 turns", check => {
|
||||
check.equals(ship.getValue("hull"), 0, "hull=0");
|
||||
check.equals(battle.log.count(), 0, "log count=0");
|
||||
});
|
||||
|
|
|
@ -18,11 +18,7 @@ module TK.SpaceTac {
|
|||
// Container of all engaged ships
|
||||
ships: RObjectContainer<Ship>
|
||||
|
||||
// List of playing ships, sorted by their initiative throw
|
||||
play_order: Ship[]
|
||||
play_index = -1
|
||||
|
||||
// Current battle "cycle" (one cycle is one turn done for all ships in the play order)
|
||||
// Current battle turn count
|
||||
cycle = 0
|
||||
|
||||
// List of deployed drones
|
||||
|
@ -32,13 +28,9 @@ module TK.SpaceTac {
|
|||
width: number
|
||||
height: number
|
||||
|
||||
// Indicator that an AI is playing
|
||||
ai_playing = false
|
||||
|
||||
constructor(fleet1 = new Fleet(new Player("Attacker")), fleet2 = new Fleet(new Player("Defender")), width = 1920, height = 1080) {
|
||||
this.fleets = [fleet1, fleet2];
|
||||
this.ships = new RObjectContainer(fleet1.ships.concat(fleet2.ships));
|
||||
this.play_order = [];
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
|
||||
|
@ -50,10 +42,6 @@ module TK.SpaceTac {
|
|||
});
|
||||
}
|
||||
|
||||
postUnserialize() {
|
||||
this.ai_playing = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Property is true if the battle has ended
|
||||
*/
|
||||
|
@ -64,9 +52,10 @@ module TK.SpaceTac {
|
|||
/**
|
||||
* Apply a turn plan through a resolution
|
||||
*/
|
||||
applyTurnPlan(plan: TurnPlan): void {
|
||||
const resolution = new TurnResolution(this, plan);
|
||||
applyTurnPlan(plan: TurnPlan, random?: RandomGenerator): void {
|
||||
const resolution = new TurnResolution(this, plan, random);
|
||||
resolution.resolve();
|
||||
this.performChecks();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -93,13 +82,6 @@ module TK.SpaceTac {
|
|||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the currently playing ship
|
||||
*/
|
||||
get playing_ship(): Ship | null {
|
||||
return this.play_order[this.play_index] || null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a ship by its ID.
|
||||
*/
|
||||
|
@ -139,86 +121,7 @@ module TK.SpaceTac {
|
|||
* This can be used by the UI to determine if player interaction is allowed
|
||||
*/
|
||||
canPlay(player: Player): boolean {
|
||||
if (this.ended) {
|
||||
return false;
|
||||
} else if (this.playing_ship && player.is(this.playing_ship.fleet.player)) {
|
||||
return this.playing_ship.isAbleToPlay(false);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Create play order, performing an initiative throw
|
||||
throwInitiative(gen: RandomGenerator = new RandomGenerator()): void {
|
||||
var play_order: Ship[] = [];
|
||||
|
||||
// Throw each ship's initiative
|
||||
this.fleets.forEach(function (fleet: Fleet) {
|
||||
fleet.ships.forEach(function (ship: Ship) {
|
||||
ship.throwInitiative(gen);
|
||||
play_order.push(ship);
|
||||
});
|
||||
});
|
||||
|
||||
// Sort by throw result
|
||||
play_order.sort(function (ship1: Ship, ship2: Ship) {
|
||||
return (ship2.play_priority - ship1.play_priority);
|
||||
});
|
||||
this.play_order = play_order;
|
||||
this.play_index = -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of turns before a specific ship plays (currently playing ship will return 0).
|
||||
*
|
||||
* Returns -1 if the ship is not in the play list.
|
||||
*/
|
||||
getPlayOrder(ship: Ship): number {
|
||||
let index = this.play_order.indexOf(ship);
|
||||
if (index < 0) {
|
||||
return -1;
|
||||
} else {
|
||||
let result = index - this.play_index;
|
||||
return (result < 0) ? (result + this.play_order.length) : result;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a ship in the play order list
|
||||
*/
|
||||
removeFromPlayOrder(idx: number): void {
|
||||
this.play_order.splice(idx, 1);
|
||||
if (idx <= this.play_index) {
|
||||
this.play_index -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a ship from the play order list
|
||||
*/
|
||||
insertInPlayOrder(idx: number, ship: Ship): void {
|
||||
this.play_order.splice(idx, 0, ship);
|
||||
if (idx <= this.play_index) {
|
||||
this.play_index += 1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the currently playing ship
|
||||
*/
|
||||
setPlayingShip(ship: Ship): void {
|
||||
let current = this.playing_ship;
|
||||
if (current) {
|
||||
current.playing = false;
|
||||
}
|
||||
|
||||
this.play_index = this.play_order.indexOf(ship);
|
||||
this.ai_playing = false;
|
||||
|
||||
current = this.playing_ship;
|
||||
if (current) {
|
||||
current.playing = true;
|
||||
}
|
||||
return !this.ended;
|
||||
}
|
||||
|
||||
// Defines the initial ship positions of all engaged fleets
|
||||
|
@ -245,25 +148,12 @@ module TK.SpaceTac {
|
|||
}
|
||||
|
||||
/**
|
||||
* Get the next playing ship
|
||||
*/
|
||||
getNextShip(): Ship {
|
||||
return this.play_order[(this.play_index + 1) % this.play_order.length];
|
||||
}
|
||||
|
||||
/**
|
||||
* Make an AI play the current ship
|
||||
*
|
||||
* This will run asynchronous work in background, until the playing ship is changed
|
||||
* Make an AI play the current turn
|
||||
*/
|
||||
playAI(debug = false): boolean {
|
||||
if (this.playing_ship && !this.ai_playing) {
|
||||
this.ai_playing = true;
|
||||
AIWorker.process(this, debug);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
// TODO
|
||||
//AIWorker.process(this, debug);
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -278,19 +168,6 @@ module TK.SpaceTac {
|
|||
this.cycle = 1;
|
||||
this.placeShips();
|
||||
iforeach(this.iships(), ship => ship.restoreInitialState());
|
||||
this.throwInitiative();
|
||||
this.setPlayingShip(this.play_order[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Force current ship's turn to end, then advance to the next one
|
||||
*/
|
||||
advanceToNextShip(): void {
|
||||
if (this.playing_ship) {
|
||||
this.applyOneAction(EndTurnAction.SINGLETON.id);
|
||||
} else if (this.play_order.length) {
|
||||
this.setPlayingShip(this.play_order[0]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -364,7 +241,7 @@ module TK.SpaceTac {
|
|||
* At the end of the action, some checks will be applied to ensure the battle state is consistent
|
||||
*/
|
||||
applyOneAction(action_id: RObjectId, target?: Target): boolean {
|
||||
let ship = this.playing_ship;
|
||||
let ship = first(this.ships.list(), ship => ship.actions.getById(action_id) !== null);
|
||||
if (ship) {
|
||||
let action = ship.actions.getById(action_id);
|
||||
if (action) {
|
||||
|
@ -377,11 +254,6 @@ module TK.SpaceTac {
|
|||
|
||||
if (!this.ended) {
|
||||
this.applyDiffs([new ShipActionEndedDiff(ship, action, target)]);
|
||||
|
||||
if (ship.playing && ship.getValue("hull") <= 0) {
|
||||
// Playing ship died during its action, force a turn end
|
||||
this.applyOneAction(EndTurnAction.SINGLETON.id);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -399,13 +271,13 @@ module TK.SpaceTac {
|
|||
}
|
||||
|
||||
/**
|
||||
* Revert the last applied action
|
||||
* Revert the last turn
|
||||
*
|
||||
* This will remove diffs from the log, so pay attention to other log clients!
|
||||
*/
|
||||
revertOneAction(): void {
|
||||
revertOneTurn(): void {
|
||||
let client = new BattleLogClient(this, this.log);
|
||||
while (!client.atStart() && !(client.getCurrent() instanceof ShipActionUsedDiff)) {
|
||||
while (!client.atStart() && !(client.getCurrent() instanceof TurnStartDiff)) {
|
||||
client.backward();
|
||||
}
|
||||
if (!client.atStart()) {
|
||||
|
|
|
@ -28,24 +28,27 @@ module TK.SpaceTac.Specs {
|
|||
], "fixed values");
|
||||
})
|
||||
|
||||
test.case("marks ships as dead, except the playing one", check => {
|
||||
test.case("marks ships as dead", check => {
|
||||
let battle = TestTools.createBattle(1, 2);
|
||||
let [ship1, ship2, ship3] = battle.play_order;
|
||||
const ship1 = battle.fleets[0].ships[0];
|
||||
const ship2 = battle.fleets[1].ships[0];
|
||||
let checks = new BattleChecks(battle);
|
||||
check.equals(checks.checkDeadShips(), [], "no ship to mark as dead");
|
||||
|
||||
battle.ships.list().forEach(ship => ship.setValue("hull", 0));
|
||||
ship2.setValue("hull", 0);
|
||||
|
||||
let result = checks.checkDeadShips();
|
||||
check.equals(result, [new ShipDeathDiff(battle, ship2)], "ship2 marked as dead");
|
||||
battle.applyDiffs(result);
|
||||
|
||||
ship1.setValue("hull", 0);
|
||||
|
||||
result = checks.checkDeadShips();
|
||||
check.equals(result, [new ShipDeathDiff(battle, ship3)], "ship3 marked as dead");
|
||||
check.equals(result, [new ShipDeathDiff(battle, ship1)], "ship1 marked as dead");
|
||||
battle.applyDiffs(result);
|
||||
|
||||
result = checks.checkDeadShips();
|
||||
check.equals(result, [], "ship1 left playing");
|
||||
check.equals(result, [], "no ship left");
|
||||
})
|
||||
|
||||
test.case("fixes area effects", check => {
|
||||
|
@ -78,7 +81,6 @@ module TK.SpaceTac.Specs {
|
|||
let ship2 = battle.fleets[1].addShip();
|
||||
ship2.setArenaPosition(1000, 1000);
|
||||
TestTools.setShipModel(ship2, 10);
|
||||
TestTools.setShipPlaying(battle, ship1);
|
||||
|
||||
let vig1 = ship1.actions.addCustom(new VigilanceAction("Vig1", { radius: 100, filter: ActionTargettingFilter.ENEMIES }, { intruder_effects: [new DamageEffect(1)] }));
|
||||
let vig2 = ship1.actions.addCustom(new VigilanceAction("Vig2", { radius: 50, filter: ActionTargettingFilter.ENEMIES }, { intruder_effects: [new DamageEffect(2)] }));
|
||||
|
|
|
@ -113,11 +113,11 @@ module TK.SpaceTac {
|
|||
}
|
||||
|
||||
/**
|
||||
* Check that not-playing ships with no more hull are dead
|
||||
* Check that ships with no more hull are dead
|
||||
*/
|
||||
checkDeadShips(): BaseBattleDiff[] {
|
||||
// We do one ship at a time, because the state of one ship may depend on another
|
||||
let dying = ifirst(this.battle.iships(true), ship => !ship.playing && ship.getValue("hull") <= 0);
|
||||
let dying = ifirst(this.battle.iships(true), ship => ship.getValue("hull") <= 0);
|
||||
|
||||
if (dying) {
|
||||
return dying.getDeathDiffs(this.battle);
|
||||
|
|
|
@ -2,7 +2,7 @@ module TK.SpaceTac {
|
|||
testing("Drone", test => {
|
||||
test.case("applies area effects when deployed", check => {
|
||||
let battle = TestTools.createBattle();
|
||||
let ship = nn(battle.playing_ship);
|
||||
let ship = battle.fleets[0].ships[0];
|
||||
TestTools.setShipModel(ship, 100, 0, 10);
|
||||
let weapon = new DeployDroneAction("testdrone", { power: 2 }, { deploy_distance: 300, drone_radius: 30, drone_effects: [new AttributeEffect("evasion", 15)] });
|
||||
ship.actions.addCustom(weapon);
|
||||
|
|
|
@ -10,9 +10,9 @@ module TK.SpaceTac.Specs {
|
|||
/**
|
||||
* Apply deterministic game steps
|
||||
*/
|
||||
function applyGameSteps(session: GameSession): void {
|
||||
function applyGameSteps(session: GameSession, random: RandomGenerator): void {
|
||||
var battle = nn(session.getBattle());
|
||||
battle.advanceToNextShip();
|
||||
battle.applyTurnPlan({ fleets: [] }, random);
|
||||
// TODO Make some fixed moves (AI?)
|
||||
battle.endBattle(battle.fleets[0]);
|
||||
}
|
||||
|
@ -29,8 +29,9 @@ module TK.SpaceTac.Specs {
|
|||
compare(loaded_session, session);
|
||||
|
||||
// Apply game steps
|
||||
applyGameSteps(session);
|
||||
applyGameSteps(loaded_session);
|
||||
const numbers = range(100).map(i => i / 101);
|
||||
applyGameSteps(session, new SkewedRandomGenerator(numbers, true));
|
||||
applyGameSteps(loaded_session, new SkewedRandomGenerator(numbers, true));
|
||||
|
||||
// Check equality after game steps
|
||||
compare(loaded_session, session);
|
||||
|
|
|
@ -168,7 +168,7 @@ module TK.SpaceTac.Specs {
|
|||
|
||||
test.case("produces death diffs", check => {
|
||||
let battle = TestTools.createBattle(1);
|
||||
let ship = nn(battle.playing_ship);
|
||||
let ship = battle.fleets[0].ships[0];
|
||||
|
||||
check.equals(ship.getDeathDiffs(battle), [
|
||||
new ShipValueDiff(ship, "hull", -1),
|
||||
|
|
|
@ -45,12 +45,6 @@ module TK.SpaceTac {
|
|||
// Personality
|
||||
personality = new Personality()
|
||||
|
||||
// Boolean set to true if the ship is currently playing its turn
|
||||
playing = false
|
||||
|
||||
// Priority in current battle's play_order (used as sort key)
|
||||
play_priority = 0
|
||||
|
||||
// Create a new ship inside a fleet
|
||||
constructor(fleet: Fleet | null = null, name: string | null = null, model = new ShipModel()) {
|
||||
super();
|
||||
|
@ -112,8 +106,7 @@ module TK.SpaceTac {
|
|||
|
||||
// Make an initiative throw, to resolve play order in a battle
|
||||
throwInitiative(gen: RandomGenerator): number {
|
||||
this.play_priority = gen.random() * this.attributes.initiative.get();
|
||||
return this.play_priority;
|
||||
return gen.random() * this.attributes.initiative.get();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -16,8 +16,6 @@ module TK.SpaceTac {
|
|||
|
||||
var battle = new Battle(fleet1, fleet2);
|
||||
battle.ships.list().forEach(ship => TestTools.setShipModel(ship, 1, 0));
|
||||
battle.play_order = fleet1.ships.concat(fleet2.ships);
|
||||
battle.setPlayingShip(battle.play_order[0]);
|
||||
return battle;
|
||||
}
|
||||
|
||||
|
@ -45,15 +43,6 @@ module TK.SpaceTac {
|
|||
return action;
|
||||
}
|
||||
|
||||
/**
|
||||
* Force the current playing ship
|
||||
*/
|
||||
static setShipPlaying(battle: Battle, ship: Ship): void {
|
||||
add(battle.play_order, ship);
|
||||
battle.play_index = battle.play_order.indexOf(ship);
|
||||
ship.playing = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a ship attributes (by changing its model)
|
||||
*/
|
||||
|
@ -115,18 +104,17 @@ module TK.SpaceTac {
|
|||
static actionChain(check: TestContext, battle: Battle, actions: [Ship, BaseAction, Target | undefined][], checks: ((check: TestContext) => void)[]): void {
|
||||
checks[0](check.sub("initial state"));
|
||||
|
||||
battle.applyDiffs([new TurnStartDiff([])]);
|
||||
|
||||
for (let i = 0; i < actions.length; i++) {
|
||||
let [ship, action, target] = actions[i];
|
||||
battle.setPlayingShip(ship);
|
||||
let result = battle.applyOneAction(action.id, target);
|
||||
check.equals(result, true, `action ${i + 1} successfully applied`);
|
||||
checks[i + 1](check.sub(`after action ${i + 1} applied`));
|
||||
}
|
||||
|
||||
for (let i = actions.length - 1; i >= 0; i--) {
|
||||
battle.revertOneAction();
|
||||
checks[i](check.sub(`after action ${i + 1} reverted`));
|
||||
}
|
||||
battle.revertOneTurn();
|
||||
checks[0](check.sub(`after turn reverted`));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2,19 +2,19 @@ module TK.SpaceTac.Specs {
|
|||
testing("ActionList", test => {
|
||||
test.case("lists actions from ship", check => {
|
||||
let actions = new ActionList();
|
||||
check.equals(actions.listAll(), [EndTurnAction.SINGLETON]);
|
||||
check.equals(actions.listAll(), []);
|
||||
|
||||
let model = new ShipModel();
|
||||
let ship = new Ship(null, null, model);
|
||||
actions.updateFromShip(ship);
|
||||
check.equals(actions.listAll(), [EndTurnAction.SINGLETON]);
|
||||
check.equals(actions.listAll(), []);
|
||||
|
||||
let action1 = new BaseAction("test1");
|
||||
let action2 = new BaseAction("test2");
|
||||
let mock = check.patch(model, "getActions", () => [action1, action2]);
|
||||
ship.level.forceLevel(3);
|
||||
actions.updateFromShip(ship);
|
||||
check.equals(actions.listAll(), [action1, action2, EndTurnAction.SINGLETON]);
|
||||
check.equals(actions.listAll(), [action1, action2]);
|
||||
check.called(mock, [[3, []]]);
|
||||
|
||||
let up1: ShipUpgrade = { code: "up1" };
|
||||
|
@ -22,7 +22,7 @@ module TK.SpaceTac.Specs {
|
|||
check.patch(model, "getLevelUpgrades", () => [up1, up2]);
|
||||
ship.level.activateUpgrade(up1, true);
|
||||
actions.updateFromShip(ship);
|
||||
check.equals(actions.listAll(), [action1, action2, EndTurnAction.SINGLETON]);
|
||||
check.equals(actions.listAll(), [action1, action2]);
|
||||
check.called(mock, [[3, ["up1"]]]);
|
||||
})
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@ module TK.SpaceTac {
|
|||
* List all actions
|
||||
*/
|
||||
listAll(): BaseAction[] {
|
||||
return this.from_model.concat(this.custom).concat([EndTurnAction.SINGLETON]);
|
||||
return this.from_model.concat(this.custom);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -2,7 +2,7 @@ module TK.SpaceTac.Specs {
|
|||
testing("BaseAction", test => {
|
||||
test.case("may be applied and reverted", check => {
|
||||
let battle = TestTools.createBattle();
|
||||
let ship = nn(battle.playing_ship);
|
||||
let ship = battle.fleets[0].ships[0];
|
||||
TestTools.setShipModel(ship, 100, 0, 10);
|
||||
let action = TestTools.addWeapon(ship, 0, 3, 100, 50);
|
||||
action.configureCooldown(2, 1);
|
||||
|
@ -10,7 +10,6 @@ module TK.SpaceTac.Specs {
|
|||
TestTools.actionChain(check, battle, [
|
||||
[ship, action, Target.newFromLocation(0, 0)],
|
||||
[ship, action, Target.newFromLocation(0, 0)],
|
||||
[ship, EndTurnAction.SINGLETON, undefined],
|
||||
], [
|
||||
check => {
|
||||
check.equals(ship.getValue("power"), 10, "power");
|
||||
|
@ -30,12 +29,6 @@ module TK.SpaceTac.Specs {
|
|||
check.equals(cooldown.uses, 2, "uses");
|
||||
check.equals(cooldown.heat, 1, "heat");
|
||||
},
|
||||
check => {
|
||||
check.equals(ship.getValue("power"), 10, "power");
|
||||
let cooldown = ship.actions.getCooldown(action);
|
||||
check.equals(cooldown.uses, 0, "uses");
|
||||
check.equals(cooldown.heat, 0, "heat");
|
||||
},
|
||||
]);
|
||||
})
|
||||
|
||||
|
|
|
@ -143,12 +143,6 @@ module TK.SpaceTac {
|
|||
* Returns an unavalability reason, null otherwise
|
||||
*/
|
||||
checkCannotBeApplied(ship: Ship, remaining_ap: number | null = null): ActionUnavailability | null {
|
||||
let battle = ship.getBattle();
|
||||
if (battle && battle.playing_ship !== ship) {
|
||||
// Ship is not playing
|
||||
return ActionUnavailability.NOT_PLAYING;
|
||||
}
|
||||
|
||||
if (!ship.actions.getById(this.id)) {
|
||||
return ActionUnavailability.NO_SUCH_ACTION;
|
||||
}
|
||||
|
|
|
@ -28,7 +28,7 @@ module TK.SpaceTac.Specs {
|
|||
|
||||
test.case("deploys a new drone", check => {
|
||||
let battle = TestTools.createBattle();
|
||||
let ship = battle.play_order[0];
|
||||
let ship = battle.fleets[0].ships[0];
|
||||
ship.setArenaPosition(0, 0);
|
||||
TestTools.setShipModel(ship, 100, 0, 3);
|
||||
|
||||
|
|
|
@ -1,199 +0,0 @@
|
|||
module TK.SpaceTac.Specs {
|
||||
testing("EndTurnAction", test => {
|
||||
test.case("can't be applied to non-playing ship", check => {
|
||||
let battle = new Battle();
|
||||
battle.fleets[0].addShip();
|
||||
battle.fleets[0].addShip();
|
||||
battle.throwInitiative();
|
||||
battle.setPlayingShip(battle.play_order[0]);
|
||||
|
||||
let action = new EndTurnAction();
|
||||
check.equals(action.checkCannotBeApplied(battle.play_order[0]), ActionUnavailability.NO_SUCH_ACTION);
|
||||
|
||||
action = EndTurnAction.SINGLETON;
|
||||
check.equals(action.checkCannotBeApplied(battle.play_order[0]), null);
|
||||
check.equals(action.checkCannotBeApplied(battle.play_order[1]), ActionUnavailability.NOT_PLAYING);
|
||||
});
|
||||
|
||||
test.case("changes active ship", check => {
|
||||
let battle = TestTools.createBattle(2, 0);
|
||||
|
||||
TestTools.actionChain(check, battle, [
|
||||
[battle.play_order[0], EndTurnAction.SINGLETON, undefined],
|
||||
], [
|
||||
check => {
|
||||
check.equals(battle.play_index, 0, "play_index is 0");
|
||||
check.same(battle.playing_ship, battle.play_order[0], "first ship is playing");
|
||||
check.equals(battle.play_order[0].playing, true, "first ship is playing");
|
||||
check.equals(battle.play_order[1].playing, false, "second ship is not playing");
|
||||
},
|
||||
check => {
|
||||
check.equals(battle.play_index, 1, "play_index is 1");
|
||||
check.same(battle.playing_ship, battle.play_order[1], "second ship is playing");
|
||||
check.equals(battle.play_order[0].playing, false, "first ship is not playing");
|
||||
check.equals(battle.play_order[1].playing, true, "second ship is playing");
|
||||
}
|
||||
]);
|
||||
});
|
||||
|
||||
test.case("generates power for previous ship", check => {
|
||||
let battle = TestTools.createBattle(1, 1);
|
||||
let [ship1, ship2] = battle.play_order;
|
||||
TestTools.setShipModel(ship1, 100, 0, 10);
|
||||
let toggle = new ToggleAction("toggle", { power: 2 });
|
||||
ship1.actions.addCustom(toggle);
|
||||
ship1.setValue("power", 6);
|
||||
|
||||
TestTools.actionChain(check, battle, [
|
||||
[ship1, toggle, undefined],
|
||||
[ship1, toggle, undefined],
|
||||
[ship1, EndTurnAction.SINGLETON, undefined],
|
||||
[ship2, EndTurnAction.SINGLETON, undefined],
|
||||
[ship1, toggle, undefined],
|
||||
[ship1, EndTurnAction.SINGLETON, undefined],
|
||||
[ship2, EndTurnAction.SINGLETON, undefined],
|
||||
[ship1, EndTurnAction.SINGLETON, undefined],
|
||||
[ship2, EndTurnAction.SINGLETON, undefined],
|
||||
[ship1, toggle, undefined],
|
||||
[ship1, EndTurnAction.SINGLETON, undefined],
|
||||
], [
|
||||
check => {
|
||||
check.equals(ship1.getValue("power"), 6, "power value");
|
||||
check.same(battle.playing_ship, ship1);
|
||||
},
|
||||
check => {
|
||||
check.equals(ship1.getValue("power"), 4, "power value");
|
||||
check.same(battle.playing_ship, ship1);
|
||||
},
|
||||
check => {
|
||||
check.equals(ship1.getValue("power"), 6, "power value");
|
||||
check.same(battle.playing_ship, ship1);
|
||||
},
|
||||
check => {
|
||||
check.equals(ship1.getValue("power"), 10, "power value");
|
||||
check.same(battle.playing_ship, ship2);
|
||||
},
|
||||
check => {
|
||||
check.equals(ship1.getValue("power"), 10, "power value");
|
||||
check.same(battle.playing_ship, ship1);
|
||||
},
|
||||
check => {
|
||||
check.equals(ship1.getValue("power"), 8, "power value");
|
||||
check.same(battle.playing_ship, ship1);
|
||||
},
|
||||
check => {
|
||||
check.equals(ship1.getValue("power"), 8, "power value");
|
||||
check.same(battle.playing_ship, ship2);
|
||||
},
|
||||
check => {
|
||||
check.equals(ship1.getValue("power"), 8, "power value");
|
||||
check.same(battle.playing_ship, ship1);
|
||||
},
|
||||
check => {
|
||||
check.equals(ship1.getValue("power"), 8, "power value");
|
||||
check.same(battle.playing_ship, ship2);
|
||||
},
|
||||
check => {
|
||||
check.equals(ship1.getValue("power"), 8, "power value");
|
||||
check.same(battle.playing_ship, ship1);
|
||||
},
|
||||
check => {
|
||||
check.equals(ship1.getValue("power"), 10, "power value");
|
||||
check.same(battle.playing_ship, ship1);
|
||||
},
|
||||
check => {
|
||||
check.equals(ship1.getValue("power"), 10, "power value");
|
||||
check.same(battle.playing_ship, ship2);
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
test.case("cools down equipment for previous ship", check => {
|
||||
let battle = TestTools.createBattle(1, 0);
|
||||
let ship = battle.play_order[0];
|
||||
|
||||
let equ1 = TestTools.addWeapon(ship);
|
||||
equ1.configureCooldown(1, 3);
|
||||
let cd1 = ship.actions.getCooldown(equ1);
|
||||
cd1.use();
|
||||
|
||||
let equ2 = TestTools.addWeapon(ship);
|
||||
equ2.configureCooldown(1, 2);
|
||||
let cd2 = ship.actions.getCooldown(equ2);
|
||||
cd2.use();
|
||||
|
||||
let equ3 = TestTools.addWeapon(ship);
|
||||
let cd3 = ship.actions.getCooldown(equ3);
|
||||
cd3.use();
|
||||
|
||||
TestTools.actionChain(check, battle, [
|
||||
[ship, EndTurnAction.SINGLETON, Target.newFromShip(ship)],
|
||||
[ship, EndTurnAction.SINGLETON, Target.newFromShip(ship)],
|
||||
[ship, EndTurnAction.SINGLETON, Target.newFromShip(ship)],
|
||||
], [
|
||||
check => {
|
||||
check.equals(cd1.heat, 3, "equ1 heat");
|
||||
check.equals(cd2.heat, 2, "equ2 heat");
|
||||
check.equals(cd3.heat, 0, "equ3 heat");
|
||||
},
|
||||
check => {
|
||||
check.equals(cd1.heat, 2, "equ1 heat");
|
||||
check.equals(cd2.heat, 1, "equ2 heat");
|
||||
check.equals(cd3.heat, 0, "equ3 heat");
|
||||
},
|
||||
check => {
|
||||
check.equals(cd1.heat, 1, "equ1 heat");
|
||||
check.equals(cd2.heat, 0, "equ2 heat");
|
||||
check.equals(cd3.heat, 0, "equ3 heat");
|
||||
},
|
||||
check => {
|
||||
check.equals(cd1.heat, 0, "equ1 heat");
|
||||
check.equals(cd2.heat, 0, "equ2 heat");
|
||||
check.equals(cd3.heat, 0, "equ3 heat");
|
||||
}
|
||||
]);
|
||||
});
|
||||
|
||||
test.case("fades sticky effects for previous ship", check => {
|
||||
let battle = TestTools.createBattle(1, 0);
|
||||
let ship = battle.play_order[0];
|
||||
|
||||
let effect1 = new BaseEffect("e1");
|
||||
let effect2 = new StickyEffect(new AttributeLimitEffect("evasion", 7), 2);
|
||||
|
||||
ship.active_effects.add(effect1);
|
||||
ship.active_effects.add(effect2);
|
||||
effect2.base.getOnDiffs(ship, ship).forEach(effect => effect.apply(battle));
|
||||
check.patch(battle, "getAreaEffects", (): [Ship, BaseEffect][] => [[ship, effect1]]);
|
||||
|
||||
TestTools.actionChain(check, battle, [
|
||||
[ship, EndTurnAction.SINGLETON, Target.newFromShip(ship)],
|
||||
[ship, EndTurnAction.SINGLETON, Target.newFromShip(ship)],
|
||||
[ship, EndTurnAction.SINGLETON, Target.newFromShip(ship)],
|
||||
], [
|
||||
check => {
|
||||
check.equals(ship.active_effects.count(), 2, "effect count");
|
||||
check.contains(ship.active_effects.ids(), effect2.id, "sticky effect active");
|
||||
check.equals((<StickyEffect>nn(ship.active_effects.get(effect2.id))).duration, 2, "duration sticky effect");
|
||||
check.equals(ship.attributes.evasion.getMaximal(), 7, "max evasion");
|
||||
},
|
||||
check => {
|
||||
check.equals(ship.active_effects.count(), 2, "effect count");
|
||||
check.contains(ship.active_effects.ids(), effect2.id, "sticky effect active");
|
||||
check.equals((<StickyEffect>nn(ship.active_effects.get(effect2.id))).duration, 1, "duration sticky effect");
|
||||
check.equals(ship.attributes.evasion.getMaximal(), 7, "max evasion");
|
||||
},
|
||||
check => {
|
||||
check.equals(ship.active_effects.count(), 1, "effect count");
|
||||
check.notcontains(ship.active_effects.ids(), effect2.id, "sticky effect removed");
|
||||
check.equals(ship.attributes.evasion.getMaximal(), Infinity, "max evasion");
|
||||
},
|
||||
check => {
|
||||
check.equals(ship.active_effects.count(), 1, "effect count");
|
||||
check.notcontains(ship.active_effects.ids(), effect2.id, "sticky effect removed");
|
||||
check.equals(ship.attributes.evasion.getMaximal(), Infinity, "max evasion");
|
||||
}
|
||||
]);
|
||||
});
|
||||
});
|
||||
}
|
|
@ -1,74 +0,0 @@
|
|||
/// <reference path="BaseAction.ts" />
|
||||
|
||||
module TK.SpaceTac {
|
||||
/**
|
||||
* Action to end the ship's turn
|
||||
*
|
||||
* This action is always available (through its singleton)
|
||||
*/
|
||||
export class EndTurnAction extends BaseAction {
|
||||
// Singleton that may be used for all ships
|
||||
static SINGLETON = new EndTurnAction();
|
||||
|
||||
constructor() {
|
||||
super("End turn");
|
||||
}
|
||||
|
||||
getVerb(ship: Ship): string {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
getTitle(ship: Ship): string {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
getPowerUsage(ship: Ship, target: Target | null): number {
|
||||
let toggled_cost = sum(ship.getToggleActions(true).map(action => action.power));
|
||||
return ship.getValue("power") + toggled_cost - ship.getAttribute("power_capacity");
|
||||
}
|
||||
|
||||
getSpecificDiffs(ship: Ship, battle: Battle, target: Target): BaseBattleDiff[] {
|
||||
if (ship.is(battle.playing_ship)) {
|
||||
let result: BaseBattleDiff[] = [];
|
||||
let new_ship = battle.getNextShip();
|
||||
|
||||
// Cool down actions
|
||||
ship.actions.listAll().forEach(action => {
|
||||
if (ship.actions.getCooldown(action).heat > 0) {
|
||||
result.push(new ShipCooldownDiff(ship, action, 1));
|
||||
}
|
||||
})
|
||||
|
||||
// "On turn end" effects
|
||||
iforeach(ship.active_effects.iterator(), effect => {
|
||||
result = result.concat(effect.getTurnEndDiffs(ship));
|
||||
});
|
||||
|
||||
// Change the active ship
|
||||
let cycle_diff = (battle.play_order.indexOf(new_ship) == 0) ? 1 : 0;
|
||||
result.push(new ShipChangeDiff(ship, new_ship, cycle_diff));
|
||||
|
||||
// "On turn start" effects
|
||||
iforeach(new_ship.active_effects.iterator(), effect => {
|
||||
result = result.concat(effect.getTurnStartDiffs(ship));
|
||||
});
|
||||
|
||||
return result;
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
protected checkShipTarget(ship: Ship, target: Target): Target | null {
|
||||
return ship.is(target.ship_id) ? target : null;
|
||||
}
|
||||
|
||||
getTargettingMode(ship: Ship): ActionTargettingMode {
|
||||
return ship.getValue("power") ? ActionTargettingMode.SELF_CONFIRM : ActionTargettingMode.SELF;
|
||||
}
|
||||
|
||||
getEffectsDescription(): string {
|
||||
return "End the current ship's turn.\nWill also generate power and cool down equipments.";
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,9 +1,8 @@
|
|||
module TK.SpaceTac.Specs {
|
||||
testing("MoveAction", test => {
|
||||
test.case("checks movement against remaining AP", check => {
|
||||
var ship = new Ship();
|
||||
var battle = new Battle(ship.fleet);
|
||||
TestTools.setShipPlaying(battle, ship);
|
||||
const battle = new Battle();
|
||||
const ship = battle.fleets[0].addShip();
|
||||
ship.setValue("power", 6);
|
||||
ship.arena_x = 0;
|
||||
ship.arena_y = 0;
|
||||
|
@ -36,7 +35,7 @@ module TK.SpaceTac.Specs {
|
|||
|
||||
test.case("applies and reverts", check => {
|
||||
let battle = TestTools.createBattle();
|
||||
let ship = battle.play_order[0];
|
||||
let ship = battle.fleets[0].ships[0];
|
||||
ship.setArenaPosition(500, 600)
|
||||
TestTools.setShipModel(ship, 100, 0, 20);
|
||||
ship.setValue("power", 5);
|
||||
|
|
|
@ -28,8 +28,6 @@ module TK.SpaceTac.Specs {
|
|||
ship3.alive = false;
|
||||
|
||||
let battle = new Battle(fleet);
|
||||
battle.play_order = [ship, ship1, ship2, ship3];
|
||||
TestTools.setShipPlaying(battle, ship);
|
||||
fleet.setBattle(battle);
|
||||
|
||||
action.apply(battle, ship, Target.newFromLocation(50, 50));
|
||||
|
@ -102,7 +100,7 @@ module TK.SpaceTac.Specs {
|
|||
|
||||
test.case("rotates toward the target", check => {
|
||||
let battle = TestTools.createBattle();
|
||||
let ship = battle.play_order[0];
|
||||
let ship = battle.fleets[0].ships[0];
|
||||
let action = TestTools.addWeapon(ship, 1, 0, 100, 30);
|
||||
check.patch(action, "checkTarget", (ship: Ship, target: Target) => target);
|
||||
check.equals(ship.arena_angle, 0);
|
||||
|
|
|
@ -84,7 +84,6 @@ module TK.SpaceTac.Specs {
|
|||
check.equals(ship2a.getValue("hull"), 10);
|
||||
check.equals(ship2b.getValue("hull"), 10);
|
||||
|
||||
TestTools.setShipPlaying(battle, ship2b);
|
||||
battle.applyOneAction(engine.id, Target.newFromLocation(500, 0));
|
||||
|
||||
check.equals(ship1a.active_effects.list(), []);
|
||||
|
|
|
@ -26,7 +26,7 @@ module TK.SpaceTac {
|
|||
|
||||
constructor(battle: Battle, debug = false) {
|
||||
this.battle = battle;
|
||||
this.ship = nn(battle.playing_ship);
|
||||
this.ship = battle.ships.list()[0]; // FIXME
|
||||
this.debug = debug;
|
||||
}
|
||||
|
||||
|
|
|
@ -45,20 +45,11 @@ module TK.SpaceTac {
|
|||
async play(): Promise<void> {
|
||||
this.started = (new Date()).getTime();
|
||||
|
||||
if (!this.ship.playing) {
|
||||
console.error(`${this.name} tries to play a ship out of turn`);
|
||||
return;
|
||||
}
|
||||
|
||||
// Work loop
|
||||
this.initWork();
|
||||
let last = new Date().getTime();
|
||||
let ship = this.ship;
|
||||
while (this.doWorkUnit()) {
|
||||
if (!this.ship.playing || this.ship != ship) {
|
||||
console.error(`${this.name} switched to another ship in unit work`);
|
||||
break;
|
||||
}
|
||||
if (this.getDuration() >= 10000) {
|
||||
console.warn(`${this.name} takes too long to play, forcing turn end`);
|
||||
break;
|
||||
|
@ -70,11 +61,6 @@ module TK.SpaceTac {
|
|||
last = t + 10;
|
||||
}
|
||||
}
|
||||
|
||||
// End the ship turn
|
||||
if (this.ship.playing) {
|
||||
this.feedback(new Maneuver(this.ship, EndTurnAction.SINGLETON, Target.newFromShip(ship)));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -52,20 +52,6 @@ module TK.SpaceTac {
|
|||
return any(this.simulation.parts, part => part.possible);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the maneuver cannot be fully done this turn
|
||||
*/
|
||||
isIncomplete(): boolean {
|
||||
return (this.simulation.need_move && !this.simulation.can_end_move) || (this.simulation.need_fire && !this.simulation.can_fire);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if another maneuver could be done next on the same ship
|
||||
*/
|
||||
mayContinue(): boolean {
|
||||
return this.ship.playing && !this.isIncomplete() && !(this.action instanceof EndTurnAction);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the location of the ship after the action
|
||||
*/
|
||||
|
@ -88,16 +74,13 @@ module TK.SpaceTac {
|
|||
* Standard feedback for this maneuver. It will apply it on the battle state.
|
||||
*/
|
||||
apply(battle: Battle): boolean {
|
||||
if (!this.ship.is(battle.playing_ship)) {
|
||||
console.error("Maneuver was not produced for the playing ship", this, battle);
|
||||
return false;
|
||||
} else if (!this.simulation.success) {
|
||||
if (!this.simulation.success) {
|
||||
return false;
|
||||
} else {
|
||||
let parts = this.simulation.parts;
|
||||
for (let i = 0; i < parts.length; i++) {
|
||||
let part = parts[i];
|
||||
if (part.action instanceof EndTurnAction || part.possible) {
|
||||
if (part.possible) {
|
||||
if (!battle.applyOneAction(part.action.id, part.target)) {
|
||||
return false;
|
||||
}
|
||||
|
@ -105,7 +88,7 @@ module TK.SpaceTac {
|
|||
return false;
|
||||
}
|
||||
}
|
||||
return this.mayContinue();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,8 +22,6 @@ module TK.SpaceTac.Specs {
|
|||
test.case("applies the highest evaluated maneuver", check => {
|
||||
let battle = new Battle();
|
||||
let ship = battle.fleets[0].addShip();
|
||||
TestTools.setShipPlaying(battle, ship);
|
||||
ship.playing = true;
|
||||
|
||||
let ai = new TacticalAI(ship, maneuver => {
|
||||
if (maneuver instanceof FixedManeuver) {
|
||||
|
|
|
@ -68,10 +68,6 @@ module TK.SpaceTac {
|
|||
console.log("AI maneuver", this.name, this.ship.name, best_maneuver, this.best_score);
|
||||
}
|
||||
|
||||
if (this.best.action instanceof EndTurnAction) {
|
||||
return false;
|
||||
}
|
||||
|
||||
let success = this.feedback(best_maneuver);
|
||||
if (success) {
|
||||
// Try to play another maneuver
|
||||
|
@ -98,7 +94,6 @@ module TK.SpaceTac {
|
|||
*/
|
||||
getDefaultProducers() {
|
||||
let producers = [
|
||||
TacticalAIHelpers.produceEndTurn,
|
||||
TacticalAIHelpers.produceDirectShots,
|
||||
TacticalAIHelpers.produceBlastShots,
|
||||
TacticalAIHelpers.produceToggleActions,
|
||||
|
|
|
@ -8,7 +8,6 @@ module TK.SpaceTac.Specs {
|
|||
let ship1b = battle.fleets[1].addShip(new Ship(null, "1B"));
|
||||
|
||||
TestTools.setShipModel(ship0a, 100, 0, 10);
|
||||
TestTools.setShipPlaying(battle, ship0a);
|
||||
|
||||
let result = imaterialize(TacticalAIHelpers.produceDirectShots(ship0a, battle));
|
||||
check.equals(result.length, 0);
|
||||
|
@ -30,7 +29,6 @@ module TK.SpaceTac.Specs {
|
|||
let ship = battle.fleets[0].addShip();
|
||||
|
||||
TestTools.setShipModel(ship, 100, 0, 10);
|
||||
TestTools.setShipPlaying(battle, ship);
|
||||
|
||||
let result = imaterialize(TacticalAIHelpers.produceRandomMoves(ship, battle, 2, 1));
|
||||
check.equals(result.length, 0);
|
||||
|
@ -51,7 +49,6 @@ module TK.SpaceTac.Specs {
|
|||
let ship = battle.fleets[0].addShip();
|
||||
let weapon = TestTools.addWeapon(ship, 50, 1, 1000, 105);
|
||||
TestTools.setShipModel(ship, 100, 0, 10, 1, [weapon]);
|
||||
TestTools.setShipPlaying(battle, ship);
|
||||
|
||||
let result = imaterialize(TacticalAIHelpers.produceInterestingBlastShots(ship, battle));
|
||||
check.equals(result.length, 0);
|
||||
|
@ -89,7 +86,6 @@ module TK.SpaceTac.Specs {
|
|||
let action3 = new VigilanceAction("Vigilance", { radius: 150 });
|
||||
TestTools.setShipModel(ship, 100, 0, 10, 1, [action1, action2, action3]);
|
||||
TestTools.addEngine(ship, 1000);
|
||||
TestTools.setShipPlaying(battle, ship);
|
||||
|
||||
check.patch(TacticalAIHelpers, "scanArena", () => iarray([
|
||||
Target.newFromLocation(1, 0),
|
||||
|
@ -158,16 +154,10 @@ module TK.SpaceTac.Specs {
|
|||
maneuver = new Maneuver(ship, engine, Target.newFromLocation(0, 48));
|
||||
check.equals(TacticalAIHelpers.evaluateIdling(ship, battle, maneuver), -0.9, "move only, at full power");
|
||||
|
||||
maneuver = new Maneuver(ship, EndTurnAction.SINGLETON, Target.newFromShip(ship));
|
||||
check.equals(TacticalAIHelpers.evaluateIdling(ship, battle, maneuver), -1, "end turn, at full power");
|
||||
|
||||
ship.setValue("power", 2);
|
||||
|
||||
maneuver = new Maneuver(ship, engine, Target.newFromLocation(0, 48));
|
||||
check.equals(TacticalAIHelpers.evaluateIdling(ship, battle, maneuver), -0.1, "move only, at reduced power");
|
||||
|
||||
maneuver = new Maneuver(ship, EndTurnAction.SINGLETON, Target.newFromShip(ship));
|
||||
check.equals(TacticalAIHelpers.evaluateIdling(ship, battle, maneuver), -0.2, "end turn, at reduced power");
|
||||
});
|
||||
|
||||
test.case("evaluates damage to enemies", check => {
|
||||
|
@ -276,7 +266,7 @@ module TK.SpaceTac.Specs {
|
|||
let battle = TestTools.createBattle();
|
||||
let ship = battle.fleets[0].ships[0];
|
||||
let enemy = battle.fleets[1].ships[0];
|
||||
TestTools.setShipModel(ship, 1, 0, 1);
|
||||
TestTools.setShipModel(ship, 5, 0, 1);
|
||||
TestTools.setShipModel(enemy, 5, 5);
|
||||
let action = new TriggerAction("Test", { range: 100, power: 1 });
|
||||
ship.actions.addCustom(action);
|
||||
|
|
|
@ -55,13 +55,6 @@ module TK.SpaceTac {
|
|||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Produce a turn end.
|
||||
*/
|
||||
static produceEndTurn(ship: Ship, battle: Battle): TacticalProducer {
|
||||
return isingle(new Maneuver(ship, EndTurnAction.SINGLETON, Target.newFromShip(ship)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Produce all "direct hit" weapon shots.
|
||||
*/
|
||||
|
@ -151,9 +144,7 @@ module TK.SpaceTac {
|
|||
static evaluateIdling(ship: Ship, battle: Battle, maneuver: Maneuver): number {
|
||||
let power_capacity = ship.getAttribute("power_capacity") || 1;
|
||||
|
||||
if (maneuver.action instanceof EndTurnAction) {
|
||||
return -ship.getValue("power") / power_capacity;
|
||||
} else if (maneuver.action instanceof TriggerAction) {
|
||||
if (maneuver.action instanceof TriggerAction) {
|
||||
return 0.5;
|
||||
} else if (maneuver.action instanceof ToggleAction) {
|
||||
return ship.actions.isToggled(maneuver.action) ? -0.2 : 0.5;
|
||||
|
|
|
@ -2,8 +2,9 @@ module TK.SpaceTac.Specs {
|
|||
testing("DroneDeployedDiff", test => {
|
||||
test.case("applies and reverts", check => {
|
||||
let battle = TestTools.createBattle();
|
||||
let drone1 = new Drone(battle.play_order[0]);
|
||||
let drone2 = new Drone(battle.play_order[0], "test");
|
||||
let ship = battle.fleets[0].ships[0];
|
||||
let drone1 = new Drone(ship);
|
||||
let drone2 = new Drone(ship, "test");
|
||||
|
||||
TestTools.diffChain(check, battle, [
|
||||
new DroneDeployedDiff(drone1),
|
||||
|
|
|
@ -1,36 +0,0 @@
|
|||
module TK.SpaceTac.Specs {
|
||||
testing("ShipChangeDiff", test => {
|
||||
test.case("applies and reverts", check => {
|
||||
let battle = new Battle();
|
||||
let attacker1 = battle.fleets[0].addShip();
|
||||
let attacker2 = battle.fleets[0].addShip();
|
||||
let defender1 = battle.fleets[1].addShip();
|
||||
battle.play_order = [defender1, attacker2, attacker1];
|
||||
battle.play_index = 0;
|
||||
battle.cycle = 1;
|
||||
|
||||
TestTools.diffChain(check, battle, [
|
||||
new ShipChangeDiff(battle.play_order[0], battle.play_order[1]),
|
||||
new ShipChangeDiff(battle.play_order[1], battle.play_order[2]),
|
||||
new ShipChangeDiff(battle.play_order[2], battle.play_order[0], 1),
|
||||
], [
|
||||
check => {
|
||||
check.same(battle.playing_ship, defender1, "first ship playing");
|
||||
check.equals(battle.cycle, 1, "first cycle");
|
||||
},
|
||||
check => {
|
||||
check.same(battle.playing_ship, attacker2, "second ship playing");
|
||||
check.equals(battle.cycle, 1, "first cycle");
|
||||
},
|
||||
check => {
|
||||
check.same(battle.playing_ship, attacker1, "third ship playing");
|
||||
check.equals(battle.cycle, 1, "first cycle");
|
||||
},
|
||||
check => {
|
||||
check.same(battle.playing_ship, defender1, "first ship playing again");
|
||||
check.equals(battle.cycle, 2, "second cycle");
|
||||
},
|
||||
]);
|
||||
});
|
||||
});
|
||||
}
|
|
@ -1,39 +0,0 @@
|
|||
/// <reference path="BaseBattleDiff.ts"/>
|
||||
|
||||
module TK.SpaceTac {
|
||||
/**
|
||||
* Current playing ship changes
|
||||
*/
|
||||
export class ShipChangeDiff extends BaseBattleShipDiff {
|
||||
// ID of the new playing ship
|
||||
new_ship: RObjectId
|
||||
|
||||
// Diff in the cycle count
|
||||
cycle_diff: number
|
||||
|
||||
constructor(ship: Ship | RObjectId, new_ship: Ship | RObjectId, cycle_diff = 0) {
|
||||
super(ship);
|
||||
|
||||
this.new_ship = (new_ship instanceof Ship) ? new_ship.id : new_ship;
|
||||
this.cycle_diff = cycle_diff;
|
||||
}
|
||||
|
||||
applyOnShip(ship: Ship, battle: Battle) {
|
||||
if (ship.is(battle.playing_ship)) {
|
||||
let new_ship = battle.getShip(this.new_ship);
|
||||
if (new_ship) {
|
||||
battle.setPlayingShip(new_ship);
|
||||
battle.cycle += this.cycle_diff;
|
||||
} else {
|
||||
console.error("Cannot apply diff - new ship not found", this);
|
||||
}
|
||||
} else {
|
||||
console.error("Cannot apply diff - ship is not playing", this);
|
||||
}
|
||||
}
|
||||
|
||||
getReverse(): BaseBattleDiff {
|
||||
return new ShipChangeDiff(this.new_ship, this.ship_id, -this.cycle_diff);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -2,7 +2,7 @@ module TK.SpaceTac.Specs {
|
|||
testing("ShipCooldownDiff", test => {
|
||||
test.case("applies and reverts", check => {
|
||||
let battle = TestTools.createBattle();
|
||||
let ship = battle.play_order[0];
|
||||
let ship = battle.fleets[0].ships[0];
|
||||
let weapon = TestTools.addWeapon(ship);
|
||||
weapon.configureCooldown(1, 3);
|
||||
let cooldown = ship.actions.getCooldown(weapon);
|
||||
|
|
|
@ -2,7 +2,7 @@ module TK.SpaceTac.Specs {
|
|||
testing("ShipDamageDiff", test => {
|
||||
test.case("applies and reverts", check => {
|
||||
let battle = TestTools.createBattle();
|
||||
let ship = battle.play_order[0];
|
||||
let ship = battle.fleets[0].ships[0];
|
||||
TestTools.setShipModel(ship, 80, 100);
|
||||
|
||||
TestTools.diffChain(check, battle, [
|
||||
|
|
|
@ -5,7 +5,6 @@ module TK.SpaceTac.Specs {
|
|||
let ship1 = battle.fleets[0].addShip();
|
||||
let ship2 = battle.fleets[0].addShip();
|
||||
let ship3 = battle.fleets[1].addShip();
|
||||
battle.play_order = [ship3, ship2, ship1];
|
||||
|
||||
TestTools.diffChain(check, battle, [
|
||||
new ShipDeathDiff(battle, ship2)
|
||||
|
@ -16,7 +15,6 @@ module TK.SpaceTac.Specs {
|
|||
check.equals(imaterialize(battle.iships(true)), [ship1, ship2, ship3], "in alive ships");
|
||||
check.equals(battle.fleets[0].ships, [ship1, ship2], "fleet1");
|
||||
check.equals(battle.fleets[1].ships, [ship3], "fleet2");
|
||||
check.equals(battle.play_order, [ship3, ship2, ship1], "in play order");
|
||||
},
|
||||
check => {
|
||||
check.equals(ship2.alive, false, "dead");
|
||||
|
@ -24,7 +22,6 @@ module TK.SpaceTac.Specs {
|
|||
check.equals(imaterialize(battle.iships(true)), [ship1, ship3], "not in alive ships anymore");
|
||||
check.equals(battle.fleets[0].ships, [ship1, ship2], "fleet1");
|
||||
check.equals(battle.fleets[1].ships, [ship3], "fleet2");
|
||||
check.equals(battle.play_order, [ship3, ship1], "removed from play order");
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
|
|
@ -5,30 +5,19 @@ module TK.SpaceTac {
|
|||
* A ship dies (or rather is put in emergency stasis mode)
|
||||
*
|
||||
* This typically happens when the ship's hull reaches 0.
|
||||
* A dead ship cannot be interacted with, and will be removed from play order.
|
||||
* A dead ship cannot be interacted with.
|
||||
*/
|
||||
export class ShipDeathDiff extends BaseBattleShipDiff {
|
||||
// Index in the play order at which the ship was
|
||||
play_index: number
|
||||
|
||||
constructor(battle: Battle, ship: Ship) {
|
||||
super(ship);
|
||||
|
||||
this.play_index = battle.play_order.indexOf(ship);
|
||||
}
|
||||
|
||||
protected applyOnShip(ship: Ship, battle: Battle): void {
|
||||
ship.alive = false;
|
||||
if (this.play_index >= 0) {
|
||||
battle.removeFromPlayOrder(this.play_index);
|
||||
}
|
||||
}
|
||||
|
||||
protected revertOnShip(ship: Ship, battle: Battle): void {
|
||||
ship.alive = true;
|
||||
if (this.play_index >= 0) {
|
||||
battle.insertInPlayOrder(this.play_index, ship);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@ module TK.SpaceTac.Specs {
|
|||
testing("ShipEffectAddedDiff", test => {
|
||||
test.case("applies and reverts", check => {
|
||||
let battle = TestTools.createBattle();
|
||||
let ship = battle.play_order[0];
|
||||
let ship = battle.fleets[0].ships[0];
|
||||
|
||||
let effect1 = new BaseEffect("e1");
|
||||
let effect2 = new BaseEffect("e2");
|
||||
|
|
|
@ -2,7 +2,7 @@ module TK.SpaceTac.Specs {
|
|||
testing("ShipEffectChangedDiff", test => {
|
||||
test.case("applies and reverts", check => {
|
||||
let battle = TestTools.createBattle();
|
||||
let ship = battle.play_order[0];
|
||||
let ship = battle.fleets[0].ships[0];
|
||||
|
||||
let effect1 = new BaseEffect("e1");
|
||||
let effect2 = new StickyEffect(new BaseEffect("e2"), 2);
|
||||
|
@ -41,7 +41,7 @@ module TK.SpaceTac.Specs {
|
|||
|
||||
test.case("leaves original effect untouched", check => {
|
||||
let battle = TestTools.createBattle();
|
||||
let ship = battle.play_order[0];
|
||||
let ship = battle.fleets[0].ships[0];
|
||||
|
||||
let effect = new StickyEffect(new BaseEffect("effect"), 2);
|
||||
let effect_at_removal = copy(effect);
|
||||
|
|
|
@ -85,10 +85,6 @@ module TK.SpaceTac.UI.Specs {
|
|||
view.splash = false;
|
||||
|
||||
let battle = Battle.newQuickRandom();
|
||||
if (nn(battle.playing_ship).fleet != battle.fleets[0]) {
|
||||
// Ensure the player plays first (to not trigger AI)
|
||||
battle.fleets.push(nn(battle.fleets.shift()));
|
||||
}
|
||||
let player = battle.fleets[0].player;
|
||||
|
||||
return [view, { player, battle }];
|
||||
|
|
|
@ -10,24 +10,23 @@ module TK.SpaceTac.UI.Specs {
|
|||
bar.setShip(ship);
|
||||
check.equals(bar.action_icons.length, 0);
|
||||
|
||||
// Ship with no equipment (only endturn action)
|
||||
// Ship with no equipment
|
||||
let player = new Player();
|
||||
ship.fleet.setPlayer(player);
|
||||
testgame.view.player = player;
|
||||
bar.setShip(ship);
|
||||
check.equals(bar.action_icons.length, 1);
|
||||
check.equals(bar.action_icons[0].action.code, "endturn");
|
||||
check.equals(bar.action_icons.length, 0);
|
||||
|
||||
// Add an engine, with move action
|
||||
TestTools.addEngine(ship, 50);
|
||||
bar.setShip(ship);
|
||||
check.equals(bar.action_icons.length, 2);
|
||||
check.equals(bar.action_icons.length, 1);
|
||||
check.equals(bar.action_icons[0].action.code, "move");
|
||||
|
||||
// Add a weapon, with fire action
|
||||
TestTools.addWeapon(ship, 10, 1, 100);
|
||||
bar.setShip(ship);
|
||||
check.equals(bar.action_icons.length, 3);
|
||||
check.equals(bar.action_icons.length, 2);
|
||||
check.equals(bar.action_icons[1].action.code, "weapon");
|
||||
});
|
||||
|
||||
|
|
|
@ -88,24 +88,11 @@ module TK.SpaceTac.UI {
|
|||
icons.forEach(icon => icon.refresh());
|
||||
}
|
||||
}
|
||||
} else if (diff instanceof ShipChangeDiff) {
|
||||
return {
|
||||
background: async () => {
|
||||
this.setShip(null);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return {}
|
||||
}
|
||||
});
|
||||
|
||||
battleview.log_processor.watchForShipChange(ship => {
|
||||
return {
|
||||
background: async () => {
|
||||
this.setShip(ship);
|
||||
}
|
||||
}
|
||||
});
|
||||
this.setInteractivity(false);
|
||||
}
|
||||
|
||||
|
|
|
@ -59,15 +59,13 @@ module TK.SpaceTac.UI {
|
|||
this.img_action.setAlpha(0.2);
|
||||
|
||||
// Hotkey indicator
|
||||
if (!(action instanceof EndTurnAction)) {
|
||||
this.shortcut_container = builder.container("shortcut", 0, -47);
|
||||
builder.in(this.shortcut_container, builder => {
|
||||
builder.image("battle-actionbar-hotkey", 0, 0, true);
|
||||
builder.text(`${(position + 1) % 10}`, 0, -4, {
|
||||
size: 12, color: "#d1d1d1", shadow: true, center: true, vcenter: true
|
||||
});
|
||||
this.shortcut_container = builder.container("shortcut", 0, -47);
|
||||
builder.in(this.shortcut_container, builder => {
|
||||
builder.image("battle-actionbar-hotkey", 0, 0, true);
|
||||
builder.text(`${(position + 1) % 10}`, 0, -4, {
|
||||
size: 12, color: "#d1d1d1", shadow: true, center: true, vcenter: true
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Bottom indicator
|
||||
this.img_bottom = builder.image("battle-actionbar-bottom-disabled", 0, 40, true);
|
||||
|
|
|
@ -9,7 +9,6 @@ module TK.SpaceTac.UI.Specs {
|
|||
|
||||
let action1 = ship.actions.addCustom(new MoveAction("Thruster"));
|
||||
let action2 = ship.actions.addCustom(new TriggerAction("Superweapon", { effects: [new DamageEffect(12)], power: 2, range: 50 }));
|
||||
let action3 = ship.actions.addCustom(new EndTurnAction());
|
||||
|
||||
ActionTooltip.fill(tooltip.getBuilder(), ship, action1, 0);
|
||||
checkText(check, tooltip.container.content.list[1], "Use Thruster");
|
||||
|
@ -23,12 +22,6 @@ module TK.SpaceTac.UI.Specs {
|
|||
checkText(check, tooltip.container.content.list[2], "Cost: 2 power");
|
||||
checkText(check, tooltip.container.content.list[3], "Fire (power 2, range 50km):\n• do 12 damage on target");
|
||||
checkText(check, tooltip.container.content.list[4], "[ 2 ]");
|
||||
|
||||
tooltip.hide();
|
||||
ActionTooltip.fill(tooltip.getBuilder(), ship, action3, 2);
|
||||
checkText(check, tooltip.container.content.list[1], "End turn");
|
||||
checkText(check, tooltip.container.content.list[2], "End the current ship's turn.\nWill also generate power and cool down equipments.");
|
||||
checkText(check, tooltip.container.content.list[3], "[ space ]");
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
|
@ -51,9 +51,7 @@ module TK.SpaceTac.UI {
|
|||
|
||||
if (typeof position != "undefined") {
|
||||
let shortcut = "";
|
||||
if (action instanceof EndTurnAction) {
|
||||
shortcut = "[ space ]";
|
||||
} else if (position == 9) {
|
||||
if (position == 9) {
|
||||
shortcut = "[ 0 ]";
|
||||
} else if (position >= 0 && position < 9) {
|
||||
shortcut = `[ ${position + 1} ]`;
|
||||
|
|
|
@ -22,8 +22,8 @@ module TK.SpaceTac.UI {
|
|||
|
||||
// Currently hovered ship
|
||||
private hovered: ArenaShip | null
|
||||
// Currently playing ship
|
||||
private playing: ArenaShip | null
|
||||
// Currently selected ship
|
||||
private selected: ArenaShip | null
|
||||
|
||||
// Layer for particles
|
||||
container: UIContainer
|
||||
|
@ -41,7 +41,7 @@ module TK.SpaceTac.UI {
|
|||
// Create a graphical arena for ship sprites to fight in a 2D space
|
||||
constructor(view: BattleView, container?: UIContainer) {
|
||||
this.view = view;
|
||||
this.playing = null;
|
||||
this.selected = null;
|
||||
this.hovered = null;
|
||||
this.range_hint = new RangeHint(this);
|
||||
|
||||
|
@ -69,13 +69,6 @@ module TK.SpaceTac.UI {
|
|||
|
||||
view.log_processor.register(diff => this.checkDroneDeployed(diff));
|
||||
view.log_processor.register(diff => this.checkDroneRecalled(diff));
|
||||
view.log_processor.watchForShipChange(ship => {
|
||||
return {
|
||||
foreground: async () => {
|
||||
await this.setShipPlaying(ship)
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -201,22 +194,22 @@ module TK.SpaceTac.UI {
|
|||
}
|
||||
|
||||
/**
|
||||
* Set the playing state on a ship sprite
|
||||
* Set the currently selected ship
|
||||
*/
|
||||
async setShipPlaying(ship: Ship | null, animate = true): Promise<void> {
|
||||
if (this.playing) {
|
||||
this.playing.setPlaying(false);
|
||||
this.playing = null;
|
||||
async setSelectedShip(ship: Ship | null, animate = true): Promise<void> {
|
||||
if (this.selected) {
|
||||
this.selected.setSelected(false);
|
||||
this.selected = null;
|
||||
}
|
||||
|
||||
if (ship) {
|
||||
let arena_ship = this.findShipSprite(ship);
|
||||
if (arena_ship) {
|
||||
this.layer_ships.bringToTop(arena_ship);
|
||||
await arena_ship.setPlaying(true, animate);
|
||||
await arena_ship.setSelected(true, animate);
|
||||
}
|
||||
|
||||
this.playing = arena_ship;
|
||||
this.selected = arena_ship;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@ module TK.SpaceTac.UI.Specs {
|
|||
let testgame = setupBattleview(test);
|
||||
|
||||
test.case("adds effects display", check => {
|
||||
let ship = nn(testgame.view.battle.playing_ship);
|
||||
let ship = testgame.view.battle.fleets[0].ships[0];
|
||||
let sprite = nn(testgame.view.arena.findShipSprite(ship));
|
||||
|
||||
check.equals(sprite.effects_messages.list.length, 0);
|
||||
|
@ -16,7 +16,7 @@ module TK.SpaceTac.UI.Specs {
|
|||
|
||||
test.case("adds sticky effects display", check => {
|
||||
let battle = testgame.view.actual_battle;
|
||||
let ship = nn(battle.playing_ship);
|
||||
let ship = testgame.view.battle.fleets[0].ships[0];
|
||||
let sprite = nn(testgame.view.arena.findShipSprite(ship));
|
||||
|
||||
check.equals(sprite.active_effects_display.list.length, 0);
|
||||
|
|
|
@ -27,14 +27,9 @@ module TK.SpaceTac.UI {
|
|||
life_evasion: UIContainer
|
||||
toggle_hsp: Toggle
|
||||
|
||||
// Play order
|
||||
play_order_container: UIContainer
|
||||
play_order: UIText
|
||||
toggle_play_order: Toggle
|
||||
|
||||
// Frames to indicate the owner, if the ship is hovered, and if it is hovered
|
||||
// Frames to indicate the owner, if the ship is selected, and if it is hovered
|
||||
frame_owner: UIImage
|
||||
frame_playing: UIImage
|
||||
frame_selected: UIImage
|
||||
frame_hover: UIImage
|
||||
|
||||
// Effects display
|
||||
|
@ -59,8 +54,8 @@ module TK.SpaceTac.UI {
|
|||
|
||||
// Add frame indicating which side this ship is on
|
||||
this.frame_owner = builder.image(this.enemy ? "battle-hud-ship-enemy" : "battle-hud-ship-own", 0, 0, true);
|
||||
this.frame_playing = builder.image(this.enemy ? "battle-hud-ship-enemy-playing" : "battle-hud-ship-own-playing", 0, 0, true);
|
||||
this.setPlaying(false);
|
||||
this.frame_selected = builder.image(this.enemy ? "battle-hud-ship-enemy-selected" : "battle-hud-ship-own-selected", 0, 0, true);
|
||||
this.setSelected(false);
|
||||
this.frame_hover = builder.image("battle-hud-ship-hover", 0, 0, true);
|
||||
this.frame_hover.setVisible(false);
|
||||
|
||||
|
@ -83,20 +78,11 @@ module TK.SpaceTac.UI {
|
|||
this.life_evasion = builder.in(this.hsp).container("evasion");
|
||||
this.toggle_hsp = this.battleview.animations.newVisibilityToggle(this.hsp, 200, false);
|
||||
|
||||
// Play order display
|
||||
this.play_order_container = builder.container("play_order", -44, 0);
|
||||
builder.in(this.play_order_container).image("battle-hud-ship-play-order", 0, 0, true);
|
||||
this.play_order = builder.in(this.play_order_container).text("", -2, 1, {
|
||||
size: 12, bold: true, color: "#d1d1d1", shadow: true, center: true
|
||||
});
|
||||
this.toggle_play_order = this.battleview.animations.newVisibilityToggle(this.play_order_container, 200, false);
|
||||
|
||||
// Effects display
|
||||
this.active_effects_display = builder.container("active-effects", 0, -44);
|
||||
this.effects_messages = builder.container("effects-messages");
|
||||
this.effects_messages_toggle = this.battleview.animations.newVisibilityToggle(this.effects_messages, 500, false);
|
||||
|
||||
this.updatePlayOrder();
|
||||
this.updateHull(this.ship.getValue("hull"));
|
||||
this.updateShield(this.ship.getValue("shield"));
|
||||
this.updateEvasion(this.ship.getAttribute("evasion"));
|
||||
|
@ -104,7 +90,7 @@ module TK.SpaceTac.UI {
|
|||
this.updateEffectsRadius();
|
||||
|
||||
// Set location
|
||||
if (this.battleview.battle.cycle == 1 && this.battleview.battle.play_index == 0 && ship.alive && this.battleview.player.is(ship.fleet.player)) {
|
||||
if (this.battleview.battle.cycle == 1) {
|
||||
this.setPosition(ship.arena_x - 500 * Math.cos(ship.arena_angle), ship.arena_y - 500 * Math.sin(ship.arena_angle));
|
||||
this.moveToArenaLocation(ship.arena_x, ship.arena_y, ship.arena_angle, 1);
|
||||
} else {
|
||||
|
@ -112,7 +98,6 @@ module TK.SpaceTac.UI {
|
|||
}
|
||||
|
||||
// Log processing
|
||||
this.battleview.log_processor.register(diff => this.processBattleDiff(diff));
|
||||
this.battleview.log_processor.registerForShip(ship, diff => this.processShipDiff(diff));
|
||||
}
|
||||
|
||||
|
@ -120,16 +105,6 @@ module TK.SpaceTac.UI {
|
|||
return `ArenaShip ${this.ship.jasmineToString()}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Process a battle diff
|
||||
*/
|
||||
private processBattleDiff(diff: BaseBattleDiff) {
|
||||
if (diff instanceof ShipChangeDiff) {
|
||||
this.updatePlayOrder();
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
/**
|
||||
* Process a ship diff
|
||||
*/
|
||||
|
@ -222,16 +197,7 @@ module TK.SpaceTac.UI {
|
|||
} else if (diff instanceof ShipActionUsedDiff) {
|
||||
let action = this.ship.actions.getById(diff.action);
|
||||
if (action) {
|
||||
if (action instanceof EndTurnAction) {
|
||||
return {
|
||||
foreground: async (speed: number) => {
|
||||
if (speed) {
|
||||
await this.displayEffect("End turn", true, speed);
|
||||
await timer.sleep(500 / speed);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (!(action instanceof ToggleAction)) {
|
||||
if (!(action instanceof ToggleAction)) {
|
||||
let action_name = action.name;
|
||||
return {
|
||||
foreground: async (speed: number) => {
|
||||
|
@ -283,32 +249,22 @@ module TK.SpaceTac.UI {
|
|||
*/
|
||||
setHovered(hovered: boolean, tactical: boolean) {
|
||||
let client = tactical ? "tactical" : "hover";
|
||||
|
||||
if (hovered && this.ship.alive) {
|
||||
this.toggle_hsp.manipulate(client)(true);
|
||||
if (tactical) {
|
||||
this.toggle_play_order.manipulate(client)(true);
|
||||
}
|
||||
} else {
|
||||
this.toggle_hsp.manipulate(client)(false);
|
||||
this.toggle_play_order.manipulate(client)(false);
|
||||
}
|
||||
|
||||
this.toggle_hsp.manipulate(client)(hovered && this.ship.alive);
|
||||
this.battleview.animations.setVisible(this.frame_hover, hovered && this.ship.alive && !tactical, 200);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the playing state on this ship
|
||||
* Set the selected state on this ship
|
||||
*
|
||||
* This will alter the HUD frame to show this state
|
||||
*/
|
||||
async setPlaying(playing: boolean, animate = true): Promise<void> {
|
||||
async setSelected(selected: boolean, animate = true): Promise<void> {
|
||||
this.frame_owner.setVisible(this.ship.alive);
|
||||
this.frame_playing.setVisible(this.ship.alive && playing);
|
||||
this.frame_selected.setVisible(this.ship.alive && selected);
|
||||
|
||||
if (playing && animate) {
|
||||
if (selected && animate) {
|
||||
this.battleview.audio.playOnce("battle-ship-change");
|
||||
await this.battleview.animations.blink(this.frame_playing);
|
||||
await this.battleview.animations.blink(this.frame_selected);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -324,7 +280,7 @@ module TK.SpaceTac.UI {
|
|||
} else {
|
||||
this.stasis.visible = false;
|
||||
}
|
||||
this.setPlaying(false);
|
||||
this.setSelected(false);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -384,18 +340,6 @@ module TK.SpaceTac.UI {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the play order indicator
|
||||
*/
|
||||
updatePlayOrder(): void {
|
||||
let play_order = this.battleview.battle.getPlayOrder(this.ship);
|
||||
if (play_order == 0) {
|
||||
this.play_order.setText("-");
|
||||
} else {
|
||||
this.play_order.setText(play_order.toString());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reposition the HSP indicators
|
||||
*/
|
||||
|
|
|
@ -6,11 +6,11 @@ module TK.SpaceTac.UI.Specs {
|
|||
let battleview = testgame.view;
|
||||
check.equals(battleview.ship_hovered, null, "initial state");
|
||||
|
||||
let ship = nn(battleview.battle.playing_ship);
|
||||
let ship = battleview.battle.fleets[0].ships[0];
|
||||
battleview.cursorHovered(ship.location, ship);
|
||||
check.same(battleview.ship_hovered, ship, "ship1 hovered");
|
||||
|
||||
ship = nn(battleview.battle.play_order[1]);
|
||||
ship = battleview.battle.fleets[1].ships[0];
|
||||
battleview.cursorHovered(ship.location, ship);
|
||||
check.same(battleview.ship_hovered, ship, "ship2 hovered");
|
||||
|
||||
|
@ -20,7 +20,7 @@ module TK.SpaceTac.UI.Specs {
|
|||
battleview.cursorOnShip(ship);
|
||||
check.same(battleview.ship_hovered, ship, "force on");
|
||||
|
||||
battleview.cursorOffShip(battleview.battle.play_order[2]);
|
||||
battleview.cursorOffShip(battleview.battle.fleets[1].ships[1]);
|
||||
check.same(battleview.ship_hovered, ship, "force off on wrong ship");
|
||||
|
||||
battleview.cursorOffShip(ship);
|
||||
|
@ -32,7 +32,7 @@ module TK.SpaceTac.UI.Specs {
|
|||
check.equals(battleview.targetting.active, false);
|
||||
battleview.setInteractionEnabled(true);
|
||||
|
||||
let ship = nn(battleview.battle.playing_ship);
|
||||
let ship = battleview.battle.fleets[0].ships[0];
|
||||
let weapon = TestTools.addWeapon(ship, 10);
|
||||
battleview.enterTargettingMode(ship, weapon, ActionTargettingMode.SPACE);
|
||||
check.equals(battleview.targetting.active, true);
|
||||
|
@ -41,7 +41,7 @@ module TK.SpaceTac.UI.Specs {
|
|||
check.equals(battleview.targetting.target, Target.newFromLocation(5, 8));
|
||||
check.equals(battleview.ship_hovered, null);
|
||||
|
||||
ship = battleview.battle.play_order[3];
|
||||
ship = battleview.battle.fleets[1].ships[0];
|
||||
battleview.cursorHovered(ship.location, ship);
|
||||
check.equals(battleview.targetting.target, Target.newFromLocation(ship.arena_x, ship.arena_y));
|
||||
check.equals(battleview.ship_hovered, null);
|
||||
|
@ -67,6 +67,7 @@ module TK.SpaceTac.UI.Specs {
|
|||
test.case("allows to choose an action and a target with shortcut keys", check => {
|
||||
let battleview = testgame.view;
|
||||
battleview.setInteractionEnabled(true);
|
||||
battleview.setShipSelected(battleview.battle.fleets[0].ships[0]);
|
||||
let action_icon = battleview.action_bar.action_icons[0];
|
||||
|
||||
check.equals(battleview.targetting.active, false);
|
||||
|
@ -79,21 +80,23 @@ module TK.SpaceTac.UI.Specs {
|
|||
battleview.numberPressed(3);
|
||||
check.equals(battleview.targetting.active, true);
|
||||
check.same(battleview.targetting.action, action_icon.action);
|
||||
check.equals(battleview.targetting.target, Target.newFromShip(battleview.battle.play_order[3]));
|
||||
check.equals(battleview.targetting.target, Target.newFromShip(battleview.battle.ships.list()[2]));
|
||||
battleview.numberPressed(4);
|
||||
check.equals(battleview.targetting.active, true);
|
||||
check.same(battleview.targetting.action, action_icon.action);
|
||||
check.equals(battleview.targetting.target, Target.newFromShip(battleview.battle.play_order[4]));
|
||||
check.equals(battleview.targetting.target, Target.newFromShip(battleview.battle.ships.list()[3]));
|
||||
});
|
||||
|
||||
test.case("adds player actions to plan", check => {
|
||||
let battleview = testgame.view;
|
||||
let playing_ship = nn(battleview.battle.playing_ship);
|
||||
check.equals(battleview.turn_plannings.length, 2);
|
||||
check.equals(battleview.turn_plannings[0].collectAllActions(), []);
|
||||
check.equals(battleview.turn_plannings[1].collectAllActions(), []);
|
||||
|
||||
let action = nn(first(playing_ship.actions.listAll(), action => action instanceof MoveAction));
|
||||
let ship = battleview.battle.fleets[0].ships[0];
|
||||
let action = nn(first(ship.actions.listAll(), action => action instanceof MoveAction));
|
||||
|
||||
battleview.setShipSelected(ship);
|
||||
battleview.applyPlayerAction(action, Target.newFromLocation(0, 0));
|
||||
check.equals(battleview.turn_plannings.length, 2);
|
||||
check.equals(battleview.turn_plannings[0].collectAllActions(), [
|
||||
|
|
|
@ -52,7 +52,10 @@ module TK.SpaceTac.UI {
|
|||
action_bar!: ActionBar
|
||||
|
||||
// Currently hovered ship
|
||||
ship_hovered!: Ship | null
|
||||
ship_hovered: Ship | null = null
|
||||
|
||||
// Currently selected ship
|
||||
ship_selected: Ship | null = null
|
||||
|
||||
// Ship tooltip
|
||||
ship_tooltip!: ShipTooltip
|
||||
|
@ -81,6 +84,7 @@ module TK.SpaceTac.UI {
|
|||
this.battle = duplicate(data.battle, <any>TK.SpaceTac);
|
||||
this.turn_plannings = this.battle.fleets.map(fleet => new TurnPlanning(this.battle, fleet.player));
|
||||
this.ship_hovered = null;
|
||||
this.ship_selected = null;
|
||||
this.background = null;
|
||||
this.multi = new MultiBattle();
|
||||
|
||||
|
@ -198,14 +202,19 @@ module TK.SpaceTac.UI {
|
|||
return false;
|
||||
}
|
||||
|
||||
let done = false;
|
||||
this.turn_plannings.forEach(planning => {
|
||||
if (this.action_bar.ship && this.player.is(planning.player)) {
|
||||
planning.addAction(this.action_bar.ship, action, target);
|
||||
const ship = this.ship_selected;
|
||||
if (ship && this.player.is(planning.player) && this.player.is(ship.getPlayer())) {
|
||||
planning.addAction(ship, action, target);
|
||||
done = true;
|
||||
}
|
||||
});
|
||||
this.planningsChanged();
|
||||
|
||||
return false;
|
||||
if (done) {
|
||||
this.planningsChanged();
|
||||
}
|
||||
return done;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -252,7 +261,7 @@ module TK.SpaceTac.UI {
|
|||
numberPressed(num: number): void {
|
||||
if (this.interacting) {
|
||||
if (this.targetting.active) {
|
||||
let ship = ifirst(this.battle.iships(true), ship => this.battle.getPlayOrder(ship) == num % 10);
|
||||
const ship = this.battle.ships.list()[num - 1];
|
||||
if (ship) {
|
||||
this.targetting.setTarget(Target.newFromShip(ship));
|
||||
}
|
||||
|
@ -312,9 +321,8 @@ module TK.SpaceTac.UI {
|
|||
cursorClicked(): void {
|
||||
if (this.targetting.active) {
|
||||
this.validationPressed();
|
||||
} else if (this.ship_hovered && this.player.is(this.ship_hovered.fleet.player) && this.interacting) {
|
||||
this.character_sheet.show(this.ship_hovered);
|
||||
this.setShipHovered(null);
|
||||
} else if (this.ship_hovered && this.player.is(this.ship_hovered.getPlayer()) && this.interacting) {
|
||||
this.setShipSelected(this.ship_hovered);
|
||||
} else {
|
||||
this.log_processor.fastForward();
|
||||
}
|
||||
|
@ -334,6 +342,21 @@ module TK.SpaceTac.UI {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the currently selected ship
|
||||
*/
|
||||
setShipSelected(ship: Ship | null): void {
|
||||
if (ship && !this.player.is(ship.getPlayer())) {
|
||||
ship = null;
|
||||
}
|
||||
|
||||
this.setShipHovered(null);
|
||||
|
||||
this.ship_selected = ship;
|
||||
this.arena.setSelectedShip(ship);
|
||||
this.action_bar.setShip(ship);
|
||||
}
|
||||
|
||||
// Enable or disable the global player interaction
|
||||
// Disable interaction when it is the AI turn, or when the current ship can't play
|
||||
setInteractionEnabled(enabled: boolean): void {
|
||||
|
|
|
@ -105,18 +105,6 @@ module TK.SpaceTac.UI {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if we need a player or AI to interact at this point
|
||||
*/
|
||||
getPlayerNeeded(): Player | null {
|
||||
if (this.log.isPlaying() && this.log.atEnd()) {
|
||||
let playing_ship = this.view.actual_battle.playing_ship;
|
||||
return playing_ship ? playing_ship.getPlayer() : null;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a diff subscriber
|
||||
*/
|
||||
|
@ -137,54 +125,6 @@ module TK.SpaceTac.UI {
|
|||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Register to playing ship changes
|
||||
*
|
||||
* If *initial* is true, the callback will be fired once at register time
|
||||
*
|
||||
* If *immediate* is true, the ShipChangeDiff is watched, otherwise the end of the EndTurn action
|
||||
*/
|
||||
watchForShipChange(callback: (ship: Ship) => LogProcessorDelegate, initial = true, immediate = false) {
|
||||
this.register(diff => {
|
||||
let changed = false;
|
||||
if (immediate && diff instanceof ShipChangeDiff) {
|
||||
changed = true;
|
||||
} else if (!immediate && diff instanceof ShipActionEndedDiff) {
|
||||
let ship = this.view.battle.getShip(diff.ship_id);
|
||||
if (ship && ship.actions.getById(diff.action) instanceof EndTurnAction) {
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (changed) {
|
||||
let ship = this.view.battle.playing_ship;
|
||||
if (ship) {
|
||||
return callback(ship);
|
||||
} else {
|
||||
return {};
|
||||
}
|
||||
} else {
|
||||
return {};
|
||||
}
|
||||
});
|
||||
|
||||
if (initial) {
|
||||
let ship = this.view.battle.playing_ship;
|
||||
if (ship) {
|
||||
let result = callback(ship);
|
||||
if (result.foreground) {
|
||||
let promise = result.foreground(0);
|
||||
if (result.background) {
|
||||
let next = result.background;
|
||||
promise.then(() => next(0));
|
||||
}
|
||||
} else if (result.background) {
|
||||
result.background(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Process a single battle diff
|
||||
*/
|
||||
|
@ -217,18 +157,8 @@ module TK.SpaceTac.UI {
|
|||
* Transfer control to the needed player (or not)
|
||||
*/
|
||||
private transferControl() {
|
||||
let player = this.getPlayerNeeded();
|
||||
if (player) {
|
||||
if (player.is(this.view.player)) {
|
||||
this.view.setInteractionEnabled(true);
|
||||
} else if (!this.ai_disabled) {
|
||||
this.view.playAI();
|
||||
} else {
|
||||
this.view.applyPlayerAction(EndTurnAction.SINGLETON);
|
||||
}
|
||||
} else {
|
||||
this.view.setInteractionEnabled(false);
|
||||
}
|
||||
// TODO Should be done by the battleview itself
|
||||
this.view.setInteractionEnabled(this.view.battle.canPlay(this.view.player));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -236,7 +166,8 @@ module TK.SpaceTac.UI {
|
|||
*/
|
||||
private checkReaction(diff: BaseBattleDiff): LogProcessorDelegate {
|
||||
if (this.log.isPlaying()) {
|
||||
let reaction = this.view.session.reactions.check(this.view.player, this.view.battle, this.view.battle.playing_ship, diff);
|
||||
let playing_ship = null; // FIXME
|
||||
let reaction = this.view.session.reactions.check(this.view.player, this.view.battle, playing_ship, diff);
|
||||
if (reaction) {
|
||||
return {
|
||||
foreground: async () => {
|
||||
|
|
|
@ -4,7 +4,7 @@ module TK.SpaceTac.UI.Specs {
|
|||
|
||||
test.case("fills ship details", check => {
|
||||
let tooltip = new ShipTooltip(testgame.view);
|
||||
let ship = testgame.view.battle.play_order[2];
|
||||
let ship = testgame.view.battle.fleets[0].ships[0];
|
||||
TestTools.setShipModel(ship, 58, 140, 12);
|
||||
ship.name = "Fury";
|
||||
ship.model = new ShipModel("fake", "Fury");
|
||||
|
@ -25,7 +25,7 @@ module TK.SpaceTac.UI.Specs {
|
|||
check.contains(images, "battle-hud-ship-effect-good");
|
||||
check.contains(images, "battle-hud-ship-effect-bad");
|
||||
check.equals(texts, [
|
||||
"Level 1 Fury", "Plays in 2 turns",
|
||||
"Level 1 Fury",
|
||||
"57", "max", "58", "100", "max", "140", "7", "9", "max", "12",
|
||||
"Weapon", "hull capacity +50", "limit shield capacity to 2 for 3 turns",
|
||||
"Super ship model !"
|
||||
|
|
|
@ -42,11 +42,6 @@ module TK.SpaceTac.UI {
|
|||
builder.text(ship.getName(), 230, 0, { color: enemy ? "#c06858" : "#65a898", size: 22, bold: true });
|
||||
|
||||
if (ship.alive) {
|
||||
if (battle) {
|
||||
let turns = battle.getPlayOrder(ship);
|
||||
builder.text((turns == 0) ? "Playing" : ((turns == 1) ? "Plays next" : `Plays in ${turns} turns`), 230, 36, { color: "#cccccc", size: 18 });
|
||||
}
|
||||
|
||||
ShipTooltip.addValue(builder, 0, "#eb4e4a", "attribute-hull_capacity", ship.getValue("hull"), ship.getAttribute("hull_capacity"));
|
||||
ShipTooltip.addValue(builder, 1, "#2ad8dc", "attribute-shield_capacity", ship.getValue("shield"), ship.getAttribute("shield_capacity"));
|
||||
ShipTooltip.addValue(builder, 2, "#c1f06b", "attribute-evasion", ship.getAttribute("evasion"));
|
||||
|
@ -55,7 +50,7 @@ module TK.SpaceTac.UI {
|
|||
let iy = 210;
|
||||
|
||||
ship.actions.listAll().forEach(action => {
|
||||
if (!(action instanceof EndTurnAction) && !(action instanceof MoveAction)) {
|
||||
if (!(action instanceof MoveAction)) {
|
||||
let icon = builder.image(`action-${action.code}`, 0, iy);
|
||||
icon.setScale(0.15);
|
||||
builder.text(action.name, 46, iy + 8);
|
||||
|
|
|
@ -12,7 +12,7 @@ module TK.SpaceTac.UI.Specs {
|
|||
test.case("draws simulation parts", check => {
|
||||
let targetting = newTargetting();
|
||||
|
||||
let ship = nn(testgame.view.battle.playing_ship);
|
||||
let ship = testgame.view.battle.fleets[0].ships[0];
|
||||
ship.setArenaPosition(10, 20);
|
||||
let weapon = TestTools.addWeapon(ship);
|
||||
let engine = TestTools.addEngine(ship, 12);
|
||||
|
@ -46,7 +46,7 @@ module TK.SpaceTac.UI.Specs {
|
|||
|
||||
test.case("updates impact indicators on ships inside the blast radius", check => {
|
||||
let targetting = newTargetting();
|
||||
let ship = nn(testgame.view.battle.playing_ship);
|
||||
let ship = testgame.view.battle.fleets[0].ships[0];
|
||||
let impacts = targetting.impact_indicators;
|
||||
let action = new TriggerAction("weapon", { range: 50 });
|
||||
|
||||
|
@ -81,7 +81,7 @@ module TK.SpaceTac.UI.Specs {
|
|||
|
||||
test.case("updates graphics from simulation", check => {
|
||||
let targetting = newTargetting();
|
||||
let ship = nn(testgame.view.battle.playing_ship);
|
||||
let ship = testgame.view.battle.fleets[0].ships[0];
|
||||
|
||||
let engine = TestTools.addEngine(ship, 8000);
|
||||
let weapon = TestTools.addWeapon(ship, 30, 5, 100, 50);
|
||||
|
@ -123,40 +123,40 @@ module TK.SpaceTac.UI.Specs {
|
|||
|
||||
test.case("snaps on ships according to targetting mode", check => {
|
||||
let targetting = newTargetting();
|
||||
let playing_ship = nn(testgame.view.battle.playing_ship);
|
||||
let action = TestTools.addWeapon(playing_ship);
|
||||
let ship = testgame.view.battle.fleets[0].ships[0];
|
||||
let action = TestTools.addWeapon(ship);
|
||||
|
||||
let ship1 = testgame.view.battle.play_order[1];
|
||||
let ship2 = testgame.view.battle.play_order[2];
|
||||
let ship1 = testgame.view.battle.fleets[1].ships[0];
|
||||
let ship2 = testgame.view.battle.fleets[1].ships[1];
|
||||
ship1.setArenaPosition(8000, 50);
|
||||
ship2.setArenaPosition(8000, 230);
|
||||
|
||||
targetting.setAction(playing_ship, action, ActionTargettingMode.SPACE);
|
||||
targetting.setAction(ship, action, ActionTargettingMode.SPACE);
|
||||
targetting.setTargetFromLocation({ x: 8000, y: 60 });
|
||||
check.equals(targetting.target, Target.newFromLocation(8000, 60), "space");
|
||||
|
||||
targetting.setAction(playing_ship, action, ActionTargettingMode.SHIP);
|
||||
targetting.setAction(ship, action, ActionTargettingMode.SHIP);
|
||||
targetting.setTargetFromLocation({ x: 8000, y: 60 });
|
||||
check.equals(targetting.target, Target.newFromShip(ship1), "ship 1");
|
||||
targetting.setTargetFromLocation({ x: 8100, y: 200 });
|
||||
check.equals(targetting.target, Target.newFromShip(ship2), "ship 2");
|
||||
|
||||
targetting.setAction(playing_ship, action, ActionTargettingMode.SURROUNDINGS);
|
||||
targetting.setAction(ship, action, ActionTargettingMode.SURROUNDINGS);
|
||||
targetting.setTargetFromLocation({ x: 8000, y: 60 });
|
||||
check.equals(targetting.target, new Target(8000, 60, playing_ship), "surroundings 1");
|
||||
targetting.setTargetFromLocation({ x: playing_ship.arena_x + 10, y: playing_ship.arena_y - 20 });
|
||||
check.equals(targetting.target, Target.newFromShip(playing_ship), "surroundings 2");
|
||||
check.equals(targetting.target, new Target(8000, 60, ship), "surroundings 1");
|
||||
targetting.setTargetFromLocation({ x: ship.arena_x + 10, y: ship.arena_y - 20 });
|
||||
check.equals(targetting.target, Target.newFromShip(ship), "surroundings 2");
|
||||
|
||||
targetting.setAction(playing_ship, action, ActionTargettingMode.SELF);
|
||||
targetting.setAction(ship, action, ActionTargettingMode.SELF);
|
||||
targetting.setTargetFromLocation({ x: 8000, y: 60 });
|
||||
check.equals(targetting.target, Target.newFromShip(playing_ship), "self 1");
|
||||
check.equals(targetting.target, Target.newFromShip(ship), "self 1");
|
||||
targetting.setTargetFromLocation({ x: 0, y: 0 });
|
||||
check.equals(targetting.target, Target.newFromShip(playing_ship), "self 2");
|
||||
check.equals(targetting.target, Target.newFromShip(ship), "self 2");
|
||||
})
|
||||
|
||||
test.case("updates the range hint display", check => {
|
||||
let targetting = newTargetting();
|
||||
let ship = nn(testgame.view.battle.playing_ship);
|
||||
let ship = testgame.view.battle.fleets[0].ships[0];
|
||||
ship.setArenaPosition(0, 0);
|
||||
TestTools.setShipModel(ship, 100, 0, 8);
|
||||
let move = TestTools.addEngine(ship, 100);
|
||||
|
|
|
@ -31,7 +31,7 @@ module TK.SpaceTac.UI.Specs {
|
|||
let battleview = testgame.view;
|
||||
battleview.timer = new Timer();
|
||||
|
||||
let ship = nn(battleview.battle.playing_ship);
|
||||
let ship = battleview.battle.fleets[0].ships[0];
|
||||
let effect = new WeaponEffect(battleview.arena, new Ship(), Target.newFromShip(ship), new TriggerAction("weapon"));
|
||||
effect.bulletsExecutor(1);
|
||||
|
||||
|
@ -44,7 +44,7 @@ module TK.SpaceTac.UI.Specs {
|
|||
let battleview = testgame.view;
|
||||
battleview.timer = new Timer();
|
||||
|
||||
let ship = nn(battleview.battle.playing_ship);
|
||||
let ship = battleview.battle.fleets[0].ships[0];
|
||||
ship.setArenaPosition(50, 30);
|
||||
|
||||
let weapon = new TriggerAction("weapon", { effects: [new DamageEffect(1)], range: 500 });
|
||||
|
|
|
@ -304,7 +304,7 @@ module TK.SpaceTac.UI {
|
|||
if (this.ship) {
|
||||
let ship = this.ship;
|
||||
builder.in(builder.container("items"), builder => {
|
||||
let actions = ship.actions.listAll().filter(action => !(action instanceof EndTurnAction));
|
||||
let actions = ship.actions.listAll();
|
||||
actions.forEach(action => {
|
||||
let button = builder.button(`action-${action.code}`, 24, 0, undefined, filler => ActionTooltip.fill(filler, ship, action));
|
||||
button.setScale(0.375);
|
||||
|
|
Loading…
Reference in New Issue