chore: initialize homebrew-magic-rpg monorepo
Consolidates the HbM: RPG project (formerly the loose hbm-books working folder) into a single repo. ObsidianNotes, foundry-lore, and foundry-system are wired in as submodules pointing at their existing Gitea repos. Loose tooling scripts are organized under tools/, obsolete/one-off scripts (fix_vault.py, generate_mocs.py, debug-*.ts, write_file_helper.py) and _books/ (superseded by ObsidianNotes) are excluded via .gitignore rather than deleted. foundryvtt-admin is excluded pending its own separate repo.
This commit is contained in:
@@ -0,0 +1,154 @@
|
||||
/**
|
||||
* HbM: RPG v3 - Creature/Monster Template
|
||||
*/
|
||||
|
||||
export const creatureTemplate = {
|
||||
name: '',
|
||||
nameEN: '',
|
||||
type: '', // Typ (np. Humanoid, Bestia, Nieumarły)
|
||||
size: '', // Rozmiar
|
||||
alignment: '', // Charakter
|
||||
|
||||
// Stats
|
||||
stats: {
|
||||
hp: 0,
|
||||
hpFormula: '',
|
||||
ac: 0,
|
||||
acType: '',
|
||||
speed: '',
|
||||
|
||||
// Attributes
|
||||
str: 10,
|
||||
dex: 10,
|
||||
con: 10,
|
||||
int: 10,
|
||||
wis: 10,
|
||||
cha: 10,
|
||||
},
|
||||
|
||||
// Combat
|
||||
combat: {
|
||||
attacks: [],
|
||||
specialAbilities: [],
|
||||
reactions: [],
|
||||
legendaryActions: [],
|
||||
},
|
||||
|
||||
// Defenses
|
||||
defenses: {
|
||||
savingThrows: [],
|
||||
skills: [],
|
||||
damageResistances: [],
|
||||
damageImmunities: [],
|
||||
conditionImmunities: [],
|
||||
senses: '',
|
||||
languages: '',
|
||||
},
|
||||
|
||||
// Challenge
|
||||
challenge: {
|
||||
cr: 0,
|
||||
xp: 0,
|
||||
},
|
||||
|
||||
// Lore
|
||||
lore: {
|
||||
description: '',
|
||||
habitat: '',
|
||||
behavior: '',
|
||||
history: '',
|
||||
},
|
||||
|
||||
notes: '',
|
||||
};
|
||||
|
||||
function getModifier(score) {
|
||||
return Math.floor((score - 10) / 2);
|
||||
}
|
||||
|
||||
function formatModifier(mod) {
|
||||
return mod >= 0 ? `+${mod}` : `${mod}`;
|
||||
}
|
||||
|
||||
export function formatCreatureForBook(creature) {
|
||||
const stats = creature.stats;
|
||||
const mods = {
|
||||
str: formatModifier(getModifier(stats.str)),
|
||||
dex: formatModifier(getModifier(stats.dex)),
|
||||
con: formatModifier(getModifier(stats.con)),
|
||||
int: formatModifier(getModifier(stats.int)),
|
||||
wis: formatModifier(getModifier(stats.wis)),
|
||||
cha: formatModifier(getModifier(stats.cha)),
|
||||
};
|
||||
|
||||
let output = `## ${creature.name}
|
||||
*${creature.size} ${creature.type}, ${creature.alignment}*
|
||||
|
||||
---
|
||||
|
||||
**Klasa Pancerza:** ${stats.ac}${stats.acType ? ` (${stats.acType})` : ''}
|
||||
**Punkty Wytrzymałości:** ${stats.hp}${stats.hpFormula ? ` (${stats.hpFormula})` : ''}
|
||||
**Szybkość:** ${stats.speed}
|
||||
|
||||
---
|
||||
|
||||
| SIŁ | ZRE | KON | INT | MDR | CHA |
|
||||
|:---:|:---:|:---:|:---:|:---:|:---:|
|
||||
| ${stats.str} (${mods.str}) | ${stats.dex} (${mods.dex}) | ${stats.con} (${mods.con}) | ${stats.int} (${mods.int}) | ${stats.wis} (${mods.wis}) | ${stats.cha} (${mods.cha}) |
|
||||
|
||||
---
|
||||
`;
|
||||
|
||||
const def = creature.defenses;
|
||||
if (def.savingThrows.length) output += `**Rzuty Obronne:** ${def.savingThrows.join(', ')}\n`;
|
||||
if (def.skills.length) output += `**Umiejętności:** ${def.skills.join(', ')}\n`;
|
||||
if (def.damageResistances.length) output += `**Odporności na Obrażenia:** ${def.damageResistances.join(', ')}\n`;
|
||||
if (def.damageImmunities.length) output += `**Niewrażliwości na Obrażenia:** ${def.damageImmunities.join(', ')}\n`;
|
||||
if (def.conditionImmunities.length) output += `**Niewrażliwości na Stany:** ${def.conditionImmunities.join(', ')}\n`;
|
||||
if (def.senses) output += `**Zmysły:** ${def.senses}\n`;
|
||||
if (def.languages) output += `**Języki:** ${def.languages}\n`;
|
||||
output += `**Poziom Wyzwania:** ${creature.challenge.cr} (${creature.challenge.xp} PD)\n`;
|
||||
|
||||
output += '\n---\n\n';
|
||||
|
||||
// Special Abilities
|
||||
if (creature.combat.specialAbilities.length) {
|
||||
creature.combat.specialAbilities.forEach(ability => {
|
||||
output += `***${ability.name}.*** ${ability.description}\n\n`;
|
||||
});
|
||||
}
|
||||
|
||||
// Actions
|
||||
if (creature.combat.attacks.length) {
|
||||
output += '### Akcje\n\n';
|
||||
creature.combat.attacks.forEach(attack => {
|
||||
output += `***${attack.name}.*** ${attack.description}\n\n`;
|
||||
});
|
||||
}
|
||||
|
||||
// Reactions
|
||||
if (creature.combat.reactions.length) {
|
||||
output += '### Reakcje\n\n';
|
||||
creature.combat.reactions.forEach(reaction => {
|
||||
output += `***${reaction.name}.*** ${reaction.description}\n\n`;
|
||||
});
|
||||
}
|
||||
|
||||
// Legendary Actions
|
||||
if (creature.combat.legendaryActions.length) {
|
||||
output += '### Akcje Legendarne\n\n';
|
||||
creature.combat.legendaryActions.forEach(action => {
|
||||
output += `***${action.name}.*** ${action.description}\n\n`;
|
||||
});
|
||||
}
|
||||
|
||||
// Lore
|
||||
if (creature.lore.description) {
|
||||
output += '---\n\n';
|
||||
output += creature.lore.description + '\n';
|
||||
}
|
||||
|
||||
return output.trim();
|
||||
}
|
||||
|
||||
export default { creatureTemplate, formatCreatureForBook };
|
||||
@@ -0,0 +1,118 @@
|
||||
/**
|
||||
* HbM: RPG v3 - Item Template
|
||||
*/
|
||||
|
||||
export const itemTemplate = {
|
||||
name: '',
|
||||
nameEN: '',
|
||||
type: '', // Weapon, Armor, Potion, Wondrous, etc.
|
||||
rarity: '', // Common, Uncommon, Rare, Very Rare, Legendary, Artifact
|
||||
attunement: false,
|
||||
attunementReq: '', // e.g., "by a spellcaster"
|
||||
|
||||
// For weapons
|
||||
weapon: {
|
||||
damage: '',
|
||||
damageType: '',
|
||||
properties: [], // e.g., ["Finesse", "Light", "Thrown (20/60)"]
|
||||
},
|
||||
|
||||
// For armor
|
||||
armor: {
|
||||
ac: 0,
|
||||
acBonus: 0,
|
||||
type: '', // Light, Medium, Heavy, Shield
|
||||
stealthDisadv: false,
|
||||
strRequirement: 0,
|
||||
},
|
||||
|
||||
description: '',
|
||||
properties: [], // Special properties/abilities
|
||||
history: '', // Item lore/backstory
|
||||
|
||||
// Pricing
|
||||
value: '',
|
||||
weight: '',
|
||||
|
||||
notes: '',
|
||||
};
|
||||
|
||||
const rarityPL = {
|
||||
'Common': 'Pospolity',
|
||||
'Uncommon': 'Niepospolity',
|
||||
'Rare': 'Rzadki',
|
||||
'Very Rare': 'Bardzo Rzadki',
|
||||
'Legendary': 'Legendarny',
|
||||
'Artifact': 'Artefakt',
|
||||
};
|
||||
|
||||
export function formatItemForBook(item) {
|
||||
const rarity = rarityPL[item.rarity] || item.rarity;
|
||||
let typeStr = item.type;
|
||||
|
||||
if (item.weapon.damage) {
|
||||
typeStr = `Broń (${item.weapon.properties.join(', ')})`;
|
||||
} else if (item.armor.type) {
|
||||
typeStr = `Zbroja (${item.armor.type})`;
|
||||
}
|
||||
|
||||
let attunement = '';
|
||||
if (item.attunement) {
|
||||
attunement = item.attunementReq
|
||||
? ` (wymaga dostrojenia ${item.attunementReq})`
|
||||
: ' (wymaga dostrojenia)';
|
||||
}
|
||||
|
||||
let output = `### ${item.name}
|
||||
*${typeStr}, ${rarity}${attunement}*
|
||||
|
||||
`;
|
||||
|
||||
// Weapon stats
|
||||
if (item.weapon.damage) {
|
||||
output += `**Obrażenia:** ${item.weapon.damage} ${item.weapon.damageType}\n`;
|
||||
if (item.weapon.properties.length) {
|
||||
output += `**Właściwości:** ${item.weapon.properties.join(', ')}\n`;
|
||||
}
|
||||
output += '\n';
|
||||
}
|
||||
|
||||
// Armor stats
|
||||
if (item.armor.type) {
|
||||
if (item.armor.ac) {
|
||||
output += `**KP:** ${item.armor.ac}`;
|
||||
} else if (item.armor.acBonus) {
|
||||
output += `**Bonus KP:** +${item.armor.acBonus}`;
|
||||
}
|
||||
if (item.armor.stealthDisadv) output += ` (utrudnia skradanie)`;
|
||||
if (item.armor.strRequirement) output += ` (wymaga SIŁ ${item.armor.strRequirement})`;
|
||||
output += '\n\n';
|
||||
}
|
||||
|
||||
output += item.description + '\n';
|
||||
|
||||
// Special properties
|
||||
if (item.properties.length) {
|
||||
output += '\n';
|
||||
item.properties.forEach(prop => {
|
||||
output += `• **${prop.name}:** ${prop.description}\n`;
|
||||
});
|
||||
}
|
||||
|
||||
// Value and weight
|
||||
if (item.value || item.weight) {
|
||||
output += '\n---\n';
|
||||
if (item.value) output += `*Wartość: ${item.value}* `;
|
||||
if (item.weight) output += `*Waga: ${item.weight}*`;
|
||||
output += '\n';
|
||||
}
|
||||
|
||||
// Lore/History
|
||||
if (item.history) {
|
||||
output += `\n*${item.history}*\n`;
|
||||
}
|
||||
|
||||
return output.trim();
|
||||
}
|
||||
|
||||
export default { itemTemplate, formatItemForBook };
|
||||
@@ -0,0 +1,162 @@
|
||||
/**
|
||||
* HbM: RPG v3 - Location Template
|
||||
*/
|
||||
|
||||
export const locationTemplate = {
|
||||
name: '',
|
||||
nameEN: '',
|
||||
type: '', // City, Village, Dungeon, Forest, etc.
|
||||
region: '',
|
||||
|
||||
// Basic info
|
||||
population: '',
|
||||
government: '',
|
||||
economy: '',
|
||||
|
||||
// Description
|
||||
description: {
|
||||
overview: '',
|
||||
atmosphere: '', // Mood, feeling, sounds, smells
|
||||
history: '',
|
||||
secrets: '', // Hidden info for GM
|
||||
},
|
||||
|
||||
// Points of Interest
|
||||
landmarks: [], // { name, description }
|
||||
|
||||
// Inhabitants
|
||||
notableNPCs: [], // References or brief descriptions
|
||||
factions: [], // { name, description, goals }
|
||||
|
||||
// For adventures
|
||||
encounters: [], // Possible random encounters
|
||||
hooks: [], // Adventure hooks
|
||||
rumors: [], // Things NPCs might say
|
||||
|
||||
// For dungeons/adventure sites
|
||||
rooms: [], // { number, name, description, contents }
|
||||
|
||||
// Maps
|
||||
mapDescription: '', // Text description if no map available
|
||||
|
||||
notes: '',
|
||||
};
|
||||
|
||||
export function formatLocationForBook(location) {
|
||||
let output = `## ${location.name}\n`;
|
||||
if (location.type || location.region) {
|
||||
output += `*${[location.type, location.region].filter(Boolean).join(', ')}*\n`;
|
||||
}
|
||||
output += '\n';
|
||||
|
||||
// Overview
|
||||
if (location.description.overview) {
|
||||
output += location.description.overview + '\n\n';
|
||||
}
|
||||
|
||||
// Basic info
|
||||
const info = [];
|
||||
if (location.population) info.push(`**Populacja:** ${location.population}`);
|
||||
if (location.government) info.push(`**Władza:** ${location.government}`);
|
||||
if (location.economy) info.push(`**Gospodarka:** ${location.economy}`);
|
||||
if (info.length) {
|
||||
output += info.join(' | ') + '\n\n';
|
||||
}
|
||||
|
||||
// Atmosphere
|
||||
if (location.description.atmosphere) {
|
||||
output += '### Atmosfera\n\n';
|
||||
output += location.description.atmosphere + '\n\n';
|
||||
}
|
||||
|
||||
// Landmarks
|
||||
if (location.landmarks.length) {
|
||||
output += '### Ważne Miejsca\n\n';
|
||||
location.landmarks.forEach(landmark => {
|
||||
output += `#### ${landmark.name}\n`;
|
||||
output += landmark.description + '\n\n';
|
||||
});
|
||||
}
|
||||
|
||||
// Notable NPCs
|
||||
if (location.notableNPCs.length) {
|
||||
output += '### Ważne Postacie\n\n';
|
||||
location.notableNPCs.forEach(npc => {
|
||||
if (typeof npc === 'string') {
|
||||
output += `• ${npc}\n`;
|
||||
} else {
|
||||
output += `• **${npc.name}** - ${npc.description}\n`;
|
||||
}
|
||||
});
|
||||
output += '\n';
|
||||
}
|
||||
|
||||
// Factions
|
||||
if (location.factions.length) {
|
||||
output += '### Frakcje\n\n';
|
||||
location.factions.forEach(faction => {
|
||||
output += `#### ${faction.name}\n`;
|
||||
output += faction.description + '\n';
|
||||
if (faction.goals) output += `*Cele: ${faction.goals}*\n`;
|
||||
output += '\n';
|
||||
});
|
||||
}
|
||||
|
||||
// History
|
||||
if (location.description.history) {
|
||||
output += '### Historia\n\n';
|
||||
output += location.description.history + '\n\n';
|
||||
}
|
||||
|
||||
// Rumors
|
||||
if (location.rumors.length) {
|
||||
output += '### Plotki\n\n';
|
||||
location.rumors.forEach((rumor, i) => {
|
||||
output += `${i + 1}. ${rumor}\n`;
|
||||
});
|
||||
output += '\n';
|
||||
}
|
||||
|
||||
// Adventure Hooks
|
||||
if (location.hooks.length) {
|
||||
output += '### Zaczepki Przygodowe\n\n';
|
||||
location.hooks.forEach(hook => {
|
||||
output += `• ${hook}\n`;
|
||||
});
|
||||
output += '\n';
|
||||
}
|
||||
|
||||
// Encounters
|
||||
if (location.encounters.length) {
|
||||
output += '### Możliwe Spotkania\n\n';
|
||||
output += '| k20 | Spotkanie |\n';
|
||||
output += '|:---:|:----------|\n';
|
||||
location.encounters.forEach((enc, i) => {
|
||||
output += `| ${i + 1} | ${enc} |\n`;
|
||||
});
|
||||
output += '\n';
|
||||
}
|
||||
|
||||
// Dungeon Rooms
|
||||
if (location.rooms.length) {
|
||||
output += '---\n\n## Pomieszczenia\n\n';
|
||||
location.rooms.forEach(room => {
|
||||
output += `### ${room.number}. ${room.name}\n\n`;
|
||||
output += room.description + '\n';
|
||||
if (room.contents) {
|
||||
output += `\n**Zawartość:** ${room.contents}\n`;
|
||||
}
|
||||
output += '\n';
|
||||
});
|
||||
}
|
||||
|
||||
// GM Secrets
|
||||
if (location.description.secrets) {
|
||||
output += '---\n\n';
|
||||
output += '> **[DLA MG]** ' + location.description.secrets + '\n';
|
||||
}
|
||||
|
||||
return output.trim();
|
||||
}
|
||||
|
||||
export default { locationTemplate, formatLocationForBook };
|
||||
@@ -0,0 +1,155 @@
|
||||
/**
|
||||
* HbM: RPG v3 - NPC Template
|
||||
*/
|
||||
|
||||
export const npcTemplate = {
|
||||
name: '',
|
||||
title: '', // e.g., "The Blacksmith", "High Priest"
|
||||
race: '',
|
||||
gender: '',
|
||||
age: '',
|
||||
occupation: '',
|
||||
location: '',
|
||||
|
||||
// Appearance
|
||||
appearance: {
|
||||
height: '',
|
||||
build: '',
|
||||
hair: '',
|
||||
eyes: '',
|
||||
distinguishing: '', // Scars, tattoos, etc.
|
||||
clothing: '',
|
||||
},
|
||||
|
||||
// Personality
|
||||
personality: {
|
||||
traits: [],
|
||||
ideals: [],
|
||||
bonds: [],
|
||||
flaws: [],
|
||||
mannerisms: '',
|
||||
voice: '', // How they speak
|
||||
},
|
||||
|
||||
// Background
|
||||
background: {
|
||||
history: '',
|
||||
secrets: '',
|
||||
goals: '',
|
||||
fears: '',
|
||||
},
|
||||
|
||||
// Relationships
|
||||
relationships: [], // { name, relation, notes }
|
||||
|
||||
// For combat NPCs
|
||||
statBlock: null, // Reference to creature template if needed
|
||||
|
||||
// Roleplay hooks
|
||||
hooks: [], // Quest hooks, rumors, etc.
|
||||
|
||||
notes: '',
|
||||
};
|
||||
|
||||
export function formatNPCForBook(npc) {
|
||||
let output = `## ${npc.name}`;
|
||||
if (npc.title) output += `, ${npc.title}`;
|
||||
output += '\n\n';
|
||||
|
||||
// Basic info
|
||||
const basicInfo = [npc.race, npc.gender, npc.age, npc.occupation].filter(Boolean);
|
||||
if (basicInfo.length) {
|
||||
output += `*${basicInfo.join(', ')}*\n`;
|
||||
}
|
||||
if (npc.location) {
|
||||
output += `**Lokacja:** ${npc.location}\n`;
|
||||
}
|
||||
output += '\n';
|
||||
|
||||
// Appearance
|
||||
if (npc.appearance.distinguishing || npc.appearance.clothing) {
|
||||
output += '### Wygląd\n\n';
|
||||
const appearanceDetails = [];
|
||||
if (npc.appearance.height) appearanceDetails.push(npc.appearance.height);
|
||||
if (npc.appearance.build) appearanceDetails.push(npc.appearance.build);
|
||||
if (npc.appearance.hair) appearanceDetails.push(`włosy: ${npc.appearance.hair}`);
|
||||
if (npc.appearance.eyes) appearanceDetails.push(`oczy: ${npc.appearance.eyes}`);
|
||||
|
||||
if (appearanceDetails.length) {
|
||||
output += appearanceDetails.join(', ') + '.\n\n';
|
||||
}
|
||||
if (npc.appearance.distinguishing) {
|
||||
output += `**Znaki szczególne:** ${npc.appearance.distinguishing}\n`;
|
||||
}
|
||||
if (npc.appearance.clothing) {
|
||||
output += `**Ubiór:** ${npc.appearance.clothing}\n`;
|
||||
}
|
||||
output += '\n';
|
||||
}
|
||||
|
||||
// Personality
|
||||
output += '### Osobowość\n\n';
|
||||
if (npc.personality.traits.length) {
|
||||
output += `**Cechy:** ${npc.personality.traits.join(', ')}\n`;
|
||||
}
|
||||
if (npc.personality.ideals.length) {
|
||||
output += `**Ideały:** ${npc.personality.ideals.join(', ')}\n`;
|
||||
}
|
||||
if (npc.personality.bonds.length) {
|
||||
output += `**Więzi:** ${npc.personality.bonds.join(', ')}\n`;
|
||||
}
|
||||
if (npc.personality.flaws.length) {
|
||||
output += `**Wady:** ${npc.personality.flaws.join(', ')}\n`;
|
||||
}
|
||||
if (npc.personality.mannerisms) {
|
||||
output += `**Maniery:** ${npc.personality.mannerisms}\n`;
|
||||
}
|
||||
if (npc.personality.voice) {
|
||||
output += `**Głos:** ${npc.personality.voice}\n`;
|
||||
}
|
||||
output += '\n';
|
||||
|
||||
// Background
|
||||
if (npc.background.history || npc.background.goals) {
|
||||
output += '### Historia\n\n';
|
||||
if (npc.background.history) {
|
||||
output += npc.background.history + '\n\n';
|
||||
}
|
||||
if (npc.background.goals) {
|
||||
output += `**Cele:** ${npc.background.goals}\n`;
|
||||
}
|
||||
if (npc.background.fears) {
|
||||
output += `**Lęki:** ${npc.background.fears}\n`;
|
||||
}
|
||||
output += '\n';
|
||||
}
|
||||
|
||||
// Relationships
|
||||
if (npc.relationships.length) {
|
||||
output += '### Relacje\n\n';
|
||||
npc.relationships.forEach(rel => {
|
||||
output += `• **${rel.name}** (${rel.relation})`;
|
||||
if (rel.notes) output += ` - ${rel.notes}`;
|
||||
output += '\n';
|
||||
});
|
||||
output += '\n';
|
||||
}
|
||||
|
||||
// Hooks
|
||||
if (npc.hooks.length) {
|
||||
output += '### Zaczepki Fabularne\n\n';
|
||||
npc.hooks.forEach(hook => {
|
||||
output += `• ${hook}\n`;
|
||||
});
|
||||
output += '\n';
|
||||
}
|
||||
|
||||
// Secrets (for GM)
|
||||
if (npc.background.secrets) {
|
||||
output += '> **[DLA MG]** ' + npc.background.secrets + '\n';
|
||||
}
|
||||
|
||||
return output.trim();
|
||||
}
|
||||
|
||||
export default { npcTemplate, formatNPCForBook };
|
||||
@@ -0,0 +1,68 @@
|
||||
/**
|
||||
* HbM: RPG v3 - Spell Template
|
||||
*/
|
||||
|
||||
export const spellTemplate = {
|
||||
name: '',
|
||||
nameEN: '', // English translation
|
||||
school: '', // Szkoła magii
|
||||
circle: 1, // Krąg (1-9)
|
||||
castingTime: '',
|
||||
range: '',
|
||||
duration: '',
|
||||
components: {
|
||||
verbal: false,
|
||||
somatic: false,
|
||||
material: '',
|
||||
},
|
||||
description: '',
|
||||
higherCircles: '', // Opis dla wyższych kręgów
|
||||
notes: '',
|
||||
};
|
||||
|
||||
export function formatSpellForBook(spell) {
|
||||
const components = [];
|
||||
if (spell.components.verbal) components.push('W');
|
||||
if (spell.components.somatic) components.push('S');
|
||||
if (spell.components.material) components.push(`M (${spell.components.material})`);
|
||||
|
||||
return `### ${spell.name}
|
||||
*${spell.school}, ${spell.circle}. krąg*
|
||||
|
||||
**Czas rzucania:** ${spell.castingTime}
|
||||
**Zasięg:** ${spell.range}
|
||||
**Komponenty:** ${components.join(', ')}
|
||||
**Czas trwania:** ${spell.duration}
|
||||
|
||||
${spell.description}
|
||||
|
||||
${spell.higherCircles ? `**Na wyższych kręgach:** ${spell.higherCircles}` : ''}
|
||||
`.trim();
|
||||
}
|
||||
|
||||
export function parseSpellFromText(text) {
|
||||
// Basic parser for spell text - customize based on your format
|
||||
const spell = { ...spellTemplate };
|
||||
|
||||
const nameMatch = text.match(/^###?\s*(.+)/m);
|
||||
if (nameMatch) spell.name = nameMatch[1].trim();
|
||||
|
||||
const schoolMatch = text.match(/\*([^,]+),\s*(\d+)\.\s*krąg\*/);
|
||||
if (schoolMatch) {
|
||||
spell.school = schoolMatch[1].trim();
|
||||
spell.circle = parseInt(schoolMatch[2]);
|
||||
}
|
||||
|
||||
const castingMatch = text.match(/Czas rzucania:\*?\*?\s*(.+)/i);
|
||||
if (castingMatch) spell.castingTime = castingMatch[1].trim();
|
||||
|
||||
const rangeMatch = text.match(/Zasięg:\*?\*?\s*(.+)/i);
|
||||
if (rangeMatch) spell.range = rangeMatch[1].trim();
|
||||
|
||||
const durationMatch = text.match(/Czas trwania:\*?\*?\s*(.+)/i);
|
||||
if (durationMatch) spell.duration = durationMatch[1].trim();
|
||||
|
||||
return spell;
|
||||
}
|
||||
|
||||
export default { spellTemplate, formatSpellForBook, parseSpellFromText };
|
||||
Reference in New Issue
Block a user