Save system: ceremonial PR (#42)
prototype for writing a save Merge branch 'main' into savesystem violently read player from file oops, missed revisions in StateManager create StateManager from file autoformat the world oops, forgot to save the split-up of save.ts Save on end-of-day, or after endgame. Putting it here avoids a circular reference problem Merge branch 'main' into savesystem Integrate save system Deal with save corruption correctly Co-authored-by: Kistaro Windrider <kistaro@gmail.com> Reviewed-on: #42 Co-authored-by: Nyeogmi <economicsbat@gmail.com> Co-committed-by: Nyeogmi <economicsbat@gmail.com>
This commit is contained in:
@ -1,6 +1,12 @@
|
||||
import { ALL_STATS, Skill, Stat, SuccessorOption, Wish } from "./datatypes.ts";
|
||||
import { getSkills } from "./skills.ts";
|
||||
import { getThralls, ItemStage, LifeStage, Thrall } from "./thralls.ts";
|
||||
import { SaveFileV1, mustBeSaveFileV1 } from "./saveformat.ts";
|
||||
|
||||
interface NewRoundConfig {
|
||||
asSuccessor: SuccessorOption;
|
||||
withWish: Wish | null;
|
||||
}
|
||||
|
||||
export class PlayerProgress {
|
||||
#name: string;
|
||||
@ -20,25 +26,65 @@ export class PlayerProgress {
|
||||
#thrallsObtainedItem: number[];
|
||||
#thrallsDeliveredItem: number[];
|
||||
|
||||
constructor(asSuccessor: SuccessorOption, withWish: Wish | null) {
|
||||
this.#name = asSuccessor.name;
|
||||
this.#thrallTemplate = asSuccessor.template.id;
|
||||
this.#nImprovements = asSuccessor.nImprovements;
|
||||
this.#stats = { ...asSuccessor.stats };
|
||||
this.#talents = { ...asSuccessor.talents };
|
||||
this.#isInPenance = asSuccessor.inPenance;
|
||||
this.#wish = withWish;
|
||||
this.#exp = 0;
|
||||
this.#blood = 0;
|
||||
this.#itemsPurloined = 0;
|
||||
this.#skillsLearned = [];
|
||||
this.#untrimmedSkillsAvailable = [];
|
||||
this.#thrallsUnlocked = [];
|
||||
this.#thrallDamage = {};
|
||||
this.#thrallsObtainedItem = [];
|
||||
this.#thrallsDeliveredItem = [];
|
||||
constructor(args: NewRoundConfig | SaveFileV1) {
|
||||
if ("asSuccessor" in args) {
|
||||
//asSuccessor: SuccessorOption, withWish: Wish | null) {
|
||||
const config = args as NewRoundConfig;
|
||||
const asSuccessor = config.asSuccessor;
|
||||
this.#name = asSuccessor.name;
|
||||
this.#thrallTemplate = asSuccessor.template.id;
|
||||
this.#nImprovements = asSuccessor.nImprovements;
|
||||
this.#stats = { ...asSuccessor.stats };
|
||||
this.#talents = { ...asSuccessor.talents };
|
||||
this.#isInPenance = asSuccessor.inPenance;
|
||||
this.#wish = config.withWish;
|
||||
this.#exp = 0;
|
||||
this.#blood = 0;
|
||||
this.#itemsPurloined = 0;
|
||||
this.#skillsLearned = [];
|
||||
this.#untrimmedSkillsAvailable = [];
|
||||
this.#thrallsUnlocked = [];
|
||||
this.#thrallDamage = {};
|
||||
this.#thrallsObtainedItem = [];
|
||||
this.#thrallsDeliveredItem = [];
|
||||
|
||||
this.refill();
|
||||
this.refill();
|
||||
} else {
|
||||
const file = mustBeSaveFileV1(args);
|
||||
this.#name = file.name;
|
||||
this.#thrallTemplate = file.thrallTemplateId;
|
||||
this.#nImprovements = file.nImprovements;
|
||||
this.#stats = {
|
||||
AGI: file.stats.agi,
|
||||
INT: file.stats.int,
|
||||
CHA: file.stats.cha,
|
||||
PSI: file.stats.psi,
|
||||
};
|
||||
this.#talents = {
|
||||
AGI: file.talents.agi,
|
||||
INT: file.talents.int,
|
||||
CHA: file.talents.cha,
|
||||
PSI: file.talents.psi,
|
||||
};
|
||||
(this.#isInPenance = file.isInPenance),
|
||||
(this.#wish = file.wishId >= 0 ? { id: file.wishId } : null);
|
||||
this.#exp = file.exp;
|
||||
this.#blood = file.blood;
|
||||
this.#itemsPurloined = file.itemsPurloined;
|
||||
this.#skillsLearned = file.skillsLearned;
|
||||
this.#untrimmedSkillsAvailable = file.untrimmedSkillsAvailableIds.map(
|
||||
(id) => {
|
||||
return { id: id };
|
||||
},
|
||||
);
|
||||
this.#thrallsUnlocked = file.thrallsUnlocked;
|
||||
this.#thrallDamage = {};
|
||||
for (let i = 0; i < file.thrallDamage.length; ++i) {
|
||||
this.#thrallDamage[i] = file.thrallDamage[i];
|
||||
}
|
||||
this.#thrallsObtainedItem = file.thrallsObtainedItem;
|
||||
this.#thrallsDeliveredItem = file.thrallsDeliveredItem;
|
||||
}
|
||||
}
|
||||
|
||||
applyEndOfTurn() {
|
||||
@ -206,7 +252,11 @@ export class PlayerProgress {
|
||||
return skillsAvailable.slice(0, 6);
|
||||
}
|
||||
|
||||
getLearnedSkills() {
|
||||
getUntrimmedAvailableSkillIds(): number[] {
|
||||
return this.#untrimmedSkillsAvailable.map((s) => s.id);
|
||||
}
|
||||
|
||||
getLearnedSkills(): Skill[] {
|
||||
let learnedSkills = [];
|
||||
for (let s of this.#skillsLearned.values()) {
|
||||
learnedSkills.push({ id: s });
|
||||
@ -214,6 +264,10 @@ export class PlayerProgress {
|
||||
return learnedSkills;
|
||||
}
|
||||
|
||||
getRawLearnedSkills(): number[] {
|
||||
return [...this.#skillsLearned];
|
||||
}
|
||||
|
||||
getStats() {
|
||||
return { ...this.#stats };
|
||||
}
|
||||
@ -233,6 +287,10 @@ export class PlayerProgress {
|
||||
return this.#thrallsUnlocked.indexOf(thrall.id) != -1;
|
||||
}
|
||||
|
||||
getUnlockedThrallIds(): number[] {
|
||||
return [...this.#thrallsUnlocked];
|
||||
}
|
||||
|
||||
damageThrall(thrall: Thrall, amount: number) {
|
||||
if (amount <= 0.0) {
|
||||
throw new Error(`damage must be some positive amount, not ${amount}`);
|
||||
@ -246,6 +304,10 @@ export class PlayerProgress {
|
||||
(this.#thrallDamage[thrall.id] ?? 0.0) + amount;
|
||||
}
|
||||
|
||||
getThrallDamage(thrall: Thrall): number {
|
||||
return this.#thrallDamage[thrall.id] ?? 0.0;
|
||||
}
|
||||
|
||||
getThrallLifeStage(thrall: Thrall): LifeStage {
|
||||
let damage = this.#thrallDamage[thrall.id] ?? 0;
|
||||
if (damage < 0.5) {
|
||||
@ -270,6 +332,10 @@ export class PlayerProgress {
|
||||
this.#thrallsObtainedItem.push(thrall.id);
|
||||
}
|
||||
|
||||
getThrallObtainedItemIds(): number[] {
|
||||
return [...this.#thrallsObtainedItem];
|
||||
}
|
||||
|
||||
deliverThrallItem(thrall: Thrall) {
|
||||
if (this.#thrallsDeliveredItem.indexOf(thrall.id) != -1) {
|
||||
return;
|
||||
@ -277,6 +343,10 @@ export class PlayerProgress {
|
||||
this.#thrallsDeliveredItem.push(thrall.id);
|
||||
}
|
||||
|
||||
getThrallDeliveredItemIds(): number[] {
|
||||
return [...this.#thrallsDeliveredItem];
|
||||
}
|
||||
|
||||
getThrallItemStage(thrall: Thrall): ItemStage {
|
||||
if (this.#thrallsDeliveredItem.indexOf(thrall.id) != -1) {
|
||||
return ItemStage.Delivered;
|
||||
@ -308,7 +378,11 @@ export function initPlayerProgress(
|
||||
asSuccessor: SuccessorOption,
|
||||
withWish: Wish | null,
|
||||
) {
|
||||
active = new PlayerProgress(asSuccessor, withWish);
|
||||
active = new PlayerProgress({ asSuccessor: asSuccessor, withWish: withWish });
|
||||
}
|
||||
|
||||
export function rehydratePlayerProgress(savefile: SaveFileV1) {
|
||||
active = new PlayerProgress(savefile);
|
||||
}
|
||||
|
||||
export function getPlayerProgress(): PlayerProgress {
|
||||
|
Reference in New Issue
Block a user