Skip to content

Commit

Permalink
address #160, #315, #346, small other improvements and fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
Lurkars committed Jul 30, 2023
1 parent 4d2a842 commit 3976a54
Show file tree
Hide file tree
Showing 25 changed files with 392 additions and 128 deletions.
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

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.70.3",
"version": "0.70.4",
"license": "AGPL3",
"description": "Gloomhaven Secretariat is a Gloomhaven Companion app.",
"homepage": "https://gloomhaven-secretariat.de",
Expand Down
6 changes: 6 additions & 0 deletions src/app/app.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,12 @@ export class AppComponent implements OnInit {
document.body.classList.remove('modern');
this.meta.updateTag({ name: 'theme-color', content: '#936658' });
}

if (settingsManager.settings.portraitMode) {
document.body.classList.add('portrait-mode');
} else {
document.body.classList.remove('portrait-mode');
}
}

applyAnimations() {
Expand Down
10 changes: 6 additions & 4 deletions src/app/game/businesslogic/CharacterManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -254,18 +254,20 @@ export class CharacterManager {

character.level = level;

if (character.health == character.maxHealth) {
character.health = character.stat.health;
}
const adjustHealth = character.health == character.maxHealth;

character.maxHealth = character.stat.health;

if (character.name == 'shackles' && character.edition == 'fh' && character.progress.perks[11] == 2) {
character.maxHealth += 5;
}

if (character.progress.equippedItems.find((identifier) => identifier.edition == 'fh' && identifier.name == '3')) {
character.maxHealth += 1;
character.health += 1;
}

if (character.health > character.maxHealth) {
if (character.health > character.maxHealth || adjustHealth) {
character.health = character.maxHealth;
}

Expand Down
45 changes: 37 additions & 8 deletions src/app/game/businesslogic/EntityManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -181,22 +181,51 @@ export class EntityManager {
return entity.entityConditions.filter((value) => (!value.expired || expiredIndicator && value.types.indexOf(ConditionType.expiredIndicator) != -1) && (hidden || value.types.indexOf(ConditionType.hidden) == -1));
}

isImmune(monster: Monster, entity: MonsterEntity, conditionName: ConditionName): boolean {
const stat = monster.stats.find((monsterStat) => monsterStat.level == entity.level && monsterStat.type == entity.type);
isImmune(entity: Entity, figure: Figure, conditionName: ConditionName): boolean {
let immune: boolean = false;
if (figure instanceof Monster && entity instanceof MonsterEntity) {
const stat = figure.stats.find((monsterStat) => monsterStat.level == entity.level && monsterStat.type == entity.type);
immune = stat != undefined && stat.immunities != undefined && stat.immunities.indexOf(conditionName as string) != -1;
} else if (figure instanceof Character) {
let immunities: ConditionName[] = [];
if (figure.progress.equippedItems.find((identifier) => identifier.edition == 'gh' && identifier.name == '38')) {
immunities.push(ConditionName.stun, ConditionName.muddle);
}
if (figure.progress.equippedItems.find((identifier) => identifier.edition == 'gh' && identifier.name == '52')) {
immunities.push(ConditionName.poison, ConditionName.wound);
}
if (figure.progress.equippedItems.find((identifier) => identifier.edition == 'gh' && identifier.name == '103')) {
immunities.push(ConditionName.poison, ConditionName.wound);
}
if (figure.progress.equippedItems.find((identifier) => identifier.edition == 'cs' && identifier.name == '57')) {
immunities.push(ConditionName.muddle);
}
if (figure.progress.equippedItems.find((identifier) => identifier.edition == 'fh' && identifier.name == '138')) {
immunities.push(ConditionName.disarm, ConditionName.stun, ConditionName.muddle);
}

if (figure.name == 'blinkblade' && figure.edition == 'fh' && figure.progress.perks[10]) {
immunities.push(ConditionName.immobilize);
} else if (figure.name == 'coral' && figure.edition == 'fh' && figure.progress.perks[7]) {
immunities.push(ConditionName.impair);
} else if (figure.name == 'prism' && figure.edition == 'fh' && figure.progress.perks[9]) {
immunities.push(ConditionName.wound);
}

let immune = stat != undefined && stat.immunities != undefined && stat.immunities.indexOf(conditionName as string) != -1;
immune = immunities.indexOf(conditionName) != -1;
}

if (!immune) {
if (conditionName == ConditionName.wound_x) {
return this.isImmune(monster, entity, ConditionName.wound);
return this.isImmune(entity, figure, ConditionName.wound);
} else if (conditionName == ConditionName.poison_x) {
return this.isImmune(monster, entity, ConditionName.poison);
return this.isImmune(entity, figure, ConditionName.poison);
} else if (conditionName == ConditionName.rupture) {
return this.isImmune(monster, entity, ConditionName.wound);
return this.isImmune(entity, figure, ConditionName.wound);
} else if (conditionName == ConditionName.infect) {
return this.isImmune(monster, entity, ConditionName.poison);
return this.isImmune(entity, figure, ConditionName.poison);
} else if (conditionName == ConditionName.chill) {
return this.isImmune(monster, entity, ConditionName.immobilize) || this.isImmune(monster, entity, ConditionName.muddle);
return this.isImmune(entity, figure, ConditionName.immobilize) || this.isImmune(entity, figure, ConditionName.muddle);
}
}

Expand Down
10 changes: 8 additions & 2 deletions src/app/game/businesslogic/RoundManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -310,8 +310,14 @@ export class RoundManager {

if (figure instanceof Character && settingsManager.settings.applyLongRest && figure.longRest && (skipSummons || !figure.summons.some((summon) => summon.active))) {
if (figure.health < figure.maxHealth || figure.entityConditions.find((entityCondition) => !entityCondition.expired && entityCondition.types.indexOf(ConditionType.clearHeal) != -1 && !entityCondition.permanent)) {
figure.health += 2;
gameManager.entityManager.addCondition(figure, new Condition(ConditionName.heal, 2), figure.active || false, figure.off || false);
let heal = 2;

if (figure.name == 'lightning' && figure.edition == 'fh-crossover' && figure.progress.perks[9]) {
heal += 1;
}

figure.health += heal;
gameManager.entityManager.addCondition(figure, new Condition(ConditionName.heal, heal), figure.active || false, figure.off || false);
gameManager.entityManager.applyCondition(figure, ConditionName.heal, true);
}
}
Expand Down
5 changes: 5 additions & 0 deletions src/app/game/businesslogic/SettingsManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -474,6 +474,11 @@ export class SettingsManager {
this.storeSettings();
}

setPortraitMode(portraitMode: boolean) {
this.settings.portraitMode = portraitMode;
this.storeSettings();
}

setPressDoubleClick(pressDoubleClick: boolean) {
this.settings.pressDoubleClick = pressDoubleClick;
this.storeSettings();
Expand Down
1 change: 1 addition & 0 deletions src/app/game/businesslogic/StateManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,7 @@ export class StateManager {
settings.fhStyle = settingsManager.settings.fhStyle;
settings.fontsize = settingsManager.settings.fontsize;
settings.fullscreen = settingsManager.settings.fullscreen;
settings.portraitMode = settingsManager.settings.portraitMode;
settings.pressDoubleClick = settingsManager.settings.pressDoubleClick;
settings.serverAutoconnect = settingsManager.settings.serverAutoconnect;
settings.serverPassword = settingsManager.settings.serverPassword;
Expand Down
1 change: 1 addition & 0 deletions src/app/game/model/Settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ export class Settings {
locale: string = "en";
lootDeck: boolean = true;
maxUndo: number = 100;
portraitMode: boolean = true;
monsters: boolean = true;
moveElements: boolean = true;
partySheet: boolean = true;
Expand Down
8 changes: 1 addition & 7 deletions src/app/ui/figures/character/cards/initiative-dialog.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,13 +74,6 @@ export class CharacterInitiativeDialogComponent {
setInitiative(initiative: number) {
if (((gameManager.game.state == GameState.draw || !settingsManager.settings.initiativeRequired) && initiative >= 0 || initiative > 0) && initiative < 100 && initiative != this.figure.initiative) {
this.figure.initiative = initiative;
if (this.character) {
if (initiative == 99 && !this.character.longRest) {
this.character.longRest = true;
} else {
this.character.longRest = false;
}
}
if (this.character) {
this.character.initiativeVisible = true;
}
Expand All @@ -99,6 +92,7 @@ export class CharacterInitiativeDialogComponent {
this.character.longRest = true;
} else {
this.setInitiative(99);
this.character.longRest = true;
if (gameManager.game.state == GameState.next) {
gameManager.sortFigures(this.character);
}
Expand Down
10 changes: 6 additions & 4 deletions src/app/ui/figures/character/character.html
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
<div class="summons-container" *ngIf="!character.absent"
[ngClass]="{'empty' : emptySummons, 'off' : character.off || character.exhausted || character.health <= 0 }">
[ngClass]="{'empty' : summonCount == 0, 'off' : character.off || character.exhausted || character.health <= 0 }">
<span class="spacer"></span>
<span class="icon" [ngClass]="{'empty' : emptySummons}" [entityAnimation]="emptySummons">
<img [src]="character.iconUrl" />
<span class="entities-menu" [ngClass]="{'empty' : summonCount == 0, 'disabled' : summonCount < 2}" [entityAnimation]="summonCount == 0"
(click)="openEntitiesMenu($event)">
<img class="icon" [src]="character.iconUrl" />
<img class="menu" src="./assets/images/up.svg">
</span>
<div class="summons">
<div class="summons" *ngIf="summonCount">
<ghs-summon-entity *ngFor="let summon of character.summons" [character]="character" [summon]="summon">
</ghs-summon-entity>
</div>
Expand Down
43 changes: 38 additions & 5 deletions src/app/ui/figures/character/character.scss
Original file line number Diff line number Diff line change
Expand Up @@ -115,18 +115,32 @@
height: 100%;
}

.icon {
.entities-menu {
cursor: pointer;
position: relative;
display: block;
width: calc(var(--ghs-unit) * 6);
width: auto;
height: calc(var(--ghs-unit) * 6);
margin-right: calc(var(--ghs-unit) * 1);

img {
width: 100%;
height: auto;
img.icon {
height: 100%;
width: auto;
filter: var(--ghs-filter-shadow);
}

img.menu {
position: absolute;
top: 50%;
left: calc(var(--ghs-unit) * -4);
transform: translateY(-50%);
opacity: 0.5;
width: calc(var(--ghs-unit) * 3.7 * var(--ghs-text-factor));
height: auto;
filter: var(--ghs-filter-darkgray);
opacity: 0.5;
}

&:not(.empty) {
opacity: 1;
transform: translate(0%, 0%);
Expand All @@ -137,6 +151,25 @@
max-width: 0;
transform: translate(0%, 100%);
}

&.disabled {
cursor: initial;
pointer-events: none;

img.menu {
display: none;
}
}

&:hover {
img.icon {
opacity: 0.5;
}

img.menu {
opacity: 1;
}
}
}

.summons {
Expand Down
15 changes: 13 additions & 2 deletions src/app/ui/figures/character/character.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import { Subscription } from 'rxjs';
import { CharacterBattleGoalsDialog } from '../battlegoal/dialog/battlegoal-dialog';
import { ItemsCharacterDialogComponent } from '../items/character/items-character-dialog';
import { ItemsDialogComponent } from '../items/dialog/items-dialog';
import { EntitiesMenuDialogComponent } from '../entities-menu/entities-menu-dialog';

@Component({
selector: 'ghs-character',
Expand Down Expand Up @@ -51,7 +52,7 @@ export class CharacterComponent implements OnInit, OnDestroy {
maxHp: number = 0;
token: number = 0;

emptySummons: boolean = true;
summonCount: number = 0;
activeConditions: EntityCondition[] = [];

constructor(private dialog: Dialog, private overlay: Overlay) { }
Expand All @@ -70,7 +71,7 @@ export class CharacterComponent implements OnInit, OnDestroy {
}

update(): void {
this.emptySummons = this.character.summons.length == 0 || this.character.summons.every((summon) => !gameManager.entityManager.isAlive(summon));
this.summonCount = this.character.summons.filter((summon) => gameManager.entityManager.isAlive(summon)).length;
this.activeConditions = gameManager.entityManager.activeConditions(this.character);
}

Expand Down Expand Up @@ -288,6 +289,16 @@ export class CharacterComponent implements OnInit, OnDestroy {
// }
}

openEntitiesMenu(event: any) {
this.dialog.open(EntitiesMenuDialogComponent, {
panelClass: 'dialog',
data: {
character: this.character
},
positionStrategy: this.overlay.position().flexibleConnectedTo(event.target).withPositions(ghsDefaultDialogPositions())
});
}

openSummonDialog(event: any): void {
this.dialog.open(CharacterSummonDialog, {
panelClass: 'dialog',
Expand Down
4 changes: 2 additions & 2 deletions src/app/ui/figures/character/fullview/fullview.html
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
<div class="container">
<div class="summons-container"
[ngClass]="{'empty' : emptySummons, 'off' : character.off || character.exhausted || character.health <= 0 }">
[ngClass]="{'empty' : summonCount == 0, 'off' : character.off || character.exhausted || character.health <= 0 }">
<span class="spacer"></span>
<span class="icon" [ngClass]="{'empty' : emptySummons}" [entityAnimation]="emptySummons">
<span class="icon" [ngClass]="{'empty' : summonCount == 0}" [entityAnimation]="summonCount == 0">
<img [src]="character.iconUrl" />
</span>
<div class="summons">
Expand Down
10 changes: 10 additions & 0 deletions src/app/ui/figures/character/sheet/character-sheet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -347,6 +347,16 @@ export class CharacterSheetComponent implements OnInit, AfterViewInit {
}
this.character.mergeAttackModifierDeck(gameManager.attackModifierManager.buildCharacterAttackModifierDeck(this.character));
gameManager.attackModifierManager.shuffleModifiers(this.character.attackModifierDeck);

if (this.character.name == 'shackles' && this.character.edition == 'fh' && index == 11) {
if (this.character.progress.perks[index] == 2) {
this.character.maxHealth += 5;
} else {
this.character.maxHealth -= 5;
}
this.character.health = this.character.maxHealth;
}

gameManager.stateManager.after();
}
}
Expand Down
29 changes: 5 additions & 24 deletions src/app/ui/figures/conditions/conditions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -124,33 +124,14 @@ export class ConditionsComponent implements OnInit {
}

isImmune(conditionName: ConditionName): boolean {

if (this.figure instanceof Character) {
let immunities: ConditionName[] = [];
if (this.figure.progress.equippedItems.find((identifier) => identifier.edition == 'gh' && identifier.name == '38')) {
immunities.push(ConditionName.stun, ConditionName.muddle);
}
if (this.figure.progress.equippedItems.find((identifier) => identifier.edition == 'gh' && identifier.name == '52')) {
immunities.push(ConditionName.poison, ConditionName.wound);
}
if (this.figure.progress.equippedItems.find((identifier) => identifier.edition == 'gh' && identifier.name == '103')) {
immunities.push(ConditionName.poison, ConditionName.wound);
}
if (this.figure.progress.equippedItems.find((identifier) => identifier.edition == 'cs' && identifier.name == '57')) {
immunities.push(ConditionName.muddle);
}
if (this.figure.progress.equippedItems.find((identifier) => identifier.edition == 'fh' && identifier.name == '138')) {
immunities.push(ConditionName.disarm, ConditionName.stun, ConditionName.muddle);
}

return immunities.indexOf(conditionName) != -1;
}

if (this.figure instanceof Monster) {
if (!(this.entity instanceof MonsterEntity)) {
return this.entities.every((entity) => this.figure instanceof Monster && entity instanceof MonsterEntity && gameManager.entityManager.isImmune(this.figure, entity, conditionName));
return this.entities.every((entity) => this.figure instanceof Monster && entity instanceof MonsterEntity && gameManager.entityManager.isImmune(entity, this.figure, conditionName));
} else {
return gameManager.entityManager.isImmune(this.entity, this.figure, conditionName);
}
return gameManager.entityManager.isImmune(this.figure, this.entity, conditionName);
} else if (this.figure instanceof Character && this.entity instanceof Character) {
return gameManager.entityManager.isImmune(this.entity, this.figure, conditionName);
}

return false;
Expand Down
Loading

0 comments on commit 3976a54

Please sign in to comment.