Browse Source

Added advantage and disadvantage to skillchecks and savethrows

Warafear 11 tháng trước cách đây
mục cha
commit
d918489e00
12 tập tin đã thay đổi với 187 bổ sung5 xóa
  1. 31 0
      src/app/journal/journal-stats/attribute-skill-container/save-throw-panel/save-throw-details/save-throw-details.component.html
  2. 6 0
      src/app/journal/journal-stats/attribute-skill-container/save-throw-panel/save-throw-details/save-throw-details.component.scss
  3. 22 1
      src/app/journal/journal-stats/attribute-skill-container/save-throw-panel/save-throw-details/save-throw-details.component.ts
  4. 9 1
      src/app/journal/journal-stats/attribute-skill-container/save-throw-panel/save-throw-field/save-throw-field.component.html
  5. 7 0
      src/app/journal/journal-stats/attribute-skill-container/save-throw-panel/save-throw-field/save-throw-field.component.scss
  6. 20 1
      src/app/journal/journal-stats/attribute-skill-container/save-throw-panel/save-throw-field/save-throw-field.component.ts
  7. 33 0
      src/app/journal/journal-stats/attribute-skill-container/skill-panel/skill-details/skill-details.component.html
  8. 6 0
      src/app/journal/journal-stats/attribute-skill-container/skill-panel/skill-details/skill-details.component.scss
  9. 20 0
      src/app/journal/journal-stats/attribute-skill-container/skill-panel/skill-details/skill-details.component.ts
  10. 9 1
      src/app/journal/journal-stats/attribute-skill-container/skill-panel/skill-field/skill-field.component.html
  11. 8 0
      src/app/journal/journal-stats/attribute-skill-container/skill-panel/skill-field/skill-field.component.scss
  12. 16 1
      src/app/journal/journal-stats/attribute-skill-container/skill-panel/skill-field/skill-field.component.ts

+ 31 - 0
src/app/journal/journal-stats/attribute-skill-container/save-throw-panel/save-throw-details/save-throw-details.component.html

@@ -8,3 +8,34 @@
 </div>
 
 <value-box [value]="saveModifier" [label]="'general.modifier'"></value-box>
+
+<mat-radio-group [(ngModel)]="advantage" (change)="showButtons()">
+  <mat-radio-button class="example-radio-button" [value]="'none'">{{
+    "skillDetails.none" | translate
+  }}</mat-radio-button>
+  <mat-radio-button class="example-radio-button" [value]="'advantage'">{{
+    "skillDetails.advantage" | translate
+  }}</mat-radio-button>
+  <mat-radio-button class="example-radio-button" [value]="'disadvantage'">{{
+    "skillDetails.disadvantage" | translate
+  }}</mat-radio-button>
+</mat-radio-group>
+
+@if (showButtonsContainer) {
+  <div class="vertical-buttons bottom">
+    <ui-button
+      [color]="'green'"
+      [type]="'apply'"
+      [width]="'w20'"
+      (click)="close('update')"
+    >
+    </ui-button>
+    <ui-button
+      [color]="'red'"
+      [type]="'discard'"
+      [width]="'w20'"
+      (click)="close('cancel')"
+    >
+    </ui-button>
+  </div>
+}

+ 6 - 0
src/app/journal/journal-stats/attribute-skill-container/save-throw-panel/save-throw-details/save-throw-details.component.scss

@@ -0,0 +1,6 @@
+mat-radio-group {
+  display: flex;
+  flex-direction: column;
+  margin: 1rem 0;
+  align-items: flex-start;
+}

+ 22 - 1
src/app/journal/journal-stats/attribute-skill-container/save-throw-panel/save-throw-details/save-throw-details.component.ts

@@ -1,5 +1,6 @@
 import { Component, Input } from '@angular/core';
 import { TranslateService } from '@ngx-translate/core';
