Răsfoiți Sursa

finished rudimentary full-spellcards

Warafear 10 luni în urmă
părinte
comite
39a4b455bc

+ 0 - 3
src/app/journal/journal-stats/ability-panel/spellslots/spellslots.component.ts

@@ -36,7 +36,6 @@ export class SpellslotsComponent {
     this.showSpellslots = spells.showSpellslots;
     this.spellcastingAttribute = spells.spellcastingAttribute;
     this.kiPoints = kiPoints;
-    // this.calculateModifiers();
     this.subscribeToProficiency();
     this.subscribeToAttribute();
   }
@@ -84,8 +83,6 @@ export class SpellslotsComponent {
       this.spellcastingAttribute !== undefined &&
       this.spellcastingAttribute !== null
     ) {
-      console.log(this.spellcastingAttribute);
-
       const command =
         'this.dataAccessor.' +
         this.spellcastingAttribute.toLowerCase() +

+ 7 - 8
src/app/journal/journal-stats/weapons-container/spell-table/favorite-spells-modal/favorite-spells-modal.component.html

@@ -157,15 +157,13 @@
             "attributesAbbreviations." + spell.savingThrowAttribute | translate
           }}
         </div>
-        <div>{{ spellSaveDC }}</div>
+        <div>{{ utils.spellSaveDC }}</div>
       </div>
-    }
-    @if (spell.needsAttackRoll) {
+    } @else if (spell.needsAttackRoll) {
       <div>
-        <div>{{ spellAttackBonus }}</div>
+        <div>{{ utils.spellAttackModifier }}</div>
       </div>
-    }
-    @if (!spell.needsSavingThrow && !spell.needsAttackRoll) {
+    } @else {
       <div>-</div>
     }
   </div>
@@ -190,8 +188,7 @@
           </span>
         </div>
       }
