Added log when an action cannot be applied
This commit is contained in:
parent
cd7334babf
commit
144eb56537
2
TODO
2
TODO
|
@ -1,3 +1,4 @@
|
|||
* Enable strict null checking in typescript
|
||||
* Ensure that tweens and particle emitters get destroyed once animation is done (or view changes)
|
||||
* Highlight ships that will be included as target of current action
|
||||
* Controls: Do not focus on ship while targetting for area effects (dissociate hover and target)
|
||||
|
@ -27,7 +28,6 @@
|
|||
* TacticalAI: allow to play several moves in the same turn
|
||||
* TacticalAI: add pauses to not play too quickly
|
||||
* TacticalAI: replace BullyAI
|
||||
* AIDuel: fix first AI always winning when two identical AIs are selected
|
||||
* Add a defeat screen (game over for now)
|
||||
* Add a victory screen, with loot display
|
||||
* Add retreat from battle
|
||||
|
|
|
@ -89,5 +89,14 @@ module TS.SpaceTac.Specs {
|
|||
{ action: jasmine.objectContaining({ code: "fire-null" }), target: new Target(ship.arena_x + 18, ship.arena_y, null), ap: 2 }
|
||||
]);
|
||||
});
|
||||
|
||||
it("does nothing if trying to move in the same spot", function () {
|
||||
let [ship, simulator, action] = simpleWeaponCase();
|
||||
let result = simulator.simulateAction(ship.listEquipment(SlotType.Engine)[0].action, new Target(ship.arena_x, ship.arena_y, null));
|
||||
expect(result.success).toBe(true);
|
||||
expect(result.need_move).toBe(false);
|
||||
expect(result.need_fire).toBe(false);
|
||||
expect(result.parts).toEqual([]);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
|
@ -59,27 +59,32 @@ module TS.SpaceTac {
|
|||
* Simulate a given action on a given valid target.
|
||||
*/
|
||||
simulateAction(action: BaseAction, target: Target): MoveFireResult {
|
||||
let result = new MoveFireResult();
|
||||
|
||||
let dx = target.x - this.ship.arena_x;
|
||||
let dy = target.y - this.ship.arena_y;
|
||||
let distance = Math.sqrt(dx * dx + dy * dy);
|
||||
let result = new MoveFireResult();
|
||||
|
||||
let ap = this.ship.values.power.get();
|
||||
let action_radius = action.getRangeRadius(this.ship);
|
||||
|
||||
if (action instanceof MoveAction || distance > action_radius) {
|
||||
result.need_move = true;
|
||||
let move_distance = action instanceof MoveAction ? distance : distance - action_radius;
|
||||
let move_target = new Target(this.ship.arena_x + dx * move_distance / distance, this.ship.arena_y + dy * move_distance / distance, null);
|
||||
let engine = this.findBestEngine();
|
||||
if (engine) {
|
||||
result.total_move_ap = engine.action.getActionPointsUsage(this.ship.getBattle(), this.ship, move_target);
|
||||
result.can_move = ap > 0;
|
||||
result.can_end_move = result.total_move_ap <= ap;
|
||||
result.move_location = move_target;
|
||||
result.parts.push({ action: engine.action, target: move_target, ap: result.total_move_ap });
|
||||
if (move_distance > 0.000001) {
|
||||
result.need_move = true;
|
||||
|
||||
ap -= result.total_move_ap;
|
||||
distance -= move_distance;
|
||||
let move_target = new Target(this.ship.arena_x + dx * move_distance / distance, this.ship.arena_y + dy * move_distance / distance, null);
|
||||
let engine = this.findBestEngine();
|
||||
if (engine) {
|
||||
result.total_move_ap = engine.action.getActionPointsUsage(this.ship, move_target);
|
||||
result.can_move = ap > 0;
|
||||
result.can_end_move = result.total_move_ap <= ap;
|
||||
result.move_location = move_target;
|
||||
result.parts.push({ action: engine.action, target: move_target, ap: result.total_move_ap });
|
||||
|
||||
ap -= result.total_move_ap;
|
||||
distance -= move_distance;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -87,7 +92,7 @@ module TS.SpaceTac {
|
|||
result.success = true;
|
||||
if (!(action instanceof MoveAction)) {
|
||||
result.need_fire = true;
|
||||
result.total_fire_ap = action.getActionPointsUsage(this.ship.getBattle(), this.ship, target);
|
||||
result.total_fire_ap = action.getActionPointsUsage(this.ship, target);
|
||||
result.can_fire = result.total_fire_ap <= ap;
|
||||
result.fire_location = target;
|
||||
result.parts.push({ action: action, target: target, ap: result.total_fire_ap });
|
||||
|
|
|
@ -8,22 +8,22 @@ module TS.SpaceTac {
|
|||
ship.addSlot(SlotType.Hull).attach(equipment);
|
||||
ship.values.power.setMaximal(10);
|
||||
|
||||
expect(action.canBeUsed(null, ship)).toBe(false);
|
||||
expect(action.checkCannotBeApplied(ship)).toBe("not enough power");
|
||||
|
||||
ship.values.power.set(5);
|
||||
|
||||
expect(action.canBeUsed(null, ship)).toBe(true);
|
||||
expect(action.canBeUsed(null, ship, 4)).toBe(true);
|
||||
expect(action.canBeUsed(null, ship, 3)).toBe(true);
|
||||
expect(action.canBeUsed(null, ship, 2)).toBe(false);
|
||||
expect(action.checkCannotBeApplied(ship)).toBe(null);
|
||||
expect(action.checkCannotBeApplied(ship, 4)).toBe(null);
|
||||
expect(action.checkCannotBeApplied(ship, 3)).toBe(null);
|
||||
expect(action.checkCannotBeApplied(ship, 2)).toBe("not enough power");
|
||||
|
||||
ship.values.power.set(3);
|
||||
|
||||
expect(action.canBeUsed(null, ship)).toBe(true);
|
||||
expect(action.checkCannotBeApplied(ship)).toBe(null);
|
||||
|
||||
ship.values.power.set(2);
|
||||
|
||||
expect(action.canBeUsed(null, ship)).toBe(false);
|
||||
expect(action.checkCannotBeApplied(ship)).toBe("not enough power");
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
|
@ -21,12 +21,18 @@ module TS.SpaceTac {
|
|||
this.equipment = equipment;
|
||||
}
|
||||
|
||||
// Check basic conditions to know if the ship can use this action at all
|
||||
// Method to reimplement to set conditions
|
||||
canBeUsed(battle: Battle, ship: Ship, remaining_ap: number = null): boolean {
|
||||
/**
|
||||
* Check basic conditions to know if the ship can use this action at all
|
||||
*
|
||||
* Method to extend to set conditions
|
||||
*
|
||||
* Returns an informative message indicating why the action cannot be used, null otherwise
|
||||
*/
|
||||
checkCannotBeApplied(ship: Ship, remaining_ap: number = null): string | null {
|
||||
let battle = ship.getBattle();
|
||||
if (battle && battle.playing_ship !== ship) {
|
||||
// Ship is not playing
|
||||
return false;
|
||||
return "ship not playing";
|
||||
}
|
||||
|
||||
// Check AP usage
|
||||
|
@ -34,11 +40,15 @@ module TS.SpaceTac {
|
|||
remaining_ap = ship.values.power.get();
|
||||
}
|
||||
var ap_usage = this.equipment ? this.equipment.ap_usage : 0;
|
||||
return remaining_ap >= ap_usage;
|
||||
if (remaining_ap >= ap_usage) {
|
||||
return null;
|
||||
} else {
|
||||
return "not enough power";
|
||||
}
|
||||
}
|
||||
|
||||
// Get the number of action points the action applied to a target would use
|
||||
getActionPointsUsage(battle: Battle, ship: Ship, target: Target): number {
|
||||
getActionPointsUsage(ship: Ship, target: Target): number {
|
||||
if (this.equipment) {
|
||||
return this.equipment.ap_usage;
|
||||
} else {
|
||||
|
@ -66,14 +76,14 @@ module TS.SpaceTac {
|
|||
|
||||
// Method to check if a target is applicable for this action
|
||||
// Will call checkLocationTarget or checkShipTarget by default
|
||||
checkTarget(battle: Battle, ship: Ship, target: Target): Target {
|
||||
if (!this.canBeUsed(battle, ship)) {
|
||||
checkTarget(ship: Ship, target: Target): Target {
|
||||
if (this.checkCannotBeApplied(ship)) {
|
||||
return null;
|
||||
} else if (target) {
|
||||
if (target.ship) {
|
||||
return this.checkShipTarget(battle, ship, target);
|
||||
return this.checkShipTarget(ship, target);
|
||||
} else {
|
||||
return this.checkLocationTarget(battle, ship, target);
|
||||
return this.checkLocationTarget(ship, target);
|
||||
}
|
||||
} else {
|
||||
return null;
|
||||
|
@ -82,38 +92,42 @@ module TS.SpaceTac {
|
|||
|
||||
// Method to reimplement to check if a space target is applicable
|
||||
// Must return null if the target can't be applied, an altered target, or the original target
|
||||
checkLocationTarget(battle: Battle, ship: Ship, target: Target): Target {
|
||||
checkLocationTarget(ship: Ship, target: Target): Target {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Method to reimplement to check if a ship target is applicable
|
||||
// Must return null if the target can't be applied, an altered target, or the original target
|
||||
checkShipTarget(battle: Battle, ship: Ship, target: Target): Target {
|
||||
checkShipTarget(ship: Ship, target: Target): Target {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Apply an action, returning true if it was successful
|
||||
apply(battle: Battle, ship: Ship, target: Target): boolean {
|
||||
if (this.canBeUsed(battle, ship)) {
|
||||
target = this.checkTarget(battle, ship, target);
|
||||
apply(ship: Ship, target: Target): boolean {
|
||||
let reject = this.checkCannotBeApplied(ship);
|
||||
if (reject == null) {
|
||||
target = this.checkTarget(ship, target);
|
||||
if (!target && this.needs_target) {
|
||||
console.warn("Action rejected - no target selected", ship, this, target);
|
||||
return false;
|
||||
}
|
||||
|
||||
let cost = this.getActionPointsUsage(battle, ship, target);
|
||||
let cost = this.getActionPointsUsage(ship, target);
|
||||
if (!ship.useActionPoints(cost)) {
|
||||
console.warn("Action rejected - not enough power", ship, this, target);
|
||||
return false;
|
||||
}
|
||||
|
||||
this.customApply(battle, ship, target);
|
||||
this.customApply(ship, target);
|
||||
return true;
|
||||
} else {
|
||||
console.warn(`Action rejected - ${reject}`, ship, this, target);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Method to reimplement to apply a action
|
||||
protected customApply(battle: Battle, ship: Ship, target: Target) {
|
||||
protected customApply(ship: Ship, target: Target) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,18 +20,18 @@ module TS.SpaceTac {
|
|||
equipment.ap_usage = 0;
|
||||
let action = new DeployDroneAction(equipment);
|
||||
|
||||
expect(action.checkTarget(null, ship, new Target(8, 0, null))).toEqual(new Target(8, 0, null));
|
||||
expect(action.checkTarget(null, ship, new Target(12, 0, null))).toEqual(new Target(8, 0, null));
|
||||
expect(action.checkTarget(ship, new Target(8, 0, null))).toEqual(new Target(8, 0, null));
|
||||
expect(action.checkTarget(ship, new Target(12, 0, null))).toEqual(new Target(8, 0, null));
|
||||
|
||||
let other = new Ship();
|
||||
other.setArenaPosition(8, 0);
|
||||
expect(action.checkTarget(null, ship, new Target(8, 0, other))).toBeNull();
|
||||
expect(action.checkTarget(ship, new Target(8, 0, other))).toBeNull();
|
||||
});
|
||||
|
||||
it("deploys a new drone", function () {
|
||||
let ship = new Ship();
|
||||
ship.setArenaPosition(0, 0);
|
||||
let battle = new Battle();
|
||||
let ship = battle.fleets[0].addShip();
|
||||
ship.setArenaPosition(0, 0);
|
||||
battle.playing_ship = ship;
|
||||
TestTools.setShipAP(ship, 3);
|
||||
let equipment = new Equipment();
|
||||
|
@ -43,7 +43,9 @@ module TS.SpaceTac {
|
|||
equipment.target_effects.push(new DamageEffect(50));
|
||||
let action = new DeployDroneAction(equipment);
|
||||
|
||||
let result = action.apply(battle, ship, new Target(5, 0, null));
|
||||
battle.log.clear();
|
||||
battle.log.addFilter("value");
|
||||
let result = action.apply(ship, new Target(5, 0, null));
|
||||
|
||||
expect(result).toBe(true);
|
||||
expect(battle.drones.length).toBe(1);
|
||||
|
|
|
@ -9,20 +9,24 @@ module TS.SpaceTac {
|
|||
super("deploy-" + equipment.code, "Deploy", true, equipment);
|
||||
}
|
||||
|
||||
checkLocationTarget(battle: Battle, ship: Ship, target: Target): Target {
|
||||
checkLocationTarget(ship: Ship, target: Target): Target {
|
||||
// TODO Not too close to other ships and drones
|
||||
target = target.constraintInRange(ship.arena_x, ship.arena_y, this.equipment.distance);
|
||||
return target;
|
||||
}
|
||||
|
||||
protected customApply(battle: Battle, ship: Ship, target: Target) {
|
||||
protected customApply(ship: Ship, target: Target) {
|
||||
let drone = new Drone(ship, this.equipment.code);
|
||||
drone.x = target.x;
|
||||
drone.y = target.y;
|
||||
drone.radius = this.equipment.blast;
|
||||
drone.effects = this.equipment.target_effects;
|
||||
drone.duration = this.equipment.duration;
|
||||
battle.addDrone(drone);
|
||||
|
||||
let battle = ship.getBattle();
|
||||
if (battle) {
|
||||
battle.addDrone(drone);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,14 +1,18 @@
|
|||
module TS.SpaceTac.Specs {
|
||||
describe("EndTurnAction", () => {
|
||||
it("can't be applied to non-playing ship", () => {
|
||||
spyOn(console, "warn").and.stub();
|
||||
|
||||
var battle = Battle.newQuickRandom();
|
||||
var action = new EndTurnAction();
|
||||
|
||||
expect(action.canBeUsed(battle, battle.play_order[0])).toBe(true);
|
||||
expect(action.canBeUsed(battle, battle.play_order[1])).toBe(false);
|
||||
expect(action.checkCannotBeApplied(battle.play_order[0])).toBe(null);
|
||||
expect(action.checkCannotBeApplied(battle.play_order[1])).toBe("ship not playing");
|
||||
|
||||
var result = action.apply(battle, battle.play_order[1], null);
|
||||
var result = action.apply(battle.play_order[1], null);
|
||||
expect(result).toBe(false);
|
||||
|
||||
expect(console.warn).toHaveBeenCalledWith("Action rejected - ship not playing", battle.play_order[1], action, null);
|
||||
});
|
||||
|
||||
it("ends turn when applied", () => {
|
||||
|
@ -17,7 +21,7 @@ module TS.SpaceTac.Specs {
|
|||
|
||||
expect(battle.playing_ship_index).toBe(0);
|
||||
|
||||
var result = action.apply(battle, battle.play_order[0], null);
|
||||
var result = action.apply(battle.play_order[0], null);
|
||||
expect(result).toBe(true);
|
||||
expect(battle.playing_ship_index).toBe(1);
|
||||
});
|
||||
|
|
|
@ -5,9 +5,13 @@ module TS.SpaceTac {
|
|||
super("endturn", "End ship's turn", false);
|
||||
}
|
||||
|
||||
protected customApply(battle: Battle, ship: Ship, target: Target) {
|
||||
protected customApply(ship: Ship, target: Target) {
|
||||
ship.endTurn();
|
||||
battle.advanceToNextShip();
|
||||
|
||||
let battle = ship.getBattle();
|
||||
if (battle) {
|
||||
battle.advanceToNextShip();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -39,7 +39,7 @@ module TS.SpaceTac {
|
|||
battle.playing_ship = ship;
|
||||
fleet.setBattle(battle);
|
||||
|
||||
action.apply(battle, ship, Target.newFromLocation(50, 50));
|
||||
action.apply(ship, Target.newFromLocation(50, 50));
|
||||
expect(mock_apply).toHaveBeenCalledTimes(1);
|
||||
expect(mock_apply).toHaveBeenCalledWith(ship2);
|
||||
});
|
||||
|
|
|
@ -12,7 +12,7 @@ module TS.SpaceTac {
|
|||
this.can_target_space = can_target_space;
|
||||
}
|
||||
|
||||
checkLocationTarget(battle: Battle, ship: Ship, target: Target): Target {
|
||||
checkLocationTarget(ship: Ship, target: Target): Target {
|
||||
if (this.can_target_space) {
|
||||
target = target.constraintInRange(ship.arena_x, ship.arena_y, this.equipment.distance);
|
||||
return target;
|
||||
|
@ -21,7 +21,7 @@ module TS.SpaceTac {
|
|||
}
|
||||
}
|
||||
|
||||
checkShipTarget(battle: Battle, ship: Ship, target: Target): Target {
|
||||
checkShipTarget(ship: Ship, target: Target): Target {
|
||||
if (ship.getPlayer() === target.ship.getPlayer()) {
|
||||
// No friendly fire
|
||||
return null;
|
||||
|
@ -48,7 +48,7 @@ module TS.SpaceTac {
|
|||
return result;
|
||||
}
|
||||
|
||||
protected customApply(battle: Battle, ship: Ship, target: Target) {
|
||||
protected customApply(ship: Ship, target: Target) {
|
||||
// Face the target
|
||||
ship.rotate(Target.newFromShip(ship).getAngleTo(target));
|
||||
|
||||
|
@ -56,7 +56,7 @@ module TS.SpaceTac {
|
|||
ship.addBattleEvent(new FireEvent(ship, this.equipment, target));
|
||||
|
||||
// Apply effects
|
||||
let effects = this.getEffects(battle, ship, target);
|
||||
let effects = this.getEffects(ship.getBattle(), ship, target);
|
||||
effects.forEach(([ship, effect]) => effect.applyOnShip(ship));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,14 +15,14 @@ module TS.SpaceTac {
|
|||
|
||||
expect(action.getDistanceByActionPoint(ship)).toBe(0.5);
|
||||
|
||||
var result = action.checkTarget(battle, ship, Target.newFromLocation(0, 2));
|
||||
var result = action.checkTarget(ship, Target.newFromLocation(0, 2));
|
||||
expect(result).toEqual(Target.newFromLocation(0, 2));
|
||||
|
||||
result = action.checkTarget(battle, ship, Target.newFromLocation(0, 8));
|
||||
result = action.checkTarget(ship, Target.newFromLocation(0, 8));
|
||||
expect(result).toEqual(Target.newFromLocation(0, 3));
|
||||
|
||||
ship.values.power.set(0);
|
||||
result = action.checkTarget(battle, ship, Target.newFromLocation(0, 8));
|
||||
result = action.checkTarget(ship, Target.newFromLocation(0, 8));
|
||||
expect(result).toBeNull();
|
||||
});
|
||||
|
||||
|
@ -31,10 +31,10 @@ module TS.SpaceTac {
|
|||
var ship2 = new Ship(null, "Test2");
|
||||
var action = new MoveAction(null);
|
||||
|
||||
var result = action.checkTarget(null, ship1, Target.newFromShip(ship1));
|
||||
var result = action.checkTarget(ship1, Target.newFromShip(ship1));
|
||||
expect(result).toBeNull();
|
||||
|
||||
result = action.checkTarget(null, ship1, Target.newFromShip(ship2));
|
||||
result = action.checkTarget(ship1, Target.newFromShip(ship2));
|
||||
expect(result).toBeNull();
|
||||
});
|
||||
|
||||
|
@ -51,13 +51,15 @@ module TS.SpaceTac {
|
|||
var action = new MoveAction(engine);
|
||||
battle.playing_ship = ship;
|
||||
|
||||
var result = action.apply(battle, ship, Target.newFromLocation(10, 10));
|
||||
spyOn(console, "warn").and.stub();
|
||||
|
||||
var result = action.apply(ship, Target.newFromLocation(10, 10));
|
||||
expect(result).toBe(true);
|
||||
expect(ship.arena_x).toBeCloseTo(3.535533, 0.00001);
|
||||
expect(ship.arena_y).toBeCloseTo(3.535533, 0.00001);
|
||||
expect(ship.values.power.get()).toEqual(0);
|
||||
|
||||
result = action.apply(battle, ship, Target.newFromLocation(10, 10));
|
||||
result = action.apply(ship, Target.newFromLocation(10, 10));
|
||||
expect(result).toBe(false);
|
||||
expect(ship.arena_x).toBeCloseTo(3.535533, 0.00001);
|
||||
expect(ship.arena_y).toBeCloseTo(3.535533, 0.00001);
|
||||
|
@ -89,19 +91,19 @@ module TS.SpaceTac {
|
|||
var action = new MoveAction(engine);
|
||||
action.safety_distance = 2;
|
||||
|
||||
var result = action.checkLocationTarget(battle, ship, Target.newFromLocation(7, 5));
|
||||
var result = action.checkLocationTarget(ship, Target.newFromLocation(7, 5));
|
||||
expect(result).toEqual(Target.newFromLocation(7, 5));
|
||||
|
||||
result = action.checkLocationTarget(battle, ship, Target.newFromLocation(8, 5));
|
||||
result = action.checkLocationTarget(ship, Target.newFromLocation(8, 5));
|
||||
expect(result).toEqual(Target.newFromLocation(8, 5));
|
||||
|
||||
result = action.checkLocationTarget(battle, ship, Target.newFromLocation(9, 5));
|
||||
result = action.checkLocationTarget(ship, Target.newFromLocation(9, 5));
|
||||
expect(result).toEqual(Target.newFromLocation(8, 5));
|
||||
|
||||
result = action.checkLocationTarget(battle, ship, Target.newFromLocation(10, 5));
|
||||
result = action.checkLocationTarget(ship, Target.newFromLocation(10, 5));
|
||||
expect(result).toEqual(Target.newFromLocation(8, 5));
|
||||
|
||||
result = action.checkLocationTarget(battle, ship, Target.newFromLocation(12, 5));
|
||||
result = action.checkLocationTarget(ship, Target.newFromLocation(12, 5));
|
||||
expect(result).toEqual(Target.newFromLocation(12, 5));
|
||||
});
|
||||
});
|
||||
|
|
|
@ -11,19 +11,24 @@ module TS.SpaceTac {
|
|||
this.safety_distance = 50;
|
||||
}
|
||||
|
||||
canBeUsed(battle: Battle, ship: Ship, remaining_ap: number = null): boolean {
|
||||
if (battle && battle.playing_ship !== ship) {
|
||||
return false;
|
||||
checkCannotBeApplied(ship: Ship, remaining_ap: number = null): string | null {
|
||||
let base = super.checkCannotBeApplied(ship, Infinity);
|
||||
if (base) {
|
||||
return base;
|
||||
}
|
||||
|
||||
// Check AP usage
|
||||
if (remaining_ap === null) {
|
||||
remaining_ap = ship.values.power.get();
|
||||
}
|
||||
return remaining_ap > 0.0001;
|
||||
if (remaining_ap > 0.0001) {
|
||||
return null
|
||||
} else {
|
||||
return "not enough power";
|
||||
}
|
||||
}
|
||||
|
||||
getActionPointsUsage(battle: Battle, ship: Ship, target: Target): number {
|
||||
getActionPointsUsage(ship: Ship, target: Target): number {
|
||||
if (target === null) {
|
||||
return 0;
|
||||
}
|
||||
|
@ -43,23 +48,26 @@ module TS.SpaceTac {
|
|||
return this.equipment.distance / this.equipment.ap_usage;
|
||||
}
|
||||
|
||||
checkLocationTarget(battle: Battle, ship: Ship, target: Target): Target {
|
||||
checkLocationTarget(ship: Ship, target: Target): Target {
|
||||
// Apply maximal distance
|
||||
var max_distance = this.getRangeRadius(ship);
|
||||
target = target.constraintInRange(ship.arena_x, ship.arena_y, max_distance);
|
||||
|
||||
// Apply collision prevention
|
||||
battle.play_order.forEach((iship: Ship) => {
|
||||
if (iship !== ship) {
|
||||
target = target.moveOutOfCircle(iship.arena_x, iship.arena_y, this.safety_distance,
|
||||
ship.arena_x, ship.arena_y);
|
||||
}
|
||||
});
|
||||
let battle = ship.getBattle();
|
||||
if (battle) {
|
||||
battle.play_order.forEach((iship: Ship) => {
|
||||
if (iship !== ship) {
|
||||
target = target.moveOutOfCircle(iship.arena_x, iship.arena_y, this.safety_distance,
|
||||
ship.arena_x, ship.arena_y);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return target;
|
||||
}
|
||||
|
||||
protected customApply(battle: Battle, ship: Ship, target: Target) {
|
||||
protected customApply(ship: Ship, target: Target) {
|
||||
ship.moveTo(target.x, target.y);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -44,14 +44,15 @@ module TS.SpaceTac {
|
|||
/**
|
||||
* Update the result of a single battle
|
||||
*/
|
||||
update(winner: AbstractAI | null) {
|
||||
if (winner) {
|
||||
if (winner == this.ai1) {
|
||||
update(winner: number) {
|
||||
if (winner >= 0) {
|
||||
if (winner == 0) {
|
||||
this.win1 += 1;
|
||||
console.log(` => Player 1 wins (${this.ai1})`);
|
||||
} else {
|
||||
this.win2 += 1;
|
||||
console.log(` => Player 2 wins (${this.ai2})`);
|
||||
}
|
||||
console.log(` => ${winner.name} wins`);
|
||||
} else {
|
||||
this.draw += 1;
|
||||
console.log(" => draw");
|
||||
|
@ -86,9 +87,9 @@ module TS.SpaceTac {
|
|||
}
|
||||
|
||||
if (battle.ended && !battle.outcome.draw) {
|
||||
this.update(battle.outcome.winner == battle.fleets[0] ? this.ai1 : this.ai2);
|
||||
this.update(battle.fleets.indexOf(battle.outcome.winner));
|
||||
} else {
|
||||
this.update(null);
|
||||
this.update(-1);
|
||||
}
|
||||
if (!this.stopped) {
|
||||
this.scheduled = Timer.global.schedule(100, () => this.next());
|
||||
|
|
|
@ -153,7 +153,7 @@ module TS.SpaceTac {
|
|||
if (distance > safety_distance) { // Don't move too close
|
||||
target = target.constraintInRange(this.ship.arena_x, this.ship.arena_y,
|
||||
(distance - safety_distance) * APPROACH_FACTOR);
|
||||
target = engine.action.checkLocationTarget(this.ship.getBattle(), this.ship, target);
|
||||
target = engine.action.checkLocationTarget(this.ship, target);
|
||||
return new BullyManeuver(new Maneuver(this.ship, engine, target));
|
||||
} else {
|
||||
return null;
|
||||
|
|
|
@ -32,8 +32,8 @@ module TS.SpaceTac {
|
|||
apply(): void {
|
||||
if (this.simulation.success) {
|
||||
this.simulation.parts.forEach(part => {
|
||||
if (!part.action.apply(this.ship.getBattle(), this.ship, part.target)) {
|
||||
console.error("AI cannot apply maneuver", this);
|
||||
if (!part.action.apply(this.ship, part.target)) {
|
||||
console.error("AI cannot apply maneuver", this, part);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -38,15 +38,15 @@ module TS.SpaceTac.Specs {
|
|||
|
||||
weapon.ap_usage = new Range(2);
|
||||
var equipment = weapon.generateFixed(0);
|
||||
expect(equipment.action.canBeUsed(null, ship)).toBe(true);
|
||||
expect(equipment.action.checkCannotBeApplied(ship)).toBe(null);
|
||||
|
||||
weapon.ap_usage = new Range(3);
|
||||
equipment = weapon.generateFixed(0);
|
||||
expect(equipment.action.canBeUsed(null, ship)).toBe(true);
|
||||
expect(equipment.action.checkCannotBeApplied(ship)).toBe(null);
|
||||
|
||||
weapon.ap_usage = new Range(4);
|
||||
equipment = weapon.generateFixed(0);
|
||||
expect(equipment.action.canBeUsed(null, ship)).toBe(false);
|
||||
expect(equipment.action.checkCannotBeApplied(ship)).toBe("not enough power");
|
||||
});
|
||||
|
||||
it("can't friendly fire", function () {
|
||||
|
@ -60,9 +60,9 @@ module TS.SpaceTac.Specs {
|
|||
weapon.setRange(10, 10);
|
||||
var equipment = weapon.generateFixed(0);
|
||||
|
||||
expect(equipment.action.checkShipTarget(null, ship1a, Target.newFromShip(ship2a))).toEqual(
|
||||
expect(equipment.action.checkShipTarget(ship1a, Target.newFromShip(ship2a))).toEqual(
|
||||
Target.newFromShip(ship2a));
|
||||
expect(equipment.action.checkShipTarget(null, ship1a, Target.newFromShip(ship1b))).toBeNull();
|
||||
expect(equipment.action.checkShipTarget(ship1a, Target.newFromShip(ship1b))).toBeNull();
|
||||
});
|
||||
|
||||
it("can't fire farther than its range", function () {
|
||||
|
@ -78,25 +78,25 @@ module TS.SpaceTac.Specs {
|
|||
var equipment = weapon.generateFixed(0);
|
||||
expect(equipment.distance).toEqual(10);
|
||||
|
||||
expect(equipment.action.checkLocationTarget(null, ship, Target.newFromLocation(15, 10))).toEqual(
|
||||
expect(equipment.action.checkLocationTarget(ship, Target.newFromLocation(15, 10))).toEqual(
|
||||
Target.newFromLocation(15, 10));
|
||||
expect(equipment.action.checkLocationTarget(null, ship, Target.newFromLocation(30, 10))).toEqual(
|
||||
expect(equipment.action.checkLocationTarget(ship, Target.newFromLocation(30, 10))).toEqual(
|
||||
Target.newFromLocation(20, 10));
|
||||
|
||||
// Ship targetting
|
||||
var ship2 = new Ship(fleet2);
|
||||
|
||||
ship2.setArenaPosition(10, 15);
|
||||
expect(equipment.action.checkShipTarget(null, ship, Target.newFromShip(ship2))).toEqual(
|
||||
expect(equipment.action.checkShipTarget(ship, Target.newFromShip(ship2))).toEqual(
|
||||
Target.newFromShip(ship2));
|
||||
|
||||
ship2.setArenaPosition(10, 25);
|
||||
expect(equipment.action.checkShipTarget(null, ship, Target.newFromShip(ship2))).toBeNull();
|
||||
expect(equipment.action.checkShipTarget(ship, Target.newFromShip(ship2))).toBeNull();
|
||||
|
||||
// Forbid targetting in space
|
||||
weapon.setRange(10, 10, false);
|
||||
equipment = weapon.generateFixed(0);
|
||||
expect(equipment.action.checkLocationTarget(null, ship, Target.newFromLocation(15, 10))).toBeNull();
|
||||
expect(equipment.action.checkLocationTarget(ship, Target.newFromLocation(15, 10))).toBeNull();
|
||||
});
|
||||
|
||||
it("can target an enemy ship and damage it", function () {
|
||||
|
@ -119,17 +119,17 @@ module TS.SpaceTac.Specs {
|
|||
|
||||
var equipment = weapon.generateFixed(0);
|
||||
|
||||
equipment.action.apply(null, ship1, Target.newFromShip(ship2));
|
||||
equipment.action.apply(ship1, Target.newFromShip(ship2));
|
||||
expect(ship2.values.hull.get()).toEqual(100);
|
||||
expect(ship2.values.shield.get()).toEqual(10);
|
||||
expect(ship1.values.power.get()).toEqual(49);
|
||||
|
||||
equipment.action.apply(null, ship1, Target.newFromShip(ship2));
|
||||
equipment.action.apply(ship1, Target.newFromShip(ship2));
|
||||
expect(ship2.values.hull.get()).toEqual(90);
|
||||
expect(ship2.values.shield.get()).toEqual(0);
|
||||
expect(ship1.values.power.get()).toEqual(48);
|
||||
|
||||
equipment.action.apply(null, ship1, Target.newFromShip(ship2));
|
||||
equipment.action.apply(ship1, Target.newFromShip(ship2));
|
||||
expect(ship2.values.hull.get()).toEqual(70);
|
||||
expect(ship2.values.shield.get()).toEqual(0);
|
||||
expect(ship1.values.power.get()).toEqual(47);
|
||||
|
|
|
@ -13,7 +13,7 @@ module TS.SpaceTac.Specs {
|
|||
expect(target.sticky_effects).toEqual([]);
|
||||
|
||||
// Attribute is immediately limited
|
||||
equipment.action.apply(null, ship, Target.newFromShip(target));
|
||||
equipment.action.apply(ship, Target.newFromShip(target));
|
||||
|
||||
expect(target.values.power.get()).toBe(4);
|
||||
expect(target.sticky_effects).toEqual([
|
||||
|
|
|
@ -7,10 +7,10 @@ module TS.SpaceTac.Equipments {
|
|||
expect(equipment.target_effects).toEqual([new ValueEffect("hull", 30)]);
|
||||
|
||||
let battle = new Battle();
|
||||
let ship = new Ship();
|
||||
let ship = battle.fleets[0].addShip();
|
||||
battle.playing_ship = ship;
|
||||
TestTools.setShipAP(ship, 10);
|
||||
let result = equipment.action.apply(battle, ship, new Target(5, 5, null));
|
||||
let result = equipment.action.apply(ship, new Target(5, 5, null));
|
||||
expect(result).toBe(true);
|
||||
|
||||
expect(battle.drones.length).toBe(1);
|
||||
|
|
|
@ -34,12 +34,12 @@ module TS.SpaceTac.Specs {
|
|||
battle.log.addFilter("value");
|
||||
|
||||
// Fire at a ship
|
||||
var t = Target.newFromShip(enemy1);
|
||||
expect(equipment.action.canBeUsed(battle, ship)).toBe(true);
|
||||
equipment.action.apply(battle, ship, t);
|
||||
var target = Target.newFromShip(enemy1);
|
||||
expect(equipment.action.checkCannotBeApplied(ship)).toBe(null);
|
||||
equipment.action.apply(ship, target);
|
||||
checkHP(50, 10, 50, 10, 50, 10);
|
||||
expect(battle.log.events.length).toBe(4);
|
||||
expect(battle.log.events[0]).toEqual(new FireEvent(ship, equipment, t));
|
||||
expect(battle.log.events[0]).toEqual(new FireEvent(ship, equipment, target));
|
||||
expect(battle.log.events[1]).toEqual(new DamageEvent(ship, 0, 20));
|
||||
expect(battle.log.events[2]).toEqual(new DamageEvent(enemy1, 0, 20));
|
||||
expect(battle.log.events[3]).toEqual(new DamageEvent(enemy2, 0, 20));
|
||||
|
@ -47,24 +47,24 @@ module TS.SpaceTac.Specs {
|
|||
battle.log.clear();
|
||||
|
||||
// Fire in space
|
||||
t = Target.newFromLocation(2.4, 0);
|
||||
expect(equipment.action.canBeUsed(battle, ship)).toBe(true);
|
||||
equipment.action.apply(battle, ship, t);
|
||||
target = Target.newFromLocation(2.4, 0);
|
||||
expect(equipment.action.checkCannotBeApplied(ship)).toBe(null);
|
||||
equipment.action.apply(ship, target);
|
||||
checkHP(50, 10, 40, 0, 40, 0);
|
||||
expect(battle.log.events.length).toBe(3);
|
||||
expect(battle.log.events[0]).toEqual(new FireEvent(ship, equipment, t));
|
||||
expect(battle.log.events[0]).toEqual(new FireEvent(ship, equipment, target));
|
||||
expect(battle.log.events[1]).toEqual(new DamageEvent(enemy1, 10, 10));
|
||||
expect(battle.log.events[2]).toEqual(new DamageEvent(enemy2, 10, 10));
|
||||
|
||||
battle.log.clear();
|
||||
|
||||
// Fire far away
|
||||
t = Target.newFromLocation(5, 0);
|
||||
expect(equipment.action.canBeUsed(battle, ship)).toBe(true);
|
||||
equipment.action.apply(battle, ship, t);
|
||||
target = Target.newFromLocation(5, 0);
|
||||
expect(equipment.action.checkCannotBeApplied(ship)).toBe(null);
|
||||
equipment.action.apply(ship, target);
|
||||
checkHP(50, 10, 40, 0, 40, 0);
|
||||
expect(battle.log.events.length).toBe(1);
|
||||
expect(battle.log.events[0]).toEqual(new FireEvent(ship, equipment, t));
|
||||
expect(battle.log.events[0]).toEqual(new FireEvent(ship, equipment, target));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
|
@ -88,7 +88,7 @@ module TS.SpaceTac.UI {
|
|||
if (!this.bar.interactive) {
|
||||
return;
|
||||
}
|
||||
if (!this.action.canBeUsed(this.battleview.battle, this.ship)) {
|
||||
if (this.action.checkCannotBeApplied(this.ship)) {
|
||||
return;
|
||||
}
|
||||
if (this.selected) {
|
||||
|
@ -104,7 +104,7 @@ module TS.SpaceTac.UI {
|
|||
this.battleview.arena.range_hint.setPrimary(this.ship, this.action);
|
||||
|
||||
// Update fading statuses
|
||||
this.bar.updateSelectedActionPower(this.action.getActionPointsUsage(this.battleview.battle, this.ship, null));
|
||||
this.bar.updateSelectedActionPower(this.action.getActionPointsUsage(this.ship, null));
|
||||
|
||||
// Set the selected state
|
||||
this.setSelected(true);
|
||||
|
@ -127,14 +127,14 @@ module TS.SpaceTac.UI {
|
|||
// Called when a target is hovered
|
||||
// This will check the target against current action and adjust it if needed
|
||||
processHover(target: Target): void {
|
||||
target = this.action.checkTarget(this.battleview.battle, this.ship, target);
|
||||
target = this.action.checkTarget(this.ship, target);
|
||||
this.targetting.setTarget(target, false, this.action.getBlastRadius(this.ship));
|
||||
this.bar.updateSelectedActionPower(this.action.getActionPointsUsage(this.battleview.battle, this.ship, target));
|
||||
this.bar.updateSelectedActionPower(this.action.getActionPointsUsage(this.ship, target));
|
||||
}
|
||||
|
||||
// Called when a target is selected
|
||||
processSelection(target: Target): void {
|
||||
if (this.action.apply(this.battleview.battle, this.ship, target)) {
|
||||
if (this.action.apply(this.ship, target)) {
|
||||
this.bar.actionEnded();
|
||||
}
|
||||
}
|
||||
|
@ -159,7 +159,7 @@ module TS.SpaceTac.UI {
|
|||
// Update the active status, from the action canBeUsed result
|
||||
updateActiveStatus(force = false): void {
|
||||
var old_active = this.active;
|
||||
this.active = this.action.canBeUsed(this.battleview.battle, this.ship);
|
||||
this.active = !this.action.checkCannotBeApplied(this.ship);
|
||||
if (force || (this.active != old_active)) {
|
||||
Animation.setVisibility(this.game, this.layer_active, this.active, 500);
|
||||
this.game.tweens.create(this.layer_icon).to({ alpha: this.active ? 1 : 0.3 }, 500).start();
|
||||
|
@ -170,7 +170,7 @@ module TS.SpaceTac.UI {
|
|||
// Update the fading status, given an hypothetical remaining AP
|
||||
updateFadingStatus(remaining_ap: number): void {
|
||||
var old_fading = this.fading;
|
||||
this.fading = this.active && !this.action.canBeUsed(this.battleview.battle, this.ship, remaining_ap);
|
||||
this.fading = this.active && (this.action.checkCannotBeApplied(this.ship, remaining_ap) != null);
|
||||
if (this.fading != old_fading) {
|
||||
Animation.setVisibility(this.game, this.layer_active, this.active && !this.fading, 500);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue