2017-02-07 19:15:21 +00:00
|
|
|
/// <reference path="ShipAttribute.ts"/>
|
|
|
|
/// <reference path="ShipValue.ts"/>
|
|
|
|
|
2017-01-26 23:52:45 +00:00
|
|
|
module TS.SpaceTac.Game {
|
2017-02-07 19:15:21 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Set of ShipAttribute for a ship
|
|
|
|
*/
|
|
|
|
export class ShipAttributes {
|
|
|
|
// Attribute controlling the play order
|
|
|
|
initiative = new ShipAttribute("initiative")
|
|
|
|
// Maximal hull value
|
|
|
|
hull_capacity = new ShipAttribute("hull capacity")
|
|
|
|
// Maximal shield value
|
|
|
|
shield_capacity = new ShipAttribute("shield capacity")
|
|
|
|
// Maximal power value
|
|
|
|
power_capacity = new ShipAttribute("power capacity")
|
|
|
|
// Initial power value at the start of a battle
|
|
|
|
power_initial = new ShipAttribute("initial power")
|
|
|
|
// Power value recovered each turn
|
|
|
|
power_recovery = new ShipAttribute("power recovery")
|
|
|
|
// Skills
|
|
|
|
skill_material = new ShipAttribute("material skill")
|
|
|
|
skill_energy = new ShipAttribute("energy skill")
|
|
|
|
skill_electronics = new ShipAttribute("electronics skill")
|
|
|
|
skill_human = new ShipAttribute("human skill")
|
|
|
|
skill_time = new ShipAttribute("time skill")
|
|
|
|
skill_gravity = new ShipAttribute("gravity skill")
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Set of ShipValue for a ship
|
|
|
|
*/
|
|
|
|
export class ShipValues {
|
|
|
|
hull = new ShipValue("hull")
|
|
|
|
shield = new ShipValue("shield")
|
|
|
|
power = new ShipValue("power")
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Static attributes and values object for name queries
|
|
|
|
*/
|
|
|
|
export const SHIP_ATTRIBUTES = new ShipAttributes();
|
|
|
|
export const SHIP_VALUES = new ShipValues();
|
|
|
|
|
|
|
|
/**
|
|
|
|
* A single ship in a fleet
|
|
|
|
*/
|
2017-02-07 18:54:53 +00:00
|
|
|
export class Ship {
|
2014-12-29 00:00:00 +00:00
|
|
|
// Fleet this ship is a member of
|
2017-02-07 19:15:21 +00:00
|
|
|
fleet: Fleet
|
2014-12-29 00:00:00 +00:00
|
|
|
|
2015-03-12 00:00:00 +00:00
|
|
|
// Level of this ship
|
2017-02-07 19:15:21 +00:00
|
|
|
level: number
|
2015-03-12 00:00:00 +00:00
|
|
|
|
2014-12-30 00:00:00 +00:00
|
|
|
// Name of the ship
|
2017-02-07 19:15:21 +00:00
|
|
|
name: string
|
2014-12-30 00:00:00 +00:00
|
|
|
|
2015-05-05 19:49:33 +00:00
|
|
|
// Code of the ShipModel used to create it
|
2017-02-07 19:15:21 +00:00
|
|
|
model: string
|
2015-05-05 19:49:33 +00:00
|
|
|
|
2015-02-06 00:00:00 +00:00
|
|
|
// Flag indicating if the ship is alive
|
2017-02-07 19:15:21 +00:00
|
|
|
alive: boolean
|
2015-02-06 00:00:00 +00:00
|
|
|
|
2014-12-30 00:00:00 +00:00
|
|
|
// Position in the arena
|
2017-02-07 19:15:21 +00:00
|
|
|
arena_x: number
|
|
|
|
arena_y: number
|
2014-12-30 00:00:00 +00:00
|
|
|
|
|
|
|
// Facing direction in the arena
|
2017-02-07 19:15:21 +00:00
|
|
|
arena_angle: number
|
2015-01-28 00:00:00 +00:00
|
|
|
|
2017-01-23 23:07:54 +00:00
|
|
|
// Sticky effects that applies a given number of times
|
2017-02-07 19:15:21 +00:00
|
|
|
sticky_effects: StickyEffect[]
|
2015-02-06 00:00:00 +00:00
|
|
|
|
2015-01-14 00:00:00 +00:00
|
|
|
// List of slots, able to contain equipment
|
2017-02-07 19:15:21 +00:00
|
|
|
slots: Slot[]
|
|
|
|
|
|
|
|
// Ship attributes
|
|
|
|
attributes = new ShipAttributes()
|
2015-01-14 00:00:00 +00:00
|
|
|
|
2017-02-07 19:15:21 +00:00
|
|
|
// Ship values
|
|
|
|
values = new ShipValues()
|
2015-01-22 00:00:00 +00:00
|
|
|
|
2017-01-20 00:02:18 +00:00
|
|
|
// Boolean set to true if the ship is currently playing its turn
|
2017-02-07 19:15:21 +00:00
|
|
|
playing = false
|
|
|
|
|
|
|
|
// Priority in play_order
|
|
|
|
play_priority = 0;
|
2017-01-20 00:02:18 +00:00
|
|
|
|
2014-12-30 00:00:00 +00:00
|
|
|
// Create a new ship inside a fleet
|
2015-01-14 00:00:00 +00:00
|
|
|
constructor(fleet: Fleet = null, name: string = null) {
|
2015-01-29 00:00:00 +00:00
|
|
|
this.fleet = fleet || new Fleet();
|
2015-03-12 00:00:00 +00:00
|
|
|
this.level = 1;
|
2014-12-30 00:00:00 +00:00
|
|
|
this.name = name;
|
2015-05-05 19:49:33 +00:00
|
|
|
this.model = "default";
|
2015-02-06 00:00:00 +00:00
|
|
|
this.alive = true;
|
2017-01-23 23:07:54 +00:00
|
|
|
this.sticky_effects = [];
|
2015-01-14 00:00:00 +00:00
|
|
|
this.slots = [];
|
2014-12-30 00:00:00 +00:00
|
|
|
|
2017-02-07 19:15:21 +00:00
|
|
|
this.attributes.initiative.set(1); // TODO Should not be needed
|
|
|
|
|
2015-01-28 00:00:00 +00:00
|
|
|
this.arena_x = 0;
|
|
|
|
this.arena_y = 0;
|
2015-01-29 00:00:00 +00:00
|
|
|
this.arena_angle = 0;
|
2015-01-28 00:00:00 +00:00
|
|
|
|
2014-12-31 00:00:00 +00:00
|
|
|
if (fleet) {
|
|
|
|
fleet.addShip(this);
|
|
|
|
}
|
2014-12-30 00:00:00 +00:00
|
|
|
}
|
|
|
|
|
2015-02-06 00:00:00 +00:00
|
|
|
// Returns true if the ship is able to play
|
|
|
|
// If *check_ap* is true, ap_current=0 will make this function return false
|
|
|
|
isAbleToPlay(check_ap: boolean = true): boolean {
|
2017-02-07 19:15:21 +00:00
|
|
|
var ap_checked = !check_ap || this.values.power.get() > 0;
|
2015-02-06 00:00:00 +00:00
|
|
|
return this.alive && ap_checked;
|
|
|
|
}
|
|
|
|
|
2014-12-30 00:00:00 +00:00
|
|
|
// Set position in the arena
|
2014-12-31 00:00:00 +00:00
|
|
|
// This does not consumes action points
|
2014-12-30 00:00:00 +00:00
|
|
|
setArenaPosition(x: number, y: number) {
|
|
|
|
this.arena_x = x;
|
|
|
|
this.arena_y = y;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Set facing angle in the arena
|
|
|
|
setArenaFacingAngle(angle: number) {
|
|
|
|
this.arena_angle = angle;
|
|
|
|
}
|
|
|
|
|
2014-12-30 00:00:00 +00:00
|
|
|
// String repr
|
|
|
|
jasmineToString(): string {
|
|
|
|
return "Ship " + this.name;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Make an initiative throw, to resolve play order in a battle
|
|
|
|
throwInitiative(gen: RandomGenerator): void {
|
2017-02-07 19:15:21 +00:00
|
|
|
this.play_priority = gen.throw(this.attributes.initiative.get());
|
2014-12-30 00:00:00 +00:00
|
|
|
}
|
2014-12-30 00:00:00 +00:00
|
|
|
|
|
|
|
// Return the player owning this ship
|
|
|
|
getPlayer(): Player {
|
2015-01-19 00:00:00 +00:00
|
|
|
if (this.fleet) {
|
|
|
|
return this.fleet.player;
|
|
|
|
} else {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// get the current battle this ship is engaged in
|
|
|
|
getBattle(): Battle {
|
|
|
|
if (this.fleet) {
|
|
|
|
return this.fleet.battle;
|
|
|
|
} else {
|
|
|
|
return null;
|
|
|
|
}
|
2014-12-30 00:00:00 +00:00
|
|
|
}
|
2014-12-31 00:00:00 +00:00
|
|
|
|
2014-12-31 00:00:00 +00:00
|
|
|
// Get the list of actions available
|
2015-01-16 00:00:00 +00:00
|
|
|
// This list does not filter out actions unavailable due to insufficient AP, it only filters out
|
2014-12-31 00:00:00 +00:00
|
|
|
// actions that are not allowed/available at all on the ship
|
2014-12-31 00:00:00 +00:00
|
|
|
getAvailableActions(): BaseAction[] {
|
2015-01-16 00:00:00 +00:00
|
|
|
var actions: BaseAction[] = [];
|
|
|
|
|
|
|
|
this.slots.forEach((slot: Slot) => {
|
|
|
|
if (slot.attached && slot.attached.action) {
|
|
|
|
actions.push(slot.attached.action);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
actions.push(new EndTurnAction());
|
|
|
|
return actions;
|
2014-12-31 00:00:00 +00:00
|
|
|
}
|
|
|
|
|
2015-02-06 00:00:00 +00:00
|
|
|
// Add an event to the battle log, if any
|
|
|
|
addBattleEvent(event: BaseLogEvent): void {
|
|
|
|
var battle = this.getBattle();
|
|
|
|
if (battle && battle.log) {
|
|
|
|
battle.log.add(event);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-02-07 00:08:07 +00:00
|
|
|
/**
|
2017-02-07 19:15:21 +00:00
|
|
|
* Get a ship value
|
|
|
|
*/
|
|
|
|
getValue(name: keyof ShipValues): number {
|
|
|
|
return this.values[name].get();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Set a ship value
|
2017-02-07 00:08:07 +00:00
|
|
|
*
|
|
|
|
* If *offset* is true, the value will be added to current value.
|
|
|
|
* If *log* is true, an attribute event will be added to the battle log
|
|
|
|
*
|
2017-02-07 19:15:21 +00:00
|
|
|
* Returns true if the value changed.
|
2017-02-07 00:08:07 +00:00
|
|
|
*/
|
2017-02-07 19:15:21 +00:00
|
|
|
setValue(name: keyof ShipValues, value: number, offset = false, log = true): boolean {
|
|
|
|
let changed: boolean;
|
|
|
|
let val = this.values[name];
|
2015-01-19 00:00:00 +00:00
|
|
|
|
|
|
|
if (offset) {
|
2017-02-07 19:15:21 +00:00
|
|
|
changed = val.add(value);
|
2015-01-19 00:00:00 +00:00
|
|
|
} else {
|
2017-02-07 19:15:21 +00:00
|
|
|
changed = val.set(value);
|
2015-01-19 00:00:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (changed && log) {
|
2017-02-07 19:15:21 +00:00
|
|
|
this.addBattleEvent(new ValueChangeEvent(this, val));
|
|
|
|
}
|
|
|
|
|
|
|
|
return changed;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get a ship attribute's current value
|
|
|
|
*/
|
|
|
|
getAttribute(name: keyof ShipAttributes): number {
|
|
|
|
return this.attributes[name].get();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Set a ship attribute
|
|
|
|
*
|
|
|
|
* If *log* is true, an attribute event will be added to the battle log
|
|
|
|
*
|
|
|
|
* Returns true if the value changed.
|
|
|
|
*/
|
|
|
|
setAttribute(name: keyof ShipAttributes, value: number, log = true): boolean {
|
|
|
|
let changed: boolean;
|
|
|
|
let attr = this.attributes[name];
|
|
|
|
|
|
|
|
changed = attr.set(value);
|
|
|
|
|
|
|
|
// TODO more generic
|
|
|
|
if (name == "power_capacity") {
|
|
|
|
this.values.power.setMaximal(attr.get());
|
|
|
|
} else if (name == "shield_capacity") {
|
|
|
|
this.values.shield.setMaximal(attr.get());
|
|
|
|
} else if (name == "hull_capacity") {
|
|
|
|
this.values.hull.setMaximal(attr.get());
|
|
|
|
}
|
|
|
|
|
|
|
|
if (changed && log) {
|
|
|
|
this.addBattleEvent(new ValueChangeEvent(this, attr));
|
2015-01-19 00:00:00 +00:00
|
|
|
}
|
2017-02-07 00:08:07 +00:00
|
|
|
|
|
|
|
return changed;
|
2015-01-19 00:00:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Initialize the action points counter
|
|
|
|
// This should be called once at the start of a battle
|
|
|
|
// If no value is provided, the attribute ap_initial will be used
|
|
|
|
initializeActionPoints(value: number = null): void {
|
|
|
|
if (value === null) {
|
2017-02-07 19:15:21 +00:00
|
|
|
value = this.attributes.power_initial.get();
|
2015-01-19 00:00:00 +00:00
|
|
|
}
|
2017-02-07 19:15:21 +00:00
|
|
|
this.setValue("power", value);
|
2015-01-19 00:00:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Recover action points
|
2017-01-12 00:36:34 +00:00
|
|
|
// This should be called once at the end of a turn
|
2015-01-19 00:00:00 +00:00
|
|
|
// If no value is provided, the current attribute ap_recovery will be used
|
|
|
|
recoverActionPoints(value: number = null): void {
|
|
|
|
if (value === null) {
|
2017-02-07 19:15:21 +00:00
|
|
|
value = this.attributes.power_recovery.get();
|
2015-01-19 00:00:00 +00:00
|
|
|
}
|
2017-02-07 19:15:21 +00:00
|
|
|
this.setValue("power", value, true);
|
2015-01-19 00:00:00 +00:00
|
|
|
}
|
|
|
|
|
2014-12-31 00:00:00 +00:00
|
|
|
// Consumes action points
|
2015-01-19 00:00:00 +00:00
|
|
|
useActionPoints(value: number): void {
|
2017-02-07 19:15:21 +00:00
|
|
|
this.setValue("power", -value, true);
|
2015-01-19 00:00:00 +00:00
|
|
|
}
|
2014-12-31 00:00:00 +00:00
|
|
|
|
2017-01-12 00:36:34 +00:00
|
|
|
// Method called at the start of battle
|
|
|
|
startBattle() {
|
|
|
|
this.updateAttributes();
|
|
|
|
this.restoreHealth();
|
|
|
|
this.initializeActionPoints();
|
|
|
|
}
|
|
|
|
|
2017-01-24 00:14:04 +00:00
|
|
|
|
2015-01-19 00:00:00 +00:00
|
|
|
// Method called at the start of this ship turn
|
2017-01-12 00:36:34 +00:00
|
|
|
startTurn(): void {
|
2017-01-20 00:02:18 +00:00
|
|
|
if (this.playing) {
|
|
|
|
console.error("startTurn called twice", this);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
this.playing = true;
|
|
|
|
|
2015-01-22 00:00:00 +00:00
|
|
|
// Recompute attributes
|
|
|
|
this.updateAttributes();
|
|
|
|
|
2015-02-27 00:00:00 +00:00
|
|
|
// Apply sticky effects
|
2017-01-24 00:14:04 +00:00
|
|
|
this.sticky_effects.forEach(effect => effect.startTurn(this));
|
|
|
|
this.cleanStickyEffects();
|
2015-02-27 00:00:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Method called at the end of this ship turn
|
|
|
|
endTurn(): void {
|
2017-01-20 00:02:18 +00:00
|
|
|
if (!this.playing) {
|
|
|
|
console.error("endTurn called before startTurn", this);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
this.playing = false;
|
|
|
|
|
2017-01-12 00:36:34 +00:00
|
|
|
// Recover action points for next turn
|
2017-02-07 19:15:21 +00:00
|
|
|
this.updateAttributes();
|
2017-01-12 00:36:34 +00:00
|
|
|
this.recoverActionPoints();
|
|
|
|
|
2017-01-24 00:14:04 +00:00
|
|
|
// Apply sticky effects
|
|
|
|
this.sticky_effects.forEach(effect => effect.endTurn(this));
|
|
|
|
this.cleanStickyEffects();
|
2015-02-27 00:00:00 +00:00
|
|
|
}
|
|
|
|
|
2017-01-24 00:14:04 +00:00
|
|
|
/**
|
|
|
|
* Register a sticky effect
|
|
|
|
*
|
|
|
|
* Pay attention to pass a copy, not the original equipment effect, because it will be modified
|
|
|
|
*/
|
|
|
|
addStickyEffect(effect: StickyEffect, log = true): void {
|
|
|
|
this.sticky_effects.push(effect);
|
2015-02-27 00:00:00 +00:00
|
|
|
if (log) {
|
|
|
|
this.addBattleEvent(new EffectAddedEvent(this, effect));
|
|
|
|
}
|
2014-12-31 00:00:00 +00:00
|
|
|
}
|
|
|
|
|
2017-01-24 00:14:04 +00:00
|
|
|
/**
|
|
|
|
* Clean sticky effects that are no longer active
|
|
|
|
*/
|
|
|
|
cleanStickyEffects() {
|
2017-01-27 00:07:06 +00:00
|
|
|
let [active, ended] = binpartition(this.sticky_effects, effect => effect.duration > 0);
|
2017-01-24 00:14:04 +00:00
|
|
|
this.sticky_effects = active;
|
|
|
|
ended.forEach(effect => this.addBattleEvent(new EffectRemovedEvent(this, effect)));
|
|
|
|
}
|
|
|
|
|
2017-02-06 21:46:55 +00:00
|
|
|
/**
|
|
|
|
* Check if the ship is inside a given circular area
|
|
|
|
*/
|
|
|
|
isInCircle(x: number, y: number, radius: number): boolean {
|
|
|
|
let dx = this.arena_x - x;
|
|
|
|
let dy = this.arena_y - y;
|
|
|
|
let distance = Math.sqrt(dx * dx + dy * dy);
|
|
|
|
return distance <= radius;
|
|
|
|
}
|
|
|
|
|
2015-01-29 00:00:00 +00:00
|
|
|
// Move toward a location
|
|
|
|
// This does not check or consume action points
|
|
|
|
moveTo(x: number, y: number, log: boolean = true): void {
|
2015-01-26 00:00:00 +00:00
|
|
|
var angle = Math.atan2(y - this.arena_y, x - this.arena_x);
|
|
|
|
this.setArenaFacingAngle(angle);
|
2015-01-29 00:00:00 +00:00
|
|
|
|
|
|
|
this.setArenaPosition(x, y);
|
|
|
|
|
2015-02-06 00:00:00 +00:00
|
|
|
if (log) {
|
|
|
|
this.addBattleEvent(new MoveEvent(this, x, y));
|
2015-01-29 00:00:00 +00:00
|
|
|
}
|
2014-12-31 00:00:00 +00:00
|
|
|
}
|
2015-01-14 00:00:00 +00:00
|
|
|
|
2015-02-09 00:00:00 +00:00
|
|
|
// Set the death status on this ship
|
|
|
|
setDead(log: boolean = true): void {
|
|
|
|
this.alive = false;
|
|
|
|
if (log) {
|
|
|
|
this.addBattleEvent(new DeathEvent(this));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-02-03 00:00:00 +00:00
|
|
|
// Apply damages to hull and/or shield
|
|
|
|
addDamage(hull: number, shield: number, log: boolean = true): void {
|
2017-02-07 19:15:21 +00:00
|
|
|
this.setValue("shield", -shield, true, log);
|
|
|
|
this.setValue("hull", -hull, true, log);
|
2015-02-03 00:00:00 +00:00
|
|
|
|
2015-02-06 00:00:00 +00:00
|
|
|
if (log) {
|
|
|
|
this.addBattleEvent(new DamageEvent(this, hull, shield));
|
|
|
|
}
|
|
|
|
|
2017-02-07 19:15:21 +00:00
|
|
|
if (this.values.hull.get() === 0) {
|
2015-02-06 00:00:00 +00:00
|
|
|
// Ship is dead
|
2015-02-09 00:00:00 +00:00
|
|
|
this.setDead(log);
|
2015-02-03 00:00:00 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-01-14 00:00:00 +00:00
|
|
|
// Add an empty equipment slot of the given type
|
|
|
|
addSlot(type: SlotType): Slot {
|
|
|
|
var result = new Slot(this, type);
|
|
|
|
this.slots.push(result);
|
|
|
|
return result;
|
2015-02-17 00:00:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// List all attached equipments of a given type (all types if null)
|
|
|
|
listEquipment(slottype: SlotType = null): Equipment[] {
|
|
|
|
var result: Equipment[] = [];
|
|
|
|
|
|
|
|
this.slots.forEach((slot: Slot) => {
|
|
|
|
if (slot.type === slottype && slot.attached) {
|
|
|
|
result.push(slot.attached);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
return result;
|
2015-01-14 00:00:00 +00:00
|
|
|
}
|
2015-01-22 00:00:00 +00:00
|
|
|
|
2015-02-13 00:00:00 +00:00
|
|
|
// Get the number of attached equipments
|
|
|
|
getEquipmentCount(): number {
|
|
|
|
var result = 0;
|
|
|
|
this.slots.forEach((slot: Slot) => {
|
|
|
|
if (slot.attached) {
|
|
|
|
result++;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get a random attached equipment, null if no equipment is attached
|
|
|
|
getRandomEquipment(random: RandomGenerator = new RandomGenerator()): Equipment {
|
|
|
|
var count = this.getEquipmentCount();
|
|
|
|
if (count === 0) {
|
|
|
|
return null;
|
|
|
|
} else {
|
|
|
|
var picked = random.throwInt(0, count - 1);
|
|
|
|
var result: Equipment = null;
|
|
|
|
var index = 0;
|
|
|
|
this.slots.forEach((slot: Slot) => {
|
|
|
|
if (slot.attached) {
|
|
|
|
if (index === picked) {
|
|
|
|
result = slot.attached;
|
|
|
|
}
|
|
|
|
index++;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-01-22 00:00:00 +00:00
|
|
|
// Update attributes, taking into account attached equipment and active effects
|
|
|
|
updateAttributes(): void {
|
2017-02-07 19:15:21 +00:00
|
|
|
// Sum all attribute effects
|
|
|
|
var new_attrs = new ShipAttributes();
|
|
|
|
this.collectEffects("attr").forEach((effect: AttributeEffect) => {
|
|
|
|
new_attrs[effect.attrcode].add(effect.value);
|
|
|
|
});
|
2015-01-22 00:00:00 +00:00
|
|
|
|
2017-02-07 19:15:21 +00:00
|
|
|
// Apply limit attributes
|
|
|
|
this.collectEffects("attrlimit").forEach((effect: AttributeLimitEffect) => {
|
|
|
|
new_attrs[effect.attrcode].setMaximal(effect.value);
|
2015-01-22 00:00:00 +00:00
|
|
|
});
|
2017-02-07 19:15:21 +00:00
|
|
|
|
|
|
|
// TODO better typing
|
|
|
|
iteritems(<any>new_attrs, (key, value) => {
|
|
|
|
this.setAttribute(<keyof ShipAttributes>key, (<ShipAttribute>value).get());
|
2015-01-22 00:00:00 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2015-01-28 00:00:00 +00:00
|
|
|
// Fully restore hull and shield
|
|
|
|
restoreHealth(): void {
|
2017-02-07 19:15:21 +00:00
|
|
|
this.values.hull.set(this.attributes.hull_capacity.get());
|
|
|
|
this.values.shield.set(this.attributes.shield_capacity.get());
|
2015-01-28 00:00:00 +00:00
|
|
|
}
|
|
|
|
|
2015-01-22 00:00:00 +00:00
|
|
|
// Collect all effects to apply for updateAttributes
|
2017-02-07 19:15:21 +00:00
|
|
|
private collectEffects(code: string): BaseEffect[] {
|
2015-01-22 00:00:00 +00:00
|
|
|
var result: BaseEffect[] = [];
|
|
|
|
|
2017-02-07 19:15:21 +00:00
|
|
|
this.slots.forEach(slot => {
|
2015-01-22 00:00:00 +00:00
|
|
|
if (slot.attached) {
|
2017-02-07 19:15:21 +00:00
|
|
|
slot.attached.permanent_effects.forEach(effect => {
|
|
|
|
if (effect.code == code) {
|
2015-01-22 00:00:00 +00:00
|
|
|
result.push(effect);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2017-02-07 19:15:21 +00:00
|
|
|
this.sticky_effects.forEach(effect => {
|
|
|
|
if (effect.base.code == code) {
|
|
|
|
result.push(effect.base);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2015-01-22 00:00:00 +00:00
|
|
|
return result;
|
|
|
|
}
|
2014-12-29 00:00:00 +00:00
|
|
|
}
|
2015-01-07 00:00:00 +00:00
|
|
|
}
|