-    }
-    @if (spell.doesHeal) {
+    } @else if (spell.doesHeal) {
       <div class="heal">
         <span
           >{{ spell.heal.diceNumber }} {{ "general.dice" | translate
@@ -204,6 +201,8 @@
           <icon [size]="'xs'" [type]="'damage'" [icon]="'heal'"></icon>
         </span>
       </div>
+    } @else {
+      <div>-</div>
     }
   </div>
 </ng-template>

+ 2 - 2
src/app/journal/journal-stats/weapons-container/spell-table/favorite-spells-modal/favorite-spells-modal.component.ts

@@ -2,6 +2,7 @@ import { Component, Input } from '@angular/core';
 import { Spell } from 'src/interfaces/spell';
 import { ModalService } from 'src/services/modal/modal.service';
 import { TranslateService } from '@ngx-translate/core';
+import { UtilsService } from 'src/services/utils/utils.service';
 
 @Component({
   selector: 'app-favorite-spells-modal',
@@ -11,14 +12,13 @@ import { TranslateService } from '@ngx-translate/core';
 export class FavoriteSpellsModalComponent {
   @Input() public preparedSpells: Spell[] = [];
   @Input() public selectedSpells: Spell[] = [];
-  @Input() public spellAttackBonus: string = '0';
-  @Input() public spellSaveDC: number = 0;
 
   checkedSpells: boolean[] = [];
 
   public constructor(
     private modalAccessor: ModalService,
     public translate: TranslateService,
+    public utils: UtilsService,
   ) {}
 
   public ngOnInit(): void {

+ 7 - 8
src/app/journal/journal-stats/weapons-container/spell-table/spell-table.component.html

@@ -147,15 +147,13 @@
                 | translate
             }}
           </div>
-          <div>{{ spellSaveDC }}</div>
+          <div>{{ utils.spellSaveDC }}</div>
         </div>
-      }
-      @if (spell.needsAttackRoll) {
+      } @else if (spell.needsAttackRoll) {
         <div>
-          <div>{{ spellAttackBonus }}</div>
+          <div>{{ utils.spellAttackModifier }}</div>
         </div>
-      }
-      @if (!spell.needsSavingThrow && !spell.needsAttackRoll) {
+      } @else {
         <div>-</div>
       }
     </div>
@@ -180,8 +178,7 @@
             </span>
           </div>
         }
-      }
-      @if (spell.doesHeal) {
+      } @else if (spell.doesHeal) {
         <div class="heal">
           <span
             >{{ spell.heal.diceNumber }} {{ "general.dice" | translate
@@ -194,6 +191,8 @@
             <icon [size]="'xs'" [type]="'damage'" [icon]="'heal'"></icon>
           </span>
         </div>
+      } @else {
+        <div>-</div>
       }
     </div>
   </ng-template>

+ 2 - 79
src/app/journal/journal-stats/weapons-container/spell-table/spell-table.component.ts

@@ -7,6 +7,7 @@ import { Spell } from 'src/interfaces/spell';
 import { FullSpellcardComponent } from 'src/app/shared-components/full-spellcard/full-spellcard.component';
 import { FavoriteSpellsModalComponent } from './favorite-spells-modal/favorite-spells-modal.component';
 import { TranslateService } from '@ngx-translate/core';
+import { UtilsService } from 'src/services/utils/utils.service';
 
 @Component({
   selector: 'spell-table',
@@ -14,46 +15,21 @@ import { TranslateService } from '@ngx-translate/core';
   styleUrls: ['./spell-table.component.scss'],
 })
 export class SpellTableComponent {
-  public spellAttackBonus: string = '0';
-  public spellSaveDC: number = 0;
-  private spellcastingAttribute: string | undefined;
-  private spellcastingAttributeModifier: number = 0;
-  private proficiencyBonus: number = 2;
-
   public spells!: Spell[];
   private preparedSpells!: Spell[];
-  // private preparedSpellsNames: string[] = [];
   public newSpellName: string = '';
 
-  public attributes: any = {
-    strength: 'STR',
-    dexterity: 'DEX',
-    constitution: 'CON',
-    intelligence: 'INT',
-    wisdom: 'WIS',
-    charisma: 'CHA',
-  };
-
-  // public areas: any = {
-  //   cone: 'Kegel',
-  //   sphere: 'Kugel',
-  //   circle: 'Kreis',
-  //   line: 'Linie',
-  //   square: 'Quadrat',
-  //   cube: 'Würfel',
-  // };
-
   public constructor(
     public dataAccessor: DataService,
     private modalAccessor: ModalService,
     public detailsAccessor: DetailsService,
     public translate: TranslateService,
+    public utils: UtilsService,
   ) {}
 
   public ngOnInit(): void {
     this.spells = this.dataAccessor.favoriteSpells;
     this.preparedSpells = this.dataAccessor.getAllPreparedSpells();
-    this.subscribeToData();
   }
 
   public showFullSpellcard(spellIndex: number): void {
@@ -76,8 +52,6 @@ export class SpellTableComponent {
     this.modalAccessor.openModal(FavoriteSpellsModalComponent, {
       preparedSpells: this.preparedSpells,
       selectedSpells: this.spells,
-      spellAttackBonus: this.spellAttackBonus,
-      spellSaveDC: this.spellSaveDC,
     });
     const resultSubscription = this.modalAccessor.result$.subscribe(
       (result) => {
@@ -95,8 +69,6 @@ export class SpellTableComponent {
     this.updateSpellsInDatabase();
   }
 
-  // utils
-
   public dropSpells(event: CdkDragDrop<string[]>): void {
     moveItemInArray(this.spells, event.previousIndex, event.currentIndex);
     this.updateSpellsInDatabase();
@@ -105,53 +77,4 @@ export class SpellTableComponent {
   public updateSpellsInDatabase(): void {
     this.dataAccessor.favoriteSpells = this.spells;
   }
-
-  private computeSpellAttackBonusAndSaveDC(): void {
-    let attackBonus =
-      this.spellcastingAttributeModifier + this.proficiencyBonus;
-    this.spellSaveDC = 8 + attackBonus;
-    if (attackBonus >= 0) {
-      this.spellAttackBonus = '+' + attackBonus;
-    } else {
-      this.spellAttackBonus = attackBonus.toString();
-    }
-  }
-
-  private subscribeToData(): void {
-    // TODO: this.dataAccessor.getSpellcastingAttribute() oder so
-    this.spellcastingAttribute = 'wisdom';
-
-    this.dataAccessor.proficiency$.subscribe((value) => {
-      this.proficiencyBonus = value;
-      if (this.spellcastingAttribute) {
-        this.computeSpellAttackBonusAndSaveDC();
-      }
-    });
-    // TODO: Modify depending on the actual spellcasting attribute
-    this.dataAccessor.wisdom$.subscribe((value) => {
-      this.spellcastingAttributeModifier = Math.floor((value.value - 10) / 2);
-      this.computeSpellAttackBonusAndSaveDC();
-    });
-  }
-
-  // public search: OperatorFunction<string, readonly string[]> = (
-  //   text$: Observable<string>
-  // ) =>
-  //   text$.pipe(
-  //     debounceTime(200),
-  //     distinctUntilChanged(),
-  //     map((term) =>
-  //       term.length < 2
-  //         ? []
-  //         : this.preparedSpellsNames
-  //             .filter((v) => v.toLowerCase().indexOf(term.toLowerCase()) > -1)
-  //             .filter(
-  //               (v) =>
-  //                 !this.spells.some(
-  //                   (spell) => spell.german.toLowerCase() === v.toLowerCase()
-  //                 )
-  //             )
-  //             .slice(0, 5)
-  //     )
-  //   );
 }

+ 30 - 161
src/app/shared-components/full-spellcard/full-spellcard.component.html

@@ -11,19 +11,23 @@
           <div class="value">{{ spell.level }}</div>
         </div>
         <div class="entry">
-          <div class="name">{{ "spellmodal.cost" | translate }}</div>
+          <div class="name">{{ "fullSpellcards.castingTime" | translate }}</div>
           <div class="value">
-            {{ spell.timeToCast }} {{ "time." + spell.cost | translate }}
+            {{ spell.timeToCast }}
+            {{ "time." + spell.cost | translate }}
           </div>
         </div>
         <div class="entry">
-          <div class="name">{{ "spellmodal.duration" | translate }}</div>
+          <div class="name">{{ "fullSpellcards.duration" | translate }}</div>
           <div class="value">
-            {{ spell.duration }} {{ "time." + spell.durationType | translate }}
+            @if (spell.duration != 0) {
+              {{ spell.duration }}
+            }
+            {{ "time." + spell.durationType | translate }}
           </div>
         </div>
         <div class="entry">
-          <div class="name">{{ "spellmodal.components" | translate }}</div>
+          <div class="name">{{ "fullSpellcards.components" | translate }}</div>
           <div class="value">
             @if (spell.needsVerbal) {
               {{ "spells.components.verbal" | translate }},
@@ -43,23 +47,35 @@
           <div class="value">{{ "schools." + spell.school | translate }}</div>
         </div>
         <div class="entry">
-          <div class="name">{{ "spellmodal.mod-save" | translate }}</div>
+          @if (spell.needsSavingThrow) {
+            <div class="name">{{ "fullSpellcards.saveDC" | translate }}</div>
+          } @else if (spell.needsAttackRoll) {
+            <div class="name">{{ "fullSpellcards.attack" | translate }}</div>
+          } @else {
+            <div class="name">{{ "fullSpellcards.modifier" | translate }}</div>
+          }
           <div class="value">
             @if (spell.needsSavingThrow) {
               {{
                 "attributesAbbreviations." + spell.savingThrowAttribute
                   | translate
               }}
-              {{ saveDC }}
+              {{ utils.spellSaveDC }}
             } @else if (spell.needsAttackRoll) {
-              {{ attackBonus }}
+              {{ utils.spellAttackModifier }}
             } @else {
               -
             }
           </div>
         </div>
         <div class="entry">
-          <div class="name">{{ "spellmodal.effect" | translate }}</div>
+          @if (spell.doesDamage) {
+            <div class="name">{{ "fullSpellcards.damage" | translate }}</div>
+          } @else if (spell.doesHeal) {
+            <div class="name">{{ "fullSpellcards.heal" | translate }}</div>
+          } @else {
+            <div class="name">{{ "fullSpellcards.effect" | translate }}</div>
+          }
           <div class="value">
             <div>
               @if (spell.doesDamage) {
@@ -82,8 +98,7 @@
                     </span>
                   </div>
                 }
-              }
-              @if (spell.doesHeal) {
+              } @else if (spell.doesHeal) {
                 <div class="heal">
                   <span
                     >{{ spell.heal?.diceNumber }} {{ "general.dice" | translate
@@ -100,6 +115,8 @@
                     ></icon>
                   </span>
                 </div>
+              } @else {
+                -
               }
             </div>
           </div>
@@ -109,9 +126,9 @@
           @if (spell.isRanged) {
             <div class="value">{{ spell.range }} ft.</div>
           } @else if (spell.range === 0) {
-            <div class="value">{{ "spellmodal.self" | translate }}</div>
+            <div class="value">{{ "fullSpellcards.self" | translate }}</div>
           } @else if (spell.range === 5) {
-            <div class="value">{{ "spellmodal.touch" | translate }}</div>
+            <div class="value">{{ "fullSpellcards.touch" | translate }}</div>
           }
           @if (spell.hasAreaOfEffect) {
             <div>
@@ -134,151 +151,3 @@
   <hr />
   <div class="description" [innerHTML]="spell.description_de"></div>
 </div>
-
-<!-- <div class="full-spellcard-container">
-  <div class="full-spellcard">
-    <h2 style="text-align: center; margin-top: 1rem">{{ spell.german }}</h2>
-
-    <table class="table table-striped" style="height: 20rem; overflow: auto">
-      <thead>
-        <tr>
-          <th scope="col">Property</th>
-          <th scope="col">Value</th>
-        </tr>
-      </thead>
-      <tbody>
-        <tr>
-          <td>Komponenten:</td>
-          <td>
-            @if (spell.needsVerbal) {
-              Verbal
-            }
-            @if (spell.needsSomatic) {
-              , Somatic
-            }
-            @if (spell.needsMaterial) {
-              , Material
-            }
-          </td>
-        </tr>
-        <tr>
-          <td>Stufe</td>
-          <td>{{ spell.level }}</td>
-        </tr>
-        <tr>
-          <td>Kosten</td>
-          <td>{{ spell.cost }}</td>
-        </tr>
-        <tr>
-          <td>Ist ein Ritual</td>
-          <td>{{ spell.isRitual }}</td>
-        </tr>
-        <tr>
-          <td>Wirkungsdauer</td>
-          <td>
-            {{ spell.duration }}
-            {{ "time." + spell.durationType | translate }}
-          </td>
-        </tr>
-
-        <tr></tr>
-        <tr>
-          <td>Benötigt Konzentration</td>
-          <td>{{ spell.needsConcentration }}</td>
-        </tr>
-        <tr>
-          <td>Schule</td>
-          <td>{{ spell.school }}</td>
-        </tr>
-        <tr>
-          <td>Reichweite</td>
-          @if (spell.isRanged) {
-            <td>{{ spell.range }}</td>
-          } @else {
-            <td>Berührung</td>
-          }
-        </tr>
-        @if (spell.hasAreaOfEffect) {
-          <tr>
-            <td>Flächeneffekt</td>
-            <td>{{ spell.areaOfEffectType }}</td>
-          </tr>
-          <tr>
-            <td>Durchmesser</td>
-            <td>{{ spell.length }}</td>
-          </tr>
-        }
-        @if (spell.needsAttackRoll) {
-          <tr>
-            <td>Benötigt Angriffswurf</td>
-            <td>{{ spell.needsAttackRoll }}</td>
-          </tr>
-        }
-        @if (spell.needsSavingThrow) {
-          <tr>
-            <td>Benötigt Rettungswurf</td>
-            <td>{{ spell.needsSavingThrow }}</td>
-          </tr>
-          <tr>
-            <td>Rettungswurfattribut</td>
-            <td>{{ spell.savingThrowAttribute }}</td>
-          </tr>
-        }
-        @if (spell.doesDamage) {
-          <tr>
-            <td>Schaden</td>
-            <td>
-              @for (damage of spell.damage; track damage) {
-                {{ damage.diceNumber }} {{ "general.dice" | translate
-                }}{{ damage.diceType }}
-                {{ damage.damageType }}
-                @if (damage.additionalDamage) {
-                  + {{ damage.additionalDamage }}
-                }
-
-                <br />
-              }
-            </td>
-          </tr>
-        }
-        @if (spell.doesHeal) {
-          <tr>
-            <td>Heilung</td>
-            <td>
-              {{ spell.heal!.diceNumber }} {{ spell.heal!.diceType }}
-              @if (spell.heal!.additionalHeal) {
-                + {{ spell.heal!.additionalHeal }}
-              }
-            </td>
-          </tr>
-        }
-        <h3>Beschreibung</h3>
-        <div [innerHTML]="spell.description_de"></div>
-      </tbody>
-    </table>
-  </div>
-
-  <div class="delete-row">
-    @if (isFromDashboard) {
-      <button class="delete-button" (click)="remove()">Entfernen</button>
-      <button
-        [class]="alreadyInFavorites ? 'disabled add-button' : 'add-button'"
-        (click)="alreadyInFavorites ? '' : addToFavorites()"
-      >
-        @if (alreadyInFavorites) {
-          Bereits in Favoriten
-        } @else {
-          Zu Favoriten hinzufügen
-        }
-      </button>
-      @if (spell.isCustom) {
-        <button class="edit-button" (click)="update()">Anpassen</button>
-      }
-
-      <button class="delete-button" (click)="remove()">Entfernen</button>
-      @if (spell.isCustom) {
-        <button class="delete-button" (click)="delete()">Löschen</button>
-      }
-    }
-  </div>
-</div> -->

+ 6 - 2
src/app/shared-components/full-spellcard/full-spellcard.component.scss

@@ -33,10 +33,8 @@ img {
 .entry {
   width: 9rem;
   height: 6rem;
-  // border: 1px solid rgba(0, 0, 0, 0.2);
 
   .name {
-    // font-size: 1.125rem;
     font-weight: 500;
   }
 
@@ -45,6 +43,12 @@ img {
   }
 }
 
+.description {
+  overflow: auto;
+  height: 15rem;
+  border-bottom: 1px solid red;
+}
+
 @mixin button {
   color: black;
   border: none;

+ 5 - 1
src/app/shared-components/full-spellcard/full-spellcard.component.ts

@@ -1,6 +1,7 @@
 import { Component, Input } from '@angular/core';
 import { Spell } from 'src/interfaces/spell';
 import { ModalService } from 'src/services/modal/modal.service';
+import { UtilsService } from 'src/services/utils/utils.service';
 
 @Component({
   selector: 'app-full-spellcard',
@@ -15,7 +16,10 @@ export class FullSpellcardComponent {
   public saveDC: number = 0;
   public attackBonus: string = '+3';
 
-  public constructor(private modalAccessor: ModalService) {}
+  public constructor(
+    private modalAccessor: ModalService,
+    public utils: UtilsService,
+  ) {}
 
   ngOnInit(): void {
     console.log('Der zauber: ', this.spell);

+ 2 - 1
src/app/shared-components/shared-components.module.ts

@@ -10,6 +10,7 @@ import { MatRippleModule } from '@angular/material/core';
 import { TranslateModule } from '@ngx-translate/core';
 import { DurationPipe } from '../../pipes/duration/duration.pipe';
 import { IconComponent } from './icon/icon.component';
+import { UtilsService } from 'src/services/utils/utils.service';
 
 @NgModule({
   declarations: [
@@ -38,6 +39,6 @@ import { IconComponent } from './icon/icon.component';
     TranslateModule,
     DurationPipe,
   ],
-  providers: [DurationPipe],
+  providers: [DurationPipe, UtilsService],
 })
 export class SharedComponentsModule {}

+ 14 - 4
src/assets/i18n/de.json

@@ -753,12 +753,22 @@
     "additionalDamage": "Weiterer Schaden",
     "description": "Beschreibung",
     "placeholder": "Beschreibung des Zaubers",
-    "length": "Länge",
+    "length": "Länge"
+  },
+  "fullSpellcards": {
+    "duration": "Wirkungsdauer",
+    "castingTime": "Zeitaufwand",
+    "attack": "Angriffsmodifikator",
+    "saveDC": "Rettungswurf-SG",
+    "modifier": "Modifikator",
+    "damage": "Schaden",
+    "heal": "Heilung",
+    "effekt": "Effekt",
+    "description": "Beschreibung",
     "components": "Komponenten",
-    "mod-save": "Modifikator/Save",
-    "effect": "Schaden/Heilung",
     "touch": "Berührung",
-    "self": "Selbst"
+    "self": "Selbst",
+    "effect": "Effekt"
   },
   "creator": {
     "new": "Neuen Charakter erstellen",

+ 16 - 0
src/services/utils/utils.service.spec.ts

@@ -0,0 +1,16 @@
+import { TestBed } from '@angular/core/testing';
+
+import { UtilsService } from './utils.service';
+
+describe('UtilsService', () => {
+  let service: UtilsService;
+
+  beforeEach(() => {
+    TestBed.configureTestingModule({});
+    service = TestBed.inject(UtilsService);
+  });
+
+  it('should be created', () => {
+    expect(service).toBeTruthy();
+  });
+});

+ 59 - 0
src/services/utils/utils.service.ts

@@ -0,0 +1,59 @@
+import { Injectable } from '@angular/core';
+import { DataService } from 'src/services/data/data.service';
+
+@Injectable({
+  providedIn: 'root',
+})
+export class UtilsService {
+  private spellcastingAttribute: string = 'wisdom'; // backup
+  private proficiencyBonus: number = 2;
+  private attributeValue: number = 0;
+  public spellAttackModifier: string = '';
+  public spellSaveDC: number = 0;
+
+  public constructor(private dataAccessor: DataService) {
+    this.spellcastingAttribute =
+      this.dataAccessor.spellslots.spellcastingAttribute;
+
+    this.subscribeToProficiency();
+    this.subscribeToAttribute();
+  }
+
+  /////////////////////////////////////////////
+  //        SPELLCASTING MODIFIERS           //
+  /////////////////////////////////////////////
+
+  private calculateModifiers(): void {
+    const spellcastingAttribute = this.spellcastingAttribute;
+    if (spellcastingAttribute !== undefined) {
+      const modifier = Math.floor((this.attributeValue - 10) / 2);
+      let attackBonus = modifier + this.proficiencyBonus;
+      if (attackBonus >= 0) {
+        this.spellAttackModifier = '+' + attackBonus;
+      } else {
+        this.spellAttackModifier = attackBonus.toString();
+      }
+      this.spellSaveDC = 8 + modifier + this.proficiencyBonus;
+    }
+  }
+
+  private subscribeToAttribute(): void {
+    if (
+      this.spellcastingAttribute !== undefined &&
+      this.spellcastingAttribute !== null
+    ) {
+      const command =
+        'this.dataAccessor.' +
+        this.spellcastingAttribute.toLowerCase() +
+        '$.subscribe((attribute) => {this.attributeValue = attribute.value; this.calculateModifiers();});';
+      eval(command);
+    }
+  }
+
+  private subscribeToProficiency(): void {
+    this.dataAccessor.proficiency$.subscribe((value: number) => {
+      this.proficiencyBonus = value;
+      this.calculateModifiers();
+    });
+  }
+}