Bladeren bron

Version 0.2 complete. Spells are missing

Warafear 1 jaar geleden
bovenliggende
commit
2bb3f5e664
19 gewijzigde bestanden met toevoegingen van 156 en 182 verwijderingen
  1. 36 0
      .nx/cache/d/daemon.log
  2. 1 1
      .nx/cache/d/server-process.json
  3. 0 2
      src/app/journal/journal-spellcards/journal-spellcards.component.html
  4. 1 1
      src/app/journal/journal-spellcards/journal-spellcards.component.ts
  5. 13 0
      src/app/journal/journal-stats/ability-panel/ability-table/ability-table.component.html
  6. 12 0
      src/app/journal/journal-stats/ability-panel/spellslots/spellslots.component.html
  7. 1 1
      src/app/journal/journal-stats/ability-panel/spellslots/spellslots.component.ts
  8. 13 10
      src/app/journal/journal-stats/ability-panel/trait-table/trait-table.component.html
  9. 3 4
      src/app/journal/journal-stats/attribute-skill-container/save-throw-panel/save-throw-field/save-throw-field.component.html
  10. 4 15
      src/app/journal/journal-stats/attribute-skill-container/save-throw-panel/save-throw-field/save-throw-field.component.ts
  11. 0 1
      src/app/journal/journal-stats/life-container/life/life.component.html
  12. 0 3
      src/app/journal/journal-stats/life-container/life/life.component.ts
  13. 15 7
      src/app/journal/journal-stats/weapons-container/spell-table/spell-table.component.html
  14. 0 1
      src/app/journal/journal-stats/weapons-container/spell-table/spell-table.component.ts
  15. 26 6
      src/app/journal/journal-stats/weapons-container/weapon-table/weapon-modal/weapon-modal.component.html
  16. 4 8
      src/app/journal/journal-stats/weapons-container/weapon-table/weapon-modal/weapon-modal.component.ts
  17. 19 14
      src/app/journal/journal-stats/weapons-container/weapon-table/weapon-table.component.html
  18. 2 2
      src/interfaces/weapon.ts
  19. 6 106
      src/services/data/data.service.ts

+ 36 - 0
.nx/cache/d/daemon.log

@@ -461546,3 +461546,39 @@ To fix this, set a unique name for each project in a project.json inside the pro
     at async processFilesAndCreateAndSerializeProjectGraph (C:\Softwareprojekte\DnD\node_modules\nx\src\daemon\server\project-graph-incremental-recomputation.js:138:17)
 [NX Daemon Server] - 2023-12-15T16:02:38.795Z - Time taken for 'hash changed files from watcher' 38.62120001018047ms
 [NX Daemon Server] - 2023-12-15T16:02:38.796Z - Done responding to the client null
+[NX Daemon Server] - 2023-12-16T09:44:37.308Z - Started listening on: \\.\pipe\nx\C:\Users\chris\AppData\Local\Temp\83d14e7134fc08a15480\d.sock
+[NX Daemon Server] - 2023-12-16T09:44:37.315Z - [WATCHER]: Subscribed to changes within: c:\Softwareprojekte\DnD (native)
+[NX Daemon Server] - 2023-12-16T09:44:37.316Z - Established a connection. Number of open connections: 1
+[NX Daemon Server] - 2023-12-16T09:44:37.318Z - Established a connection. Number of open connections: 2
+[NX Daemon Server] - 2023-12-16T09:44:37.319Z - Closed a connection. Number of open connections: 1
+[NX Daemon Server] - 2023-12-16T09:44:37.322Z - [REQUEST]: Client Request for Project Graph Received
+[NX Daemon Server] - 2023-12-16T09:44:37.451Z - Error detected when recomputing project file map: The following projects are defined in multiple locations:
+- DnDTools: 
+  - 
+  - .
+
+To fix this, set a unique name for each project in a project.json inside the project's root. If the project does not currently have a project.json, you can create one that contains only a name.
+[NX Daemon Server] - 2023-12-16T09:44:37.451Z - [REQUEST]: Responding to the client with an error. Error when preparing serialized project graph. The following projects are defined in multiple locations:
+- DnDTools: 
+  - 
+  - .
+
+To fix this, set a unique name for each project in a project.json inside the project's root. If the project does not currently have a project.json, you can create one that contains only a name.
+Error: The following projects are defined in multiple locations:
+- DnDTools: 
+  - 
+  - .
+
+To fix this, set a unique name for each project in a project.json inside the project's root. If the project does not currently have a project.json, you can create one that contains only a name.
+    at readProjectConfigurationsFromRootMap (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\project-configuration-utils.js:97:15)
+    at buildProjectsConfigurationsFromProjectPathsAndPlugins (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\project-configuration-utils.js:70:19)
+    at createProjectConfigurations (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:131:129)
+    at WorkspaceContext.<anonymous> (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:82:39)
+    at getProjectConfigurationsFromContext (c:\Softwareprojekte\DnD\node_modules\nx\src\utils\workspace-context.js:26:29)
+    at _retrieveProjectConfigurations (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:81:72)
+    at retrieveProjectConfigurations (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:58:12)
+    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
+    at async processCollectedUpdatedAndDeletedFiles (c:\Softwareprojekte\DnD\node_modules\nx\src\daemon\server\project-graph-incremental-recomputation.js:102:34)
+    at async processFilesAndCreateAndSerializeProjectGraph (c:\Softwareprojekte\DnD\node_modules\nx\src\daemon\server\project-graph-incremental-recomputation.js:138:17)
+[NX Daemon Server] - 2023-12-16T09:44:37.453Z - Time taken for 'hash changed files from watcher' 29.795899987220764ms
+[NX Daemon Server] - 2023-12-16T09:44:37.454Z - Done responding to the client null

+ 1 - 1
.nx/cache/d/server-process.json

@@ -1 +1 @@
-{"processId":1964}
+{"processId":6796}

+ 0 - 2
src/app/journal/journal-spellcards/journal-spellcards.component.html

@@ -54,5 +54,3 @@
     }
   </div>
 </div>
-
-<!-- (click)="openSpellModal(true, index, spellIndex)" -->

+ 1 - 1
src/app/journal/journal-spellcards/journal-spellcards.component.ts

@@ -86,7 +86,7 @@ export class JournalSpellcardsComponent {
             this.openSpellModal(true, level, spellIndex);
           }, 100);
         } else if (result.state === 'add') {
-          this.dataAccessor.favoriteSpells.push(spell);
+          this.dataAccessor.addFavoriteSpell(spell);
         } else if (result.state !== 'cancel') {
           console.log(result.state);
           throw new Error('Unexpected result state, please send a bug report.');

+ 13 - 0
src/app/journal/journal-stats/ability-panel/ability-table/ability-table.component.html

@@ -1,4 +1,5 @@
 <div cdkDropList class="example-list" (cdkDropListDropped)="drop($event)">
+  @for(ability of abilities; let index = $index; track ability){
   <div
     class="example-box"
     [class]="ability.currentlyUsedCharges === ability.charges ? 'used' : ''"
@@ -31,6 +32,18 @@
       </span>
     </div>
   </div>
+  }@empty{
+  <div
+    style="
+      text-align: center;
+      margin-top: 2rem;
+      font-size: 1.25rem;
+      font-weight: 500;
+    "
+  >
+    Noch keine Fähigkeit hinzugefügt
+  </div>
+  }
 </div>
 
 <ability-modal

+ 12 - 0
src/app/journal/journal-stats/ability-panel/spellslots/spellslots.component.html

@@ -30,6 +30,18 @@
       </ng-container>
     </div>
   </div>
+  @if(!kiPoints.showKiPoints && !showSpellslots){
+  <div
+    style="
+      text-align: center;
+      margin-top: 2rem;
+      font-size: 1.25rem;
+      font-weight: 500;
+    "
+  >
+    Weder KI-Punkte noch Zauberplätze hinzugefügt
+  </div>
+  }
 </div>
 
 <spellslots-modal

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

@@ -33,7 +33,7 @@ export class SpellslotsComponent {
         this.correctSpellslotsView(levelIndex);
       });
       this.correctKiPointsView();
-    }, 200);
+    }, 10);
   }
 
   //////////////

+ 13 - 10
src/app/journal/journal-stats/ability-panel/trait-table/trait-table.component.html

@@ -1,4 +1,5 @@
 <div cdkDropList class="example-list" (cdkDropListDropped)="drop($event)">
+  @for(trait of traits; let index = $index; track trait){
   <div
     class="example-box"
     *ngFor="let trait of traits; let abilityIndex = index"
@@ -11,15 +12,19 @@
 
     <p>{{ trait.shortDescription }}</p>
   </div>
+  }@empty{
+  <div
+    style="
+      text-align: center;
+      margin-top: 2rem;
+      font-size: 1.25rem;
+      font-weight: 500;
+    "
+  >
+    Noch keine Eigenschaft hinzugefügt
+  </div>
+  }
 </div>
-<!-- <ui-button
-  style="margin: 1rem"
-  [type]="'add'"
-  [size]="'xlarge'"
-  [color]="'primary'"
-  (click)="openTraitModal()"
->
-</ui-button> -->
 
 <trait-modal
   (traitCreated)="addNewlyCreatedTrait($event)"
@@ -27,5 +32,3 @@
   [isToUpdate]="isToUpdate"
   [traitToUpdate]="traitToUpdate"
 ></trait-modal>
-
-<!-- (click)="openTraitModal(abilityIndex)" -->

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

@@ -5,11 +5,10 @@
     [(ngModel)]="attribute.proficiency"
     (click)="updateAttribute(); $event.stopPropagation()"
   />
-  <div>{{ attribute.proficiency }}></div>
 
-  <div class="save-throw-field__name">{{ nameTranslator[attributeName] }}</div>
+  <div class="save-throw-field__name">
+    {{ nameTranslator[attributeName] }}
+  </div>
 
   <div class="save-throw-field__value">{{ saveModifier }}</div>
 </div>
-
-<!-- updateAttribute(); -->

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

@@ -19,7 +19,7 @@ export class SaveThrowFieldComponent {
   @Input() attributeName: string = '';
   public attribute: Attribute = { name: '', value: 0, proficiency: false };
 
-  private proficiencyBonus: number = 2;
+  private proficiencyBonus: number = 0;
   private attributeModifier: number = 0;
   public saveModifier: string = '0';
 
@@ -35,11 +35,6 @@ export class SaveThrowFieldComponent {
   public ngOnInit(): void {
     this.initAttributeSubscription();
     this.initProficiencySubscription();
-    // if (this.attributeName === 'charisma') {
-    //   setInterval(() => {
-    //     console.log('current attritube: ', this.attribute);
-    //   }, 1000);
-    // }
   }
 
   private initAttributeSubscription(): void {
@@ -47,7 +42,6 @@ export class SaveThrowFieldComponent {
       `this.dataAccessor.${this.attributeName}$`
     );
     observable.subscribe((newValue: Attribute) => {
-      // console.log('new value: ', newValue);
       this.attribute = newValue;
       this.attributeModifier = this.calculateAttributeModifier();
       this.saveModifier = this.calculateSaveModifier();
@@ -86,13 +80,8 @@ export class SaveThrowFieldComponent {
   }
 
   public updateAttribute(): void {
-    this.dataAccessor.updateAttribute(this.attribute);
+    setTimeout(() => {
+      this.dataAccessor.updateAttribute(this.attribute);
+    });
   }
-
-  // log(): void {
-  //   // console.log('current attritube: ', this.attributeProficiency);
-  //   // this.dataAccessor.updateAttribute(this.attribute);
-  //   // this.attributeProficiency = !this.attributeProficiency;
-  //   this.calculateSaveModifier();
-  // }
 }

+ 0 - 1
src/app/journal/journal-stats/life-container/life/life.component.html

@@ -1,6 +1,5 @@
 <div class="life-box">
   <div class="life-box-name" (click)="openDetailsPanel()">Trefferpunkte</div>
-  <div>{{ name }}</div>
   <div class="life-box-bar" (click)="openDetailsPanel()">
     <!-- FIXME: The percentages are not shown correctly when using the details panel -->
     <div

+ 0 - 3
src/app/journal/journal-stats/life-container/life/life.component.ts

@@ -22,15 +22,12 @@ export class LifeComponent {
   public temporaryHitPointsPercentage: number = 0;
   public missingHitPointsPercentage: number = 0;
 
-  public name: string = '';
-
   ngOnInit(): void {
     const hitPointsData = this.dataAccessor.hitPoints;
     this.maxHitPoints = hitPointsData.maxHitPoints;
     this.currentHitPoints = hitPointsData.currentHitPoints;
     this.temporaryHitPoints = hitPointsData.temporaryHitPoints;
     this.calculatePercentages();
-    this.name = this.dataAccessor.characterName;
   }
 
   public addHitPoints(): void {

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

@@ -16,12 +16,8 @@
     class="example-list table-content"
     (cdkDropListDropped)="dropSpells($event)"
   >
-    <div
-      class="example-box"
-      *ngFor="let spell of spells; let index = index"
-      cdkDrag
-      (click)="showFullSpellcard(index)"
-    >
+    @for(spell of spells; let index = $index; track spell){
+    <div class="example-box" cdkDrag (click)="showFullSpellcard(index)">
       <!--  Range Icon -->
       <ng-container
         [ngTemplateOutlet]="distanceIconTemplate"
@@ -63,6 +59,18 @@
         [ngTemplateOutletContext]="{ spell: spell }"
       ></ng-container>
     </div>
+    }@empty{
+    <div
+      style="
+        text-align: center;
+        margin-top: 2rem;
+        font-size: 1.25rem;
+        font-weight: 500;
+      "
+    >
+      Noch keine Zauber hinzugefügt
+    </div>
+    }
   </div>
   <input
     id="typeahead-basic"
@@ -161,7 +169,7 @@
 <ng-template #spellRangeTemplate let-spell="spell">
   <div class="spell-range">
     <div *ngIf="spell.isRanged">{{ spell.range }} ft.</div>
-    <div *ngIf="!spell.isRanged">5 ft.</div>
+    <div *ngIf="!spell.isRanged">Berührung</div>
 
     <div *ngIf="spell.hasAreaOfEffect">
       <span>{{ spell.radius }} ft. {{ areas[spell.areaOfEffectType] }} </span>

+ 0 - 1
src/app/journal/journal-stats/weapons-container/spell-table/spell-table.component.ts

@@ -56,7 +56,6 @@ export class SpellTableComponent {
     this.spells = this.dataAccessor.favoriteSpells;
     this.preparedSpells = this.dataAccessor.getAllPreparedSpells();
     this.preparedSpellsNames = this.preparedSpells.map((spell) => spell.name);
-    console.log(this.preparedSpellsNames);
     this.subscribeToData();
   }
 

+ 26 - 6
src/app/journal/journal-stats/weapons-container/weapon-table/weapon-modal/weapon-modal.component.html

@@ -69,22 +69,42 @@
     </div>
 
     <div class="input-element" *ngIf="isRanged">
-      <label for="weaponRange">Reichweite</label>
+      <label for="weaponRange">Normale Reichweite</label>
       <input
-        type="text"
+        type="number"
         class="add-input"
         id="weaponRange"
-        [(ngModel)]="range"
+        [(ngModel)]="range[0]"
+      />
+    </div>
+
+    <div class="input-element" *ngIf="isRanged">
+      <label for="weaponRange">Große Reichweite</label>
+      <input
+        type="number"
+        class="add-input"
+        id="weaponRange"
+        [(ngModel)]="range[1]"
+      />
+    </div>
+
+    <div class="input-element" *ngIf="canBeThrown">
+      <label for="weaponRange">Normale Wurfreichweite</label>
+      <input
+        type="number"
+        class="add-input"
+        id="weaponRange"
+        [(ngModel)]="throwRange[0]"
       />
     </div>
 
     <div class="input-element" *ngIf="canBeThrown">
-      <label for="weaponRange">Wurfreichweite</label>
+      <label for="weaponRange">Große Wurfreichweite</label>
       <input
-        type="text"
+        type="number"
         class="add-input"
         id="weaponRange"
-        [(ngModel)]="throwRange"
+        [(ngModel)]="throwRange[1]"
       />
     </div>
 

+ 4 - 8
src/app/journal/journal-stats/weapons-container/weapon-table/weapon-modal/weapon-modal.component.ts

@@ -14,8 +14,8 @@ export class WeaponModalComponent {
   @Input() public isUpdate: boolean = false;
 
   public name: string = '';
-  public range: string = '5 ft.';
-  public throwRange: string = '';
+  public range: number[] = [5, 5];
+  public throwRange: number[] = [5, 5];
   public attackBonus: string = '+0';
   public damage: Damage[] = [{ diceNumber: '', diceType: '', damageType: '' }];
   public proficient: boolean = false;
@@ -141,10 +141,6 @@ export class WeaponModalComponent {
     this.resetItem();
   }
 
-  /**
-   * Creates a new Weapon object with the updated or newly generated values.
-   * @returns The created item
-   */
   public createItem(): Weapon {
     console.log('createItem() in weapon-modal.component.ts');
     return {
@@ -171,8 +167,8 @@ export class WeaponModalComponent {
    */
   public resetItem(): void {
     this.name = '';
-    this.range = '5 ft.';
-    this.throwRange = '';
+    this.range = [5, 5];
+    this.throwRange = [5, 5];
     this.attackBonus = '+0';
     this.damage = [{ diceNumber: '', diceType: '', damageType: '' }];
     this.proficient = false;

+ 19 - 14
src/app/journal/journal-stats/weapons-container/weapon-table/weapon-table.component.html

@@ -12,12 +12,8 @@
     class="example-list table-content"
     (cdkDropListDropped)="dropWeapons($event)"
   >
-    <div
-      class="example-box"
-      *ngFor="let weapon of weapons; let index = index"
-      cdkDrag
-      (click)="openDetailsPanel(index)"
-    >
+    @for(weapon of weapons; let index = $index; track weapon){
+    <div class="example-box" cdkDrag (click)="openDetailsPanel(index)">
       <!--  Range Icon -->
       <ng-container
         [ngTemplateOutlet]="distanceIconTemplate"
@@ -44,6 +40,18 @@
         [ngTemplateOutletContext]="{ weapon: weapon }"
       ></ng-container>
     </div>
+    } @empty{
+    <div
+      style="
+        text-align: center;
+        margin-top: 3rem;
+        font-size: 1.25rem;
+        font-weight: 500;
+      "
+    >
+      Noch keine Waffen hinzugefügt
+    </div>
+    }
   </div>
 </div>
 
@@ -91,12 +99,9 @@
 
 <!-- Range -->
 <ng-template #weaponRangeTemplate let-weapon="weapon">
-  <div class="weapon-range">{{ weapon.range }}</div>
+  @if(weapon.isRanged){
+  <div class="weapon-range">
+    {{ weapon.range[0] }}/{{ weapon.range[1] }} ft.
+  </div>
+  }@else{ Nahkampf }
 </ng-template>
-
-<!-- <weapon-modal
-  #weaponTable
-  (weaponCreated)="addWeapon($event)"
-  (weaponUpdated)="updateWeapon($event.weapon, $event.index)"
-  (weaponDelete)="deleteWeapon($event)"
-></weapon-modal> -->

+ 2 - 2
src/interfaces/weapon.ts

@@ -2,8 +2,8 @@ export interface Weapon {
   name: string;
   damage: Damage[];
   attackBonus: string;
-  range: string;
-  throwRange?: string;
+  range: number[];
+  throwRange?: number[];
   proficient: boolean;
   isVersatile: boolean;
   isTwoHanded: boolean;

+ 6 - 106
src/services/data/data.service.ts

@@ -134,114 +134,9 @@ export class DataService {
 
   // #endregion
 
-  // #region WEAPONS
-
-  // #endregion
-
   // #region # SPELLS
 
-  private _favoriteSpells: Spell[] = [
-    {
-      name: 'Feuerball',
-      level: 3,
-      cost: 'action',
-      canRitual: false,
-      needsVerbal: true,
-      needsSomatic: true,
-      needsMaterial: true,
-      needsConcentration: false,
-      needsAttackRoll: false,
-      needsSavingThrow: true,
-      savingThrowAttribute: 'dexterity',
-      school: 'evocation',
-      doesDamage: true,
-      damage: [
-        { diceNumber: '8', diceType: 'd6', damageType: 'fire' },
-        { diceNumber: '8', diceType: 'd6', damageType: 'fire' },
-      ],
-      doesHeal: false,
-      heal: { diceNumber: '', diceType: '', additionalHeal: 0 },
-      isRanged: true,
-      description:
-        'Ein heller Strahl schießt von deinem Zeigefinger zu einem von dir gewählten Punkt in Reichweite und blüht dann mit einem tiefen Brüllen zu einer Flammenexplosion auf. Jede Kreatur in einem Umkreis von 6 Metern um diesen Punkt muss einen Rettungswurf auf Geschicklichkeit machen. Bei einem misslungenen Rettungswurf erleidet das Ziel 8W6 Feuerschaden, bei einem erfolgreichen Wurf die Hälfte des Schadens. Das Feuer breitet sich um Ecken aus. Es entzündet brennbare Gegenstände in der Umgebung, die nicht getragen werden. Wenn du diesen Zauber mit einem Zauberplatz des 4. Grades oder höher wirkst, erhöht sich der Schaden um 1W6 für jeden Grad über dem 3.',
-      range: 150,
-      hasAreaOfEffect: true,
-      radius: 20,
-      areaOfEffectType: 'sphere',
-    },
-    {
-      name: 'Feuerpfeil',
-      level: 0,
-      cost: 'action',
-      canRitual: false,
-      needsVerbal: true,
-      needsSomatic: true,
-      needsMaterial: true,
-      needsConcentration: false,
-      needsAttackRoll: true,
-      needsSavingThrow: false,
-      school: 'evocation',
-      doesDamage: true,
-      doesHeal: false,
-      heal: { diceNumber: '', diceType: '', additionalHeal: 0 },
-      description:
-        'Du schleuderst einen Splitter aus Feuer auf eine Kreatur in Reichweite. Lege einen Fernkampf-Zauberangriff gegen das Ziel ab. Bei einem Treffer erleidet das Ziel 1W10 Feuerschaden. Ein brennbarer Gegenstand, der von diesem Zauber getroffen wird, geht in Flammen auf, wenn er nicht getragen oder in der Hand gehalten wird. Der Schaden dieses Zaubers steigt um 1W10, wenn du die 5. Stufe (2W10), die 11. Stufe (3W10) und die 17. Stufe (4W10) erreichst.  ',
-      damage: [{ diceNumber: '1', diceType: 'd10', damageType: 'fire' }],
-      isRanged: true,
-      range: 120,
-      hasAreaOfEffect: false,
-      areaOfEffectType: '',
-      radius: 0,
-    },
-    {
-      name: 'Vampiric Touch',
-      level: 3,
-      cost: 'action',
-      canRitual: false,
-      needsVerbal: true,
-      needsSomatic: true,
-      needsMaterial: false,
-      needsConcentration: true,
-      needsAttackRoll: true,
-      needsSavingThrow: false,
-      doesDamage: true,
-      doesHeal: false,
-      heal: { diceNumber: '', diceType: '', additionalHeal: 0 },
-      description:
-        'Die Berührung deiner schattenumrankten Hand kann anderen die Lebenskraft entziehen, um deine Wunden zu heilen. Führe einen Nahkampf-Zauberangriff gegen eine Kreatur in deiner Reichweite aus. Bei einem Treffer erleidet das Ziel 3W6 nekrotischen Schaden, und du erhältst Trefferpunkte in Höhe der Hälfte des zugefügten nekrotischen Schadens zurück. Bis der Zauber endet, kannst du den Angriff in jeder deiner Runden als Aktion wiederholen. Wenn du diesen Zauber mit einem Zauberplatz des 4. Grades oder höher wirkst, erhöht sich der Schaden um 1W6 für jeden Grad über dem 3.',
-      school: 'necromancy',
-      damage: [{ diceNumber: '3', diceType: 'd6', damageType: 'necrotic' }],
-      isRanged: false,
-      range: 5,
-      hasAreaOfEffect: false,
-      areaOfEffectType: '',
-      radius: 0,
-    },
-    {
-      name: 'Heilende Berührung',
-      level: 1,
-      cost: 'action',
-      canRitual: false,
-      needsVerbal: true,
-      needsSomatic: true,
-      needsMaterial: false,
-      needsConcentration: false,
-      needsAttackRoll: false,
-      needsSavingThrow: false,
-      doesDamage: false,
-      damage: [{ diceNumber: '', diceType: '', damageType: '' }],
-      doesHeal: true,
-      heal: { diceNumber: '1', diceType: 'd8', additionalHeal: 5 },
-      description:
-        'Deine Berührung kann Wunden heilen. Berühre eine Kreatur und spende ihr 1W8 + deinem Fertigkeitsbonus Trefferpunkte. Dieser Zauber hat keine Wirkung auf Untote oder Konstrukte. Wenn du diesen Zauber mit einem Zauberplatz des 2. Grades oder höher wirkst, erhöht sich die Heilung um 1W8 für jeden Grad über dem 1.',
-      school: 'evocation',
-      isRanged: false,
-      range: 5,
-      hasAreaOfEffect: false,
-      areaOfEffectType: '',
-      radius: 0,
-    },
-  ];
+  private _favoriteSpells: Spell[] = [];
 
   public get favoriteSpells(): Spell[] {
     return this._favoriteSpells;
@@ -252,6 +147,11 @@ export class DataService {
     this.setData('favoriteSpells', { spells: spells });
   }
 
+  public addFavoriteSpell(spell: Spell): void {
+    this._favoriteSpells.push(spell);
+    this.setData('favoriteSpells', { spells: this._favoriteSpells });
+  }
+
   private _spellLevel0: Spell[] = [
     {
       name: 'Führung',