Files
dsabot/commands/Attack.js
TobenderZephyr c6cacdae5e switched nedb to nedb-promises (#37)
* breaking change: switched to nedb-promises
* Linting
* some dev dependencies
* more tests
* updated package version
* bug fixing
* changed isNaN to isString
* (fix) args[0]
2021-05-03 18:39:33 +02:00

163 lines
5.5 KiB
JavaScript

require('module-alias/register');
const { roll } = require('@dsabot/Roll');
const { findMessage } = require('@dsabot/findMessage');
const { isEmpty } = require('@dsabot/isEmpty');
const { db } = require('../globals');
const { CombatTechniques } = require('../globals');
const { Werte } = require('../globals');
const { Weapons } = require('../globals');
const { MeleeWeapons } = require('../globals');
function getCombatTechnique(Weapon) {
if (Weapon) return CombatTechniques.find(technique => technique.id === Weapon.combattechnique);
return null;
}
function getAttribute(abbr) {
return Werte.find(attribute => attribute.kuerzel === abbr);
}
function CompareAttackResult(dice = [8, 8], Comparison = 6) {
let ok = false;
let crit = false;
let dd = false;
let fumble = false;
dice.forEach((val, index) => {
if (index === 0) {
ok = val <= Comparison ? true : false;
crit = val === 1 ? true : false;
fumble = val === 20 ? true : false;
if ((ok && !crit) || (!ok && !fumble)) {
dice.pop();
}
}
if (index === 1) {
dd = crit && val < Comparison ? true : false;
fumble = !crit && val > Comparison ? true : false;
}
});
return {
Ok: ok,
Patzer: fumble,
CriticalHit: crit,
DoubleDamage: dd,
Dice: dice,
};
}
function getAttributeLevel(Player = {}, Attribute = '') {
return Player.attributes.find(a => a.id === Attribute).level;
}
function getCombatTechniqueLevel(Player = {}, CombatTechnique = {}) {
if (Player && CombatTechnique) {
const p = Player.combattechniques.find(technique => technique.id === CombatTechnique.id);
return {
id: CombatTechnique.id,
name: CombatTechnique.name,
level: p ? p.level : 6,
Leiteigenschaft: CombatTechnique.Leiteigenschaft,
};
}
return null;
}
function getWeapon(Weapon = '') {
return Weapons.find(
w => w.id === Weapon.toLowerCase() || w.name.toLowerCase() === Weapon.toLowerCase()
);
}
function isMeleeWeapon(Weapon) {
if (MeleeWeapons.find(MeleeWeapon => MeleeWeapon.id === Weapon.id)) return true;
return false;
}
function handleAttack(doc, { message, args }) {
if (isEmpty(doc)) {
return message.reply(findMessage('NOENTRY'));
}
const Player = doc.character;
const Weapon = getWeapon(args[0]);
if (!Weapon) {
return message.reply(findMessage('NO_SUCH_WEAPON'));
}
// Determining Both Attack and Ranged Attack Values.
const CombatTechnique = getCombatTechniqueLevel(Player, getCombatTechnique(Weapon)); //?+
const Attribute = isMeleeWeapon(Weapon)
? getAttributeLevel(Player, 'mut')
: getAttributeLevel(Player, 'fingerfertigkeit');
let AttackValue = isMeleeWeapon(Weapon)
? CombatTechnique.level + Weapon.at_mod
: CombatTechnique.level;
AttackValue += Math.floor((Attribute - 8) / 3);
const { dice } = roll(2, 20);
const Bonus = parseInt(args[1], 10) || 0;
const Comparison = Math.floor(AttackValue + Bonus);
const AttackResult = CompareAttackResult(dice, Comparison);
let Reply = `Du greifst mit ${Weapon.name} an.\n Dein Angriffswert für ${CombatTechnique.name} ist ${AttackValue} (KtW: ${CombatTechnique.level})\n`;
Reply += `Deine 🎲: \` ${AttackResult.Dice.join(', ')} \`\n\n`;
Reply += !AttackResult.Ok ? findMessage('COMBAT_FAIL') : findMessage('COMBAT_SUCCESS');
Reply += AttackResult.Patzer ? findMessage('COMBAT_CRIT_FAIL') : '';
Reply += AttackResult.CriticalHit ? findMessage('COMBAT_CRIT_SUCCESS') : '';
Reply += AttackResult.DoubleDamage ? findMessage('COMBAT_DOUBLEDAMAGE') : '';
if (AttackResult.Ok) {
// adding 1 to damage for every point above weapon's "Leiteigenschaft"
// applies only to Melee Weapons.
let AttackBonus = 0;
if (isMeleeWeapon(Weapon) && Weapon.DmgThreshold) {
CombatTechnique.Leiteigenschaft.forEach(abbr => {
const attrib = getAttribute(abbr);
const AttributeValue = getAttributeLevel(Player, attrib.id);
if (Weapon.DmgThreshold < AttributeValue) {
AttackBonus += Math.floor(AttributeValue - Weapon.DmgThreshold);
}
});
}
const DamageDice = roll(1, 6).dice;
let Damage = Weapon.diemodificator + AttackBonus + DamageDice.reduce((p, v) => p + v);
Damage = AttackResult.DoubleDamage ? (Damage *= 2) : Damage;
Reply += '\n\nHier aufklappen, wenn der Gegner nicht parieren/Ausweichen konnte:\n';
Reply += `||\n`;
Reply += ` ${Weapon.name} (${Weapon.dice}W6+${
Weapon.diemodificator
}) richtet ${Damage} schaden an. ${
AttackBonus ? `(+${AttackBonus} Bonus auf Leiteigenschaft)` : ''
}`;
Reply += `\nDeine 🎲: ${DamageDice.join(', ')}\n||\n`;
}
return message.reply(Reply);
}
module.exports = {
name: 'attack',
description: 'Würfelt den Attackewert auf eine Nahkampfwaffe.',
aliases: ['angriff', 'attacke'],
usage: '<Waffe>',
needs_args: true,
async exec(message, args) {
db.findOne({ user: message.author.tag })
.then(doc => {
handleAttack(doc, { message, args });
})
.catch(err => {
message.reply(findMessage('ERROR'));
throw new Error(err);
});
},
};