Forbid move and trigger actions while in vigilance
This commit is contained in:
parent
7bc6378754
commit
c3268ebdea
1
TODO.md
1
TODO.md
|
@ -56,7 +56,6 @@ Battle
|
|||
Ships models and actions
|
||||
------------------------
|
||||
|
||||
* Fix vigilance action triggering when the ship moves with one active (moving should disable vigilance actions)
|
||||
* Fix vigilance action not disabling when reaching the maximum number of triggerings
|
||||
* Highlight the effects area that will contain the new position when move-targetting
|
||||
* Add movement attribute (for main engine action, km/power)
|
||||
|
|
|
@ -295,7 +295,7 @@ module TK.SpaceTac {
|
|||
});
|
||||
|
||||
// Deactivate toggle actions
|
||||
iforeach(this.iToggleActions(true), action => {
|
||||
this.getToggleActions(true).forEach(action => {
|
||||
result = result.concat(action.getSpecificDiffs(this, battle, Target.newFromShip(this)));
|
||||
});
|
||||
|
||||
|
@ -381,17 +381,19 @@ module TK.SpaceTac {
|
|||
/**
|
||||
* Iterator over toggle actions
|
||||
*/
|
||||
iToggleActions(only_active = false): Iterator<ToggleAction> {
|
||||
return <Iterator<ToggleAction>>ifilter(iarray(this.actions.listAll()), action => {
|
||||
return (action instanceof ToggleAction && (!only_active || this.actions.isToggled(action)));
|
||||
});
|
||||
getToggleActions(only_active = false): ToggleAction[] {
|
||||
let result = cfilter(this.actions.listAll(), ToggleAction);
|
||||
if (only_active) {
|
||||
result = result.filter(action => this.actions.isToggled(action));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the effects that this ship has on another ship (which may be herself)
|
||||
*/
|
||||
getAreaEffects(ship: Ship): BaseEffect[] {
|
||||
let toggled = imaterialize(this.iToggleActions(true));
|
||||
let toggled = this.getToggleActions(true);
|
||||
let effects = toggled.map(action => {
|
||||
if (bool(action.filterImpactedShips(this, this.location, Target.newFromShip(ship), [ship]))) {
|
||||
return action.effects;
|
||||
|
|
|
@ -44,22 +44,22 @@ module TK.SpaceTac.Specs {
|
|||
check.patch(action, "getPowerUsage", () => 3);
|
||||
|
||||
let ship = new Ship();
|
||||
check.equals(action.checkCannotBeApplied(ship), "action not available");
|
||||
check.equals(action.checkCannotBeApplied(ship), ActionUnavailability.NO_SUCH_ACTION);
|
||||
|
||||
ship.actions.addCustom(action);
|
||||
check.equals(action.checkCannotBeApplied(ship), "not enough power");
|
||||
check.equals(action.checkCannotBeApplied(ship), ActionUnavailability.POWER);
|
||||
|
||||
ship.setValue("power", 5);
|
||||
check.equals(action.checkCannotBeApplied(ship), null);
|
||||
check.equals(action.checkCannotBeApplied(ship, 4), null);
|
||||
check.equals(action.checkCannotBeApplied(ship, 3), null);
|
||||
check.equals(action.checkCannotBeApplied(ship, 2), "not enough power");
|
||||
check.equals(action.checkCannotBeApplied(ship, 2), ActionUnavailability.POWER);
|
||||
|
||||
ship.setValue("power", 3);
|
||||
check.equals(action.checkCannotBeApplied(ship), null);
|
||||
|
||||
ship.setValue("power", 2);
|
||||
check.equals(action.checkCannotBeApplied(ship), "not enough power");
|
||||
check.equals(action.checkCannotBeApplied(ship), ActionUnavailability.POWER);
|
||||
})
|
||||
|
||||
test.case("checks against overheat", check => {
|
||||
|
@ -80,13 +80,13 @@ module TK.SpaceTac.Specs {
|
|||
check.equals(action.checkCannotBeApplied(ship), null);
|
||||
|
||||
cooldown.use();
|
||||
check.equals(action.checkCannotBeApplied(ship), "overheated");
|
||||
check.equals(action.checkCannotBeApplied(ship), ActionUnavailability.OVERHEATED);
|
||||
|
||||
cooldown.cool();
|
||||
check.equals(action.checkCannotBeApplied(ship), "overheated");
|
||||
check.equals(action.checkCannotBeApplied(ship), ActionUnavailability.OVERHEATED);
|
||||
|
||||
cooldown.cool();
|
||||
check.equals(action.checkCannotBeApplied(ship), "overheated");
|
||||
check.equals(action.checkCannotBeApplied(ship), ActionUnavailability.OVERHEATED);
|
||||
|
||||
cooldown.cool();
|
||||
check.equals(action.checkCannotBeApplied(ship), null);
|
||||
|
|
|
@ -35,6 +35,22 @@ module TK.SpaceTac {
|
|||
ENEMIES
|
||||
}
|
||||
|
||||
/**
|
||||
* Reasons for action unavailibility
|
||||
*/
|
||||
export enum ActionUnavailability {
|
||||
// Ship is not playing
|
||||
NOT_PLAYING = "Not this ship turn",
|
||||
// Action is not available
|
||||
NO_SUCH_ACTION = "Action not available",
|
||||
// Not enough power remaining
|
||||
POWER = "Not enough power",
|
||||
// Action is overheated
|
||||
OVERHEATED = "Overheated",
|
||||
// Vigilance is activated
|
||||
VIGILANCE = "In vigilance"
|
||||
}
|
||||
|
||||
/**
|
||||
* Base class for a battle action.
|
||||
*
|
||||
|
@ -106,17 +122,17 @@ module TK.SpaceTac {
|
|||
*
|
||||
* Method to extend to set conditions
|
||||
*
|
||||
* Returns an informative message indicating why the action cannot be used, null otherwise
|
||||
* Returns an unavalability reason, null otherwise
|
||||
*/
|
||||
checkCannotBeApplied(ship: Ship, remaining_ap: number | null = null): string | null {
|
||||
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 "ship not playing";
|
||||
return ActionUnavailability.NOT_PLAYING;
|
||||
}
|
||||
|
||||
if (!ship.actions.getById(this.id)) {
|
||||
return "action not available";
|
||||
return ActionUnavailability.NO_SUCH_ACTION;
|
||||
}
|
||||
|
||||
// Check AP usage
|
||||
|
@ -125,12 +141,12 @@ module TK.SpaceTac {
|
|||
}
|
||||
var ap_usage = this.getPowerUsage(ship, null);
|
||||
if (remaining_ap < ap_usage) {
|
||||
return "not enough power";
|
||||
return ActionUnavailability.POWER;
|
||||
}
|
||||
|
||||
// Check cooldown
|
||||
if (!ship.actions.isUsable(this)) {
|
||||
return "overheated";
|
||||
return ActionUnavailability.OVERHEATED;
|
||||
}
|
||||
|
||||
return null;
|
||||
|
|
|
@ -8,11 +8,11 @@ module TK.SpaceTac.Specs {
|
|||
battle.setPlayingShip(battle.play_order[0]);
|
||||
|
||||
let action = new EndTurnAction();
|
||||
check.equals(action.checkCannotBeApplied(battle.play_order[0]), "action not available");
|
||||
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]), "ship not playing");
|
||||
check.equals(action.checkCannotBeApplied(battle.play_order[1]), ActionUnavailability.NOT_PLAYING);
|
||||
});
|
||||
|
||||
test.case("changes active ship", check => {
|
||||
|
|
|
@ -23,7 +23,7 @@ module TK.SpaceTac {
|
|||
}
|
||||
|
||||
getPowerUsage(ship: Ship, target: Target | null): number {
|
||||
let toggled_cost = isum(imap(ship.iToggleActions(true), action => action.power));
|
||||
let toggled_cost = sum(ship.getToggleActions(true).map(action => action.power));
|
||||
return ship.getValue("power") + toggled_cost - ship.getAttribute("power_capacity");
|
||||
}
|
||||
|
||||
|
|
|
@ -125,5 +125,16 @@ module TK.SpaceTac.Specs {
|
|||
action = new MoveAction("Engine", { distance_per_power: 58, safety_distance: 12 });
|
||||
check.equals(action.getEffectsDescription(), "Move: 58km per power point (safety: 12km)");
|
||||
});
|
||||
|
||||
test.case("can't be used while in vigilance", check => {
|
||||
let ship = new Ship();
|
||||
TestTools.setShipModel(ship, 10, 10, 10);
|
||||
let vigilance = ship.actions.addCustom(new VigilanceAction("Vigilance"));
|
||||
let action = ship.actions.addCustom(new MoveAction("Engine"));
|
||||
|
||||
check.equals(action.checkCannotBeApplied(ship), null);
|
||||
ship.actions.toggle(vigilance, true);
|
||||
check.equals(action.checkCannotBeApplied(ship), ActionUnavailability.VIGILANCE);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
|
@ -48,7 +48,7 @@ module TK.SpaceTac {
|
|||
return Target.newFromLocation(ship.arena_x + Math.cos(ship.arena_angle) * 100, ship.arena_y + Math.sin(ship.arena_angle) * 100);
|
||||
}
|
||||
|
||||
checkCannotBeApplied(ship: Ship, remaining_ap: number | null = null): string | null {
|
||||
checkCannotBeApplied(ship: Ship, remaining_ap: number | null = null): ActionUnavailability | null {
|
||||
let base = super.checkCannotBeApplied(ship, Infinity);
|
||||
if (base) {
|
||||
return base;
|
||||
|
@ -58,11 +58,16 @@ module TK.SpaceTac {
|
|||
if (remaining_ap === null) {
|
||||
remaining_ap = ship.getValue("power");
|
||||
}
|
||||
if (remaining_ap > 0.0001) {
|
||||
return null;
|
||||
} else {
|
||||
return "not enough power";
|
||||
if (remaining_ap < 0.0001) {
|
||||
return ActionUnavailability.POWER;
|
||||
}
|
||||
|
||||
// Check vigilance actions
|
||||
if (any(ship.getToggleActions(true), action => action instanceof VigilanceAction)) {
|
||||
return ActionUnavailability.VIGILANCE;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
getPowerUsage(ship: Ship, target: Target | null): number {
|
||||
|
|
|
@ -136,5 +136,16 @@ module TK.SpaceTac.Specs {
|
|||
action.configureTrigger({ effects: effects, power: 2, range: 120, blast: 100, angle: 80 });
|
||||
check.equals(action.getEffectsDescription(), "Fire (power 2, range 120km):\n• evasion +20% in 100km radius");
|
||||
})
|
||||
|
||||
test.case("can't be used while in vigilance", check => {
|
||||
let ship = new Ship();
|
||||
TestTools.setShipModel(ship, 10, 10, 10);
|
||||
let vigilance = ship.actions.addCustom(new VigilanceAction("Vigilance"));
|
||||
let action = ship.actions.addCustom(new TriggerAction("Weapon"));
|
||||
|
||||
check.equals(action.checkCannotBeApplied(ship), null);
|
||||
ship.actions.toggle(vigilance, true);
|
||||
check.equals(action.checkCannotBeApplied(ship), ActionUnavailability.VIGILANCE);
|
||||
})
|
||||
});
|
||||
}
|
||||
|
|
|
@ -90,6 +90,21 @@ module TK.SpaceTac {
|
|||
return this.range;
|
||||
}
|
||||
|
||||
checkCannotBeApplied(ship: Ship, remaining_ap: number | null = null): ActionUnavailability | null {
|
||||
let base = super.checkCannotBeApplied(ship, remaining_ap);
|
||||
if (base) {
|
||||
return base;
|
||||
}
|
||||
|
||||
// Check vigilance actions
|
||||
if (any(ship.getToggleActions(true), action => action instanceof VigilanceAction)) {
|
||||
// TODO Could allow trigger actions that does not involve a move effect
|
||||
return ActionUnavailability.VIGILANCE;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
filterImpactedShips(ship: Ship, source: ArenaLocation, target: Target, ships: Ship[]): Ship[] {
|
||||
if (this.blast) {
|
||||
return ships.filter(ship => arenaDistance(ship.location, target) <= this.blast);
|
||||
|
|
|
@ -9,9 +9,9 @@ module TK.SpaceTac.UI.Specs {
|
|||
let ship = new Ship();
|
||||
TestTools.setShipModel(ship, 100, 0, 10);
|
||||
|
||||
let action1 = new MoveAction("Thruster");
|
||||
let action2 = new TriggerAction("Superweapon", { effects: [new DamageEffect(12)], power: 2, range: 50 });
|
||||
let action3 = new EndTurnAction();
|
||||
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, (<any>tooltip).container.content.children[1], "Use Thruster");
|
||||
|
|
|
@ -14,34 +14,25 @@ module TK.SpaceTac.UI {
|
|||
|
||||
builder.text(action.getTitle(ship), 150, 0, { size: 24 });
|
||||
|
||||
let cost = "";
|
||||
if (action instanceof MoveAction) {
|
||||
if (ship.getValue("power") == 0) {
|
||||
cost = "Not enough power";
|
||||
} else {
|
||||
cost = `Cost: 1 power per ${action.distance_per_power}km`;
|
||||
}
|
||||
let unavailable = action.checkCannotBeApplied(ship);
|
||||
if (unavailable != null) {
|
||||
builder.text(unavailable, 150, 40, { color: "#e54d2b" });
|
||||
} else if (action instanceof MoveAction) {
|
||||
let cost = `Cost: 1 power per ${action.distance_per_power}km`;
|
||||
builder.text(cost, 150, 40, { color: "#ffdd4b" });
|
||||
} else {
|
||||
let power_usage = action.getPowerUsage(ship, null);
|
||||
if (power_usage) {
|
||||
if (ship.getValue("power") < power_usage) {
|
||||
cost = "Not enough power";
|
||||
} else if (power_usage > 0) {
|
||||
cost = `Cost: ${power_usage} power`;
|
||||
} else {
|
||||
cost = `Recover: ${-power_usage} power`;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (cost) {
|
||||
let cost = (power_usage > 0) ? `Cost: ${power_usage} power` : `Recover: ${-power_usage} power`;
|
||||
builder.text(cost, 150, 40, { color: "#ffdd4b" });
|
||||
}
|
||||
}
|
||||
|
||||
let cooldown = ship.actions.getCooldown(action);
|
||||
if (cooldown.overheat) {
|
||||
if (cooldown.heat > 0) {
|
||||
builder.text("Cooling down ...", 150, 80, { color: "#d8894d" });
|
||||
} else if (cooldown.willOverheat() && cost != "Not enough power") {
|
||||
} else if (!unavailable && cooldown.willOverheat()) {
|
||||
if (cooldown.cooling > 1) {
|
||||
let turns = cooldown.cooling - 1;
|
||||
builder.text(`Unavailable for ${turns} turn${turns > 1 ? "s" : ""} if used`, 150, 80, { color: "#d8894d" });
|
||||
|
|
Loading…
Reference in a new issue