From 7f280fc74170fef443ea7d7694ba389af9149597 Mon Sep 17 00:00:00 2001 From: Matthias Puchstein Date: Sun, 15 Jun 2025 18:40:15 +0200 Subject: [PATCH] added spells --- public/icon64.png | Bin 0 -> 8272 bytes public/manifest.json | 3 +- src/components/CharacterSheet.css | 5 + src/components/CharacterSheet.tsx | 55 ++++++- src/components/Spells.tsx | 235 +++++++++++++++++++++++++++++ src/styles/talespire-variables.css | 1 + src/types/character.ts | 21 +++ 7 files changed, 314 insertions(+), 6 deletions(-) create mode 100644 public/icon64.png create mode 100644 src/components/Spells.tsx diff --git a/public/icon64.png b/public/icon64.png new file mode 100644 index 0000000000000000000000000000000000000000..e7ce54bbe6555f4316e951496010e0e328ecf961 GIT binary patch literal 8272 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 literal 0 HcmV?d00001 diff --git a/public/manifest.json b/public/manifest.json index bbb9836..512e29d 100644 --- a/public/manifest.json +++ b/public/manifest.json @@ -14,9 +14,10 @@ "initTimeout": 10 }, "icons": { - "64x64": "/icon.png" + "64x64": "/icon64.png" }, "environment": { + "webViewBackgroundColor": "#1a1a1a", "capabilities": ["chat", "dice"], "extras": ["colorStyles"] } diff --git a/src/components/CharacterSheet.css b/src/components/CharacterSheet.css index 236c21c..5613270 100644 --- a/src/components/CharacterSheet.css +++ b/src/components/CharacterSheet.css @@ -541,3 +541,8 @@ button:active { transform: scale(1.1); box-shadow: 0 6px 16px rgba(0, 0, 0, 0.3); } + +body { + background: var(--ts-background-primary, var(--background-color)); + transition: background-color 0.3s ease; +} \ No newline at end of file diff --git a/src/components/CharacterSheet.tsx b/src/components/CharacterSheet.tsx index 4a0ee9a..b10232f 100644 --- a/src/components/CharacterSheet.tsx +++ b/src/components/CharacterSheet.tsx @@ -1,13 +1,16 @@ +// src/components/CharacterSheet.tsx import React, { useState } from 'react'; -import type {DSACharacter} from '../types/character'; +import type { DSACharacter } from '../types/character'; import BasicInfo from './BasicInfo'; import Attributes from './Attributes'; import Skills from './Skills'; +import Spells from './Spells'; import CombatValues from './CombatValues'; -import './CharacterSheet.css'; -import ThemeToggle from "./ThemeToggle.tsx"; +import ThemeToggle from './ThemeToggle'; import iconUrl from '/icon.png'; +import './CharacterSheet.css'; +// Erweiterte Initial-Daten mit Astralenergie und Zaubern const initialCharacter: DSACharacter = { id: crypto.randomUUID(), name: '', @@ -26,12 +29,18 @@ const initialCharacter: DSACharacter = { strength: 8 }, skills: {}, + spells: {}, // ← Neu hinzugefügt combat: { lifePoints: { max: 30, current: 30 }, stamina: { max: 30, current: 30 }, initiative: 10, speed: 8 }, + astralEnergy: { // ← Neu hinzugefügt für Zauberer + max: 0, + current: 0 + }, + magicalTraditions: [], // ← Neu hinzugefügt advantages: [], disadvantages: [], equipment: [] @@ -40,17 +49,53 @@ const initialCharacter: DSACharacter = { const CharacterSheet: React.FC = () => { const [character, setCharacter] = useState(initialCharacter); + // Hilfsfunktion um zu prüfen ob Charakter Zauberer ist + const isSpellcaster = character.astralEnergy && character.astralEnergy.max > 0; + return (
+
- DSA 5e Logo + DSA 5e Character Sheet

DSA 5 Character Sheet

