diff --git a/graphics/exported/equipment/ionthruster.png b/graphics/exported/equipment/ionthruster.png
new file mode 100644
index 0000000..1f1c189
Binary files /dev/null and b/graphics/exported/equipment/ionthruster.png differ
diff --git a/graphics/exported/equipment/voidhawkengine.png b/graphics/exported/equipment/voidhawkengine.png
new file mode 100644
index 0000000..d9d679a
Binary files /dev/null and b/graphics/exported/equipment/voidhawkengine.png differ
diff --git a/graphics/ui/actions.svg b/graphics/ui/actions.svg
index b60bb71..1a5411f 100644
--- a/graphics/ui/actions.svg
+++ b/graphics/ui/actions.svg
@@ -16,13 +16,29 @@
version="1.1"
inkscape:version="0.92.1 r15371"
sodipodi:docname="actions.svg"
- inkscape:export-filename="/home/michael/workspace/perso/spacetac/graphics/exported/equipment/invertershield.png"
+ inkscape:export-filename="/home/michael/workspace/perso/spacetac/graphics/exported/equipment/voidhawkengine.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90"
viewBox="0 0 256 256"
enable-background="new">
+
+
+
+
+
@@ -819,6 +835,244 @@
stdDeviation="1.6714617"
id="feGaussianBlur5574" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ style="display:none">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
{
- equipment.action = new MoveAction(equipment, resolveForLevel(distance_per_power, level));
+ equipment.action = new MoveAction(equipment, resolveForLevel(distance_per_power, level), resolveForLevel(safety_distance, level));
});
}
diff --git a/src/core/actions/MoveAction.spec.ts b/src/core/actions/MoveAction.spec.ts
index afec4bc..34e9380 100644
--- a/src/core/actions/MoveAction.spec.ts
+++ b/src/core/actions/MoveAction.spec.ts
@@ -106,7 +106,7 @@ module TS.SpaceTac {
expect(result).toEqual(Target.newFromLocation(12, 5));
});
- it("move exclusion radius is applied correctly over two ships", function () {
+ it("exclusion radius is applied correctly over two ships", function () {
var battle = TestTools.createBattle(1, 2);
var ship = battle.fleets[0].ships[0];
var enemy1 = battle.fleets[1].ships[0];
@@ -122,5 +122,24 @@ module TS.SpaceTac {
var result = action.checkLocationTarget(ship, Target.newFromLocation(0, 110));
expect(result).toEqual(Target.newFromLocation(0, 65));
});
+
+ it("exclusion radius does not make the ship go back", function () {
+ var battle = TestTools.createBattle(1, 2);
+ var ship = battle.fleets[0].ships[0];
+ var enemy1 = battle.fleets[1].ships[0];
+ var enemy2 = battle.fleets[1].ships[1];
+ TestTools.setShipAP(ship, 100);
+ enemy1.setArenaPosition(0, 50);
+ enemy2.setArenaPosition(0, 80);
+
+ var action = new MoveAction(new Equipment());
+ action.distance_per_power = 1000;
+ action.safety_distance = 60;
+
+ let result = action.checkLocationTarget(ship, Target.newFromLocation(0, 100));
+ expect(result).toBeNull();
+ result = action.checkLocationTarget(ship, Target.newFromLocation(0, 140));
+ expect(result).toEqual(Target.newFromLocation(0, 140));
+ });
});
}
diff --git a/src/core/actions/MoveAction.ts b/src/core/actions/MoveAction.ts
index 4b7dd73..50e4dd2 100644
--- a/src/core/actions/MoveAction.ts
+++ b/src/core/actions/MoveAction.ts
@@ -10,11 +10,11 @@ module TS.SpaceTac {
// Equipment cannot be null (engine)
equipment: Equipment
- constructor(equipment: Equipment, distance_per_power = 0) {
+ constructor(equipment: Equipment, distance_per_power = 0, safety_distance = 120) {
super("move", "Move", true, equipment);
this.distance_per_power = distance_per_power;
- this.safety_distance = 120;
+ this.safety_distance = safety_distance;
}
checkCannotBeApplied(ship: Ship, remaining_ap: number | null = null): string | null {
@@ -70,7 +70,13 @@ module TS.SpaceTac {
let ships = imaterialize(ifilter(battle.iships(true), s => s !== ship));
ships = ships.sort((a, b) => cmp(a.getDistanceTo(ship), b.getDistanceTo(ship), true));
ships.forEach(s => {
- target = target.moveOutOfCircle(s.arena_x, s.arena_y, this.safety_distance, ship.arena_x, ship.arena_y);
+ let new_target = target.moveOutOfCircle(s.arena_x, s.arena_y, this.safety_distance, ship.arena_x, ship.arena_y);
+ if (target != new_target && s.getDistanceTo(ship) < this.safety_distance) {
+ // Already inside the nearest ship's exclusion area
+ target = Target.newFromLocation(ship.arena_x, ship.arena_y);
+ } else {
+ target = new_target;
+ }
});
}
return target;
@@ -85,10 +91,10 @@ module TS.SpaceTac {
return target.constraintInRange(ship.arena_x, ship.arena_y, max_distance);
}
- checkLocationTarget(ship: Ship, target: Target): Target {
+ checkLocationTarget(ship: Ship, target: Target): Target | null {
target = this.applyReachableRange(ship, target);
target = this.applyExclusion(ship, target);
- return target;
+ return target.getDistanceTo(ship.location) > 0 ? target : null;
}
protected customApply(ship: Ship, target: Target) {
@@ -96,7 +102,7 @@ module TS.SpaceTac {
}
getEffectsDescription(): string {
- return `Move: ${this.distance_per_power}km per power point`;
+ return `Move: ${this.distance_per_power}km per power point (safety: ${this.safety_distance}km)`;
}
}
}
diff --git a/src/core/equipments/Engines.spec.ts b/src/core/equipments/Engines.spec.ts
new file mode 100644
index 0000000..0ba7bd6
--- /dev/null
+++ b/src/core/equipments/Engines.spec.ts
@@ -0,0 +1,99 @@
+module TS.SpaceTac.Equipments {
+ describe("Engines", function () {
+ it("generates RocketEngine based on level", function () {
+ let template = new RocketEngine();
+
+ let equipment = template.generate(1);
+ expect(equipment.requirements).toEqual({ "skill_materials": 1 });
+ expect(equipment.effects).toEqual([new AttributeEffect("maneuvrability", 2)]);
+ expect(equipment.cooldown).toEqual(new Cooldown(2, 0));
+ expect(equipment.action).toEqual(new MoveAction(equipment, 200));
+ expect(equipment.price).toEqual(120);
+
+ equipment = template.generate(2);
+ expect(equipment.requirements).toEqual({ "skill_materials": 2 });
+ expect(equipment.effects).toEqual([new AttributeEffect("maneuvrability", 4)]);
+ expect(equipment.cooldown).toEqual(new Cooldown(2, 0));
+ expect(equipment.action).toEqual(new MoveAction(equipment, 220));
+ expect(equipment.price).toEqual(320);
+
+ equipment = template.generate(3);
+ expect(equipment.requirements).toEqual({ "skill_materials": 3 });
+ expect(equipment.effects).toEqual([new AttributeEffect("maneuvrability", 6)]);
+ expect(equipment.cooldown).toEqual(new Cooldown(2, 0));
+ expect(equipment.action).toEqual(new MoveAction(equipment, 240));
+ expect(equipment.price).toEqual(720);
+
+ equipment = template.generate(10);
+ expect(equipment.requirements).toEqual({ "skill_materials": 10 });
+ expect(equipment.effects).toEqual([new AttributeEffect("maneuvrability", 20)]);
+ expect(equipment.cooldown).toEqual(new Cooldown(2, 0));
+ expect(equipment.action).toEqual(new MoveAction(equipment, 380));
+ expect(equipment.price).toEqual(9120);
+ });
+
+ it("generates IonEngine based on level", function () {
+ let template = new IonEngine();
+
+ let equipment = template.generate(1);
+ expect(equipment.requirements).toEqual({ "skill_photons": 1 });
+ expect(equipment.effects).toEqual([new AttributeEffect("maneuvrability", 1)]);
+ expect(equipment.cooldown).toEqual(new Cooldown(3, 1));
+ expect(equipment.action).toEqual(new MoveAction(equipment, 120));
+ expect(equipment.price).toEqual(150);
+
+ equipment = template.generate(2);
+ expect(equipment.requirements).toEqual({ "skill_photons": 2 });
+ expect(equipment.effects).toEqual([new AttributeEffect("maneuvrability", 2)]);
+ expect(equipment.cooldown).toEqual(new Cooldown(3, 1));
+ expect(equipment.action).toEqual(new MoveAction(equipment, 135));
+ expect(equipment.price).toEqual(380);
+
+ equipment = template.generate(3);
+ expect(equipment.requirements).toEqual({ "skill_photons": 3 });
+ expect(equipment.effects).toEqual([new AttributeEffect("maneuvrability", 3)]);
+ expect(equipment.cooldown).toEqual(new Cooldown(3, 1));
+ expect(equipment.action).toEqual(new MoveAction(equipment, 150));
+ expect(equipment.price).toEqual(840);
+
+ equipment = template.generate(10);
+ expect(equipment.requirements).toEqual({ "skill_photons": 10 });
+ expect(equipment.effects).toEqual([new AttributeEffect("maneuvrability", 10)]);
+ expect(equipment.cooldown).toEqual(new Cooldown(3, 1));
+ expect(equipment.action).toEqual(new MoveAction(equipment, 255));
+ expect(equipment.price).toEqual(10500);
+ });
+
+ it("generates VoidhawkEngine based on level", function () {
+ let template = new VoidhawkEngine();
+
+ let equipment = template.generate(1);
+ expect(equipment.requirements).toEqual({ "skill_gravity": 2 });
+ expect(equipment.effects).toEqual([new AttributeEffect("maneuvrability", -5)]);
+ expect(equipment.cooldown).toEqual(new Cooldown(1, 0));
+ expect(equipment.action).toEqual(new MoveAction(equipment, 2000, 250));
+ expect(equipment.price).toEqual(340);
+
+ equipment = template.generate(2);
+ expect(equipment.requirements).toEqual({ "skill_gravity": 4 });
+ expect(equipment.effects).toEqual([new AttributeEffect("maneuvrability", -5)]);
+ expect(equipment.cooldown).toEqual(new Cooldown(1, 0));
+ expect(equipment.action).toEqual(new MoveAction(equipment, 2000, 240));
+ expect(equipment.price).toEqual(500);
+
+ equipment = template.generate(3);
+ expect(equipment.requirements).toEqual({ "skill_gravity": 6 });
+ expect(equipment.effects).toEqual([new AttributeEffect("maneuvrability", -4)]);
+ expect(equipment.cooldown).toEqual(new Cooldown(1, 0));
+ expect(equipment.action).toEqual(new MoveAction(equipment, 2000, 230));
+ expect(equipment.price).toEqual(820);
+
+ equipment = template.generate(10);
+ expect(equipment.requirements).toEqual({ "skill_gravity": 20 });
+ expect(equipment.effects).toEqual([new AttributeEffect("maneuvrability", 2)]);
+ expect(equipment.cooldown).toEqual(new Cooldown(1, 0));
+ expect(equipment.action).toEqual(new MoveAction(equipment, 2000, 160));
+ expect(equipment.price).toEqual(7540);
+ });
+ });
+}
diff --git a/src/core/equipments/Engines.ts b/src/core/equipments/Engines.ts
new file mode 100644
index 0000000..67bd2cf
--- /dev/null
+++ b/src/core/equipments/Engines.ts
@@ -0,0 +1,36 @@
+///
+
+module TS.SpaceTac.Equipments {
+ export class RocketEngine extends LootTemplate {
+ constructor() {
+ super(SlotType.Engine, "Rocket Engine", "First-era conventional deep-space engine, based on gas exhausts pushed through a nozzle", 120);
+
+ this.setSkillsRequirements({ "skill_materials": 1 });
+ this.setCooldown(irepeat(2), 0);
+ this.addAttributeEffect("maneuvrability", 2);
+ this.addMoveAction(istep(200, irepeat(20)));
+ }
+ }
+
+ export class IonEngine extends LootTemplate {
+ constructor() {
+ super(SlotType.Engine, "Ion Thruster", "Electric propulsion based on accelerating ions through an electrostatic grid", 150, 230);
+
+ this.setSkillsRequirements({ "skill_photons": 1 });
+ this.setCooldown(irepeat(3), irepeat(1));
+ this.addAttributeEffect("maneuvrability", 1);
+ this.addMoveAction(istep(120, irepeat(15)));
+ }
+ }
+
+ export class VoidhawkEngine extends LootTemplate {
+ constructor() {
+ super(SlotType.Engine, "VoidHawk Engine", "Mid-range gravity field warp generator, allowing to make small jumps", 340, 160);
+
+ this.setSkillsRequirements({ "skill_gravity": 2 });
+ this.setCooldown(irepeat(1), 0);
+ this.addAttributeEffect("maneuvrability", istep(-5, irepeat(0.8)));
+ this.addMoveAction(irepeat(2000), istep(250, irepeat(-10)));
+ }
+ }
+}
diff --git a/src/core/equipments/RocketEngine.spec.ts b/src/core/equipments/RocketEngine.spec.ts
deleted file mode 100644
index fb0937a..0000000
--- a/src/core/equipments/RocketEngine.spec.ts
+++ /dev/null
@@ -1,27 +0,0 @@
-module TS.SpaceTac.Equipments {
- describe("Rocket Engine", function () {
- it("generates equipment based on level", function () {
- let template = new RocketEngine();
-
- let equipment = template.generate(1);
- expect(equipment.requirements).toEqual({ "skill_photons": 1 });
- expect(equipment.effects).toEqual([new AttributeEffect("maneuvrability", 1)]);
- expect(equipment.action).toEqual(new MoveAction(equipment, 200));
-
- equipment = template.generate(2);
- expect(equipment.requirements).toEqual({ "skill_photons": 2 });
- expect(equipment.effects).toEqual([new AttributeEffect("maneuvrability", 2)]);
- expect(equipment.action).toEqual(new MoveAction(equipment, 220));
-
- equipment = template.generate(3);
- expect(equipment.requirements).toEqual({ "skill_photons": 3 });
- expect(equipment.effects).toEqual([new AttributeEffect("maneuvrability", 3)]);
- expect(equipment.action).toEqual(new MoveAction(equipment, 240));
-
- equipment = template.generate(10);
- expect(equipment.requirements).toEqual({ "skill_photons": 10 });
- expect(equipment.effects).toEqual([new AttributeEffect("maneuvrability", 10)]);
- expect(equipment.action).toEqual(new MoveAction(equipment, 380));
- });
- });
-}
diff --git a/src/core/equipments/RocketEngine.ts b/src/core/equipments/RocketEngine.ts
deleted file mode 100644
index a7c7d87..0000000
--- a/src/core/equipments/RocketEngine.ts
+++ /dev/null
@@ -1,14 +0,0 @@
-///
-
-module TS.SpaceTac.Equipments {
- export class RocketEngine extends LootTemplate {
- constructor() {
- super(SlotType.Engine, "Rocket Engine", "First-era conventional deep-space engine, based on gas exhausts pushed through a nozzle");
-
- this.setSkillsRequirements({ "skill_photons": 1 });
- this.setCooldown(irepeat(2), 0);
- this.addAttributeEffect("maneuvrability", 1);
- this.addMoveAction(istep(200, irepeat(20)));
- }
- }
-}
diff --git a/src/ui/battle/ActionTooltip.spec.ts b/src/ui/battle/ActionTooltip.spec.ts
index e366d55..629d094 100644
--- a/src/ui/battle/ActionTooltip.spec.ts
+++ b/src/ui/battle/ActionTooltip.spec.ts
@@ -21,7 +21,7 @@ module TS.SpaceTac.UI.Specs {
ActionTooltip.fill(tooltip.getFiller(), ship, action1, 0);
checkText((tooltip).container.content.children[1], "Engine");
checkText((tooltip).container.content.children[2], "Cost: 1 power per 0km");
- checkText((tooltip).container.content.children[3], "Move: 0km per power point");
+ checkText((tooltip).container.content.children[3], "Move: 0km per power point (safety: 120km)");
checkText((tooltip).container.content.children[4], "[ 1 ]");
tooltip.hide();