diff --git a/TODO.md b/TODO.md index 344da14..14e52a6 100644 --- a/TODO.md +++ b/TODO.md @@ -24,9 +24,9 @@ Map/story Character sheet --------------- -* Replace the close icon by a validation icon in creation view -* Allow to change/buy ship model -* Add personality indicators (editable in creation view) +* Improve action and attribute tooltips +* Implement sliders for personality traits +* Center the portraits when there are less than 5 Battle ------ diff --git a/data/stage2/image/character/creation-help.png b/data/stage2/image/character/creation-help.png new file mode 100644 index 0000000..ac4abb1 Binary files /dev/null and b/data/stage2/image/character/creation-help.png differ diff --git a/data/stage2/image/character/initial.png b/data/stage2/image/character/initial.png index 48354ba..99627ff 100644 Binary files a/data/stage2/image/character/initial.png and b/data/stage2/image/character/initial.png differ diff --git a/data/stage2/image/character/level-display.png b/data/stage2/image/character/level-display.png index aa294cc..b780df6 100644 Binary files a/data/stage2/image/character/level-display.png and b/data/stage2/image/character/level-display.png differ diff --git a/data/stage2/image/character/level-experience.png b/data/stage2/image/character/level-experience.png index a294a77..be4b394 100644 Binary files a/data/stage2/image/character/level-experience.png and b/data/stage2/image/character/level-experience.png differ diff --git a/data/stage2/image/character/model-next-hover.png b/data/stage2/image/character/model-next-hover.png new file mode 100644 index 0000000..121cf05 Binary files /dev/null and b/data/stage2/image/character/model-next-hover.png differ diff --git a/data/stage2/image/character/model-next.png b/data/stage2/image/character/model-next.png new file mode 100644 index 0000000..a695735 Binary files /dev/null and b/data/stage2/image/character/model-next.png differ diff --git a/data/stage2/image/character/model-prev-hover.png b/data/stage2/image/character/model-prev-hover.png new file mode 100644 index 0000000..bc7fb69 Binary files /dev/null and b/data/stage2/image/character/model-prev-hover.png differ diff --git a/data/stage2/image/character/model-prev.png b/data/stage2/image/character/model-prev.png new file mode 100644 index 0000000..8334517 Binary files /dev/null and b/data/stage2/image/character/model-prev.png differ diff --git a/data/stage2/image/character/name-button-hover.png b/data/stage2/image/character/name-button-hover.png index ed8af5c..239826c 100644 Binary files a/data/stage2/image/character/name-button-hover.png and b/data/stage2/image/character/name-button-hover.png differ diff --git a/data/stage2/image/character/name-button.png b/data/stage2/image/character/name-button.png index 61f7b1b..e407358 100644 Binary files a/data/stage2/image/character/name-button.png and b/data/stage2/image/character/name-button.png differ diff --git a/data/stage2/image/character/name-display.png b/data/stage2/image/character/name-display.png index e609e62..b77da40 100644 Binary files a/data/stage2/image/character/name-display.png and b/data/stage2/image/character/name-display.png differ diff --git a/data/stage2/image/character/personality-background.png b/data/stage2/image/character/personality-background.png new file mode 100644 index 0000000..b0476c6 Binary files /dev/null and b/data/stage2/image/character/personality-background.png differ diff --git a/data/stage2/image/character/personality-trait-base.png b/data/stage2/image/character/personality-trait-base.png new file mode 100644 index 0000000..5dd8483 Binary files /dev/null and b/data/stage2/image/character/personality-trait-base.png differ diff --git a/data/stage2/image/character/personality-trait-cursor-hover.png b/data/stage2/image/character/personality-trait-cursor-hover.png new file mode 100644 index 0000000..a5af7f2 Binary files /dev/null and b/data/stage2/image/character/personality-trait-cursor-hover.png differ diff --git a/data/stage2/image/character/personality-trait-cursor.png b/data/stage2/image/character/personality-trait-cursor.png new file mode 100644 index 0000000..32037e7 Binary files /dev/null and b/data/stage2/image/character/personality-trait-cursor.png differ diff --git a/data/stage2/image/character/portrait-hover.png b/data/stage2/image/character/portrait-hover.png index fd00cb1..a462798 100644 Binary files a/data/stage2/image/character/portrait-hover.png and b/data/stage2/image/character/portrait-hover.png differ diff --git a/data/stage2/image/character/portrait-on.png b/data/stage2/image/character/portrait-on.png index b6b24ee..3e7a569 100644 Binary files a/data/stage2/image/character/portrait-on.png and b/data/stage2/image/character/portrait-on.png differ diff --git a/data/stage2/image/character/section-title.png b/data/stage2/image/character/section-title.png new file mode 100644 index 0000000..71565bc Binary files /dev/null and b/data/stage2/image/character/section-title.png differ diff --git a/data/stage2/image/character/ship-column-left.png b/data/stage2/image/character/ship-column-left.png new file mode 100644 index 0000000..d7ea433 Binary files /dev/null and b/data/stage2/image/character/ship-column-left.png differ diff --git a/data/stage2/image/character/ship-column.png b/data/stage2/image/character/ship-column-right.png similarity index 100% rename from data/stage2/image/character/ship-column.png rename to data/stage2/image/character/ship-column-right.png diff --git a/data/stage2/image/character/ship-model.png b/data/stage2/image/character/ship-model.png index 87250ec..77acec8 100644 Binary files a/data/stage2/image/character/ship-model.png and b/data/stage2/image/character/ship-model.png differ diff --git a/data/stage2/image/character/upgrade-on.png b/data/stage2/image/character/upgrade-on.png index e8c3625..8abde4c 100644 Binary files a/data/stage2/image/character/upgrade-on.png and b/data/stage2/image/character/upgrade-on.png differ diff --git a/data/stage2/image/character/validate-creation-hover.png b/data/stage2/image/character/validate-creation-hover.png new file mode 100644 index 0000000..a273396 Binary files /dev/null and b/data/stage2/image/character/validate-creation-hover.png differ diff --git a/data/stage2/image/character/validate-creation.png b/data/stage2/image/character/validate-creation.png new file mode 100644 index 0000000..9facff5 Binary files /dev/null and b/data/stage2/image/character/validate-creation.png differ diff --git a/docs/style.md b/docs/style.md index 670f730..0abf9d9 100644 --- a/docs/style.md +++ b/docs/style.md @@ -1,5 +1,14 @@ # UI style guidelines +## Shapes + +Main UI shapes are: + +* long hexagon +* rectangles, optionally with left and/or right side tilted (if both are tilted, it should be symmetrical) + +Buttons should be lit by a pure white line in top-left corner (~75% of the border length) + ## Color palette http://paletton.com/#uid=63D0c0kcBwN43YM8AMYhnnWlyeQ diff --git a/graphics/ui/character.svg b/graphics/ui/character.svg index fef7e4a..594bf9c 100644 --- a/graphics/ui/character.svg +++ b/graphics/ui/character.svg @@ -23,6 +23,18 @@ enable-background="new"> + + + + @@ -219,27 +231,27 @@ inkscape:collect="always" id="linearGradient13848"> + style="stop-color:#6c87a9;stop-opacity:1" /> + style="stop-color:#fff3df;stop-opacity:1" /> + style="stop-color:#a3bbd9;stop-opacity:1" /> + style="stop-color:#3f5a7d;stop-opacity:0" /> @@ -259,7 +271,7 @@ inkscape:collect="always" id="linearGradient12973"> - - - - - - - + + + + + + + + + + + + + + inkscape:measure-start="1124.3,270.115" + inkscape:measure-end="1629.17,270.115" + inkscape:lockguides="false" + inkscape:snap-grids="true"> + style="display:inline"> A fine piece of ship, managing to combinemovement speed and weapon precision @@ -1307,7 +1345,7 @@ transform="translate(0,30)"> - - - - - - + style="fill:#3f5a7d;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.64511573px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + + Avenger @@ -1395,7 +1417,7 @@ id="g12386" transform="translate(-3.7618713)"> + id="g14081" + inkscape:export-filename="/home/michael/workspace/spacetac/data/stage2/image/character/ship-column-left.png" + inkscape:export-xdpi="96" + inkscape:export-ydpi="96"> - - - + transform="translate(-0.77904,-50.000005)" /> @@ -1754,13 +1747,13 @@ x="0" /> Attributes Actions + style="font-size:21.33333397px;fill:#a3bbd9;fill-opacity:1">Actions - + + + + + + + + transform="rotate(90,435,830.24998)" /> + transform="matrix(1,0,0,-1,0,1660.5)" /> + transform="matrix(1,0,0,-1,3.0000002e-6,1660.5)" /> ... - Compose your initial teamby choosing a modelfor each ship, and customizethe name and personalityof the Artificial Intelligence pilot - Validate team + id="g7344" + transform="translate(-56.429011,-29.84612)"> - + style="fill:#1f282d;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + id="rect7253" + width="850" + height="550" + x="1006.429" + y="60" /> + + + + - - - - Courageous + style="font-size:32px;line-height:25px;text-align:center;text-anchor:middle;fill:#dbeff9;fill-opacity:1">Courageous Wise + style="font-size:32px;text-align:center;text-anchor:middle;fill:#dbeff9;fill-opacity:1">Wise + transform="translate(0,106)" + inkscape:export-filename="/home/michael/workspace/spacetac/data/stage2/image/character/personality-trait-base.png" + inkscape:export-xdpi="96" + inkscape:export-ydpi="96"> + style="fill:url(#radialGradient6270);fill-opacity:1;fill-rule:evenodd;stroke:#3a6479;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> Kind + style="font-size:32px;line-height:25px;fill:#dbeff9;fill-opacity:1">Kind Resilient + style="font-size:32px;text-align:center;text-anchor:middle;fill:#dbeff9;fill-opacity:1">Resilient Shrewd + style="font-size:32px;line-height:25px;text-align:center;text-anchor:middle;fill:#dbeff9;fill-opacity:1">Shrewd Funny + style="font-size:32px;text-align:center;text-anchor:middle;fill:#dbeff9;fill-opacity:1">Funny - + inkscape:export-ydpi="96"> + + + + + + + + + + Artana - - - - - - - - ... + - + id="g7371" + transform="translate(-3.168989,-4.471985)"> + + + + Pilot + x="1046.0613" + y="122.14172" + style="font-size:42.66666794px;fill:#dce9f9;fill-opacity:1">Pilot + + AI personality tweaker + + + + + + + + + + + + + + + + + + + + + + Compose your initial teamby choosing a modelfor each ship, and customizethe name and personalityof the Artificial Intelligence pilot + + + + Ship + + + + + + + Validate team + + + + + + + + + + + - Ship + transform="matrix(-1,0,0,1,867.4259,-2.9999999e-6)" /> + + + + + + + + + + + + + + + + + + + + + + + + + + - + 1 - 1 + 2 - 2 + 3 - 3 + 4 - 4 + 5 + 5 - 6 - 6 + 7 - 7 + 8 - 8 + 9 - 9 + 10 + y="1033.85" + id="text7309-3-1-9-55">10 + @@ -2608,7 +3043,7 @@ x="0" /> + style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#dce6ad;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + style="fill:none;fill-opacity:0.02765958;fill-rule:evenodd;stroke:#b0ba83;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> Hardened Hull + style="font-size:21.33333397px;fill:#dce9f9;fill-opacity:1">Hardened Hull SecondaryGatling @@ -2903,7 +3338,7 @@ style="display:inline" /> Gatling Gun + style="font-size:21.33333397px;line-height:15.27999938%;text-align:center;text-anchor:middle;fill:#dce9f9;fill-opacity:1">Gatling Gun 12 + style="font-size:29.33333397px;line-height:15.27999938%;text-align:center;text-anchor:middle;fill:#dce9f9;fill-opacity:1">12 12 @@ -3172,7 +3607,7 @@ x="630.97443" style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:64px;line-height:25px;font-family:DAGGERSQUARE;-inkscape-font-specification:DAGGERSQUARE;letter-spacing:0px;word-spacing:0px;display:inline;fill:#e7ebf0;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter13789)" xml:space="preserve"> Level 9 { + let up1 = { code: "test1" }; + let up2 = { code: "test2" }; + + let level = new ShipLevel(); + check.equals(level.getUpgrades(), []); + check.equals(level.hasUpgrade(up1), false); + + level.activateUpgrade(up1, true); + check.equals(level.getUpgrades(), ["test1"]); + check.equals(level.hasUpgrade(up1), true); + + level.activateUpgrade(up1, true); + check.equals(level.getUpgrades(), ["test1"]); + check.equals(level.hasUpgrade(up1), true); + + level.activateUpgrade(up1, false); + check.equals(level.getUpgrades(), []); + check.equals(level.hasUpgrade(up1), false); + + level.activateUpgrade(up1, true); + level.activateUpgrade(up2, true); + check.equals(level.getUpgrades(), ["test1", "test2"]); + level.clearUpgrades(); + check.equals(level.getUpgrades(), []); + }); }); } diff --git a/src/core/ShipLevel.ts b/src/core/ShipLevel.ts index 52c3b75..73368e1 100644 --- a/src/core/ShipLevel.ts +++ b/src/core/ShipLevel.ts @@ -108,5 +108,12 @@ module TK.SpaceTac { hasUpgrade(upgrade: ShipUpgrade): boolean { return contains(this.upgrades, upgrade.code); } + + /** + * Clear all activated upgrades + */ + clearUpgrades(): void { + this.upgrades = []; + } } } diff --git a/src/ui/battle/BattleView.ts b/src/ui/battle/BattleView.ts index 8c31fc0..5317da0 100644 --- a/src/ui/battle/BattleView.ts +++ b/src/ui/battle/BattleView.ts @@ -118,7 +118,7 @@ module TK.SpaceTac.UI { this.layer_borders, this.getWidth() - 112, 0); this.ship_list.bindToLog(this.log_processor); this.ship_tooltip = new ShipTooltip(this); - this.character_sheet = new CharacterSheet(this); + this.character_sheet = new CharacterSheet(this, CharacterSheetMode.DISPLAY); this.layer_sheets.add(this.character_sheet); // Targetting info @@ -286,7 +286,7 @@ module TK.SpaceTac.UI { if (this.targetting.active) { this.validationPressed(); } else if (this.ship_hovered && this.player.is(this.ship_hovered.fleet.player) && this.interacting) { - this.character_sheet.show(this.ship_hovered, CharacterSheetMode.DISPLAY); + this.character_sheet.show(this.ship_hovered); this.setShipHovered(null); } } diff --git a/src/ui/character/CharacterPersonality.ts b/src/ui/character/CharacterPersonality.ts new file mode 100644 index 0000000..7a59ca0 --- /dev/null +++ b/src/ui/character/CharacterPersonality.ts @@ -0,0 +1,67 @@ +module TK.SpaceTac.UI { + /** + * Character personality traits editor + */ + export class CharacterPersonality { + private view: BaseView + private background: UIImage + private name: UIText + private ship?: Ship + + constructor(builder: UIBuilder, x: number, y: number) { + this.view = builder.view; + + this.background = builder.image("character-personality-background", x, y); + builder = builder.in(this.background); + + builder.in(builder.image("character-section-title", 0, 0, false)).text("Pilot", 80, 45, { color: "#dce9f9", size: 32 }); + + this.name = builder.in(builder.image("character-name-display", 430, 50, true)).text("", 0, 0, { size: 28 }); + + builder.button("character-name-button", 664, 0, () => this.renamePersonality(), "Rename personality"); + + builder.text("AVAILABLE SOON !", 690, 528, { size: 20, color: "#a7b3db" }); + + builder.styled({ size: 24, color: "#dbeff9" }, builder => { + builder.image("character-personality-trait-base", 420, 198, true); + builder.text("Courageous", 144, 140); + builder.text("Wise", 725, 140); + + builder.image("character-personality-trait-base", 420, 316, true); + builder.text("Kind", 144, 268); + builder.text("Resilient", 725, 268); + + builder.image("character-personality-trait-base", 420, 444, true); + builder.text("Shrewd", 144, 388); + builder.text("Funny", 725, 388); + }); + } + + /** + * Change the content to display a ship's personality + */ + displayShip(ship: Ship) { + let builder = new UIBuilder(this.view); + this.ship = ship; + + builder.change(this.name, ship.name || ""); + } + + /** + * Open a dialog to rename the ship's personality + */ + renamePersonality(): void { + if (!this.ship) { + return; + } + let ship = this.ship; + + UITextDialog.ask(this.view, "Choose a name for this ship's personality", ship.name || undefined).then(name => { + if (bool(name)) { + ship.name = name; + this.displayShip(ship); + } + }); + } + } +} diff --git a/src/ui/character/CharacterSheet.spec.ts b/src/ui/character/CharacterSheet.spec.ts index 8756d70..5743c07 100644 --- a/src/ui/character/CharacterSheet.spec.ts +++ b/src/ui/character/CharacterSheet.spec.ts @@ -7,7 +7,7 @@ module TK.SpaceTac.UI.Specs { test.case("displays fleet and ship information", check => { let view = testgame.view; check.patch(view, "getWidth", () => 1240); - let sheet = new CharacterSheet(view); + let sheet = new CharacterSheet(view, CharacterSheetMode.DISPLAY); check.equals(sheet.x, -1240); @@ -17,40 +17,38 @@ module TK.SpaceTac.UI.Specs { let ship2 = fleet.addShip(); ship2.name = "Ship 2"; - sheet.show(ship1, undefined, false); + sheet.show(ship1, false); check.equals(sheet.x, 0); check.equals(sheet.group_portraits.length, 2); - check.equals(sheet.text_name.text, "Ship 1"); + check.equals(sheet.text_name && sheet.text_name.text, "Ship 1"); let portrait = as(Phaser.Button, sheet.group_portraits.getChildAt(1)); portrait.onInputUp.dispatch(); - check.equals(sheet.text_name.text, "Ship 2"); + check.equals(sheet.text_name && sheet.text_name.text, "Ship 2"); }); test.case("controls global interactivity state", check => { - let sheet = new CharacterSheet(testgame.view); + let sheet = new CharacterSheet(testgame.view, CharacterSheetMode.EDITION); check.equals(sheet.isInteractive(), false, "no ship"); let ship = new Ship(); ship.critical = true; - sheet.show(ship, CharacterSheetMode.EDITION); + sheet.show(ship); check.equals(sheet.isInteractive(), false, "critical ship"); ship.critical = false; - sheet.show(ship, CharacterSheetMode.EDITION); + sheet.show(ship); check.equals(sheet.isInteractive(), true, "normal ship"); - sheet.show(ship, CharacterSheetMode.DISPLAY); + sheet = new CharacterSheet(testgame.view, CharacterSheetMode.DISPLAY); + sheet.show(ship); check.equals(sheet.isInteractive(), false, "interactivity disabled"); - sheet.show(ship, CharacterSheetMode.DISPLAY); + sheet.show(ship); check.equals(sheet.isInteractive(), false, "interactivity stays disabled"); - - sheet.show(ship, CharacterSheetMode.EDITION); - check.equals(sheet.isInteractive(), true, "interactivity reenabled"); }); }); }); diff --git a/src/ui/character/CharacterSheet.ts b/src/ui/character/CharacterSheet.ts index a767c69..80ee9af 100644 --- a/src/ui/character/CharacterSheet.ts +++ b/src/ui/character/CharacterSheet.ts @@ -10,7 +10,7 @@ module TK.SpaceTac.UI { */ export class CharacterSheet extends Phaser.Image { // Global sheet mode - mode: CharacterSheetMode = CharacterSheetMode.DISPLAY + mode: CharacterSheetMode // Parent view view: BaseView @@ -18,20 +18,20 @@ module TK.SpaceTac.UI { // UI components builder builder: UIBuilder + // Close/validate button + close_button: UIButton + // X positions xshown = 0 xhidden = -2000 // Groups + group_level: Phaser.Group group_portraits: Phaser.Group group_attributes: Phaser.Image group_actions: Phaser.Image group_upgrades: Phaser.Group - // Buttons - close_button: UIButton - rename_button: UIButton - // Currently displayed fleet fleet?: Fleet @@ -39,33 +39,33 @@ module TK.SpaceTac.UI { ship?: Ship // Variable data + personality?: CharacterPersonality image_portrait: Phaser.Image text_model: Phaser.Text text_description: Phaser.Text - text_name: Phaser.Text + text_name?: Phaser.Text text_level: Phaser.Text text_upgrade_points: Phaser.Text valuebar_experience: ValueBar - constructor(view: BaseView, onclose?: Function) { + constructor(view: BaseView, mode: CharacterSheetMode, onclose?: Function) { super(view.game, 0, 0, view.getImageInfo("character-sheet").key, view.getImageInfo("character-sheet").frame); + if (!onclose) { + onclose = () => this.hide(); + } + this.view = view; - this.builder = new UIBuilder(view, this).styled({ color: "#e7ebf0", size: 16, shadow: true }); + this.mode = mode; + this.builder = new UIBuilder(view, this).styled({ color: "#dce9f9", size: 16, shadow: true }); this.xhidden = -this.view.getWidth(); this.x = this.xhidden; this.inputEnabled = true; - if (!onclose) { - onclose = () => this.hide(); - } - this.close_button = this.builder.button("character-close-button", 1920, 0, onclose, "Close the character sheet"); - this.close_button.anchor.set(1, 0); - this.image_portrait = this.builder.image("translucent", 435, 271, true); - this.builder.image("character-entry", 28, 740); + this.builder.image("character-entry", 24, 740); this.group_portraits = this.builder.group("portraits", 90, 755); @@ -75,27 +75,55 @@ module TK.SpaceTac.UI { let description_bg = this.builder.image("character-ship-description", 434, 654, true); this.text_description = this.builder.in(description_bg).text("", 0, 0, { color: "#a0afc3", width: 510 }); - this.group_attributes = this.builder.image("character-ship-column", 30, 30); - this.group_actions = this.builder.image("character-ship-column", 698, 30); + this.group_attributes = this.builder.image("character-ship-column-left", 28, 28); + this.group_actions = this.builder.image("character-ship-column-right", 698, 28); - let name_bg = this.builder.image("character-name-display", 434, 940, true); - this.text_name = this.builder.in(name_bg).text("", 0, 0, { size: 28 }); - - this.rename_button = this.builder.button("character-name-button", 656, 890, () => this.renamePersonality(), "Rename personality"); - - let points_bg = this.builder.image("character-level-upgrades", 582, 986); + this.group_level = this.builder.group("level"); + let points_bg = this.builder.in(this.group_level).image("character-level-upgrades", 582, 986); this.builder.in(points_bg, builder => { builder.text("Upgrade points", 46, 10, { center: false, vcenter: false }); builder.image("character-upgrade-point", 147, 59, true); }); this.text_upgrade_points = this.builder.in(points_bg).text("", 106, 60, { size: 28 }); - let level_bg = this.builder.image("character-level-display", 434, 1032, true); + let level_bg = this.builder.in(this.group_level).image("character-level-display", 434, 1032, true); this.text_level = this.builder.in(level_bg).text("", 0, 4, { size: 28 }); this.valuebar_experience = this.builder.in(level_bg).valuebar("character-level-experience", -level_bg.width * 0.5, -level_bg.height * 0.5); this.group_upgrades = this.builder.group("upgrades"); + if (this.mode == CharacterSheetMode.CREATION) { + this.builder.in(this.builder.image("character-section-title", 180, 30, false)).text("Ship", 80, 45, { color: "#dce9f9", size: 32 }); + + this.personality = new CharacterPersonality(this.builder, 950, 30); + + this.close_button = this.builder.button("character-validate-creation", 140, 930, onclose, + "Validate the team, and start the campaign", undefined, { + hover_bottom: true, + text: "Validate team", + text_x: 295, + text_y: 57, + text_style: { size: 32, color: "#fff3df" } + } + ); + + this.builder.in(this.builder.image("character-creation-help", 970, 680), builder => { + builder.text("Compose your initial team by choosing a model for each ship, and customize the name and personality of the Artificial Intelligence pilot", + 405, 150, { color: "#a3bbd9", size: 22, width: 500 }); + }); + + this.builder.button("character-model-prev", 216, 500, () => this.changeModel(-1), "Select previous model", undefined, { center: true }); + this.builder.button("character-model-next", 654, 500, () => this.changeModel(1), "Select next model", undefined, { center: true }); + + this.group_level.visible = false; + this.group_upgrades.visible = false; + } else { + this.text_name = this.builder.in(this.builder.image("character-name-display", 434, 940, true)).text("", 0, 0, { size: 28 }); + + this.close_button = this.builder.button("character-close-button", 1920, 0, onclose, "Close the character sheet"); + this.close_button.anchor.set(1, 0); + } + this.refreshUpgrades(); this.refreshAttributes(); this.refreshActions(); @@ -109,20 +137,22 @@ module TK.SpaceTac.UI { } /** - * Open a dialog to rename the ship's personality + * Change the ship model */ - renamePersonality(): void { - if (!this.ship) { - return; - } - let ship = this.ship; + changeModel(offset: number): void { + if (this.mode == CharacterSheetMode.CREATION && this.ship) { + let models = ShipModel.getDefaultCollection(); - UITextDialog.ask(this.view, "Choose a name for this ship's personality", ship.name || undefined).then(name => { - if (bool(name)) { - ship.name = name; - this.refreshShipInfo(); + let idx = models.map(model => model.code).indexOf(this.ship.model.code) + offset; + if (idx < 0) { + idx = models.length - 1; + } else if (idx >= models.length) { + idx = 0; } - }); + + this.ship.setModel(models[idx]); + this.refresh(); + } } /** @@ -132,13 +162,17 @@ module TK.SpaceTac.UI { if (this.ship) { let ship = this.ship; this.builder.change(this.image_portrait, `ship-${ship.model.code}-portrait`); - this.text_name.setText(ship.name || ""); + if (this.text_name) { + this.text_name.setText(ship.name || ""); + } + if (this.personality) { + this.personality.displayShip(ship); + } this.text_model.setText(ship.model.name); this.text_level.setText(`Level ${ship.level.get()}`); this.text_description.setText(ship.model.getDescription()); this.text_upgrade_points.setText(`${ship.getAvailableUpgradePoints()}`); this.valuebar_experience.setValue(ship.level.getExperience(), ship.level.getNextGoal()); - this.rename_button.visible = this.mode == CharacterSheetMode.CREATION; } } @@ -149,7 +183,7 @@ module TK.SpaceTac.UI { let builder = this.builder.in(this.group_upgrades); builder.clear(); - if (!this.ship) { + if (!this.ship || this.mode == CharacterSheetMode.CREATION) { return; } let ship = this.ship; @@ -196,7 +230,7 @@ module TK.SpaceTac.UI { center: true, vcenter: true, size: 28, - color: ship.level.get() >= (i + 1) ? "#e7ebf0" : "#808285" + color: ship.level.get() >= (i + 1) ? "#dce9f9" : "#293038" }); }); @@ -225,7 +259,7 @@ module TK.SpaceTac.UI { let builder = this.builder.in(this.group_attributes); builder.clear(); - builder.text("Attributes", 74, 20, { color: "#a0afc3" }); + builder.text("Attributes", 74, 20, { color: "#a3bbd9" }); if (this.ship) { let ship = this.ship; @@ -248,7 +282,7 @@ module TK.SpaceTac.UI { let builder = this.builder.in(this.group_actions); builder.clear(); - builder.text("Actions", 74, 20, { color: "#a0afc3" }); + builder.text("Actions", 74, 20, { color: "#a3bbd9" }); if (this.ship) { let ship = this.ship; @@ -265,20 +299,20 @@ module TK.SpaceTac.UI { } /** - * Update the fleet sidebar + * Refresh the fleet display */ - updateFleet(fleet: Fleet) { - if (fleet !== this.fleet || fleet.ships.length != this.group_portraits.length) { - destroyChildren(this.group_portraits); - this.fleet = fleet; + private refreshFleet(): void { + destroyChildren(this.group_portraits); + if (this.fleet) { let builder = this.builder.in(this.group_portraits); - fleet.ships.forEach((ship, idx) => { + this.fleet.ships.forEach((ship, idx) => { let button: UIButton; button = new CharacterPortrait(ship).draw(builder, 64 + idx * 140, 64, () => { if (button) { builder.select(button); this.ship = ship; + this.refreshShipInfo(); this.refreshActions(); this.refreshAttributes(); @@ -303,16 +337,18 @@ module TK.SpaceTac.UI { /** * Show the sheet for a given ship */ - show(ship: Ship, mode: CharacterSheetMode = CharacterSheetMode.DISPLAY, animate = true, sound = true) { + show(ship: Ship, animate = true, sound = true) { this.ship = ship; - this.mode = mode; + this.fleet = ship.fleet; this.refreshShipInfo(); this.refreshUpgrades(); this.refreshAttributes(); this.refreshActions(); - this.updateFleet(ship.fleet); + if (ship.fleet !== this.fleet || ship.fleet.ships.length != this.group_portraits.length) { + this.refreshFleet(); + } if (sound) { this.view.audio.playOnce("ui-dialog-open"); @@ -343,7 +379,12 @@ module TK.SpaceTac.UI { */ refresh() { if (this.ship) { - this.show(this.ship, this.mode, false, false); + this.refreshShipInfo(); + this.refreshUpgrades(); + this.refreshAttributes(); + this.refreshActions(); + + this.refreshFleet(); } } } diff --git a/src/ui/character/FleetCreationView.ts b/src/ui/character/FleetCreationView.ts index 606f799..88fe216 100644 --- a/src/ui/character/FleetCreationView.ts +++ b/src/ui/character/FleetCreationView.ts @@ -19,8 +19,8 @@ module TK.SpaceTac.UI { this.built_fleet.addShip(new Ship(null, MissionGenerator.generateCharacterName(), models[1])); this.built_fleet.credits = this.built_fleet.ships.length * 1000; - this.character_sheet = new CharacterSheet(this, () => this.validateFleet()); - this.character_sheet.show(this.built_fleet.ships[0], CharacterSheetMode.CREATION, false); + this.character_sheet = new CharacterSheet(this, CharacterSheetMode.CREATION, () => this.validateFleet()); + this.character_sheet.show(this.built_fleet.ships[0], false); this.getLayer("characters").add(this.character_sheet); } diff --git a/src/ui/common/UIBuilder.ts b/src/ui/common/UIBuilder.ts index 735fcbe..341c26f 100644 --- a/src/ui/common/UIBuilder.ts +++ b/src/ui/common/UIBuilder.ts @@ -58,18 +58,35 @@ module TK.SpaceTac.UI { * Button options */ export type UIButtonOptions = { + // Centering + center?: boolean + // Name of the hover picture (by default, the button name, with "-hover" appended) hover_name?: string // Name of the "on" picture (by default, the button name, with "-on" appended) on_name?: string + + // Whether "hover" picture should stay near the button (otherwise will be on top) + hover_bottom?: boolean + + // Whether "on" picture should stay near the button (otherwise will be on top) + on_bottom?: boolean + + // Text content + text?: string + text_x?: number + text_y?: number + + // Text content style override + text_style?: UITextStyleI } /** * Main UI builder tool */ export class UIBuilder { - private view: BaseView + view: BaseView private game: MainUI private parent: UIContainer private text_style: UITextStyle @@ -201,6 +218,10 @@ module TK.SpaceTac.UI { let result = new Phaser.Button(this.game, x, y, info.key, undefined, null, info.frame, info.frame); result.name = name; + if (options.center) { + result.anchor.set(0.5); + } + let clickable = bool(onclick); result.input.useHandCursor = clickable; if (clickable) { @@ -216,7 +237,7 @@ module TK.SpaceTac.UI { let on_info = this.view.getImageInfo(options.on_name || (name + "-on")); if (on_info.exists) { on_mask = new Phaser.Image(this.game, 0, 0, on_info.key, on_info.frame); - on_mask.name = "*on*"; + on_mask.name = options.on_bottom ? "on" : "*on*"; on_mask.visible = false; result.addChild(on_mask); } @@ -236,7 +257,7 @@ module TK.SpaceTac.UI { let hover_mask: Phaser.Image | null = null; if (hover_info.exists) { hover_mask = new Phaser.Image(this.game, 0, 0, hover_info.key, hover_info.frame); - hover_mask.name = "*hover*"; + hover_mask.name = options.hover_bottom ? "hover" : "*hover*"; hover_mask.visible = false; result.addChild(hover_mask); } @@ -268,6 +289,10 @@ module TK.SpaceTac.UI { }, 100); } + if (options.text) { + this.in(result).text(options.text, options.text_x || 0, options.text_y || 0, options.text_style); + } + this.add(result); return result; } diff --git a/src/ui/map/UniverseMapView.ts b/src/ui/map/UniverseMapView.ts index b6ad689..7dcde3f 100644 --- a/src/ui/map/UniverseMapView.ts +++ b/src/ui/map/UniverseMapView.ts @@ -113,7 +113,7 @@ module TK.SpaceTac.UI { this.button_options = builder.button("map-options", 1628, 0, () => this.showOptions(), "Game options"); }); - this.character_sheet = new CharacterSheet(this); + this.character_sheet = new CharacterSheet(this, CharacterSheetMode.EDITION); this.layer_overlay.add(this.character_sheet); this.conversation = new MissionConversationDisplay(this); @@ -165,7 +165,7 @@ module TK.SpaceTac.UI { this.backToRouter(); } else { this.setZoom(this.zoom); - this.character_sheet.updateFleet(this.player.fleet); + this.character_sheet.refresh(); this.player_fleet.updateShipSprites(); } } @@ -310,7 +310,7 @@ module TK.SpaceTac.UI { openShop(): void { let location = this.session.getLocation(); if (this.interactive && location && location.shop) { - this.character_sheet.show(this.player.fleet.ships[0], CharacterSheetMode.EDITION); + this.character_sheet.show(this.player.fleet.ships[0]); } }