+ + {/* Grundinformationen */} + + {/* Eigenschaften */} - + + {/* Kampfwerte */} + + {/* Fertigkeiten */} + + + {/* Zauber - nur anzeigen wenn Astralenergie > 0 oder explizit gewünscht */} + {(isSpellcaster || Object.keys(character.spells).length > 0) && ( + + )} + + {/* Button zum Hinzufügen von Zaubern falls noch kein Zauberer */} + {!isSpellcaster && Object.keys(character.spells).length === 0 && ( +
+ +
+ )}
); }; diff --git a/src/components/Spells.tsx b/src/components/Spells.tsx new file mode 100644 index 0000000..37620b2 --- /dev/null +++ b/src/components/Spells.tsx @@ -0,0 +1,235 @@ +import React, { useState } from 'react'; +import type { DSACharacter, DSASpell, DSAAttributes } from '../types/character'; + +interface SpellsProps { + character: DSACharacter; + setCharacter: React.Dispatch>; +} + +const Spells: React.FC = ({ character, setCharacter }) => { + const [newSpell, setNewSpell] = useState>({ + name: '', + tradition: [], + attributes: ['cleverness', 'intuition', 'charisma'], + skillValue: 0, + aspCost: '4 AsP', + castingTime: '2 Aktionen', + range: 'Berührung', + duration: 'Sofort', + difficulty: 0, + description: '', + effect: '' + }); + + // Häufige DSA 5e Zauber für Quick-Add + const commonSpells: Partial[] = [ + { + name: 'Ignifaxius', + tradition: ['Gildenmagier'], + attributes: ['cleverness', 'dexterity', 'constitution'], + aspCost: '2 AsP', + castingTime: '2 Aktionen', + range: '7 Meter', + duration: 'Sofort', + difficulty: 0, + description: 'Entzündet brennbares Material' + }, + { + name: 'Odem Arcanum', + tradition: ['Gildenmagier'], + attributes: ['cleverness', 'intuition', 'intuition'], + aspCost: '1 AsP', + castingTime: '2 Aktionen', + range: 'Berührung', + duration: 'Sofort', + difficulty: 0, + description: 'Erkennt magische Objekte und Wesen' + }, + { + name: 'Balsam Salabunde', + tradition: ['Gildenmagier', 'Druide'], + attributes: ['cleverness', 'intuition', 'dexterity'], + aspCost: '4 AsP (A), 2 AsP (B), 8 AsP (C)', + castingTime: '8 Aktionen', + range: 'Berührung', + duration: 'Sofort', + difficulty: 0, + description: 'Heilt Wunden' + } + ]; + + const addSpell = (spellData: Partial) => { + const spell: DSASpell = { + id: crypto.randomUUID(), + name: spellData.name || '', + tradition: spellData.tradition || [], + attributes: spellData.attributes || ['cleverness', 'intuition', 'charisma'], + skillValue: spellData.skillValue || 0, + aspCost: spellData.aspCost || '4 AsP', + castingTime: spellData.castingTime || '2 Aktionen', + range: spellData.range || 'Berührung', + duration: spellData.duration || 'Sofort', + difficulty: spellData.difficulty || 0, + description: spellData.description || '', + effect: spellData.effect || '' + }; + + setCharacter(prev => ({ + ...prev, + spells: { + ...prev.spells, + [spell.id]: spell + } + })); + }; + + const updateSpell = (spellId: string, field: keyof DSASpell, value: any) => { + setCharacter(prev => ({ + ...prev, + spells: { + ...prev.spells, + [spellId]: { + ...prev.spells[spellId], + [field]: value + } + } + })); + }; + + const removeSpell = (spellId: string) => { + setCharacter(prev => { + const { [spellId]: removed, ...remainingSpells } = prev.spells; + return { + ...prev, + spells: remainingSpells + }; + }); + }; + + const calculateSpellCheck = (spell: DSASpell): number => { + const [attr1, attr2, attr3] = spell.attributes; + return character.attributes[attr1] + character.attributes[attr2] + character.attributes[attr3] + spell.skillValue; + }; + + const updateAstralEnergy = (field: 'max' | 'current', value: number) => { + setCharacter(prev => ({ + ...prev, + astralEnergy: { + ...prev.astralEnergy!, + [field]: Math.max(0, value) + } + })); + }; + + return ( +
+

Zauber & Astralenergie

+ + {/* Astralenergie Tracking */} + {character.astralEnergy && ( +
+

Astralenergie (AsP)

+
+
+ + updateAstralEnergy('current', parseInt(e.target.value) || 0)} + min="0" + /> +
+
+ + updateAstralEnergy('max', parseInt(e.target.value) || 0)} + min="0" + /> +
+
+
+ )} + + {/* Häufige Zauber hinzufügen */} +
+

Häufige Zauber hinzufügen

+
+ {commonSpells.map((spell, index) => ( + + ))} +
+
+ + {/* Zauberliste */} +
+

Beherrschte Zauber

+ {Object.keys(character.spells).length === 0 ? ( +

Noch keine Zauber erlernt. Füge welche hinzu!

+ ) : ( +
+ {Object.entries(character.spells).map(([spellId, spell]) => ( +
+
+

{spell.name}

+ +
+ +
+
+ {spell.attributes.map(attr => attr.substring(0, 2).toUpperCase()).join('/')} +
+ +
+
AsP: {spell.aspCost}
+
Dauer: {spell.castingTime}
+
Reichweite: {spell.range}
+
+
+ +
+ + updateSpell(spellId, 'skillValue', parseInt(e.target.value) || 0)} + min="0" + max="20" + /> +
+ +
+ Gesamt: {calculateSpellCheck(spell)} +
+ + {spell.description && ( +
+ {spell.description} +
+ )} +
+ ))} +
+ )} +
+
+ ); +}; + +export default Spells; \ No newline at end of file diff --git a/src/styles/talespire-variables.css b/src/styles/talespire-variables.css index 81b8083..437a6d5 100644 --- a/src/styles/talespire-variables.css +++ b/src/styles/talespire-variables.css @@ -12,4 +12,5 @@ /* Add other TaleSpire variables as you discover them */ --ts-color-background: #f5f5f5; --ts-color-on-background: #222222; + --ts-background-primary: #1a1a1a, } diff --git a/src/types/character.ts b/src/types/character.ts index ce3b1e1..e0fbcdb 100644 --- a/src/types/character.ts +++ b/src/types/character.ts @@ -32,6 +32,21 @@ export interface DSACombatValues { speed: number; } +export interface DSASpell { + id: string; + name: string; + tradition: string[]; // Gildenmagier, Hexe, Druide, etc. + attributes: [keyof DSAAttributes, keyof DSAAttributes, keyof DSAAttributes]; + skillValue: number; // FW - Fertigkeitswert + aspCost: string; // "4 AsP", "2 AsP pro Stufe" + castingTime: string; // "2 Aktionen", "5 Minuten" + range: string; // "Berührung", "7 Meter" + duration: string; // "Sofort", "5 Minuten" + difficulty: number; // Erschwernis/Erleichterung + description: string; + effect: string; +} + export interface DSACharacter { id: string; name: string; @@ -45,4 +60,10 @@ export interface DSACharacter { advantages: string[]; // Vorteile disadvantages: string[]; // Nachteile equipment: string[]; // Ausrüstung + astralEnergy?: { + max: number; + current: number; + }; + spells: Record; + magicalTraditions: string[]; }