2017-02-09 00:00:35 +00:00
|
|
|
module TS.SpaceTac {
|
2014-12-31 00:00:00 +00:00
|
|
|
// Action to move to a given location
|
|
|
|
export class MoveAction extends BaseAction {
|
2017-08-17 22:53:21 +00:00
|
|
|
// Distance allowed for each power point (raw, without applying maneuvrability)
|
2017-05-29 18:12:57 +00:00
|
|
|
distance_per_power: number
|
2015-04-21 20:14:17 +00:00
|
|
|
|
2017-08-17 17:51:22 +00:00
|
|
|
// Safety distance from other ships
|
2017-05-29 18:12:57 +00:00
|
|
|
safety_distance: number
|
2015-04-21 20:14:17 +00:00
|
|
|
|
2017-03-09 17:11:00 +00:00
|
|
|
// Equipment cannot be null (engine)
|
2017-05-29 18:12:57 +00:00
|
|
|
equipment: Equipment
|
2017-03-09 17:11:00 +00:00
|
|
|
|
2017-08-17 22:53:21 +00:00
|
|
|
// Impact of maneuvrability (in % of distance)
|
|
|
|
maneuvrability_factor: number
|
|
|
|
|
|
|
|
constructor(equipment: Equipment, distance_per_power = 0, safety_distance = 120, maneuvrability_factor = 0) {
|
2017-01-08 22:42:53 +00:00
|
|
|
super("move", "Move", true, equipment);
|
2015-04-21 20:14:17 +00:00
|
|
|
|
2017-04-18 19:51:23 +00:00
|
|
|
this.distance_per_power = distance_per_power;
|
2017-07-31 22:49:00 +00:00
|
|
|
this.safety_distance = safety_distance;
|
2017-08-17 22:53:21 +00:00
|
|
|
this.maneuvrability_factor = maneuvrability_factor;
|
2014-12-31 00:00:00 +00:00
|
|
|
}
|
|
|
|
|
2017-03-09 17:11:00 +00:00
|
|
|
checkCannotBeApplied(ship: Ship, remaining_ap: number | null = null): string | null {
|
2017-03-07 19:27:46 +00:00
|
|
|
let base = super.checkCannotBeApplied(ship, Infinity);
|
|
|
|
if (base) {
|
|
|
|
return base;
|
2015-02-26 00:00:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Check AP usage
|
|
|
|
if (remaining_ap === null) {
|
2017-02-07 19:15:21 +00:00
|
|
|
remaining_ap = ship.values.power.get();
|
2015-02-26 00:00:00 +00:00
|
|
|
}
|
2017-03-07 19:27:46 +00:00
|
|
|
if (remaining_ap > 0.0001) {
|
2017-03-08 23:18:40 +00:00
|
|
|
return null;
|
2017-03-07 19:27:46 +00:00
|
|
|
} else {
|
|
|
|
return "not enough power";
|
|
|
|
}
|
2014-12-31 00:00:00 +00:00
|
|
|
}
|
|
|
|
|
2017-03-07 19:27:46 +00:00
|
|
|
getActionPointsUsage(ship: Ship, target: Target): number {
|
2015-02-26 00:00:00 +00:00
|
|
|
if (target === null) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
var distance = Target.newFromShip(ship).getDistanceTo(target);
|
2017-08-17 22:53:21 +00:00
|
|
|
return Math.ceil(distance / this.getDistanceByActionPoint(ship));
|
2015-02-26 00:00:00 +00:00
|
|
|
}
|
|
|
|
|
2015-03-03 00:00:00 +00:00
|
|
|
getRangeRadius(ship: Ship): number {
|
2017-08-17 22:53:21 +00:00
|
|
|
return ship.getValue("power") * this.getDistanceByActionPoint(ship);
|
2015-03-03 00:00:00 +00:00
|
|
|
}
|
|
|
|
|
2017-09-10 20:20:29 +00:00
|
|
|
/**
|
|
|
|
* Get the distance range that may be traveled with 1 action point
|
|
|
|
*/
|
|
|
|
getDistanceRangeByActionPoint(): IntegerRange {
|
|
|
|
let min_distance = Math.ceil(this.distance_per_power * (1 - this.maneuvrability_factor * 0.01));
|
|
|
|
return new IntegerRange(min_distance, this.distance_per_power);
|
|
|
|
}
|
|
|
|
|
2017-01-19 18:33:56 +00:00
|
|
|
/**
|
|
|
|
* Get the distance that may be traveled with 1 action point
|
|
|
|
*/
|
|
|
|
getDistanceByActionPoint(ship: Ship): number {
|
2017-08-17 22:53:21 +00:00
|
|
|
let maneuvrability = Math.max(ship.getAttribute("maneuvrability"), 0);
|
|
|
|
let factor = maneuvrability / (maneuvrability + 2);
|
2017-09-10 20:20:29 +00:00
|
|
|
let range = this.getDistanceRangeByActionPoint();
|
|
|
|
return range.getProportional(factor);
|
2017-01-19 18:33:56 +00:00
|
|
|
}
|
|
|
|
|
2017-08-17 17:51:22 +00:00
|
|
|
/**
|
|
|
|
* Get an exclusion helper for this move action
|
|
|
|
*/
|
|
|
|
getExclusionAreas(ship: Ship): ExclusionAreas {
|
|
|
|
return ExclusionAreas.fromShip(ship, this.safety_distance);
|
|
|
|
}
|
|
|
|
|
2017-06-19 23:04:27 +00:00
|
|
|
/**
|
|
|
|
* Apply exclusion areas (neer arena borders, or other ships)
|
|
|
|
*/
|
2017-08-17 17:51:22 +00:00
|
|
|
applyExclusion(ship: Ship, target: Target): Target {
|
|
|
|
let exclusion = this.getExclusionAreas(ship);
|
|
|
|
|
|
|
|
let destination = exclusion.stopBefore(new ArenaLocation(target.x, target.y), ship.location);
|
|
|
|
target = Target.newFromLocation(destination.x, destination.y);
|
2017-06-19 23:04:27 +00:00
|
|
|
return target;
|
|
|
|
}
|
|
|
|
|
2017-06-21 23:32:18 +00:00
|
|
|
/**
|
|
|
|
* Apply reachable range, with remaining power
|
|
|
|
*/
|
|
|
|
applyReachableRange(ship: Ship, target: Target, margin = 0.1): Target {
|
|
|
|
let max_distance = this.getRangeRadius(ship);
|
|
|
|
max_distance = Math.max(0, max_distance - margin);
|
|
|
|
return target.constraintInRange(ship.arena_x, ship.arena_y, max_distance);
|
|
|
|
}
|
2017-06-19 23:04:27 +00:00
|
|
|
|
2017-07-31 22:49:00 +00:00
|
|
|
checkLocationTarget(ship: Ship, target: Target): Target | null {
|
2017-06-21 23:32:18 +00:00
|
|
|
target = this.applyReachableRange(ship, target);
|
2017-06-19 23:04:27 +00:00
|
|
|
target = this.applyExclusion(ship, target);
|
2017-07-31 22:49:00 +00:00
|
|
|
return target.getDistanceTo(ship.location) > 0 ? target : null;
|
2014-12-31 00:00:00 +00:00
|
|
|
}
|
2015-01-02 00:00:00 +00:00
|
|
|
|
2017-03-07 19:27:46 +00:00
|
|
|
protected customApply(ship: Ship, target: Target) {
|
2017-08-17 17:51:22 +00:00
|
|
|
ship.moveTo(target.x, target.y, this.equipment);
|
2015-01-02 00:00:00 +00:00
|
|
|
}
|
2017-04-18 22:55:59 +00:00
|
|
|
|
|
|
|
getEffectsDescription(): string {
|
2017-09-10 20:20:29 +00:00
|
|
|
let range = this.getDistanceRangeByActionPoint();
|
|
|
|
let rangeinfo = (range.max == range.min) ? `${range.min}` : `${range.min}-${range.max}`;
|
|
|
|
let result = `Move: ${rangeinfo}km per power point`;
|
2017-08-17 22:53:21 +00:00
|
|
|
|
|
|
|
if (this.safety_distance) {
|
2017-09-10 20:20:29 +00:00
|
|
|
result += ` (safety: ${this.safety_distance}km)`;
|
2017-08-17 22:53:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
2017-04-18 22:55:59 +00:00
|
|
|
}
|
2014-12-31 00:00:00 +00:00
|
|
|
}
|
2015-01-07 00:00:00 +00:00
|
|
|
}
|