1
0
Fork 0
spacetac/src/ui/battle/LogProcessor.ts

243 lines
8.2 KiB
TypeScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

module TS.SpaceTac.UI {
// Processor of battle log events
// This will process incoming battle events, and update the battleview accordingly
export class LogProcessor {
// Link to the battle view
private view: BattleView;
// Link to the battle
private battle: Battle;
// Link to the battle log
private log: BattleLog;
// Subscription identifier
private subscription: any = null;
// Delay before processing next events
private delayed = false;
// Processing queue, when delay is active
private queue: BaseLogEvent[] = [];
// Forward events to other subscribers
private forwarding: LogSubscriber[] = [];
constructor(view: BattleView) {
this.view = view;
this.battle = view.battle;
this.log = view.battle.log;
}
/**
* Start log processing
*/
start() {
this.subscription = this.log.subscribe(event => this.processBattleEvent(event));
this.battle.injectInitialEvents();
}
/**
* Register a sub-subscriber.
*
* The difference with registering directly to the BattleLog is that events may be delayed
* for animations.
*/
register(callback: LogSubscriber) {
this.forwarding.push(callback);
}
/**
* Introduce a delay in event processing
*/
delayNextEvents(duration: number) {
if (duration > 0 && !this.view.gameui.headless) {
this.delayed = true;
this.view.timer.schedule(duration, () => this.processQueued());
}
}
/**
* Process the events queued due to a delay
*/
processQueued() {
let events = acopy(this.queue);
this.queue = [];
this.delayed = false;
events.forEach(event => this.processBattleEvent(event));
}
/**
* Process a single event
*/
processBattleEvent(event: BaseLogEvent) {
if (this.delayed) {
this.queue.push(event);
return;
}
console.log("Battle event", event);
this.forwarding.forEach(subscriber => subscriber(event));
if (event instanceof ShipChangeEvent) {
this.processShipChangeEvent(event);
} else if (event instanceof MoveEvent) {
this.processMoveEvent(event);
} else if (event instanceof ValueChangeEvent) {
this.processValueChangedEvent(event);
} else if (event instanceof DeathEvent) {
this.processDeathEvent(event);
} else if (event instanceof FireEvent) {
this.processFireEvent(event);
} else if (event instanceof DamageEvent) {
this.processDamageEvent(event);
} else if (event instanceof EndBattleEvent) {
this.processEndBattleEvent(event);
} else if (event instanceof DroneDeployedEvent) {
this.processDroneDeployedEvent(event);
} else if (event instanceof DroneDestroyedEvent) {
this.processDroneDestroyedEvent(event);
} else if (event instanceof DroneAppliedEvent) {
this.processDroneAppliedEvent(event);
} else if (event instanceof EffectAddedEvent || event instanceof EffectRemovedEvent ||  event instanceof EffectDurationChangedEvent) {
this.processEffectEvent(event);
}
}
// Destroy the log processor
destroy() {
if (this.subscription) {
this.log.unsubscribe(this.subscription);
this.subscription = null;
}
}
// Playing ship changed
private processShipChangeEvent(event: ShipChangeEvent): void {
if (event.target && event.target.ship) {
this.view.arena.setShipPlaying(event.target.ship);
this.view.ship_list.setPlaying(event.target.ship);
} else {
this.view.arena.setShipPlaying(null);
this.view.ship_list.setPlaying(null);
}
if (this.battle.canPlay(this.view.player)) {
// Player turn
this.view.setInteractionEnabled(true);
} else {
this.view.setInteractionEnabled(false);
if (event.ship.isAbleToPlay()) {
// AI turn
this.battle.playAI();
} else {
// Ship unable to play, skip turn
this.view.timer.schedule(2000, () => {
this.battle.advanceToNextShip();
});
}
}
}
// Damage to ship
private processDamageEvent(event: DamageEvent): void {
var item = this.view.ship_list.findItem(event.ship);
if (item) {
item.setDamageHit();
}
}
// Ship moved
private processMoveEvent(event: MoveEvent): void {
var sprite = this.view.arena.findShipSprite(event.ship);
if (sprite) {
let duration = sprite.moveTo(event.target.x, event.target.y, event.facing_angle, !event.initial);
this.delayNextEvents(duration);
}
}
// Ship value changed
private processValueChangedEvent(event: ValueChangeEvent): void {
var sprite = this.view.arena.findShipSprite(event.ship);
if (sprite) {
sprite.displayValueChanged(event);
}
var item = this.view.ship_list.findItem(event.ship);
if (item) {
item.updateAttributes();
}
// TODO Update tooltip
}
// A ship died
private processDeathEvent(event: DeathEvent): void {
if (this.view.ship_hovered === event.ship) {
this.view.setShipHovered(null);
}
this.view.arena.markAsDead(event.ship);
this.view.ship_list.markAsDead(event.ship);
if (!event.initial) {
this.delayNextEvents(1000);
}
}
// Weapon used
private processFireEvent(event: FireEvent): void {
var source = Target.newFromShip(event.ship);
var destination = event.target;
var effect = new WeaponEffect(this.view.arena, source, destination, event.weapon);
let duration = effect.start();
this.delayNextEvents(duration);
}
// Battle ended (victory or defeat)
private processEndBattleEvent(event: EndBattleEvent): void {
this.view.setInteractionEnabled(false);
if (event.outcome.winner && event.outcome.winner.player === this.view.player) {
// Victory !
// TODO Loot screen
this.view.player.exitBattle();
this.view.game.state.start("router");
} else {
// TODO Game over ?
}
}
// Sticky effect on ship added, changed or removed
private processEffectEvent(event: EffectAddedEvent | EffectRemovedEvent | EffectDurationChangedEvent): void {
var item = this.view.ship_list.findItem(event.ship);
if (item) {
item.updateEffects();
}
}
// New drone deployed
private processDroneDeployedEvent(event: DroneDeployedEvent): void {
let duration = this.view.arena.addDrone(event.drone, !event.initial);
this.delayNextEvents(duration);
}
// Drone destroyed
private processDroneDestroyedEvent(event: DroneDestroyedEvent): void {
this.view.arena.removeDrone(event.drone);
}
// Drone applied
private processDroneAppliedEvent(event: DroneAppliedEvent): void {
let drone = this.view.arena.findDrone(event.drone);
if (drone) {
let duration = drone.setApplied();
this.delayNextEvents(duration);
}
}
}
}