diff --git a/package.json b/package.json index eb43811b9..7dcbd4a19 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "gloomhavensecretariat", - "version": "0.102.3", + "version": "0.102.4", "license": "AGPL3", "description": "Gloomhaven Secretariat is a Gloomhaven/Frosthaven Companion app.", "homepage": "https://gloomhaven-secretariat.de", @@ -101,7 +101,7 @@ "ng-in-viewport": "^16.1.0", "rxjs": "~7.8.1", "tslib": "^2.8.0", - "uuid": "^10.0.0", + "uuid": "^11.0.1", "zone.js": "~0.14.10" }, "devDependencies": { @@ -114,7 +114,7 @@ "@types/jasmine": "~5.1.4", "@types/leaflet": "^1.9.14", "@types/uuid": "^10.0.0", - "electron": "^32.2.0", + "electron": "^33.0.2", "electron-builder": "^25.1.8", "http-server": "^14.1.1", "husky": "^9.1.6", diff --git a/src/app/game/model/data/Loot.ts b/src/app/game/model/data/Loot.ts index d4b1b1c17..506b3d292 100644 --- a/src/app/game/model/data/Loot.ts +++ b/src/app/game/model/data/Loot.ts @@ -22,9 +22,11 @@ export enum LootType { special2 = "special2" } -export const enhancableLootTypes: LootType[] = [LootType.lumber, LootType.metal, LootType.hide, LootType.arrowvine, LootType.axenut, LootType.corpsecap, LootType.flamefruit, LootType.rockroot, LootType.snowthistle, LootType.money]; +export const resourceLootTypes: LootType[] = [LootType.lumber, LootType.metal, LootType.hide, LootType.arrowvine, LootType.axenut, LootType.corpsecap, LootType.flamefruit, LootType.rockroot, LootType.snowthistle]; -export const appliableLootTypes: LootType[] = [LootType.money, LootType.lumber, LootType.metal, LootType.hide, LootType.arrowvine, LootType.axenut, LootType.corpsecap, LootType.flamefruit, LootType.rockroot, LootType.snowthistle, LootType.special1, LootType.special2, LootType.random_item]; +export const enhancableLootTypes: LootType[] = [...resourceLootTypes, LootType.money]; + +export const appliableLootTypes: LootType[] = [...enhancableLootTypes, LootType.special1, LootType.special2, LootType.random_item]; export function getLootClass(type: LootType): LootClass { diff --git a/src/app/ui/figures/party/party-sheet-dialog.ts b/src/app/ui/figures/party/party-sheet-dialog.ts index 1e93d25a3..0fd15b3a2 100644 --- a/src/app/ui/figures/party/party-sheet-dialog.ts +++ b/src/app/ui/figures/party/party-sheet-dialog.ts @@ -1045,7 +1045,7 @@ export class PartySheetDialogComponent implements OnInit, OnDestroy { openResources() { this.dialog.open(PartyResourcesDialogComponent, { - panelClass: ['dialog-invert'], + panelClass: ['dialog'], }); } diff --git a/src/app/ui/figures/party/resources/resources.html b/src/app/ui/figures/party/resources/resources.html index 30a02a3b1..9acc41143 100644 --- a/src/app/ui/figures/party/resources/resources.html +++ b/src/app/ui/figures/party/resources/resources.html @@ -3,7 +3,9 @@ - + + + + + + + + + + + + + - - + +
@@ -19,11 +21,45 @@
+ - + {{character.progress.gold || '-'}} + + + {{totalGold || '-'}} +
+ - + {{character.progress.experience || '-'}} + + + {{totalXP || '-'}} +
{{(gameManager.game.party.loot[lootType] || '-')}} + {{(party.loot[lootType] || '-')}} + + - {{(character.progress.loot[lootType] || '-')}} + {{(character.progress.loot[lootType] || '-')}} + {{(total[lootType] || '-')}} @@ -32,4 +68,9 @@
+ +
+ + +
\ No newline at end of file diff --git a/src/app/ui/figures/party/resources/resources.scss b/src/app/ui/figures/party/resources/resources.scss index b35ce76ab..cf4d3d942 100644 --- a/src/app/ui/figures/party/resources/resources.scss +++ b/src/app/ui/figures/party/resources/resources.scss @@ -1,6 +1,7 @@ .resources-dialog { position: relative; + color: var(--ghs-color-white); table { border-collapse: collapse; @@ -15,14 +16,72 @@ border-bottom: calc(var(--ghs-unit) * 0.2 * var(--ghs-dialog-factor)) solid var(--ghs-color-darkgray); } + th { + label { + cursor: pointer; + font-size: calc(var(--ghs-unit) * 2 * var(--ghs-text-factor)); + display: flex; + justify-content: flex-end; + align-items: center; + } + } + tbody tr { + + td, + th { + position: relative; + z-index: 1; + + span, + input { + position: relative; + z-index: 2; + } + + input { + width: calc(var(--ghs-unit) * 4 * var(--ghs-dialog-factor)); + max-width: 100%; + text-align: center; + border: none; + outline: none; + } + } + &:nth-child(odd) { - background-color: var(--ghs-color-lightgray); + + td, + th { + &::before { + content: ' '; + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + background-color: var(--ghs-color-darkgray); + opacity: 0.3; + z-index: 0; + } + } } &:hover { - background-color: var(--ghs-color-yellow); - opacity: 0.5; + + td, + th { + &::before { + content: ' '; + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + background-color: var(--ghs-color-yellow); + opacity: 0.5; + z-index: 0; + } + } } } @@ -58,6 +117,35 @@ .ghs-svg { width: calc(var(--ghs-unit) * 3 * var(--ghs-dialog-factor)); height: auto; + filter: var(--ghs-filter-white) + } + } + + .buttons { + display: flex; + margin-top: calc(var(--ghs-unit) * 2 * var(--ghs-dialog-factor)); + font-family: var(--ghs-font-title); + font-size: calc(var(--ghs-unit) * 3 * var(--ghs-dialog-factor)); + justify-content: space-between; + align-items: center; + + a { + cursor: pointer; + min-width: 33%; + display: flex; + justify-content: center; + + &:hover { + opacity: 0.6; + } + } + + .cancel { + color: var(--ghs-color-red); + } + + .apply { + color: var(--ghs-color-green); } } } \ No newline at end of file diff --git a/src/app/ui/figures/party/resources/resources.ts b/src/app/ui/figures/party/resources/resources.ts index bc97b8bea..da2da5c0c 100644 --- a/src/app/ui/figures/party/resources/resources.ts +++ b/src/app/ui/figures/party/resources/resources.ts @@ -3,7 +3,8 @@ import { DialogRef } from "@angular/cdk/dialog"; import { Component, OnInit } from "@angular/core"; import { gameManager, GameManager } from "src/app/game/businesslogic/GameManager"; import { Character } from "src/app/game/model/Character"; -import { LootType } from "src/app/game/model/data/Loot"; +import { LootType, resourceLootTypes } from "src/app/game/model/data/Loot"; +import { Party } from "src/app/game/model/Party"; import { ghsDialogClosingHelper } from "src/app/ui/helper/Static"; @Component({ @@ -15,20 +16,70 @@ export class PartyResourcesDialogComponent implements OnInit { gameManager: GameManager = gameManager; + party: Party = new Party(); characters: Character[] = []; total: Partial> = {}; - lootColumns: LootType[] = [LootType.lumber, LootType.metal, LootType.hide, LootType.arrowvine, LootType.axenut, LootType.corpsecap, LootType.flamefruit, LootType.rockroot, LootType.snowthistle];; + totalGold: number = 0; + totalXP: number = 0; + lootColumns: LootType[] = resourceLootTypes; + + edit: boolean = false; + edited: boolean = false; constructor(private dialogRef: DialogRef) { } ngOnInit(): void { - this.characters = gameManager.game.figures.filter((figure) => figure instanceof Character).map((figure) => figure as Character); + this.party = JSON.parse(JSON.stringify(gameManager.game.party)); + this.characters = gameManager.game.figures.filter((figure) => figure instanceof Character).map((figure) => JSON.parse(JSON.stringify(figure))); + this.update(); + } + + update() { this.lootColumns.forEach((type) => { this.total[type] = (gameManager.game.party.loot[type] || 0); if (this.characters.length > 0) { this.total[type] = (this.total[type] || 0) + this.characters.map((character) => character.progress.loot[type] || 0).reduce((a, b) => a + b); } }) + if (this.characters.length) { + this.totalGold = this.characters.map((character) => character.progress.gold || 0).reduce((a, b) => a + b); + this.totalXP = this.characters.map((character) => character.progress.experience || 0).reduce((a, b) => a + b); + } + } + + changeLoot(character: Character | undefined, type: LootType, event: any) { + if (character) { + character.progress.loot[type] = +event.target.value || undefined; + } else { + this.party.loot[type] = +event.target.value || undefined; + } + this.update(); + this.edited = true; + } + + changeGold(character: Character, event: any) { + character.progress.gold = +event.target.value; + this.update(); + this.edited = true; + } + + changeXP(character: Character, event: any) { + character.progress.experience = +event.target.value; + this.update(); + this.edited = true; + } + + apply() { + gameManager.stateManager.before("applyResourceChange"); + gameManager.game.party.loot = this.party.loot; + gameManager.game.figures.filter((figure) => figure instanceof Character).forEach((figure) => { + const character = this.characters.find((character) => character.edition == figure.edition && character.name == figure.name); + if (character) { + figure.progress = character.progress; + } + }) + gameManager.stateManager.after(); + ghsDialogClosingHelper(this.dialogRef); } close() { diff --git a/src/app/ui/header/menu/campaign/campaign.html b/src/app/ui/header/menu/campaign/campaign.html index 29b1fff83..5b470dd00 100644 --- a/src/app/ui/header/menu/campaign/campaign.html +++ b/src/app/ui/header/menu/campaign/campaign.html @@ -29,19 +29,27 @@ -
+
-
+
+ +
+ +
-
+
-
+
+ +
+ +
@@ -50,10 +58,6 @@
-
- -
-
diff --git a/src/app/ui/header/menu/campaign/campaign.ts b/src/app/ui/header/menu/campaign/campaign.ts index 3164f7062..a63c67aef 100644 --- a/src/app/ui/header/menu/campaign/campaign.ts +++ b/src/app/ui/header/menu/campaign/campaign.ts @@ -12,6 +12,7 @@ import { ItemsDialogComponent } from "src/app/ui/figures/items/dialog/items-dial import { PartySheetDialogComponent } from "src/app/ui/figures/party/party-sheet-dialog"; import { WorldMapComponent } from "src/app/ui/figures/party/world-map/world-map"; import { ScenarioChartDialogComponent } from "../../../figures/party/scenario-chart/scenario-chart"; +import { PartyResourcesDialogComponent } from "src/app/ui/figures/party/resources/resources"; @Component({ @@ -159,6 +160,12 @@ export class CampaignMenuComponent implements OnInit { this.close.emit(); } + openResources() { + this.dialog.open(PartyResourcesDialogComponent, { + panelClass: ['dialog'], + }); + this.close.emit(); + } addParty() { let party = new Party(); diff --git a/src/assets/locales/de.json b/src/assets/locales/de.json index 720064ee8..bb5342ed7 100644 --- a/src/assets/locales/de.json +++ b/src/assets/locales/de.json @@ -37,6 +37,7 @@ "name": "Name für Kampagne {0}", "reset": "Kampagne zurücksetzen" }, + "resources": "Ressourcen Übersicht", "sheet": "Globaler Kampagnenbogen" }, "cancel": "Abbrechen", @@ -1016,6 +1017,8 @@ "summer": "Sommer", "supply": { ".": "Versorgung von Frosthaven", + "apply": "Änderungen anwenden", + "edit": "Bearbeiten", "total": "Insgesamt" }, "totalDefense": "Gesamte Verteidigung", diff --git a/src/assets/locales/en.json b/src/assets/locales/en.json index e47200b35..689d27296 100644 --- a/src/assets/locales/en.json +++ b/src/assets/locales/en.json @@ -37,6 +37,7 @@ "name": "Name for Campaign {0}", "reset": "Reset Campaign" }, + "resources": "Resource Overview Table", "sheet": "Global Campaign Management Sheet", "trials": { ".": "Trials", @@ -1233,6 +1234,8 @@ "summer": "Summer", "supply": { ".": "Frosthaven Supply", + "apply": "Apply changes", + "edit": "Edit", "total": "Total" }, "totalDefense": "Total Defense",