diff --git a/graphics/ui/map.svg b/graphics/ui/map.svg
index 3586ea9..3d45445 100644
--- a/graphics/ui/map.svg
+++ b/graphics/ui/map.svg
@@ -811,8 +811,8 @@
style="color-interpolation-filters:sRGB"
inkscape:label="Drop Shadow"
id="filter7229-3"
- x="-0.2"
- y="-0.2"
+ x="-0.25"
+ y="-0.25"
height="1.5"
width="1.5">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ inkscape:snap-global="false"
+ inkscape:snap-object-midpoints="true"
+ inkscape:measure-start="551.543,453.963"
+ inkscape:measure-end="1261.48,449.72">
+
+
+
+
+
+ X
+
+ Active jobs
+ Proposed jobs
+
+
+
+ Escort a merchant transport to Rhinard
+ Reward : 500 zotys
+
+
+
+
+
+ Deliver an item to the FTC contact in Suburbia
+ Reward : Legendary SubMunition Missile Mk4
+
+
+ Cannot accept more missions
+
+
+
+
+
+ Cancel
+
+
+
+
+
+
+ Deliver an item to the FTC contact in Suburbia
+ Reward : Legendary SubMunition Missile Mk4
+
+
+
+
+
+ Deliver an item to the FTC contact in Suburbia
+ Reward : Legendary SubMunition Missile Mk4
+
+
+
+
+
+ Deliver an item to the FTC contact in Suburbia
+ Reward : Legendary SubMunition Missile Mk4
+
+
+
+ Accept
+
+
+
+
+
+
+
+
+
+
diff --git a/out/assets/images/common/dialog.png b/out/assets/images/common/dialog.png
new file mode 100644
index 0000000..8a66288
Binary files /dev/null and b/out/assets/images/common/dialog.png differ
diff --git a/out/assets/images/map/mission-action.png b/out/assets/images/map/mission-action.png
new file mode 100644
index 0000000..a4ede33
Binary files /dev/null and b/out/assets/images/map/mission-action.png differ
diff --git a/src/core/NameGenerator.ts b/src/core/NameGenerator.ts
index f2c6ba8..36d93c2 100644
--- a/src/core/NameGenerator.ts
+++ b/src/core/NameGenerator.ts
@@ -8,7 +8,7 @@ module TS.SpaceTac {
private random: RandomGenerator;
constructor(choices: string[], random: RandomGenerator = new RandomGenerator()) {
- this.choices = choices.slice(0);
+ this.choices = acopy(choices);
this.random = random;
}
diff --git a/src/core/Shop.spec.ts b/src/core/Shop.spec.ts
index ea86cbd..1dda8a6 100644
--- a/src/core/Shop.spec.ts
+++ b/src/core/Shop.spec.ts
@@ -31,5 +31,41 @@ module TS.SpaceTac.Specs {
expect(shop.stock).toEqual([equ1, equ2]);
expect(fleet.credits).toEqual(1000);
});
+
+ it("generates secondary missions", function () {
+ let universe = new Universe();
+ universe.generate(4);
+ let start = universe.getStartLocation();
+
+ let shop = new Shop();
+ expect((shop).missions.length).toBe(0);
+
+ let result = shop.getMissions(start, 4);
+ expect(result.length).toBe(4);
+ expect((shop).missions.length).toBe(4);
+
+ let oresult = shop.getMissions(start, 4);
+ expect(oresult).toEqual(result);
+
+ result.forEach(mission => {
+ expect(mission.main).toBe(false);
+ });
+ });
+
+ it("assigns missions to a fleet", function () {
+ let shop = new Shop();
+ let player = new Player();
+ let mission = new Mission(new Universe());
+ (shop).missions = [mission];
+
+ expect(shop.getMissions(new StarLocation(), 1)).toEqual([mission]);
+ expect(player.missions.secondary).toEqual([]);
+
+ shop.acceptMission(mission, player);
+
+ expect((shop).missions).toEqual([]);
+ expect(player.missions.secondary).toEqual([mission]);
+ expect(mission.fleet).toBe(player.fleet);
+ });
});
}
diff --git a/src/core/Shop.ts b/src/core/Shop.ts
index a0c71a3..5f94786 100644
--- a/src/core/Shop.ts
+++ b/src/core/Shop.ts
@@ -15,6 +15,9 @@ module TS.SpaceTac {
// Random generator
private random: RandomGenerator
+ // Available missions
+ private missions: Mission[] = []
+
constructor(level = 1, stock: Equipment[] = [], count = 40) {
this.level = level;
this.stock = stock;
@@ -98,5 +101,33 @@ module TS.SpaceTac {
return false;
}
}
+
+ /**
+ * Get a list of available secondary missions
+ */
+ getMissions(around: StarLocation, max_count = 3): Mission[] {
+ while (this.missions.length < max_count) {
+ let generator = new MissionGenerator(around.star.universe, around.star.level, around, this.random);
+ let mission = generator.generate();
+ this.missions.push(mission);
+ }
+
+ return this.missions;
+ }
+
+ /**
+ * Assign a mission to a fleet
+ *
+ * Returns true on success
+ */
+ acceptMission(mission: Mission, player: Player): boolean {
+ if (player.missions.secondary.length < 2 && remove(this.missions, mission)) {
+ mission.fleet = player.fleet;
+ add(player.missions.secondary, mission);
+ return true;
+ } else {
+ return false;
+ }
+ }
}
}
\ No newline at end of file
diff --git a/src/core/Star.spec.ts b/src/core/Star.spec.ts
index d8129cf..9784efa 100644
--- a/src/core/Star.spec.ts
+++ b/src/core/Star.spec.ts
@@ -2,10 +2,10 @@ module TS.SpaceTac.Specs {
describe("Star", () => {
it("lists links to other stars", () => {
var universe = new Universe();
- universe.stars.push(new Star(universe, 0, 0));
- universe.stars.push(new Star(universe, 1, 0));
- universe.stars.push(new Star(universe, 0, 1));
- universe.stars.push(new Star(universe, 1, 1));
+ universe.stars.push(new Star(universe, 0, 0, "Star A"));
+ universe.stars.push(new Star(universe, 1, 0, "Star B"));
+ universe.stars.push(new Star(universe, 0, 1, "Star C"));
+ universe.stars.push(new Star(universe, 1, 1, "Star D"));
universe.addLink(universe.stars[0], universe.stars[1]);
universe.addLink(universe.stars[0], universe.stars[3]);
@@ -26,6 +26,11 @@ module TS.SpaceTac.Specs {
expect(universe.stars[3].getLinkTo(universe.stars[0])).toEqual(universe.starlinks[1]);
expect(universe.stars[3].getLinkTo(universe.stars[1])).toBeNull();
expect(universe.stars[3].getLinkTo(universe.stars[2])).toBeNull();
+
+ let neighbors = universe.stars[0].getNeighbors();
+ expect(neighbors.length).toBe(2);
+ expect(neighbors).toContain(universe.stars[1]);
+ expect(neighbors).toContain(universe.stars[3]);
});
});
}
diff --git a/src/core/Star.ts b/src/core/Star.ts
index 3aa2d43..bade1ef 100644
--- a/src/core/Star.ts
+++ b/src/core/Star.ts
@@ -89,6 +89,14 @@ module TS.SpaceTac {
return `Star ${this.name}`;
}
+ /**
+ * Add a location of interest
+ */
+ addLocation(type: StarLocationType): StarLocation {
+ let result = new StarLocation(this, type);
+ return result;
+ }
+
// Get the distance to another star
getDistanceTo(star: Star): number {
var dx = this.x - star.x;
@@ -159,6 +167,13 @@ module TS.SpaceTac {
return result;
}
+ /**
+ * Get the neighboring star systems (single jump accessible)
+ */
+ getNeighbors(): Star[] {
+ return nna(this.getLinks().map(link => link.getPeer(this)));
+ }
+
// Check if a location is far enough from all other ones
private checkMinDistance(loc: StarLocation, others: StarLocation[]): boolean {
return others.every((iloc: StarLocation): boolean => {
diff --git a/src/core/Universe.ts b/src/core/Universe.ts
index 5cbb731..5257d5d 100644
--- a/src/core/Universe.ts
+++ b/src/core/Universe.ts
@@ -13,10 +13,31 @@ module TS.SpaceTac {
radius = 5
// Source of randomness
- random = RandomGenerator.global;
+ random = RandomGenerator.global
- // Generates a universe, with star systems and such
+ /**
+ * Add a single star
+ */
+ addStar(level = 1, name?: string): Star {
+ let result = new Star(this, 0, 0, name || `Star ${this.stars.length + 1}`);
+ result.level = level;
+ this.stars.push(result);
+ return result;
+ }
+
+ /**
+ * Generates a random universe, with star systems and locations of interest
+ *
+ * This will also :
+ * - create a network of jump links between star systems
+ * - add random shops
+ * - define a progressive gradient of enemy levels
+ */
generate(starcount = 50): void {
+ if (starcount < 4) {
+ starcount = 4;
+ }
+
while (this.stars.length == 0 || any(this.stars, star => star.getLinks().length == 0)) {
this.stars = this.generateStars(starcount);
@@ -27,7 +48,7 @@ module TS.SpaceTac {
this.generateWarpLocations();
this.stars.forEach((star: Star) => {
- star.generate();
+ star.generate(this.random);
});
this.setEncounterLevels();
diff --git a/src/core/missions/MainStory.spec.ts b/src/core/missions/MainStory.spec.ts
index 987dffb..754f53a 100644
--- a/src/core/missions/MainStory.spec.ts
+++ b/src/core/missions/MainStory.spec.ts
@@ -30,13 +30,13 @@ module TS.SpaceTac.Specs {
let fleet_size = fleet.ships.length;
checkPart(story, 0, "^Travel to Terranax galaxy$");
- (story.current_part).skip();
+ (story.current_part).skip();
checkPart(story, 1, "^Find your contact in .*$");
goTo(fleet, (story.current_part).destination);
checkPart(story, 2, "^Speak with your contact");
- (story.current_part).skip();
+ (story.current_part).skip();
checkPart(story, 3, "^Go with .* in .* system$");
expect(fleet.ships.length).toBe(fleet_size + 1);
diff --git a/src/core/missions/MainStory.ts b/src/core/missions/MainStory.ts
index 12051f0..1fa440d 100644
--- a/src/core/missions/MainStory.ts
+++ b/src/core/missions/MainStory.ts
@@ -17,27 +17,27 @@ module TS.SpaceTac {
let start_location = nn(fleet.location);
// Arrival
- let dialog = this.addPart(new MissionPartDialog(this, [], "Travel to Terranax galaxy"));
- dialog.addPiece(null, "Wow ! From what my sensors tell me, there is not much activity around here.");
- dialog.addPiece(null, "I remember the last time I came in this galaxy, you needed to be aware of collisions at all time, so crowded it was.");
- dialog.addPiece(null, "Well...I did not pick a signal from our contact yet. We should be looking for her in this system.");
+ let conversation = this.addPart(new MissionPartConversation(this, [], "Travel to Terranax galaxy"));
+ conversation.addPiece(null, "Wow ! From what my sensors tell me, there is not much activity around here.");
+ conversation.addPiece(null, "I remember the last time I came in this galaxy, you needed to be aware of collisions at all time, so crowded it was.");
+ conversation.addPiece(null, "Well...I did not pick a signal from our contact yet. We should be looking for her in this system.");
// 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));
contact_character.fleet.setLocation(contact_location, true);
this.addPart(new MissionPartGoTo(this, contact_location, `Find your contact in ${contact_location.star.name}`));
- dialog = this.addPart(new MissionPartDialog(this, [contact_character], "Speak with your contact"));
- dialog.addPiece(contact_character, "Finally, you came!");
- dialog.addPiece(contact_character, "Sorry for not broadcasting my position. As you may have encountered, this star system is not safe anymore.");
- dialog.addPiece(null, "Nothing we could not handle, we just hope the other teams have not run across more trouble.");
- dialog.addPiece(contact_character, "I do not even know if the other contacts made it to their rendezvous point. Jumping between systems has become quite a hassle around here.");
- dialog.addPiece(null, "And we still do not know why those rogue fleets are trying to lockdown the whole galaxy? Did you have some interaction with them?");
- dialog.addPiece(contact_character, "Well, they tend to shoot you on sight if you go near a location they defend. Do not know if that qualifies as interaction though...");
- dialog.addPiece(null, "So where do we go from here? In your last message, you told us of a resistance group growing.");
- dialog.addPiece(contact_character, "Yes, some merchants and miners have rallied behind a retired TSF general, but I lost contact with them weeks ago.");
- dialog.addPiece(contact_character, "We may go to their last known location, but first I want you to see something in a nearby system.");
- dialog.addPiece(null, "Ok, let's go...");
+ conversation = this.addPart(new MissionPartConversation(this, [contact_character], "Speak with your contact"));
+ conversation.addPiece(contact_character, "Finally, you came!");
+ conversation.addPiece(contact_character, "Sorry for not broadcasting my position. As you may have encountered, this star system is not safe anymore.");
+ conversation.addPiece(null, "Nothing we could not handle, we just hope the other teams have not run across more trouble.");
+ conversation.addPiece(contact_character, "I do not even know if the other contacts made it to their rendezvous point. Jumping between systems has become quite a hassle around here.");
+ conversation.addPiece(null, "And we still do not know why those rogue fleets are trying to lockdown the whole galaxy? Did you have some interaction with them?");
+ conversation.addPiece(contact_character, "Well, they tend to shoot you on sight if you go near a location they defend. Do not know if that qualifies as interaction though...");
+ conversation.addPiece(null, "So where do we go from here? In your last message, you told us of a resistance group growing.");
+ conversation.addPiece(contact_character, "Yes, some merchants and miners have rallied behind a retired TSF general, but I lost contact with them weeks ago.");
+ conversation.addPiece(contact_character, "We may go to their last known location, but first I want you to see something in a nearby system.");
+ conversation.addPiece(null, "Ok, let's go...");
// Go take a look at the graveyard
let nearby_systems = nna(start_location.star.getLinks().map(link => link.getPeer(contact_location.star)));
diff --git a/src/core/missions/Mission.ts b/src/core/missions/Mission.ts
index 734c83c..d354b3d 100644
--- a/src/core/missions/Mission.ts
+++ b/src/core/missions/Mission.ts
@@ -21,13 +21,17 @@ module TS.SpaceTac {
// Indicator that the mission is completed
completed: boolean
- constructor(universe: Universe, fleet: Fleet, main = false) {
+ // Title of this mission (should be kept short)
+ title: string
+
+ constructor(universe: Universe, fleet = new Fleet(), main = false) {
this.universe = universe;
this.fleet = fleet;
this.main = main;
this.parts = [];
this.completed = false;
this.current_part = new MissionPart(this, "Empty mission");
+ this.title = main ? "Main story" : "Secondary mission";
}
/**
diff --git a/src/core/missions/MissionGenerator.spec.ts b/src/core/missions/MissionGenerator.spec.ts
new file mode 100644
index 0000000..25fc52c
--- /dev/null
+++ b/src/core/missions/MissionGenerator.spec.ts
@@ -0,0 +1,24 @@
+module TS.SpaceTac.Specs {
+ describe("MissionGenerator", () => {
+ it("generates escort missions", () => {
+ let universe = new Universe();
+ let star1 = universe.addStar(1);
+ let loc1 = star1.locations[0];
+ let star2 = universe.addStar(2);
+ let loc2 = star2.locations[0];
+ let star3 = universe.addStar(3);
+ let loc3 = star3.locations[0];
+ universe.addLink(star1, star2);
+ universe.addLink(star2, star3);
+
+ let generator = new MissionGenerator(universe, 3, loc2);
+ let mission = generator.generateEscort();
+
+ expect(mission.title).toBe("Escort a ship to a level 3 system");
+ expect(mission.parts.length).toBe(1);
+ expect(mission.parts[0] instanceof MissionPartEscort).toBe(true);
+ let escort = mission.parts[0];
+ expect(escort.destination).toBe(loc3);
+ });
+ });
+}
diff --git a/src/core/missions/MissionGenerator.ts b/src/core/missions/MissionGenerator.ts
new file mode 100644
index 0000000..f522f64
--- /dev/null
+++ b/src/core/missions/MissionGenerator.ts
@@ -0,0 +1,45 @@
+module TS.SpaceTac {
+ /**
+ * Random generator of secondary missions that can be taken from
+ */
+ export class MissionGenerator {
+ universe: Universe
+ level: number
+ around: StarLocation
+ random: RandomGenerator
+
+ constructor(universe: Universe, level: number, around: StarLocation, random = RandomGenerator.global) {
+ this.universe = universe;
+ this.level = level;
+ this.around = around;
+ this.random = random;
+ }
+
+ /**
+ * Generate a single mission
+ */
+ generate(): Mission {
+ let generators = [
+ bound(this, "generateEscort")
+ ];
+
+ let generator = this.random.choice(generators);
+ let result = generator();
+ // TODO Add reward
+ return result;
+ }
+
+ /**
+ * Generate an escort mission
+ */
+ generateEscort(): Mission {
+ let mission = new Mission(this.universe);
+ let ship = new Ship();
+ let dest_star = minBy(this.around.star.getNeighbors(), star => Math.abs(star.level - this.level));
+ let destination = this.random.choice(dest_star.locations);
+ mission.addPart(new MissionPartEscort(mission, destination, ship));
+ mission.title = `Escort a ship to a level ${dest_star.level} system`;
+ return mission;
+ }
+ }
+}
diff --git a/src/core/missions/MissionPartDialog.spec.ts b/src/core/missions/MissionPartConversation.spec.ts
similarity index 86%
rename from src/core/missions/MissionPartDialog.spec.ts
rename to src/core/missions/MissionPartConversation.spec.ts
index 0ed8087..fd27c0c 100644
--- a/src/core/missions/MissionPartDialog.spec.ts
+++ b/src/core/missions/MissionPartConversation.spec.ts
@@ -1,11 +1,11 @@
module TS.SpaceTac.Specs {
- describe("MissionPartDialog", () => {
- it("advances through dialog", function () {
+ describe("MissionPartConversation", () => {
+ it("advances through conversation", function () {
let universe = new Universe();
let fleet = new Fleet();
let ship1 = new Ship(null, "Tim");
let ship2 = new Ship(null, "Ben");
- let part = new MissionPartDialog(new Mission(universe, fleet), [ship1, ship2], "Talk to Tim");
+ let part = new MissionPartConversation(new Mission(universe, fleet), [ship1, ship2], "Talk to Tim");
expect(part.title).toEqual("Talk to Tim");
expect(part.checkCompleted()).toBe(true, "No dialog piece");
@@ -36,7 +36,7 @@ module TS.SpaceTac.Specs {
let universe = new Universe();
let fleet = new Fleet();
let ship = new Ship(null, "Tim");
- let part = new MissionPartDialog(new Mission(universe, fleet), [ship]);
+ let part = new MissionPartConversation(new Mission(universe, fleet), [ship]);
part.addPiece(null, "Hello !");
part.addPiece(ship, "Hiya !");
diff --git a/src/core/missions/MissionPartDialog.ts b/src/core/missions/MissionPartConversation.ts
similarity index 86%
rename from src/core/missions/MissionPartDialog.ts
rename to src/core/missions/MissionPartConversation.ts
index e9295d7..3bff2bd 100644
--- a/src/core/missions/MissionPartDialog.ts
+++ b/src/core/missions/MissionPartConversation.ts
@@ -2,9 +2,9 @@
module TS.SpaceTac {
/**
- * A single dialog piece
+ * A single conversation piece
*/
- interface DialogPiece {
+ interface ConversationPiece {
// Interlocutor (null for the player's fleet)
interlocutor: Ship | null
@@ -13,14 +13,14 @@ module TS.SpaceTac {
}
/**
- * A mission part that triggers a dialog
+ * A mission part that triggers a conversation
*/
- export class MissionPartDialog extends MissionPart {
+ export class MissionPartConversation extends MissionPart {
// Other ships with which the dialog will take place
interlocutors: Ship[]
// Pieces of dialog
- pieces: DialogPiece[] = []
+ pieces: ConversationPiece[] = []
// Current piece
current_piece = 0
@@ -70,7 +70,7 @@ module TS.SpaceTac {
/**
* Get the current piece of dialog
*/
- getCurrent(): DialogPiece {
+ getCurrent(): ConversationPiece {
if (this.checkCompleted()) {
return {
interlocutor: null,
@@ -88,7 +88,7 @@ module TS.SpaceTac {
/**
* Get the interlocutor from the player fleet that will say the piece
*/
- private getFleetInterlocutor(piece: DialogPiece): Ship | null {
+ private getFleetInterlocutor(piece: ConversationPiece): Ship | null {
if (this.fleet.ships.length > 0) {
// TODO Choose a ship by its personality traits
return this.fleet.ships[0];
diff --git a/src/ui/Preload.ts b/src/ui/Preload.ts
index 8425d29..01b0594 100644
--- a/src/ui/Preload.ts
+++ b/src/ui/Preload.ts
@@ -18,6 +18,7 @@ module TS.SpaceTac.UI {
this.loadImage("common/arrow.png");
this.loadImage("common/button-ok.png");
this.loadImage("common/button-cancel.png");
+ this.loadImage("common/dialog.png");
this.loadSheet("common/dialog-close.png", 92, 82);
this.loadImage("menu/title.png");
this.loadImage("menu/button.png");
@@ -70,6 +71,7 @@ module TS.SpaceTac.UI {
this.loadImage("map/location-warp.png");
this.loadSheet("map/status.png", 32);
this.loadSheet("map/missions.png", 70);
+ this.loadSheet("map/mission-action.png", 192, 56);
this.loadImage("character/sheet.png");
this.loadImage("character/close.png");
this.loadImage("character/ship.png");
diff --git a/src/ui/common/UIComponent.ts b/src/ui/common/UIComponent.ts
index 925b8db..be87a89 100644
--- a/src/ui/common/UIComponent.ts
+++ b/src/ui/common/UIComponent.ts
@@ -231,8 +231,8 @@ module TS.SpaceTac.UI {
/**
* Add a static image, positioning its center.
*/
- addImage(x: number, y: number, key: string, scale = 1): void {
- let image = new Phaser.Image(this.container.game, x, y, key);
+ addImage(x: number, y: number, key: string, frame = 0, scale = 1): void {
+ let image = new Phaser.Image(this.container.game, x, y, key, frame);
image.anchor.set(0.5, 0.5);
image.scale.set(scale);
this.addInternalChild(image);
diff --git a/src/ui/common/UIDialog.ts b/src/ui/common/UIDialog.ts
index b0dfc0e..7db82b8 100644
--- a/src/ui/common/UIDialog.ts
+++ b/src/ui/common/UIDialog.ts
@@ -7,7 +7,7 @@ module TS.SpaceTac.UI {
* When a modal dialog opens, an overlay is displayed behind it to prevent clicking through it
*/
export class UIDialog extends UIComponent {
- constructor(parent: BaseView, width: number, height: number, background: string) {
+ constructor(parent: BaseView, width = 1495, height = 1080, background = "common-dialog") {
super(parent, width, height, background);
if (parent.dialogs_layer.children.length == 0) {
@@ -23,6 +23,7 @@ module TS.SpaceTac.UI {
*/
addOverlay(layer: Phaser.Group): void {
let overlay = layer.game.add.button(0, 0, "common-transparent", () => null);
+ overlay.input.useHandCursor = false;
overlay.scale.set(this.view.getWidth() / overlay.width, this.view.getHeight() / overlay.height);
layer.add(overlay);
}
@@ -30,7 +31,7 @@ module TS.SpaceTac.UI {
/**
* Add a close button
*/
- addCloseButton(key: string, x: number, y: number, frame = 0, frame_hover = 1): void {
+ addCloseButton(key = "common-dialog-close", x = 1325, y = 131, frame = 0, frame_hover = 1): void {
this.addButton(x, y, () => this.close(), key, frame, frame_hover, "Close this dialog");
}
diff --git a/src/ui/map/ActiveMissionsDisplay.ts b/src/ui/map/ActiveMissionsDisplay.ts
index c8aedbf..4990788 100644
--- a/src/ui/map/ActiveMissionsDisplay.ts
+++ b/src/ui/map/ActiveMissionsDisplay.ts
@@ -8,7 +8,7 @@ module TS.SpaceTac.UI {
private missions: ActiveMissions
constructor(parent: BaseView, missions: ActiveMissions) {
- super(parent, 520, 210);
+ super(parent, 520, 240);
this.missions = missions;
this.update();
@@ -21,10 +21,11 @@ module TS.SpaceTac.UI {
this.clearContent();
let active = this.missions.getCurrent();
- let offset = 245 - active.length * 70;
+ let spacing = 80;
+ let offset = 245 - active.length * spacing;
active.forEach((mission, idx) => {
- this.addImage(35, offset + 70 * idx, "map-missions");
- this.addText(90, offset + 70 * idx, mission.current_part.title, "#d2e1f3", 22, false, false, 430, true);
+ this.addImage(35, offset + spacing * idx, "map-missions", mission.main ? 0 : 1);
+ this.addText(90, offset + spacing * idx, mission.current_part.title, "#d2e1f3", 20, false, false, 430, true);
});
}
}
diff --git a/src/ui/map/ConversationDisplay.ts b/src/ui/map/ConversationDisplay.ts
index aa252df..64af708 100644
--- a/src/ui/map/ConversationDisplay.ts
+++ b/src/ui/map/ConversationDisplay.ts
@@ -3,7 +3,7 @@ module TS.SpaceTac.UI {
* Display of an active conversation
*/
export class ConversationDisplay extends UIComponent {
- dialog: MissionPartDialog | null = null
+ dialog: MissionPartConversation | null = null
player: Player
on_end: Function | null = null
@@ -21,7 +21,7 @@ module TS.SpaceTac.UI {
*/
updateFromMissions(missions: ActiveMissions, on_end: Function | null = null) {
let parts = missions.getCurrent().map(mission => mission.current_part);
- this.dialog = first(parts, part => part instanceof MissionPartDialog);
+ this.dialog = first(parts, part => part instanceof MissionPartConversation);
if (this.dialog) {
this.on_end = on_end;
diff --git a/src/ui/map/MapLocationMenu.ts b/src/ui/map/MapLocationMenu.ts
index d1059d1..f96cde9 100644
--- a/src/ui/map/MapLocationMenu.ts
+++ b/src/ui/map/MapLocationMenu.ts
@@ -34,7 +34,9 @@ module TS.SpaceTac.UI {
if (location) {
let actions: [string, Function][] = [];
if (location.shop) {
+ let shop = location.shop;
actions.push(["Go to dockyard", () => view.openShop()]);
+ actions.push(["Show jobs", () => new MissionsDialog(view, shop, view.player)]);
}
switch (location.type) {
diff --git a/src/ui/map/MissionsDialog.ts b/src/ui/map/MissionsDialog.ts
new file mode 100644
index 0000000..24392e9
--- /dev/null
+++ b/src/ui/map/MissionsDialog.ts
@@ -0,0 +1,69 @@
+module TS.SpaceTac.UI {
+ /**
+ * Dialog to show available missions
+ */
+ export class MissionsDialog extends UIDialog {
+ shop: Shop
+ player: Player
+ location: StarLocation
+
+ constructor(view: BaseView, shop: Shop, player: Player) {
+ super(view);
+
+ this.shop = shop;
+ this.player = player;
+ this.location = player.fleet.location || new StarLocation();
+
+ this.refresh();
+ }
+
+ /**
+ * Refresh the dialog content
+ */
+ refresh() {
+ this.clearContent();
+ this.addCloseButton();
+
+ let offset = 160;
+
+ let active = this.player.missions.getCurrent().filter(mission => !mission.main);
+ if (active.length) {
+ this.addText(this.width / 2, offset, "Active jobs", "#b8d2f1", 36);
+ offset += 110;
+
+ active.forEach(mission => {
+ this.addMission(offset, mission.title, "Reward: ???", 0, () => null);
+ offset += 110;
+ });
+ }
+
+ let proposed = this.shop.getMissions(this.location);
+ if (proposed.length) {
+ this.addText(this.width / 2, offset, "Proposed jobs", "#b8d2f1", 36);
+ offset += 110;
+
+ proposed.forEach(mission => {
+ this.addMission(offset, mission.title, "Reward: ???", 2, () => {
+ this.shop.acceptMission(mission, this.player);
+ this.refresh();
+ });
+ offset += 110;
+ });
+ }
+ }
+
+ /**
+ * Add a mission text
+ */
+ addMission(yoffset: number, title: string, subtitle: string, button_frame: number, button_callback: Function) {
+ this.addImage(320, yoffset, "map-missions", 1);
+ if (title) {
+ this.addText(380, yoffset - 15, title, "#d2e1f3", 22, false, false, 620, true);
+ }
+ if (subtitle) {
+ this.addText(380, yoffset + 22, subtitle, "#d2e1f3", 20, false, false, 620, true);
+ }
+ this.addButton(1120, yoffset, button_callback, "map-mission-action", button_frame, button_frame + 1);
+ }
+ }
+}
\ No newline at end of file