Skip to content

Commit

Permalink
documentation
Browse files Browse the repository at this point in the history
  • Loading branch information
BarthPaleologue committed Oct 9, 2024
1 parent 5f45c91 commit 8648a65
Show file tree
Hide file tree
Showing 10 changed files with 145 additions and 7 deletions.
59 changes: 59 additions & 0 deletions src/ts/missions/mission.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,51 +7,97 @@ import i18n from "../i18n";
import { UniverseObjectId } from "../saveFile/universeCoordinates";
import { SeededStarSystemModel } from "../starSystem/seededStarSystemModel";

/**
* Registered mission types. Those are used to display localized strings in the UI
*/
export const enum MissionType {
SIGHT_SEEING_FLY_BY,
SIGHT_SEEING_TERMINATOR_LANDING,
SIGHT_SEEING_ASTEROID_FIELD
}

/**
* Serialized mission object as stored in save files
*/
export type MissionSerialized = {
missionGiver: UniverseObjectId;
type: MissionType;
tree: MissionNodeSerialized;
reward: number;
};

/**
* General mission abstraction. The mission can have any arbitrary task tree and reward.
* If you want to create new mission archetypes, you should register a new enum variant in MissionType
*/
export class Mission {
/**
* The task tree that the player has to complete to finish the mission
*/
readonly tree: MissionNode;

/**
* The reward that the player gets for completing the mission
*/
readonly reward: number;

/**
* The space station that gave the mission
*/
readonly missionGiver: SpaceStationModel;

/**
* The type of the mission (useful for displaying localized strings)
*/
readonly missionType: MissionType;

/**
* Creates a new mission
* @param tree The task tree that the player has to complete to finish the mission
* @param reward The reward that the player gets for completing the mission
* @param missionGiver The space station that gave the mission
* @param missionType The type of the mission (useful for displaying localized strings)
*/
constructor(tree: MissionNode, reward: number, missionGiver: SpaceStationModel, missionType: MissionType) {
this.tree = tree;
this.reward = reward;
this.missionGiver = missionGiver;
this.missionType = missionType;
}

/**
* Describes the next task that the player has to complete given the current mission context
* @param context The current mission context
*/
async describeNextTask(context: MissionContext): Promise<string> {
return await this.tree.describeNextTask(context);
}

/**
* Returns true if the two missions have the same task tree
* @param other The other mission to compare to
*/
equals(other: Mission): boolean {
return this.tree.equals(other.tree);
}

/**
* Returns the reward that the player gets for completing the mission
*/
getReward(): number {
return this.reward;
}

/**
* Returns all the current target systems that the player has to visit to complete the mission
*/
getTargetSystems(): SystemSeed[] {
return this.tree.getTargetSystems();
}

/**
* Returns the localized string for the mission type
*/
getTypeString(): string {
switch (this.missionType) {
case MissionType.SIGHT_SEEING_FLY_BY:
Expand All @@ -65,6 +111,9 @@ export class Mission {
}
}

/**
* Returns a string describing the mission using the mission tree and the origin seed
*/
describe(): string {
const originSystem = this.missionGiver.starSystem;
if(!(originSystem instanceof SeededStarSystemModel)) {
Expand All @@ -75,10 +124,16 @@ export class Mission {
return this.tree.describe(originSeed);
}

/**
* Returns true if the mission is completed, false otherwise
*/
isCompleted(): boolean {
return this.tree.isCompleted();
}

/**
* Serializes the mission to a JSON object for storage in save files
*/
serialize(): MissionSerialized {
return {
missionGiver: getUniverseIdForSpaceStationModel(this.missionGiver),
Expand All @@ -88,6 +143,10 @@ export class Mission {
};
}

/**
* Updates the mission state recursively given the current mission context
* @param context The current mission context
*/
update(context: MissionContext): void {
if (this.isCompleted()) return;
this.tree.updateState(context);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ export type MissionAsteroidFieldNodeSerialized = MissionNodeSerialized & {
state: AsteroidFieldMissionState;
};

/**
* Node used to describe a trek to an asteroid field
*/
export class MissionAsteroidFieldNode implements MissionNode {
private state = AsteroidFieldMissionState.NOT_IN_SYSTEM;

Expand All @@ -37,6 +40,10 @@ export class MissionAsteroidFieldNode implements MissionNode {
this.targetSystemSeed = new SystemSeed(objectId.starSystem.starSectorX, objectId.starSystem.starSectorY, objectId.starSystem.starSectorZ, objectId.starSystem.index);
}

/**
* Set the state of the asteroid field mission. Useful when deserializing an ongoing mission.
* @param state The state of the mission
*/
public setState(state: AsteroidFieldMissionState) {
this.state = state;
}
Expand Down
7 changes: 7 additions & 0 deletions src/ts/missions/nodes/actions/sightseeing/missionFlyByNode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ export type MissionFlyByNodeSerialized = MissionNodeSerialized & {
state: FlyByState;
};

/**
* Node used to describe a fly-by mission around a target object
*/
export class MissionFlyByNode implements MissionNode {
private state: FlyByState = FlyByState.NOT_IN_SYSTEM;

Expand All @@ -36,6 +39,10 @@ export class MissionFlyByNode implements MissionNode {
this.targetSystemSeed = new SystemSeed(objectId.starSystem.starSectorX, objectId.starSystem.starSectorY, objectId.starSystem.starSectorZ, objectId.starSystem.index);
}

/**
* Set the state of the fly-by mission. Useful when deserializing an ongoing mission.
* @param state The state of the mission
*/
public setState(state: FlyByState) {
this.state = state;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ export type MissionTerminatorLandingNodeSerialized = MissionNodeSerialized & {
state: LandMissionState;
};

/**
* Node used to describe a landing mission on a target object near the terminator line
*/
export class MissionTerminatorLandingNode implements MissionNode {
private state: LandMissionState = LandMissionState.NOT_IN_SYSTEM;

Expand All @@ -39,6 +42,10 @@ export class MissionTerminatorLandingNode implements MissionNode {
this.targetSystemSeed = new SystemSeed(objectId.starSystem.starSectorX, objectId.starSystem.starSectorY, objectId.starSystem.starSectorZ, objectId.starSystem.index);
}

/**
* Set the state of the landing mission. Useful when deserializing an ongoing mission.
* @param state The state of the mission
*/
setState(state: LandMissionState) {
this.state = state;
}
Expand Down
18 changes: 11 additions & 7 deletions src/ts/missions/nodes/deserializeNode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ import { MissionTerminatorLandingNode, MissionTerminatorLandingNodeSerialized }
import { MissionXorNode, MissionXorNodeSerialized } from "./logic/missionXorNode";
import { MissionSequenceNode, MissionSequenceNodeSerialized } from "./logic/missionSequenceNode";

/**
* Deserialize recursively a mission node.
* @param missionNodeSerialized The serialized mission node.
*/
export function deserializeMissionNode(missionNodeSerialized: MissionNodeSerialized): MissionNode {
switch (missionNodeSerialized.type) {
case MissionNodeType.AND:
Expand All @@ -28,37 +32,37 @@ export function deserializeMissionNode(missionNodeSerialized: MissionNodeSeriali
}
}

export function deserializeMissionAndNode(serialized: MissionAndNodeSerialized): MissionAndNode {
function deserializeMissionAndNode(serialized: MissionAndNodeSerialized): MissionAndNode {
return new MissionAndNode(serialized.children.map((child) => deserializeMissionNode(child)));
}

export function deserializeMissionOrNode(serialized: MissionOrNodeSerialized): MissionOrNode {
function deserializeMissionOrNode(serialized: MissionOrNodeSerialized): MissionOrNode {
return new MissionOrNode(serialized.children.map((child) => deserializeMissionNode(child)));
}

export function deserializeMissionXorNode(serialized: MissionXorNodeSerialized): MissionXorNode {
function deserializeMissionXorNode(serialized: MissionXorNodeSerialized): MissionXorNode {
return new MissionXorNode(serialized.children.map((child) => deserializeMissionNode(child)));
}

export function deserializeMissionSequenceNode(serialized: MissionSequenceNodeSerialized): MissionSequenceNode {
function deserializeMissionSequenceNode(serialized: MissionSequenceNodeSerialized): MissionSequenceNode {
const missionNode = new MissionSequenceNode(serialized.children.map((child) => deserializeMissionNode(child)));
missionNode.setActiveChildIndex(serialized.activeChildIndex);
return missionNode;
}

export function deserializeMissionAsteroidFieldNode(serialized: MissionAsteroidFieldNodeSerialized): MissionAsteroidFieldNode {
function deserializeMissionAsteroidFieldNode(serialized: MissionAsteroidFieldNodeSerialized): MissionAsteroidFieldNode {
const missionNode = new MissionAsteroidFieldNode(serialized.objectId);
missionNode.setState(serialized.state);
return missionNode;
}

export function deserializeMissionFlyByNode(serialized: MissionFlyByNodeSerialized): MissionFlyByNode {
function deserializeMissionFlyByNode(serialized: MissionFlyByNodeSerialized): MissionFlyByNode {
const missionNode = new MissionFlyByNode(serialized.objectId);
missionNode.setState(serialized.state);
return missionNode;
}

export function deserializeMissionTerminatorLandingNode(serialized: MissionTerminatorLandingNodeSerialized): MissionTerminatorLandingNode {
function deserializeMissionTerminatorLandingNode(serialized: MissionTerminatorLandingNodeSerialized): MissionTerminatorLandingNode {
const missionNode = new MissionTerminatorLandingNode(serialized.objectId);
missionNode.setState(serialized.state);
return missionNode;
Expand Down
3 changes: 3 additions & 0 deletions src/ts/missions/nodes/logic/missionAndNode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ import i18n from "../../../i18n";

export type MissionAndNodeSerialized = MissionNodeSerialized;

/**
* Node used to describe a set of tasks that must all be completed in any order.
*/
export class MissionAndNode implements MissionNode {
readonly children: MissionNode[];

Expand Down
3 changes: 3 additions & 0 deletions src/ts/missions/nodes/logic/missionOrNode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ import { SystemSeed } from "../../../utils/systemSeed";

export type MissionOrNodeSerialized = MissionNodeSerialized;

/**
* Node used to describe a set of tasks where only a subset must be completed in any order.
*/
export class MissionOrNode implements MissionNode {
readonly children: MissionNode[];

Expand Down
10 changes: 10 additions & 0 deletions src/ts/missions/nodes/logic/missionSequenceNode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ export type MissionSequenceNodeSerialized = MissionNodeSerialized & {
activeChildIndex: number;
};

/**
* Node used to describe a sequence of tasks that must be completed in order.
*/
export class MissionSequenceNode implements MissionNode {
public children: MissionNode[];

Expand Down Expand Up @@ -42,7 +45,14 @@ export class MissionSequenceNode implements MissionNode {
this.hasCompletedLock = this.children.every((child) => child.isCompleted());
}

/**
* Set the active child index. Useful when deserializing an ongoing mission.
* @param index The index of the child to set as active.
*/
setActiveChildIndex(index: number) {
if (index < 0 || index >= this.children.length) {
throw new Error(`Invalid index ${index} for mission sequence node. Must be between 0 and ${this.children.length - 1}`);
}
this.activeChildIndex = index;
}

Expand Down
3 changes: 3 additions & 0 deletions src/ts/missions/nodes/logic/missionXorNode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ import { SystemSeed } from "../../../utils/systemSeed";

export type MissionXorNodeSerialized = MissionNodeSerialized;

/**
* Node used to describe a set of tasks where only one must be completed.
*/
export class MissionXorNode implements MissionNode {
readonly children: MissionNode[];

Expand Down
35 changes: 35 additions & 0 deletions src/ts/missions/nodes/missionNode.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,53 @@
import { MissionContext } from "../missionContext";
import { SystemSeed } from "../../utils/systemSeed";

/**
* Describes any node in the mission tree.
*/
export interface MissionNode {
/**
* Returns true if the node is completed, false otherwise.
*/
isCompleted(): boolean;

/**
* Updates the state of the node recursively.
* @param context The mission context.
*/
updateState(context: MissionContext): void;

/**
* Returns true if the node is equal to another node, false otherwise.
* @param other The other node to compare to.
*/
equals(other: MissionNode): boolean;

/**
* Describes the node recursively.
* @param originSeed The seed of the system where the mission has been given.
*/
describe(originSeed: SystemSeed): string;

/**
* Describes the next task to be done in the mission subtree.
* @param context The mission context.
*/
describeNextTask(context: MissionContext): Promise<string>;

/**
* Returns the target systems of the subtree.
*/
getTargetSystems(): SystemSeed[];

/**
* Serializes the node recursively.
*/
serialize(): MissionNodeSerialized;
}

/**
* Describes the type of mission node. Useful for serialization/deserialization.
*/
export const enum MissionNodeType {
FLY_BY,
TERMINATOR_LANDING,
Expand All @@ -27,6 +58,10 @@ export const enum MissionNodeType {
SEQUENCE
}

/**
* Base type for all serialized mission nodes.
* Nodes should specialize this type with their relevant fields.
*/
export type MissionNodeSerialized = {
type: MissionNodeType;
children: MissionNodeSerialized[];
Expand Down

0 comments on commit 8648a65

Please sign in to comment.