'use strict';
/**
* @property {string} attribute Attribute the damage is going to apply to
* @property {number} amount Initial amount of damage to be done
* @property {?Character} attacker Character causing the damage
* @property {*} source Where the damage came from: skill, item, room, etc.
* @property {Object} metadata Extra info about the damage: type, hidden, critical, etc.
*/
class Damage {
/**
* @param {string} attribute Attribute the damage is going to apply to
* @param {number} amount
* @param {Character} [attacker=null] Character causing the damage
* @param {*} [source=null] Where the damage came from: skill, item, room, etc.
* @property {Object} metadata Extra info about the damage: type, hidden, critical, etc.
*/
constructor(attribute, amount, attacker = null, source = null, metadata = {}) {
if (!Number.isFinite(amount)) {
throw new TypeError(`Damage amount must be a finite Number, got ${amount}.`);
}
if (typeof attribute !== 'string') {
throw new TypeError("Damage attribute name must be a string");
}
this.attacker = attacker;
this.attribute = attribute;
this.amount = amount;
this.source = source;
this.metadata = metadata;
}
/**
* Evaluate actual damage taking attacker/target's effects into account
* @param {Character} target
* @return {number} Final damage amount
*/
evaluate(target) {
let amount = this.amount;
if (this.attacker) {
amount = this.attacker.evaluateOutgoingDamage(this, amount, target);
}
return target.evaluateIncomingDamage(this, amount);
}
/**
* Actually lower the attribute
* @param {Character} target
* @fires Character#hit
* @fires Character#damaged
*/
commit(target) {
const finalAmount = this.evaluate(target);
target.lowerAttribute(this.attribute, finalAmount);
if (this.attacker) {
/**
* @event Character#hit
* @param {Damage} damage
* @param {Character} target
* @param {Number} finalAmount
*/
this.attacker.emit('hit', this, target, finalAmount);
}
/**
* @event Character#damaged
* @param {Damage} damage
* @param {Number} finalAmount
*/
target.emit('damaged', this, finalAmount);
}
}
module.exports = Damage;