Move distance is now dependent on maneuvrability
This commit is contained in:
parent
d3cbcb0c04
commit
2106b93439
1
TODO.md
1
TODO.md
|
@ -58,7 +58,6 @@ Ships models and equipments
|
|||
* Add permanent effects and actions to ship models
|
||||
* Add critical hit/miss
|
||||
* Add damage over time effect (tricky to make intuitive)
|
||||
* Move distance should increase with maneuvrability
|
||||
* Chance to hit should increase with precision
|
||||
* Add actions with cost dependent of distance (like current move actions)
|
||||
* Add "cone" targetting
|
||||
|
|
|
@ -82,6 +82,7 @@ module TS.SpaceTac {
|
|||
|
||||
if (equipment.action instanceof MoveAction) {
|
||||
simpleFactor(equipment.action, 'distance_per_power');
|
||||
simpleFactor(equipment.action, 'maneuvrability_factor', true);
|
||||
}
|
||||
|
||||
if (equipment.cooldown.overheat) {
|
||||
|
|
|
@ -84,13 +84,13 @@ module TS.SpaceTac.Specs {
|
|||
|
||||
it("adds move actions", function () {
|
||||
let template = new LootTemplate(SlotType.Engine, "Engine");
|
||||
template.addMoveAction(irange(undefined, 100, 10));
|
||||
template.addMoveAction(irange(undefined, 100, 10), istep(50, irepeat(10)), irepeat(95));
|
||||
|
||||
let result = template.generate(1);
|
||||
expect(result.action).toEqual(new MoveAction(result, 100));
|
||||
expect(result.action).toEqual(new MoveAction(result, 100, 50, 95));
|
||||
|
||||
result = template.generate(2);
|
||||
expect(result.action).toEqual(new MoveAction(result, 110));
|
||||
expect(result.action).toEqual(new MoveAction(result, 110, 60, 95));
|
||||
});
|
||||
|
||||
it("adds fire actions", function () {
|
||||
|
|
|
@ -193,9 +193,9 @@ module TS.SpaceTac {
|
|||
/**
|
||||
* Add a move action.
|
||||
*/
|
||||
addMoveAction(distance_per_power: LeveledValue, safety_distance: LeveledValue = irepeat(120)): void {
|
||||
addMoveAction(distance_per_power: LeveledValue, safety_distance: LeveledValue = irepeat(120), maneuvrability_factor: LeveledValue = irepeat(80)): void {
|
||||
this.base_modifiers.push((equipment, level) => {
|
||||
equipment.action = new MoveAction(equipment, resolveForLevel(distance_per_power, level), resolveForLevel(safety_distance, level));
|
||||
equipment.action = new MoveAction(equipment, resolveForLevel(distance_per_power, level), resolveForLevel(safety_distance, level), resolveForLevel(maneuvrability_factor, level));
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -60,7 +60,7 @@ module TS.SpaceTac {
|
|||
if (engines.length == 0) {
|
||||
return null;
|
||||
} else {
|
||||
return maxBy(engines, engine => (engine.action instanceof MoveAction) ? engine.action.distance_per_power : 0);
|
||||
return maxBy(engines, engine => (engine.action instanceof MoveAction) ? engine.action.getDistanceByActionPoint(this.ship) : 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -35,10 +35,12 @@ module TS.SpaceTac {
|
|||
return equipment;
|
||||
}
|
||||
|
||||
// Add an engine, allowing a ship to move *distance*, for each action points
|
||||
/**
|
||||
* Add an engine, allowing a ship to move *distance*, for each action points
|
||||
*/
|
||||
static addEngine(ship: Ship, distance: number): Equipment {
|
||||
var equipment = this.getOrGenEquipment(ship, SlotType.Engine, new Equipments.RocketEngine(), true);
|
||||
(<MoveAction>equipment.action).distance_per_power = distance;
|
||||
let equipment = ship.addSlot(SlotType.Engine).attach(new Equipment(SlotType.Engine));
|
||||
equipment.action = new MoveAction(equipment, distance);
|
||||
return equipment;
|
||||
}
|
||||
|
||||
|
|
|
@ -9,18 +9,18 @@ module TS.SpaceTac {
|
|||
ship.arena_x = 0;
|
||||
ship.arena_y = 0;
|
||||
var engine = new Equipment();
|
||||
var action = new MoveAction(engine, 0.5);
|
||||
var action = new MoveAction(engine, 10);
|
||||
|
||||
expect(action.getDistanceByActionPoint(ship)).toBe(0.5);
|
||||
expect(action.getDistanceByActionPoint(ship)).toBe(10);
|
||||
|
||||
var result = action.checkTarget(ship, Target.newFromLocation(0, 2));
|
||||
expect(result).toEqual(Target.newFromLocation(0, 2));
|
||||
var result = action.checkTarget(ship, Target.newFromLocation(0, 20));
|
||||
expect(result).toEqual(Target.newFromLocation(0, 20));
|
||||
|
||||
result = action.checkTarget(ship, Target.newFromLocation(0, 8));
|
||||
expect(result).toEqual(Target.newFromLocation(0, 2.9));
|
||||
result = action.checkTarget(ship, Target.newFromLocation(0, 80));
|
||||
expect(nn(result).y).toBeCloseTo(59.9, 0.000001);
|
||||
|
||||
ship.values.power.set(0);
|
||||
result = action.checkTarget(ship, Target.newFromLocation(0, 8));
|
||||
result = action.checkTarget(ship, Target.newFromLocation(0, 80));
|
||||
expect(result).toBeNull();
|
||||
});
|
||||
|
||||
|
@ -141,5 +141,36 @@ module TS.SpaceTac {
|
|||
result = action.checkLocationTarget(ship, Target.newFromLocation(0, 1400));
|
||||
expect(result).toEqual(Target.newFromLocation(0, 1400));
|
||||
});
|
||||
|
||||
it("applies ship maneuvrability to determine distance per power point", function () {
|
||||
let ship = new Ship();
|
||||
|
||||
let action = new MoveAction(new Equipment(), 100, undefined, 60);
|
||||
ship.setAttribute("maneuvrability", 0);
|
||||
expect(action.getDistanceByActionPoint(ship)).toBeCloseTo(40, 0.01);
|
||||
ship.setAttribute("maneuvrability", 1);
|
||||
expect(action.getDistanceByActionPoint(ship)).toBeCloseTo(60, 0.01);
|
||||
ship.setAttribute("maneuvrability", 2);
|
||||
expect(action.getDistanceByActionPoint(ship)).toBeCloseTo(70, 0.01);
|
||||
ship.setAttribute("maneuvrability", 10);
|
||||
expect(action.getDistanceByActionPoint(ship)).toBeCloseTo(90, 0.01);
|
||||
|
||||
action = new MoveAction(new Equipment(), 100, undefined, 0);
|
||||
ship.setAttribute("maneuvrability", 0);
|
||||
expect(action.getDistanceByActionPoint(ship)).toBeCloseTo(100, 0.01);
|
||||
ship.setAttribute("maneuvrability", 10);
|
||||
expect(action.getDistanceByActionPoint(ship)).toBeCloseTo(100, 0.01);
|
||||
});
|
||||
|
||||
it("builds a textual description", function () {
|
||||
let action = new MoveAction(new Equipment(), 58, 0, 0);
|
||||
expect(action.getEffectsDescription()).toEqual("Move: 58km per power point");
|
||||
|
||||
action = new MoveAction(new Equipment(), 58, 12, 0);
|
||||
expect(action.getEffectsDescription()).toEqual("Move: 58km per power point (safety: 12km)");
|
||||
|
||||
action = new MoveAction(new Equipment(), 58, 12, 80);
|
||||
expect(action.getEffectsDescription()).toEqual("Move: 58km per power point (safety: 12km, maneuvrability influence: 80%)");
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
module TS.SpaceTac {
|
||||
// Action to move to a given location
|
||||
export class MoveAction extends BaseAction {
|
||||
// Distance allowed for each power point
|
||||
// Distance allowed for each power point (raw, without applying maneuvrability)
|
||||
distance_per_power: number
|
||||
|
||||
// Safety distance from other ships
|
||||
|
@ -10,11 +10,15 @@ module TS.SpaceTac {
|
|||
// Equipment cannot be null (engine)
|
||||
equipment: Equipment
|
||||
|
||||
constructor(equipment: Equipment, distance_per_power = 0, safety_distance = 120) {
|
||||
// Impact of maneuvrability (in % of distance)
|
||||
maneuvrability_factor: number
|
||||
|
||||
constructor(equipment: Equipment, distance_per_power = 0, safety_distance = 120, maneuvrability_factor = 0) {
|
||||
super("move", "Move", true, equipment);
|
||||
|
||||
this.distance_per_power = distance_per_power;
|
||||
this.safety_distance = safety_distance;
|
||||
this.maneuvrability_factor = maneuvrability_factor;
|
||||
}
|
||||
|
||||
checkCannotBeApplied(ship: Ship, remaining_ap: number | null = null): string | null {
|
||||
|
@ -40,18 +44,20 @@ module TS.SpaceTac {
|
|||
}
|
||||
|
||||
var distance = Target.newFromShip(ship).getDistanceTo(target);
|
||||
return Math.ceil(distance / this.distance_per_power);
|
||||
return Math.ceil(distance / this.getDistanceByActionPoint(ship));
|
||||
}
|
||||
|
||||
getRangeRadius(ship: Ship): number {
|
||||
return ship.values.power.get() * this.distance_per_power;
|
||||
return ship.getValue("power") * this.getDistanceByActionPoint(ship);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the distance that may be traveled with 1 action point
|
||||
*/
|
||||
getDistanceByActionPoint(ship: Ship): number {
|
||||
return this.distance_per_power;
|
||||
let maneuvrability = Math.max(ship.getAttribute("maneuvrability"), 0);
|
||||
let factor = maneuvrability / (maneuvrability + 2);
|
||||
return Math.ceil(this.distance_per_power * (1 - this.maneuvrability_factor * 0.01 * (1 - factor)));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -92,7 +98,20 @@ module TS.SpaceTac {
|
|||
}
|
||||
|
||||
getEffectsDescription(): string {
|
||||
return `Move: ${this.distance_per_power}km per power point (safety: ${this.safety_distance}km)`;
|
||||
let result = `Move: ${this.distance_per_power}km per power point`;
|
||||
|
||||
let precisions = [];
|
||||
if (this.safety_distance) {
|
||||
precisions.push(`safety: ${this.safety_distance}km`);
|
||||
}
|
||||
if (this.maneuvrability_factor) {
|
||||
precisions.push(`maneuvrability influence: ${this.maneuvrability_factor}%`);
|
||||
}
|
||||
if (precisions.length) {
|
||||
result += ` (${precisions.join(", ")})`;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,60 +7,60 @@ module TS.SpaceTac.Equipments {
|
|||
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.action).toEqual(new MoveAction(equipment, 200, 120, 70));
|
||||
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.action).toEqual(new MoveAction(equipment, 220, 120, 70));
|
||||
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.action).toEqual(new MoveAction(equipment, 240, 120, 70));
|
||||
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.action).toEqual(new MoveAction(equipment, 380, 120, 70));
|
||||
expect(equipment.price).toEqual(9120);
|
||||
});
|
||||
|
||||
it("generates IonEngine based on level", function () {
|
||||
let template = new IonEngine();
|
||||
it("generates IonThruster based on level", function () {
|
||||
let template = new IonThruster();
|
||||
|
||||
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.action).toEqual(new MoveAction(equipment, 120, 120, 80));
|
||||
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.action).toEqual(new MoveAction(equipment, 135, 120, 80));
|
||||
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.action).toEqual(new MoveAction(equipment, 150, 120, 80));
|
||||
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.action).toEqual(new MoveAction(equipment, 255, 120, 80));
|
||||
expect(equipment.price).toEqual(10500);
|
||||
});
|
||||
|
||||
|
@ -71,28 +71,28 @@ module TS.SpaceTac.Equipments {
|
|||
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.action).toEqual(new MoveAction(equipment, 2000, 250, 0));
|
||||
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.action).toEqual(new MoveAction(equipment, 2000, 240, 0));
|
||||
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.action).toEqual(new MoveAction(equipment, 2000, 230, 0));
|
||||
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.action).toEqual(new MoveAction(equipment, 2000, 160, 0));
|
||||
expect(equipment.price).toEqual(7540);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -8,11 +8,11 @@ module TS.SpaceTac.Equipments {
|
|||
this.setSkillsRequirements({ "skill_materials": 1 });
|
||||
this.setCooldown(irepeat(2), 0);
|
||||
this.addAttributeEffect("maneuvrability", 2);
|
||||
this.addMoveAction(istep(200, irepeat(20)));
|
||||
this.addMoveAction(istep(200, irepeat(20)), undefined, irepeat(70));
|
||||
}
|
||||
}
|
||||
|
||||
export class IonEngine extends LootTemplate {
|
||||
export class IonThruster extends LootTemplate {
|
||||
constructor() {
|
||||
super(SlotType.Engine, "Ion Thruster", "Electric propulsion based on accelerating ions through an electrostatic grid", 150, 230);
|
||||
|
||||
|
@ -30,7 +30,7 @@ module TS.SpaceTac.Equipments {
|
|||
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)));
|
||||
this.addMoveAction(irepeat(2000), istep(250, irepeat(-10)), irepeat(0));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@ module TS.SpaceTac.UI {
|
|||
if (ship.getValue("power") == 0) {
|
||||
cost = "Not enough power";
|
||||
} else {
|
||||
cost = `Cost: 1 power per ${action.distance_per_power}km`;
|
||||
cost = `Cost: 1 power per ${action.getDistanceByActionPoint(ship)}km`;
|
||||
}
|
||||
} else if (action.equipment) {
|
||||
let power_usage = action.getActionPointsUsage(ship, null);
|
||||
|
|
|
@ -108,7 +108,7 @@ module TS.SpaceTac.UI {
|
|||
let move = part.action instanceof MoveAction;
|
||||
let color = (enabled && part.possible) ? (move ? 0xe09c47 : 0xdc6441) : 0x8e8e8e;
|
||||
let src = previous ? previous.target : this.ship.location;
|
||||
let gradation = part.action instanceof MoveAction ? part.action.distance_per_power : 0;
|
||||
let gradation = (part.action instanceof MoveAction) ? part.action.getDistanceByActionPoint(this.ship) : 0;
|
||||
this.drawVector(color, src.x, src.y, part.target.x, part.target.y, gradation);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue