Triggers can fire on character sheet checks

This commit is contained in:
Stefan Zermatten
2022-08-12 19:52:58 +02:00
parent ecfeeaccd9
commit 13fc0c0b12
3 changed files with 73 additions and 34 deletions

View File

@@ -11,46 +11,18 @@ export default function applyTriggers(node, { creature, targets, scope, log }, t
const type = prop.type; const type = prop.type;
if (creature.triggers?.[type]?.[timing]) { if (creature.triggers?.[type]?.[timing]) {
creature.triggers[type][timing].forEach(trigger => { creature.triggers[type][timing].forEach(trigger => {
if (triggerMatchTags(trigger, prop)) { applyTrigger(trigger, { creature, prop, targets, scope, log });
applyTrigger(trigger, { creature, targets, scope, log });
}
}); });
} }
} }
function triggerMatchTags(trigger, prop) { export function applyTrigger(trigger, { creature, prop, targets, scope, log }) {
let matched = false; // If there is a prop we are applying the trigger from,
const propTags = getEffectivePropTags(prop); // don't fire if the tags don't match
// Check the target tags if (!triggerMatchTags(trigger, prop)) {
if ( return;
!trigger.targetTags?.length ||
difference(trigger.targetTags, propTags).length === 0
) {
matched = true;
} }
// Check the extra tags
trigger.extraTags?.forEach(extra => {
if (extra.operation === 'OR') {
if (matched) return;
if (
!extra.tags.length ||
difference(extra.tags, propTags).length === 0
) {
matched = true;
}
} else if (extra.operation === 'NOT') {
if (
extra.tags.length &&
intersection(extra.tags, propTags)
) {
return false;
}
}
});
return matched;
}
export function applyTrigger(trigger, { creature, targets, scope, log }) {
// Prevent trigger from firing if it's inactive // Prevent trigger from firing if it's inactive
if (trigger.inactive) { if (trigger.inactive) {
return; return;
@@ -102,3 +74,35 @@ export function applyTrigger(trigger, { creature, targets, scope, log }) {
trigger.firing = false; trigger.firing = false;
} }
function triggerMatchTags(trigger, prop) {
let matched = false;
const propTags = getEffectivePropTags(prop);
// Check the target tags
if (
!trigger.targetTags?.length ||
difference(trigger.targetTags, propTags).length === 0
) {
matched = true;
}
// Check the extra tags
trigger.extraTags?.forEach(extra => {
if (extra.operation === 'OR') {
if (matched) return;
if (
!extra.tags.length ||
difference(extra.tags, propTags).length === 0
) {
matched = true;
}
} else if (extra.operation === 'NOT') {
if (
extra.tags.length &&
intersection(extra.tags, propTags)
) {
return false;
}
}
});
return matched;
}

View File

@@ -3,10 +3,15 @@ import { ValidatedMethod } from 'meteor/mdg:validated-method';
import { RateLimiterMixin } from 'ddp-rate-limiter-mixin'; import { RateLimiterMixin } from 'ddp-rate-limiter-mixin';
import getRootCreatureAncestor from '/imports/api/creature/creatureProperties/getRootCreatureAncestor.js'; import getRootCreatureAncestor from '/imports/api/creature/creatureProperties/getRootCreatureAncestor.js';
import CreatureProperties from '/imports/api/creature/creatureProperties/CreatureProperties.js'; import CreatureProperties from '/imports/api/creature/creatureProperties/CreatureProperties.js';
import {
getPropertiesOfType, getVariables
} from '/imports/api/engine/loadCreatures.js';
import { groupBy, remove } from 'lodash';
import { CreatureLogSchema, insertCreatureLogWork } from '/imports/api/creature/log/CreatureLogs.js'; import { CreatureLogSchema, insertCreatureLogWork } from '/imports/api/creature/log/CreatureLogs.js';
import { assertEditPermission } from '/imports/api/creature/creatures/creaturePermissions.js'; import { assertEditPermission } from '/imports/api/creature/creatures/creaturePermissions.js';
import rollDice from '/imports/parser/rollDice.js'; import rollDice from '/imports/parser/rollDice.js';
import numberToSignedString from '/imports/ui/utility/numberToSignedString.js'; import numberToSignedString from '/imports/ui/utility/numberToSignedString.js';
import { applyTrigger } from '/imports/api/engine/actions/applyTriggers.js';
const doCheck = new ValidatedMethod({ const doCheck = new ValidatedMethod({
name: 'creatureProperties.doCheck', name: 'creatureProperties.doCheck',
@@ -45,12 +50,40 @@ export function doCheckWork({
creatureName: creature.name, creatureName: creature.name,
}); });
// Add the variables to the creature document
const variables = getVariables(creature._id);
delete variables._id;
delete variables._creatureId;
creature.variables = variables;
const scope = creature.variables;
// Get the triggers
let triggers = getPropertiesOfType(creature._id, 'trigger');
remove(triggers, trigger => trigger.event !== 'check');
triggers = groupBy(triggers, 'timing');
// Set the creature as the target
const targets = [creature];
applyTriggers(triggers, 'before', { creature, prop, targets, scope, log });
rollCheck({prop, log, methodScope}); rollCheck({prop, log, methodScope});
applyTriggers(triggers, 'after', { creature, prop, targets, scope, log });
// Insert the log // Insert the log
insertCreatureLogWork({log, creature, method}); insertCreatureLogWork({log, creature, method});
} }
function applyTriggers(triggers, timing, opts) {
// Get matching triggers
let selectedTriggers = triggers[timing] || [];
// Sort the triggers
selectedTriggers.sort((a, b) => a.order - b.order);
// Apply the triggers
selectedTriggers.forEach(trigger => {
applyTrigger(trigger, opts)
});
}
function rollCheck({prop, log, methodScope}){ function rollCheck({prop, log, methodScope}){
// get the modifier for the roll // get the modifier for the roll
let rollModifier; let rollModifier;

View File

@@ -5,6 +5,7 @@ import STORAGE_LIMITS from '/imports/constants/STORAGE_LIMITS.js';
const eventOptions = { const eventOptions = {
doActionProperty: 'Do action', doActionProperty: 'Do action',
// receiveActionProperty: 'Receiving action property', // receiveActionProperty: 'Receiving action property',
check: 'Roll check',
// flipToggle: 'Toggle changed', // flipToggle: 'Toggle changed',
// adjustProperty: 'Attribute adjusted', // adjustProperty: 'Attribute adjusted',
anyRest: 'Short or long rest', anyRest: 'Short or long rest',
@@ -26,6 +27,7 @@ const actionPropertyTypeOptions = {
note: 'Note', note: 'Note',
roll: 'Roll', roll: 'Roll',
savingThrow: 'Saving throw', savingThrow: 'Saving throw',
spell: 'Spell',
toggle: 'Toggle', toggle: 'Toggle',
} }