From 69a65b07357305343d00a2b8a65de9e84ac27259 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Lemaire?= Date: Tue, 6 Mar 2018 15:39:48 +0100 Subject: [PATCH] Improved character sheet tooltips --- graphics/ui/character.svg | 1113 +++++++++-------- src/common | 2 +- src/core/FleetGenerator.ts | 2 +- src/core/Ship.spec.ts | 18 +- src/core/Ship.ts | 14 +- src/core/ShipGenerator.spec.ts | 2 +- src/core/ShipGenerator.ts | 4 +- src/core/ShipLevel.ts | 4 +- src/core/TestTools.ts | 2 +- src/core/actions/ActionList.spec.ts | 6 +- src/core/models/ModelAvenger.ts | 38 +- src/core/models/ModelBreeze.ts | 8 +- src/core/models/ModelCommodore.ts | 8 +- src/core/models/ModelCreeper.ts | 8 +- src/core/models/ModelFalcon.ts | 8 +- src/core/models/ModelFlea.ts | 8 +- src/core/models/ModelJumper.ts | 8 +- src/core/models/ModelRhino.ts | 8 +- src/core/models/ModelTomahawk.ts | 8 +- src/core/models/ModelTrapper.ts | 8 +- src/core/models/ModelXander.ts | 8 +- .../{BaseModel.spec.ts => ShipModel.spec.ts} | 24 +- .../models/{BaseModel.ts => ShipModel.ts} | 36 +- src/ui/battle/ShipTooltip.spec.ts | 2 +- src/ui/character/CharacterUpgrade.spec.ts | 75 ++ src/ui/character/CharacterUpgrade.ts | 31 +- src/ui/character/FleetCreationView.ts | 2 +- src/ui/common/Tooltip.ts | 2 +- 28 files changed, 795 insertions(+), 662 deletions(-) rename src/core/models/{BaseModel.spec.ts => ShipModel.spec.ts} (71%) rename src/core/models/{BaseModel.ts => ShipModel.ts} (86%) create mode 100644 src/ui/character/CharacterUpgrade.spec.ts diff --git a/graphics/ui/character.svg b/graphics/ui/character.svg index d1c2cd2..c68907e 100644 --- a/graphics/ui/character.svg +++ b/graphics/ui/character.svg @@ -878,11 +878,11 @@ borderopacity="1.0" inkscape:pageopacity="0" inkscape:pageshadow="2" - inkscape:zoom="0.99999999" - inkscape:cx="549.91693" - inkscape:cy="482.67414" + inkscape:zoom="0.5" + inkscape:cx="984.86575" + inkscape:cy="573.79438" inkscape:document-units="px" - inkscape:current-layer="layer1" + inkscape:current-layer="layer4" showgrid="false" units="px" showborder="true" @@ -998,7 +998,7 @@ + id="image12382" + preserveAspectRatio="none" + height="256" + width="256" /> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 12 + + Upgrade points + + + + + + + + + + + + + + + + + + + + + + Level 9 + + + Attributes + Actions + + + + + + + ... + + + + ... + + + + + transform="translate(39.664806,-11.249922)"> @@ -1707,8 +2227,9 @@ style="fill:none;fill-opacity:0.02765958;fill-rule:evenodd;stroke:#bfc8aa;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> @@ -1746,290 +2267,10 @@ y="1017.7109" /> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 12 - - Upgrade points - - - - ... - + id="image4664" + preserveAspectRatio="none" + height="64" + width="64" + style="display:inline" + transform="translate(0,-11.249983)" /> Gatling + transform="rotate(90,1247.875,941.375)"> @@ -2113,45 +2360,11 @@ x="0" /> - - - - + transform="translate(37,-11.249983)"> Gatling Gun + transform="translate(190,-5.249983)"> + id="image12836" + preserveAspectRatio="none" + height="52" + width="52" /> 12 Base equipment - - - - - - - - - - - - - - - - Level 9 - - - Attributes - Actions - @@ -2468,35 +2547,11 @@ inkscape:connector-curvature="0" /> - - ... - - - - + transform="translate(-1.2460938e-5,98.994957)" /> diff --git a/src/common b/src/common index 2882c79..0fcd953 160000 --- a/src/common +++ b/src/common @@ -1 +1 @@ -Subproject commit 2882c791e8af845517fd030c6e789296d347213d +Subproject commit 0fcd953719ed8dbaab92cfaf525a2e34078b069a diff --git a/src/core/FleetGenerator.ts b/src/core/FleetGenerator.ts index f9dddca..2e47981 100644 --- a/src/core/FleetGenerator.ts +++ b/src/core/FleetGenerator.ts @@ -15,7 +15,7 @@ module TK.SpaceTac { var fleet = new Fleet(player); var ship_generator = new ShipGenerator(this.random); - let models = this.random.sample(BaseModel.getDefaultCollection(), ship_count); + let models = this.random.sample(ShipModel.getDefaultCollection(), ship_count); range(ship_count).forEach(i => { var ship = ship_generator.generate(level, models[i] || null, upgrade); diff --git a/src/core/Ship.spec.ts b/src/core/Ship.spec.ts index ccf81ba..2bda4b8 100644 --- a/src/core/Ship.spec.ts +++ b/src/core/Ship.spec.ts @@ -5,7 +5,7 @@ module TK.SpaceTac.Specs { check.equals(ship.getName(false), "Ship"); check.equals(ship.getName(true), "Level 1 Ship"); - ship.model = new BaseModel("test", "Hauler"); + ship.model = new ShipModel("test", "Hauler"); check.equals(ship.getName(false), "Hauler"); check.equals(ship.getName(true), "Level 1 Hauler"); @@ -35,7 +35,7 @@ module TK.SpaceTac.Specs { }); test.case("applies permanent effects of ship model on attributes", check => { - let model = new BaseModel(); + let model = new ShipModel(); let ship = new Ship(null, null, model); check.patch(model, "getEffects", () => [ @@ -151,17 +151,19 @@ module TK.SpaceTac.Specs { let ship = new Ship(); check.equals(ship.getAttributeDescription("maneuvrability"), "Ability to move first, fast and to evade weapons"); - check.patch(ship.model, "getEffects", () => [new AttributeEffect("maneuvrability", 4)]); - ship.updateAttributes(); - check.equals(ship.getAttribute("maneuvrability"), 4); - check.equals(ship.getAttributeDescription("maneuvrability"), "Ability to move first, fast and to evade weapons\n\nLevel 1 Ship: +4"); + check.patch(ship, "getUpgrades", () => [ + { code: "Base", effects: [new AttributeEffect("maneuvrability", 3)] }, + { code: "Up1", effects: [new AttributeEffect("precision", 1)] }, + { code: "Up2", effects: [new AttributeEffect("precision", 1), new AttributeEffect("maneuvrability", 1)] } + ]); + check.equals(ship.getAttributeDescription("maneuvrability"), "Ability to move first, fast and to evade weapons\n\nBase: +3\nUp2: +1"); ship.active_effects.add(new StickyEffect(new AttributeLimitEffect("maneuvrability", 3))); - check.equals(ship.getAttributeDescription("maneuvrability"), "Ability to move first, fast and to evade weapons\n\nLevel 1 Ship: +4\nSticky effect: limit to 3"); + check.equals(ship.getAttributeDescription("maneuvrability"), "Ability to move first, fast and to evade weapons\n\nBase: +3\nUp2: +1\nSticky effect: limit to 3"); ship.active_effects.remove(ship.active_effects.list()[0]); ship.active_effects.add(new AttributeEffect("maneuvrability", -1)); - check.equals(ship.getAttributeDescription("maneuvrability"), "Ability to move first, fast and to evade weapons\n\nLevel 1 Ship: +4\nActive effect: -1"); + check.equals(ship.getAttributeDescription("maneuvrability"), "Ability to move first, fast and to evade weapons\n\nBase: +3\nUp2: +1\nActive effect: -1"); }); test.case("produces death diffs", check => { diff --git a/src/core/Ship.ts b/src/core/Ship.ts index 62333fb..3e20634 100644 --- a/src/core/Ship.ts +++ b/src/core/Ship.ts @@ -6,7 +6,7 @@ module TK.SpaceTac { */ export class Ship extends RObject { // Ship model - model: BaseModel + model: ShipModel // Fleet this ship is a member of fleet: Fleet @@ -52,7 +52,7 @@ module TK.SpaceTac { play_priority = 0 // Create a new ship inside a fleet - constructor(fleet: Fleet | null = null, name: string | null = null, model = new BaseModel()) { + constructor(fleet: Fleet | null = null, name: string | null = null, model = new ShipModel()) { super(); this.fleet = fleet || new Fleet(); @@ -139,14 +139,14 @@ module TK.SpaceTac { /** * Get the list of activated upgrades */ - getUpgrades(): ModelUpgrade[] { + getUpgrades(): ShipUpgrade[] { return this.model.getActivatedUpgrades(this.level.get(), this.level.getUpgrades()); } /** * Toggle an upgrade */ - activateUpgrade(upgrade: ModelUpgrade, on: boolean): void { + activateUpgrade(upgrade: ShipUpgrade, on: boolean): void { if (on && (upgrade.cost || 0) > this.getAvailableUpgradePoints()) { return; } @@ -402,8 +402,10 @@ module TK.SpaceTac { } } - this.getModelEffects().forEach(effect => { - addEffect(`Level ${this.level.get()} ${this.model.name}`, effect); + this.getUpgrades().forEach(upgrade => { + if (upgrade.effects) { + upgrade.effects.forEach(effect => addEffect(upgrade.code, effect)); + } }); this.active_effects.list().forEach(effect => { diff --git a/src/core/ShipGenerator.spec.ts b/src/core/ShipGenerator.spec.ts index 3f9f5db..cafee09 100644 --- a/src/core/ShipGenerator.spec.ts +++ b/src/core/ShipGenerator.spec.ts @@ -2,7 +2,7 @@ module TK.SpaceTac.Specs { testing("ShipGenerator", test => { test.case("can use ship model", check => { var gen = new ShipGenerator(); - var model = new BaseModel("test", "Test"); + var model = new ShipModel("test", "Test"); var ship = gen.generate(3, model, false); check.same(ship.model, model); check.same(ship.level.get(), 3); diff --git a/src/core/ShipGenerator.ts b/src/core/ShipGenerator.ts index 1681260..ebfcbf5 100644 --- a/src/core/ShipGenerator.ts +++ b/src/core/ShipGenerator.ts @@ -15,10 +15,10 @@ module TK.SpaceTac { * * If *upgrade* is true, random levelling options will be chosen */ - generate(level: number, model: BaseModel | null = null, upgrade = true): Ship { + generate(level: number, model: ShipModel | null = null, upgrade = true): Ship { if (!model) { // Get a random model - model = BaseModel.getRandomModel(level, this.random); + model = ShipModel.getRandomModel(level, this.random); } let result = new Ship(null, null, model); diff --git a/src/core/ShipLevel.ts b/src/core/ShipLevel.ts index 23d04cc..52c3b75 100644 --- a/src/core/ShipLevel.ts +++ b/src/core/ShipLevel.ts @@ -94,7 +94,7 @@ module TK.SpaceTac { * * This does not check the upgrade points needed */ - activateUpgrade(upgrade: ModelUpgrade, active: boolean): void { + activateUpgrade(upgrade: ShipUpgrade, active: boolean): void { if (active) { add(this.upgrades, upgrade.code); } else { @@ -105,7 +105,7 @@ module TK.SpaceTac { /** * Check if an upgrade is active */ - hasUpgrade(upgrade: ModelUpgrade): boolean { + hasUpgrade(upgrade: ShipUpgrade): boolean { return contains(this.upgrades, upgrade.code); } } diff --git a/src/core/TestTools.ts b/src/core/TestTools.ts index 77fd0c8..0167c4b 100644 --- a/src/core/TestTools.ts +++ b/src/core/TestTools.ts @@ -58,7 +58,7 @@ module TK.SpaceTac { * Set a ship attributes (by changing its model) */ static setShipModel(ship: Ship, hull: number, shield = 0, power = 0, level = 1, actions: BaseAction[] = [], effects: BaseEffect[] = []) { - let model = new BaseModel(); + let model = new ShipModel(); ship.level.forceLevel(level); ship.model = model; diff --git a/src/core/actions/ActionList.spec.ts b/src/core/actions/ActionList.spec.ts index 5f43614..3482064 100644 --- a/src/core/actions/ActionList.spec.ts +++ b/src/core/actions/ActionList.spec.ts @@ -4,7 +4,7 @@ module TK.SpaceTac.Specs { let actions = new ActionList(); check.equals(actions.listAll(), [EndTurnAction.SINGLETON]); - let model = new BaseModel(); + let model = new ShipModel(); let ship = new Ship(null, null, model); actions.updateFromShip(ship); check.equals(actions.listAll(), [EndTurnAction.SINGLETON]); @@ -17,8 +17,8 @@ module TK.SpaceTac.Specs { check.equals(actions.listAll(), [action1, action2, EndTurnAction.SINGLETON]); check.called(mock, [[3, []]]); - let up1: ModelUpgrade = { code: "up1" }; - let up2: ModelUpgrade = { code: "up2" }; + let up1: ShipUpgrade = { code: "up1" }; + let up2: ShipUpgrade = { code: "up2" }; check.patch(model, "getLevelUpgrades", () => [up1, up2]); ship.level.activateUpgrade(up1, true); actions.updateFromShip(ship); diff --git a/src/core/models/ModelAvenger.ts b/src/core/models/ModelAvenger.ts index a0cd08f..b62aaea 100644 --- a/src/core/models/ModelAvenger.ts +++ b/src/core/models/ModelAvenger.ts @@ -1,7 +1,7 @@ -/// +/// module TK.SpaceTac { - export class ModelAvenger extends BaseModel { + export class ModelAvenger extends ShipModel { constructor() { super("avenger", "Avenger"); } @@ -10,7 +10,7 @@ module TK.SpaceTac { return "A heavy ship, dedicated to firing high precision charged shots across great distances."; } - getLevelUpgrades(level: number): ModelUpgrade[] { + getLevelUpgrades(level: number): ShipUpgrade[] { let engine = new MoveAction("Engine", { distance_per_power: 50, safety_distance: 250, @@ -35,19 +35,10 @@ module TK.SpaceTac { }, "submunitionmissile"); long_range_missile.configureCooldown(1, 2); - let shield_booster = new TriggerAction("Shield Booster", { - effects: [ - new StickyEffect(new AttributeEffect("shield_capacity", 50), 2), - new ValueEffect("shield", 70), - ], - power: 2 - }, "forcefield"); - shield_booster.configureCooldown(1, 4); - if (level == 1) { return [ { - code: "Base Attributes", + code: "Avenger Base", effects: [ new AttributeEffect("precision", 8), new AttributeEffect("maneuvrability", 0), @@ -73,28 +64,41 @@ module TK.SpaceTac { return [ { code: "Laser Targetting", + description: "Improved targetting, using fine-grained laser sensors", cost: 1, - effects: [new AttributeEffect("precision", 2)] + effects: [new AttributeEffect("precision", 2)], }, { code: "Basic Countermeasures", + description: "Chaffs and lures to divert enemy fire", cost: 1, - effects: [new AttributeEffect("maneuvrability", 2)] + effects: [new AttributeEffect("maneuvrability", 2)], }, { code: "Targetting Assist", + description: "Share your targetting subnetwork with nearby ships", cost: 3, actions: [new ToggleAction("Targetting Assist", { power: 3, radius: 300, effects: [new AttributeEffect("precision", 2)] - }, "precisionboost")] + }, "precisionboost")], }, ]; } else if (level == 3) { + let shield_booster = new TriggerAction("Shield Booster", { + effects: [ + new StickyEffect(new AttributeEffect("shield_capacity", 50), 2), + new ValueEffect("shield", 70), + ], + power: 2 + }, "forcefield"); + shield_booster.configureCooldown(1, 4); + return [ { code: "Gyroscopic Stabilizers", + description: "Heavy mercury gyroscopes, used to stabilize the whole ship while firing", cost: 1, effects: [ new AttributeEffect("precision", 3), @@ -103,11 +107,13 @@ module TK.SpaceTac { }, { code: "Shield Booster", + description: "Temporary power surge directed toward the shield mainframe, to boost its output", cost: 3, actions: [shield_booster] }, { code: "Hard Coated Hull", + description: "Improved metal coating of outer hull layers, making them more damage resistant", cost: 2, effects: [new AttributeEffect("hull_capacity", 10)] }, diff --git a/src/core/models/ModelBreeze.ts b/src/core/models/ModelBreeze.ts index b25b7c1..cd9aa3b 100644 --- a/src/core/models/ModelBreeze.ts +++ b/src/core/models/ModelBreeze.ts @@ -1,7 +1,7 @@ -/// +/// module TK.SpaceTac { - export class ModelBreeze extends BaseModel { + export class ModelBreeze extends ShipModel { constructor() { super("breeze", "Breeze"); } @@ -10,7 +10,7 @@ module TK.SpaceTac { return "A swift piece of maneuvrability, able to go deep behind enemy lines, and come back without a scratch."; } - getLevelUpgrades(level: number): ModelUpgrade[] { + getLevelUpgrades(level: number): ShipUpgrade[] { if (level == 1) { let engine = new MoveAction("Engine", { distance_per_power: 300, @@ -36,7 +36,7 @@ module TK.SpaceTac { return [ { - code: "Base Attributes", + code: "Breeze Base", effects: [ new AttributeEffect("precision", 3), new AttributeEffect("maneuvrability", 12), diff --git a/src/core/models/ModelCommodore.ts b/src/core/models/ModelCommodore.ts index da5a3a6..51db0cb 100644 --- a/src/core/models/ModelCommodore.ts +++ b/src/core/models/ModelCommodore.ts @@ -1,7 +1,7 @@ -/// +/// module TK.SpaceTac { - export class ModelCommodore extends BaseModel { + export class ModelCommodore extends ShipModel { constructor() { super("commodore", "Commodore"); } @@ -10,7 +10,7 @@ module TK.SpaceTac { return "A devil whirlwind, very dangerous to surround."; } - getLevelUpgrades(level: number): ModelUpgrade[] { + getLevelUpgrades(level: number): ShipUpgrade[] { if (level == 1) { let engine = new MoveAction("Engine", { distance_per_power: 150, @@ -33,7 +33,7 @@ module TK.SpaceTac { return [ { - code: "Base Attributes", + code: "Commodore Base", effects: [ new AttributeEffect("precision", 5), new AttributeEffect("maneuvrability", 6), diff --git a/src/core/models/ModelCreeper.ts b/src/core/models/ModelCreeper.ts index fbbe81d..5cde10c 100644 --- a/src/core/models/ModelCreeper.ts +++ b/src/core/models/ModelCreeper.ts @@ -1,7 +1,7 @@ -/// +/// module TK.SpaceTac { - export class ModelCreeper extends BaseModel { + export class ModelCreeper extends ShipModel { constructor() { super("creeper", "Creeper"); } @@ -10,7 +10,7 @@ module TK.SpaceTac { return "A fast ship, with low firepower but extensive support modules."; } - getLevelUpgrades(level: number): ModelUpgrade[] { + getLevelUpgrades(level: number): ShipUpgrade[] { if (level == 1) { let engine = new MoveAction("Engine", { distance_per_power: 220, @@ -40,7 +40,7 @@ module TK.SpaceTac { return [ { - code: "Base Attributes", + code: "Creeper Base", effects: [ new AttributeEffect("precision", 3), new AttributeEffect("maneuvrability", 12), diff --git a/src/core/models/ModelFalcon.ts b/src/core/models/ModelFalcon.ts index 177cd27..4a0dd04 100644 --- a/src/core/models/ModelFalcon.ts +++ b/src/core/models/ModelFalcon.ts @@ -1,7 +1,7 @@ -/// +/// module TK.SpaceTac { - export class ModelFalcon extends BaseModel { + export class ModelFalcon extends ShipModel { constructor() { super("falcon", "Falcon"); } @@ -10,7 +10,7 @@ module TK.SpaceTac { return "A ship with an efficient targetting system, allowing to hit multiple foes."; } - getLevelUpgrades(level: number): ModelUpgrade[] { + getLevelUpgrades(level: number): ShipUpgrade[] { if (level == 1) { let engine = new MoveAction("Engine", { distance_per_power: 130, @@ -32,7 +32,7 @@ module TK.SpaceTac { return [ { - code: "Base Attributes", + code: "Falcon Base", effects: [ new AttributeEffect("precision", 8), new AttributeEffect("maneuvrability", 4), diff --git a/src/core/models/ModelFlea.ts b/src/core/models/ModelFlea.ts index 1f51c5d..c022656 100644 --- a/src/core/models/ModelFlea.ts +++ b/src/core/models/ModelFlea.ts @@ -1,7 +1,7 @@ -/// +/// module TK.SpaceTac { - export class ModelFlea extends BaseModel { + export class ModelFlea extends ShipModel { constructor() { super("flea", "Flea"); } @@ -10,7 +10,7 @@ module TK.SpaceTac { return "An agile but weak ship, specialized in disruptive technologies."; } - getLevelUpgrades(level: number): ModelUpgrade[] { + getLevelUpgrades(level: number): ShipUpgrade[] { if (level == 1) { let engine = new MoveAction("Engine", { distance_per_power: 400, @@ -32,7 +32,7 @@ module TK.SpaceTac { return [ { - code: "Base Attributes", + code: "Flea Base", effects: [ new AttributeEffect("precision", 0), new AttributeEffect("maneuvrability", 15), diff --git a/src/core/models/ModelJumper.ts b/src/core/models/ModelJumper.ts index fdd597d..0c5e649 100644 --- a/src/core/models/ModelJumper.ts +++ b/src/core/models/ModelJumper.ts @@ -1,7 +1,7 @@ -/// +/// module TK.SpaceTac { - export class ModelJumper extends BaseModel { + export class ModelJumper extends ShipModel { constructor() { super("jumper", "Jumper"); } @@ -10,7 +10,7 @@ module TK.SpaceTac { return "A mid-range action ship, with support abilities."; } - getLevelUpgrades(level: number): ModelUpgrade[] { + getLevelUpgrades(level: number): ShipUpgrade[] { if (level == 1) { let engine = new MoveAction("Engine", { distance_per_power: 200, @@ -38,7 +38,7 @@ module TK.SpaceTac { return [ { - code: "Base Attributes", + code: "Jumper Base", effects: [ new AttributeEffect("precision", 9), new AttributeEffect("maneuvrability", 3), diff --git a/src/core/models/ModelRhino.ts b/src/core/models/ModelRhino.ts index cdd31ad..2b44d49 100644 --- a/src/core/models/ModelRhino.ts +++ b/src/core/models/ModelRhino.ts @@ -1,7 +1,7 @@ -/// +/// module TK.SpaceTac { - export class ModelRhino extends BaseModel { + export class ModelRhino extends ShipModel { constructor() { super("rhino", "Rhino"); } @@ -10,7 +10,7 @@ module TK.SpaceTac { return "A sturdy ship, able to sustain massive damage."; } - getLevelUpgrades(level: number): ModelUpgrade[] { + getLevelUpgrades(level: number): ShipUpgrade[] { if (level == 1) { let engine = new MoveAction("Engine", { distance_per_power: 140, @@ -32,7 +32,7 @@ module TK.SpaceTac { return [ { - code: "Base Attributes", + code: "Rhino Base", effects: [ new AttributeEffect("precision", 4), new AttributeEffect("maneuvrability", 3), diff --git a/src/core/models/ModelTomahawk.ts b/src/core/models/ModelTomahawk.ts index bb3a20b..0aac2d2 100644 --- a/src/core/models/ModelTomahawk.ts +++ b/src/core/models/ModelTomahawk.ts @@ -1,7 +1,7 @@ -/// +/// module TK.SpaceTac { - export class ModelTomahawk extends BaseModel { + export class ModelTomahawk extends ShipModel { constructor() { super("tomahawk", "Tomahawk"); } @@ -10,7 +10,7 @@ module TK.SpaceTac { return "A ship compensating its somewhat weak equipments with high power and usability."; } - getLevelUpgrades(level: number): ModelUpgrade[] { + getLevelUpgrades(level: number): ShipUpgrade[] { if (level == 1) { let engine = new MoveAction("Engine", { distance_per_power: 160, @@ -49,7 +49,7 @@ module TK.SpaceTac { return [ { - code: "Base Attributes", + code: "Tomahawk Base", effects: [ new AttributeEffect("precision", 8), new AttributeEffect("maneuvrability", 3), diff --git a/src/core/models/ModelTrapper.ts b/src/core/models/ModelTrapper.ts index 66a814f..d82af6f 100644 --- a/src/core/models/ModelTrapper.ts +++ b/src/core/models/ModelTrapper.ts @@ -1,7 +1,7 @@ -/// +/// module TK.SpaceTac { - export class ModelTrapper extends BaseModel { + export class ModelTrapper extends ShipModel { constructor() { super("trapper", "Trapper"); } @@ -10,7 +10,7 @@ module TK.SpaceTac { return "A mostly defensive ship, used to protect allies from enemy fire."; } - getLevelUpgrades(level: number): ModelUpgrade[] { + getLevelUpgrades(level: number): ShipUpgrade[] { if (level == 1) { let engine = new MoveAction("Engine", { distance_per_power: 220, @@ -38,7 +38,7 @@ module TK.SpaceTac { return [ { - code: "Base Attributes", + code: "Trapper Base", effects: [ new AttributeEffect("precision", 3), new AttributeEffect("maneuvrability", 2), diff --git a/src/core/models/ModelXander.ts b/src/core/models/ModelXander.ts index d1846a0..e05dda8 100644 --- a/src/core/models/ModelXander.ts +++ b/src/core/models/ModelXander.ts @@ -1,7 +1,7 @@ -/// +/// module TK.SpaceTac { - export class ModelXander extends BaseModel { + export class ModelXander extends ShipModel { constructor() { super("xander", "Xander"); } @@ -10,7 +10,7 @@ module TK.SpaceTac { return "A ship with impressive survival capabilities."; } - getLevelUpgrades(level: number): ModelUpgrade[] { + getLevelUpgrades(level: number): ShipUpgrade[] { if (level == 1) { let engine = new MoveAction("Engine", { distance_per_power: 150, @@ -37,7 +37,7 @@ module TK.SpaceTac { return [ { - code: "Base Attributes", + code: "Xander Base", effects: [ new AttributeEffect("precision", 8), new AttributeEffect("maneuvrability", 5), diff --git a/src/core/models/BaseModel.spec.ts b/src/core/models/ShipModel.spec.ts similarity index 71% rename from src/core/models/BaseModel.spec.ts rename to src/core/models/ShipModel.spec.ts index c35e4bf..4650e03 100644 --- a/src/core/models/BaseModel.spec.ts +++ b/src/core/models/ShipModel.spec.ts @@ -1,25 +1,25 @@ module TK.SpaceTac.Specs { - testing("BaseModel", test => { + testing("ShipModel", test => { test.case("picks random models from default collection", check => { check.patch(console, "error", null); - check.patch(BaseModel, "getDefaultCollection", iterator([ - [new BaseModel("a")], + check.patch(ShipModel, "getDefaultCollection", iterator([ + [new ShipModel("a")], [], - [new BaseModel("a"), new BaseModel("b")], - [new BaseModel("a")], + [new ShipModel("a"), new ShipModel("b")], + [new ShipModel("a")], [], ])); - check.equals(BaseModel.getRandomModel(), new BaseModel("a"), "pick from a one-item list"); - check.equals(BaseModel.getRandomModel(), new BaseModel(), "pick from an empty list"); + check.equals(ShipModel.getRandomModel(), new ShipModel("a"), "pick from a one-item list"); + check.equals(ShipModel.getRandomModel(), new ShipModel(), "pick from an empty list"); - check.equals(sorted(BaseModel.getRandomModels(2), (a, b) => cmp(a.code, b.code)), [new BaseModel("a"), new BaseModel("b")], "sample from good-sized list"); - check.equals(BaseModel.getRandomModels(2), [new BaseModel("a"), new BaseModel("a")], "sample from too small list"); - check.equals(BaseModel.getRandomModels(2), [new BaseModel(), new BaseModel()], "sample from empty list"); + check.equals(sorted(ShipModel.getRandomModels(2), (a, b) => cmp(a.code, b.code)), [new ShipModel("a"), new ShipModel("b")], "sample from good-sized list"); + check.equals(ShipModel.getRandomModels(2), [new ShipModel("a"), new ShipModel("a")], "sample from too small list"); + check.equals(ShipModel.getRandomModels(2), [new ShipModel(), new ShipModel()], "sample from empty list"); }); test.case("makes upgrades available by level", check => { - let model = new BaseModel(); + let model = new ShipModel(); function verify(desc: string, level: number, specific: string[], available: string[], activated: string[], chosen: string[] = []) { check.in(`${desc} level ${level}`, check => { @@ -31,7 +31,7 @@ module TK.SpaceTac.Specs { verify("initial", 1, [], [], []); - check.patch(model, "getLevelUpgrades", (level: number): ModelUpgrade[] => { + check.patch(model, "getLevelUpgrades", (level: number): ShipUpgrade[] => { if (level == 1) { return [ { code: "l1" }, diff --git a/src/core/models/BaseModel.ts b/src/core/models/ShipModel.ts similarity index 86% rename from src/core/models/BaseModel.ts rename to src/core/models/ShipModel.ts index 8665f68..96d60eb 100644 --- a/src/core/models/BaseModel.ts +++ b/src/core/models/ShipModel.ts @@ -4,11 +4,13 @@ module TK.SpaceTac { * * Upgrades allow for customizing a model, and are unlocked at given levels */ - export type ModelUpgrade = { + export type ShipUpgrade = { // Displayable upgrade name, should be unique on the model code: string // Upgrade points cost (may be used to balance upgrades) cost?: number + // Textual description of the upgrade + description?: string // Optional list of upgrade codes that must be activated for this one to be available depends?: string[] // Optional list of upgrade codes that this upgrade will fully replace @@ -26,7 +28,7 @@ module TK.SpaceTac { * * A model defines the ship's design, actions, permanent effects, and levelling options. */ - export class BaseModel { + export class ShipModel { constructor( // Code to identify the model readonly code = "default", @@ -52,7 +54,7 @@ module TK.SpaceTac { /** * Get basic level upgrades */ - protected getStandardUpgrades(level: number): ModelUpgrade[] { + protected getStandardUpgrades(level: number): ShipUpgrade[] { return [ { code: `Hull upgrade Lv${level - 1}`, effects: [new AttributeEffect("hull_capacity", 5)], cost: 2 }, { code: `Shield upgrade Lv${level - 1}`, effects: [new AttributeEffect("shield_capacity", 5)], cost: 2 }, @@ -63,15 +65,15 @@ module TK.SpaceTac { /** * Get the list of upgrades unlocked at a given level */ - getLevelUpgrades(level: number): ModelUpgrade[] { + getLevelUpgrades(level: number): ShipUpgrade[] { return []; } /** * Get the list of upgrades activated, given a ship level and an upgrade set */ - getActivatedUpgrades(level: number, upgrade_codes: string[]): ModelUpgrade[] { - let result: ModelUpgrade[] = []; + getActivatedUpgrades(level: number, upgrade_codes: string[]): ShipUpgrade[] { + let result: ShipUpgrade[] = []; range(level).forEach(i => { let upgrades = this.getLevelUpgrades(i + 1); @@ -95,7 +97,7 @@ module TK.SpaceTac { * * This does not filter the upgrades on dependencies */ - getAvailableUpgrades(level: number): ModelUpgrade[] { + getAvailableUpgrades(level: number): ShipUpgrade[] { return flatten(range(level).map(i => this.getLevelUpgrades(i + 1))); } @@ -120,14 +122,14 @@ module TK.SpaceTac { * * This scans the current namespace for model classes starting with 'Model'. */ - static getDefaultCollection(): BaseModel[] { - let result: BaseModel[] = []; + static getDefaultCollection(): ShipModel[] { + let result: ShipModel[] = []; let namespace: any = TK.SpaceTac; for (let class_name in namespace) { if (class_name && class_name.indexOf("Model") == 0) { let model_class = namespace[class_name]; - if (model_class.prototype instanceof BaseModel) { + if (model_class.prototype instanceof ShipModel) { let model = new model_class(); result.push(model); } @@ -140,15 +142,15 @@ module TK.SpaceTac { /** * Pick a random model in the default collection */ - static getRandomModel(level?: number, random = RandomGenerator.global): BaseModel { - let collection = BaseModel.getDefaultCollection(); + static getRandomModel(level?: number, random = RandomGenerator.global): ShipModel { + let collection = ShipModel.getDefaultCollection(); if (level) { collection = collection.filter(model => model.isAvailable(level)); } if (collection.length == 0) { console.error("Couldn't pick a random ship model"); - return new BaseModel(); + return new ShipModel(); } else { return random.choice(collection); } @@ -159,17 +161,17 @@ module TK.SpaceTac { * * At first it tries to pick unique models, then fill with duplicates */ - static getRandomModels(count: number, level?: number, random = RandomGenerator.global): BaseModel[] { - let collection = BaseModel.getDefaultCollection(); + static getRandomModels(count: number, level?: number, random = RandomGenerator.global): ShipModel[] { + let collection = ShipModel.getDefaultCollection(); if (level) { collection = collection.filter(model => model.isAvailable(level)); } if (collection.length == 0) { console.error("Couldn't pick a random model"); - return range(count).map(() => new BaseModel()); + return range(count).map(() => new ShipModel()); } else { - let result: BaseModel[] = []; + let result: ShipModel[] = []; while (count > 0) { let picked = random.sample(collection, Math.min(count, collection.length)); result = result.concat(picked); diff --git a/src/ui/battle/ShipTooltip.spec.ts b/src/ui/battle/ShipTooltip.spec.ts index 5cb3206..d4db2ec 100644 --- a/src/ui/battle/ShipTooltip.spec.ts +++ b/src/ui/battle/ShipTooltip.spec.ts @@ -7,7 +7,7 @@ module TK.SpaceTac.UI.Specs { let ship = testgame.view.battle.play_order[2]; TestTools.setShipModel(ship, 58, 140, 12); ship.name = "Fury"; - ship.model = new BaseModel("fake", "Fury"); + ship.model = new ShipModel("fake", "Fury"); check.patch(ship.model, "getDescription", () => "Super ship model !"); TestTools.addWeapon(ship, 50); TestTools.setAttribute(ship, "precision", 7); diff --git a/src/ui/character/CharacterUpgrade.spec.ts b/src/ui/character/CharacterUpgrade.spec.ts new file mode 100644 index 0000000..4c7515b --- /dev/null +++ b/src/ui/character/CharacterUpgrade.spec.ts @@ -0,0 +1,75 @@ +/// + +module TK.SpaceTac.UI.Specs { + testing("CharacterUpgrade", test => { + let testgame = setupSingleView(test, () => [new BaseView(), []]); + + test.acase("fills tooltip content", async check => { + let ship = new Ship(); + let upgrade: ShipUpgrade = { + code: "Test Upgrade", + description: "A super ship upgrade", + effects: [ + new AttributeEffect("hull_capacity", 10), + new AttributeEffect("shield_capacity", 5), + ] + }; + + let display = new CharacterUpgrade(ship, upgrade, 3); + let tooltip = new TooltipContainer(testgame.view); + let builder = new TooltipBuilder(tooltip); + display.fillTooltip(builder); + check.equals(cfilter(tooltip.content.children, Phaser.Text).map(child => child.text), [ + "Test Upgrade", + "Permanent effects:", + "• hull capacity +10", + "• shield capacity +5", + "A super ship upgrade", + ]); + + upgrade.effects = []; + upgrade.actions = [new TriggerAction("Test action", { + range: 50, + effects: [new DamageEffect(10)] + })]; + + builder.clear(); + display.fillTooltip(builder); + check.equals(cfilter(tooltip.content.children, Phaser.Text).map(child => child.text), [ + "Test Upgrade", + "Fire (power 1, range 50km):", + "• do 10 damage on target", + "A super ship upgrade", + ]); + }) + + test.acase("gets an appropriate icon", async check => { + let ship = new Ship(); + let upgrade: ShipUpgrade = { + code: "Test Upgrade", + effects: [ + new AttributeEffect("hull_capacity", 10), + new AttributeEffect("shield_capacity", 5), + ] + }; + let display = new CharacterUpgrade(ship, upgrade, 3); + check.equals(display.getIcon(), "attribute-hull_capacity"); + + upgrade.effects = []; + upgrade.actions = [new BaseAction("Test Action")]; + check.equals(display.getIcon(), "action-testaction"); + + upgrade.actions = []; + check.equals(display.getIcon(), "translucent"); + + upgrade.effects = [new DamageEffect(10)]; + check.equals(display.getIcon(), "translucent"); + + upgrade.effects = [ + new DamageEffect(10), + new AttributeMultiplyEffect("precision", 2) + ]; + check.equals(display.getIcon(), "attribute-precision"); + }) + }) +} diff --git a/src/ui/character/CharacterUpgrade.ts b/src/ui/character/CharacterUpgrade.ts index f221c16..2adc996 100644 --- a/src/ui/character/CharacterUpgrade.ts +++ b/src/ui/character/CharacterUpgrade.ts @@ -5,7 +5,7 @@ module TK.SpaceTac.UI { export class CharacterUpgrade { constructor( readonly ship: Ship, - readonly upgrade: ModelUpgrade, + readonly upgrade: ShipUpgrade, readonly level: number ) { } @@ -28,7 +28,7 @@ module TK.SpaceTac.UI { if (enabled) { builder.text(this.upgrade.code, 166, 40, { size: 16, color: "#e7ebf0", width: 210 }); - let icon = builder.image(this.getIcon(this.upgrade), 40, 40, true); + let icon = builder.image(this.getIcon(), 40, 40, true); if (icon.width && icon.width > 64) { icon.scale.set(64 / icon.width); } @@ -60,32 +60,43 @@ module TK.SpaceTac.UI { /** * Fill the tooltip for this upgrade */ - private fillTooltip(builder: TooltipBuilder): boolean { + fillTooltip(builder: TooltipBuilder): boolean { builder.text(this.upgrade.code, 0, 0, { size: 20 }); - let y = 30; + let y = 42; - if (this.upgrade.effects) { + if (bool(this.upgrade.effects)) { + builder.text("Permanent effects:", 0, y); + y += 30; this.upgrade.effects.forEach(effect => { - builder.text(effect.getDescription(), 0, y); + builder.text(`• ${effect.getDescription()}`, 0, y); y += 30; }); } - if (this.upgrade.actions) { + if (bool(this.upgrade.actions)) { this.upgrade.actions.forEach(action => { - builder.text(action.getEffectsDescription(), 0, y); - y += 60; + action.getEffectsDescription().split('\n').forEach(line => { + builder.text(line, 0, y); + y += 30; + }) }); } + if (bool(this.upgrade.description)) { + y += 10; + builder.text(this.upgrade.description, 0, y, { size: 14, color: "#999999", width: 540 }); + } + return true; } /** * Get an icon code for an upgrade */ - private getIcon(upgrade: ModelUpgrade): string { + getIcon(): string { + let upgrade = this.upgrade; + if (upgrade.actions && upgrade.actions.length) { return `action-${upgrade.actions[0].code}`; } else if (upgrade.effects && upgrade.effects.length) { diff --git a/src/ui/character/FleetCreationView.ts b/src/ui/character/FleetCreationView.ts index 7133823..8e22749 100644 --- a/src/ui/character/FleetCreationView.ts +++ b/src/ui/character/FleetCreationView.ts @@ -12,7 +12,7 @@ module TK.SpaceTac.UI { create() { super.create(); - let models = BaseModel.getRandomModels(2); + let models = ShipModel.getRandomModels(2); this.built_fleet = new Fleet(); this.built_fleet.addShip(new Ship(null, MissionGenerator.generateCharacterName(), models[0])); diff --git a/src/ui/common/Tooltip.ts b/src/ui/common/Tooltip.ts index df46847..9ca4ba9 100644 --- a/src/ui/common/Tooltip.ts +++ b/src/ui/common/Tooltip.ts @@ -4,7 +4,7 @@ module TK.SpaceTac.UI { export type TooltipFiller = string | ((filler: TooltipBuilder) => string) | ((filler: TooltipBuilder) => boolean); - class TooltipContainer extends Phaser.Group { + export class TooltipContainer extends Phaser.Group { view: BaseView background: Phaser.Graphics content: Phaser.Group