Refactored battle log processing
This commit is contained in:
parent
8c0aa73ab7
commit
efcb00e955
|
@ -36,6 +36,9 @@ module TS.SpaceTac {
|
|||
// Timer to use for scheduled things
|
||||
timer = Timer.global
|
||||
|
||||
// Indicator that an AI is playing
|
||||
ai_playing = false
|
||||
|
||||
// Create a battle between two fleets
|
||||
constructor(fleet1 = new Fleet(), fleet2 = new Fleet(), width = 1808, height = 948) {
|
||||
this.fleets = [fleet1, fleet2];
|
||||
|
@ -243,6 +246,8 @@ module TS.SpaceTac {
|
|||
this.playing_ship.startTurn();
|
||||
}
|
||||
|
||||
this.ai_playing = false;
|
||||
|
||||
if (log && previous_ship && this.playing_ship) {
|
||||
this.log.add(new ShipChangeEvent(previous_ship, this.playing_ship));
|
||||
}
|
||||
|
@ -251,13 +256,17 @@ module TS.SpaceTac {
|
|||
/**
|
||||
* Make an AI play the current ship
|
||||
*/
|
||||
playAI(ai: AbstractAI | null = null) {
|
||||
if (this.playing_ship) {
|
||||
playAI(ai: AbstractAI | null = null): boolean {
|
||||
if (this.playing_ship && !this.ai_playing) {
|
||||
this.ai_playing = true;
|
||||
if (!ai) {
|
||||
// TODO Use an AI adapted to the fleet
|
||||
ai = new TacticalAI(this.playing_ship, this.timer);
|
||||
}
|
||||
ai.play();
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -25,15 +25,28 @@ module TS.SpaceTac {
|
|||
|
||||
/**
|
||||
* Apply the event on a battle state
|
||||
*
|
||||
* By default it does nothing
|
||||
*/
|
||||
apply(battle: Battle) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the reverse event
|
||||
*
|
||||
* By default it returns a stub event that does nothing
|
||||
*/
|
||||
getReverse(): BaseBattleEvent {
|
||||
throw new Error("No reverse implemented");
|
||||
return new StubBattleEvent();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Battle event that does nothing
|
||||
*/
|
||||
export class StubBattleEvent extends BaseBattleEvent {
|
||||
constructor() {
|
||||
super("stub");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -11,5 +11,9 @@ module TS.SpaceTac {
|
|||
|
||||
this.drone = drone;
|
||||
}
|
||||
|
||||
getReverse(): BaseBattleEvent {
|
||||
return new DroneDestroyedEvent(this.drone);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,5 +11,9 @@ module TS.SpaceTac {
|
|||
|
||||
this.drone = drone;
|
||||
}
|
||||
|
||||
getReverse(): BaseBattleEvent {
|
||||
return new DroneDeployedEvent(this.drone);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
10
src/core/events/ShipChangeEvent.spec.ts
Normal file
10
src/core/events/ShipChangeEvent.spec.ts
Normal file
|
@ -0,0 +1,10 @@
|
|||
module TS.SpaceTac.Specs {
|
||||
describe("ShipChangeEvent", function () {
|
||||
it("get reverse event", function () {
|
||||
let ship1 = new Ship();
|
||||
let ship2 = new Ship();
|
||||
let event = new ShipChangeEvent(ship1, ship2);
|
||||
expect(event.getReverse()).toEqual(new ShipChangeEvent(ship2, ship1));
|
||||
});
|
||||
});
|
||||
}
|
|
@ -1,7 +1,9 @@
|
|||
/// <reference path="BaseBattleEvent.ts"/>
|
||||
|
||||
module TS.SpaceTac {
|
||||
// Battle event, when a ship turn ended, and advanced to a new one
|
||||
/**
|
||||
* Event that changes the current playing ship
|
||||
*/
|
||||
export class ShipChangeEvent extends BaseLogShipEvent {
|
||||
// Ship that starts playing
|
||||
new_ship: Ship;
|
||||
|
@ -11,5 +13,9 @@ module TS.SpaceTac {
|
|||
|
||||
this.new_ship = new_ship;
|
||||
}
|
||||
|
||||
getReverse(): BaseBattleEvent {
|
||||
return new ShipChangeEvent(this.new_ship, this.ship);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
9
src/core/events/ValueChangeEvent.spec.ts
Normal file
9
src/core/events/ValueChangeEvent.spec.ts
Normal file
|
@ -0,0 +1,9 @@
|
|||
module TS.SpaceTac.Specs {
|
||||
describe("ValueChangeEvent", function () {
|
||||
it("get reverse event", function () {
|
||||
let ship = new Ship();
|
||||
let event = new ValueChangeEvent(ship, new ShipValue("hull", 15, 22), 10);
|
||||
expect(event.getReverse()).toEqual(new ValueChangeEvent(ship, new ShipValue("hull", 5, 22), -10));
|
||||
});
|
||||
});
|
||||
}
|
|
@ -1,7 +1,9 @@
|
|||
/// <reference path="BaseBattleEvent.ts"/>
|
||||
|
||||
module TS.SpaceTac {
|
||||
// Event logged when a ship value or attribute changed
|
||||
/**
|
||||
* Event logged when a ship value or attribute changed
|
||||
*/
|
||||
export class ValueChangeEvent extends BaseLogShipEvent {
|
||||
// Saved version of the current value
|
||||
value: ShipValue;
|
||||
|
@ -15,5 +17,11 @@ module TS.SpaceTac {
|
|||
this.value = copy(value);
|
||||
this.diff = diff;
|
||||
}
|
||||
|
||||
getReverse(): BaseBattleEvent {
|
||||
let value = copy(this.value);
|
||||
value.set(value.get() - this.diff);
|
||||
return new ValueChangeEvent(this.ship, value, -this.diff);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -128,18 +128,26 @@ module TS.SpaceTac.UI {
|
|||
});
|
||||
this.battle.endBattle(first(this.battle.fleets, fleet => fleet.player != this.player));
|
||||
});
|
||||
this.inputs.bindCheat("a", "Use AI to play", () => {
|
||||
if (this.interacting && this.battle.playing_ship) {
|
||||
this.setInteractionEnabled(false);
|
||||
this.action_bar.setShip(new Ship());
|
||||
this.battle.playAI(new TacticalAI(this.battle.playing_ship));
|
||||
}
|
||||
});
|
||||
this.inputs.bindCheat("a", "Use AI to play", () => this.playAI());
|
||||
|
||||
// Start processing the log
|
||||
this.log_processor.start();
|
||||
}
|
||||
|
||||
/**
|
||||
* Make the AI play current ship
|
||||
*
|
||||
* If the AI is already playing, do nothing
|
||||
*/
|
||||
playAI(): void {
|
||||
if (this.battle.playAI()) {
|
||||
if (this.interacting) {
|
||||
this.action_bar.setShip(new Ship());
|
||||
}
|
||||
this.setInteractionEnabled(false);
|
||||
}
|
||||
}
|
||||
|
||||
// Leaving the view, we unbind the battle
|
||||
shutdown() {
|
||||
this.exitTargettingMode();
|
||||
|
|
|
@ -32,27 +32,43 @@ module TS.SpaceTac.UI.Specs {
|
|||
return 0;
|
||||
});
|
||||
expect(battle.turn).toBe(1);
|
||||
expect(processor.atStart()).toBe(true);
|
||||
expect(processor.atEnd()).toBe(true);
|
||||
|
||||
processor.stepForward();
|
||||
expect(battle.turn).toBe(1);
|
||||
expect(processor.atStart()).toBe(true);
|
||||
expect(processor.atEnd()).toBe(true);
|
||||
|
||||
battle.log.add(new FakeEvent());
|
||||
expect(battle.turn).toBe(1);
|
||||
expect(processor.atStart()).toBe(true);
|
||||
expect(processor.atEnd()).toBe(false);
|
||||
|
||||
processor.stepForward();
|
||||
expect(battle.turn).toBe(2);
|
||||
expect(processor.atStart()).toBe(false);
|
||||
expect(processor.atEnd()).toBe(true);
|
||||
|
||||
processor.stepForward();
|
||||
expect(battle.turn).toBe(2);
|
||||
expect(processor.atStart()).toBe(false);
|
||||
expect(processor.atEnd()).toBe(true);
|
||||
|
||||
processor.stepBackward();
|
||||
expect(battle.turn).toBe(1);
|
||||
expect(processor.atStart()).toBe(true);
|
||||
expect(processor.atEnd()).toBe(false);
|
||||
|
||||
processor.stepBackward();
|
||||
expect(battle.turn).toBe(1);
|
||||
expect(processor.atStart()).toBe(true);
|
||||
expect(processor.atEnd()).toBe(false);
|
||||
|
||||
processor.stepForward();
|
||||
expect(battle.turn).toBe(2);
|
||||
expect(processor.atStart()).toBe(false);
|
||||
expect(processor.atEnd()).toBe(true);
|
||||
})
|
||||
})
|
||||
}
|
|
@ -56,6 +56,7 @@ module TS.SpaceTac.UI {
|
|||
*/
|
||||
start() {
|
||||
this.subscription = this.log.subscribe(event => this.processBattleEvent(event));
|
||||
this.cursor = this.log.events.length - 1;
|
||||
this.battle.getBootstrapEvents().forEach(event => this.processBattleEvent(event));
|
||||
}
|
||||
|
||||
|
@ -63,9 +64,9 @@ module TS.SpaceTac.UI {
|
|||
* Make a step backward in time
|
||||
*/
|
||||
stepBackward() {
|
||||
if (this.cursor >= 0) {
|
||||
this.processBattleEvent(this.log.events[this.cursor].getReverse());
|
||||
if (!this.atStart()) {
|
||||
this.cursor -= 1;
|
||||
this.processBattleEvent(this.log.events[this.cursor + 1].getReverse());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -73,7 +74,7 @@ module TS.SpaceTac.UI {
|
|||
* Make a step forward in time
|
||||
*/
|
||||
stepForward() {
|
||||
if (this.cursor < this.log.events.length - 1) {
|
||||
if (!this.atEnd()) {
|
||||
this.cursor += 1;
|
||||
this.processBattleEvent(this.log.events[this.cursor]);
|
||||
}
|
||||
|
@ -85,6 +86,9 @@ module TS.SpaceTac.UI {
|
|||
* This will rewind all applied event
|
||||
*/
|
||||
jumpToStart() {
|
||||
while (!this.atStart()) {
|
||||
this.stepBackward();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -93,6 +97,34 @@ module TS.SpaceTac.UI {
|
|||
* This will apply all remaining event
|
||||
*/
|
||||
jumpToEnd() {
|
||||
while (!this.atEnd()) {
|
||||
this.stepForward();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if we are currently at the start of the log
|
||||
*/
|
||||
atStart(): boolean {
|
||||
return this.cursor < 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if we are currently at the end of the log
|
||||
*/
|
||||
atEnd(): boolean {
|
||||
return this.cursor >= this.log.events.length - 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if we need a player or AI to interact at this point
|
||||
*/
|
||||
getPlayerNeeded(): Player | null {
|
||||
if (this.atEnd()) {
|
||||
return this.battle.playing_ship ? this.battle.playing_ship.getPlayer() : null;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -176,6 +208,28 @@ module TS.SpaceTac.UI {
|
|||
} else if (event instanceof DroneAppliedEvent) {
|
||||
this.processDroneAppliedEvent(event);
|
||||
}
|
||||
|
||||
// FIXME temporary fix for cursor not being forwarded
|
||||
let cursor = this.log.events.indexOf(event);
|
||||
if (cursor >= 0) {
|
||||
this.cursor = cursor;
|
||||
}
|
||||
|
||||
// Transfer control to the needed player
|
||||
let player = this.getPlayerNeeded();
|
||||
if (player) {
|
||||
if (this.battle.playing_ship && !this.battle.playing_ship.alive) {
|
||||
this.view.setInteractionEnabled(false);
|
||||
this.battle.advanceToNextShip();
|
||||
this.delayNextEvents(200);
|
||||
} else if (player === this.view.player) {
|
||||
this.view.setInteractionEnabled(true);
|
||||
} else {
|
||||
this.view.playAI();
|
||||
}
|
||||
} else {
|
||||
this.view.setInteractionEnabled(false);
|
||||
}
|
||||
}
|
||||
|
||||
// Destroy the log processor
|
||||
|
@ -191,24 +245,7 @@ module TS.SpaceTac.UI {
|
|||
private processShipChangeEvent(event: ShipChangeEvent): void {
|
||||
this.view.arena.setShipPlaying(event.new_ship);
|
||||
this.view.ship_list.setPlaying(event.new_ship);
|
||||
|
||||
if (this.battle.canPlay(this.view.player)) {
|
||||
// Player turn
|
||||
this.view.gameui.audio.playOnce("battle-ship-change");
|
||||
this.view.setInteractionEnabled(true);
|
||||
} else {
|
||||
this.view.setInteractionEnabled(false);
|
||||
if (event.new_ship.isAbleToPlay()) {
|
||||
// AI turn
|
||||
this.view.gameui.audio.playOnce("battle-ship-change");
|
||||
this.battle.playAI();
|
||||
} else {
|
||||
// Ship unable to play, skip turn
|
||||
this.view.timer.schedule(event.new_ship.alive ? 2000 : 200, () => {
|
||||
this.battle.advanceToNextShip();
|
||||
});
|
||||
}
|
||||
}
|
||||
this.view.gameui.audio.playOnce("battle-ship-change");
|
||||
}
|
||||
|
||||
// Damage to ship
|
||||
|
|
Loading…
Reference in a new issue