diff --git a/TODO b/TODO
index a5a0105..673be91 100644
--- a/TODO
+++ b/TODO
@@ -3,4 +3,3 @@
* Add retreat from battle
* Refactor the tooltip system to use it more
* Flash ship icons that receive damage
-* Add a ship model system
\ No newline at end of file
diff --git a/src/app/game/Ship.ts b/src/app/game/Ship.ts
index 3aaa7c4..8b6d1d3 100644
--- a/src/app/game/Ship.ts
+++ b/src/app/game/Ship.ts
@@ -14,6 +14,9 @@ module SpaceTac.Game {
// Name of the ship
name: string;
+ // Code of the ShipModel used to create it
+ model: string;
+
// Flag indicating if the ship is alive
alive: boolean;
@@ -67,6 +70,7 @@ module SpaceTac.Game {
this.fleet = fleet || new Fleet();
this.level = 1;
this.name = name;
+ this.model = "default";
this.alive = true;
this.initiative = this.newAttribute(AttributeCode.Initiative);
this.initiative.setMaximal(1);
diff --git a/src/app/game/ShipGenerator.ts b/src/app/game/ShipGenerator.ts
index 3706c48..69994fb 100644
--- a/src/app/game/ShipGenerator.ts
+++ b/src/app/game/ShipGenerator.ts
@@ -13,16 +13,20 @@ module SpaceTac.Game {
// Generate a ship of a given level
// The ship will not be named, nor will be a member of any fleet
- generate(level: number): Ship {
+ generate(level: number, model: ShipModel = null): Ship {
var result = new Ship();
var loot = new LootGenerator(this.random);
- // Add equipment slots
- result.addSlot(SlotType.Armor);
- result.addSlot(SlotType.Engine);
- result.addSlot(SlotType.Power);
- result.addSlot(SlotType.Shield);
- result.addSlot(SlotType.Weapon);
+ if (!model) {
+ // Get a random model
+ model = ShipModel.getRandomModel(level, this.random);
+ }
+
+ // Apply model
+ result.model = model.code;
+ model.slots.forEach((slot: SlotType) => {
+ result.addSlot(slot);
+ });
// Fill equipment slots
result.slots.forEach((slot: Slot) => {
diff --git a/src/app/game/ShipModel.ts b/src/app/game/ShipModel.ts
new file mode 100644
index 0000000..5a4c9c3
--- /dev/null
+++ b/src/app/game/ShipModel.ts
@@ -0,0 +1,48 @@
+module SpaceTac.Game {
+ "use strict";
+
+ // A model of ship
+ // It defines the ship looks, and available slots for equipment
+ export class ShipModel {
+ // Code to identify the model
+ code: string;
+
+ // Minimal level to use this model
+ level: number;
+
+ // Available slots
+ slots: SlotType[];
+
+ constructor(code: string, level: number, ...slots: SlotType[]) {
+ this.code = code;
+ this.level = level;
+ this.slots = slots;
+ }
+
+ // Get the default ship model collection available in-game
+ static getDefaultCollection(): ShipModel[] {
+ // TODO Store in cache
+ var result = [];
+
+ result.push(new ShipModel("scout", 1, SlotType.Armor, SlotType.Engine, SlotType.Power, SlotType.Weapon));
+
+ result.push(new ShipModel("whirlwind", 1, SlotType.Armor, SlotType.Engine, SlotType.Power, SlotType.Shield,
+ SlotType.Weapon, SlotType.Weapon));
+
+ return result;
+ }
+
+ // Pick a random model in the default collection
+ static getRandomModel(level: Number, random: RandomGenerator = new RandomGenerator()): ShipModel {
+ var collection = this.getDefaultCollection();
+ collection = collection.filter((model: ShipModel) => {
+ return model.level <= level;
+ });
+ var result = random.choice(collection);
+ if (!result) {
+ console.error("Couldn't pick a random model for level " + level.toString());
+ }
+ return result;
+ }
+ }
+}
diff --git a/src/app/game/specs/Ship.spec.ts b/src/app/game/specs/Ship.spec.ts
index 8efbc38..4f75721 100644
--- a/src/app/game/specs/Ship.spec.ts
+++ b/src/app/game/specs/Ship.spec.ts
@@ -1,6 +1,6 @@
///
-module SpaceTac.Game {
+module SpaceTac.Game.Specs {
"use strict";
describe("Ship", function () {
diff --git a/src/app/game/specs/ShipGenerator.spec.ts b/src/app/game/specs/ShipGenerator.spec.ts
new file mode 100644
index 0000000..ac35afa
--- /dev/null
+++ b/src/app/game/specs/ShipGenerator.spec.ts
@@ -0,0 +1,18 @@
+///
+
+module SpaceTac.Game.Specs {
+ "use strict";
+
+ describe("ShipGenerator", function () {
+ it("can use ship model", function () {
+ var gen = new ShipGenerator();
+ var model = new ShipModel("test", 1, SlotType.Shield, SlotType.Weapon, SlotType.Weapon);
+ var ship = gen.generate(1, model);
+ expect(ship.model).toBe("test");
+ expect(ship.slots.length).toBe(3);
+ expect(ship.slots[0].type).toBe(SlotType.Shield);
+ expect(ship.slots[1].type).toBe(SlotType.Weapon);
+ expect(ship.slots[2].type).toBe(SlotType.Weapon);
+ });
+ });
+}
diff --git a/src/app/view/battle/ArenaShip.ts b/src/app/view/battle/ArenaShip.ts
index 5b8df18..31422c4 100644
--- a/src/app/view/battle/ArenaShip.ts
+++ b/src/app/view/battle/ArenaShip.ts
@@ -22,7 +22,7 @@ module SpaceTac.View {
super(battleview.game);
// Add ship sprite
- this.sprite = new Phaser.Button(battleview.game, 0, 0, "ship-scout-sprite");
+ this.sprite = new Phaser.Button(battleview.game, 0, 0, "ship-" + ship.model + "-sprite");
this.sprite.rotation = ship.arena_angle;
this.sprite.anchor.set(0.5, 0.5);
this.addChild(this.sprite);
diff --git a/src/app/view/battle/ShipListItem.ts b/src/app/view/battle/ShipListItem.ts
index 0c4db4c..6c877c6 100644
--- a/src/app/view/battle/ShipListItem.ts
+++ b/src/app/view/battle/ShipListItem.ts
@@ -41,7 +41,7 @@ module SpaceTac.View {
this.layer_base = new Phaser.Image(this.game, 0, 0, "battle-shiplist-base", 0);
this.addChild(this.layer_base);
- this.layer_portrait = new Phaser.Image(this.game, 30, 30, "ship-scout-portrait", 0);
+ this.layer_portrait = new Phaser.Image(this.game, 30, 30, "ship-" + ship.model + "-portrait", 0);
this.layer_portrait.anchor.set(0.5, 0.5);
this.layer_portrait.scale.set(0.19, 0.19);
this.addChild(this.layer_portrait);