155 lines
6.1 KiB
TypeScript
155 lines
6.1 KiB
TypeScript
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);
|
|
const final_location = (move && move.distance) ? TurnPlanning.getTargetForAction(ship, move) : ship.location;
|
|
const active = first(plan.actions, action => action.category === ActionCategory.ACTIVE);
|
|
|
|
this.updateMoveAction(ship, move, active, parent);
|
|
this.updateActiveAction(ship, final_location, active, parent);
|
|
} else {
|
|
console.error("Ship not found to update actions", plan);
|
|
}
|
|
}
|
|
|
|
private updateMoveAction(ship: Ship, plan: ActionPlan | null, active: ActionPlan | null, parent: UIContainer) {
|
|
let builder = parent.getBuilder();
|
|
let child = parent.getByName("moveline");
|
|
const graphics = child ? as(UIGraphics, child) : builder.graphics("moveline");
|
|
const move_location = plan ? TurnPlanning.getTargetForAction(ship, plan) : undefined;
|
|
graphics.clear();
|
|
if (move_location) {
|
|
graphics.addLine({
|
|
start: ship.location,
|
|
end: move_location,
|
|
width: 5,
|
|
color: PLAN_COLOR
|
|
});
|
|
}
|
|
|
|
child = parent.getByName("moveghost");
|
|
const ghost = child ? as(UIImage, child) : builder.image(`ship-${ship.model.code}-sprite`, 0, 0, true);
|
|
ghost.setName("moveghost");
|
|
if (move_location) {
|
|
ghost.setVisible(true);
|
|
ghost.setPosition(move_location.x, move_location.y);
|
|
if (builder.view.isTintSupported()) {
|
|
ghost.setTintFill(PLAN_COLOR);
|
|
} else {
|
|
ghost.setAlpha(0.6);
|
|
}
|
|
ghost.setRotation((active && active.angle) ? active.angle : arenaAngle(ship.location, move_location));
|
|
} 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.angle || 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 = TurnPlanning.getTargetForAction(ship, plan);
|
|
if (arenaDistance(from, center) > 0.0) {
|
|
graphics.addLine({
|
|
start: from,
|
|
end: center,
|
|
width: 6,
|
|
alpha: 0.2,
|
|
color: PLAN_COLOR_HL
|
|
});
|
|
}
|
|
graphics.addCircle({
|
|
center,
|
|
radius,
|
|
fill: { color: PLAN_COLOR, alpha: 0.2 },
|
|
border: { color: PLAN_COLOR_HL, alpha: 0.2, width: 4 },
|
|
});
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|