1
0
Fork 0
spacetac/src/core/missions/MissionGenerator.ts

149 lines
5.3 KiB
TypeScript

module TS.SpaceTac {
const POOL_SHIP_NAMES = [
"Zert",
"Ob'tec",
"Paayk",
"Fen_amr",
"TempZst",
"croNt",
"Appn",
"Vertix",
"Opan-vel",
"Yz-aol",
"Arkant",
"PNX",
]
/**
* Random generator of secondary missions that can be taken from
*/
export class MissionGenerator {
universe: Universe
around: StarLocation
random: RandomGenerator
equipment_generator: LootGenerator
constructor(universe: Universe, around: StarLocation, random = RandomGenerator.global) {
this.universe = universe;
this.around = around;
this.random = random;
this.equipment_generator = new LootGenerator(this.random);
}
/**
* Generate a single mission
*/
generate(): Mission {
let generators = [
bound(this, "generateEscort"),
bound(this, "generateCleanLocation"),
];
let generator = this.random.choice(generators);
let result = generator();
if (result.value) {
result.reward = this.generateReward(result.value);
}
return result;
}
/**
* 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)}`;
return result;
}
/**
* Try to generate an equipment of given value
*/
tryGenerateEquipmentReward(value: number): Equipment | null {
let minvalue = value * 0.8;
let maxvalue = value * 1.2;
let qualities = [EquipmentQuality.FINE, EquipmentQuality.PREMIUM, EquipmentQuality.LEGENDARY];
let candidates: Equipment[] = [];
for (let pass = 0; pass < 10; pass++) {
let equipment: Equipment | null;
let level = 1;
do {
let quality = qualities[this.random.weighted([15, 12, 2])];
equipment = this.equipment_generator.generate(level, quality);
if (equipment && equipment.getPrice() >= minvalue && equipment.getPrice() <= maxvalue) {
candidates.push(equipment);
}
level += 1;
} while (equipment && equipment.getPrice() < maxvalue * 1.5 && level < 20);
}
if (candidates.length > 0) {
return this.random.choice(candidates);
} else {
return null;
}
}
/**
* Generate a reward
*/
generateReward(value: number): MissionReward {
if (this.random.bool()) {
let equipment = this.tryGenerateEquipmentReward(value);
if (equipment) {
return equipment;
} else {
return value;
}
} else {
return value;
}
}
/**
* Helper to set the difficulty of a mission
*/
setDifficulty(mission: Mission, base_value: number, fight_level: number) {
let level_diff = fight_level - this.around.star.level;
let code = (level_diff > 0) ? MissionDifficulty.hard : (level_diff < 0 ? MissionDifficulty.easy : MissionDifficulty.normal);
let value = fight_level * (base_value + base_value * 0.1 * clamp(level_diff, -5, 5));
mission.setDifficulty(code, Math.round(value));
}
/**
* Generate an escort mission
*/
generateEscort(): Mission {
let mission = new Mission(this.universe);
let dest_star = this.random.choice(this.around.star.getNeighbors());
let destination = this.random.choice(dest_star.locations);
let ship = this.generateShip(dest_star.level);
mission.addPart(new MissionPartEscort(mission, destination, ship));
mission.title = `Escort a ship to a level ${dest_star.level} system`;
this.setDifficulty(mission, 1000, dest_star.level);
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 here = (dest_star == this.around.star);
let choices = dest_star.locations;
if (here) {
choices = choices.filter(loc => loc != this.around);
}
let destination = this.random.choice(choices);
mission.addPart(new MissionPartCleanLocation(mission, destination));
mission.addPart(new MissionPartGoTo(mission, this.around, "Go back to collect your reward"));
mission.title = `Defeat a level ${destination.star.level} fleet in ${here ? "this" : "a nearby"} system`;
this.setDifficulty(mission, here ? 300 : 500, dest_star.level);
return mission;
}
}
}