Prechádzať zdrojové kódy

feat: Implemented combined class and subclass features

Warafear 11 mesiacov pred
rodič
commit
f30c212ff1

+ 4 - 4
src/app/journal/journal-character/class/class.component.scss

@@ -36,11 +36,11 @@
 .feature-level {
   position: absolute;
   left: -1.5rem;
-  top: 1rem;
-  font-size: 1.5rem;
-  font-weight: 600;
+  top: 1.25rem;
+  font-size: 1.25rem;
+  font-weight: bold;
+  color: rgb(78, 78, 78);
 }
-
 .feature-button {
   position: absolute;
   right: 0;

+ 18 - 0
src/app/journal/journal-character/combined/combined.component.html

@@ -0,0 +1,18 @@
+<div class="combined-container">
+  <div class="content">{{ "character.complete.description" | translate }}</div>
+  <div class="features">
+    @for (feature of combined; track feature) {
+      <div class="feature">
+        <div class="feature-name">{{ feature.name }}</div>
+        <div class="feature-level">{{ feature.level }}</div>
+        <icon-button
+          [icon]="'add'"
+          class="feature-button"
+          (click)="addFeature(feature)"
+        ></icon-button>
+        <div [innerHTML]="feature.description"></div>
+        <hr />
+      </div>
+    }
+  </div>
+</div>

+ 47 - 0
src/app/journal/journal-character/combined/combined.component.scss

@@ -0,0 +1,47 @@
+.combined-container {
+  width: 800px;
+  height: calc(100vh - 10.5rem);
+  overflow: auto;
+  margin: auto;
+  border: 1px solid black;
+  padding: 2rem;
+  border-radius: 10px;
+  background-color: var(--items-hover);
+  box-shadow: var(--shadow-large);
+  position: absolute;
+  top: 8.5rem;
+  left: 50%;
+  transform: translateX(-50%);
+}
+
+.content {
+  font-size: 1.25rem;
+  font-weight: 600;
+}
+
+.feature {
+  margin-top: 1.5rem;
+  position: relative;
+}
+
+.feature-name {
+  font-size: 1.5rem;
+  font-weight: 600;
+  margin-bottom: 1rem;
+  margin-left: 1rem;
+}
+
+.feature-level {
+  position: absolute;
+  left: -1.5rem;
+  top: 0.25rem;
+  font-size: 1.25rem;
+  font-weight: bold;
+  color: rgb(78, 78, 78);
+}
+
+.feature-button {
+  position: absolute;
+  right: 0;
+  top: 0rem;
+}

+ 23 - 0
src/app/journal/journal-character/combined/combined.component.spec.ts

@@ -0,0 +1,23 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { CombinedComponent } from './combined.component';
+
+describe('CombinedComponent', () => {
+  let component: CombinedComponent;
+  let fixture: ComponentFixture<CombinedComponent>;
+
+  beforeEach(async () => {
+    await TestBed.configureTestingModule({
+      declarations: [CombinedComponent]
+    })
+    .compileComponents();
+    
+    fixture = TestBed.createComponent(CombinedComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});

+ 123 - 0
src/app/journal/journal-character/combined/combined.component.ts

@@ -0,0 +1,123 @@
+import { Component } from '@angular/core';
+import { Ability } from 'src/interfaces/ability';
+import { DataService } from 'src/services/data/data.service';
+import { ModalService } from 'src/services/modal/modal.service';
+import { Trait } from 'src/interfaces/traits';
+import { AbilityModalComponent } from '../../journal-stats/ability-panel/ability-table/ability-modal/ability-modal.component';
+import { TraitModalComponent } from '../../journal-stats/ability-panel/trait-table/trait-modal/trait-modal.component';
+import { ClassService } from 'src/services/class/class.service';
+import { SubclassService } from 'src/services/subclass/subclass.service';
+
+@Component({
+  selector: 'combined',
+  templateUrl: './combined.component.html',
+  styleUrl: './combined.component.scss',
+})
+export class CombinedComponent {
+  public combined: any[] = [];
+
+  public constructor(
+    private dataAccessor: DataService,
+    private modalAccessor: ModalService,
+    private classAccessor: ClassService,
+    private subclassAccessor: SubclassService,
+  ) {
+    this.getCombinedData();
+  }
+
+  /**
+   * Retrieves the class and subclass features and combines them into a single array
+   */
+  private getCombinedData() {
+    let className = this.dataAccessor.characterData.class;
+    let subclassName = this.dataAccessor.characterData.subclass;
+    let classFeatures = JSON.parse(
+      JSON.stringify(this.classAccessor.getClassDetails(className).features),
+    );
+    let subclassFeatures = JSON.parse(
+      JSON.stringify(
+        this.subclassAccessor.getSubclassDetails(subclassName).features,
+      ),
+    );
+
+    // Builds the array from deep copies of the class and subclass features.
+    while (classFeatures.length > 0 && subclassFeatures.length > 0) {
+      if (classFeatures[0].level < subclassFeatures[0].level) {
+        this.combined.push(classFeatures.shift());
+      } else {
+        this.combined.push(subclassFeatures.shift());
+      }
+    }
+    if (classFeatures.length > 0) {
+      this.combined.push(...classFeatures);
+    } else {
+      this.combined.push(...subclassFeatures);
+    }
+  }
+
+  public addFeature(feature: any) {
+    if ('ability' in feature) {
+      this.addAbility(feature);
+    } else {
+      this.addTrait(feature);
+    }
+  }
+
+  private addAbility(feature: any) {
+    let index = feature.name.indexOf('Optional');
+    if (index > -1) {
+      feature.name = feature.name.slice(index, 8);
+    }
+    let ability: Ability = {
+      name: feature.name,
+      shortDescription: '',
+      longDescription: feature.description,
+      cost: '',
+      charges: 0,
+      currentlyUsedCharges: 0,
+    };
+    this.modalAccessor.openModal(AbilityModalComponent, {
+      ability: ability,
+      isUpdate: true,
+      isAddedFromCharacter: true,
+    });
+    const resultSubscription = this.modalAccessor.result$.subscribe(
+      (result) => {
+        if (result.state === 'update' || result.state === 'add') {
+          let ability = this.dataAccessor.abilities;
+          ability.push(result.data);
+          this.dataAccessor.abilities = ability;
+        }
+        resultSubscription.unsubscribe();
+      },
+    );
+  }
+
+  private addTrait(feature: any) {
+    let index = feature.name.indexOf('Optional');
+    if (index > -1) {
+      feature.name = feature.name.slice(index, 8);
+    }
+    let trait: Trait = {
+      name: feature.name,
+      shortDescription: '',
+      longDescription: feature.description,
+      origin: 'Class',
+    };
+    this.modalAccessor.openModal(TraitModalComponent, {
+      trait: trait,
+      isUpdate: true,
+      isAddedFromCharacter: true,
+    });
+    const resultSubscription = this.modalAccessor.result$.subscribe(
+      (result) => {
+        if (result.state === 'update' || result.state === 'add') {
+          let traits = this.dataAccessor.traits;
+          traits.push(result.data);
+          this.dataAccessor.traits = traits;
+        }
+        resultSubscription.unsubscribe();
+      },
+    );
+  }
+}

+ 1 - 2
src/app/journal/journal-character/journal-character.component.html

@@ -65,8 +65,7 @@
       <ng-container ngbNavItem="combined">
         <button ngbNavLink>{{ "character.complete.label" | translate }}</button>
         <ng-template ngbNavContent>
-          <!-- <class></class> -->
-          Coming soon!
+          <combined></combined>
         </ng-template>
       </ng-container>
       <ng-container ngbNavItem="background">

+ 4 - 3
src/app/journal/journal-character/subclass/subclass.component.scss

@@ -35,9 +35,10 @@
 .feature-level {
   position: absolute;
   left: -1.5rem;
-  top: 1rem;
-  font-size: 1.5rem;
-  font-weight: 600;
+  top: 1.25rem;
+  font-size: 1.25rem;
+  font-weight: bold;
+  color: rgb(78, 78, 78);
 }
 
 .feature-button {

+ 2 - 0
src/app/journal/journal.module.ts

@@ -98,6 +98,7 @@ import { FavoriteSpellsModalComponent } from './journal-stats/weapons-container/
 import { MatRippleModule } from '@angular/material/core';
 import { CustomSpellsModalComponent } from './journal-spellcards/custom-spells-modal/custom-spells-modal.component';
 import { DurationPipe } from '../../pipes/duration/duration.pipe';
+import { CombinedComponent } from './journal-character/combined/combined.component';
 
 @NgModule({
   declarations: [
@@ -175,6 +176,7 @@ import { DurationPipe } from '../../pipes/duration/duration.pipe';
     StoryComponent,
     FavoriteSpellsModalComponent,
     CustomSpellsModalComponent,
+    CombinedComponent,
   ],
   providers: [TranslatePipe, DurationPipe],
   imports: [

+ 5 - 3
src/assets/i18n/de.json

@@ -399,6 +399,7 @@
     "petrified": "Versteinert",
     "poisoned": "Vergiftet",
     "prone": "Liegend",
+    "restrained": "Festgesetzt",
     "stunned": "Betäubt",
     "unconscious": "Bewusstlos",
     "conditionDescriptions": {
@@ -422,7 +423,7 @@
         "Ein blinder Charakter kann nicht sehen. Er scheitert automatisch bei allen Attributwürfen, die auf Sicht basieren.",
         "Angriffe gegen ihn haben Vorteil, seine Angriffe wiederum haben Nachteil."
       ],
-      "Festgesetzt": [
+      "restrained": [
         "Die Bewegungsrate eines festgesetzten Charakters wird auf 0 gesetzt.",
         "Angriffe gegen ihn haben Vorteil, seine Angriffe wiederum haben Nachteil.",
         "Er scheitert automatisch bei allen Geschicklichkeitsrettungswürfen."
@@ -669,7 +670,8 @@
       "sorcerer": "Herkunft"
     },
     "complete": {
-      "label": "Vollständige Übersicht"
+      "label": "Kombinierte Übersicht",
+      "description": "Hier werden die kombinierten Eigeschaften und Fähigkeiten deiner Klasse und Unterklasse angezeigt."
     },
     "background": {
       "label": "Hintergrund"
@@ -752,7 +754,7 @@
     "delete": "Charakter löschen",
     "confirm": "Möchtest du <b>{{name}}</b> unwiederruflich löschen?",
     "hint": "Die App befindet sich immer noch in einem Entwicklungsstadium und es können Fehler auftreten",
-    "issues": "Fehler bitte auf LINK_MISSING melden",
+    "issues": "Fehler und Anmerkungen bitte auf dem Git-Server in Issues vermerken.",
     "okay": "Verstanden"
   }
 }

+ 106 - 1
src/services/class/class.service.ts

@@ -227,6 +227,13 @@ export class ClassService {
         `,
         ability: '',
       },
+      {
+        name: 'Ability Score Improvement',
+        level: 8,
+        description: `
+        <p>When you reach 8th level, and again at 12th, 16th, and 19th level, you can increase one ability score of your choice by 2, or you can increase two ability scores of your choice by 1. As normal, you can't increase an ability score above 20 using this feature.</p>
+        `,
+      },
       {
         name: 'Purity of Blood',
         level: 10,
@@ -234,6 +241,13 @@ export class ClassService {
         <p>At 10th level, your mastery of the ki flowing through you makes you immune to disease and poison.</p>
         `,
       },
+      {
+        name: 'Ability Score Improvement',
+        level: 12,
+        description: `
+        <p>When you reach 12th level, and again at 16th, and 19th level, you can increase one ability score of your choice by 2, or you can increase two ability scores of your choice by 1. As normal, you can't increase an ability score above 20 using this feature.</p>
+        `,
+      },
       {
         name: 'Tongue of the Sun and Moon',
         level: 13,
@@ -255,6 +269,13 @@ export class ClassService {
         <p>At 15th level, your ki sustains you so that you suffer none of the frailty of old age, and you can't be aged magically. You can still die of old age, however. In addition, you no longer need food or water.</p>
         `,
       },
+      {
+        name: 'Ability Score Improvement',
+        level: 16,
+        description: `
+        <p>When you reach 16th level, and again at 19th level, you can increase one ability score of your choice by 2, or you can increase two ability scores of your choice by 1. As normal, you can't increase an ability score above 20 using this feature.</p>
+        `,
+      },
       {
         name: 'Empty Body',
         level: 18,
@@ -264,6 +285,13 @@ export class ClassService {
         `,
         ability: '',
       },
+      {
+        name: 'Ability Score Improvement',
+        level: 19,
+        description: `
+        <p>When you reach 19th level, you can increase one ability score of your choice by 2, or you can increase two ability scores of your choice by 1. As normal, you can't increase an ability score above 20 using this feature.</p>
+        `,
+      },
       {
         name: 'Perfect Self',
         level: 20,
@@ -558,6 +586,13 @@ export class ClassService {
          <p> Additionally, if you are surprised at the beginning of combat and aren't incapacitated, you can act normally on your first turn, but only if you enter your rage before doing anything else on that turn. </p>
         `,
       },
+      {
+        name: 'Ability Score Improvement',
+        level: 8,
+        description: `
+        <p>When you reach 8th level, and again at 12th, 16th, and 19th level, you can increase one ability score of your choice by 2, or you can increase two ability scores of your choice by 1. As normal, you can't increase an ability score above 20 using this feature.</p>
+        `,
+      },
       {
         name: 'Brutal Critical',
         level: 9,
@@ -588,6 +623,13 @@ export class ClassService {
           <p>Beginning at 15th level, your rage is so fierce that it ends early only if you fall unconscious or if you choose to end it. <p>
         `,
       },
+      {
+        name: 'Ability Score Improvement',
+        level: 16,
+        description: `
+        <p>When you reach 16th level, and again at 19th level, you can increase one ability score of your choice by 2, or you can increase two ability scores of your choice by 1. As normal, you can't increase an ability score above 20 using this feature.</p>
+        `,
+      },
       {
         name: 'Indomitable Might',
         level: 18,
@@ -595,6 +637,13 @@ export class ClassService {
           <p>Beginning at 18th level, if your total for a Strength check is less than your Strength score, you can use that score in place of the total.</p>
         `,
       },
+      {
+        name: 'Ability Score Improvement',
+        level: 19,
+        description: `
+        <p>When you reach 19th level, you can increase one ability score of your choice by 2, or you can increase two ability scores of your choice by 1. As normal, you can't increase an ability score above 20 using this feature.</p>
+        `,
+      },
       {
         name: 'Primal Champion',
         level: 20,
@@ -800,6 +849,13 @@ export class ClassService {
         <p>In addition, you have advantage on saving throws against plants that are magically created or manipulated to impede movement, such as those created by the Entangle spell.</p>
         `,
       },
+      {
+        name: 'Ability Score Improvement',
+        level: 8,
+        description: `
+        <p>When you reach 8th level, and again at 12th, 16th, and 19th level, you can increase one ability score of your choice by 2, or you can increase two ability scores of your choice by 1. As normal, you can't increase an ability score above 20 using this feature.</p>
+        `,
+      },
       {
         name: 'Hide in Plain Sight',
         level: 10,
@@ -819,6 +875,13 @@ export class ClassService {
         `,
         ability: '',
       },
+      {
+        name: 'Ability Score Improvement',
+        level: 12,
+        description: `
+        <p>When you reach 12th level, and again at 16th, and 19th level, you can increase one ability score of your choice by 2, or you can increase two ability scores of your choice by 1. As normal, you can't increase an ability score above 20 using this feature.</p>
+        `,
+      },
       {
         name: 'Vanish',
         level: 14,
@@ -827,6 +890,13 @@ export class ClassService {
         `,
         ability: '',
       },
+      {
+        name: 'Ability Score Improvement',
+        level: 16,
+        description: `
+        <p>When you reach 16th level, and again at 19th level, you can increase one ability score of your choice by 2, or you can increase two ability scores of your choice by 1. As normal, you can't increase an ability score above 20 using this feature.</p>
+        `,
+      },
       {
         name: 'Feral Senses',
         level: 18,
@@ -835,6 +905,13 @@ export class ClassService {
         <p>You are also aware of the location of any invisible creature within 30 feet of you, provided that the creature isn't hidden from you and you aren't blinded or deafened.</p>
         `,
       },
+      {
+        name: 'Ability Score Improvement',
+        level: 19,
+        description: `
+        <p>When you reach 19th level, you can increase one ability score of your choice by 2, or you can increase two ability scores of your choice by 1. As normal, you can't increase an ability score above 20 using this feature.</p>
+        `,
+      },
       {
         name: 'Foe Slayer',
         level: 20,
@@ -1205,7 +1282,14 @@ export class ClassService {
       },
       {
         name: 'Ability Score Improvement',
-        level: 16,
+        level: 4,
+        description: `
+        <p>When you reach 16th level, and again at 19th level, you can increase one ability score of your choice by 2, or you can increase two ability scores of your choice by 1. As normal, you can't increase an ability score above 20 using this feature.</p>
+        `,
+      },
+      {
+        name: 'Ability Score Improvement',
+        level: 19,
         description: `
         <p>When you reach 16th level, you can increase one ability score of your choice by 2, or you can increase two ability scores of your choice by 1. As normal, you can't increase an ability score above 20 using this feature.</p>
         `,
@@ -1684,6 +1768,27 @@ export class ClassService {
         <p>You learn two additional spells from any classes at 14th level and again at 18th level.</p>
         `,
       },
+      {
+        name: 'Ability Score Improvement',
+        level: 12,
+        description: `
+        <p>When you reach 12th level, and again at 16th, and 19th level, you can increase one ability score of your choice by 2, or you can increase two ability scores of your choice by 1. As normal, you can't increase an ability score above 20 using this feature.</p>
+        `,
+      },
+      {
+        name: 'Ability Score Improvement',
+        level: 16,
+        description: `
+        <p>When you reach 16th level, and again at 19th level, you can increase one ability score of your choice by 2, or you can increase two ability scores of your choice by 1. As normal, you can't increase an ability score above 20 using this feature.</p>
+        `,
+      },
+      {
+        name: 'Ability Score Improvement',
+        level: 19,
+        description: `
+        <p>When you reach 19th level, you can increase one ability score of your choice by 2, or you can increase two ability scores of your choice by 1. As normal, you can't increase an ability score above 20 using this feature.</p>
+        `,
+      },
       {
         name: 'Superior Inspiration',
         level: 20,