Added "clean location" mission type
This commit is contained in:
parent
c8c08dc4cd
commit
c646b8722c
1
TODO.md
1
TODO.md
|
@ -36,6 +36,7 @@ Character sheet
|
||||||
Battle
|
Battle
|
||||||
------
|
------
|
||||||
|
|
||||||
|
* Fix numerous effects being displayed on ships at the end, behind outcome dialog
|
||||||
* Add a voluntary retreat option
|
* Add a voluntary retreat option
|
||||||
* Display effects description instead of attribute changes
|
* Display effects description instead of attribute changes
|
||||||
* Display radius for area effects (both on action hover, and while action is active)
|
* Display radius for area effects (both on action hover, and while action is active)
|
||||||
|
|
|
@ -107,7 +107,7 @@ module TS.SpaceTac {
|
||||||
*/
|
*/
|
||||||
getMissions(around: StarLocation, max_count = 3): Mission[] {
|
getMissions(around: StarLocation, max_count = 3): Mission[] {
|
||||||
while (this.missions.length < max_count) {
|
while (this.missions.length < max_count) {
|
||||||
let generator = new MissionGenerator(around.star.universe, around.star.level, around, this.random);
|
let generator = new MissionGenerator(around.star.universe, around, this.random);
|
||||||
let mission = generator.generate();
|
let mission = generator.generate();
|
||||||
this.missions.push(mission);
|
this.missions.push(mission);
|
||||||
}
|
}
|
||||||
|
|
|
@ -94,6 +94,7 @@ module TS.SpaceTac {
|
||||||
*/
|
*/
|
||||||
addLocation(type: StarLocationType): StarLocation {
|
addLocation(type: StarLocationType): StarLocation {
|
||||||
let result = new StarLocation(this, type);
|
let result = new StarLocation(this, type);
|
||||||
|
this.locations.push(result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -72,13 +72,7 @@ module TS.SpaceTac {
|
||||||
this.encounter_gen = true;
|
this.encounter_gen = true;
|
||||||
|
|
||||||
if (this.encounter_random.random() < 0.8) {
|
if (this.encounter_random.random() < 0.8) {
|
||||||
var fleet_generator = new FleetGenerator(this.encounter_random);
|
this.setupEncounter();
|
||||||
let variations: [number, number][] = [[this.star.level, 4], [this.star.level + 1, 3], [this.star.level + 2, 2]];
|
|
||||||
if (this.star.level > 1) {
|
|
||||||
variations.push([this.star.level - 1, 5]);
|
|
||||||
}
|
|
||||||
let [level, enemies] = this.encounter_random.choice(variations);
|
|
||||||
this.encounter = fleet_generator.generate(level, new Player(this.star.universe, "Enemy"), enemies, true);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -123,5 +117,20 @@ module TS.SpaceTac {
|
||||||
this.encounter_gen = true;
|
this.encounter_gen = true;
|
||||||
this.encounter = null;
|
this.encounter = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Forces the setup of an encounter
|
||||||
|
*/
|
||||||
|
setupEncounter() {
|
||||||
|
this.encounter_gen = true;
|
||||||
|
|
||||||
|
let fleet_generator = new FleetGenerator(this.encounter_random);
|
||||||
|
let variations: [number, number][] = [[this.star.level, 4], [this.star.level + 1, 3], [this.star.level + 2, 2]];
|
||||||
|
if (this.star.level > 1) {
|
||||||
|
variations.push([this.star.level - 1, 5]);
|
||||||
|
}
|
||||||
|
let [level, enemies] = this.encounter_random.choice(variations);
|
||||||
|
this.encounter = fleet_generator.generate(level, new Player(this.star.universe, "Enemy"), enemies, true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,19 +6,33 @@ module TS.SpaceTac.Specs {
|
||||||
let loc1 = star1.locations[0];
|
let loc1 = star1.locations[0];
|
||||||
let star2 = universe.addStar(2);
|
let star2 = universe.addStar(2);
|
||||||
let loc2 = star2.locations[0];
|
let loc2 = star2.locations[0];
|
||||||
let star3 = universe.addStar(3);
|
|
||||||
let loc3 = star3.locations[0];
|
|
||||||
universe.addLink(star1, star2);
|
universe.addLink(star1, star2);
|
||||||
universe.addLink(star2, star3);
|
|
||||||
|
|
||||||
let generator = new MissionGenerator(universe, 3, loc2);
|
let generator = new MissionGenerator(universe, loc1);
|
||||||
let mission = generator.generateEscort();
|
let mission = generator.generateEscort();
|
||||||
|
|
||||||
expect(mission.title).toBe("Escort a ship to a level 3 system");
|
expect(mission.title).toBe("Escort a ship to a level 2 system");
|
||||||
expect(mission.parts.length).toBe(1);
|
expect(mission.parts.length).toBe(1);
|
||||||
expect(mission.parts[0] instanceof MissionPartEscort).toBe(true);
|
expect(mission.parts[0] instanceof MissionPartEscort).toBe(true);
|
||||||
let escort = <MissionPartEscort>mission.parts[0];
|
let escort = <MissionPartEscort>mission.parts[0];
|
||||||
expect(escort.destination).toBe(loc3);
|
expect(escort.destination).toBe(loc2);
|
||||||
|
expect(escort.ship.level.get()).toBe(2);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("generates location cleaning missions", () => {
|
||||||
|
let universe = new Universe();
|
||||||
|
let star1 = universe.addStar(1);
|
||||||
|
let loc1 = star1.locations[0];
|
||||||
|
let loc2 = star1.addLocation(StarLocationType.PLANET);
|
||||||
|
|
||||||
|
let generator = new MissionGenerator(universe, loc1);
|
||||||
|
let mission = generator.generateCleanLocation();
|
||||||
|
|
||||||
|
expect(mission.title).toBe("Defeat a level 1 fleet in this system");
|
||||||
|
expect(mission.parts.length).toBe(1);
|
||||||
|
expect(mission.parts[0] instanceof MissionPartCleanLocation).toBe(true);
|
||||||
|
let part = <MissionPartCleanLocation>mission.parts[0];
|
||||||
|
expect(part.destination).toBe(loc2);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,13 +19,11 @@ module TS.SpaceTac {
|
||||||
*/
|
*/
|
||||||
export class MissionGenerator {
|
export class MissionGenerator {
|
||||||
universe: Universe
|
universe: Universe
|
||||||
level: number
|
|
||||||
around: StarLocation
|
around: StarLocation
|
||||||
random: RandomGenerator
|
random: RandomGenerator
|
||||||
|
|
||||||
constructor(universe: Universe, level: number, around: StarLocation, random = RandomGenerator.global) {
|
constructor(universe: Universe, around: StarLocation, random = RandomGenerator.global) {
|
||||||
this.universe = universe;
|
this.universe = universe;
|
||||||
this.level = level;
|
|
||||||
this.around = around;
|
this.around = around;
|
||||||
this.random = random;
|
this.random = random;
|
||||||
}
|
}
|
||||||
|
@ -35,7 +33,8 @@ module TS.SpaceTac {
|
||||||
*/
|
*/
|
||||||
generate(): Mission {
|
generate(): Mission {
|
||||||
let generators = [
|
let generators = [
|
||||||
bound(this, "generateEscort")
|
bound(this, "generateEscort"),
|
||||||
|
bound(this, "generateCleanLocation"),
|
||||||
];
|
];
|
||||||
|
|
||||||
let generator = this.random.choice(generators);
|
let generator = this.random.choice(generators);
|
||||||
|
@ -47,9 +46,9 @@ module TS.SpaceTac {
|
||||||
/**
|
/**
|
||||||
* Generate a new ship
|
* Generate a new ship
|
||||||
*/
|
*/
|
||||||
private generateShip() {
|
private generateShip(level: number) {
|
||||||
let generator = new ShipGenerator(this.random);
|
let generator = new ShipGenerator(this.random);
|
||||||
let result = generator.generate(this.level, null, true);
|
let result = generator.generate(level, null, true);
|
||||||
result.name = `${this.random.choice(POOL_SHIP_NAMES)}-${this.random.randInt(10, 999)}`;
|
result.name = `${this.random.choice(POOL_SHIP_NAMES)}-${this.random.randInt(10, 999)}`;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -59,12 +58,28 @@ module TS.SpaceTac {
|
||||||
*/
|
*/
|
||||||
generateEscort(): Mission {
|
generateEscort(): Mission {
|
||||||
let mission = new Mission(this.universe);
|
let mission = new Mission(this.universe);
|
||||||
let ship = this.generateShip();
|
let dest_star = this.random.choice(this.around.star.getNeighbors());
|
||||||
let dest_star = minBy(this.around.star.getNeighbors(), star => Math.abs(star.level - this.level));
|
|
||||||
let destination = this.random.choice(dest_star.locations);
|
let destination = this.random.choice(dest_star.locations);
|
||||||
|
let ship = this.generateShip(dest_star.level);
|
||||||
mission.addPart(new MissionPartEscort(mission, destination, ship));
|
mission.addPart(new MissionPartEscort(mission, destination, ship));
|
||||||
mission.title = `Escort a ship to a level ${dest_star.level} system`;
|
mission.title = `Escort a ship to a level ${dest_star.level} system`;
|
||||||
return mission;
|
return mission;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate a clean location mission
|
||||||
|
*/
|
||||||
|
generateCleanLocation(): Mission {
|
||||||
|
let mission = new Mission(this.universe);
|
||||||
|
let dest_star = this.random.choice(this.around.star.getNeighbors().concat([this.around.star]));
|
||||||
|
let choices = dest_star.locations;
|
||||||
|
if (dest_star == this.around.star) {
|
||||||
|
choices = choices.filter(loc => loc != this.around);
|
||||||
|
}
|
||||||
|
let destination = this.random.choice(choices);
|
||||||
|
mission.addPart(new MissionPartCleanLocation(mission, destination));
|
||||||
|
mission.title = `Defeat a level ${destination.star.level} fleet in ${(dest_star == this.around.star) ? "this" : "a nearby"} system`;
|
||||||
|
return mission;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
25
src/core/missions/MissionPartCleanLocation.spec.ts
Normal file
25
src/core/missions/MissionPartCleanLocation.spec.ts
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
module TS.SpaceTac.Specs {
|
||||||
|
describe("MissionPartEscort", () => {
|
||||||
|
it("completes when the fleet is at location, and the encounter is clean", function () {
|
||||||
|
let destination = new StarLocation(new Star(null, 0, 0, "Atanax"));
|
||||||
|
destination.clearEncounter();
|
||||||
|
|
||||||
|
let universe = new Universe();
|
||||||
|
let fleet = new Fleet();
|
||||||
|
let part = new MissionPartCleanLocation(new Mission(universe, fleet), destination);
|
||||||
|
|
||||||
|
expect(part.title).toEqual("Clean a planet in Atanax system");
|
||||||
|
expect(part.checkCompleted()).toBe(false, "Init location");
|
||||||
|
|
||||||
|
expect(destination.isClear()).toBe(true);
|
||||||
|
part.onStarted();
|
||||||
|
expect(destination.isClear()).toBe(false);
|
||||||
|
|
||||||
|
fleet.setLocation(destination, true);
|
||||||
|
expect(part.checkCompleted()).toBe(false, "Encounter not clear");
|
||||||
|
|
||||||
|
destination.clearEncounter();
|
||||||
|
expect(part.checkCompleted()).toBe(true, "Encouter cleared");
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
22
src/core/missions/MissionPartCleanLocation.ts
Normal file
22
src/core/missions/MissionPartCleanLocation.ts
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
/// <reference path="MissionPartGoTo.ts" />
|
||||||
|
|
||||||
|
module TS.SpaceTac {
|
||||||
|
/**
|
||||||
|
* A mission part that requires the fleet to clean a specific location of enemies
|
||||||
|
*/
|
||||||
|
export class MissionPartCleanLocation extends MissionPartGoTo {
|
||||||
|
ship: Ship
|
||||||
|
|
||||||
|
constructor(mission: Mission, destination: StarLocation, directive?: string) {
|
||||||
|
super(mission, destination, directive || `Clean a ${StarLocationType[destination.type].toLowerCase()} in ${destination.star.name} system`);
|
||||||
|
}
|
||||||
|
|
||||||
|
checkCompleted(): boolean {
|
||||||
|
return super.checkCompleted() && this.destination.isClear();
|
||||||
|
}
|
||||||
|
|
||||||
|
onStarted(): void {
|
||||||
|
this.destination.setupEncounter();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue