116 lines
3.2 KiB
JavaScript
116 lines
3.2 KiB
JavaScript
import evaluateString from '/imports/api/creature/computation/afterComputation/evaluateString.js';
|
|
import dealDamage from '/imports/api/creature/creatureProperties/methods/dealDamage.js';
|
|
import {insertCreatureLog} from '/imports/api/creature/log/CreatureLogs.js';
|
|
import { CompilationContext } from '/imports/parser/parser.js';
|
|
|
|
export default function applyDamage({
|
|
prop,
|
|
creature,
|
|
targets,
|
|
actionContext,
|
|
log,
|
|
}){
|
|
let damageTargets = prop.target === 'self' ? [creature] : targets;
|
|
let scope = {
|
|
...creature.variables,
|
|
...actionContext,
|
|
};
|
|
// Add the target's variables to the scope
|
|
if (targets.length === 1){
|
|
scope.target = targets[0].variables;
|
|
}
|
|
// Determine if the hit is critical
|
|
let criticalHit = !!(
|
|
actionContext.criticalHit &&
|
|
actionContext.criticalHit.value &&
|
|
prop.damageType !== 'healing' // Can't critically heal
|
|
);
|
|
// Double the damage rolls if the hit is critical
|
|
let context = new CompilationContext({
|
|
doubleRolls: criticalHit,
|
|
});
|
|
|
|
// Compute the roll the first time, logging any errors
|
|
var {result} = evaluateString({
|
|
string: prop.amount,
|
|
scope,
|
|
fn: 'reduce',
|
|
context
|
|
});
|
|
|
|
// If the result is an error bail out now
|
|
if (result.constructor.name === 'ErrorNode'){
|
|
log.content.push({
|
|
name: 'Damage error',
|
|
value: result.toString(),
|
|
});
|
|
return;
|
|
}
|
|
|
|
// Memoise the damage suffix for the log
|
|
let suffix = (criticalHit ? ' critical ' : ' ') +
|
|
prop.damageType +
|
|
(prop.damageType !== ' healing ' ? ' damage ': '');
|
|
|
|
if (damageTargets && damageTargets.length) {
|
|
// Iterate through all the targets
|
|
damageTargets.forEach(target => {
|
|
let name = prop.damageType === 'healing' ? 'Healing' : 'Damage';
|
|
|
|
// Reroll the damage if needed
|
|
if (prop.target === 'each'){
|
|
({result, context} = evaluateString({
|
|
string: prop.amount,
|
|
scope,
|
|
fn: 'reduce'
|
|
}));
|
|
}
|
|
// If the result is an error or not a number bail out now
|
|
if (result.constructor.name === 'ErrorNode' || !result.isNumber){
|
|
log.content.push({
|
|
name: 'Damage error',
|
|
value: result.toString(),
|
|
});
|
|
return;
|
|
}
|
|
|
|
// Deal the damage to the target
|
|
let damageDealt = dealDamage.call({
|
|
creatureId: target._id,
|
|
damageType: prop.damageType,
|
|
amount: result.value,
|
|
});
|
|
|
|
// Log the damage done
|
|
if (target._id === creature._id){
|
|
// Target is same as self, log damage as such
|
|
log.content.push({
|
|
name,
|
|
value: damageDealt + suffix + ' to self',
|
|
});
|
|
} else {
|
|
log.content.push({
|
|
name,
|
|
value: 'Dealt ' + damageDealt + suffix + ` ${target.name && ' to '}${target.name}`,
|
|
});
|
|
// Log the damage received on that creature's log as well
|
|
insertCreatureLog.call({
|
|
log: {
|
|
creatureId: target._id,
|
|
content: [{
|
|
name,
|
|
value: 'Recieved ' + damageDealt + suffix,
|
|
}],
|
|
}
|
|
});
|
|
}
|
|
});
|
|
} else {
|
|
// There are no targets, just log the result
|
|
log.content.push({
|
|
name: prop.damageType === 'healing' ? 'Healing' : 'Damage',
|
|
value: result.toString() + suffix,
|
|
});
|
|
}
|
|
}
|