Skip to content

Commit

Permalink
fix enfeeble/empower handling, easier file import
Browse files Browse the repository at this point in the history
  • Loading branch information
Lurkars committed Nov 28, 2024
1 parent 43fd02b commit 82c01d5
Show file tree
Hide file tree
Showing 7 changed files with 109 additions and 136 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "gloomhavensecretariat",
"version": "0.104.2",
"version": "0.104.3",
"license": "AGPL3",
"description": "Gloomhaven Secretariat is a Gloomhaven/Frosthaven Companion app.",
"homepage": "https://gloomhaven-secretariat.de",
Expand Down
12 changes: 7 additions & 5 deletions src/app/game/businesslogic/AttackModifierManager.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import { ghsShuffleArray } from "src/app/ui/helper/Static";
import { AttackModifier, AttackModifierDeck, AttackModifierType, AttackModifierValueType, CsOakDeckAttackModifier, GameAttackModifierDeckModel, additionalTownGuardAttackModifier, defaultAttackModifier, defaultTownGuardAttackModifier } from "src/app/game/model/data/AttackModifier";
import { ghsShuffleArray } from "src/app/ui/helper/Static";
import { Character } from "../model/Character";
import { CharacterData } from "../model/data/CharacterData";
import { CampaignData } from "../model/data/EditionData";
import { Perk, PerkCard, PerkType } from "../model/data/Perks";
import { Figure } from "../model/Figure";
import { Game } from "../model/Game";
import { Monster } from "../model/Monster";
import { Party } from "../model/Party";
import { Perk, PerkCard, PerkType } from "../model/data/Perks";
import { gameManager } from "./GameManager";
import { settingsManager } from "./SettingsManager";
import { CharacterData } from "../model/data/CharacterData";

export class AttackModifierManager {
game: Game;
Expand Down Expand Up @@ -258,7 +258,7 @@ export class AttackModifierManager {
const lastVisible = attackModifierDeck.lastVisible;
let restoreCards: AttackModifier[] = onlyUpcoming && current > -1 ? attackModifierDeck.cards.splice(0, current + 1) : [];
attackModifierDeck.cards = attackModifierDeck.cards.filter((attackModifier, index) =>
index > attackModifierDeck.current || (attackModifier.type != AttackModifierType.bless && attackModifier.type != AttackModifierType.curse)
index > attackModifierDeck.current || (attackModifier.type != AttackModifierType.bless && attackModifier.type != AttackModifierType.curse && attackModifier.type != AttackModifierType.empower && attackModifier.type != AttackModifierType.enfeeble)
);

// apply Challenge #1500
Expand All @@ -284,7 +284,9 @@ export class AttackModifierManager {
(attackModifier, index) =>
index > attackModifierDeck.current ||
(attackModifier.type != AttackModifierType.bless &&
attackModifier.type != AttackModifierType.curse)
attackModifier.type != AttackModifierType.curse &&
attackModifier.type != AttackModifierType.empower &&
attackModifier.type != AttackModifierType.enfeeble)
);
attackModifierDeck.current = attackModifierDeck.current - (before - attackModifierDeck.cards.length);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,9 @@ export class AttackModifierDeckDialogComponent implements OnInit {
(attackModifier: AttackModifier, index: number) =>
index <= this.deck.current &&
(attackModifier.type == AttackModifierType.bless ||
attackModifier.type == AttackModifierType.curse)
attackModifier.type == AttackModifierType.curse ||
attackModifier.type == AttackModifierType.empower ||
attackModifier.type == AttackModifierType.enfeeble)
);
}

Expand Down Expand Up @@ -364,7 +366,7 @@ export class AttackModifierDeckDialogComponent implements OnInit {
}
} else {
for (let i = 0; i < value * -1; i++) {
const empower = this.deck.cards.find((am, index) => index > this.deck.current && am.type == AttackModifierType.empower && am.id && am.id.startsWith("additional-" + this.empowerChars[index].name));
const empower = this.deck.cards.find((am, index) => this.empowerChars[index] && index > this.deck.current && am.type == AttackModifierType.empower && am.id && am.id.startsWith("additional-" + this.empowerChars[index].name));
if (empower) {
this.deck.cards.splice(this.deck.cards.indexOf(empower), 1);
}
Expand All @@ -385,7 +387,7 @@ export class AttackModifierDeckDialogComponent implements OnInit {
}
} else {
for (let i = 0; i < value * -1; i++) {
const enfeeble = this.deck.cards.find((am, index) => index > this.deck.current && am.type == AttackModifierType.enfeeble && am.id && am.id.startsWith("additional-" + this.empowerChars[index].name));
const enfeeble = this.deck.cards.find((am, index) => this.empowerChars[index] && index > this.deck.current && am.type == AttackModifierType.enfeeble && am.id && am.id.startsWith("additional-" + this.empowerChars[index].name));
if (enfeeble) {
this.deck.cards.splice(this.deck.cards.indexOf(enfeeble), 1);
}
Expand Down
50 changes: 21 additions & 29 deletions src/app/ui/header/menu/datamanagement/datamanagement.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,32 +5,30 @@
<div class="line">
<a tabclick (click)="exportGame()"><span [ghs-label]="'datamanagement.exportGame'"></span></a>
</div>
<div class="line">
<label tabclick class="input-file" (click)="importGameCheck()"
[ngClass]="{'confirm-delete' : confirm == 'importGame'}" (mouseleave)="cancelConfirm()">
<input type="file" [ngClass]="{'disabled' : confirm != 'importGame'}" [disabled]="confirm != 'importGame'"
accept="application/json" (change)="importGame($event)" />
&lt;<span [ghs-label]="'datamanagement.importGame'"></span>(!)&gt;
</label>
</div>
<div class="line">
<a tabclick (click)="resetGame()" [ngClass]="{'confirm-delete' : confirm == 'resetGame'}"
(mouseleave)="cancelConfirm()">&lt;<span [ghs-label]="'datamanagement.resetGame'"></span>(!)&gt;</a>
</div>
<div class="line">
<div class="hint-container">
<label tabclick class="input-file hint-trigger" (click)="importFileCheck($event)"
[ngClass]="{'confirm-delete' : confirm == 'importFile'}" (mouseleave)="cancelConfirm()">
<input type="file" [ngClass]="{'disabled' : confirm != 'importFile'}" [disabled]="confirm != 'importFile'"
accept="application/json" (change)="importFile($event)" />
&lt;<span [ghs-label]="'datamanagement.importFile'"></span>(!)&gt;
</label>
<img src="./assets/images/hint.svg" class="hint-trigger ghs-svg">
<span class="hint">
<span class="text" [ghs-label]="'datamanagement.importFile.hint'"></span>
</span>
</div>
</div>
</div>

<div class="column">
<div class="line">
<a tabclick (click)="exportSettings()"><span [ghs-label]="'datamanagement.exportSettings'"></span></a>
</div>
<div class="line">
<label class="input-file" (click)="importSettingsCheck()"
[ngClass]="{'confirm-delete' : confirm == 'importSettings'}" (mouseleave)="cancelConfirm()">
<input type="file" [ngClass]="{'disabled' : confirm != 'importSettings'}"
[disabled]="confirm != 'importSettings'" accept="application/json" (change)="importSettings($event)" />
&lt;<span [ghs-label]="'datamanagement.importSettings'"></span>(!)&gt;
</label>
</div>
<div class="line">
<a tabclick (click)="resetSettings()" [ngClass]="{'confirm-delete' : confirm == 'resetSettings'}"
(mouseleave)="cancelConfirm()">&lt;<span [ghs-label]="'datamanagement.resetSettings'"></span>(!)&gt;</a>
Expand All @@ -41,15 +39,6 @@
<div class="line">
<a tabclick (click)="exportDataDump()"><span [ghs-label]="'datamanagement.exportDataDump'"></span></a>
</div>
<div class="line" [ngClass]="{'disabled' : working}">
<label tabclick class="input-file" (click)="importDataDumpCheck()"
[ngClass]="{'confirm-delete' : confirm == 'importDataDump'}" (mouseleave)="cancelConfirm()">
<input type="file" [ngClass]="{'disabled' : confirm != 'importDataDump'}"
[disabled]="confirm != 'importDataDump'" accept="application/json" (change)="importDataDump($event)" />
&lt;<span [ghs-label]="'datamanagement.importDataDump'"></span>(!)&gt;
<img src="./assets/images/shuffle.svg" class="working" *ngIf="working == 'importDataDump'">
</label>
</div>
<div class="line">
<a tabclick (click)="clearAllData()" [ngClass]="{'confirm-delete' : confirm == 'clearAllData'}"
(mouseleave)="cancelConfirm()">&lt;<span [ghs-label]="'datamanagement.clearAll'"></span>(!)&gt;</a>
Expand Down Expand Up @@ -190,9 +179,11 @@
</div>
<div class="line">
<span class="input-button">
<input tabclick type="text" #inputUnlock (keyup.enter)="addUnlock($event.target)" (keyup)="inputUnlock.classList.remove('error')"
[ghs-label]="'datamanagement.addUnlock'" [ghs-label-attribute]="'placeholder'">
<span class="add-button" (click)="addUnlock(inputUnlock)" [ngClass]="{'disabled' : !inputUnlock.value}"></span>
<input tabclick type="text" #inputUnlock (keyup.enter)="addUnlock($event.target)"
(keyup)="inputUnlock.classList.remove('error')" [ghs-label]="'datamanagement.addUnlock'"
[ghs-label-attribute]="'placeholder'">
<span class="add-button" (click)="addUnlock(inputUnlock)"
[ngClass]="{'disabled' : !inputUnlock.value}"></span>
</span>
</div>
<div class="line spoilers">
Expand All @@ -215,7 +206,8 @@
<span class="input-button">
<input tabclick type="text" #inputSpoiler (keyup.enter)="addSpoiler($event.target)" (keyup)="0"
[ghs-label]="'datamanagement.addSpoiler'" [ghs-label-attribute]="'placeholder'">
<span class="add-button" (click)="addSpoiler(inputSpoiler)" [ngClass]="{'disabled' : !(inputSpoiler.value)}"></span>
<span class="add-button" (click)="addSpoiler(inputSpoiler)"
[ngClass]="{'disabled' : !(inputSpoiler.value)}"></span>
</span>
</div>
<div class="line spoilers">
Expand Down
9 changes: 9 additions & 0 deletions src/app/ui/header/menu/datamanagement/datamanagement.scss
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,15 @@
animation: shake .5s linear;
color: var(--ghs-color-red) !important;
}

&.warning {
animation: shake .5s linear;
color: var(--ghs-color-yellow) !important;
}
}

.hint-container label.hint-trigger {
margin-left: 0;
}
}

Expand Down
160 changes: 62 additions & 98 deletions src/app/ui/header/menu/datamanagement/datamanagement.ts
Original file line number Diff line number Diff line change
Expand Up @@ -191,42 +191,59 @@ export class DatamanagementMenuComponent implements OnInit {
}
}

importGameCheck() {
if (this.confirm != "importGame") {
importFileCheck(event: any) {
event.target.classList.remove("warning");
event.target.parentElement.classList.remove("warning");
if (this.confirm != "importFile") {
setTimeout(() => {
this.confirm = "importGame";
this.confirm = "importFile";
}, 100);
} else {
ghsInputFullScreenCheck();
}
}

importGame(event: any) {
event.target.parentElement.classList.remove("error");
importFile(inputEvent: any) {
this.working = "importFile";
inputEvent.target.parentElement.classList.remove("warning");
const reader = new FileReader();
try {
const reader = new FileReader();
reader.addEventListener('load', (event: any) => {
gameManager.stateManager.before("loadGameFromFile");
const gameModel: GameModel = Object.assign(new GameModel(), JSON.parse(event.target.result));
if (gameModel.revision < gameManager.game.revision) {
storageManager.addBackup(gameManager.game.toModel());
gameModel.revision = gameManager.game.revision;
gameModel.revisionOffset = gameManager.game.revisionOffset;
reader.addEventListener('load', async (event: any) => {
const data = JSON.parse(event.target.result);
if (data.revision && typeof data.revision === 'number') {
this.importGame(Object.assign(new GameModel(), data));
} else if (data.zoom && typeof data.zoom === 'number') {
this.importSettings(Object.assign(new Settings(), data));
} else if (data.game && data.settings) {
this.importDataDump(data);
} else {
inputEvent.target.parentElement.classList.add("warning");
}
gameManager.game.fromModel(gameModel);
gameManager.stateManager.after();
});
this.working = "";
})

if (event.target.files.length > 0) {
reader.readAsText(event.target.files[0]);
event.target.value = "";
if (inputEvent.target.files.length > 0) {
reader.readAsText(inputEvent.target.files[0]);
inputEvent.target.value = "";
}
} catch (e: any) {
console.warn(e);
event.target.parentElement.classList.add("error");
inputEvent.target.parentElement.classList.add("warning");
this.working = "";
}
}

importGame(gameModel: GameModel) {
gameManager.stateManager.before("loadGameFromFile");
if (gameModel.revision < gameManager.game.revision) {
storageManager.addBackup(gameManager.game.toModel());
gameModel.revision = gameManager.game.revision;
gameModel.revisionOffset = gameManager.game.revisionOffset;
}
gameManager.game.fromModel(gameModel);
gameManager.stateManager.after();
}

resetGame(): void {
if (this.confirm != "resetGame") {
this.confirm = "resetGame";
Expand All @@ -253,31 +270,9 @@ export class DatamanagementMenuComponent implements OnInit {
}
}

importSettingsCheck() {
if (this.confirm != "importSettings") {
setTimeout(() => {
this.confirm = "importSettings";
}, 100);
} else {
ghsInputFullScreenCheck();
}
}

importSettings(event: any) {
event.target.parentElement.classList.remove("error");
try {
const reader = new FileReader();
reader.addEventListener('load', async (event: any) => {
const settings: Settings = Object.assign(new Settings(), JSON.parse(event.target.result));
settingsManager.settings = settings;
await storageManager.write('settings', 'default', settingsManager.settings);
});

reader.readAsText(event.target.files[0]);
} catch (e: any) {
console.warn(e);
event.target.parentElement.classList.add("error");
}
async importSettings(settings: Settings) {
settingsManager.settings = settings;
await storageManager.write('settings', 'default', settingsManager.settings);
}

resetSettings(): void {
Expand All @@ -293,60 +288,29 @@ export class DatamanagementMenuComponent implements OnInit {
await gameManager.stateManager.autoBackup("ghs-data-dump-" + new Date().toISOString() + ".json", true);
}

importDataDumpCheck() {
if (this.confirm != "importDataDump") {
setTimeout(() => {
this.confirm = "importDataDump";
}, 100);
} else {
ghsInputFullScreenCheck();
async importDataDump(data: any) {
gameManager.stateManager.errorLog = data.errorLog || [];
const keys = Object.keys(data);
let success = false;
for (let i = 0; i < keys.length; i++) {
const key = keys[i];
if (key === 'game') {
await storageManager.write('game', 'default', data[key]);
success = true;
} else if (key === 'settings') {
await storageManager.write('settings', 'default', Object.assign(new Settings(), data[key]));
} else if (key === 'undo') {
await storageManager.writeArray('undo', data[key]);
} else if (key === 'redo') {
await storageManager.writeArray('redo', data[key]);
} else if (key === 'undo-infos') {
await storageManager.writeArray('undo-infos', data[key]);
} else if (key === 'game-backup') {
await storageManager.writeArray('game-backup', data[key]);
}
}
}


importDataDump(event: any) {
event.target.parentElement.classList.remove("error");
try {
this.working = "importDataDump";
const reader = new FileReader();
reader.addEventListener('load', async (event: any) => {
const datadump: any = JSON.parse(event.target.result);
gameManager.stateManager.errorLog = datadump.errorLog || [];
let migration = false;
const keys = Object.keys(datadump);
for (let i = 0; i < keys.length; i++) {
const key = keys[i];
if (key.startsWith('ghs-')) {
await localStorage.setItem(key, JSON.stringify(datadump[key]));
migration = true;
} else if (key === 'game') {
await storageManager.write('game', 'default', datadump[key]);
} else if (key === 'settings') {
await storageManager.write('settings', 'default', Object.assign(new Settings(), datadump[key]));
} else if (key === 'undo') {
await storageManager.writeArray('undo', datadump[key]);
} else if (key === 'redo') {
await storageManager.writeArray('redo', datadump[key]);
} else if (key === 'undo-infos') {
await storageManager.writeArray('undo-infos', datadump[key]);
} else if (key === 'game-backup') {
await storageManager.writeArray('game-backup', datadump[key]);
}
}

if (migration) {
storageManager.migrate();
}

this.working = "";
window.location.reload();
});

reader.readAsText(event.target.files[0]);
} catch (e: any) {
console.warn(e);
this.working = "";
event.target.parentElement.classList.add("error");
if (success) {
window.location.reload();
}
}

Expand Down
4 changes: 4 additions & 0 deletions src/assets/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,10 @@
"exportGame": "Export Game to File",
"exportSettings": "Export Settings to File",
"importDataDump": "Import Data Dump",
"importFile": {
".": "Import File",
"hint": "Import any exported file like Game, Backup, Datadump or Settings. Confirm import with second click!"
},
"importGame": "Import Game from File",
"importSettings": "Import Settings from File",
"removeAllSpoilers": "Remove all",
Expand Down

0 comments on commit 82c01d5

Please sign in to comment.