+import { DetailsService } from 'src/services/details/details.service';
 
 @Component({
   selector: 'app-save-throw-details',
@@ -9,6 +10,26 @@ import { TranslateService } from '@ngx-translate/core';
 export class SaveThrowDetailsComponent {
   @Input() attributeName: string = '';
   @Input() saveModifier: string = '';
+  @Input() advantage: 'none' | 'advantage' | 'disadvantage' = 'none';
 
-  constructor(public translate: TranslateService) {}
+  public showButtonsContainer: boolean = false;
+
+  constructor(
+    public translate: TranslateService,
+    public detailsAccessor: DetailsService,
+  ) {}
+
+  public showButtons(): void {
+    this.showButtonsContainer = true;
+  }
+
+  public close(result: string): void {
+    if (result === 'update') {
+      this.detailsAccessor.closePanel(result, {
+        advantage: this.advantage,
+      });
+    } else if (result === 'cancel') {
+      this.detailsAccessor.closePanel(result);
+    }
+  }
 }

+ 9 - 1
src/app/journal/journal-stats/attribute-skill-container/save-throw-panel/save-throw-field/save-throw-field.component.html

@@ -10,5 +10,13 @@
     {{ "attributes." + attribute.name | translate }}
   </div>
 
-  <div class="save-throw-field__value">{{ saveModifier }}</div>
+  <div [class]="attribute.advantage" class="save-throw-field__value">
+    {{ saveModifier }}
+  </div>
+  <!-- TODO: Potential Advantage style -->
+  <!-- @if (skill.advantage !== "none") {
+    <span>
+      <icon [size]="'xs'" [type]="'UI'" [icon]="skill.advantage!"></icon>
+    </span>
+  } -->
 </div>

+ 7 - 0
src/app/journal/journal-stats/attribute-skill-container/save-throw-panel/save-throw-field/save-throw-field.component.scss

@@ -24,4 +24,11 @@
     font-size: 1.5rem;
     font-weight: 600;
   }
+  .advantage {
+    color: var(--accept);
+  }
+
+  .disadvantage {
+    color: var(--delete);
+  }
 }

+ 20 - 1
src/app/journal/journal-stats/attribute-skill-container/save-throw-panel/save-throw-field/save-throw-field.component.ts

@@ -13,7 +13,12 @@ import { TranslateService } from '@ngx-translate/core';
 })
 export class SaveThrowFieldComponent {
   @Input() attributeName: string = '';
-  public attribute: Attribute = { name: '', value: 0, proficiency: false };
+  public attribute: Attribute = {
+    name: '',
+    value: 0,
+    proficiency: false,
+    advantage: 'none',
+  };
 
   private proficiencyBonus: number = 0;
   private attributeModifier: number = 0;
@@ -36,6 +41,10 @@ export class SaveThrowFieldComponent {
     );
     observable.subscribe((newValue: Attribute) => {
       this.attribute = newValue;
+      // MIGRATION: Add default value for advantage
+      if (this.attribute.advantage === undefined) {
+        this.attribute.advantage = 'none';
+      }
       this.attributeModifier = this.calculateAttributeModifier();
       this.saveModifier = this.calculateSaveModifier();
     });
@@ -69,7 +78,17 @@ export class SaveThrowFieldComponent {
     this.detailsAccessor.openPanel(SaveThrowDetailsComponent, {
       attributeName: this.attributeName,
       saveModifier: this.saveModifier,
+      advantage: this.attribute.advantage,
     });
+    const resultSubscription = this.detailsAccessor.result$.subscribe(
+      (result) => {
+        if (result.state === 'update') {
+          this.attribute.advantage = result.data.advantage;
+          this.updateAttribute();
+        }
+        resultSubscription.unsubscribe();
+      },
+    );
   }
 
   public updateAttribute(): void {

+ 33 - 0
src/app/journal/journal-stats/attribute-skill-container/skill-panel/skill-details/skill-details.component.html

@@ -1,3 +1,36 @@
 <div class="title">{{ "skills." + skillName | translate }}</div>
 <div class="content">{{ "skillsDescription." + skillName | translate }}</div>
 <value-box [value]="skillModifier" [label]="'general.modifier'"></value-box>
+
+<h4 class="t-2">{{ "skillDetails.title" | translate }}</h4>
+
+<mat-radio-group [(ngModel)]="advantage" (change)="showButtons()">
+  <mat-radio-button class="example-radio-button" [value]="'none'">{{
+    "skillDetails.none" | translate
+  }}</mat-radio-button>
+  <mat-radio-button class="example-radio-button" [value]="'advantage'">{{
+    "skillDetails.advantage" | translate
+  }}</mat-radio-button>
+  <mat-radio-button class="example-radio-button" [value]="'disadvantage'">{{
+    "skillDetails.disadvantage" | translate
+  }}</mat-radio-button>
+</mat-radio-group>
+
+@if (showButtonsContainer) {
+  <div class="vertical-buttons bottom">
+    <ui-button
+      [color]="'green'"
+      [type]="'apply'"
+      [width]="'w20'"
+      (click)="close('update')"
+    >
+    </ui-button>
+    <ui-button
+      [color]="'red'"
+      [type]="'discard'"
+      [width]="'w20'"
+      (click)="close('cancel')"
+    >
+    </ui-button>
+  </div>
+}

+ 6 - 0
src/app/journal/journal-stats/attribute-skill-container/skill-panel/skill-details/skill-details.component.scss

@@ -0,0 +1,6 @@
+mat-radio-group {
+  display: flex;
+  flex-direction: column;
+  margin: 1rem 0;
+  align-items: flex-start;
+}

+ 20 - 0
src/app/journal/journal-stats/attribute-skill-container/skill-panel/skill-details/skill-details.component.ts

@@ -1,4 +1,5 @@
 import { Component, Input } from '@angular/core';
+import { DetailsService } from 'src/services/details/details.service';
 
 @Component({
   selector: 'app-skill-details',
@@ -8,4 +9,23 @@ import { Component, Input } from '@angular/core';
 export class SkillDetailsComponent {
   @Input() skillName: string = '';
   @Input() skillModifier: string = '';
+  @Input() advantage: 'none' | 'advantage' | 'disadvantage' = 'none';
+
+  public showButtonsContainer: boolean = false;
+
+  public constructor(public detailsAccessor: DetailsService) {}
+
+  public showButtons(): void {
+    this.showButtonsContainer = true;
+  }
+
+  public close(result: string): void {
+    if (result === 'update') {
+      this.detailsAccessor.closePanel(result, {
+        advantage: this.advantage,
+      });
+    } else if (result === 'cancel') {
+      this.detailsAccessor.closePanel(result);
+    }
+  }
 }

+ 9 - 1
src/app/journal/journal-stats/attribute-skill-container/skill-panel/skill-field/skill-field.component.html

@@ -11,5 +11,13 @@
       | translate
   }}</label>
   <label class="skill-name">{{ "skills." + skillName | translate }}</label>
-  <label class="skill-modifier">{{ skillModifier }}</label>
+  <label [class]="skill.advantage" class="skill-modifier">{{
+    skillModifier
+  }}</label>
+  <!-- TODO: Potential Advantage style -->
+  <!-- @if (skill.advantage !== "none") {
+    <span>
+      <icon [size]="'xs'" [type]="'UI'" [icon]="skill.advantage!"></icon>
+    </span>
+  } -->
 </div>

+ 8 - 0
src/app/journal/journal-stats/attribute-skill-container/skill-panel/skill-field/skill-field.component.scss

@@ -31,4 +31,12 @@
     font-size: 1.5em;
     font-weight: 600;
   }
+
+  .advantage {
+    color: var(--accept);
+  }
+
+  .disadvantage {
+    color: var(--delete);
+  }
 }

