better error handling, added chant command
This commit is contained in:
@ -6,7 +6,7 @@ const { findMessage } = require('@dsabot/findMessage');
|
||||
const { getSpell } = require('@dsabot/getSpell');
|
||||
const { CalculateQuality } = require('@dsabot/CalculateQuality');
|
||||
const { CompareResults } = require('@dsabot/CompareResults');
|
||||
const { CreateResultTable } = require('@dsabot/CreateResultTable');
|
||||
const { CreateResultTable, f } = require('@dsabot/CreateResultTable');
|
||||
module.exports = {
|
||||
name: 'cast',
|
||||
description:
|
||||
@ -15,17 +15,17 @@ module.exports = {
|
||||
' die Berechnung einbezogen.',
|
||||
aliases: ['zaubern'],
|
||||
usage: '<Zaubern> [<-Erschwernis> / <+Erleichterung>]',
|
||||
needs_args: true,
|
||||
needs_args: false,
|
||||
async exec(message, args) {
|
||||
db.find({ user: message.author.tag }, (err, docs) => {
|
||||
if (docs.length === 0) {
|
||||
return message.reply(findMessage('NOENTRY'));
|
||||
}
|
||||
if (!docs[0].character.hasOwnProperty('spells'))
|
||||
return message.reply(findMessage('NO_SPELLS'));
|
||||
if (!isNaN(args[0])) {
|
||||
return message.reply(findMessage('WRONG_ARGUMENTS'));
|
||||
}
|
||||
|
||||
console.log(args[0]);
|
||||
const Spell = getSpell({ Character: docs[0].character, spell_name: args[0] });
|
||||
if (!Spell) {
|
||||
return message.reply(findMessage('SPELL_UNKNOWN'));
|
||||
@ -44,11 +44,14 @@ module.exports = {
|
||||
);
|
||||
const Reply = new Discord.MessageEmbed();
|
||||
Reply.addFields({
|
||||
name: `Du würfelst auf das Talent **${Spell.Name}** (Stufe ${Spell.Level} + ${Bonus})`,
|
||||
name: `Du würfelst auf das Talent **${Spell.Name}** ( Stufe ${Spell.Level} ${
|
||||
Bonus ? `${f(Bonus)} ` : ''
|
||||
})`,
|
||||
value: CreateResultTable({
|
||||
Attributes: Attributes,
|
||||
Throws: DiceThrow,
|
||||
PointsUsed: PointsUsed,
|
||||
Bonus: Bonus,
|
||||
}),
|
||||
inline: false,
|
||||
});
|
||||
@ -69,15 +72,17 @@ module.exports = {
|
||||
} else if (Passed < 3) {
|
||||
Reply.addFields({
|
||||
name: findMessage('TITLE_FAILURE'),
|
||||
value: `${Passed === 0 ? 'Keine Probe' : `nur ${Passed}/3 Proben`} erfolgreich. 😪`,
|
||||
value: `${
|
||||
Passed === 0 ? 'Keine Probe' : `nur ${Passed}/3 Proben`
|
||||
} erfolgreich. 😪`,
|
||||
inline: false,
|
||||
});
|
||||
} else {
|
||||
Reply.addFields({
|
||||
name: findMessage('TITLE_SUCCESS'),
|
||||
value: `Dein verbleibender Bonus: ${PointsRemaining}/${Spell.Level} (QS${CalculateQuality(
|
||||
PointsRemaining
|
||||
)})`,
|
||||
value: `Dein verbleibender Bonus: ${PointsRemaining}/${
|
||||
Spell.Level
|
||||
} (QS${CalculateQuality(PointsRemaining)})`,
|
||||
inline: false,
|
||||
});
|
||||
}
|
||||
|
93
commands/Chant.js
Normal file
93
commands/Chant.js
Normal file
@ -0,0 +1,93 @@
|
||||
const globals = require('../globals');
|
||||
const Discord = require('discord.js');
|
||||
const db = globals.db;
|
||||
const { roll } = require('@dsabot/Roll');
|
||||
const { findMessage } = require('@dsabot/findMessage');
|
||||
const { getChant } = require('@dsabot/getChant');
|
||||
const { CalculateQuality } = require('@dsabot/CalculateQuality');
|
||||
const { CompareResults } = require('@dsabot/CompareResults');
|
||||
const { CreateResultTable, f } = require('@dsabot/CreateResultTable');
|
||||
module.exports = {
|
||||
name: 'chant',
|
||||
description:
|
||||
' Du machst eine Fertigkeitsprobe auf Magietalente.\n' +
|
||||
' Es werden drei Würfel auf deine Eigenschaftswerte geworfen. Deine Boni werden in' +
|
||||
' die Berechnung einbezogen.',
|
||||
aliases: [''],
|
||||
usage: '<Liturgie/Zeremonie> [<-Erschwernis> / <+Erleichterung>]',
|
||||
needs_args: false,
|
||||
async exec(message, args) {
|
||||
db.find({ user: message.author.tag }, (err, docs) => {
|
||||
if (docs.length === 0) {
|
||||
return message.reply(findMessage('NOENTRY'));
|
||||
}
|
||||
if (!docs[0].character.hasOwnProperty('chants'))
|
||||
return message.reply(findMessage('NO_CHANTS'));
|
||||
if (!isNaN(args[0])) {
|
||||
return message.reply(findMessage('WRONG_ARGUMENTS'));
|
||||
}
|
||||
const Chant = getSpell({ Character: docs[0].character, chant_name: args[0] });
|
||||
if (!Chant) {
|
||||
return message.reply(findMessage('CHANT_UNKNOWN'));
|
||||
}
|
||||
if (!Chant.Level || !Chant.Attributes) {
|
||||
return;
|
||||
}
|
||||
const Attributes = Chant.Attributes;
|
||||
const DiceThrow = roll(3, 20, message.author.tag).dice;
|
||||
const Bonus = parseInt(args[1]) || 0;
|
||||
let { Passed, CriticalHit, Fumbles, PointsUsed, PointsRemaining } = CompareResults(
|
||||
DiceThrow,
|
||||
Attributes.map(attr => attr.Level),
|
||||
Bonus,
|
||||
Chant.Level
|
||||
);
|
||||
const Reply = new Discord.MessageEmbed();
|
||||
Reply.addFields({
|
||||
name: `Du würfelst auf das Talent **${Chant.Name}** ( Stufe ${Chant.Level} ${
|
||||
Bonus ? `${f(Bonus)} ` : ''
|
||||
})`,
|
||||
value: CreateResultTable({
|
||||
Attributes: Attributes,
|
||||
Throws: DiceThrow,
|
||||
PointsUsed: PointsUsed,
|
||||
Bonus: Bonus,
|
||||
}),
|
||||
inline: false,
|
||||
});
|
||||
if (Fumbles >= 2) {
|
||||
Reply.setColor('#900c3f');
|
||||
Reply.addFields({
|
||||
name: findMessage('TITLE_CRIT_FAILURE'),
|
||||
value: findMessage('MSG_CRIT_FAILURE'),
|
||||
inline: false,
|
||||
});
|
||||
} else if (CriticalHit >= 2) {
|
||||
Reply.setColor('#1E8449');
|
||||
Reply.addFields({
|
||||
name: findMessage('TITLE_CRIT_SUCCESS'),
|
||||
value: findMessage('MSG_CRIT_SUCCESS'),
|
||||
inline: false,
|
||||
});
|
||||
} else if (Passed < 3) {
|
||||
Reply.addFields({
|
||||
name: findMessage('TITLE_FAILURE'),
|
||||
value: `${
|
||||
Passed === 0 ? 'Keine Probe' : `nur ${Passed}/3 Proben`
|
||||
} erfolgreich. 😪`,
|
||||
inline: false,
|
||||
});
|
||||
} else {
|
||||
Reply.addFields({
|
||||
name: findMessage('TITLE_SUCCESS'),
|
||||
value: `Dein verbleibender Bonus: ${PointsRemaining}/${
|
||||
Chant.Level
|
||||
} (QS${CalculateQuality(PointsRemaining)})`,
|
||||
inline: false,
|
||||
});
|
||||
}
|
||||
|
||||
message.reply(Reply);
|
||||
});
|
||||
},
|
||||
};
|
@ -6,9 +6,9 @@ const { getChant } = require('@dsabot/getChant');
|
||||
module.exports = {
|
||||
name: 'chants',
|
||||
description: 'Zeigt dir deinen Fertigkeitswert im jeweiligen Magietalent (Götterwirken).',
|
||||
aliases: ['chant', 'segen', 'liturgie'],
|
||||
usage: '<Zauber>',
|
||||
needs_args: true,
|
||||
aliases: ['segen', 'liturgie', 'liturgien', 'zeremonien'],
|
||||
usage: '[<Liturgie / Zeremonie>]',
|
||||
needs_args: false,
|
||||
|
||||
async exec(message, args) {
|
||||
console.log(message.author.tag);
|
||||
@ -17,6 +17,7 @@ module.exports = {
|
||||
return message.reply(findMessage('NOENTRY'));
|
||||
}
|
||||
Character = docs[0].character;
|
||||
if (!Character.hasOwnProperty('chants')) return message.reply(findMessage('NO_CHANTS'));
|
||||
if (args.length === 0) {
|
||||
return message.reply(ReplyChantList(createChantList(Character))); //?+
|
||||
}
|
||||
@ -37,18 +38,22 @@ const createChantList = (Character = {}) => {
|
||||
let ChantList = [];
|
||||
|
||||
// todo: send 'chant' to getChant() so we can filter out blessings.
|
||||
Character.chants.forEach(chant => ChantList.push(getChant({ Character: Character, chant_name: chant.id })));
|
||||
Character.chants.forEach(chant =>
|
||||
ChantList.push(getChant({ Character: Character, chant_name: chant.id }))
|
||||
);
|
||||
return ChantList.filter(value => value !== undefined); //?+
|
||||
};
|
||||
|
||||
const ReplyChantList = (ChantList = []) => {
|
||||
if (!ChantList) return;
|
||||
return `${ChantList.map(chant => `${chant.name} ${chant.level ? `(${chant.level})` : ''}`).join('\n')}`;
|
||||
return `${ChantList.map(chant => `${chant.Name} ${chant.Level ? `(${chant.Level})` : ''}`).join(
|
||||
'\n'
|
||||
)}`;
|
||||
};
|
||||
|
||||
const ReplyChant = (Chant = {}) => {
|
||||
if (!Chant) return;
|
||||
return `Deine Werte für ${Chant.name} ${Chant.level ? '(' + Chant.level + ')' : ''} sind:
|
||||
return `Deine Werte für ${Chant.Name} ${Chant.Level ? '(' + Chant.Level + ')' : ''} sind:
|
||||
|
||||
${Chant.Attributes.map(attribute => `${attribute.Name}: ${attribute.Level}`).join(' ')}
|
||||
`;
|
||||
|
@ -16,6 +16,7 @@ module.exports = {
|
||||
return message.reply(findMessage('NOENTRY'));
|
||||
}
|
||||
Character = docs[0].character;
|
||||
if (!Character.hasOwnProperty('spells')) return message.reply(findMessage('NO_SPELLS'));
|
||||
if (args.length === 0) {
|
||||
return message.reply(ReplySpellList(createSpellList(Character)));
|
||||
}
|
||||
@ -45,7 +46,9 @@ const ReplySpell = (Spell = {}) => {
|
||||
const createSpellList = (Character = {}) => {
|
||||
if (!Character || !Character.hasOwnProperty('spells')) return;
|
||||
let SpellList = [];
|
||||
Character.spells.forEach(spell => SpellList.push(getSpell({ Character: Character, spell_name: spell.id })));
|
||||
Character.spells.forEach(spell =>
|
||||
SpellList.push(getSpell({ Character: Character, spell_name: spell.id }))
|
||||
);
|
||||
return SpellList.filter(value => value !== undefined); //?+
|
||||
};
|
||||
/*
|
||||
|
@ -473,4 +473,88 @@ module.exports = [
|
||||
},
|
||||
chant: { duration: { amount: 2, unit: 'Aktion' }, type: 'Chant', property: '' },
|
||||
},
|
||||
{
|
||||
id: 'ackersegen',
|
||||
name: 'Ackersegen',
|
||||
attributes: ['MU', 'KL', 'IN'],
|
||||
cost: { initial: 16, additional: {} },
|
||||
effect: {
|
||||
description:
|
||||
'Der Geweihte wandert über das frisch gesäte Feld und segnet die Ackerfrüchte. Die Wirkung des Segens entfaltet sich auf einer Fläche von bis zu QS x 1.000 Quadratschritt (der Geweihte darf vom Zentrum des betroffenen Gebietes aber nicht weiter weg sein, als die Reichweite der Liturgie beträgt). Die Ackerfrucht ist weniger anfällig gegen Krankheiten und Ungeziefer, während alle anderen Pflanzen auf dem Acker in ihrem Wachstum gehemmt werden. Der Segen schützt die Pflanzen jedoch nicht vor äußeren Einflüssen wie Dürre, Überflutung oder Hagelschlag.',
|
||||
duration: { amount: 1, modifier: null, unit: 'Wachstumszyklus (6-12Mo)' },
|
||||
instant: false,
|
||||
pulse: false,
|
||||
},
|
||||
chant: { duration: { amount: 1, unit: 'Stunden' }, type: 'Ceremonie', property: '' },
|
||||
},
|
||||
{
|
||||
id: 'exorzismus',
|
||||
name: 'Exorzismus',
|
||||
attributes: ['MU', 'IN', 'CH'],
|
||||
cost: { initial: 32, additional: {} },
|
||||
effect: {
|
||||
description:
|
||||
'Mit einem Exorzismus werden Dämonen und Geister ausgetrieben, die Besitz von einem Lebewesen ergriffen haben. Gelingt der Exorzismus, wird der Dämon oder Geist aus dem Körper vertrieben und zurück in die Niederhöllen oder ins Totenreich verbannt.',
|
||||
duration: {},
|
||||
instant: true,
|
||||
pulse: false,
|
||||
},
|
||||
chant: { duration: { amount: 8, unit: 'Stunden' }, type: 'Ceremonie', property: '' },
|
||||
},
|
||||
{
|
||||
id: 'geweihterpanzer',
|
||||
name: 'Geweihter Panzer',
|
||||
attributes: ['MU', 'IN', 'CH'],
|
||||
cost: { initial: 16, additional: {} },
|
||||
effect: {
|
||||
description:
|
||||
'Die Rüstung des Geweihten gilt als geweiht. Wenn Dämonen den Geweihten angreifen, verursachen erfolgreiche Angriffe des Dämons 1W3 SP bei ihm, da er den Geweihten oder seine Rüstung berühren muss.',
|
||||
duration: { amount: 15, modifier: 'QS', unit: 'Minuten' },
|
||||
instant: false,
|
||||
pulse: false,
|
||||
},
|
||||
chant: { duration: { amount: 30, unit: 'Minuten' }, type: 'Ceremonie', property: '' },
|
||||
},
|
||||
{
|
||||
id: 'loewengestalt',
|
||||
name: 'Löwengestalt',
|
||||
attributes: ['MU', 'KL', 'IN'],
|
||||
cost: { initial: 16, additional: {} },
|
||||
effect: {
|
||||
description:
|
||||
'Der Geweihte verwandelt sich in einen Löwen. Hierbei wird die Kleidung nicht mitverwandelt. In der Löwengestalt behält der Geweihte seine geistigen Eigenschaften und erhält die körperlichen Eigenschaften und Fähigkeiten des Löwen. Zudem kann er QS x 2 Punkte zusätzlich auf die körperlichen Eigenschaften des Löwen verteilen. In der Löwengestalt kann er keine übernatürlichen Fähigkeiten wie Zauber und Liturgien wirken. In Löwengestalt gilt der Geweihte als gesegnet.',
|
||||
duration: { amount: 3, modifier: 'QS', unit: 'Stunden' },
|
||||
instant: false,
|
||||
pulse: false,
|
||||
},
|
||||
chant: { duration: { amount: 30, unit: 'Minuten' }, type: 'Ceremonie', property: '' },
|
||||
},
|
||||
{
|
||||
id: 'nebelleib',
|
||||
name: 'Nebelleib',
|
||||
attributes: ['KL', 'IN', 'CH'],
|
||||
cost: { initial: 16, additional: {} },
|
||||
effect: {
|
||||
description:
|
||||
'Der Körper des Phexgeweihten verwandelt sich in Nebel. Seine Kleidung und Gegenstände, die er am Körper trug, werden nicht mitverwandelt. Profane, magische und geweihte Waffen richten gegen den Nebel keinen Schaden an. Zauber mit dem Merkmal Verwandlung können nicht gegen den Nebel eingesetzt werden. Der Geweihte kann sich bei relativer Windstille mit GS 4 willentlich fortbewegen; bei leichtem Gegenwind muss er eine Probe auf Willenskraft bestehen, um nicht abgetrieben zu werden; bei starkem Gegenwind wird er aber in Windrichtung davongeblasen, ohne sich dagegen wehren zu können. Der Geweihte kann seine Umgebung mit allen fünf Sinnen wahrnehmen. Der Geweihte bleibt so lange ein Nebel, bis die Wirkungsdauer vorüber ist.',
|
||||
duration: { amount: 10, modifier: 'QS', unit: 'Minuten' },
|
||||
instant: false,
|
||||
pulse: false,
|
||||
},
|
||||
chant: { duration: { amount: 30, unit: 'Minuten' }, type: 'Ceremonie', property: '' },
|
||||
},
|
||||
{
|
||||
id: 'objektweihe',
|
||||
name: 'Objektweihe',
|
||||
attributes: ['KL', 'IN', 'CH'],
|
||||
cost: { initial: 16, additional: {} },
|
||||
effect: {
|
||||
description:
|
||||
'Das Objekt, üblicherweise ein liturgischer Gegenstand oder eine rituelle Waffe wie ein Sonnenzepter oder ein Rondrakamm, wird geweiht. Damit wird es von den karmalen Kräften der jeweiligen Gottheit durchdrungen, weswegen üblicherweise nur ausgewählte, der Gottheit gefällige Gegenstände geweiht und nur wahren Gläubigen ausgehändigt werden. Sollte das geweihte Objekt eine Waffe sein, gilt sie nun als geweihte Waffe. Das Objekt darf maximal 4 Stein wiegen. Für jede QS kann das Objekt 1 Stein mehr wiegen. Die Objektweihe wird vor allem für die geweihten Rabenschnäbel der Borongeweihten, das Sonnenzepter der Praioten und die Rondrakämme der Rondrageweihtenschaft verwendet. (Für die Herstellung von Zeremonialgegenständen ist allerdings noch die SF "Zeremonialgegenstände herstellen" notwendig.)',
|
||||
duration: {},
|
||||
instant: true,
|
||||
pulse: false,
|
||||
},
|
||||
chant: { duration: { amount: 2, unit: 'Stunden' }, type: 'Ceremonie', property: '' },
|
||||
},
|
||||
];
|
||||
|
1
data/Chants.json
Normal file
1
data/Chants.json
Normal file
File diff suppressed because one or more lines are too long
1
data/Spells.json
Normal file
1
data/Spells.json
Normal file
File diff suppressed because one or more lines are too long
@ -1,12 +1,19 @@
|
||||
const CreateResultTable = ({ Attributes: Attributes, Throws: Throws, PointsUsed: PointsUsed, Bonus: Bonus = 0 }) => {
|
||||
const CreateResultTable = ({
|
||||
Attributes: Attributes,
|
||||
Throws: Throws,
|
||||
PointsUsed: PointsUsed,
|
||||
Bonus: Bonus = 0,
|
||||
}) => {
|
||||
return `
|
||||
\`\`\`
|
||||
${''.padEnd(15)} ${Attributes.map(attr => `${attr.Name}`.padStart(6)).join('\t|\t')}\t|
|
||||
${'Dein Wert'.padEnd(15)} ${Attributes.map(attr => `${attr.Level}${Bonus ? `(${f(Bonus)})` : ``}`.padStart(6)).join(
|
||||
${'Dein Wert'.padEnd(15)} ${Attributes.map(attr =>
|
||||
`${attr.Level}${Bonus ? `(${f(Bonus)})` : ``}`.padStart(6)
|
||||
).join('\t|\t')}\t|
|
||||
${'Dein Wurf'.padEnd(15)} ${Throws.map(Throw => `${Throw}`.padStart(6)).join('\t|\t')}\t|
|
||||
${'Abzüge'.padEnd(15)} ${PointsUsed.map(Points => `${Points}`.replace(0, '--').padStart(6)).join(
|
||||
'\t|\t'
|
||||
)}\t|
|
||||
${'Dein Wurf'.padEnd(15)} ${Throws.map(Throw => `${Throw}`.padStart(6)).join('\t|\t')}\t|
|
||||
${'Abzüge'.padEnd(15)} ${PointsUsed.map(Points => `${Points}`.replace(0, '--').padStart(6)).join('\t|\t')}\t|
|
||||
${'Gesamt'.padEnd(15)} ${PointsUsed.reduce((acc, cur) => acc + cur)
|
||||
.toString()
|
||||
.padStart(6)}
|
||||
@ -18,4 +25,4 @@ const f = n => {
|
||||
return (n > 0 ? '+' : '') + n;
|
||||
};
|
||||
|
||||
module.exports = { CreateResultTable };
|
||||
module.exports = { CreateResultTable, f };
|
||||
|
@ -1,6 +1,6 @@
|
||||
const { getAttributeLevels } = require('@dsabot/getAttributeLevels');
|
||||
const Chants = require('../data/Chants.json');
|
||||
|
||||
const Chants = require('../data/Chants');
|
||||
const getChant = ({ Character: Character = [], chant_name: chant_name = '' } = {}) => {
|
||||
let chant_entry =
|
||||
Chants.find(chant => chant.id.toLowerCase() === chant_name.toLowerCase()) ||
|
||||
@ -10,13 +10,13 @@ const getChant = ({ Character: Character = [], chant_name: chant_name = '' } = {
|
||||
console.log(`getChant() Did not find entry for ${chant_name}`);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!Character.hasOwnProperty('chants')) return;
|
||||
let Level = 0; // This is the minimum attributes value.
|
||||
let Chant = Character.chants.find(chant => chant.id === chant_entry.id) || {};
|
||||
if (Chant && Chant.hasOwnProperty('level')) {
|
||||
Level = Chant.level || 0;
|
||||
}
|
||||
|
||||
console.log(chant_entry);
|
||||
let Attributes = getAttributeLevels(chant_entry.attributes, Character);
|
||||
|
||||
return {
|
||||
|
@ -1,22 +1,5 @@
|
||||
const { getAttributeLevels } = require('@dsabot/getAttributeLevels');
|
||||
const Spells = require('../data/Spells');
|
||||
/* definition of attributes in spell database
|
||||
|
||||
{
|
||||
id: 'adlerauge', // the id of the spell inside characters database.
|
||||
name: 'Adlerauge', // the well-known name of the spell.
|
||||
attributes: [ 'KL', 'IN', 'FF' ], // needed attribute checks when casting the spell
|
||||
spellduration: 2, // the player needs this many actions to cast the spell.
|
||||
modified_by: [], // the spell is modified by this character's attribute
|
||||
cost: null, // how many units does the spell cost? (when activated)
|
||||
cost_type: 'asp', // what kind of points does the character need?
|
||||
// AsP = Astral Points, KaP = Karmal Points
|
||||
effect: '', // What is the desired effect of this spell?
|
||||
effectduration: '' // How long does the effect last?
|
||||
talent: null //
|
||||
},
|
||||
|
||||
*/
|
||||
const Spells = require('../data/Spells.json');
|
||||
|
||||
const getSpell = ({ Character: Character = [], spell_name: spell_name = '' } = {}) => {
|
||||
const spell_entry =
|
||||
@ -24,11 +7,12 @@ const getSpell = ({ Character: Character = [], spell_name: spell_name = '' } = {
|
||||
Spells.find(spell => spell.name.toLowerCase() === spell_name.toLowerCase());
|
||||
|
||||
if (!spell_entry) {
|
||||
console.log(`getSpell did not find entry for ${spell_name}`);
|
||||
console.log(`getSpell() did not find entry for ${spell_name}`);
|
||||
return;
|
||||
}
|
||||
|
||||
let Level = 0; // This is the minimum attributes value.
|
||||
if (!Character.hasOwnProperty('spells')) return;
|
||||
let Spell = Character.spells.find(spell => spell.id === spell_entry.id) || {}; //?+
|
||||
if (Spell && Spell.hasOwnProperty('level')) {
|
||||
Level = Spell.level || 0;
|
||||
|
@ -141,7 +141,8 @@ const Replies = [
|
||||
{ id: 'ROLL', string: 'Du würfelst:'},
|
||||
{ id: 'HEADS_OR_TAILS', string: 'Die Münze landet auf ' },
|
||||
{ id: 'SPELL_UNKNOWN', string: 'Diesen Zauber kenne ich nicht.' },
|
||||
{ id: 'NO_SPELLS', string: 'Du kennst keine Zaubersprüche.'}
|
||||
{ id: 'NO_SPELLS', string: 'Du kennst keine Zaubersprüche.'},
|
||||
{ id: 'NO_CHANTS', string: 'Du kennst keine Liturgien.'}
|
||||
];
|
||||
const Declination = ['dem', 'der', 'dem', '']; // Maskulinum, Feminimum, Neutrum, None
|
||||
const Articles = ['Der','Die','Das',''];
|
||||
|
Reference in New Issue
Block a user