Changed how before and after triggers are handled

This commit is contained in:
ThaumRystra
2023-11-25 11:59:32 +02:00
parent f676dfd928
commit 24438d5a92

View File

@@ -37,6 +37,7 @@ interface BaseTask {
interface PropTask extends BaseTask {
step?: number,
subtaskFn?: undefined,
beforeTriggersDone?: undefined | true;
}
interface DamagePropTask extends BaseTask {
@@ -322,12 +323,29 @@ async function applyNextTask(action: Action, userInput?) {
if (!prop) throw new Meteor.Error('Not found', 'Property could not be found');
if (prop.deactivatedByToggle) return;
// Before triggers
const tasks: PropTask[] = [];
if (!task.beforeTriggersDone && prop.triggerIds?.before?.length) {
// Push the before triggers
forEach(prop.triggerIds?.before, triggerId => {
tasks.push({ propId: triggerId, targetIds: task.targetIds });
});
doNext(action, [
...tasks,
{ ...task, beforeTriggersDone: true },
]);
return;
}
// Apply the property
result = await applyPropertyByType[prop.type]?.(prop, task, action, userInput);
// store the task's details and save the result
// Because we recomputed the property in the action context, store the whole thing,
// rather than just a reference to it
result.scope[`#${prop.type}`] = prop;
// After triggers
// Because each property might change its targets, it is responsible for its own after triggers
}
action.results.push({
...result,
@@ -400,19 +418,66 @@ function afterChildrenTriggerTasks(prop, targetIds) {
}
/**
* Get the child and after children tasks for a given property
* Returns a list of tasks containing the following:
* After triggers
* Children of the prop
* After-children triggers
* @param action
* @param prop
* @param targetIds
* @returns
*/
async function childAndTriggerTasks(action, prop, targetIds) {
async function defaultAfterPropTasks(action, prop, targetIds) {
return [
...afterTriggerTasks(prop, targetIds),
...await childTasks(action, prop, targetIds),
...afterChildrenTriggerTasks(prop, targetIds)
]
}
/**
* Returns a list of tasks containing the following:
* After triggers
* After-children triggers
* @param action
* @param prop
* @param targetIds
* @returns
*/
function skipChildrenTasks(prop, targetIds) {
return [
...afterTriggerTasks(prop, targetIds),
...afterChildrenTriggerTasks(prop, targetIds)
]
}
/**
* Returns a list of tasks containing the following:
* After triggers
* After-children triggers
* @param action
* @param prop
* @param targetIds
* @returns
*/
function singleChildTask(prop, targetIds, childProp) {
return [
...afterTriggerTasks(prop, targetIds),
...propTasks(childProp, targetIds),
...afterChildrenTriggerTasks(prop, targetIds)
]
}
function afterTriggerTasks(prop, targetIds) {
const tasks: PropTask[] = [];
// Push the after triggers
forEach(prop.triggerIds?.after, triggerId => {
tasks.push({ propId: triggerId, targetIds });
});
return tasks;
}
/**
* Get all the trigger tasks for a given trigger path
* @param action
@@ -439,22 +504,7 @@ function triggerTasks(action: Action, prop, targetIds: string[], triggerPath: st
* @returns Returns [before triggers, prop, after triggers] tasks
*/
export function propTasks(prop, targetIds?) {
const tasks: Task[] = [];
// Push the before triggers
forEach(prop.triggerIds?.before, triggerId => {
tasks.push({ propId: triggerId, targetIds });
});
// Push the prop task
tasks.push({ propId: prop._id, targetIds });
// Push the after triggers
forEach(prop.triggerIds?.after, triggerId => {
tasks.push({ propId: triggerId, targetIds });
});
return tasks;
return [{ propId: prop._id, targetIds }];
}
/**
@@ -465,8 +515,6 @@ export function propTasks(prop, targetIds?) {
*/
function perTargetTasks(task: PropTask, targetIds: string[] = task.targetIds) {
const tasks: Task[] = [];
// Keep propId
const propId = task.propId;
// Increment step
const step = (task.step || 0) + 1;
@@ -474,7 +522,7 @@ function perTargetTasks(task: PropTask, targetIds: string[] = task.targetIds) {
// If there are targets, apply a new task to each target
for (const targetId of targetIds) {
tasks.push({
propId,
...task,
step,
targetIds: [targetId],
});
@@ -482,7 +530,7 @@ function perTargetTasks(task: PropTask, targetIds: string[] = task.targetIds) {
} else {
// Otherwise just do the next step
tasks.push({
propId,
...task,
step,
targetIds,
});
@@ -553,8 +601,7 @@ export function getEffectiveActionScope(action: Action) {
function doNextStep(action, task) {
doNext(action, [{
propId: task.propId,
targetIds: task.targetIds,
...task,
step: (task.step || 0) + 1,
}]);
}
@@ -624,7 +671,7 @@ const applyPropertyByType = {
// TODO
// Push children tasks
tasks.push(...await childAndTriggerTasks(action, prop, task.targetIds));
tasks.push(...await defaultAfterPropTasks(action, prop, task.targetIds));
doNext(action, tasks);
return result;
}
@@ -636,8 +683,8 @@ const applyPropertyByType = {
const damageTargetIds = prop.target === 'self' ? [action.creatureId] : task.targetIds;
const queueChildren = async function () {
doNext(action, await childAndTriggerTasks(action, prop, damageTargetIds));
const queueNext = async function () {
doNext(action, await defaultAfterPropTasks(action, prop, damageTargetIds));
}
// Step 0, split the task
@@ -650,7 +697,7 @@ const applyPropertyByType = {
else if (task.step === 1) {
if (!prop.amount) {
queueChildren();
queueNext();
return result;
}
@@ -658,7 +705,7 @@ const applyPropertyByType = {
recalculateCalculation(prop.amount, action, 'reduce');
const value = +prop.amount.value;
if (!isFinite(value)) {
queueChildren();
queueNext();
return result;
}
@@ -715,7 +762,7 @@ const applyPropertyByType = {
},
},
...triggerTasks(action, stat, damageTargetIds, 'damageProperty.after'),
...await childAndTriggerTasks(action, prop, damageTargetIds)
...await defaultAfterPropTasks(action, prop, damageTargetIds)
]);
return result;
}
@@ -734,9 +781,9 @@ const applyPropertyByType = {
case 'if': {
recalculateCalculation(prop.condition, action, 'reduce');
if (prop.condition?.value) {
doNext(action, await childAndTriggerTasks(action, prop, targets));
doNext(action, await defaultAfterPropTasks(action, prop, targets));
} else {
doNext(action, afterChildrenTriggerTasks(action, prop));
doNext(action, skipChildrenTasks(prop, targets));
}
return result;
}
@@ -749,19 +796,17 @@ const applyPropertyByType = {
name: 'Branch Error',
value: 'Index did not resolve into a valid number'
}, targets);
doNext(action, afterChildrenTriggerTasks(prop, targets));
doNext(action, skipChildrenTasks(prop, targets));
return result;
}
let index = Math.floor(prop.condition?.value);
if (index < 1) index = 1;
if (index > children.length) index = children.length;
doNext(action, [
...propTasks(children[index - 1], targets),
...afterChildrenTriggerTasks(prop, targets),
]);
const child = children[index - 1];
doNext(action, singleChildTask(prop, targets, child));
return result;
}
doNext(action, afterChildrenTriggerTasks(prop, targets));
doNext(action, skipChildrenTasks(prop, targets));
return result;
}
case 'hit': {
@@ -772,9 +817,9 @@ const applyPropertyByType = {
value: '**On hit**'
}, targets);
}
doNext(action, await childAndTriggerTasks(action, prop, targets));
doNext(action, await defaultAfterPropTasks(action, prop, targets));
} else {
doNext(action, afterChildrenTriggerTasks(action, prop));
doNext(action, skipChildrenTasks(prop, targets));
}
return result;
}
@@ -786,9 +831,9 @@ const applyPropertyByType = {
value: '**On miss**'
}, targets);
}
doNext(action, await childAndTriggerTasks(action, prop, targets));
doNext(action, await defaultAfterPropTasks(action, prop, targets));
} else {
doNext(action, afterChildrenTriggerTasks(action, prop));
doNext(action, skipChildrenTasks(prop, targets));
}
return result;
}
@@ -800,9 +845,9 @@ const applyPropertyByType = {
value: '**On failed save**'
}, targets);
}
doNext(action, await childAndTriggerTasks(action, prop, targets));
doNext(action, await defaultAfterPropTasks(action, prop, targets));
} else {
doNext(action, afterChildrenTriggerTasks(action, prop));
doNext(action, skipChildrenTasks(prop, targets));
}
return result;
}
@@ -814,22 +859,20 @@ const applyPropertyByType = {
value: '**On save**'
}, targets);
}
doNext(action, await childAndTriggerTasks(action, prop, targets));
doNext(action, await defaultAfterPropTasks(action, prop, targets));
} else {
doNext(action, afterChildrenTriggerTasks(action, prop));
doNext(action, skipChildrenTasks(prop, targets));
}
return result;
}
case 'random': {
const children = await getPropertyChildren(action.creatureId, prop._id);
if (children.length) {
const index = rollDice(1, children.length)[0] - 1;
doNext(action, [
...propTasks(children[index - 1], targets),
...afterChildrenTriggerTasks(prop, targets),
]);
const index = rollDice(1, children.length)[0];
const child = children[index - 1];
doNext(action, singleChildTask(prop, targets, child));
} else {
doNext(action, afterChildrenTriggerTasks(action, prop));
doNext(action, skipChildrenTasks(action, prop));
}
return result;
}
@@ -851,13 +894,15 @@ const applyPropertyByType = {
throw 'User input was required for this step'
}
const children = await getPropertyChildren(action.creatureId, prop._id);
if (!children.length) {
doNext(action, skipChildrenTasks(action, prop));
return result;
}
let index = userInput.choice;
if (!isFinite(index) || index < 0) index = 0;
if (index > children.length - 1) index = children.length - 1;
doNext(action, [
...propTasks(children[index], targets),
...afterChildrenTriggerTasks(prop, targets),
]);
const child = children[index];
doNext(action, singleChildTask(prop, targets, child));
return result;
}
}
@@ -867,7 +912,7 @@ const applyPropertyByType = {
async folder(prop, task: PropTask, action: Action): Promise<PartialTaskResult> {
const result = createResult();
doNext(action, await childAndTriggerTasks(action, prop, task.targetIds));
doNext(action, await defaultAfterPropTasks(action, prop, task.targetIds));
return result;
},
@@ -897,7 +942,7 @@ const applyPropertyByType = {
});
}
doNext(action, await childAndTriggerTasks(action, prop, task.targetIds));
doNext(action, await defaultAfterPropTasks(action, prop, task.targetIds));
return result;
},
@@ -906,7 +951,7 @@ const applyPropertyByType = {
// If there isn't a calculation, just apply the children instead
if (!prop.roll?.calculation) {
doNext(action, await childAndTriggerTasks(action, prop, task.targetIds));
doNext(action, await defaultAfterPropTasks(action, prop, task.targetIds));
return result;
}
@@ -935,7 +980,7 @@ const applyPropertyByType = {
// If we didn't end up with a constant or a number of finite value, give up
if (reduced?.parseType !== 'constant' || (reduced.valueType === 'number' && !isFinite(reduced.value))) {
doNext(action, await childAndTriggerTasks(action, prop, task.targetIds));
doNext(action, await defaultAfterPropTasks(action, prop, task.targetIds));
return result;
}
const value = reduced.value;
@@ -951,7 +996,7 @@ const applyPropertyByType = {
}, task.targetIds);
// Apply children
doNext(action, await childAndTriggerTasks(action, prop, task.targetIds));
doNext(action, await defaultAfterPropTasks(action, prop, task.targetIds));
return result;
},
}