+ 16 - 1
src/app/journal/journal-stats/attribute-skill-container/skill-panel/skill-field/skill-field.component.ts

@@ -14,7 +14,7 @@ import { TranslateService } from '@ngx-translate/core';
 })
 export class SkillFieldComponent {
   @Input() skillName: string = '';
-  public skill: Skill = { name: '', proficiency: false };
+  public skill: Skill = { name: '', proficiency: false, advantage: 'none' };
   private attribute: Attribute = { name: '', value: 0, proficiency: false };
   public skillModifier: string = '0';
   public skillProficiency: boolean = false;
@@ -51,6 +51,10 @@ export class SkillFieldComponent {
     );
     observable.subscribe((newValue: Skill) => {
       this.skill = newValue;
+      // MIGRATION: Add default value for advantage
+      if (this.skill.advantage === undefined) {
+        this.skill.advantage = 'none';
+      }
       this.skillProficiency = this.skill.proficiency;
       this.skillModifier = this.calculateModifier();
     });
@@ -67,6 +71,7 @@ export class SkillFieldComponent {
     this.dataAccessor.updateSkill({
       name: this.skillName,
       proficiency: this.skillProficiency,
+      advantage: this.skill.advantage,
     });
   }
 
@@ -86,6 +91,16 @@ export class SkillFieldComponent {
     this.detailsAccessor.openPanel(SkillDetailsComponent, {
       skillName: this.skillName,
       skillModifier: this.skillModifier,
+      advantage: this.skill.advantage,
     });
+    const resultSubscription = this.detailsAccessor.result$.subscribe(
+      (result) => {
+        if (result.state === 'update') {
+          this.skill.advantage = result.data.advantage;
+          this.updateValue();
+        }
+        resultSubscription.unsubscribe();
+      },
+    );
   }
 }