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;
if (creature.triggers?.[type]?.[timing]) {
creature.triggers[type][timing].forEach(trigger => {
if (triggerMatchTags(trigger, prop)) {
applyTrigger(trigger, { creature, targets, scope, log });
}
applyTrigger(trigger, { creature, prop, targets, scope, log });
});
}
}
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;
export function applyTrigger(trigger, { creature, prop, targets, scope, log }) {
// If there is a prop we are applying the trigger from,
// don't fire if the tags don't match
if (!triggerMatchTags(trigger, prop)) {
return;
}
// 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
if (trigger.inactive) {
return;
@@ -102,3 +74,35 @@ export function applyTrigger(trigger, { creature, targets, scope, log }) {
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 getRootCreatureAncestor from '/imports/api/creature/creatureProperties/getRootCreatureAncestor.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 { assertEditPermission } from '/imports/api/creature/creatures/creaturePermissions.js';
import rollDice from '/imports/parser/rollDice.js';
import numberToSignedString from '/imports/ui/utility/numberToSignedString.js';
import { applyTrigger } from '/imports/api/engine/actions/applyTriggers.js';
const doCheck = new ValidatedMethod({
name: 'creatureProperties.doCheck',
@@ -45,12 +50,40 @@ export function doCheckWork({
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});
applyTriggers(triggers, 'after', { creature, prop, targets, scope, log });
// Insert the log
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}){
// get the modifier for the roll
let rollModifier;

View File

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