Triggers can fire on character sheet checks
This commit is contained in:
@@ -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;
|
||||||
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user