diff --git a/.gitignore b/.gitignore index 81c5986..ae73ac5 100644 --- a/.gitignore +++ b/.gitignore @@ -1,10 +1,15 @@ -node_modules +/node_modules/ .env .eslintrc.js .eslintrc.json -.vscode -.github -data/dsabot.db -data/dsabot.db~ -data +.jshint +.prettierrc +/.vscode/ +/.github/ +.DS_Store +Thumbs.db +/data/dsabot.db +!/data/*.js +!/data/*.json +/private diff --git a/.jshintrc b/.jshintrc new file mode 100644 index 0000000..ebc4f87 --- /dev/null +++ b/.jshintrc @@ -0,0 +1,3 @@ +{ + "esversion": 9 + } \ No newline at end of file diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..47bec69 --- /dev/null +++ b/.prettierrc @@ -0,0 +1,19 @@ +{ + "arrowParens": "avoid", + "bracketSpacing": true, + "embeddedLanguageFormatting": "auto", + "htmlWhitespaceSensitivity": "css", + "insertPragma": false, + "jsxBracketSameLine": true, + "jsxSingleQuote": true, + "printWidth": 100, + "proseWrap": "preserve", + "quoteProps": "as-needed", + "requirePragma": false, + "semi": true, + "singleQuote": true, + "tabWidth": 4, + "trailingComma": "es5", + "useTabs": false, + "vueIndentScriptAndStyle": false + } \ No newline at end of file diff --git a/README.md b/README.md index 98fcb74..17a817d 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,5 @@ [![CodeQL](https://github.com/TobenderZephyr/dsabot/actions/workflows/codeql-analysis.yml/badge.svg)](https://github.com/TobenderZephyr/dsabot/actions/workflows/codeql-analysis.yml) + # DSA Discord Bot This Project is a fork of LucaSchwan/dsa-bot. @@ -10,37 +11,44 @@ It can roll dice and even compare results with your characters attributes. # Commands ### !help + Send the user a simple command list with things to do. ## Dice Rolling -### !roll *x* W/D *y* +### !roll _x_ W/D _y_ -This command can be used to roll dice. To use it one has to put in the number of dice to use as the *x* and the number of sides as the *y* in between those Numbers stands W/D which simply means dice(D) or the german word "Würfel" (W). Theoretically it doesn't matter what Letter is in between but for roleplay gamers this should feel natural. +This command can be used to roll dice. To use it one has to put in the number of dice to use as the _x_ and the number of sides as the _y_ in between those Numbers stands W/D which simply means dice(D) or the german word "Würfel" (W). Theoretically it doesn't matter what Letter is in between but for roleplay gamers this should feel natural. ie `!roll 3w20` ### !heads + Throw a coin. Heads or Tails? ## Tracking System + As this Bot should help with tracking your character, simply attach your .tdc file in a private message. ### !ep / !ap [Value] + Probes on your attributes. Rolls 1 die and compares it with the given value. Rolls another, if returned number is 1 or 20. ie `!ep 11` ### !ep / !ap [Attribute or Abbreviation] + Does the same as above. You don't need to remember your stats (if you sent a `tdc`-File, that is.) ie. `!ep Mut` or `!ep KK` ### !skill [skillname] + Returns the current level of the desired skill. ### !attack [weaponname] ([-Disadvantages/+Advantages]) + Rolls an attack by using the weapon based skillset. Calculates your combat technique value and takes into account for `MU` or `FF`. `caution`: It does not yet make use of any benefits or disadvantages your character possesses. @@ -49,19 +57,24 @@ ie. `!attack Waqqif` For a list of weapons to chose from, use `!weapons` ### !talent [skillname] ([-Disadvantages/+Advantages]) + Rolls 3 dice and compares the results of each with your current level of character attributes including your bonus on that particular skill. `caution`: It does not yet make use of any benefits or disadvantages your character has (at the moment). ie. `!talent klettern -2` + ``` @TobenderZephyr, Du würfelst auf das Talent Klettern. Deine Werte für MU, GE, KK sind 12, 13, 12. (Bonus: 6) Das waren deine 🎲: 1, 16, 2. Damit hast du 3/3 Proben bestanden. Dein Bonus: 3/6. ``` + ### !talents + Sends the User a list of talents to use on the `!talent` command. ### !tp [attribute1] [attribute2] [attribute3] ([bonus] [-Disadvantage/+Advantages]) + This command also rolls 3 dice and compares their values with entered arguments. This one is better suited for people, who did not provide a `.tdc`-File or if one of the other numerous Advantages and/or Disadvantages need to be taken into account. @@ -74,9 +87,35 @@ Roll with a set Bonus of 4: Roll with a Benefit given by the GM: `!tp 11 10 11 0 +2` +### !spells [spell] + +This command returns a list of spells known to you. This differs from `!talents` because there would be many more additions to certain +spells through rule books. +If you define a spell by not leaving arguments empty, it will display your current level and checks on your stats. + +### !chants [chant] + +See `!spells`. This uses karma point talents. + +### !cast [spell] ([-Disadvantages/+Advantages]) + +Rolls 3 dice and compares the results of each with your current level of character attributes including your bonus on that particular spell. +`caution`: It does not yet make use of any benefits or disadvantages your character has (at the moment). + +ie. `!cast fulminictus +1` + +### !chant [chant] ([-Disadvantages/+Advantages]) + +See `!cast`. This uses karma point talents. + +ie. `!chant Lautlos +1` + # How to use + To connect the script to a Bot, you need to create a Bot using the Discord Developer Portal. To do this you can follow a guide like [this](https://discordpy.readthedocs.io/en/latest/discord.html). + ## Docker + Just pull the docker image and you are good to go. `docker pull tobenderzephyr/dsabot:latest` @@ -85,12 +124,14 @@ The container needs at least the following Environment variables: `BOT_TOKEN`: The token which you retrieve for your bot Discord Developer Portal `CMDPREFIX`: Instead of using `!` as your prefix, you may want to use your own. -You may run the container with `docker run -rm -v ./data:/usr/src/app/data -e BOT_TOKEN=[token] -e CMDPREFIX=! tobenderzephyr/dsabot:latest` +You may run the container with `docker run -rm -v ./data:/usr/src/app/data/ -e BOT_TOKEN=[token] -e CMDPREFIX=! tobenderzephyr/dsabot:latest` The database is stored under `./data`, so you are good to just mount this as a volume as seen in the example above. ### docker-compose + You may aswell use a simple `docker-compose.yml` and use docker-compose for easy running the app: + ``` version: "3" services: @@ -102,7 +143,7 @@ services: BOT_TOKEN: CMDPREFIX: ! volumes: - - ./data:/usr/src/app/data + - ./data/:/usr/src/app/data/ ``` ## manual setup @@ -114,12 +155,10 @@ Then you need to run the following code inside of a terminal while beeing in the `npm install` Rename `.sample.env` file to `.env` -Enter the token you received on the Discord Developer Portal into the variable BOT_TOKEN inside `.env`. - +Enter the token you received on the Discord Developer Portal into the variable BOT_TOKEN inside `.env`. When you joined your Bot to your desired channel all you need to enter inside the bots directory: `npm start` Then your Bot should run and be working in your channel. - diff --git a/commands/Cast.js b/commands/Cast.js new file mode 100644 index 0000000..c72d58b --- /dev/null +++ b/commands/Cast.js @@ -0,0 +1,90 @@ +const globals = require('../globals'); +const Discord = require('discord.js'); +const db = globals.db; +const { roll } = require('@dsabot/Roll'); +const { findMessage } = require('@dsabot/findMessage'); +const { getSpell } = require('@dsabot/getSpell'); +const { CalculateQuality } = require('@dsabot/CalculateQuality'); +const { CompareResults } = require('@dsabot/CompareResults'); +const { CreateResultTable, f } = require('@dsabot/CreateResultTable'); +module.exports = { + name: 'cast', + 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: ['zaubern'], + usage: ' [<-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('spells')) return message.reply(findMessage('NO_SPELLS')); + if (!isNaN(args[0])) { + return message.reply(findMessage('WRONG_ARGUMENTS')); + } + const Spell = getSpell({ Character: docs[0].character, spell_name: args[0] }); + if (!Spell) { + return message.reply(findMessage('SPELL_UNKNOWN')); + } + if (!Spell.Level || !Spell.Attributes) { + return; + } + const Attributes = Spell.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, + Spell.Level + ); + const Reply = new Discord.MessageEmbed(); + Reply.addFields({ + name: `Du würfelst auf den Zauber **${Spell.Name}** ( Stufe ${Spell.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}/${Spell.Level} (QS${CalculateQuality( + PointsRemaining + )})`, + inline: false, + }); + } + + message.reply(Reply); + }); + }, +}; diff --git a/commands/Chant.js b/commands/Chant.js new file mode 100644 index 0000000..bca7ce3 --- /dev/null +++ b/commands/Chant.js @@ -0,0 +1,89 @@ +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: ' [<-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 = getChant({ 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 die Liturgie **${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); + }); + }, +}; diff --git a/commands/Chants.js b/commands/Chants.js new file mode 100644 index 0000000..de46f37 --- /dev/null +++ b/commands/Chants.js @@ -0,0 +1,61 @@ +//const globals = require('../globals'); +const globals = require('../globals'); +const Discord = require('discord.js'); +const db = globals.db; +const { findMessage } = require('@dsabot/findMessage'); +const { getChant } = require('@dsabot/getChant'); +module.exports = { + name: 'chants', + description: 'Zeigt dir deinen Fertigkeitswert im jeweiligen Magietalent (Götterwirken).', + aliases: ['segen', 'liturgie', 'liturgien', 'zeremonien'], + usage: '[]', + needs_args: false, + + async exec(message, args) { + db.find({ user: message.author.tag }, (err, docs) => { + if (docs.length === 0) { + return message.reply(findMessage('NOENTRY')); + } + Character = docs[0].character; + if (!Character.hasOwnProperty('chants')) return message.reply(findMessage('NO_CHANTS')); + if (args.length === 0) { + const Embed = new Discord.MessageEmbed() + .setColor('#0099ff') + .setTitle(findMessage('CHANTS_TITLE')) + .setDescription(findMessage('CHANTS_DESCRIPTION')) + .addField(ReplyChantList(createChantList(Character)), '\u200B', true); + return message.reply(Embed); + } + const Chant = getChant({ + Character: Character, + chant_name: args[0], + }); + if (!Chant) { + return message.reply(findMessage('SPELL_UNKNOWN')); + } + return message.reply(ReplyChant(Chant)); + }); + }, +}; + +const createChantList = (Character = {}) => { + if (!Character || !Character.hasOwnProperty('chants')) return; + 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 }))); + return ChantList.filter(value => value !== undefined); +}; + +const ReplyChantList = (ChantList = []) => { + if (!ChantList) return; + 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: + + ${Chant.Attributes.map(attribute => `${attribute.Name}: ${attribute.Level}`).join(' ')} + `; +}; diff --git a/commands/Skill.js b/commands/Skill.js index f8f623e..d0f3f44 100644 --- a/commands/Skill.js +++ b/commands/Skill.js @@ -1,31 +1,24 @@ const globals = require('../globals'); const db = globals.db; -const { findMessage }= require('@dsabot/findMessage'); +const { findMessage } = require('@dsabot/findMessage'); const { getSkill } = require('@dsabot/getSkill'); module.exports = { - name: 'skill', - description: 'Zeigt dir deinen Fertigkeitswert im jeweiligen Talent.', - aliases: [], - usage: '', - needs_args: true, + name: 'skill', + description: 'Zeigt dir deinen Fertigkeitswert im jeweiligen Talent.', + aliases: [], + usage: '', + needs_args: true, - async exec(message, args) { - try { - db.find({ - user: message.author.tag, - }, function(err, docs) { - if (docs.length === 0) { - return message.reply(findMessage('NOENTRY')); - } - else { - const Skill = getSkill({Character: docs[0].character, args: args}); - if(!Skill) { return message.reply(findMessage('TALENT_UNKNOWN'));} - return message.reply(`Du hast folgenden Wert in **${Skill.Name}**: ${Skill.Level}`) - } - }); - } - catch (e) { - throw e; - } - }, -}; \ No newline at end of file + async exec(message, args) { + db.find({ user: message.author.tag }, (err, docs) => { + if (docs.length === 0) { + return message.reply(findMessage('NOENTRY')); + } + const Skill = getSkill({ Character: docs[0].character, args: args }); + if (!Skill) { + return message.reply(findMessage('TALENT_UNKNOWN')); + } + return message.reply(`Du hast folgenden Wert in **${Skill.Name}**: ${Skill.Level}`); + }); + }, +}; diff --git a/commands/Spells.js b/commands/Spells.js new file mode 100644 index 0000000..2e810bc --- /dev/null +++ b/commands/Spells.js @@ -0,0 +1,57 @@ +//const globals = require('../globals'); +const globals = require('../globals'); +const db = globals.db; +const Discord = require('discord.js'); +const { findMessage } = require('@dsabot/findMessage'); +const { getSpell } = require('@dsabot/getSpell'); +module.exports = { + name: 'spells', + description: 'Zeigt dir deinen Fertigkeitswert im jeweiligen Magietalent.', + aliases: ['spell', 'zauber'], + usage: '', + needs_args: false, + + async exec(message, args) { + db.find({ user: message.author.tag }, (err, docs) => { + if (docs.length === 0) { + return message.reply(findMessage('NOENTRY')); + } + Character = docs[0].character; + if (!Character.hasOwnProperty('spells')) return message.reply(findMessage('NO_SPELLS')); + if (args.length === 0) { + const Embed = new Discord.MessageEmbed() + .setColor('#0099ff') + .setTitle(findMessage('SPELLS_TITLE')) + .setDescription(findMessage('SPELLS_DESCRIPTION')) + .addField(ReplySpellList(createSpellList(Character)), '\u200B', true); + return message.reply(Embed); + } + const Spell = getSpell({ + Character: Character, + spell_name: args[0], + }); + if (!Spell) return message.reply(findMessage('SPELL_UNKNOWN')); + return message.reply(ReplySpell(Spell)); + }); + }, +}; + +const ReplySpellList = (SpellList = []) => { + if (!SpellList) return findMessage('NO_SPELLS'); + return `${SpellList.map(s => `${s.Name} (${s.Level})`).join('\n')}`; +}; + +const ReplySpell = (Spell = {}) => { + if (!Spell) return; + return `Deine Werte für ${Spell.Name} (${Spell.Level}) sind: + + ${Spell.Attributes.map(attribute => `${attribute.Name}: ${attribute.Level}`).join(' ')} + `; +}; + +const createSpellList = (Character = {}) => { + if (!Character || !Character.hasOwnProperty('spells')) return; + let SpellList = []; + Character.spells.forEach(spell => SpellList.push(getSpell({ Character: Character, spell_name: spell.id }))); + return SpellList.filter(value => value !== undefined); //?+ +}; diff --git a/commands/Talent.js b/commands/Talent.js index 220c76a..3467ea3 100644 --- a/commands/Talent.js +++ b/commands/Talent.js @@ -1,101 +1,85 @@ const globals = require('../globals'); const Discord = require('discord.js'); const db = globals.db; -const { roll } = require('@dsabot/Roll'); -const { findMessage } = require('@dsabot/findMessage'); +const { roll } = require('@dsabot/Roll'); +const { findMessage } = require('@dsabot/findMessage'); const { getSkill } = require('@dsabot/getSkill'); const { CalculateQuality } = require('@dsabot/CalculateQuality'); const { CompareResults } = require('@dsabot/CompareResults'); +const { CreateResultTable } = require('@dsabot/CreateResultTable'); module.exports = { - name: 'talent', - description: ' Du machst eine Fertigkeitsprobe.\n' + - ' Es werden drei Würfel auf deine Eigenschaftswerte geworfen. Hast du Boni auf dein Talent und/oder' + - ' ist der Wurf erleichtert oder erschwert, wird dies in die Berechnung einbezogen.', - aliases: ['t'], - usage: ' [<-Erschwernis> / <+Erleichterung>]', - needs_args: true, - async exec(message, args) { - try { - db.find({ - user: message.author.tag, - }, function (err, docs) { - if (docs.length === 0) { - return message.reply(findMessage('NOENTRY')); - } - if (!isNaN(args[0])) { - return message.reply(findMessage('WRONG_ARGUMENTS')); - } else { - - const Skill = getSkill({Character: docs[0].character, args: args}); - if(!Skill) { return message.reply(findMessage('TALENT_UNKNOWN'));} - - const Attributes = Skill.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, - Skill.Level); - const Reply = new Discord.MessageEmbed(); - Reply.addFields({ - name: `Du würfelst auf das Talent **${Skill.Name}** (Stufe ${Skill.Level} + ${Bonus})`, - value: CreateTable({Attributes: Attributes, Throws: DiceThrow, PointsUsed: PointsUsed}), - 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}/${Skill.Level} (QS${CalculateQuality(PointsRemaining)})`, - inline: false - }); - } - - message.reply(Reply); - } - }); - } catch (e) { - throw e; - } - }, + name: 'talent', + description: + ' Du machst eine Fertigkeitsprobe.\n' + + ' Es werden drei Würfel auf deine Eigenschaftswerte geworfen. Hast du Boni auf dein Talent und/oder' + + ' ist der Wurf erleichtert oder erschwert, wird dies in die Berechnung einbezogen.', + aliases: ['t'], + usage: ' [<-Erschwernis> / <+Erleichterung>]', + needs_args: true, + async exec(message, args) { + db.find({ user: message.author.tag }, (err, docs) => { + if (docs.length === 0) { + return message.reply(findMessage('NOENTRY')); + } + if (!isNaN(args[0])) { + return message.reply(findMessage('WRONG_ARGUMENTS')); + } + + const Skill = getSkill({ Character: docs[0].character, args: args }); + if (!Skill) { + return message.reply(findMessage('TALENT_UNKNOWN')); + } + + const Attributes = Skill.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, + Skill.Level + ); + const Reply = new Discord.MessageEmbed(); + Reply.addFields({ + name: `Du würfelst auf das Talent **${Skill.Name}** (Stufe ${Skill.Level} + ${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}/${Skill.Level} (QS${CalculateQuality( + PointsRemaining + )})`, + inline: false, + }); + } + message.reply(Reply); + }); + }, }; - -function Pad(Number = 0) { - return Number.toString().padStart(1, ' '); -} - -const CreateTable = ({Attributes: Attributes, Throws: Throws, PointsUsed: PointsUsed}) => { - return ` - \`\`\` - ${' '.padEnd(15)} ${Attributes.map(attr => `${attr.Name}`.padStart(5)).join('\t|\t')}\t| - ${'Dein Wert'.padEnd(15)} ${Attributes.map(attr => `${attr.Level}`.padStart(5)).join('\t|\t')}\t| - ${'Dein Wurf'.padEnd(15)} ${Throws.map(Throw => `${Throw}`.padStart(5)).join('\t|\t')}\t| - ${'Abzüge'.padEnd(15)} ${PointsUsed.map(Points => `${Points}`.replace(0,'--').padStart(5)).join('\t|\t')}\t| - ${'Gesamt'.padEnd(15)} ${PointsUsed.reduce((acc,cur) => acc+cur).toString().padStart(5)} - \`\`\` - `; -}; \ No newline at end of file diff --git a/data/dsabot.db b/data/dsabot.db index 8b13789..e69de29 100644 --- a/data/dsabot.db +++ b/data/dsabot.db @@ -1 +0,0 @@ - diff --git a/functions/CompareResults.js b/functions/CompareResults.js index 578d546..80ead78 100644 --- a/functions/CompareResults.js +++ b/functions/CompareResults.js @@ -1,35 +1,51 @@ -const CompareResults = (Throws = [], AttributeLevels = [8, 8, 8], Bonus = 0, PointsRemaining = 0) => { +/** + * Compares each item inside an array Throws + * with corresponding AttributeLevels (With added bonus) + * + * @param {Array} Throws=[] + * @param {Array} AttributeLevels=[8,8,8] + * @param {BigInt} Bonus=0 + * @param {BigInt} PointsRemaining=0 + */ +const CompareResults = ( + Throws = [], + AttributeLevels = [8, 8, 8], + Bonus = 0, + PointsRemaining = 0 +) => { + let Passed = 0; + let Fumbles = 0; + let CriticalHit = 0; + let AllPointsUsed = []; - let Passed = 0; - let Fumbles = 0; - let CriticalHit = 0; - let AllPointsUsed = []; - - for (let i = 0; i < Throws.length; i++) { - let PointsUsed = 0; - if (Math.floor(AttributeLevels[i] + Bonus) >= Throws[i]) { - Passed++; - } else if (Math.floor(AttributeLevels[i] + PointsRemaining + Bonus) >= Throws[i]) { - Passed++; - PointsUsed = (Throws[i] - Bonus - AttributeLevels[i]); - PointsRemaining -= PointsUsed; - } - else { - // We need to use all our points, so that next die/dice - // would not return a 'Passed'. - PointsUsed = PointsRemaining; - PointsRemaining -= PointsUsed; - } - if (Throws[i] == 1) { CriticalHit++; } - if (Throws[i] == 20) { Fumbles++; } - AllPointsUsed.push(PointsUsed); - } - return { - Passed: Passed, - CriticalHit: CriticalHit, - Fumbles: Fumbles, - PointsUsed: AllPointsUsed, - PointsRemaining: PointsRemaining - }; + for (let i = 0; i < Throws.length; i++) { + let PointsUsed = 0; + if (Math.floor(AttributeLevels[i] + Bonus) >= Throws[i]) { + Passed++; + } else if (Math.floor(AttributeLevels[i] + PointsRemaining + Bonus) >= Throws[i]) { + Passed++; + PointsUsed = Throws[i] - Bonus - AttributeLevels[i]; + PointsRemaining -= PointsUsed; + } else { + // We need to use all our points, so that next die/dice + // would not return a 'Passed'. + PointsUsed = PointsRemaining; + PointsRemaining -= PointsUsed; + } + if (Throws[i] == 1) { + CriticalHit++; + } + if (Throws[i] == 20) { + Fumbles++; + } + AllPointsUsed.push(PointsUsed); + } + return { + Passed: Passed, + CriticalHit: CriticalHit, + Fumbles: Fumbles, + PointsUsed: AllPointsUsed, + PointsRemaining: PointsRemaining, + }; }; module.exports = { CompareResults }; diff --git a/functions/CreateResultTable.js b/functions/CreateResultTable.js new file mode 100644 index 0000000..dce5bc2 --- /dev/null +++ b/functions/CreateResultTable.js @@ -0,0 +1,28 @@ +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('\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)} + \`\`\` + `; +}; + +const f = n => { + return (n > 0 ? '+' : '') + n; +}; + +module.exports = { CreateResultTable, f }; diff --git a/functions/getChant.js b/functions/getChant.js new file mode 100644 index 0000000..fa282dc --- /dev/null +++ b/functions/getChant.js @@ -0,0 +1,28 @@ +const { getAttributeLevels } = require('@dsabot/getAttributeLevels'); +const Chants = require('@Lib/Chants.json'); + +const getChant = ({ Character: Character = [], chant_name: chant_name = '' } = {}) => { + //if (!Character.hasOwnProperty('chants')) return; + let chant_entry = + Chants.find(chant => chant.id.toLowerCase() === chant_name.toLowerCase()) || + Chants.find(chant => chant.name.toLowerCase() === chant_name.toLowerCase()); + + if (!chant_entry) { + console.log(`getChant() Did not find entry for ${chant_name}`); + 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; + } + let Attributes = getAttributeLevels(chant_entry.attributes, Character); + + return { + Name: chant_entry.name, + Level: Level, + Attributes: Attributes, + }; +}; +module.exports = { getChant }; diff --git a/functions/getSkill.js b/functions/getSkill.js index eac6170..20b2ff6 100644 --- a/functions/getSkill.js +++ b/functions/getSkill.js @@ -1,24 +1,27 @@ const globals = require('../globals'); -const { getAttributeLevels } = require("@dsabot/getAttributeLevels"); +const { getAttributeLevels } = require('@dsabot/getAttributeLevels'); const getSkill = ({ Character: Character = [], args: args = [] } = {}) => { - let skill_entry = globals.Talente.find(skill => skill.id.toLowerCase() === args[0].toLowerCase()) || - globals.Talente.find(skill => skill.name.toLowerCase() === args[0].toLowerCase()); + let skill_entry = + globals.Talente.find(skill => skill.id.toLowerCase() === args[0].toLowerCase()) || + globals.Talente.find(skill => skill.name.toLowerCase() === args[0].toLowerCase()); - if (!skill_entry) { return; } + if (!skill_entry) { + return; + } - let Level = 0; // This is the minimum attributes value. - let cSkill = Character.skills.find(skill => skill.id === skill_entry.id) || {}; - if (cSkill) { - Level = cSkill.level || 0; - } - let Name = globals.Talente.find(skill => skill.id === skill_entry.id).name; - let Attributes = getAttributeLevels(skill_entry.values, Character); + let Level = 0; // This is the minimum attributes value. + let cSkill = Character.skills.find(skill => skill.id === skill_entry.id) || {}; + if (cSkill) { + Level = cSkill.level || 0; + } + let Name = globals.Talente.find(skill => skill.id === skill_entry.id).name; + let Attributes = getAttributeLevels(skill_entry.values, Character); - return { - Name: Name, - Level: Level, - Attributes: Attributes - }; + return { + Name: Name, + Level: Level, + Attributes: Attributes, + }; }; module.exports = { getSkill }; diff --git a/functions/getSpell.js b/functions/getSpell.js new file mode 100644 index 0000000..cb71bf4 --- /dev/null +++ b/functions/getSpell.js @@ -0,0 +1,30 @@ +const { getAttributeLevels } = require('@dsabot/getAttributeLevels'); +const Spells = require('@Lib/Spells.json'); + +const getSpell = ({ Character: Character = [], spell_name: spell_name = '' } = {}) => { + const spell_entry = + Spells.find(spell => spell.id.toLowerCase() === spell_name.toLowerCase()) || + Spells.find(spell => spell.name.toLowerCase() === spell_name.toLowerCase()); + + if (!spell_entry) { + 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; + } + let ModifiedBy = spell_entry.modified_by; + let Attributes = getAttributeLevels(spell_entry.attributes, Character); + + return { + Name: spell_entry.name, + Level: Level, + Attributes: Attributes, + ModifiedBy: ModifiedBy, + }; +}; +module.exports = { getSpell }; diff --git a/globals.js b/globals.js index a8822e6..3011b5b 100644 --- a/globals.js +++ b/globals.js @@ -139,7 +139,15 @@ const Replies = [ { id: 'PARRY_SUCCESS', string: 'Parade erfolgreich.'}, { id: 'PARRY_CRIT_SUCCESS', string: 'Kritischer Erfolg! Du darfst einen Passierschlag ausführen!'}, { id: 'ROLL', string: 'Du würfelst:'}, - { id: 'HEADS_OR_TAILS', string: 'Die Münze landet auf '} + { 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: 'SPELLS_TITLE', string: 'Zaubersprüche'}, + { id: 'SPELLS_DESCRIPTION', string: 'Folgende Zaubersprüche beherrschst du:'}, + { id: 'NO_CHANTS', string: 'Du kennst keine Liturgien.' }, + { id: 'CHANTS_TITLE', string: 'Liturgien'}, + { id: 'CHANTS_DESCRIPTION', string: 'Folgende Liturgien beherrschst du:' }, + { id: 'CHANT_UNKNOWN', string: 'Diese Liturgie kenne ich nicht.'} ]; const Declination = ['dem', 'der', 'dem', '']; // Maskulinum, Feminimum, Neutrum, None const Articles = ['Der','Die','Das','']; @@ -231,5 +239,6 @@ const Advantages = [ const Disadvantages = [ {} ]; + module.exports = { Werte, Talente, Coin, TalentKategorien, DiceRegex, Discord, MessageEmbed, db, Replies, MeleeWeapons, Weapons, RangedWeapons, CombatTechniques, Articles, Declination }; diff --git a/jest.config.js b/jest.config.js index 7ede3f6..c23092f 100644 --- a/jest.config.js +++ b/jest.config.js @@ -1,8 +1,10 @@ module.exports = { - testEnvironment: 'node', - moduleNameMapper: { - "@dsabot/(.*)": "/functions/$1", - "@Commands/(.*)": "/commands/$1", - "@Root/(.*)": "/$1", - } -}; \ No newline at end of file + testEnvironment: 'node', + moduleNameMapper: { + '@dsabot/(.*)': '/functions/$1', + '@Commands/(.*)': '/commands/$1', + '@Root/(.*)': '/$1', + '@data/(.*)': '/data/$i', + '@lib/(.*)': '/lib/$i', + }, +}; diff --git a/jsconfig.json b/jsconfig.json index a4fad4e..213b761 100644 --- a/jsconfig.json +++ b/jsconfig.json @@ -3,11 +3,14 @@ "baseUrl": ".", "paths": { "@dsabot/*": ["./functions/*"], - "@globals": ["./globals"] + "@globals": ["./globals"], + "@data/*": ["./data/*"], + "@Commands/*": ["./commands/*"], + "@Lib/*": ["./lib/*"] }, }, "exclude": ["node_modules"], "typeAcquisition": { - "exclude": [ "dotenv" ] + "exclude": [ "dotenv", "source-map" ] }, } \ No newline at end of file diff --git a/lib/Chants.json b/lib/Chants.json new file mode 100644 index 0000000..79f64e0 --- /dev/null +++ b/lib/Chants.json @@ -0,0 +1 @@ +[{"id":"bannderdunkelheit","name":"Bann der Dunkelheit","attributes":["MU","KL","CH"],"cost":{"initial":4,"additional":{"amount":2,"interval":1,"unit":"Minute"}},"effect":{"description":"Aus der Hand des Geweihten strahlt ein helles Licht. Das Licht zählt regeltechnisch als Sonnenlicht.","duration":{},"instant":false,"pulse":true},"chant":{"duration":{"amount":1,"unit":"Aktion"},"type":"Chant","property":""}},{"id":"bannderfurcht","name":"Bann der Furcht","attributes":["IN","CH","CH"],"cost":{"initial":8,"additional":{}},"effect":{"description":"Durch diese Liturgie wird pro QS eine Stufe des Zustands Furcht aufgehoben.","duration":{},"instant":true,"pulse":false},"chant":{"duration":{"amount":2,"unit":"Aktionen"},"type":"Chant","property":""}},{"id":"banndeslichts","name":"Bann des Lichts","attributes":["MU","KL","CH"],"cost":{"initial":16,"additional":{"amount":8,"interval":5,"unit":"Minuten"}},"effect":{"description":"Um den Geweihten herum bildet sich eine Kugel aus Dunkelheit mit einem Durchmesser von QS x 3 Schritt. Pro QS erschweren sich die Sichtverhältnisse um eine Stufe. Natürliche und magische Lichtquellen können die Dunkelheit nicht erhellen. Bei karmalen Lichtquellen entscheidet die höhere QS (wie bei einer Vergleichsprobe), ob das Licht zu sehen ist oder nicht. Hierbei gilt alles oder nichts Das Licht wird nicht um die QS der Liturgie gedämpft, sondern die höhere QS entscheidet darüber ob Licht zu sehen ist oder nicht. Für den Geweihten werden die Sichtverhältnisse durch die Liturgie nicht erschwert. Der Geweihte muss vor dem Wirken der Liturgie entscheiden, ob die Zone der Dunkelheit an Ort und Stelle verbleiben oder sich mit ihm als Zentrum bewegen soll.","duration":{},"instant":false,"pulse":true},"chant":{"duration":{"amount":4,"unit":"Aktionen"},"type":"Chant","property":""}},{"id":"blendstrahl","name":"Blendstrahl","attributes":["MU","KL","IN"],"cost":{"initial":4,"additional":{}},"effect":{"description":"Der Betroffene wird geblendet. Es erhält eine Stufe des Zustands Verwirrung.","duration":{"amount":1,"modifier":"QS","unit":"Kampfrunden"},"instant":false,"pulse":false},"chant":{"duration":{"amount":1,"unit":"Aktion"},"type":"Chant","property":""}},{"id":"ehrenhaftigkeit","name":"Ehrenhaftigkeit","attributes":["MU","IN","CH"],"cost":{"initial":8,"additional":{}},"effect":{"description":"Ehrenhaft bedeutet in diesem Fall, dass der Betroffene sich an die Gebote des Geweihten hält. Dies kann je nach Auslegung und Kultur bedeuten, dass der Betroffene bei Patzern des Gegners auf weitere Angriffe verzichtet, nicht von hinten angreift, dem Gegner die Chance gibt, eine verlorene Waffe wieder aufzusammeln, auf Waffengifte verzichtet usw.","duration":{"amount":3,"modifier":"QS","unit":"Minuten"},"instant":false,"pulse":false},"chant":{"duration":{"amount":4,"unit":"Aktionen"},"type":"Chant","property":""}},{"id":"entzifferung","name":"Entzifferung","attributes":["KL","KL","IN"],"cost":{"initial":4,"additional":{}},"effect":{"description":"Die Textmenge richtet sich nach der QS. Für jede QS kann er fünf Foliantenseiten in normaler Schriftgröße entziffern.","duration":{"amount":3,"modifier":"QS","unit":"Minuten"},"instant":false,"pulse":false},"chant":{"duration":{"amount":8,"unit":"Aktionen"},"type":"Chant","property":""}},{"id":"ermutigung","name":"Ermutigung","attributes":["MU","IN","CH"],"cost":{"initial":4,"additional":{}},"effect":{"description":"Das Ziel wird zuversichtlicher und mutiger. Je nach QS erhält es verschiedene Boni. Die Boni sind kumulativ, d.h. bei QS 3 hat das Ziel insgesamt MU +2 und AT +1.","duration":{"amount":3,"modifier":"QS","unit":"Minuten"},"instant":false,"pulse":false},"chant":{"duration":{"amount":8,"unit":"Aktionen"},"type":"Chant","property":""}},{"id":"fallinsnichts","name":"Fall ins Nichts","attributes":["MU","IN","GE"],"cost":{"initial":8,"additional":{}},"effect":{"description":"Für jede QS kann der Geweihte drei Schritt Fallschaden ignorieren.","duration":{"amount":3,"modifier":"QS","unit":"Kampfrunden"},"instant":false,"pulse":false},"chant":{"duration":{"amount":1,"unit":"Aktion"},"type":"Chant","property":""}},{"id":"friedvolleaura","name":"Friedvolle Aura","attributes":["MU","IN","CH"],"cost":{"initial":8,"additional":{}},"effect":{"description":"Um den Geweihten anzugreifen, ist eine Probe auf Willenskraft (Bedrohungen standhalten) des Gegners notwendig, bei der er mehr QS haben muss als der Geweihte. Ist diese Probe nicht erfolgreich, kann der Angriff nicht ausgeführt werden. Gelingt sie, so ist die Attacke gegen den Geweihten dennoch um QS der Liturgie erschwert. Die Wirkung der Liturgie bezieht sich nur auf den Geweihten. Während der Wirkung der Liturgie kann der Geweihte keine Angriffe (Attacke, Fernkampf) oder sonstige offensive Handlungen gegen seine Feinde ausführen, wohl aber seine Kampfgefährten mit Handlungen unterstützen.","duration":{"amount":3,"modifier":"QS","unit":"Kampfrunden"},"instant":false,"pulse":false},"chant":{"duration":{"amount":1,"unit":"Aktion"},"type":"Chant","property":""}},{"id":"giftbann","name":"Giftbann","attributes":["KL","IN","CH"],"cost":{"initial":2,"additional":{"amount":2,"interval":1,"unit":"Giftstufe(n)"}},"effect":{"description":"Der Giftbann neutralisiert ein Gift. Die maximale Giftstufe darf die QS nicht übersteigen, sonst wirkt die Liturgie nicht und gilt als misslungen.","duration":{"amount":3,"modifier":"QS","unit":"Kampfrunden"},"instant":false,"pulse":false},"chant":{"duration":{"amount":4,"unit":"Aktionen"},"type":"Chant","property":""}},{"id":"goettlicherfingerzeig","name":"Göttlicher Fingerzeig","attributes":["KL","IN","IN"],"cost":{"initial":8,"additional":{}},"effect":{"description":"Voraussetzung ist, dass ein solcher Gegenstand überhaupt in Reichweite liegt. Dies kann z. B. ein verborgener Schlüssel für eine Truhe, ein Zettel mit Hinweisen oder ein benötigtes improvisiertes Werkzeug sein. Ist der Gegenstand durch Magie oder karmales Wirken verborgen, kann der Geweihte das Objekt nicht mittels dieser Liturgie entdecken. Der Gegenstand darf sich maximal QS Schritt vom Geweihten entfernt.","duration":{"amount":1,"modifier":null,"unit":"Minute"},"instant":false,"pulse":false},"chant":{"duration":{"amount":4,"unit":"Aktionen"},"type":"Chant","property":""}},{"id":"goettlicheszeichen","name":"Göttliches Zeichen","attributes":["IN","IN","CH"],"cost":{"initial":4,"additional":{}},"effect":{"description":"Das Zeichen äußert sich z. B. als Donnergrollen, obwohl keine Wolken am Himmel zu sehen sind (Rondra), das Schnattern eines Storches (Peraine) oder als kurzer Moment der Stille (Boron). Innerhalb der Zone der Liturgie können Personen das göttliche Zeichen wahrnehmen. Der Radius der Zone beträgt QS x 10 in Schritt. Bei Proben auf Bekehren & Überzeugen kann der Meister eine Erleichterung von 1 gewähren, wenn der Geweihte das Zeichen bei der Anwendung miteinbezieht.","duration":{"amount":3,"modifier":"QS","unit":"Kampfrunden"},"instant":false,"pulse":false},"chant":{"duration":{"amount":4,"unit":"Aktionen"},"type":"Chant","property":""}},{"id":"heilsegen","name":"Heilsegen","attributes":["KL","IN","CH"],"cost":{"initial":4,"additional":{"amount":1,"interval":1,"unit":"LeP"}},"effect":{"description":"Der Betroffene erhält innerhalb von 5 Minuten nach dem Wirken der Liturgie verlorene LeP in Höhe der verwendeten KaP zurück. Der Geweihte kann maximal so viele KaP einsetzen, wie er FW hat. Wird die Liturgie vor dem Ablauf der durch den Konstitutionswert angegebenen Frist für den Tod eines Helden begonnen, kann er gerettet werden. Wird die Liturgie jedoch unterbrochen, überlebt der Patient danach nur noch die verbliebenen Kampfrunden.","duration":{},"instant":true,"pulse":false},"chant":{"duration":{"amount":16,"unit":"Aktionen"},"type":"Chant","property":""}},{"id":"kleinerbannwideruntote","name":"Kleiner Bann wider Untote","attributes":["MU","MU","CH"],"cost":{"initial":4,"additional":{}},"effect":{"description":"Der Bann verursacht 2W6+(QS x2) SP gegen ein untotes Wesen. Der Bann trifft automatisch sein Ziel und dieses kann sich dagegen nicht verteidigen.","duration":{},"instant":true,"pulse":false},"chant":{"duration":{"amount":1,"unit":"Aktion"},"type":"Chant","property":""}},{"id":"kleinerbannstrahl","name":"Kleiner Bannstrahl","attributes":["MU","IN","CH"],"cost":{"initial":8,"additional":{}},"effect":{"description":"Der Bannstrahl richtet gegen einen Dämon 2W6+(QS x2) SP an. Gegen Dämonen aus Blakharaz’ Domäne wird der Schaden verdoppelt. Der Bannstrahl trifft automatisch sein Ziel und dieses kann sich dagegen nicht verteidigen. Der kleine Bannstrahl ist nicht davon abhängig, ob der Himmel zu sehen ist. Der Strahl entsteht direkt beim Dämon, auf den der Strahl wirken soll.","duration":{},"instant":true,"pulse":false},"chant":{"duration":{"amount":2,"unit":"Aktionen"},"type":"Chant","property":""}},{"id":"krankheitsbann","name":"Krankheitsbann","attributes":["KL","IN","CH"],"cost":{"initial":2,"additional":{"amount":2,"interval":1,"unit":"Krankheitsstufe(n)"}},"effect":{"description":"Diese Liturgie heilt Krankheiten (die bisher erlittenen Auswirkungen werden nicht geheilt). Die maximale Krankheitsstufe darf die QS nicht übersteigen, sonst wirkt die Liturgie nicht und gilt als misslungen. Die Liturgie heilt auch alle Symptome der Krankheit, aber keine bis dahin entstandenen Schäden (LeP-Verlust, Narben usw.).","duration":{},"instant":true,"pulse":false},"chant":{"duration":{"amount":16,"unit":"Aktionen"},"type":"Chant","property":""}},{"id":"lautlos","name":"Lautlos","attributes":["IN","IN","GE"],"cost":{"initial":4,"additional":{"amount":2,"interval":1,"unit":"Minute"}},"effect":{"description":"Proben auf Verbergen (Schleichen) sind um QS erleichtert.","duration":{},"instant":false,"pulse":true},"chant":{"duration":{"amount":4,"unit":"Aktionen"},"type":"Chant","property":""}},{"id":"magieschutz","name":"Magieschutz","attributes":["MU","IN","CH"],"cost":{"initial":8,"additional":{"amount":4,"interval":10,"unit":"Minuten"}},"effect":{"description":"Er erhält einen Bonus von QS –1 auf SK und ZK (mindestens jedoch 1 Punkt) gegen magische Effekte.","duration":{},"instant":false,"pulse":true},"chant":{"duration":{"amount":4,"unit":"Aktionen"},"type":"Chant","property":""}},{"id":"magiesicht","name":"Magiesicht","attributes":["KL","IN","IN"],"cost":{"initial":4,"additional":{}},"effect":{"description":"Mit dieser Liturgie lässt sich aktives magisches Wirken auf Gegenständen und Personen erkennen. Je nach Stärke der astralen Kräfte im Objekt kann die Probe erleichtert oder erschwert werden. Je nach QS können dabei nachfolgende Analysen mittels des Zaubers ANALYS oder entsprechenden Liturgien beeinflusst werden. Der Geweihte kann nur ein ausgewähltes Wesen oder Objekt in Reichweite untersuchen. Er hat keine Rundumsicht.","duration":{"amount":1,"modifier":null,"unit":"Minute"},"instant":false,"pulse":false},"chant":{"duration":{"amount":2,"unit":"Aktionen"},"type":"Chant","property":""}},{"id":"mondsicht","name":"Mondsicht","attributes":["KL","KL","IN"],"cost":{"initial":2,"additional":{"amount":1,"interval":10,"unit":"Minuten"}},"effect":{"description":"Erschwernisse der Sichtverhältnisse durch Dunkelheit werden um QS –1 Stufen gesenkt (mindestens jedoch 1","duration":{},"instant":false,"pulse":true},"chant":{"duration":{"amount":4,"unit":"Aktionen"},"type":"Chant","property":""}},{"id":"mondsilberzunge","name":"Mondsilberzunge","attributes":["KL","IN","CH"],"cost":{"initial":8,"additional":{}},"effect":{"description":"Der Held wirkt vertrauenerweckend. Er erhält eine Erleichterung von QS auf die Fertigkeiten Überreden und Handel (Feilschen).","duration":{"amount":3,"modifier":"QS","unit":"Minute"},"instant":false,"pulse":false},"chant":{"duration":{"amount":1,"unit":"Aktionen"},"type":"Chant","property":""}},{"id":"objektsegen","name":"Objektsegen","attributes":["MU","IN","CH"],"cost":{"initial":4,"additional":{}},"effect":{"description":"Mit dieser Liturgie werden für Götterdienste benötigte Materialien (z. B. Salbungsöl eines Borongeweihten, das Saatgut eines Perainegeweihten oder Sternenstaub bei Phexgeweihten) gesegnet. Der Gegenstand zählt nicht als geweiht, sondern nur als gesegnet.","duration":{"amount":3,"modifier":"QS","unit":"Stunden"},"instant":false,"pulse":false},"chant":{"duration":{"amount":4,"unit":"Aktionen"},"type":"Chant","property":""}},{"id":"ortderruhe","name":"Ort der Ruhe","attributes":["MU","KL","IN"],"cost":{"initial":4,"additional":{}},"effect":{"description":"Innerhalb der Zone werden Geräusche gedämpft. Der Radius der Zone beträgt QS x 3 Schritt. Proben gegen Sinnesschärfe (Wahrnehmen), um leise Geräusche wie Flüstern zu hören, sind innerhalb der Zone um QS erschwert. Die Zone verbleibt an Ort und Stelle. Geräusche, die aus der Zone dringen, bleiben gedämpft, Geräusche, die in die Zone eindringen, werden gedämpft.","duration":{"amount":3,"modifier":"QS","unit":"Stunden"},"instant":false,"pulse":false},"chant":{"duration":{"amount":8,"unit":"Aktionen"},"type":"Chant","property":""}},{"id":"pflanzenwuchs","name":"Pflanzenwuchs","attributes":["KL","IN","CH"],"cost":{"initial":8,"additional":{}},"effect":{"description":"Die Liturgie lässt eine maximal buschgroße Pflanze übernatürlich schnell wachsen. Pro QS wächst die Pflanze 30 % schneller als für die Gattung typisch.","duration":{"amount":1,"modifier":null,"unit":"Jahr"},"instant":false,"pulse":false},"chant":{"duration":{"amount":16,"unit":"Aktionen"},"type":"Chant","property":""}},{"id":"rabenruf","name":"Rabenruf","attributes":["MU","KL","IN"],"cost":{"initial":8,"additional":{}},"effect":{"description":"Der Geweihte ruft bis zu QS x 3 Raben aus einem Radius von QS x 3 Meilen herbei. Die Vögel verhalten sich ihm gegenüber zutraulich. Der Geweihte kann einen der Raben dazu benutzen, einen kleinen Gegenstand wie einen Ring zu transportieren, maximal bis zu einer Reichweite von QS x 3 Meile. Der Rabe findet den Zielort in der Regel automatisch. Es können maximal so viele Raben zum Geweihten fliegen, wie sich zu diesem Zeitpunkt in der Reichweite der Liturgie befinden.","duration":{"amount":3,"modifier":"QS","unit":"Stunden"},"instant":false,"pulse":false},"chant":{"duration":{"amount":16,"unit":"Aktionen"},"type":"Chant","property":""}},{"id":"schlaf","name":"Schlaf","attributes":["KL","IN","CH"],"cost":{"initial":8,"additional":{}},"effect":{"description":"Der Geweihte betäubt den Betroffenen. Erreicht dieser so Betäubung Stufe IV, schläft er ein und ist vor Ablauf der Wirkungsdauer nur durch großen Lärm, kräftiges Anstoßen oder Ähnliches zu wecken. Ungestört schläft er, bis er auf natürlichem Wege erwacht.","duration":{"amount":3,"modifier":"QS","unit":"Minuten"},"instant":false,"pulse":false},"chant":{"duration":{"amount":2,"unit":"Aktionen"},"type":"Chant","property":""}},{"id":"schlangenstab","name":"Schlangenstab","attributes":["MU","KL","IN"],"cost":{"initial":8,"additional":{}},"effect":{"description":"Die Schlange beschützt den Geweihten mit den ihr zur Verfügung stehenden Mitteln und folgt ihm. Stirbt die Schlange, verwandelt sie sich wieder zurück in das Objekt. Die Schlange gilt als gesegnet wie durch einen Objektsegen.","duration":{"amount":3,"modifier":"QS","unit":"Minuten"},"instant":false,"pulse":false},"chant":{"duration":{"amount":2,"unit":"Aktionen"},"type":"Chant","property":""}},{"id":"schlangenzunge","name":"Schlangenzunge","attributes":["MU","KL","IN"],"cost":{"initial":8,"additional":{}},"effect":{"description":"Für Umstehende klingt dies wie zischende Laute. Bei der Darstellung eines solchen Gespräches sollte bedacht werden, dass Schlangen einen tierischen Verstand haben und die Welt anders wahrnehmen als Menschen.","duration":{"amount":3,"modifier":"QS","unit":"Minuten"},"instant":false,"pulse":false},"chant":{"duration":{"amount":8,"unit":"Aktionen"},"type":"Chant","property":""}},{"id":"schmerzresistenz","name":"Schmerzresistenz","attributes":["MU","IN","KO"],"cost":{"initial":8,"additional":{}},"effect":{"description":"Alle Effekte der Stufen des Zustands Schmerz können ignoriert werden, bis auf Stufe IV (ab Stufe IV wird der Geweihe von den ganz normalen Auswirkungen des Zustands betroffen).","duration":{"amount":3,"modifier":"QS","unit":"Kampfrunden"},"instant":false,"pulse":false},"chant":{"duration":{"amount":1,"unit":"Aktion"},"type":"Chant","property":""}},{"id":"schutzderwehrlosen","name":"Schutz der Wehrlosen","attributes":["MU","IN","CH"],"cost":{"initial":8,"additional":{}},"effect":{"description":"Der Geweihte kann einen Kämpfer, der eine wehr- oder schutzlose Person angreift oder angreifen will, herausfordern. Der Herausgeforderte lässt von seinem Opfer ab und greift stattdessen den Rondrageweihten an.","duration":{"amount":3,"modifier":"QS","unit":"Minuten"},"instant":false,"pulse":false},"chant":{"duration":{"amount":1,"unit":"Aktion"},"type":"Chant","property":""}},{"id":"sternenglanz","name":"Sternenglanz","attributes":["KL","IN","CH"],"cost":{"initial":8,"additional":{}},"effect":{"description":"Es kann so einen um QS x 10 % höheren Preis erzielen. Misstrauische Käufer können diese Täuschung durchschauen, wenn ihnen eine vergleichende Probe auf Sinnesschärfe (Suchen) erschwert um QS +2 gelingt.","duration":{"amount":15,"modifier":"QS","unit":"Minuten"},"instant":false,"pulse":false},"chant":{"duration":{"amount":2,"unit":"Aktion"},"type":"Chant","property":""}},{"id":"wahrheit","name":"Wahrheit","attributes":["MU","KL","IN"],"cost":{"initial":16,"additional":{}},"effect":{"description":"Der Betroffene muss dem Geweihten (und nur ihm) wahrheitsgemäß auf jede seiner Frage antworten, so lange die Wirkungsdauer der Liturgie anhält. Das Opfer der Liturgie weiß, was es sagt.","duration":{"amount":3,"modifier":"QS","unit":"Minuten"},"instant":false,"pulse":false},"chant":{"duration":{"amount":8,"unit":"Aktion"},"type":"Chant","property":""}},{"id":"wieselflink","name":"Wieselflink","attributes":["IN","IN","GE"],"cost":{"initial":8,"additional":{}},"effect":{"description":"Der Geweihte wird flinker und schneller. Je nach QS erhält er verschiedene Boni. Die Boni sind kumulativ, d.h. bei QS 5 hat der Geweihte insgesamt GE +3, GS + 1 und AW +1. Durch die Steigerung der GE können auch die Schadensschwellen bei Kampftechniken mit GE betroffen sein. Der Geweihte macht also eventuell mehr Schaden mit einigen Waffen.","duration":{"amount":3,"modifier":"QS","unit":"Minuten"},"instant":false,"pulse":false},"chant":{"duration":{"amount":2,"unit":"Aktion"},"type":"Chant","property":""}},{"id":"wundersameverstaendigung","name":"Wundersame Verständigung","attributes":["KL","KL","IN"],"cost":{"initial":8,"additional":{}},"effect":{"description":"Der Geweihte erhält die Stufen in der Sprache, die er gerade für seine Kommunikation benötigt. Es ist nicht notwendig, dass der Geweihte schon einmal etwas von der Sprache gehört oder gelesen hat.","duration":{"amount":3,"modifier":"QS","unit":"Stunden"},"instant":false,"pulse":false},"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":""}}] \ No newline at end of file diff --git a/lib/Spells.json b/lib/Spells.json new file mode 100644 index 0000000..3eca5a3 --- /dev/null +++ b/lib/Spells.json @@ -0,0 +1 @@ +[{"id":"adlerauge","name":"Adlerauge","attributes":["KL","IN","FF"],"modified_by":[],"cost":{"initial":4,"additional":{"amount":2,"interval":5,"unit":"Minuten"}},"effect":{"description":"Das Talent Sinnesschärfe wird während der Wirkungsdauer um QS +3 des Zaubers erhöht.","duration":{},"pulse":true,"instant":false},"talent":null,"spell":{"duration":{"amount":2,"unit":"Aktionen"},"type":"Spell","property":"Heilung"}},{"id":"analysarkanstruktur","name":"Analys Arkanstruktur","attributes":["KL","KL","IN"],"modified_by":[],"cost":{"initial":16,"additional":{}},"effect":{"description":"Der Zauberer erhält detaillierte Hinweise, ob das Objekt magisch ist und falls ja, wie seine magische Struktur beschaffen ist. Durch die so gesammelten Informationen kann der Zauberer bei einer Magischen Analyse mehr QS ansammeln als üblich. Jede QS des Analys entspricht der Höhe der maximal ansammelbaren QS der Probe auf Magiekunde (unterschiedliche Anwendungsgebiete) für die Magische Analyse.","duration":{},"pulse":false,"instant":true},"talent":null,"spell":{"duration":{"amount":32,"unit":"Aktionen"},"type":"Spell","property":"Hellsicht"}},{"id":"armatrutz","name":"Armatrutz","attributes":["KL","IN","FF"],"modified_by":[],"cost":{"initial":4,"additional":null},"effect":{"description":"Die Haut des Zaubernden verhärtet sich, ohne ihre Flexibilität zu verlieren. So erhält er einen natürlichen Rüstungsschutz, der sich auf getragene Rüstung aufaddiert, ohne die Belastung zu erhöhen. Die Höhe des gewünschten zusätzlichen Rüstungsschutzes muss der Zaubernde vor der Probe festlegen. Maximal ist ein zusätzlicher RS von 3 möglich.","duration":{"amount":3,"modifier":"QS","unit":"Minuten"},"pulse":false,"instant":false},"talent":null,"spell":{"duration":{"amount":1,"unit":"Aktionen"},"type":"Spell","property":"Heilung"}},{"id":"axxeleratus","name":"Axxeleratus","attributes":["KL","IN","FF"],"modified_by":[],"cost":{"initial":8,"additional":{}},"effect":{"description":"Die Bewegungen des Verzauberten werden übernatürlich beschleunigt. Dies bringt folgende Erleichterungen: +1 Verteidigung, GS x 2, INI-Basiswert x 2. Gegner können Attacken und Fernkampfangriffe des Beschleunigten schlechter abwehren und erhalten auf Verteidigung eine Erschwernis von 2.","duration":{"amount":5,"modifier":"QS","unit":"Kampfrunden"},"pulse":false,"instant":false},"talent":null,"spell":{"duration":{"amount":1,"unit":"Aktionen"},"type":"Spell","property":"Heilung"}},{"id":"balsamsalabunde","name":"Balsam Salabunde","attributes":["KL","IN","FF"],"modified_by":[],"cost":{"initial":4,"additional":{"amount":1,"interval":1,"unit":"LeP"}},"effect":{"description":"Der Verzauberte erhält innerhalb von 6 Minuten nach dem Wirken des Zaubers verlorene LeP in Höhe der verwendeten AsP zurück. Der Zauberer kann maximal so viele AsP einsetzen, wie er FW hat. Für jede QS sinkt die Zeit um 1 Minute. Wird der Zauber vor dem Ablauf der durch den Konstitutionswert angegebenen Frist für den Tod eines Helden begonnen, kann er gerettet werden. Wird der Zauber jedoch unterbrochen, überlebt der Patient danach nur noch die verbliebenen Kampfrunden.","duration":{},"pulse":false,"instant":true},"talent":null,"spell":{"duration":{"amount":16,"unit":"Aktionen"},"type":"Spell","property":"Heilung"}},{"id":"bannbaladin","name":"Bannbaladin","attributes":["MU","IN","CH"],"modified_by":["ZK"],"cost":{"initial":8,"additional":{}},"effect":{"description":"","duration":{"amount":3,"modifier":"QS","unit":"Minuten"},"pulse":false,"instant":false},"talent":null,"spell":{"duration":{"amount":4,"unit":"Aktionen"},"type":"Spell","property":"Einfluss"}},{"id":"blickindiegedanken","name":"Blick in die Gedanken","attributes":["MU","KL","IN"],"modified_by":["ZK"],"cost":{"initial":8,"additional":{"amount":4,"interval":30,"unit":"Sekunden"}},"effect":{"description":"","duration":{},"pulse":true,"instant":false},"talent":null,"spell":{"duration":{"amount":4,"unit":"Aktionen"},"type":"Spell","property":"Hellsicht"}},{"id":"blitzdichfind","name":"Blitz dich find","attributes":["MU","IN","CH"],"modified_by":["ZK"],"cost":{"initial":4,"additional":{"amount":null,"interval":null,"unit":null}},"effect":{"description":"","duration":{"amount":"QS Kampfrunden","modifier":"QS Kampfrunden","unit":null},"pulse":false,"instant":false},"talent":null,"spell":{"duration":{"amount":1,"unit":"Aktionen"},"type":"Spell","property":"Einfluss"}},{"id":"corpofesso","name":"Corpofesso","attributes":["KL","IN","KO"],"modified_by":["ZK"],"cost":{"initial":16,"additional":{"amount":null,"interval":null,"unit":null}},"effect":{"description":"","duration":{"amount":2,"modifier":"QS","unit":"Kampfrunden"},"pulse":false,"instant":false},"talent":null,"spell":{"duration":{"amount":2,"unit":"Aktionen"},"type":"Spell","property":"Verwandlung"}},{"id":"disruptivo","name":"Disruptivo","attributes":["MU","KL","CH"],"modified_by":[],"cost":{"initial":8,"additional":{"amount":null,"interval":null,"unit":null}},"effect":{"description":"","duration":{},"pulse":true,"instant":false},"talent":null,"spell":{"duration":{"amount":8,"unit":"Aktionen"},"type":"Spell","property":"Antimagie"}},{"id":"duplicatus","name":"Duplicatus","attributes":["KL","IN","CH"],"modified_by":[],"cost":{"initial":4,"additional":{"amount":null,"interval":null,"unit":null}},"effect":{"description":"","duration":{"amount":3,"modifier":"QS","unit":"Kampfrunden"},"pulse":false,"instant":false},"talent":null,"spell":{"duration":{"amount":2,"unit":"Aktionen"},"type":"Spell","property":"Illusion"}},{"id":"falkenauge","name":"Falkenauge","attributes":["MU","KL","IN"],"modified_by":[],"cost":{"initial":4,"additional":{"amount":null,"interval":null,"unit":null}},"effect":{"description":"","duration":{"amount":2,"modifier":"QS","unit":"Kampfrunden"},"pulse":false,"instant":false},"talent":null,"spell":{"duration":{"amount":2,"unit":"Aktionen"},"type":"Spell","property":null}},{"id":"flimflam","name":"Flim Flam","attributes":["MU","KL","CH"],"modified_by":[],"cost":{"initial":2,"additional":{"amount":null,"interval":null,"unit":null}},"effect":{"description":"","duration":{},"pulse":true,"instant":false},"talent":null,"spell":{"duration":{"amount":1,"unit":"Aktion"},"type":"Spell","property":"Elementar"}},{"id":"fulminictus","name":"Fulminictus","attributes":["KL","IN","KO"],"modified_by":["ZK"],"cost":{"initial":8,"additional":{"amount":null,"interval":null,"unit":null}},"effect":{"description":"","duration":{},"pulse":false,"instant":true},"talent":null,"spell":{"duration":{"amount":1,"unit":"Aktion"},"type":"Spell","property":"Verwandlung"}},{"id":"gardianum","name":"Gardianum","attributes":["MU","KL","CH"],"modified_by":[],"cost":{"initial":4,"additional":{"amount":null,"interval":null,"unit":null}},"effect":{"description":"","duration":{"amount":5,"modifier":null,"unit":"Minuten"},"pulse":false,"instant":false},"talent":null,"spell":{"duration":{"amount":1,"unit":"Aktion"},"type":"Spell","property":"Antimagie"}},{"id":"grossegier","name":"Große Gier","attributes":["MU","IN","CH"],"modified_by":["SK"],"cost":{"initial":8,"additional":{"amount":null,"interval":null,"unit":null}},"effect":{"description":"","duration":{"amount":15,"modifier":"QS","unit":"Minuten"},"pulse":false,"instant":false},"talent":null,"spell":{"duration":{"amount":2,"unit":"Aktionen"},"type":"Spell","property":"Einfluss"}},{"id":"harmlosegestalt","name":"Harmlose Gestalt","attributes":["KL","IN","CH"],"modified_by":[],"cost":{"initial":8,"additional":{"amount":null,"interval":null,"unit":null}},"effect":{"description":"","duration":{},"pulse":true,"instant":false},"talent":null,"spell":{"duration":{"amount":4,"unit":"Aktionen"},"type":"Spell","property":"Illusion"}},{"id":"hexengalle","name":"Hexengalle","attributes":["KL","IN","KO"],"modified_by":[],"cost":{"initial":4,"additional":{"amount":null,"interval":null,"unit":null}},"effect":{"description":"","duration":{},"pulse":false,"instant":true},"talent":null,"spell":{"duration":{"amount":1,"unit":"Aktionen"},"type":"Spell","property":"Verwandlung"}},{"id":"hexenkrallen","name":"Hexenkrallen","attributes":["KL","IN","KO"],"modified_by":[],"cost":{"initial":4,"additional":{"amount":null,"interval":null,"unit":null}},"effect":{"description":"","duration":{"amount":3,"modifier":"QS","unit":"Minuten"},"pulse":false,"instant":false},"talent":null,"spell":{"duration":{"amount":1,"unit":"Aktionen"},"type":"Spell","property":"Verwandlung"}},{"id":"horriphobos","name":"Horriphobos","attributes":["MU","IN","CH"],"modified_by":["SK"],"cost":{"initial":8,"additional":{"amount":null,"interval":null,"unit":null}},"effect":{"description":"","duration":{"amount":3,"modifier":"QS","unit":"Minuten"},"pulse":false,"instant":false},"talent":null,"spell":{"duration":{"amount":2,"unit":"Aktionen"},"type":"Spell","property":"Einfluss"}},{"id":"ignifaxius","name":"Ignifaxius","attributes":["MU","KL","CH"],"modified_by":[],"cost":{"initial":8,"additional":{"amount":null,"interval":null,"unit":null}},"effect":{"description":"","duration":{},"pulse":false,"instant":true},"talent":null,"spell":{"duration":{"amount":2,"unit":"Aktionen"},"type":"Spell","property":"Elementar"}},{"id":"invocatiominima","name":"Invocatio Minima","attributes":["MU","CH","KO"],"modified_by":[],"cost":{"initial":4,"additional":{"amount":null,"interval":null,"unit":null}},"effect":{"description":"","duration":{},"pulse":false,"instant":true},"talent":null,"spell":{"duration":{"amount":4,"unit":"Aktionen"},"type":"Spell","property":"Sphaeren"}},{"id":"katzenaugen","name":"Katzenaugen","attributes":["KL","IN","KO"],"modified_by":[],"cost":{"initial":2,"additional":{"amount":1,"interval":10,"unit":"Minuten"}},"effect":{"description":"","duration":{},"pulse":true,"instant":false},"talent":null,"spell":{"duration":{"amount":4,"unit":"Aktionen"},"type":"Spell","property":"Verwandlung"}},{"id":"kroetensprung","name":"Krötensprung","attributes":["KL","IN","KO"],"modified_by":[],"cost":{"initial":2,"additional":{"amount":null,"interval":null,"unit":null}},"effect":{"description":"","duration":{},"pulse":false,"instant":true},"talent":null,"spell":{"duration":{"amount":2,"unit":"Aktionen"},"type":"Spell","property":"Verwandlung"}},{"id":"manifesto","name":"Manifesto","attributes":["MU","KL","CH"],"modified_by":[],"cost":{"initial":4,"additional":{"amount":null,"interval":null,"unit":null}},"effect":{"description":"","duration":{},"pulse":false,"instant":true},"talent":null,"spell":{"duration":{"amount":4,"unit":"Aktionen"},"type":"Spell","property":"Elementar"}},{"id":"manusmiracula","name":"Manus Miracula","attributes":["KL","FF","KK"],"modified_by":[],"cost":{"initial":4,"additional":{"amount":2,"interval":5,"unit":"Minuten"}},"effect":{"description":"","duration":{},"pulse":true,"instant":false},"talent":null,"spell":{"duration":{"amount":2,"unit":"Aktionen"},"type":"Spell","property":"Telekinese"}},{"id":"motoricus","name":"Motoricus","attributes":["KL","FF","KK"],"modified_by":[],"cost":{"initial":4,"additional":{"amount":2,"interval":5,"unit":"Minuten"}},"effect":{"description":"","duration":{},"pulse":true,"instant":false},"talent":null,"spell":{"duration":{"amount":2,"unit":"Aktionen"},"type":"Spell","property":"Telekinese"}},{"id":"nebelwand","name":"Nebelwand","attributes":["MU","KL","CH"],"modified_by":[],"cost":{"initial":4,"additional":{"amount":null,"interval":null,"unit":null}},"effect":{"description":"","duration":{"amount":15,"modifier":"QS","unit":"Minuten"},"pulse":false,"instant":false},"talent":null,"spell":{"duration":{"amount":2,"unit":"Aktionen"},"type":"Spell","property":"Elementar"}},{"id":"oculusillusionis","name":"Oculus Illusionis","attributes":["KL","IN","CH"],"modified_by":[],"cost":{"initial":4,"additional":{"amount":2,"interval":5,"unit":"Minuten"}},"effect":{"description":"","duration":{},"pulse":true,"instant":false},"talent":null,"spell":{"duration":{"amount":4,"unit":"Aktionen"},"type":"Spell","property":"Illusion"}},{"id":"odemarcanum","name":"Odem Arcanum","attributes":["MU","KL","IN"],"modified_by":[],"cost":{"initial":4,"additional":{"amount":null,"interval":null,"unit":null}},"effect":{"description":"","duration":{"amount":1,"modifier":null,"unit":"Minute"},"pulse":false,"instant":false},"talent":null,"spell":{"duration":{"amount":2,"unit":"Aktionen"},"type":"Spell","property":"Hellsicht"}},{"id":"paralys","name":"Paralys","attributes":["KL","IN","KO"],"modified_by":["ZK"],"cost":{"initial":8,"additional":{"amount":null,"interval":null,"unit":null}},"effect":{"description":"","duration":{"amount":2,"modifier":"QS","unit":"Minuten"},"pulse":false,"instant":false},"talent":null,"spell":{"duration":{"amount":2,"unit":"Aktionen"},"type":"Spell","property":"Verwandlung"}},{"id":"penetrizzel","name":"Penetrizzel","attributes":["MU","KL","IN"],"modified_by":[],"cost":{"initial":4,"additional":{"amount":2,"interval":1,"unit":"Minute"}},"effect":{"description":"","duration":{},"pulse":true,"instant":false},"talent":null,"spell":{"duration":{"amount":2,"unit":"Aktionen"},"type":"Spell","property":"Hellsicht"}},{"id":"psychostabilis","name":"Psychostabilis","attributes":["KL","IN","FF"],"modified_by":[],"cost":{"initial":4,"additional":{"amount":2,"interval":10,"unit":"Minuten"}},"effect":{"description":"","duration":{},"pulse":true,"instant":false},"talent":null,"spell":{"duration":{"amount":8,"unit":"Aktionen"},"type":"Spell","property":"Heilung"}},{"id":"radau","name":"Radau","attributes":["KL","FF","KK"],"modified_by":[],"cost":{"initial":4,"additional":{"amount":2,"interval":1,"unit":"Kampfrunde"}},"effect":{"description":"","duration":{},"pulse":true,"instant":false},"talent":null,"spell":{"duration":{"amount":2,"unit":"Aktionen"},"type":"Spell","property":"Telekinese"}},{"id":"respondami","name":"Respondami","attributes":["MU","IN","CH"],"modified_by":["SK"],"cost":{"initial":8,"additional":{"amount":null,"interval":null,"unit":null}},"effect":{"description":"","duration":{"amount":15,"modifier":"QS","unit":"Minuten"},"pulse":false,"instant":false},"talent":null,"spell":{"duration":{"amount":2,"unit":"Aktionen"},"type":"Spell","property":"Einfluss"}},{"id":"salander","name":"Salander","attributes":["KL","IN","KO"],"modified_by":["ZK"],"cost":{"initial":16,"additional":{"amount":null,"interval":null,"unit":null}},"effect":{"description":"","duration":{"amount":3,"modifier":"QS","unit":"Stunden"},"pulse":false,"instant":false},"talent":null,"spell":{"duration":{"amount":8,"unit":"Aktionen"},"type":"Spell","property":"Verwandlung"}},{"id":"sanftmut","name":"Sanftmut","attributes":["MU","IN","CH"],"modified_by":["SK"],"cost":{"initial":4,"additional":{"amount":null,"interval":null,"unit":null}},"effect":{"description":"","duration":{"amount":3,"modifier":"QS","unit":"Minuten"},"pulse":false,"instant":false},"talent":null,"spell":{"duration":{"amount":2,"unit":"Aktionen"},"type":"Spell","property":"Einfluss"}},{"id":"satuariasherrlichkeit","name":"Satuarias Herrlichkeit","attributes":["KL","IN","KO"],"modified_by":[],"cost":{"initial":8,"additional":{"amount":null,"interval":null,"unit":null}},"effect":{"description":"","duration":{"amount":3,"modifier":"QS","unit":"Stunden"},"pulse":false,"instant":false},"talent":null,"spell":{"duration":{"amount":4,"unit":"Aktionen"},"type":"Spell","property":"Verwandlung"}},{"id":"silentium","name":"Silentium","attributes":["KL","FF","KK"],"modified_by":[],"cost":{"initial":4,"additional":{"amount":2,"interval":5,"unit":"Minuten"}},"effect":{"description":"","duration":{},"pulse":true,"instant":false},"talent":null,"spell":{"duration":{"amount":8,"unit":"Aktionen"},"type":"Spell","property":"Telekinese"}},{"id":"somnigravis","name":"Somnigravis","attributes":["MU","IN","CH"],"modified_by":["SK"],"cost":{"initial":8,"additional":{"amount":null,"interval":null,"unit":null}},"effect":{"description":"","duration":{"amount":3,"modifier":"QS","unit":"Minuten"},"pulse":false,"instant":false},"talent":null,"spell":{"duration":{"amount":8,"unit":"Aktionen"},"type":"Spell","property":"Einfluss"}},{"id":"spinnenlauf","name":"Spinnenlauf","attributes":["KL","IN","KO"],"modified_by":[],"cost":{"initial":4,"additional":{"amount":2,"interval":5,"unit":"Minuten"}},"effect":{"description":"","duration":{},"pulse":true,"instant":false},"talent":null,"spell":{"duration":{"amount":4,"unit":"Aktionen"},"type":"Spell","property":"Verwandlung"}},{"id":"spurlos","name":"Spurlos","attributes":["KL","FF","KK"],"modified_by":[],"cost":{"initial":4,"additional":{"amount":2,"interval":5,"unit":"Minuten"}},"effect":{"description":"","duration":{},"pulse":true,"instant":false},"talent":null,"spell":{"duration":{"amount":4,"unit":"Aktionen"},"type":"Spell","property":"Telekinese"}},{"id":"transversalis","name":"Transversalis","attributes":["MU","CH","KO"],"modified_by":[],"cost":{"initial":8,"additional":{"amount":null,"interval":null,"unit":null}},"effect":{"description":"","duration":{},"pulse":false,"instant":true},"talent":null,"spell":{"duration":{"amount":8,"unit":"Aktionen"},"type":"Spell","property":"Sphaeren"}},{"id":"visibili","name":"Visibili","attributes":["KL","IN","KO"],"modified_by":[],"cost":{"initial":8,"additional":{"amount":4,"interval":5,"unit":"Minuten"}},"effect":{"description":"","duration":{},"pulse":true,"instant":false},"talent":null,"spell":{"duration":{"amount":4,"unit":"Aktionen"},"type":"Spell","property":"Verwandlung"}},{"id":"wasseratem","name":"Wasseratem","attributes":["KL","IN","KO"],"modified_by":[],"cost":{"initial":4,"additional":{"amount":2,"interval":5,"unit":"Minuten"}},"effect":{"description":"","duration":{},"pulse":true,"instant":false},"talent":null,"spell":{"duration":{"amount":8,"unit":"Aktionen"},"type":"Spell","property":"Verwandlung"}},{"id":"bluttrinken","name":"Blut trinken","attributes":["MU","IN","CH"],"modified_by":[],"cost":{"initial":3,"additional":{"amount":null,"interval":null,"unit":null}},"effect":{"description":"Der Animist kann das Blut eines von ihm getöteten Kulturschaffenden trinken, um sich dessen letzte Lebenskräfte anzueignen. Dadurch kann der Animist QS LeP bei sich heilen, allerdings nur maximal bis zum eigenen Maximalwert. Der Einsatz dieser Fähigkeit dauert mindestens 2 Aktionen, nach Meisterentscheid auch noch länger.","duration":{"amount":"sofort","modifier":"sofort","unit":null},"pulse":false,"instant":false},"talent":null,"spell":{"duration":{"amount":null,"unit":"Aktionen"},"type":null,"property":null}},{"id":"durchfestematerie","name":"Durch feste Materie","attributes":["IN","IN","CH"],"modified_by":[],"cost":{"initial":4,"additional":{"amount":null,"interval":null,"unit":null}},"effect":{"description":"Der Animist lässt eine Wesenheit in sich einfahren, die seinen physischen Körper und sein Traditionsartefakt durchscheinend werden lässt. Er kann sich während der Wirkungsdauer durch feste, unbelebte Materie und Objekte wie Wände, Türen und Tische, nicht aber durch lebende Wesen, hindurchbewegen. Der Animist ist während der Wirkungsdauer immun gegen profane Waffen, nicht jedoch gegen magische oder karmale Waffen oder Angriffe.","duration":{"amount":"QS x 2 KR","modifier":"QS x 2 KR","unit":null},"pulse":false,"instant":false},"talent":null,"spell":{"duration":{"amount":null,"unit":"Aktionen"},"type":null,"property":null}},{"id":"grossersprung","name":"Großer Sprung","attributes":["IN","GE","KO"],"modified_by":[],"cost":{"initial":4,"additional":{"amount":null,"interval":null,"unit":null}},"effect":{"description":"Der Animist kann mit dieser Kraft erstaunlich hoch und weit springen. Die normale Sprungreichweite wird pro QS um 50 % erhöht. Pro KR kann der Animist mit 1 Aktion einen Sprungversuch durchführen.","duration":{"amount":"QS x 2 KR","modifier":"QS x 2 KR","unit":null},"pulse":false,"instant":false},"talent":null,"spell":{"duration":{"amount":null,"unit":"Aktionen"},"type":null,"property":null}},{"id":"erinnerungsmelodie","name":"Erinnerungsmelodie","attributes":["KL","IN","IN"],"modified_by":[],"cost":{"initial":null,"additional":{"amount":1,"interval":5,"unit":"Minuten"}},"effect":{"description":"Mit dem Lied ruft sich der Elf eine Erinnerung aus lang vergangener Zeit zurück.Für je ein Jahr, das das Ereignis zurückliegt, muss er 5 Minuten spielen.Zusätzlich spielt er so lange, wie die Situation dauert, an die er sich zurück entsinnen will.","duration":{},"pulse":true,"instant":false},"talent":null,"spell":{"duration":{"amount":null,"unit":"Aktionen"},"type":null,"property":null}},{"id":"freundschaftslied","name":"Freundschaftslied","attributes":["IN","CH","CH"],"modified_by":[],"cost":{"initial":null,"additional":{"amount":null,"interval":null,"unit":null}},"effect":{"description":"Mit dem Freundschaftslied können zwei Elfen, die es gemeinsam spielen, ein festes Band der Freundschaft zwischeneinander weben. Dies ist nur einmal im Leben eines Elfen möglich.Es besteht aus drei einstündigen Strophen, die an drei aufeinanderfolgenden Tagen von beiden gemeinsam gespielt werden müssen. So miteinander verbundene Elfen spüren die Anwesenheit des anderen und können starke Emotionen des anderen auch auf größere Entfernungen wahrnehmen. Sie können gegenseitig den Zauberspruch BALSAM aufeinander wirken, selbst wenn sie keine AsP zur Verfügung haben. In solchen Fällen können sie mit dem Zauberspruch ihre Lebensenergie direkt auf den anderen übertragen.","duration":{"amount":"","modifier":"","unit":null},"pulse":false,"instant":false},"talent":"musizieren","spell":{"duration":{"amount":null,"unit":"Aktionen"},"type":null,"property":null}},{"id":"friedenslied","name":"Friedenslied","attributes":["MU","IN","CH"],"modified_by":[],"cost":{"initial":null,"additional":{"amount":null,"interval":null,"unit":null}},"effect":{"description":"Nach 5 Minuten des Spielens erzeugt dieses Lied eine Zone des Friedens um den Elfen herum (QS x 3 Schritt Radius). So lange er weiterspielt, verlieren Tiere und kulturschaffende Wesen das Interesse daran, mit Gewalt gegeneinander oder gegen den Elfen vorzugehen. Um trotzdem aktiv zu kämpfen, ist eine Fertigkeitsprobe auf Willenskraft, erschwert durch die QS x 2 in der Probe auf das Friedenslied fällig. Die Möglichkeit, sich zu verteidigen, ist durch das Friedenslied nicht eingeschränkt. Nicht betroffen sind widernatürliche Wesenheiten wie Untote, Dämonen, Elementare oder Golems.","duration":{"amount":"","modifier":"","unit":null},"pulse":false,"instant":false},"talent":"musizieren","spell":{"duration":{"amount":8,"unit":"Aktionen"},"type":null,"property":null}},{"id":"zaubermelodie","name":"Zaubermelodie","attributes":["MU","IN","CH"],"modified_by":[],"cost":{"initial":8,"additional":{"amount":null,"interval":null,"unit":null}},"effect":{"description":"Spielt der Elf ungestört eine Stunde lang diese Melodie, kann er sich in einen tranceartigen Zustand versetzen, in dem er sich in Einklang mit den astralen Strömungen der Umgebung bringen kann. Er erwacht nach einer halben Stunde aus der Trance. Wenn er aus der Trance erwacht, sind für ihn alle Proben auf Zaubersprüche und Rituale bis zum nächsten Sonnenaufgang erleichtert. Bei QS 1-3 um 1, bei QS 4-6 um 2","duration":{"amount":"bis Sonnenaufgang","modifier":"bis Sonnenaufgang","unit":null},"pulse":false,"instant":false},"talent":"musizieren","spell":{"duration":{"amount":60,"unit":"Aktionen"},"type":null,"property":null}},{"id":"sorgenlied","name":"Sorgenlied","attributes":["MU","IN","IN"],"modified_by":[],"cost":{"initial":2,"additional":{"amount":null,"interval":null,"unit":null}},"effect":{"description":"Der Elf flicht Fragen in das Lied ein, die er an einen guten Freund stellen möchte. Hierdurch kann er erfahren, ob sein Freund gesund, krank oder gar tot ist, ob er um sein Leben fürchtet oder ob er zufrieden und glücklich ist. Mit dem Lied sind nur allgemeine Eindrücke zu erzielen. Klar formulierte Gedankenbilder lassen sich so nicht übertragen. Je weiter der gesuchte Freund vom Sänger entfernt ist, desto länger dauert das Lied. Pro 100 Meilen muss er 5 Minuten singen, um ihn zu erreichen.","duration":{"amount":"bis Sonnenaufgang","modifier":"bis Sonnenaufgang","unit":null},"pulse":false,"instant":false},"talent":"singen","spell":{"duration":{"amount":5,"unit":"Aktionen"},"type":null,"property":null}},{"id":"melodiederkunstfertigkeit","name":"Melodie der Kunstfertigkeit","attributes":["IN","IN","CH"],"modified_by":[],"cost":{"initial":4,"additional":{"amount":null,"interval":null,"unit":null}},"effect":{"description":"Proben auf Handwerkstalente, die der Elf während der Melodie der Kunstfertigkeit nutzt, sind um QS des Rituals erleichtert.","duration":{"amount":"bis Sonnenaufgang","modifier":"bis Sonnenaufgang","unit":null},"pulse":false,"instant":false},"talent":"singen","spell":{"duration":{"amount":5,"unit":"Aktionen"},"type":null,"property":null}},{"id":"lieddeszauberschutzes","name":"Lied des Zauberschutzes","attributes":["IN","CH","CH"],"modified_by":[],"cost":{"initial":6,"additional":{"amount":null,"interval":null,"unit":null}},"effect":{"description":"Der Elf verfügt über einen magischen Schutz, der regeltechnisch wie ein GARDIANUM wirkt. Der Schild ist allerdings nur auf seinen Körper beschränkt und hat eine Schildstärke von QS x 2. Der Schild hält, bis die Schildstärke auf 0 oder darunter gesunken ist, oder 30 Minuten vergangen sind (je nachdem, was zuerst eintritt).","duration":{"amount":"bis Sonnenaufgang","modifier":"bis Sonnenaufgang","unit":null},"pulse":false,"instant":false},"talent":"musizieren","spell":{"duration":{"amount":5,"unit":"Aktionen"},"type":null,"property":null}},{"id":"lieddeswindgefluesters","name":"Lied des Windgeflüsters","attributes":["IN","IN","CH"],"modified_by":[],"cost":{"initial":"4 AsP","additional":{"amount":null,"interval":null,"unit":null}},"effect":{"description":"Der Elf kann sich vom Wind Bilder, Töne und Stimmungen schicken lassen. Sie ergeben kein klares, zusammenhängendes Bild, aber unter den Eindrücken können sich Informationen befinden, die dem Elf bei einer persönlichen Frage weiterhelfen können. Bei der nächsten Probe auf ein Wissenstalent, das der Lösung dieser Frage dient, erhält der Elf bei Teilproben auf KL eine Erleichterung von QS/2.","duration":{"amount":"bis Sonnenaufgang","modifier":"bis Sonnenaufgang","unit":null},"pulse":false,"instant":false},"talent":"musizieren","spell":{"duration":{"amount":5,"unit":"Aktionen"},"type":null,"property":null}},{"id":"lieddestrostes","name":"Lied des Trostes","attributes":["IN","CH","CH"],"modified_by":[],"cost":{"initial":"3 AsP pro Zuhörer","additional":{"amount":null,"interval":null,"unit":null}},"effect":{"description":"Der Elf kann durch das Lied QS ausgewählten Zuhörern innerhalb einer Reichweite von 20 Schritt 1 Stufe Furcht nehmen.","duration":{"amount":"bis Sonnenaufgang","modifier":"bis Sonnenaufgang","unit":null},"pulse":false,"instant":false},"talent":"musizieren","spell":{"duration":{"amount":5,"unit":"Aktionen"},"type":null,"property":null}},{"id":"liedderabwehrdaemonischermaechte","name":"Lied der Abwehr dämonischer Mächte","attributes":["IN","CH","CH"],"modified_by":[],"cost":{"initial":"6 AsP","additional":{"amount":null,"interval":null,"unit":null}},"effect":{"description":"In einem Radius von 50 Schritt um den Elfen herum ist das Wirken von Zaubern oder magischen Handlungen mit dem Merkmal Dämonisch um QS erschwert. Die Wirkung dauert auch 10 Minuten nach dem Ende des Liedes noch an.","duration":{"amount":"10 Minuten nach Liedende.","modifier":"10 Minuten nach Liedende.","unit":null},"pulse":false,"instant":false},"talent":"musizieren","spell":{"duration":{"amount":5,"unit":"Aktionen"},"type":null,"property":null}},{"id":"lieddererholung","name":"Lied der Erholung","attributes":["IN","CH","CH"],"modified_by":[],"cost":{"initial":"3 AsP pro Zuhörer","additional":{"amount":null,"interval":null,"unit":null}},"effect":{"description":"Der Elf kann durch das Lied QS ausgewählten Zuhörern innerhalb einer Reichweite von 20 Schritt 1 Stufe Betäubung nehmen.","duration":{"amount":"","modifier":"","unit":null},"pulse":false,"instant":false},"talent":"musizieren","spell":{"duration":{"amount":5,"unit":"Aktionen"},"type":null,"property":null}},{"id":"liedderklarheit","name":"Lied der Klarheit","attributes":["IN","CH","CH"],"modified_by":[],"cost":{"initial":"3 AsP pro Zuhörer","additional":{"amount":null,"interval":null,"unit":null}},"effect":{"description":"Der Elf kann durch das Lied QS ausgewählten Zuhörern innerhalb einer Reichweite von 20 Schritt 1 Stufe Verwirrung nehmen.","duration":{"amount":"","modifier":"","unit":null},"pulse":false,"instant":false},"talent":"musizieren","spell":{"duration":{"amount":5,"unit":"Aktionen"},"type":null,"property":null}},{"id":"liedderlieder","name":"Lied der Lieder","attributes":["MU","IN","CH"],"modified_by":[],"cost":{"initial":"12 AsP","additional":{"amount":null,"interval":null,"unit":null}},"effect":{"description":"Nachdem der Elf 20 Minuten lang musiziert oder gesungen hat, sind alle Zuhörer mit einer Seelenkraft von 2 oder weniger im Bann des Liedes, welche sich in einem Radius von maximal 20 Schritt um den Elfen herum aufhalten. Die Zuhörer glauben, das Lied dauere noch QS Stunden an, auch wenn der Elf gar nicht mehr da ist. Während des Banns erhalten sie den Status Bewegungsunfähig. Sollte ein gebannter Zuhörer 1 SP oder mehr Schaden erleiden, fällt der Bann von ihm ab.","duration":{"amount":"","modifier":"","unit":null},"pulse":false,"instant":false},"talent":"musizieren","spell":{"duration":{"amount":20,"unit":"Aktionen"},"type":null,"property":null}},{"id":"liedderpflanzen","name":"Lied der Pflanzen","attributes":["IN","CH","CH"],"modified_by":[],"cost":{"initial":"2 AsP","additional":{"amount":null,"interval":null,"unit":null}},"effect":{"description":"Der Elf spielt das Lied für eine Pflanze. Pro QS erhöht sich die Haltbarkeit dieser Pflanze um 50 %.","duration":{"amount":"","modifier":"","unit":null},"pulse":false,"instant":false},"talent":"musizieren","spell":{"duration":{"amount":20,"unit":"Aktionen"},"type":null,"property":null}},{"id":"liedderreinheit","name":"Lied der Reinheit","attributes":["MU","IN","CH"],"modified_by":[],"cost":{"initial":"8 AsP pro 5 KR","additional":{"amount":null,"interval":null,"unit":null}},"effect":{"description":"Um den Elfen herum entsteht eine Zone von QS x 2 Schritt, die während der Wirkungsdauer Dämonen 1W6 SP pro KR zufügt. Dämonische Essenzen, etwa jene, die durch INVOCATIO MINOR gerufen wurden, werden augenblicklich in die Niederhöllen verbannt. Verseuchter und toter Boden, gleich durch welchem Umstand (Dämonen, Naturkatastrophe), wird nach dem Ende des Lieds in der Zone wieder fruchtbar.","duration":{"amount":"","modifier":"","unit":null},"pulse":false,"instant":false},"talent":"musizieren","spell":{"duration":{"amount":5,"unit":"Aktionen"},"type":null,"property":null}},{"id":"lieddertierwahrnehmung","name":"Lied der Tierwahrnehmung","attributes":["IN","CH","CH"],"modified_by":[],"cost":{"initial":"4 AsP pro Minute","additional":{"amount":null,"interval":null,"unit":null}},"effect":{"description":"In einem Radius von QS Meilen kann der Elf die Sinne von Tieren der Größenkategorie winzig nutzen, um die Gegend wahrzunehmen. Er kann dadurch z. B. sich nähernde Feinde wahrnehmen oder den Ort, an dem sich die Tiere befinden, einsehen. Im Zweifelsfall muss der Elf eine Probe auf Sinnesschärfe ablegen.","duration":{"amount":"","modifier":"","unit":null},"pulse":false,"instant":false},"talent":"musizieren","spell":{"duration":{"amount":5,"unit":"Aktionen"},"type":null,"property":null}},{"id":"lieddesheilschlafs","name":"Lied der Tierwahrnehmung","attributes":["IN","IN","CH"],"modified_by":[],"cost":{"initial":"8 AsP","additional":{"amount":null,"interval":null,"unit":null}},"effect":{"description":"QS Zuhörer in einem Radius von 20 Schritt erhalten bei ihrer nächsten Regenerationsphase +1 LeP und +1 AsP (letzteres nur, wenn sie Zauberer sind).","duration":{"amount":"","modifier":"","unit":null},"pulse":false,"instant":false},"talent":"singen","spell":{"duration":{"amount":5,"unit":"Aktionen"},"type":null,"property":null}},{"id":"arcanovi","name":"Arcanovi","attributes":["KL","IN","FF"],"modified_by":[],"cost":{"initial":16,"additional":{"amount":null,"interval":null,"unit":null}},"effect":{"description":"","duration":{"amount":"sofort","modifier":"sofort","unit":null},"pulse":false,"instant":false},"talent":null,"spell":{"duration":{"amount":8,"unit":"Aktionen"},"type":"Ritual","property":"Objekt"}},{"id":"dschinnenruf","name":"Dschinnruf","attributes":["MU","CH","KO"],"modified_by":[],"cost":{"initial":32,"additional":{"amount":null,"interval":null,"unit":null}},"effect":{"description":"","duration":{"amount":"sofort","modifier":"sofort","unit":null},"pulse":false,"instant":false},"talent":null,"spell":{"duration":{"amount":8,"unit":"Stunden"},"type":"Ritual","property":"Sphaeren"}},{"id":"elementarerdiener","name":"Elementarer Diener","attributes":["MU","CH","KO"],"modified_by":[],"cost":{"initial":16,"additional":{"amount":null,"interval":null,"unit":null}},"effect":{"description":"","duration":{"amount":"sofort","modifier":"sofort","unit":null},"pulse":false,"instant":false},"talent":null,"spell":{"duration":{"amount":30,"unit":"Minuten"},"type":"Ritual","property":"Sphaeren"}},{"id":"invocatiomanor","name":"Invocatio Manor","attributes":["MU","CH","KO"],"modified_by":[],"cost":{"initial":32,"additional":{"amount":null,"interval":null,"unit":null}},"effect":{"description":"","duration":{"amount":"sofort","modifier":"sofort","unit":null},"pulse":false,"instant":false},"talent":null,"spell":{"duration":{"amount":8,"unit":"Stunden"},"type":"Ritual","property":"Sphaeren"}},{"id":"invocatiominor","name":"Invocatio Minor","attributes":["MU","CH","KO"],"modified_by":[],"cost":{"initial":16,"additional":{"amount":null,"interval":null,"unit":null}},"effect":{"description":"","duration":{"amount":"sofort","modifier":"sofort","unit":null},"pulse":false,"instant":false},"talent":null,"spell":{"duration":{"amount":30,"unit":"Minuten"},"type":"Ritual","property":"Sphaeren"}},{"id":"zauberklingegeisterspeer","name":"Zauberklinge Geisterspeer","attributes":["KL","IN","FF"],"modified_by":[],"cost":{"initial":null,"additional":{"amount":null,"interval":null,"unit":null}},"effect":{"description":"","duration":{"amount":1,"modifier":"FP","unit":"Tage"},"pulse":false,"instant":false},"talent":null,"spell":{"duration":{"amount":8,"unit":"Stunden"},"type":"Ritual","property":"Objekt"}}] \ No newline at end of file diff --git a/package.json b/package.json index 831bb22..b373c33 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "dsabot", - "version": "1.1.0", + "version": "1.5.0", "description": "", "main": "index.js", "scripts": { @@ -9,7 +9,10 @@ "test": "jest" }, "_moduleAliases": { - "@dsabot": "functions" + "@dsabot": "functions", + "@data": "data", + "@Commands": "commands", + "@Lib": "lib" }, "author": "", "license": "ISC",