diff --git a/@types/index.d.ts b/@types/index.d.ts index 4316c8a9..2aed7c9e 100644 --- a/@types/index.d.ts +++ b/@types/index.d.ts @@ -69,6 +69,22 @@ export interface InitiativeTrackerData { leafletIntegration: boolean; playerMarker: string; monsterMarker: string; + state: InitiativeViewState; +} + +export interface InitiativeViewState { + creatures: CreatureState[]; + state: boolean; + current: number; + name: string; +} + +export interface CreatureState extends HomebrewCreature { + status: string[]; + enabled: boolean; + currentHP: number; + initiative: number; + player: boolean; } export interface SRDMonster { diff --git a/manifest.json b/manifest.json index 3b5976a0..3bacfaf0 100644 --- a/manifest.json +++ b/manifest.json @@ -1,7 +1,7 @@ { "id": "initiative-tracker", "name": "Initiative Tracker", - "version": "3.0.5", + "version": "3.1.0", "minAppVersion": "0.12.10", "author": "Jeremy Valentine", "description": "TTRPG Initiative Tracker for Obsidian.md", diff --git a/package.json b/package.json index 2ebbb2f7..b342273d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "initiative-tracker", - "version": "3.0.5", + "version": "3.1.0", "description": "TTRPG Initiative Tracker for Obsidian.md", "main": "main.js", "scripts": { diff --git a/src/main.ts b/src/main.ts index fe81e20f..5b0f43d1 100644 --- a/src/main.ts +++ b/src/main.ts @@ -332,7 +332,8 @@ export default class InitiativeTracker extends Plugin { console.log("Initiative Tracker v" + this.manifest.version + " loaded"); } - onunload() { + async onunload() { + await this.saveSettings(); this.app.workspace.trigger("initiative-tracker:unload"); this.app.workspace .getLeavesOfType(INTIATIVE_TRACKER_VIEW) diff --git a/src/settings.ts b/src/settings.ts index b7f841da..34cb061d 100644 --- a/src/settings.ts +++ b/src/settings.ts @@ -184,9 +184,11 @@ export default class InitiativeTrackerSettings extends PluginSettingTab { const marker = this.plugin.leaflet.markerIcons.find( (icon) => icon.type == this.plugin.data.playerMarker ); - inner.innerHTML = marker.html; + if (marker) { + inner.innerHTML = marker.html; - playerMarker.descEl.appendChild(div); + playerMarker.descEl.appendChild(div); + } } const monsterMarker = new Setting(containerEl) .setName("Default Monster Marker Type") @@ -208,9 +210,11 @@ export default class InitiativeTrackerSettings extends PluginSettingTab { const marker = this.plugin.leaflet.markerIcons.find( (icon) => icon.type == this.plugin.data.monsterMarker ); - inner.innerHTML = marker.html; + if (marker) { + inner.innerHTML = marker.html; - monsterMarker.descEl.appendChild(div); + monsterMarker.descEl.appendChild(div); + } } } @@ -230,6 +234,7 @@ export default class InitiativeTrackerSettings extends PluginSettingTab { } }); } catch (e) { + console.error(e); new Notice( "There was an error displaying the settings tab for Obsidian Initiative Tracker." ); @@ -807,9 +812,11 @@ class NewPlayerModal extends Modal { const marker = this.plugin.leaflet.markerIcons.find( (icon) => icon.type == this.player.marker ); - inner.innerHTML = marker.html; + if (marker) { + inner.innerHTML = marker.html; - markerSetting.descEl.appendChild(div); + markerSetting.descEl.appendChild(div); + } } } @@ -1026,9 +1033,11 @@ class NewCreatureModal extends Modal { const marker = this.plugin.leaflet.markerIcons.find( (icon) => icon.type == this.creature.marker ); - inner.innerHTML = marker.html; + if (marker) { + inner.innerHTML = marker.html; - markerSetting.descEl.appendChild(div); + markerSetting.descEl.appendChild(div); + } } } diff --git a/src/utils/constants.ts b/src/utils/constants.ts index 9c52d722..d8eebc2d 100644 --- a/src/utils/constants.ts +++ b/src/utils/constants.ts @@ -15,5 +15,11 @@ export const DEFAULT_SETTINGS: InitiativeTrackerData = { sync: false, leafletIntegration: false, playerMarker: "default", - monsterMarker: "default" + monsterMarker: "default", + state: { + creatures: [], + state: false, + current: null, + name: null + } }; diff --git a/src/utils/creature.ts b/src/utils/creature.ts index 99cb6df8..7715e0f1 100644 --- a/src/utils/creature.ts +++ b/src/utils/creature.ts @@ -1,5 +1,11 @@ -import type { Condition, HomebrewCreature, SRDMonster } from "@types"; +import type { + Condition, + CreatureState, + HomebrewCreature, + SRDMonster +} from "@types"; import type InitiativeTracker from "src/main"; +import { Conditions } from "."; import { DEFAULT_UNDEFINED } from "./constants"; function getId() { @@ -101,4 +107,32 @@ export class Creature { toProperties() { return { ...this }; } + + toJSON(): CreatureState { + return { + name: this.name, + initiative: this.initiative - this.modifier, + modifier: this.modifier, + hp: this.max, + ac: this.ac, + note: this.note, + id: this.id, + marker: this.marker, + currentHP: this.hp, + status: Array.from(this.status).map((c) => c.name), + enabled: this.enabled, + player: this.player + }; + } + + static fromJSON(state: CreatureState) { + const creature = new Creature(state, state.initiative); + creature.enabled = state.enabled; + + creature.hp = state.currentHP; + creature.status = new Set( + state.status.map((n) => Conditions.find(({ name }) => n == name)) + ); + return creature; + } } diff --git a/src/view.ts b/src/view.ts index 7ad86077..f1944945 100644 --- a/src/view.ts +++ b/src/view.ts @@ -4,8 +4,14 @@ import { BASE, INTIATIVE_TRACKER_VIEW, MIN_WIDTH_FOR_HAMBURGER } from "./utils"; import type InitiativeTracker from "./main"; import App from "./svelte/App.svelte"; -import type { Creature } from "./utils/creature"; -import type { Condition, TrackerEvents, TrackerViewState } from "@types"; +import { Creature } from "./utils/creature"; +import type { + Condition, + InitiativeViewState, + TrackerEvents, + TrackerViewState +} from "@types"; +import Creature__SvelteComponent_ from "./svelte/Creature.svelte"; export default class TrackerView extends ItemView { public creatures: Creature[] = []; @@ -42,7 +48,12 @@ export default class TrackerView extends ItemView { constructor(public leaf: WorkspaceLeaf, public plugin: InitiativeTracker) { super(leaf); - this.newEncounter(); + + if (this.plugin.data.state?.creatures?.length) { + this.newEncounterFromState(this.plugin.data.state); + } else { + this.newEncounter(); + } this.registerEvent( this.app.workspace.on( @@ -142,6 +153,27 @@ export default class TrackerView extends ItemView { ) ); } + newEncounterFromState(initiativeState: InitiativeViewState) { + if (!initiativeState || !initiativeState?.creatures.length) { + this.newEncounter(); + } + const { creatures, state, name, current } = initiativeState; + this.creatures = [...creatures.map((c) => Creature.fromJSON(c))]; + + if (name) { + this.name = name; + this.setAppState({ + name: this.name + }); + } + this.state = state; + this.current = current; + this.trigger("initiative-tracker:new-encounter", this.appState); + + this.setAppState({ + creatures: this.ordered + }); + } private _addCreature(creature: Creature) { this.creatures.push(creature); @@ -197,11 +229,13 @@ export default class TrackerView extends ItemView { async newEncounter({ name, players = true, - creatures = [] + creatures = [], + roll = true }: { name?: string; players?: boolean | string[]; creatures?: Creature[]; + roll?: boolean; } = {}) { if (players instanceof Array && players.length) { this.creatures = [ @@ -227,7 +261,12 @@ export default class TrackerView extends ItemView { this.trigger("initiative-tracker:new-encounter", this.appState); - await this.rollInitiatives(); + if (roll) await this.rollInitiatives(); + else { + this.setAppState({ + creatures: this.ordered + }); + } } resetEncounter() { @@ -483,4 +522,17 @@ export default class TrackerView extends ItemView { const [name, ...data] = args; this.app.workspace.trigger(name, ...data); } + async onunload() { + if (this.state) { + this.plugin.data.state = { + creatures: [...this.ordered.map((c) => c.toJSON())], + state: this.state, + current: this.current, + name: this.name + }; + } else { + this.plugin.data.state = null; + } + await this.plugin.saveSettings(); + } } diff --git a/versions.json b/versions.json index 7ba63ad1..8b403ee0 100644 --- a/versions.json +++ b/versions.json @@ -2,5 +2,6 @@ "0.0.10": "0.12.4", "1.0.1": "0.12.4", "2.0.3": "0.12.10", - "3.0.5": "0.12.10" + "3.0.5": "0.12.10", + "3.1.0": "0.12.10" } \ No newline at end of file