module TK.SpaceTac.UI { const PLAN_COLOR = 0xa5b7da const PLAN_COLOR_HL = 0xdde6f9 /** * Displays and maintain a turn plan */ export class TurnPlanDisplay { readonly container: UIContainer private battle?: Battle constructor(builder: UIBuilder) { this.container = builder.container("battleplan"); } update(plan: TurnPlan, battle?: Battle): void { this.battle = battle; this.updateBattle(plan, this.container); } private updateBattle(plan: TurnPlan, parent: UIContainer) { const builder = parent.getBuilder(); if (parent.list.length > plan.fleets.length) { builder.clear(); } while (parent.list.length < plan.fleets.length) { builder.container("fleetplan"); } iforeach(izip(plan.fleets, ifilterclass(parent.list, UIContainer)), ([fleetplan, child]) => { this.updateFleet(fleetplan, child); }); } private updateFleet(plan: FleetPlan, parent: UIContainer) { const builder = parent.getBuilder(); if (parent.list.length > plan.ships.length) { builder.clear(); } while (parent.list.length < plan.ships.length) { builder.container("shipplan"); } iforeach(izip(plan.ships, ifilterclass(parent.list, UIContainer)), ([shipplan, child]) => { this.updateShip(shipplan, child); }); } private updateShip(plan: ShipPlan, parent: UIContainer) { const ship = this.battle ? this.battle.getShip(plan.ship) : null; if (ship) { const move = first(plan.actions, action => action.category === ActionCategory.MOVE); this.updateMoveAction(ship, move, parent); const final_location = (move && move.target) ? move.target : ship.location; const active = first(plan.actions, action => action.category === ActionCategory.ACTIVE); this.updateActiveAction(ship, final_location, active, parent); } else { console.error("Ship not found to update actions", plan); } } private updateMoveAction(ship: Ship, plan: ActionPlan | null, parent: UIContainer) { let child = parent.getByName("moveline"); const graphics = child ? as(UIGraphics, child) : parent.getBuilder().graphics("moveline"); graphics.clear(); if (plan && plan.target) { graphics.addLine({ start: ship.location, end: plan.target, width: 5, color: PLAN_COLOR }); } child = parent.getByName("moveghost"); const ghost = child ? as(UIImage, child) : parent.getBuilder().image(`ship-${ship.model.code}-sprite`, 0, 0, true); ghost.setName("moveghost"); if (plan && plan.target) { ghost.setVisible(true); ghost.setPosition(plan.target.x, plan.target.y); ghost.setTint(PLAN_COLOR); } else { ghost.setVisible(false); } } private updateActiveAction(ship: Ship, from: IArenaLocation, plan: ActionPlan | null, parent: UIContainer) { let child = parent.getByName("activearea"); const graphics = child ? as(UIGraphics, child) : parent.getBuilder().graphics("activearea"); graphics.clear(); const action = plan ? ship.actions.getById(plan.action) : null; if (action && plan) { let radius = 0; let angle = 0; if (action instanceof TriggerAction) { if (action.angle) { angle = (action.angle * 0.5) * Math.PI / 180; radius = action.range; } else { radius = action.blast; } } else if (action instanceof DeployDroneAction) { radius = action.drone_radius; } else if (action instanceof ToggleAction) { radius = action.radius; } if (radius) { if (angle) { const base_angle = plan.target ? Math.atan2(plan.target.y - from.y, plan.target.x - from.x) : 0; graphics.addCircleArc({ center: from, radius, angle: { start: base_angle - angle, span: angle * 2 }, fill: { color: PLAN_COLOR, alpha: 0.2 }, border: { color: PLAN_COLOR_HL, alpha: 0.2, width: 4 }, }); } else { const center = plan ? plan.target : from; graphics.addCircle({ center, radius, fill: { color: PLAN_COLOR, alpha: 0.2 }, border: { color: PLAN_COLOR_HL, alpha: 0.2, width: 4 }, }); } } } } } }