diff --git a/data/fh/scenarios/093B.json b/data/fh/scenarios/093B.json
index a73fa87a8..d3947dc1c 100644
--- a/data/fh/scenarios/093B.json
+++ b/data/fh/scenarios/093B.json
@@ -4,8 +4,8 @@
"edition": "fh",
"complexity": 2,
"rewards": {
- "items": [
- "235"
+ "itemBlueprints": [
+ "79"
]
},
"monsters": [
diff --git a/package-lock.json b/package-lock.json
index e9ede4772..6b7ca2409 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "gloomhavensecretariat",
- "version": "0.83.6",
+ "version": "0.83.7",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "gloomhavensecretariat",
- "version": "0.83.6",
+ "version": "0.83.7",
"license": "AGPL3",
"dependencies": {
"@angular/animations": "^17.0.6",
diff --git a/package.json b/package.json
index 5773cefc3..563bdb5dd 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "gloomhavensecretariat",
- "version": "0.83.6",
+ "version": "0.83.7",
"license": "AGPL3",
"description": "Gloomhaven Secretariat is a Gloomhaven Companion app.",
"homepage": "https://gloomhaven-secretariat.de",
diff --git a/src/app/ui/figures/actions/action.ts b/src/app/ui/figures/actions/action.ts
index 25a97f1df..914d00ce3 100644
--- a/src/app/ui/figures/actions/action.ts
+++ b/src/app/ui/figures/actions/action.ts
@@ -235,6 +235,9 @@ export class ActionComponent implements OnInit, OnDestroy {
if (this.action.valueType == ActionValueType.plus) {
return statValue + EntityValueFunction(this.action.value);
} else if (this.action.valueType == ActionValueType.minus) {
+ if (!statValue) {
+ return "-";
+ }
return statValue - EntityValueFunction(this.action.value);
}
}
diff --git a/src/app/ui/footer/scenario/summary/scenario-summary.ts b/src/app/ui/footer/scenario/summary/scenario-summary.ts
index 8ff14b4f6..362a691c4 100644
--- a/src/app/ui/footer/scenario/summary/scenario-summary.ts
+++ b/src/app/ui/footer/scenario/summary/scenario-summary.ts
@@ -534,18 +534,42 @@ export class ScenarioSummaryComponent {
}
changeCollectiveGold(event: any, index: number) {
- gameManager.stateManager.before("finishScenario.dialog.collectiveGold", '' + index, event.target.value);
- this.collectiveGold[index] = +event.target.value;
- this.updateFinish();
- gameManager.stateManager.after();
+ let value = +event.target.value;
+ const old = this.collectiveGold[index] || 0;
+ this.collectiveGold[index] = 0;
+ if (value < 0) {
+ value = 0;
+ } else if (value > this.availableCollectiveGold()) {
+ value = this.availableCollectiveGold();
+ }
+ this.collectiveGold[index] = old;
+ if (value != (this.collectiveGold[index] || 0)) {
+ gameManager.stateManager.before("finishScenario.dialog.collectiveGold", '' + index, event.target.value);
+ this.collectiveGold[index] = +event.target.value;
+ this.updateFinish();
+ gameManager.stateManager.after();
+ }
+ event.target.value = value;
}
changeCollectiveResource(event: any, index: number, type: LootType) {
- gameManager.stateManager.before("finishScenario.dialog.collectiveResource", type, '' + index, event.target.value);
- this.collectiveResources[index] = this.collectiveResources[index] || {};
- this.collectiveResources[index][type] = +event.target.value;
- this.updateFinish();
- gameManager.stateManager.after();
+ let value = +event.target.value;
+ const old = this.collectiveResources[index][type] || 0;
+ this.collectiveResources[index][type] = 0;
+ if (value < 0) {
+ value = 0;
+ } else if (value > this.availableCollectiveResource(type)) {
+ value = this.availableCollectiveResource(type);
+ }
+ this.collectiveResources[index][type] = old;
+ if (value != (this.collectiveResources[index][type] || 0)) {
+ gameManager.stateManager.before("finishScenario.dialog.collectiveResource", type, '' + index, event.target.value);
+ this.collectiveResources[index] = this.collectiveResources[index] || {};
+ this.collectiveResources[index][type] = value;
+ this.updateFinish();
+ gameManager.stateManager.after();
+ }
+ event.target.value = value;
}
changeCalendarSectionManual(event: any, index: number) {
diff --git a/src/app/ui/header/element/element.scss b/src/app/ui/header/element/element.scss
index 25e4dd423..14111fd6c 100644
--- a/src/app/ui/header/element/element.scss
+++ b/src/app/ui/header/element/element.scss
@@ -67,9 +67,10 @@ ghs-element {
}
}
- &.new #outline {
- display: none;
+ &.new #outline path {
+ fill: var(--ghs-color-gray) !important;
}
+
}
&:hover .element-svg {
@@ -78,6 +79,10 @@ ghs-element {
#bg {
opacity: 1 !important;
}
+
+ &.new #outline path {
+ fill: var(--ghs-color-white) !important;
+ }
}
&.consume {
diff --git a/src/app/ui/header/menu/settings/settings.html b/src/app/ui/header/menu/settings/settings.html
index ade639b70..a3365d038 100644
--- a/src/app/ui/header/menu/settings/settings.html
+++ b/src/app/ui/header/menu/settings/settings.html
@@ -659,14 +659,15 @@
+ [ngClass]="{'immunity': settingsManager.settings.applyConditionsExcludes.indexOf(condition.name) != -1}"
+ (click)="toggleApplyConditionsExclude(condition.name)">
+ [src]="'./assets/images' + (settingsManager.settings.fhStyle ? '/fh' : '') + '/condition/' + condition.name + '.svg'" />
+
X
2}">
-
+
@@ -710,14 +711,15 @@
+ [ngClass]="{'immunity': settingsManager.settings.activeApplyConditionsExcludes.indexOf(condition.name) != -1}"
+ (click)="toggleActiveApplyConditionsExclude(condition.name)">
+ [src]="'./assets/images' + (settingsManager.settings.fhStyle ? '/fh' : '') + '/condition/' + condition.name + '.svg'" />
+
X
2}">
-
+
diff --git a/src/app/ui/header/menu/settings/settings.scss b/src/app/ui/header/menu/settings/settings.scss
index cdd8f32dc..d1ab39789 100644
--- a/src/app/ui/header/menu/settings/settings.scss
+++ b/src/app/ui/header/menu/settings/settings.scss
@@ -26,6 +26,8 @@
cursor: pointer;
width: calc(var(--ghs-unit) * 3.5 * var(--ghs-dialog-factor));
height: calc(var(--ghs-unit) * 3.5 * var(--ghs-dialog-factor));
+ position: relative;
+ display: flex;
&.immunity {
opacity: 0.7;
@@ -41,6 +43,16 @@
width: 100%;
height: auto;
}
+
+ .value {
+ font-family: var(--ghs-font-title);
+ font-size: calc(var(--ghs-unit) * 1.3 * var(--ghs-dialog-factor));
+ color: var(--ghs-color-white);
+ position: absolute;
+ bottom: 0;
+ left: calc(var(--ghs-unit) * 1.8 * var(--ghs-dialog-factor));
+ transform: translateX(-50%);
+ }
}
.hint-trigger {
diff --git a/src/app/ui/header/menu/settings/settings.ts b/src/app/ui/header/menu/settings/settings.ts
index 3aaafc077..333865aba 100644
--- a/src/app/ui/header/menu/settings/settings.ts
+++ b/src/app/ui/header/menu/settings/settings.ts
@@ -22,19 +22,22 @@ export class SettingsMenuComponent {
GameState = GameState;
SubMenu = SubMenu;
wakeLock: boolean;
- applyConditionsExcludes: ConditionName[] = [];
- activeApplyConditionsExcludes: ConditionName[] = [];
+ applyConditionsExcludes: Condition[] = [];
+ activeApplyConditionsExcludes: Condition[] = [];
WebSocket = WebSocket;
+ ConditionType = ConditionType;
constructor(public platform: Platform) {
this.wakeLock = 'wakeLock' in navigator;
Object.keys(ConditionName).forEach((conditionName) => {
const condition = new Condition(conditionName);
- if (condition.types.indexOf(ConditionType.turn) != -1 || condition.types.indexOf(ConditionType.afterTurn) != -1) {
- this.applyConditionsExcludes.push(condition.name);
- } if (condition.types.indexOf(ConditionType.apply) != -1) {
- this.activeApplyConditionsExcludes.push(condition.name);
+ if (!gameManager.game.edition || gameManager.conditions(gameManager.game.edition).map((condition) => condition.name).indexOf(condition.name) != -1 || condition.types.indexOf(ConditionType.hidden) != -1) {
+ if (condition.types.indexOf(ConditionType.turn) != -1 || condition.types.indexOf(ConditionType.afterTurn) != -1) {
+ this.applyConditionsExcludes.push(condition);
+ } if (condition.types.indexOf(ConditionType.apply) != -1) {
+ this.activeApplyConditionsExcludes.push(condition);
+ }
}
})
}
diff --git a/src/app/ui/helper/label.ts b/src/app/ui/helper/label.ts
index 5629f53ff..311bc4a23 100644
--- a/src/app/ui/helper/label.ts
+++ b/src/app/ui/helper/label.ts
@@ -36,16 +36,15 @@ export const applyPlaceholder = function (value: string, placeholder: string[] =
let replace: string = match;
let image: string = '';
if (type == "condition") {
- image = '';
+ image = '';
+ image += '';
if (value) {
image += '' + value + '';
}
- replace = '' + (fh ? ' ' : settingsManager.getLabel('game.condition.' + split[2])) + image + '';
+ image += '';
+ replace = '' + (fh ? ' ' : settingsManager.getLabel('game.condition.' + split[2], [value ? value : ''])) + image + '';
} else if (type == "immunity") {
- image = '';
- if (value) {
- image += '' + value + '';
- }
+ image = '' + (value ? '' + value + '' : '') + '';
replace = '' + (fh ? ' ' : settingsManager.getLabel('game.condition.' + split[2])) + image + '';
} else if (type == "action" && split.length == 3 && !split[2].startsWith('specialTarget') && !split[2].startsWith('summon') && !split[2].startsWith('area')) {
split.splice(0, 1);
diff --git a/src/assets/locales/de.json b/src/assets/locales/de.json
index ccea2483a..cb67d8869 100644
--- a/src/assets/locales/de.json
+++ b/src/assets/locales/de.json
@@ -1411,7 +1411,7 @@
"brittle": "Nachfragen ob nach erhaltenden Schaden %game.condition.brittle% angewendet werden soll um den Schaden zu erhöhen.",
"heal": "Kein Zustand, aber eine Hilfe ob %game.action.heal% angwendet werden soll wenn die Trefferpunkte erhöht werden.",
"poison": "Nachfragen ob nach erhaltenden Schaden %game.action.attack% +1 von %game.condition.poison% angewendet werden soll (inklusive %game.attackmodifier.double%).",
- "poison_x": "Nachfragen ob nach erhaltenden Schaden %game.action.attack% +1 von %game.condition.poison_x% angewendet werden soll (inklusive %game.attackmodifier.double%).",
+ "poison_x": "Nachfragen ob nach erhaltenden Schaden %game.action.attack% +X von %game.condition.poison_x:X% angewendet werden soll (inklusive %game.attackmodifier.double%).",
"shield": "Kein Zustand, aber eine Hilfe ob nach erhaltenden Schaden %game.action.shield% angwendet werden soll.",
"ward": "Nachfragen ob nach erhaltenden Schaden %game.condition.ward% angewendet werden soll um den erhaltenden Schaden zu reduzieren."
}
@@ -1468,7 +1468,7 @@
"bane": "Am Ende des Zuges automatisch %game.condition.bane% Schaden hinzufügen.",
"regenerate": "Am Anfang des Zuges automatisch %game.condition.regenerate% anwenden.",
"wound": "Am Anfang des Zuges automatisch %game.condition.wound% Schaden hinzufügen.",
- "wound_x": "Am Anfang des Zuges automatisch %game.condition.wound_x% Schaden hinzufügen."
+ "wound_x": "Am Anfang des Zuges automatisch %game.condition.wound_x:X% Schaden hinzufügen."
}
},
"applyLongRest": {
diff --git a/src/assets/locales/en.json b/src/assets/locales/en.json
index 9c7cefe3f..ab1d6c8bf 100644
--- a/src/assets/locales/en.json
+++ b/src/assets/locales/en.json
@@ -1560,7 +1560,7 @@
"brittle": "On suffering damage, ask to apply %game.condition.brittle% and increase damage.",
"heal": "No condition, but helper if %game.action.heal% should be applied when increasing hitpoints.",
"poison": "On suffering damage, ask to apply %game.action.attack% +1 from %game.condition.poison% (including %game.attackmodifier.double%).",
- "poison_x": "On suffering damage, ask to apply %game.action.attack% +1 from %game.condition.poison_x% (including %game.attackmodifier.double%).",
+ "poison_x": "On suffering damage, ask to apply %game.action.attack% +X from %game.condition.poison_x:X% (including %game.attackmodifier.double%).",
"shield": "No condition, but helper if %game.action.shield% should be applied when taking damage.",
"ward": "On suffering damage, ask to apply %game.condition.ward% and lowering damage."
}
@@ -1617,7 +1617,7 @@
"bane": "Automatic apply %game.condition.bane% damage at end of turn.",
"regenerate": "Automatic apply %game.condition.regenerate% at start of turn.",
"wound": "Automatic apply %game.condition.wound% damage at end of turn.",
- "wound_x": "Automatic apply %game.condition.wound_x% damage at end of turn."
+ "wound_x": "Automatic apply %game.condition.wound_x:X% damage at end of turn."
}
},
"applyLongRest": {
diff --git a/src/styles.scss b/src/styles.scss
index 3991ac343..feeca1de6 100644
--- a/src/styles.scss
+++ b/src/styles.scss
@@ -1063,6 +1063,16 @@ input[type="radio"] {
.icon {
margin: 0;
}
+
+ .value {
+ font-family: var(--ghs-font-title);
+ font-size: 0.6em;
+ color: var(--ghs-color-white);
+ position: absolute;
+ bottom: -0.2em;
+ left: 1.1em;
+ transform: translateX(-50%);
+ }
}
}