Added attribute damage and self damage results to actions and log.
This commit is contained in:
@@ -255,6 +255,7 @@ export function damagePropertyWork({property, operation, value}){
|
||||
}, {
|
||||
selector: property
|
||||
});
|
||||
return currentValue - damage;
|
||||
} else if (operation === 'increment'){
|
||||
let currentValue = property.value - (property.damage || 0);
|
||||
let currentDamage = property.damage;
|
||||
@@ -268,9 +269,47 @@ export function damagePropertyWork({property, operation, value}){
|
||||
}, {
|
||||
selector: property
|
||||
});
|
||||
return increment;
|
||||
}
|
||||
}
|
||||
|
||||
const damagePropertiesByName = new ValidatedMethod({
|
||||
name: 'CreatureProperties.damagePropertiesByName',
|
||||
validate: new SimpleSchema({
|
||||
creatureId: SimpleSchema.RegEx.Id,
|
||||
variableName: {
|
||||
type: String,
|
||||
},
|
||||
operation: {
|
||||
type: String,
|
||||
allowedValues: ['set', 'increment']
|
||||
},
|
||||
value: Number,
|
||||
}).validator(),
|
||||
mixins: [RateLimiterMixin],
|
||||
rateLimit: {
|
||||
numRequests: 20,
|
||||
timeInterval: 5000,
|
||||
},
|
||||
run({creatureId, variableName, operation, value}) {
|
||||
// Check permissions
|
||||
assertEditPermission(creatureId, this.userId);
|
||||
CreatureProperties.find({
|
||||
'ancestors.id': creatureId,
|
||||
variableName,
|
||||
removed: {$ne: false},
|
||||
inactive: {$ne: true},
|
||||
}).forEach(property => {
|
||||
// Check if property can take damage
|
||||
let schema = CreatureProperties.simpleSchema(property);
|
||||
if (!schema.allowsKey('damage')) return;
|
||||
// Damage the property
|
||||
damagePropertyWork({property: property, operation, value})
|
||||
});
|
||||
recomputeCreature.call({charId: creatureId});
|
||||
}
|
||||
})
|
||||
|
||||
const damageProperty = new ValidatedMethod({
|
||||
name: 'creatureProperties.damage',
|
||||
validate: new SimpleSchema({
|
||||
@@ -303,6 +342,58 @@ const damageProperty = new ValidatedMethod({
|
||||
},
|
||||
});
|
||||
|
||||
const dealDamage = new ValidatedMethod({
|
||||
name: 'creatureProperties.dealDamage',
|
||||
validate: new SimpleSchema({
|
||||
creatureId: SimpleSchema.RegEx.Id,
|
||||
damageType: {
|
||||
type: String,
|
||||
},
|
||||
amount: Number,
|
||||
}).validator(),
|
||||
mixins: [RateLimiterMixin],
|
||||
rateLimit: {
|
||||
numRequests: 20,
|
||||
timeInterval: 5000,
|
||||
},
|
||||
run({creatureId, damageType, amount}) {
|
||||
let creature = Creatures.findOne(creatureId, {
|
||||
fields: {
|
||||
damageMultipliers: 1,
|
||||
owner: 1,
|
||||
readers: 1,
|
||||
writers: 1,
|
||||
},
|
||||
});
|
||||
// Check permissions
|
||||
assertEditPermission(creatureId, this.userId);
|
||||
let healthBars = CreatureProperties.find({
|
||||
'ancestors.id': creatureId,
|
||||
type: 'attribute',
|
||||
attributeType:'healthBar',
|
||||
removed: {$ne: true},
|
||||
inactive: {$ne: true},
|
||||
}, {
|
||||
sort: {order: -1},
|
||||
});
|
||||
let multiplier = creature.damageMultipliers[damageType];
|
||||
if (multiplier === undefined) multiplier = 1;
|
||||
let totalDamage = Math.floor(amount * multiplier);
|
||||
let damageLeft = totalDamage;
|
||||
healthBars.forEach(healthBar => {
|
||||
if (damageLeft === 0) return;
|
||||
let damageAdded = damagePropertyWork({
|
||||
property: healthBar,
|
||||
operation: 'increment',
|
||||
value: damageLeft,
|
||||
});
|
||||
damageLeft -= damageAdded;
|
||||
});
|
||||
recomputeCreature.call({charId: creatureId});
|
||||
return totalDamage;
|
||||
},
|
||||
});
|
||||
|
||||
export function adjustQuantityWork({property, operation, value}){
|
||||
// Check if property has quantity
|
||||
let schema = CreatureProperties.simpleSchema(property);
|
||||
@@ -476,6 +567,8 @@ export {
|
||||
duplicateProperty,
|
||||
insertPropertyFromLibraryNode,
|
||||
updateProperty,
|
||||
dealDamage,
|
||||
damagePropertiesByName,
|
||||
damageProperty,
|
||||
adjustQuantity,
|
||||
selectAmmoItem,
|
||||
|
||||
56
app/imports/api/creature/actions/applyAdjustment.js
Normal file
56
app/imports/api/creature/actions/applyAdjustment.js
Normal file
@@ -0,0 +1,56 @@
|
||||
import evaluateString from '/imports/api/creature/computation/afterComputation/evaluateString.js';
|
||||
import {insertCreatureLog} from '/imports/api/creature/log/CreatureLogs.js';
|
||||
import { damagePropertiesByName } from '/imports/api/creature/CreatureProperties.js';
|
||||
|
||||
export default function applyAdjustment({
|
||||
prop,
|
||||
creature,
|
||||
targets,
|
||||
actionContext
|
||||
}){
|
||||
let damageTargets = prop.target === 'self' ? [creature] : targets;
|
||||
let scope = {
|
||||
...creature.variables,
|
||||
...actionContext,
|
||||
};
|
||||
try {
|
||||
var {result, errors} = evaluateString(prop.amount, scope, 'reduce');
|
||||
if (typeof result !== 'number') {
|
||||
return insertCreatureLog.call({ log: {
|
||||
text: errors.join(', ') || 'Something went wrong',
|
||||
creatureId: creature._id,
|
||||
}});
|
||||
}
|
||||
} catch (e){
|
||||
return insertCreatureLog.call({ log: {
|
||||
text: e.toString(),
|
||||
creatureId: creature._id,
|
||||
}});
|
||||
}
|
||||
if (damageTargets) {
|
||||
damageTargets.forEach(target => {
|
||||
if (prop.target === 'each'){
|
||||
result = evaluateString(prop.amount, scope, 'reduce');
|
||||
}
|
||||
damagePropertiesByName.call({
|
||||
creatureId: target._id,
|
||||
variableName: prop.stat,
|
||||
operation: prop.operation || 'increment',
|
||||
value: result
|
||||
});
|
||||
insertCreatureLog.call({
|
||||
log: {
|
||||
text: `${prop.stat} ${prop.operation === 'set' ? 'set to' : ''} ${-result}`,
|
||||
creatureId: target._id,
|
||||
}
|
||||
});
|
||||
});
|
||||
} else {
|
||||
insertCreatureLog.call({
|
||||
log: {
|
||||
text: `${prop.stat} ${prop.operation === 'set' ? 'set to' : ''} ${-result}`,
|
||||
creatureId: creature._id,
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -8,7 +8,7 @@ export default function applyAttack({
|
||||
//targets,
|
||||
//actionContext
|
||||
}){
|
||||
let result = roll(1, 20) + prop.rollBonusResult;
|
||||
let result = roll(1, 20)[0] + prop.rollBonusResult;
|
||||
insertCreatureLog.call({
|
||||
log: {
|
||||
text: `${prop.name} attack. ${result} to hit`,
|
||||
|
||||
@@ -1,27 +1,63 @@
|
||||
import evaluateString from '/imports/api/creature/computation/afterComputation/evaluateString.js';
|
||||
|
||||
//if (Meteor.isServer){
|
||||
// var sendWebhook = require('/imports/server/discord/webhook.js').default;
|
||||
//}
|
||||
import {insertCreatureLog} from '/imports/api/creature/log/CreatureLogs.js';
|
||||
import { dealDamage } from '/imports/api/creature/CreatureProperties.js';
|
||||
|
||||
export default function applyDamage({
|
||||
prop,
|
||||
creature,
|
||||
//targets,
|
||||
targets,
|
||||
actionContext
|
||||
}){
|
||||
//let damageTargets = prop.target === 'self' ? [creature] : targets;
|
||||
let damageTargets = prop.target === 'self' ? [creature] : targets;
|
||||
let scope = {
|
||||
...creature.variables,
|
||||
...actionContext,
|
||||
};
|
||||
let {result, errors} = evaluateString(prop.amount, scope, 'reduce');
|
||||
if (Meteor.isClient){
|
||||
errors.forEach(e => console.error(e));
|
||||
console.log(`${result} ${prop.damageType}${prop.damageType !== 'healing'? ' damage': ''}`);
|
||||
try {
|
||||
var {result, errors} = evaluateString(prop.amount, scope, 'reduce');
|
||||
if (typeof result !== 'number') {
|
||||
return insertCreatureLog.call({ log: {
|
||||
text: errors.join(', '),
|
||||
creatureId: creature._id,
|
||||
}});
|
||||
}
|
||||
} catch (e){
|
||||
return insertCreatureLog.call({ log: {
|
||||
text: e.toString(),
|
||||
creatureId: creature._id,
|
||||
}});
|
||||
}
|
||||
if (damageTargets) {
|
||||
damageTargets.forEach(target => {
|
||||
if (prop.target === 'each'){
|
||||
result = evaluateString(prop.amount, scope, 'reduce');
|
||||
}
|
||||
let damageDealt = dealDamage.call({
|
||||
creatureId: target._id,
|
||||
damageType: prop.damageType,
|
||||
amount: result,
|
||||
});
|
||||
insertCreatureLog.call({
|
||||
log: {
|
||||
text: `Recieved ${damageDealt} ${prop.damageType}${prop.damageType !== 'healing'? ' damage': ''}`,
|
||||
creatureId: target._id,
|
||||
}
|
||||
});
|
||||
if (target._id !== creature._id){
|
||||
insertCreatureLog.call({
|
||||
log: {
|
||||
text: `Dealt ${damageDealt} ${prop.damageType}${prop.damageType !== 'healing'? ' damage': ''}`,
|
||||
creatureId: creature._id,
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
} else {
|
||||
insertCreatureLog.call({
|
||||
log: {
|
||||
text: `${result} ${prop.damageType}${prop.damageType !== 'healing'? ' damage': ''}`,
|
||||
creatureId: creature._id,
|
||||
}
|
||||
});
|
||||
}
|
||||
//if (Meteor.isServer) sendWebhook({
|
||||
// webhook: creature.webhook,
|
||||
// message: `${result} ${prop.damageType}${prop.damageType !== 'healing'? ' damage': ''}`,
|
||||
//});
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import applyAction from '/imports/api/creature/actions/applyAction.js';
|
||||
import applyAdjustment from '/imports/api/creature/actions/applyAdjustment.js';
|
||||
import applyAttack from '/imports/api/creature/actions/applyAttack.js';
|
||||
import applyDamage from '/imports/api/creature/actions/applyDamage.js';
|
||||
import applyBuff from '/imports/api/creature/actions/applyBuff.js';
|
||||
@@ -26,7 +27,7 @@ function applyProperty(options){
|
||||
applyDamage(options);
|
||||
return true;
|
||||
case 'adjustment':
|
||||
// applyAdjustment(options);
|
||||
applyAdjustment(options);
|
||||
return true;
|
||||
case 'buff':
|
||||
applyBuff(options);
|
||||
|
||||
@@ -33,15 +33,15 @@ function combineAttribute(stat, aggregator, memo){
|
||||
stat.value = getAggregatorResult(stat, aggregator);
|
||||
stat.baseValue = aggregator.statBaseValue;
|
||||
stat.baseValueErrors = aggregator.baseValueErrors;
|
||||
if (stat.attributeType === 'ability') {
|
||||
stat.modifier = Math.floor((stat.value - 10) / 2);
|
||||
}
|
||||
if (stat.attributeType === 'spellSlot'){
|
||||
let {result, context} = evaluateCalculation(stat.spellSlotLevelCalculation, memo);
|
||||
stat.spellSlotLevelValue = result.value;
|
||||
stat.spellSlotLevelErrors = context.errors;
|
||||
}
|
||||
stat.currentValue = stat.value - (stat.damage || 0);
|
||||
if (stat.attributeType === 'ability') {
|
||||
stat.modifier = Math.floor((stat.currentValue - 10) / 2);
|
||||
}
|
||||
stat.hide = aggregator.hasNoEffects &&
|
||||
stat.baseValue === undefined ||
|
||||
undefined
|
||||
|
||||
@@ -67,43 +67,28 @@ function computeAction(prop, memo){
|
||||
});
|
||||
}
|
||||
|
||||
function computeAttack(prop, memo){
|
||||
// Roll bonus
|
||||
let {result, context} = evaluateCalculation(prop.rollBonus, memo);
|
||||
prop.rollBonusResult = result.value;
|
||||
function computePropertyField(prop, memo, fieldName, fn){
|
||||
let {result, context} = evaluateCalculation(prop[fieldName], memo, fn);
|
||||
prop[`${fieldName}Result`] = result.value;
|
||||
if (context.errors.length){
|
||||
prop.rollBonusErrors = context.errors;
|
||||
prop[`${fieldName}Errors`] = context.errors;
|
||||
} else {
|
||||
delete prop.rollBonusErrors;
|
||||
delete prop[`${fieldName}Errors`];
|
||||
}
|
||||
}
|
||||
|
||||
function computeAttack(prop, memo){
|
||||
computePropertyField(prop, memo, 'rollBonus');
|
||||
}
|
||||
|
||||
function computeSavingThrow(prop, memo){
|
||||
let {result, context} = evaluateCalculation(prop.dc, memo);
|
||||
prop.dcResult = result.value;
|
||||
if (context.errors.length){
|
||||
prop.dcErrors = context.errors;
|
||||
} else {
|
||||
delete prop.dcErrors;
|
||||
}
|
||||
computePropertyField(prop, memo, 'dc');
|
||||
}
|
||||
|
||||
function computeSpellList(prop, memo){
|
||||
let {result, context} = evaluateCalculation(prop.maxPrepared, memo);
|
||||
prop.maxPreparedResult = result.value;
|
||||
if (context.errors.length){
|
||||
prop.maxPreparedErrors = context.errors;
|
||||
} else {
|
||||
delete prop.maxPreparedErrors;
|
||||
}
|
||||
computePropertyField(prop, memo, 'maxPrepared');
|
||||
}
|
||||
|
||||
function computeSlot(prop, memo){
|
||||
let {result, context} = evaluateCalculation(prop.slotCondition, memo);
|
||||
prop.slotConditionResult = result.value;
|
||||
if (context.errors.length){
|
||||
prop.slotConditionErrors = context.errors;
|
||||
} else {
|
||||
delete prop.slotConditionErrors;
|
||||
}
|
||||
computePropertyField(prop, memo, 'slotCondition');
|
||||
}
|
||||
|
||||
@@ -23,6 +23,11 @@ const AdjustmentSchema = new SimpleSchema({
|
||||
type: String,
|
||||
optional: true,
|
||||
},
|
||||
operation: {
|
||||
type: String,
|
||||
allowedValues: ['set', 'increment'],
|
||||
defaultValue: 'increment',
|
||||
},
|
||||
});
|
||||
|
||||
export { AdjustmentSchema };
|
||||
|
||||
@@ -6,7 +6,9 @@
|
||||
<v-list-tile-action class="mr-4">
|
||||
<div class="display-1 mod">
|
||||
<template v-if="swapScoresAndMods">
|
||||
{{ model.value }}
|
||||
<span :class="{'primary--text': model.currentValue !== model.value}">
|
||||
{{ model.currentValue }}
|
||||
</span>
|
||||
</template>
|
||||
<template v-else>
|
||||
{{ numberToSignedString(model.modifier) }}
|
||||
@@ -17,7 +19,9 @@
|
||||
{{ numberToSignedString(model.modifier) }}
|
||||
</template>
|
||||
<template v-else>
|
||||
{{ model.value }}
|
||||
<span :class="{'primary--text': model.currentValue !== model.value}">
|
||||
{{ model.currentValue }}
|
||||
</span>
|
||||
</template>
|
||||
</div>
|
||||
</v-list-tile-action>
|
||||
|
||||
@@ -19,6 +19,15 @@
|
||||
@change="change('amount', ...arguments)"
|
||||
/>
|
||||
</div>
|
||||
<smart-select
|
||||
label="Operation"
|
||||
class="mx-1"
|
||||
style="flex-basis: 300px;"
|
||||
:items="adjustmentOps"
|
||||
:value="model.operation"
|
||||
:error-messages="errors.operation"
|
||||
@change="change('operation', ...arguments)"
|
||||
/>
|
||||
<smart-select
|
||||
v-if="parentTarget !== 'self'"
|
||||
label="Target"
|
||||
@@ -52,6 +61,12 @@ export default {
|
||||
default: undefined,
|
||||
},
|
||||
},
|
||||
data(){return {
|
||||
adjustmentOps: [
|
||||
{text: 'Damage', value: 'increment'},
|
||||
{text: 'Set', value: 'set'},
|
||||
],
|
||||
}},
|
||||
computed: {
|
||||
targetOptions(){
|
||||
if (this.parentTarget === 'singleTarget') {
|
||||
|
||||
Reference in New Issue
Block a user