2017-09-24 22:23:22 +00:00
|
|
|
module TK.SpaceTac {
|
2017-09-19 15:09:06 +00:00
|
|
|
/**
|
|
|
|
* Targetting mode for an action.
|
|
|
|
*
|
|
|
|
* This is a hint as to what type of target is required for this action.
|
|
|
|
*/
|
|
|
|
export enum ActionTargettingMode {
|
|
|
|
// Apply immediately on the ship owning the action, without confirmation
|
|
|
|
SELF,
|
|
|
|
// Apply on the ship owning the action, with a confirmation
|
|
|
|
SELF_CONFIRM,
|
|
|
|
// Apply on one selected ship
|
|
|
|
SHIP,
|
|
|
|
// Apply on a space area
|
|
|
|
SPACE
|
|
|
|
}
|
|
|
|
|
2017-07-24 22:02:43 +00:00
|
|
|
/**
|
|
|
|
* Base class for a battle action.
|
|
|
|
*
|
|
|
|
* An action should be the only way to modify a battle state.
|
|
|
|
*/
|
2017-02-07 18:54:53 +00:00
|
|
|
export class BaseAction {
|
2014-12-31 00:00:00 +00:00
|
|
|
// Identifier code for the type of action
|
2017-05-16 23:12:05 +00:00
|
|
|
code: string
|
2014-12-31 00:00:00 +00:00
|
|
|
|
2017-01-08 22:42:53 +00:00
|
|
|
// Human-readable name
|
2017-05-16 23:12:05 +00:00
|
|
|
name: string
|
2017-01-08 22:42:53 +00:00
|
|
|
|
2015-01-28 00:00:00 +00:00
|
|
|
// Equipment that triggers this action
|
2017-05-16 23:12:05 +00:00
|
|
|
equipment: Equipment | null
|
2015-01-28 00:00:00 +00:00
|
|
|
|
2015-01-06 00:00:00 +00:00
|
|
|
// Create the action
|
2017-09-19 15:09:06 +00:00
|
|
|
constructor(code: string, name: string, equipment: Equipment | null = null) {
|
2014-12-31 00:00:00 +00:00
|
|
|
this.code = code;
|
2017-01-08 22:42:53 +00:00
|
|
|
this.name = name;
|
2015-01-28 00:00:00 +00:00
|
|
|
this.equipment = equipment;
|
2014-12-31 00:00:00 +00:00
|
|
|
}
|
|
|
|
|
2017-05-22 16:29:04 +00:00
|
|
|
/**
|
2017-09-19 15:09:06 +00:00
|
|
|
* Get the relevent cooldown for this action
|
2017-05-22 16:29:04 +00:00
|
|
|
*/
|
2017-09-19 15:09:06 +00:00
|
|
|
get cooldown(): Cooldown {
|
|
|
|
return this.equipment ? this.equipment.cooldown : new Cooldown();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get the targetting mode
|
|
|
|
*/
|
|
|
|
getTargettingMode(ship: Ship): ActionTargettingMode {
|
|
|
|
if (this.getBlastRadius(ship)) {
|
|
|
|
return ActionTargettingMode.SPACE;
|
|
|
|
} else if (this.getRangeRadius(ship)) {
|
|
|
|
return ActionTargettingMode.SHIP;
|
2017-05-22 16:29:04 +00:00
|
|
|
} else {
|
2017-09-19 15:09:06 +00:00
|
|
|
return ActionTargettingMode.SELF_CONFIRM;
|
2017-05-22 16:29:04 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-09-19 15:09:06 +00:00
|
|
|
/**
|
|
|
|
* Get a default target for this action
|
|
|
|
*/
|
|
|
|
getDefaultTarget(ship: Ship): Target {
|
|
|
|
return Target.newFromShip(ship);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get the number of turns this action is unavailable, because of overheating
|
|
|
|
*/
|
|
|
|
getCooldownDuration(estimated = false): number {
|
|
|
|
let cooldown = this.cooldown;
|
|
|
|
return estimated ? this.cooldown.cooling : this.cooldown.heat;
|
|
|
|
}
|
|
|
|
|
2017-05-22 16:29:04 +00:00
|
|
|
/**
|
|
|
|
* Get the number of remaining uses before overheat, infinity if there is no overheat
|
|
|
|
*/
|
|
|
|
getUsesBeforeOverheat(): number {
|
2017-09-19 15:09:06 +00:00
|
|
|
return this.cooldown.getRemainingUses();
|
2017-05-22 16:29:04 +00:00
|
|
|
}
|
|
|
|
|
2017-03-07 19:27:46 +00:00
|
|
|
/**
|
|
|
|
* 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
|
|
|
|
*/
|
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 battle = ship.getBattle();
|
2015-02-26 00:00:00 +00:00
|
|
|
if (battle && battle.playing_ship !== ship) {
|
|
|
|
// Ship is not playing
|
2017-03-07 19:27:46 +00:00
|
|
|
return "ship not playing";
|
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-04-18 19:51:23 +00:00
|
|
|
var ap_usage = this.getActionPointsUsage(ship, null);
|
2017-05-16 23:12:05 +00:00
|
|
|
if (remaining_ap < ap_usage) {
|
2017-03-07 19:27:46 +00:00
|
|
|
return "not enough power";
|
|
|
|
}
|
2017-05-16 23:12:05 +00:00
|
|
|
|
|
|
|
// Check cooldown
|
2017-09-19 15:09:06 +00:00
|
|
|
if (!this.cooldown.canUse()) {
|
2017-05-16 23:12:05 +00:00
|
|
|
return "overheated";
|
|
|
|
}
|
|
|
|
|
|
|
|
return null;
|
2014-12-31 00:00:00 +00:00
|
|
|
}
|
|
|
|
|
2015-02-26 00:00:00 +00:00
|
|
|
// Get the number of action points the action applied to a target would use
|
2017-03-09 17:11:00 +00:00
|
|
|
getActionPointsUsage(ship: Ship, target: Target | null): number {
|
2017-04-18 19:51:23 +00:00
|
|
|
return 0;
|
2015-02-26 00:00:00 +00:00
|
|
|
}
|
|
|
|
|
2015-03-03 00:00:00 +00:00
|
|
|
// Get the range of this action
|
|
|
|
getRangeRadius(ship: Ship): number {
|
2017-04-18 19:51:23 +00:00
|
|
|
return 0;
|
2015-03-03 00:00:00 +00:00
|
|
|
}
|
|
|
|
|
2015-03-06 00:00:00 +00:00
|
|
|
// Get the effect area radius of this action
|
|
|
|
getBlastRadius(ship: Ship): number {
|
2017-04-18 19:51:23 +00:00
|
|
|
return 0;
|
2015-03-06 00:00:00 +00:00
|
|
|
}
|
|
|
|
|
2017-09-19 15:09:06 +00:00
|
|
|
/**
|
|
|
|
* Check if a target is suitable for this action
|
|
|
|
*
|
|
|
|
* Will call checkLocationTarget or checkShipTarget by default
|
|
|
|
*/
|
|
|
|
checkTarget(ship: Ship, target: Target): Target | null {
|
2017-03-07 19:27:46 +00:00
|
|
|
if (this.checkCannotBeApplied(ship)) {
|
2014-12-31 00:00:00 +00:00
|
|
|
return null;
|
2017-09-19 15:09:06 +00:00
|
|
|
} else {
|
2015-01-06 00:00:00 +00:00
|
|
|
if (target.ship) {
|
2017-03-07 19:27:46 +00:00
|
|
|
return this.checkShipTarget(ship, target);
|
2015-01-06 00:00:00 +00:00
|
|
|
} else {
|
2017-03-07 19:27:46 +00:00
|
|
|
return this.checkLocationTarget(ship, target);
|
2015-01-06 00:00:00 +00:00
|
|
|
}
|
2014-12-31 00:00:00 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-09-19 15:09:06 +00:00
|
|
|
// Method to reimplement to check if a space target is suitable
|
2014-12-31 00:00:00 +00:00
|
|
|
// Must return null if the target can't be applied, an altered target, or the original target
|
2017-09-19 15:09:06 +00:00
|
|
|
protected checkLocationTarget(ship: Ship, target: Target): Target | null {
|
2014-12-31 00:00:00 +00:00
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
2017-09-19 15:09:06 +00:00
|
|
|
// Method to reimplement to check if a ship target is suitable
|
2014-12-31 00:00:00 +00:00
|
|
|
// Must return null if the target can't be applied, an altered target, or the original target
|
2017-09-19 15:09:06 +00:00
|
|
|
protected checkShipTarget(ship: Ship, target: Target): Target | null {
|
2014-12-31 00:00:00 +00:00
|
|
|
return null;
|
|
|
|
}
|
2015-01-02 00:00:00 +00:00
|
|
|
|
2017-09-19 15:09:06 +00:00
|
|
|
/**
|
|
|
|
* Apply an action, returning true if it was successful
|
|
|
|
*/
|
|
|
|
apply(ship: Ship, target = this.getDefaultTarget(ship)): boolean {
|
2017-03-07 19:27:46 +00:00
|
|
|
let reject = this.checkCannotBeApplied(ship);
|
|
|
|
if (reject == null) {
|
2017-03-08 23:18:40 +00:00
|
|
|
let checked_target = this.checkTarget(ship, target);
|
2017-09-19 15:09:06 +00:00
|
|
|
if (!checked_target) {
|
2017-03-08 23:18:40 +00:00
|
|
|
console.warn("Action rejected - invalid target", ship, this, target);
|
2015-01-06 00:00:00 +00:00
|
|
|
return false;
|
|
|
|
}
|
2015-02-26 00:00:00 +00:00
|
|
|
|
2017-03-08 23:18:40 +00:00
|
|
|
let cost = this.getActionPointsUsage(ship, checked_target);
|
2017-02-19 21:52:11 +00:00
|
|
|
if (!ship.useActionPoints(cost)) {
|
2017-03-08 23:18:40 +00:00
|
|
|
console.warn("Action rejected - not enough power", ship, this, checked_target);
|
2015-02-26 00:00:00 +00:00
|
|
|
return false;
|
|
|
|
}
|
2017-02-19 21:52:11 +00:00
|
|
|
|
2017-04-24 17:59:16 +00:00
|
|
|
if (this.equipment) {
|
|
|
|
this.equipment.addWear(1);
|
|
|
|
ship.listEquipment(SlotType.Power).forEach(equipment => equipment.addWear(1));
|
|
|
|
}
|
|
|
|
|
2017-09-19 15:09:06 +00:00
|
|
|
this.cooldown.use();
|
|
|
|
|
2017-07-24 22:02:43 +00:00
|
|
|
let battle = ship.getBattle();
|
|
|
|
if (battle) {
|
2017-09-14 21:56:28 +00:00
|
|
|
battle.log.add(new ActionAppliedEvent(ship, this, checked_target, cost));
|
2017-07-24 22:02:43 +00:00
|
|
|
}
|
|
|
|
|
2017-03-08 23:18:40 +00:00
|
|
|
this.customApply(ship, checked_target);
|
2017-02-19 21:52:11 +00:00
|
|
|
return true;
|
2015-01-06 00:00:00 +00:00
|
|
|
} else {
|
2017-03-07 19:27:46 +00:00
|
|
|
console.warn(`Action rejected - ${reject}`, ship, this, target);
|
2015-01-02 00:00:00 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-09-19 15:09:06 +00:00
|
|
|
/**
|
|
|
|
* Method to reimplement to apply the action
|
|
|
|
*/
|
|
|
|
protected customApply(ship: Ship, target: Target): void {
|
2015-01-02 00:00:00 +00:00
|
|
|
}
|
2017-04-18 19:51:23 +00:00
|
|
|
|
|
|
|
/**
|
2017-04-18 22:55:59 +00:00
|
|
|
* Get textual description of effects
|
2017-04-18 19:51:23 +00:00
|
|
|
*/
|
2017-04-18 22:55:59 +00:00
|
|
|
getEffectsDescription(): string {
|
|
|
|
return "";
|
2017-04-18 19:51:23 +00:00
|
|
|
}
|
2014-12-31 00:00:00 +00:00
|
|
|
}
|
2015-01-07 00:00:00 +00:00
|
|
|
}
|