132 lines
5.4 KiB
TypeScript
132 lines
5.4 KiB
TypeScript
import { filter } from 'lodash';
|
|
import { EngineAction } from '/imports/api/engine/action/EngineActions';
|
|
import InputProvider from '/imports/api/engine/action/functions/userInput/InputProvider';
|
|
import { applyAfterPropTasksForSingleChild, applyAfterPropTasksForSomeChildren, applyAfterTasksSkipChildren, applyDefaultAfterPropTasks, applyTaskToEachTarget } from '/imports/api/engine/action/functions/applyTaskGroups';
|
|
import { getEffectiveActionScope } from '/imports/api/engine/action/functions/getEffectiveActionScope';
|
|
import recalculateCalculation from '/imports/api/engine/action/functions/recalculateCalculation';
|
|
import { PropTask } from '/imports/api/engine/action/tasks/Task';
|
|
import TaskResult from '/imports/api/engine/action/tasks/TaskResult';
|
|
import { getPropertyChildren } from '/imports/api/engine/loadCreatures';
|
|
|
|
export default async function applyBranchProperty(
|
|
task: PropTask, action: EngineAction, result: TaskResult, userInput: InputProvider
|
|
): Promise<void> {
|
|
const prop = task.prop;
|
|
const targets = task.targetIds;
|
|
|
|
switch (prop.branchType) {
|
|
case 'if': {
|
|
await recalculateCalculation(prop.condition, action, 'reduce', userInput);
|
|
if (prop.condition?.value) {
|
|
return applyDefaultAfterPropTasks(action, prop, targets, userInput);
|
|
} else {
|
|
return applyAfterTasksSkipChildren(action, prop, targets, userInput);
|
|
}
|
|
}
|
|
case 'index': {
|
|
const children = await getPropertyChildren(action.creatureId, prop);
|
|
if (!children.length) {
|
|
return applyAfterTasksSkipChildren(action, prop, targets, userInput);
|
|
}
|
|
await recalculateCalculation(prop.condition, action, 'reduce', userInput);
|
|
if (!isFinite(prop.condition?.value)) {
|
|
result.appendLog({
|
|
name: 'Branch Error',
|
|
value: `Index did not resolve into a valid number, got \`${prop.condition?.value}\` instead`,
|
|
silenced: prop.silent,
|
|
}, targets);
|
|
return applyAfterTasksSkipChildren(action, prop, targets, userInput);
|
|
}
|
|
let index = Math.floor(prop.condition?.value);
|
|
if (index < 1) index = 1;
|
|
if (index > children.length) index = children.length;
|
|
const child = children[index - 1];
|
|
return applyAfterPropTasksForSingleChild(action, prop, child, targets, userInput);
|
|
}
|
|
case 'hit': {
|
|
const scope = await getEffectiveActionScope(action);
|
|
if (scope['~attackHit']?.value) {
|
|
if (!targets.length && !prop.silent) {
|
|
result.appendLog({
|
|
value: '**On hit**',
|
|
silenced: prop.silent,
|
|
}, targets);
|
|
}
|
|
return applyDefaultAfterPropTasks(action, prop, targets, userInput);
|
|
} else {
|
|
return applyAfterTasksSkipChildren(action, prop, targets, userInput);
|
|
}
|
|
}
|
|
case 'miss': {
|
|
const scope = await getEffectiveActionScope(action);
|
|
if (scope['~attackMiss']?.value) {
|
|
if (!targets.length && !prop.silent) {
|
|
result.appendLog({
|
|
value: '**On miss**',
|
|
silenced: prop.silent,
|
|
}, targets);
|
|
}
|
|
return applyDefaultAfterPropTasks(action, prop, targets, userInput);
|
|
} else {
|
|
return applyAfterTasksSkipChildren(action, prop, targets, userInput);
|
|
}
|
|
}
|
|
case 'failedSave': {
|
|
const scope = await getEffectiveActionScope(action);
|
|
if (scope['~saveFailed']?.value) {
|
|
if (!targets.length && !prop.silent) {
|
|
result.appendLog({
|
|
value: '**On failed save**',
|
|
silenced: prop.silent,
|
|
}, targets);
|
|
}
|
|
return applyDefaultAfterPropTasks(action, prop, targets, userInput);
|
|
} else {
|
|
return applyAfterTasksSkipChildren(action, prop, targets, userInput);
|
|
}
|
|
}
|
|
case 'successfulSave': {
|
|
const scope = await getEffectiveActionScope(action);
|
|
if (scope['~saveSucceeded']?.value) {
|
|
if (!targets.length && !prop.silent) {
|
|
result.appendLog({
|
|
value: '**On save**',
|
|
silenced: prop.silent,
|
|
}, targets);
|
|
}
|
|
return applyDefaultAfterPropTasks(action, prop, targets, userInput);
|
|
} else {
|
|
return applyAfterTasksSkipChildren(action, prop, targets, userInput);
|
|
}
|
|
}
|
|
case 'random': {
|
|
const children = await getPropertyChildren(action.creatureId, prop);
|
|
if (children.length) {
|
|
const index = (await userInput.rollDice([{ number: 1, diceSize: children.length }]))[0][0];
|
|
const child = children[index - 1];
|
|
return applyAfterPropTasksForSingleChild(action, prop, child, targets, userInput);
|
|
} else {
|
|
return applyAfterTasksSkipChildren(action, prop, targets, userInput);
|
|
}
|
|
}
|
|
case 'eachTarget':
|
|
if (targets.length > 1) {
|
|
return applyTaskToEachTarget(action, task, targets, userInput);
|
|
}
|
|
return applyDefaultAfterPropTasks(action, prop, targets, userInput);
|
|
case 'choice': {
|
|
const children = await getPropertyChildren(action.creatureId, prop);
|
|
let choices: string[];
|
|
let chosenChildren: typeof children = [];
|
|
if (children.length) {
|
|
choices = await userInput.choose(children);
|
|
chosenChildren = filter(children, child => choices.includes(child._id));
|
|
}
|
|
if (!children.length || !chosenChildren.length) {
|
|
return applyAfterTasksSkipChildren(action, prop, targets, userInput);
|
|
}
|
|
return applyAfterPropTasksForSomeChildren(action, prop, chosenChildren, targets, userInput);
|
|
}
|
|
}
|
|
}
|