diff --git a/TODO.md b/TODO.md index c97e4ba..772fc12 100644 --- a/TODO.md +++ b/TODO.md @@ -32,6 +32,7 @@ Battle ------ * Fix stats only filling for one fleet +* Display shield (and its (dis)appearance) * Add a voluntary retreat option * Toggle bar/text display in power section of action bar * Show a cooldown indicator on move action icon, if the simulation would cause the engine to overheat @@ -65,7 +66,6 @@ Ships models and actions * Add damage on collisions (when two ships are moved to the same place) * Add hull points to drones and make them take area damage * Allow to customize effects based on whether a target is enemy, allied or self -* Add damage mode: shield / shield or hull / shield then hull / hull * Add pinned effect (cannot be moved) * Add a reflect damage effect * Add untargettable effect (can only be targetted with area effects) diff --git a/src/core/TestTools.ts b/src/core/TestTools.ts index 0167c4b..ee7e7af 100644 --- a/src/core/TestTools.ts +++ b/src/core/TestTools.ts @@ -35,7 +35,7 @@ module TK.SpaceTac { */ static addWeapon(ship: Ship, damage = 100, power_usage = 1, max_distance = 100, blast = 0, angle = 0): TriggerAction { let action = new TriggerAction("Weapon", { - effects: [new DamageEffect(damage)], + effects: [new DamageEffect(damage, DamageEffectMode.SHIELD_THEN_HULL)], power: power_usage, range: max_distance, blast: blast, diff --git a/src/core/effects/DamageEffect.spec.ts b/src/core/effects/DamageEffect.spec.ts index dba29eb..835b885 100644 --- a/src/core/effects/DamageEffect.spec.ts +++ b/src/core/effects/DamageEffect.spec.ts @@ -1,5 +1,26 @@ module TK.SpaceTac.Specs { testing("DamageEffect", test => { + test.case("computes shield and hull damage, according to mode", check => { + let ship = new Ship(); + TestTools.setShipModel(ship, 2, 3); + + check.equals(new DamageEffect(1, DamageEffectMode.HULL_ONLY).getEffectiveDamage(ship), new ShipDamageDiff(ship, 1, 0, 1), "hull 1"); + check.equals(new DamageEffect(3, DamageEffectMode.HULL_ONLY).getEffectiveDamage(ship), new ShipDamageDiff(ship, 2, 0, 3), "hull 3"); + + check.equals(new DamageEffect(1, DamageEffectMode.SHIELD_ONLY).getEffectiveDamage(ship), new ShipDamageDiff(ship, 0, 1, 1), "shield 1"); + check.equals(new DamageEffect(4, DamageEffectMode.SHIELD_ONLY).getEffectiveDamage(ship), new ShipDamageDiff(ship, 0, 3, 4), "shield 4"); + + check.equals(new DamageEffect(1, DamageEffectMode.SHIELD_THEN_HULL).getEffectiveDamage(ship), new ShipDamageDiff(ship, 0, 1, 1), "piercing 1"); + check.equals(new DamageEffect(4, DamageEffectMode.SHIELD_THEN_HULL).getEffectiveDamage(ship), new ShipDamageDiff(ship, 1, 3, 4), "piercing 4"); + check.equals(new DamageEffect(8, DamageEffectMode.SHIELD_THEN_HULL).getEffectiveDamage(ship), new ShipDamageDiff(ship, 2, 3, 8), "piercing 8"); + + check.equals(new DamageEffect(1, DamageEffectMode.SHIELD_OR_HULL).getEffectiveDamage(ship), new ShipDamageDiff(ship, 0, 1, 1), "normal 1"); + check.equals(new DamageEffect(4, DamageEffectMode.SHIELD_OR_HULL).getEffectiveDamage(ship), new ShipDamageDiff(ship, 0, 3, 4), "normal 4"); + ship.setValue("shield", 0); + check.equals(new DamageEffect(1, DamageEffectMode.SHIELD_OR_HULL).getEffectiveDamage(ship), new ShipDamageDiff(ship, 1, 0, 1), "normal no shield 1"); + check.equals(new DamageEffect(4, DamageEffectMode.SHIELD_OR_HULL).getEffectiveDamage(ship), new ShipDamageDiff(ship, 2, 0, 4), "normal no shield 4"); + }); + test.case("applies damage", check => { let battle = new Battle(); let ship = battle.fleets[0].addShip(); @@ -14,21 +35,24 @@ module TK.SpaceTac.Specs { checkValues("initial", 150, 400); - battle.applyDiffs(new DamageEffect(50).getOnDiffs(ship, ship)); + battle.applyDiffs(new DamageEffect(50, DamageEffectMode.SHIELD_THEN_HULL).getOnDiffs(ship, ship)); checkValues("after 50 damage", 150, 350); - battle.applyDiffs(new DamageEffect(250).getOnDiffs(ship, ship)); + battle.applyDiffs(new DamageEffect(250, DamageEffectMode.SHIELD_THEN_HULL).getOnDiffs(ship, ship)); checkValues("after 250 damage", 150, 100); - battle.applyDiffs(new DamageEffect(201).getOnDiffs(ship, ship)); + battle.applyDiffs(new DamageEffect(201, DamageEffectMode.SHIELD_THEN_HULL).getOnDiffs(ship, ship)); checkValues("after 201 damage", 49, 0); - battle.applyDiffs(new DamageEffect(8000).getOnDiffs(ship, ship)); + battle.applyDiffs(new DamageEffect(8000, DamageEffectMode.SHIELD_THEN_HULL).getOnDiffs(ship, ship)); checkValues("after 8000 damage", 0, 0); }); test.case("gets a textual description", check => { check.equals(new DamageEffect(10).getDescription(), "do 10 damage"); + check.equals(new DamageEffect(10, DamageEffectMode.HULL_ONLY).getDescription(), "do 10 hull damage"); + check.equals(new DamageEffect(10, DamageEffectMode.SHIELD_ONLY).getDescription(), "do 10 shield damage"); + check.equals(new DamageEffect(10, DamageEffectMode.SHIELD_THEN_HULL).getDescription(), "do 10 piercing damage"); }); test.case("applies damage modifiers", check => { diff --git a/src/core/effects/DamageEffect.ts b/src/core/effects/DamageEffect.ts index 053e18d..ac4dc0e 100644 --- a/src/core/effects/DamageEffect.ts +++ b/src/core/effects/DamageEffect.ts @@ -1,19 +1,35 @@ /// module TK.SpaceTac { + /** + * Mode for damage effect + */ + export enum DamageEffectMode { + // Apply on shield only + SHIELD_ONLY, + // Apply on shield, then remaining value on hull + SHIELD_THEN_HULL, + // Apply on shield only if up, otherwise on hull + SHIELD_OR_HULL, + // Apply on hull only + HULL_ONLY + } + /** * Apply damage on a ship. - * - * Damage is applied on shield while there is some, then on the hull. */ export class DamageEffect extends BaseEffect { - // Base damage points + // Damage amount value: number - constructor(value = 0) { + // Damage mode + mode: DamageEffectMode + + constructor(value: number, mode = DamageEffectMode.SHIELD_OR_HULL) { super("damage"); this.value = value; + this.mode = mode; } /** @@ -33,18 +49,31 @@ module TK.SpaceTac { * Get the effective damage done to both shield and hull (in this order) */ getEffectiveDamage(ship: Ship): ShipDamageDiff { + let shield = ship.getValue("shield"); + let hull = ship.getValue("hull"); + let dhull = 0; + let dshield = 0; + // Apply modifiers - let theoritical = Math.round(this.value * this.getFactor(ship)); - let damage = theoritical; + let damage = Math.round(this.value * this.getFactor(ship)); - // Apply on shields - let shield = (damage >= ship.getValue("shield")) ? ship.getValue("shield") : damage; - damage -= shield; + // Split in shield/hull damage + if (this.mode == DamageEffectMode.HULL_ONLY) { + dhull = Math.min(damage, hull); + } else if (this.mode == DamageEffectMode.SHIELD_ONLY) { + dshield = Math.min(damage, shield); + } else if (this.mode == DamageEffectMode.SHIELD_OR_HULL) { + if (shield) { + dshield = Math.min(damage, shield); + } else { + dhull = Math.min(damage, hull); + } + } else { + dshield = Math.min(damage, shield); + dhull = Math.min(damage - dshield, hull); + } - // Apply on hull - let hull = (damage >= ship.getValue("hull")) ? ship.getValue("hull") : damage; - - return new ShipDamageDiff(ship, hull, shield, theoritical); + return new ShipDamageDiff(ship, dhull, dshield, damage); } getOnDiffs(ship: Ship, source: Ship | Drone): BaseBattleDiff[] { @@ -68,7 +97,16 @@ module TK.SpaceTac { } getDescription(): string { - return `do ${this.value} damage`; + let mode = ""; + if (this.mode == DamageEffectMode.HULL_ONLY) { + mode = " hull"; + } else if (this.mode == DamageEffectMode.SHIELD_ONLY) { + mode = " shield"; + } else if (this.mode == DamageEffectMode.SHIELD_THEN_HULL) { + mode = " piercing"; + } + + return `do ${this.value}${mode} damage`; } } } diff --git a/src/core/models/ModelBreeze.ts b/src/core/models/ModelBreeze.ts index 9ac3ffb..cca7e95 100644 --- a/src/core/models/ModelBreeze.ts +++ b/src/core/models/ModelBreeze.ts @@ -19,7 +19,7 @@ module TK.SpaceTac { engine.configureCooldown(2, 1); let gatling = new TriggerAction("Gatling Gun", { - effects: [new DamageEffect(2)], + effects: [new DamageEffect(2, DamageEffectMode.SHIELD_THEN_HULL)], power: 2, range: 200, }, "gatlinggun"); diff --git a/src/core/models/ModelCommodore.ts b/src/core/models/ModelCommodore.ts index b0a86e0..4ef5fdc 100644 --- a/src/core/models/ModelCommodore.ts +++ b/src/core/models/ModelCommodore.ts @@ -17,7 +17,7 @@ module TK.SpaceTac { }); let laser = new TriggerAction("Wingspan Laser", { - effects: [new DamageEffect(1)], + effects: [new DamageEffect(2, DamageEffectMode.SHIELD_THEN_HULL)], power: 4, range: 250, angle: 140, }, "prokhorovlaser"); diff --git a/src/core/models/ModelFalcon.ts b/src/core/models/ModelFalcon.ts index 76190d1..c5720eb 100644 --- a/src/core/models/ModelFalcon.ts +++ b/src/core/models/ModelFalcon.ts @@ -36,8 +36,8 @@ module TK.SpaceTac { effects: [ new AttributeEffect("precision", 8), new AttributeEffect("maneuvrability", 4), - new AttributeEffect("hull_capacity", 50), - new AttributeEffect("shield_capacity", 50), + new AttributeEffect("hull_capacity", 2), + new AttributeEffect("shield_capacity", 2), new AttributeEffect("power_capacity", 9), ] }, diff --git a/src/core/models/ModelXander.ts b/src/core/models/ModelXander.ts index b5a130c..3e611a5 100644 --- a/src/core/models/ModelXander.ts +++ b/src/core/models/ModelXander.ts @@ -17,7 +17,7 @@ module TK.SpaceTac { }); let laser = new TriggerAction("Prokhorov Laser", { - effects: [new DamageEffect(2)], + effects: [new DamageEffect(2, DamageEffectMode.SHIELD_THEN_HULL)], power: 3, range: 250, angle: 80, }); diff --git a/src/ui/battle/WeaponEffect.spec.ts b/src/ui/battle/WeaponEffect.spec.ts index 21994b0..9e2a963 100644 --- a/src/ui/battle/WeaponEffect.spec.ts +++ b/src/ui/battle/WeaponEffect.spec.ts @@ -50,7 +50,7 @@ module TK.SpaceTac.UI.Specs { let ship = nn(battleview.battle.playing_ship); ship.setArenaPosition(50, 30); - let weapon = new TriggerAction("weapon", { effects: [new DamageEffect()], range: 500 }); + let weapon = new TriggerAction("weapon", { effects: [new DamageEffect(1)], range: 500 }); check.patch(weapon, "getImpactedShips", () => [ship]); let dest = new Ship();