diff --git a/TODO.md b/TODO.md index 68f2060..d20da42 100644 --- a/TODO.md +++ b/TODO.md @@ -12,7 +12,6 @@ Menu/settings/saves Map/story --------- -* Initial contact has no equipment, and dies immediately in the first fight * Add sound effects and more visual effects (jumps...) * Add factions and reputation * Allow to cancel secondary missions diff --git a/graphics/exported/character/random-off.png b/graphics/exported/character/random-off.png new file mode 100644 index 0000000..2cf3713 Binary files /dev/null and b/graphics/exported/character/random-off.png differ diff --git a/graphics/exported/character/random-on.png b/graphics/exported/character/random-on.png new file mode 100644 index 0000000..643a80c Binary files /dev/null and b/graphics/exported/character/random-on.png differ diff --git a/graphics/exported/character/rename-off.png b/graphics/exported/character/rename-off.png new file mode 100644 index 0000000..25ab2ca Binary files /dev/null and b/graphics/exported/character/rename-off.png differ diff --git a/graphics/exported/character/rename-on.png b/graphics/exported/character/rename-on.png new file mode 100644 index 0000000..5df07e8 Binary files /dev/null and b/graphics/exported/character/rename-on.png differ diff --git a/graphics/exported/character/validate.png b/graphics/exported/character/validate.png new file mode 100644 index 0000000..6bf0b1a Binary files /dev/null and b/graphics/exported/character/validate.png differ diff --git a/graphics/ui/character.svg b/graphics/ui/character.svg index ebed785..a0de0fc 100644 --- a/graphics/ui/character.svg +++ b/graphics/ui/character.svg @@ -24,6 +24,32 @@ inkscape:export-ydpi="96"> + + + + + + @@ -586,6 +612,136 @@ y1="227.4481" x2="106.11795" y2="227.4481" /> + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml - + @@ -1788,4 +1944,140 @@ sodipodi:role="line">X + + + + + + + + + + + + ? + + + + + ... + + + + + OK + + diff --git a/src/core/Equipment.ts b/src/core/Equipment.ts index 0ae4b68..5d39a61 100644 --- a/src/core/Equipment.ts +++ b/src/core/Equipment.ts @@ -61,7 +61,7 @@ module TK.SpaceTac { } jasmineToString() { - return this.attached_to ? `${this.attached_to.ship.getFullName()} - ${this.name}` : this.name; + return this.attached_to ? `${this.attached_to.ship.getName()} - ${this.name}` : this.name; } /** diff --git a/src/core/Fleet.ts b/src/core/Fleet.ts index cfa9ae9..961b6c5 100644 --- a/src/core/Fleet.ts +++ b/src/core/Fleet.ts @@ -26,7 +26,7 @@ module TK.SpaceTac { } jasmineToString(): string { - return `${this.player.name}'s fleet [${this.ships.map(ship => ship.getFullName()).join(",")}]`; + return `${this.player.name}'s fleet [${this.ships.map(ship => ship.getName()).join(",")}]`; } /** diff --git a/src/core/Ship.spec.ts b/src/core/Ship.spec.ts index 3d78524..737b27c 100644 --- a/src/core/Ship.spec.ts +++ b/src/core/Ship.spec.ts @@ -2,16 +2,20 @@ module TK.SpaceTac.Specs { testing("Ship", test => { test.case("creates a full name", check => { let ship = new Ship(); - check.equals(ship.getFullName(false), "Level 1 unnamed"); + check.equals(ship.getName(false), "Ship"); + check.equals(ship.getName(true), "Level 1 Ship"); - ship.name = "Titan"; - check.equals(ship.getFullName(false), "Level 1 Titan"); + ship.model = new ShipModel("test", "Hauler"); + check.equals(ship.getName(false), "Hauler"); + check.equals(ship.getName(true), "Level 1 Hauler"); + + ship.name = "Titan-W12"; + check.equals(ship.getName(false), "Titan-W12"); + check.equals(ship.getName(true), "Level 1 Titan-W12"); ship.level.forceLevel(3); - check.equals(ship.getFullName(false), "Level 3 Titan"); - - ship.fleet.player.name = "Emperor"; - check.equals(ship.getFullName(true), "Emperor's Level 3 Titan"); + check.equals(ship.getName(false), "Titan-W12"); + check.equals(ship.getName(true), "Level 3 Titan-W12"); }); test.case("moves in the arena", check => { diff --git a/src/core/Ship.ts b/src/core/Ship.ts index ac229eb..696565e 100644 --- a/src/core/Ship.ts +++ b/src/core/Ship.ts @@ -12,8 +12,8 @@ module TK.SpaceTac { level = new ShipLevel() skills = new ShipSkills() - // Name of the ship - name: string + // Name of the ship, null if unimportant + name: string | null // Code of the ShipModel used to create it model: ShipModel @@ -57,7 +57,7 @@ module TK.SpaceTac { play_priority = 0; // Create a new ship inside a fleet - constructor(fleet: Fleet | null = null, name = "unnamed", model = new ShipModel("default", "Default", 1, 0, false, 0)) { + constructor(fleet: Fleet | null = null, name: string | null = null, model = new ShipModel("default", "Ship", 1, 0, false, 0)) { super(); this.fleet = fleet || new Fleet(); @@ -84,11 +84,11 @@ module TK.SpaceTac { } /** - * Returns the full name of this ship + * Returns the name of this ship */ - getFullName(owner = true): string { - let result = `Level ${this.level.get()} ${this.name}`; - return owner ? `${this.fleet.player.name}'s ${result}` : result; + getName(level = true): string { + let name = this.name || this.model.name; + return level ? `Level ${this.level.get()} ${name}` : name; } // Returns true if the ship is able to play diff --git a/src/core/ShipGenerator.spec.ts b/src/core/ShipGenerator.spec.ts index 1235342..a67fa63 100644 --- a/src/core/ShipGenerator.spec.ts +++ b/src/core/ShipGenerator.spec.ts @@ -3,7 +3,7 @@ module TK.SpaceTac.Specs { test.case("can use ship model", check => { var gen = new ShipGenerator(); var model = new ShipModel("test", "Test", 1, 2, true, 3); - var ship = gen.generate(1, model); + var ship = gen.generate(1, model, false); check.same(ship.model, model); check.equals(ship.cargo_space, 2); check.equals(ship.slots.length, 7); diff --git a/src/core/ShipGenerator.ts b/src/core/ShipGenerator.ts index 9ddd230..83d5ab9 100644 --- a/src/core/ShipGenerator.ts +++ b/src/core/ShipGenerator.ts @@ -17,7 +17,7 @@ module TK.SpaceTac { * * If *force_damage_equipment, at least one "damaging" weapon will be chosen */ - generate(level: number, model: ShipModel | null = null, upgrade = false, force_damage_equipment = true): Ship { + generate(level: number, model: ShipModel | null = null, upgrade = true, force_damage_equipment = true): Ship { if (!model) { // Get a random model model = ShipModel.getRandomModel(level, this.random); diff --git a/src/core/missions/MainStory.spec.ts b/src/core/missions/MainStory.spec.ts index 748c946..f753f9a 100644 --- a/src/core/missions/MainStory.spec.ts +++ b/src/core/missions/MainStory.spec.ts @@ -43,6 +43,8 @@ module TK.SpaceTac.Specs { checkPart(story, 3, /^Go with .* in .* system$/); check.same(fleet.ships.length, fleet_size + 1); + check.same(fleet.ships[fleet_size].critical, true); + check.greater(fleet.ships[fleet_size].getAttribute("hull_capacity"), 0); goTo(fleet, (story.current_part).destination); checkPart(story, 4, /^Listen to .*$/); diff --git a/src/core/missions/MainStory.ts b/src/core/missions/MainStory.ts index 0149a4d..5971c75 100644 --- a/src/core/missions/MainStory.ts +++ b/src/core/missions/MainStory.ts @@ -15,6 +15,7 @@ module TK.SpaceTac { let random = RandomGenerator.global; let start_location = nn(fleet.location); + let mission_generator = new MissionGenerator(universe, start_location); // Arrival let conversation = this.addPart(new MissionPartConversation(this, [], "Travel to Terranax galaxy")); @@ -24,7 +25,7 @@ module TK.SpaceTac { // Get in touch with our contact let contact_location = randomLocation(random, [start_location.star], [start_location]); - let contact_character = new Ship(null, "Osten-37", ShipModel.getRandomModel(1, random)); + let contact_character = mission_generator.generateShip(1); contact_character.fleet.setLocation(contact_location, true); this.addPart(new MissionPartGoTo(this, contact_location, `Find your contact in ${contact_location.star.name}`, MissionPartDestinationHint.SYSTEM)); conversation = this.addPart(new MissionPartConversation(this, [contact_character], "Speak with your contact")); diff --git a/src/core/missions/MissionGenerator.ts b/src/core/missions/MissionGenerator.ts index cfc4b00..fe123ab 100644 --- a/src/core/missions/MissionGenerator.ts +++ b/src/core/missions/MissionGenerator.ts @@ -1,17 +1,17 @@ module TK.SpaceTac { const POOL_SHIP_NAMES = [ - "Zert", - "Ob'tec", - "Paayk", - "Fen_amr", - "TempZst", - "croNt", - "Appn", - "Vertix", - "Opan-vel", - "Yz-aol", - "Arkant", - "PNX", + "Zert", "Zark", "Zeem", + "Ob'tec", "Ob'vac", "Ob'sig", + "Paayk", "Paakt", + "Fen_amr", "Fin_am", "Fen_AA", + "TempZst", "TriZth", + "croNt", "coRzt", + "Appn", "Appq", + "Vertix", "Vortix", + "Opan-vel", "Ipal-ven", "Epan-vek", + "Yz-aol", "Yz-aib", + "Arkant", "Arkyan", + "PNX", "PGV", "PXT", "PRZ", ] /** @@ -47,13 +47,20 @@ module TK.SpaceTac { return result; } + /** + * Generate a character name + */ + static generateCharacterName(random = RandomGenerator.global): string { + return `${random.choice(POOL_SHIP_NAMES)}-${random.randInt(10, 999)}`; + } + /** * Generate a new ship that may be used in a mission */ generateShip(level: number) { let generator = new ShipGenerator(this.random); let result = generator.generate(level, null, true); - result.name = `${this.random.choice(POOL_SHIP_NAMES)}-${this.random.randInt(10, 999)}`; + result.name = MissionGenerator.generateCharacterName(this.random); return result; } diff --git a/src/ui/battle/ShipTooltip.spec.ts b/src/ui/battle/ShipTooltip.spec.ts index a7b60a5..e9ff635 100644 --- a/src/ui/battle/ShipTooltip.spec.ts +++ b/src/ui/battle/ShipTooltip.spec.ts @@ -27,7 +27,7 @@ module TK.SpaceTac.UI.Specs { check.contains(images, "ship-fake-portrait"); check.contains(images, "equipment-equipment"); check.equals(texts, [ - "Phil's Level 1 Fury", "Plays in 2 turns", + "Level 1 Fury", "Plays in 2 turns", "7", "3", "9", "max", "12", "57", "max", "58", "100", "max", "140", "Active effects", "• hull capacity +50", "• damage -15% for 3 turns", "• limit precision to 10", "Weapons", "equipment Mk1" diff --git a/src/ui/battle/ShipTooltip.ts b/src/ui/battle/ShipTooltip.ts index 0373961..0514576 100644 --- a/src/ui/battle/ShipTooltip.ts +++ b/src/ui/battle/ShipTooltip.ts @@ -31,7 +31,7 @@ module TK.SpaceTac.UI { }); let enemy = !ship.getPlayer().is(this.battleview.player); - builder.text(ship.getFullName(), 168, 0, { color: enemy ? "#cc0d00" : "#ffffff", size: 22, bold: true }); + builder.text(ship.getName(), 168, 0, { color: enemy ? "#cc0d00" : "#ffffff", size: 22, bold: true }); if (ship.alive) { let turns = this.battleview.battle.getPlayOrder(ship); diff --git a/src/ui/character/CharacterFleetMember.ts b/src/ui/character/CharacterFleetMember.ts index 1643ff2..ee32497 100644 --- a/src/ui/character/CharacterFleetMember.ts +++ b/src/ui/character/CharacterFleetMember.ts @@ -26,7 +26,7 @@ module TK.SpaceTac.UI { this.levelup.visible = this.ship.getAvailableUpgradePoints() > 0; this.addChild(this.levelup); - sheet.view.tooltip.bindDynamicText(this, () => ship.getFullName()); + sheet.view.tooltip.bindDynamicText(this, () => ship.getName()); } /** diff --git a/src/ui/character/CharacterSheet.spec.ts b/src/ui/character/CharacterSheet.spec.ts index 48c68ba..9cf3044 100644 --- a/src/ui/character/CharacterSheet.spec.ts +++ b/src/ui/character/CharacterSheet.spec.ts @@ -28,14 +28,14 @@ module TK.SpaceTac.UI.Specs { check.equals(sheet.x, 0); check.equals(sheet.portraits.length, 2); - check.equals(sheet.ship_name.text, "Player's Level 1 Ship 1"); + check.equals(sheet.ship_name.text, "Ship 1"); check.equals(sheet.ship_slots.length, 4); check.equals(sheet.ship_cargo.length, 3); let portrait = sheet.portraits.getChildAt(1); portrait.onInputUp.dispatch(); - check.equals(sheet.ship_name.text, "Player's Level 1 Ship 2"); + check.equals(sheet.ship_name.text, "Ship 2"); check.equals(sheet.ship_slots.length, 1); check.equals(sheet.ship_cargo.length, 2); }); @@ -126,7 +126,7 @@ module TK.SpaceTac.UI.Specs { ship.critical = true; sheet.show(ship); check.equals(sheet.isInteractive(), false, "critical ship"); - + ship.critical = false; sheet.show(ship); check.equals(sheet.isInteractive(), true, "normal ship"); @@ -139,7 +139,7 @@ module TK.SpaceTac.UI.Specs { sheet.show(ship, undefined, undefined, true); check.equals(sheet.isInteractive(), true, "interactivity reenabled"); - }); + }); }); test.case("fits slots in area", check => { diff --git a/src/ui/character/CharacterSheet.ts b/src/ui/character/CharacterSheet.ts index a9353a9..68339d2 100644 --- a/src/ui/character/CharacterSheet.ts +++ b/src/ui/character/CharacterSheet.ts @@ -216,7 +216,7 @@ module TK.SpaceTac.UI { let upgrade_points = ship.getAvailableUpgradePoints(); - this.ship_name.setText(ship.getFullName()); + this.ship_name.setText(ship.getName(false)); this.ship_level.setText(ship.level.get().toString()); this.ship_experience.setValue(ship.level.getExperience(), ship.level.getNextGoal()); this.ship_upgrade_points.setText(upgrade_points.toString()); diff --git a/src/ui/character/FleetCreationView.ts b/src/ui/character/FleetCreationView.ts index e1e9c34..6e96390 100644 --- a/src/ui/character/FleetCreationView.ts +++ b/src/ui/character/FleetCreationView.ts @@ -15,8 +15,8 @@ module TK.SpaceTac.UI { let models = ShipModel.getRandomModels(2); this.built_fleet = new Fleet(); - this.built_fleet.addShip(new Ship(null, "First", models[0])); - this.built_fleet.addShip(new Ship(null, "Second", models[1])); + this.built_fleet.addShip(new Ship(null, MissionGenerator.generateCharacterName(), models[0])); + this.built_fleet.addShip(new Ship(null, MissionGenerator.generateCharacterName(), models[1])); this.built_fleet.credits = this.built_fleet.ships.length * 1000; let basic_equipments = () => { diff --git a/src/ui/common/UIConversation.ts b/src/ui/common/UIConversation.ts index c2b6163..803ca62 100644 --- a/src/ui/common/UIConversation.ts +++ b/src/ui/common/UIConversation.ts @@ -136,7 +136,7 @@ module TK.SpaceTac.UI { setCurrentShipMessage(ship: Ship, content: string): void { let style = new UIConversationStyle(); style.image = `ship-${ship.model.code}-portrait`; - style.image_caption = ship.name; + style.image_caption = ship.getName(false); style.image_size = 256; let own = ship.getPlayer() == this.view.gameui.session.player;