Progress on action choices
This commit is contained in:
@@ -3,7 +3,7 @@ import ParseNode from '/imports/parser/parseTree/ParseNode';
|
|||||||
import array from '/imports/parser/parseTree/array';
|
import array from '/imports/parser/parseTree/array';
|
||||||
import constant, { isFiniteNode } from '/imports/parser/parseTree/constant';
|
import constant, { isFiniteNode } from '/imports/parser/parseTree/constant';
|
||||||
import resolve from '/imports/parser/resolve';
|
import resolve from '/imports/parser/resolve';
|
||||||
import InputProvider from '/imports/api/engine/action/functions/InputProvider';
|
import InputProvider from '/imports/api/engine/action/functions/userInput/InputProvider';
|
||||||
import Context from '/imports/parser/types/Context';
|
import Context from '/imports/parser/types/Context';
|
||||||
|
|
||||||
//set up the collection for creature variables
|
//set up the collection for creature variables
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import { loadCreature } from '/imports/api/engine/loadCreatures';
|
|||||||
import EngineActions, { EngineAction } from '/imports/api/engine/action/EngineActions';
|
import EngineActions, { EngineAction } from '/imports/api/engine/action/EngineActions';
|
||||||
import applyAction from '/imports/api/engine/action/functions/applyAction';
|
import applyAction from '/imports/api/engine/action/functions/applyAction';
|
||||||
import { LogContent, Removal, Update } from '/imports/api/engine/action/tasks/TaskResult';
|
import { LogContent, Removal, Update } from '/imports/api/engine/action/tasks/TaskResult';
|
||||||
import inputProvider from '/imports/api/engine/action/functions/inputProviderForTests.testFn';
|
import inputProvider from './functions/userInput/inputProviderForTests.testFn';
|
||||||
|
|
||||||
const creatureId = Random.id();
|
const creatureId = Random.id();
|
||||||
const targetId = Random.id();
|
const targetId = Random.id();
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ export interface EngineAction {
|
|||||||
_id?: string;
|
_id?: string;
|
||||||
_isSimulation?: boolean;
|
_isSimulation?: boolean;
|
||||||
_stepThrough?: boolean;
|
_stepThrough?: boolean;
|
||||||
|
_choices?: any[],
|
||||||
creatureId: string;
|
creatureId: string;
|
||||||
rootPropId: string;
|
rootPropId: string;
|
||||||
targetIds?: string[];
|
targetIds?: string[];
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import recalculateCalculation from '/imports/api/engine/action/functions/recalcu
|
|||||||
import { getEffectiveActionScope } from '/imports/api/engine/action/functions/getEffectiveActionScope';
|
import { getEffectiveActionScope } from '/imports/api/engine/action/functions/getEffectiveActionScope';
|
||||||
import numberToSignedString from '/imports/api/utility/numberToSignedString';
|
import numberToSignedString from '/imports/api/utility/numberToSignedString';
|
||||||
import { getConstantValueFromScope, getNumberFromScope } from '/imports/api/creature/creatures/CreatureVariables';
|
import { getConstantValueFromScope, getNumberFromScope } from '/imports/api/creature/creatures/CreatureVariables';
|
||||||
import InputProvider from '/imports/api/engine/action/functions/InputProvider';
|
import InputProvider from '/imports/api/engine/action/functions/userInput/InputProvider';
|
||||||
import { CalculatedField } from '/imports/api/properties/subSchemas/computedField';
|
import { CalculatedField } from '/imports/api/properties/subSchemas/computedField';
|
||||||
|
|
||||||
export default async function applyActionProperty(
|
export default async function applyActionProperty(
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { EngineAction } from '/imports/api/engine/action/EngineActions';
|
import { EngineAction } from '/imports/api/engine/action/EngineActions';
|
||||||
import InputProvider from '/imports/api/engine/action/functions/InputProvider';
|
import InputProvider from '/imports/api/engine/action/functions/userInput/InputProvider';
|
||||||
import { applyDefaultAfterPropTasks, applyTaskToEachTarget } from '/imports/api/engine/action/functions/applyTaskGroups';
|
import { applyDefaultAfterPropTasks, applyTaskToEachTarget } from '/imports/api/engine/action/functions/applyTaskGroups';
|
||||||
import recalculateCalculation from '/imports/api/engine/action/functions/recalculateCalculation';
|
import recalculateCalculation from '/imports/api/engine/action/functions/recalculateCalculation';
|
||||||
import { PropTask } from '/imports/api/engine/action/tasks/Task';
|
import { PropTask } from '/imports/api/engine/action/tasks/Task';
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { filter } from 'lodash';
|
import { filter } from 'lodash';
|
||||||
import { EngineAction } from '/imports/api/engine/action/EngineActions';
|
import { EngineAction } from '/imports/api/engine/action/EngineActions';
|
||||||
import InputProvider from '/imports/api/engine/action/functions/InputProvider';
|
import InputProvider from '/imports/api/engine/action/functions/userInput/InputProvider';
|
||||||
import { applyAfterPropTasksForSingleChild, applyAfterPropTasksForSomeChildren, applyAfterTasksSkipChildren, applyDefaultAfterPropTasks, applyTaskToEachTarget } from '/imports/api/engine/action/functions/applyTaskGroups';
|
import { applyAfterPropTasksForSingleChild, applyAfterPropTasksForSomeChildren, applyAfterTasksSkipChildren, applyDefaultAfterPropTasks, applyTaskToEachTarget } from '/imports/api/engine/action/functions/applyTaskGroups';
|
||||||
import { getEffectiveActionScope } from '/imports/api/engine/action/functions/getEffectiveActionScope';
|
import { getEffectiveActionScope } from '/imports/api/engine/action/functions/getEffectiveActionScope';
|
||||||
import recalculateCalculation from '/imports/api/engine/action/functions/recalculateCalculation';
|
import recalculateCalculation from '/imports/api/engine/action/functions/recalculateCalculation';
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ import recalculateInlineCalculations from '/imports/api/engine/action/functions/
|
|||||||
import getPropertyTitle from '/imports/api/utility/getPropertyTitle';
|
import getPropertyTitle from '/imports/api/utility/getPropertyTitle';
|
||||||
import INLINE_CALCULATION_REGEX from '/imports/constants/INLINE_CALCULTION_REGEX';
|
import INLINE_CALCULATION_REGEX from '/imports/constants/INLINE_CALCULTION_REGEX';
|
||||||
import { applyAfterTasksSkipChildren } from '/imports/api/engine/action/functions/applyTaskGroups';
|
import { applyAfterTasksSkipChildren } from '/imports/api/engine/action/functions/applyTaskGroups';
|
||||||
import InputProvider from '/imports/api/engine/action/functions/InputProvider';
|
import InputProvider from '/imports/api/engine/action/functions/userInput/InputProvider';
|
||||||
|
|
||||||
export default async function applyBuffProperty(
|
export default async function applyBuffProperty(
|
||||||
task: PropTask, action: EngineAction, result: TaskResult, userInput: InputProvider
|
task: PropTask, action: EngineAction, result: TaskResult, userInput: InputProvider
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import resolve from '/imports/parser/resolve';
|
|||||||
import toString from '/imports/parser/toString';
|
import toString from '/imports/parser/toString';
|
||||||
import { getPropertiesOfType } from '/imports/api/engine/loadCreatures';
|
import { getPropertiesOfType } from '/imports/api/engine/loadCreatures';
|
||||||
import applyTask from '/imports/api/engine/action/tasks/applyTask';
|
import applyTask from '/imports/api/engine/action/tasks/applyTask';
|
||||||
import InputProvider from '/imports/api/engine/action/functions/InputProvider';
|
import InputProvider from '/imports/api/engine/action/functions/userInput/InputProvider';
|
||||||
import getEffectivePropTags from '/imports/api/engine/computation/utility/getEffectivePropTags';
|
import getEffectivePropTags from '/imports/api/engine/computation/utility/getEffectivePropTags';
|
||||||
import Context from '/imports/parser/types/Context';
|
import Context from '/imports/parser/types/Context';
|
||||||
import applySavingThrowProperty from '/imports/api/engine/action/applyProperties/applySavingThrowProperty';
|
import applySavingThrowProperty from '/imports/api/engine/action/applyProperties/applySavingThrowProperty';
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { EngineAction } from '/imports/api/engine/action/EngineActions';
|
import { EngineAction } from '/imports/api/engine/action/EngineActions';
|
||||||
import InputProvider from '/imports/api/engine/action/functions/InputProvider';
|
import InputProvider from '/imports/api/engine/action/functions/userInput/InputProvider';
|
||||||
import { applyDefaultAfterPropTasks } from '/imports/api/engine/action/functions/applyTaskGroups';
|
import { applyDefaultAfterPropTasks } from '/imports/api/engine/action/functions/applyTaskGroups';
|
||||||
import recalculateInlineCalculations from '/imports/api/engine/action/functions/recalculateInlineCalculations';
|
import recalculateInlineCalculations from '/imports/api/engine/action/functions/recalculateInlineCalculations';
|
||||||
import { PropTask } from '/imports/api/engine/action/tasks/Task';
|
import { PropTask } from '/imports/api/engine/action/tasks/Task';
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { EngineAction } from '/imports/api/engine/action/EngineActions';
|
import { EngineAction } from '/imports/api/engine/action/EngineActions';
|
||||||
import InputProvider from '/imports/api/engine/action/functions/InputProvider';
|
import InputProvider from '/imports/api/engine/action/functions/userInput/InputProvider';
|
||||||
import { applyDefaultAfterPropTasks } from '/imports/api/engine/action/functions/applyTaskGroups';
|
import { applyDefaultAfterPropTasks } from '/imports/api/engine/action/functions/applyTaskGroups';
|
||||||
import { rollAndReduceCalculation } from '/imports/api/engine/action/functions/recalculateCalculation';
|
import { rollAndReduceCalculation } from '/imports/api/engine/action/functions/recalculateCalculation';
|
||||||
import { PropTask } from '/imports/api/engine/action/tasks/Task';
|
import { PropTask } from '/imports/api/engine/action/tasks/Task';
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { getFromScope } from '/imports/api/creature/creatures/CreatureVariables';
|
import { getFromScope } from '/imports/api/creature/creatures/CreatureVariables';
|
||||||
import { EngineAction } from '/imports/api/engine/action/EngineActions';
|
import { EngineAction } from '/imports/api/engine/action/EngineActions';
|
||||||
import InputProvider from '/imports/api/engine/action/functions/InputProvider';
|
import InputProvider from '/imports/api/engine/action/functions/userInput/InputProvider';
|
||||||
import { applyDefaultAfterPropTasks } from '/imports/api/engine/action/functions/applyTaskGroups';
|
import { applyDefaultAfterPropTasks } from '/imports/api/engine/action/functions/applyTaskGroups';
|
||||||
import { getEffectiveActionScope } from '/imports/api/engine/action/functions/getEffectiveActionScope';
|
import { getEffectiveActionScope } from '/imports/api/engine/action/functions/getEffectiveActionScope';
|
||||||
import recalculateCalculation from '/imports/api/engine/action/functions/recalculateCalculation';
|
import recalculateCalculation from '/imports/api/engine/action/functions/recalculateCalculation';
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { EngineAction } from '/imports/api/engine/action/EngineActions';
|
import { EngineAction } from '/imports/api/engine/action/EngineActions';
|
||||||
import InputProvider from '/imports/api/engine/action/functions/InputProvider';
|
import InputProvider from '/imports/api/engine/action/functions/userInput/InputProvider';
|
||||||
import { applyAfterTasksSkipChildren, applyDefaultAfterPropTasks } from '/imports/api/engine/action/functions/applyTaskGroups';
|
import { applyAfterTasksSkipChildren, applyDefaultAfterPropTasks } from '/imports/api/engine/action/functions/applyTaskGroups';
|
||||||
import recalculateCalculation from '/imports/api/engine/action/functions/recalculateCalculation';
|
import recalculateCalculation from '/imports/api/engine/action/functions/recalculateCalculation';
|
||||||
import { PropTask } from '/imports/api/engine/action/tasks/Task';
|
import { PropTask } from '/imports/api/engine/action/tasks/Task';
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import { loadCreature } from '/imports/api/engine/loadCreatures';
|
|||||||
import EngineActions, { EngineAction } from '/imports/api/engine/action/EngineActions';
|
import EngineActions, { EngineAction } from '/imports/api/engine/action/EngineActions';
|
||||||
import applyAction from '/imports/api/engine/action/functions/applyAction';
|
import applyAction from '/imports/api/engine/action/functions/applyAction';
|
||||||
import { LogContent, Mutation, Removal, Update } from '/imports/api/engine/action/tasks/TaskResult';
|
import { LogContent, Mutation, Removal, Update } from '/imports/api/engine/action/tasks/TaskResult';
|
||||||
import inputProvider from '/imports/api/engine/action/functions/inputProviderForTests.testFn';
|
import inputProvider from './userInput/inputProviderForTests.testFn';
|
||||||
/**
|
/**
|
||||||
* Removes all creatures, properties, and creatureVariable documents from the database
|
* Removes all creatures, properties, and creatureVariable documents from the database
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
import { EngineAction } from '/imports/api/engine/action/EngineActions';
|
import { EngineAction } from '/imports/api/engine/action/EngineActions';
|
||||||
import { getSingleProperty } from '/imports/api/engine/loadCreatures';
|
import { getSingleProperty } from '/imports/api/engine/loadCreatures';
|
||||||
import applyTask from '/imports/api/engine/action/tasks/applyTask'
|
import applyTask from '/imports/api/engine/action/tasks/applyTask'
|
||||||
import InputProvider from '/imports/api/engine/action/functions/InputProvider';
|
import InputProvider from '/imports/api/engine/action/functions/userInput/InputProvider';
|
||||||
|
import saveInputChoices from './userInput/saveInputChoices';
|
||||||
|
|
||||||
// TODO create a function to get the effective value of a property,
|
// TODO create a function to get the effective value of a property,
|
||||||
// simulating all the result updates in the action so far
|
// simulating all the result updates in the action so far
|
||||||
@@ -17,6 +18,16 @@ export default async function applyAction(action: EngineAction, userInput: Input
|
|||||||
if (!simulate && stepThrough) throw 'Cannot step through unless simulating';
|
if (!simulate && stepThrough) throw 'Cannot step through unless simulating';
|
||||||
if (simulate && !userInput) throw 'Must provide a function to get user input when simulating';
|
if (simulate && !userInput) throw 'Must provide a function to get user input when simulating';
|
||||||
|
|
||||||
|
if (action._isSimulation || action._stepThrough) {
|
||||||
|
console.error('_isSimulation and _stepThrough should not be set on the action, rather call\
|
||||||
|
applyAction with the appropriate options');
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we are simulating, save the user input choices
|
||||||
|
if (simulate) {
|
||||||
|
userInput = saveInputChoices(action, userInput);
|
||||||
|
}
|
||||||
|
|
||||||
action._stepThrough = stepThrough;
|
action._stepThrough = stepThrough;
|
||||||
action._isSimulation = simulate;
|
action._isSimulation = simulate;
|
||||||
action.taskCount = 0;
|
action.taskCount = 0;
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { getPropertyChildren, getSingleProperty } from '/imports/api/engine/load
|
|||||||
import { EngineAction } from '/imports/api/engine/action/EngineActions';
|
import { EngineAction } from '/imports/api/engine/action/EngineActions';
|
||||||
import applyTask from '../tasks/applyTask';
|
import applyTask from '../tasks/applyTask';
|
||||||
import { PropTask } from '../tasks/Task';
|
import { PropTask } from '../tasks/Task';
|
||||||
import InputProvider from '/imports/api/engine/action/functions/InputProvider';
|
import InputProvider from '/imports/api/engine/action/functions/userInput/InputProvider';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get all the child tasks of a given property
|
* Get all the child tasks of a given property
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import resolve from '/imports/parser/resolve';
|
|||||||
import { getEffectiveActionScope } from '/imports/api/engine/action/functions/getEffectiveActionScope';
|
import { getEffectiveActionScope } from '/imports/api/engine/action/functions/getEffectiveActionScope';
|
||||||
import { CalculatedField } from '/imports/api/properties/subSchemas/computedField';
|
import { CalculatedField } from '/imports/api/properties/subSchemas/computedField';
|
||||||
import { ResolveLevel } from '/imports/parser/parseTree/NodeFactory';
|
import { ResolveLevel } from '/imports/parser/parseTree/NodeFactory';
|
||||||
import InputProvider from '/imports/api/engine/action/functions/InputProvider';
|
import InputProvider from '/imports/api/engine/action/functions/userInput/InputProvider';
|
||||||
import { EngineAction } from '/imports/api/engine/action/EngineActions';
|
import { EngineAction } from '/imports/api/engine/action/EngineActions';
|
||||||
|
|
||||||
// TODO Redo the work of
|
// TODO Redo the work of
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import recalculateCalculation from './recalculateCalculation'
|
|||||||
import { InlineCalculation } from '/imports/api/properties/subSchemas/inlineCalculationField';
|
import { InlineCalculation } from '/imports/api/properties/subSchemas/inlineCalculationField';
|
||||||
import { EngineAction } from '/imports/api/engine/action/EngineActions';
|
import { EngineAction } from '/imports/api/engine/action/EngineActions';
|
||||||
import ResolveLevel from '/imports/parser/types/ResolveLevel';
|
import ResolveLevel from '/imports/parser/types/ResolveLevel';
|
||||||
import InputProvider from '/imports/api/engine/action/functions/InputProvider';
|
import InputProvider from '/imports/api/engine/action/functions/userInput/InputProvider';
|
||||||
|
|
||||||
export default async function recalculateInlineCalculations(
|
export default async function recalculateInlineCalculations(
|
||||||
inlineCalcObj: InlineCalculation, action: EngineAction,
|
inlineCalcObj: InlineCalculation, action: EngineAction,
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ type InputProvider = {
|
|||||||
/**
|
/**
|
||||||
* Get the details of a check or save
|
* Get the details of a check or save
|
||||||
*/
|
*/
|
||||||
check(suggestedParams: CheckParams): Promise<CheckParams>;
|
//check(suggestedParams: CheckParams): Promise<CheckParams>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type Advantage = 0 | 1 | -1;
|
export type Advantage = 0 | 1 | -1;
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
import Alea from 'alea';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a function that can be be used as InputProvider.rollDice
|
||||||
|
* this function instance must be used for the entire action
|
||||||
|
*/
|
||||||
|
export default function getDeterministicDiceRoller(
|
||||||
|
actionId: string
|
||||||
|
): (dice: { number: number, diceSize: number }[]) => Promise<number[][]> {
|
||||||
|
// Create a random number generator seeded on the ID of the action
|
||||||
|
if (!actionId) throw new Meteor.Error('Id Required', 'action ID can not be ' + actionId)
|
||||||
|
const randFrac = Alea(actionId);
|
||||||
|
return (dice) => {
|
||||||
|
const results: number[][] = [];
|
||||||
|
for (const diceRoll of dice) {
|
||||||
|
const values: number[] = [];
|
||||||
|
if (diceRoll.number > 100) {
|
||||||
|
throw new Meteor.Error('Too many dice', 'can only roll up to 100 dice at once');
|
||||||
|
}
|
||||||
|
for (let i = 0; i < diceRoll.number; i++) {
|
||||||
|
const rolledValue = ~~(randFrac() * diceRoll.diceSize) + 1
|
||||||
|
values.push(rolledValue);
|
||||||
|
}
|
||||||
|
results.push(values);
|
||||||
|
}
|
||||||
|
return Promise.resolve(results);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
import InputProvider from '/imports/api/engine/action/functions/userInput/InputProvider';
|
||||||
|
import getDeterministicDiceRoller from '/imports/api/engine/action/functions/userInput/getDeterministicDiceRoller';
|
||||||
|
|
||||||
|
// This assumes the user's choices are in exactly the order they will be requested
|
||||||
|
// Dice rolls are done fresh, no cheating
|
||||||
|
export default function getReplayChoicesInputProvider(actionId: string, decisions: any[]):
|
||||||
|
InputProvider {
|
||||||
|
const dRoller = getDeterministicDiceRoller(actionId);
|
||||||
|
const replaySavedInput: InputProvider = {
|
||||||
|
nextStep() {
|
||||||
|
return Promise.resolve();
|
||||||
|
},
|
||||||
|
// To roll dice, ignore the user and use the deterministic dice roller again
|
||||||
|
rollDice(dice) {
|
||||||
|
decisions.pop();
|
||||||
|
return dRoller(dice);
|
||||||
|
},
|
||||||
|
choose() {
|
||||||
|
return Promise.resolve(decisions.pop());
|
||||||
|
},
|
||||||
|
advantage() {
|
||||||
|
return Promise.resolve(decisions.pop());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return replaySavedInput;
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import InputProvider from '/imports/api/engine/action/functions/InputProvider';
|
import InputProvider from '/imports/api/engine/action/functions/userInput/InputProvider';
|
||||||
|
|
||||||
const inputProviderForTests: InputProvider = {
|
const inputProviderForTests: InputProvider = {
|
||||||
/**
|
/**
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
import { EngineAction } from '/imports/api/engine/action/EngineActions';
|
||||||
|
import InputProvider from '/imports/api/engine/action/functions/userInput/InputProvider';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new version of the user input function, that saves the user's choices to an array
|
||||||
|
* before returning them
|
||||||
|
*/
|
||||||
|
export default function saveInputChoices(action: EngineAction, userInput: InputProvider): InputProvider {
|
||||||
|
const newInputProvider: Partial<InputProvider> = {};
|
||||||
|
|
||||||
|
if (!action._choices) {
|
||||||
|
action._choices = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
// For every function in the given input provider
|
||||||
|
for (const key in userInput) {
|
||||||
|
const oldFn = userInput[key];
|
||||||
|
// Make a new function that does the same thing, but saves the result to action._choices
|
||||||
|
const newFn = (...args) => {
|
||||||
|
const result = oldFn(...args);
|
||||||
|
action._choices.push(result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
newInputProvider[key] = newFn;
|
||||||
|
}
|
||||||
|
|
||||||
|
return newInputProvider as InputProvider;
|
||||||
|
}
|
||||||
@@ -5,6 +5,7 @@ import { assertEditPermission } from '/imports/api/sharing/sharingPermissions';
|
|||||||
import { getCreature } from '/imports/api/engine/loadCreatures';
|
import { getCreature } from '/imports/api/engine/loadCreatures';
|
||||||
import applyAction from '/imports/api/engine/action/functions/applyAction';
|
import applyAction from '/imports/api/engine/action/functions/applyAction';
|
||||||
import writeChangedAction from '../functions/writeChangedAction';
|
import writeChangedAction from '../functions/writeChangedAction';
|
||||||
|
import getReplayChoicesInputProvider from '/imports/api/engine/action/functions/userInput/getReplayChoicesInputProvider';
|
||||||
|
|
||||||
export const runAction = new ValidatedMethod({
|
export const runAction = new ValidatedMethod({
|
||||||
name: 'actions.runAction',
|
name: 'actions.runAction',
|
||||||
@@ -13,23 +14,32 @@ export const runAction = new ValidatedMethod({
|
|||||||
type: Object,
|
type: Object,
|
||||||
blackbox: true,
|
blackbox: true,
|
||||||
},
|
},
|
||||||
userInput: {
|
decisions: {
|
||||||
|
type: Array,
|
||||||
|
},
|
||||||
|
'decisions.$': {
|
||||||
type: Object,
|
type: Object,
|
||||||
blackbox: true,
|
blackbox: true,
|
||||||
optional: true,
|
|
||||||
},
|
},
|
||||||
stepThrough: {
|
|
||||||
type: Boolean,
|
|
||||||
optional: true,
|
|
||||||
}
|
|
||||||
}).validator(),
|
}).validator(),
|
||||||
run: async function ({ actionId, userInput }: { actionId: string, userInput?: any }) {
|
run: async function ({ actionId, decisions }: { actionId: string, decisions: any[] }) {
|
||||||
|
// Get the action
|
||||||
const action = await EngineActions.findOneAsync(actionId);
|
const action = await EngineActions.findOneAsync(actionId);
|
||||||
if (!action) throw 'Action not found';
|
if (!action) throw new Meteor.Error('not-found', 'Action not found');
|
||||||
|
|
||||||
|
// Permissions
|
||||||
assertEditPermission(getCreature(action.creatureId), this.userId);
|
assertEditPermission(getCreature(action.creatureId), this.userId);
|
||||||
|
|
||||||
|
// Keep a copy of the original so that a diff can be done later to store what changed
|
||||||
const originalAction = EJSON.clone(action);
|
const originalAction = EJSON.clone(action);
|
||||||
|
|
||||||
|
// Replay the user's decisions as user input
|
||||||
|
const userInput = getReplayChoicesInputProvider(actionId, decisions);
|
||||||
|
|
||||||
|
// Apply the action
|
||||||
applyAction(action, userInput);
|
applyAction(action, userInput);
|
||||||
// Persist changes to the action
|
|
||||||
|
// Persist changes
|
||||||
const writePromise = writeChangedAction(originalAction, action);
|
const writePromise = writeChangedAction(originalAction, action);
|
||||||
return writePromise;
|
return writePromise;
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { getFromScope } from '/imports/api/creature/creatures/CreatureVariables';
|
import { getFromScope } from '/imports/api/creature/creatures/CreatureVariables';
|
||||||
import { EngineAction } from '/imports/api/engine/action/EngineActions';
|
import { EngineAction } from '/imports/api/engine/action/EngineActions';
|
||||||
import InputProvider, { CheckParams } from '/imports/api/engine/action/functions/InputProvider';
|
import InputProvider, { CheckParams } from '/imports/api/engine/action/functions/userInput/InputProvider';
|
||||||
import { applyDefaultAfterPropTasks } from '/imports/api/engine/action/functions/applyTaskGroups';
|
import { applyDefaultAfterPropTasks } from '/imports/api/engine/action/functions/applyTaskGroups';
|
||||||
import { getEffectiveActionScope } from '/imports/api/engine/action/functions/getEffectiveActionScope';
|
import { getEffectiveActionScope } from '/imports/api/engine/action/functions/getEffectiveActionScope';
|
||||||
import recalculateCalculation from '/imports/api/engine/action/functions/recalculateCalculation';
|
import recalculateCalculation from '/imports/api/engine/action/functions/recalculateCalculation';
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import applyDamagePropTask from '/imports/api/engine/action/tasks/applyDamagePro
|
|||||||
import applyItemAsAmmoTask from '/imports/api/engine/action/tasks/applyItemAsAmmoTask';
|
import applyItemAsAmmoTask from '/imports/api/engine/action/tasks/applyItemAsAmmoTask';
|
||||||
import { getSingleProperty } from '/imports/api/engine/loadCreatures';
|
import { getSingleProperty } from '/imports/api/engine/loadCreatures';
|
||||||
import applyProperties from '/imports/api/engine/action/applyProperties';
|
import applyProperties from '/imports/api/engine/action/applyProperties';
|
||||||
import InputProvider from '/imports/api/engine/action/functions/InputProvider';
|
import InputProvider from '/imports/api/engine/action/functions/userInput/InputProvider';
|
||||||
|
|
||||||
// DamagePropTask promises a number of actual damage done
|
// DamagePropTask promises a number of actual damage done
|
||||||
export default async function applyTask(
|
export default async function applyTask(
|
||||||
|
|||||||
@@ -5,18 +5,7 @@
|
|||||||
Action
|
Action
|
||||||
</v-toolbar-title>
|
</v-toolbar-title>
|
||||||
</template>
|
</template>
|
||||||
<!--
|
<log-content :model="allLogContent" />
|
||||||
<pre>
|
|
||||||
<code>
|
|
||||||
{{ actionJson }}
|
|
||||||
</code>
|
|
||||||
</pre>
|
|
||||||
<pre>
|
|
||||||
<code>
|
|
||||||
{{ resultJson }}
|
|
||||||
</code>
|
|
||||||
</pre>
|
|
||||||
-->
|
|
||||||
<component
|
<component
|
||||||
:is="activeInput"
|
:is="activeInput"
|
||||||
v-if="activeInput"
|
v-if="activeInput"
|
||||||
@@ -43,12 +32,21 @@
|
|||||||
Step
|
Step
|
||||||
</v-btn>
|
</v-btn>
|
||||||
<v-btn
|
<v-btn
|
||||||
|
v-if="actionDone"
|
||||||
slot="actions"
|
slot="actions"
|
||||||
text
|
text
|
||||||
:disabled="actionBusy && !actionDone"
|
@click="finishAction"
|
||||||
|
>
|
||||||
|
{{ 'Apply Results' }}
|
||||||
|
</v-btn>
|
||||||
|
<v-btn
|
||||||
|
v-else
|
||||||
|
slot="actions"
|
||||||
|
text
|
||||||
|
:disabled="actionBusy"
|
||||||
@click="startAction"
|
@click="startAction"
|
||||||
>
|
>
|
||||||
{{ actionDone ? 'Apply Results' : 'Start' }}
|
{{ 'Start' }}
|
||||||
</v-btn>
|
</v-btn>
|
||||||
</dialog-base>
|
</dialog-base>
|
||||||
</template>
|
</template>
|
||||||
@@ -58,11 +56,16 @@ import DialogBase from '/imports/client/ui/dialogStack/DialogBase.vue';
|
|||||||
import EngineActions from '/imports/api/engine/action/EngineActions';
|
import EngineActions from '/imports/api/engine/action/EngineActions';
|
||||||
import applyAction from '/imports/api/engine/action/functions/applyAction';
|
import applyAction from '/imports/api/engine/action/functions/applyAction';
|
||||||
import AdvantageInput from '/imports/client/ui/creature/actions/input/AdvantageInput.vue';
|
import AdvantageInput from '/imports/client/ui/creature/actions/input/AdvantageInput.vue';
|
||||||
|
import RollInput from '/imports/client/ui/creature/actions/input/RollInput.vue';
|
||||||
|
import getDeterministicDiceRoller from '/imports/api/engine/action/functions/userInput/getDeterministicDiceRoller';
|
||||||
|
import LogContent from '/imports/client/ui/log/LogContent.vue';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
DialogBase,
|
DialogBase,
|
||||||
AdvantageInput,
|
AdvantageInput,
|
||||||
|
RollInput,
|
||||||
|
LogContent,
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
actionId: {
|
actionId: {
|
||||||
@@ -89,13 +92,34 @@ export default {
|
|||||||
},
|
},
|
||||||
resultJson() {
|
resultJson() {
|
||||||
return JSON.stringify(this.actionResult, null, 2);
|
return JSON.stringify(this.actionResult, null, 2);
|
||||||
}
|
},
|
||||||
|
allLogContent() {
|
||||||
|
const action = this.actionResult;
|
||||||
|
const contents = [];
|
||||||
|
action?.results?.forEach(result => {
|
||||||
|
result.mutations?.forEach(mutation => {
|
||||||
|
mutation.contents?.forEach(logContent => {
|
||||||
|
contents.push(logContent);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
return contents;
|
||||||
|
},
|
||||||
},
|
},
|
||||||
meteor: {
|
meteor: {
|
||||||
action() {
|
action() {
|
||||||
return EngineActions.findOne(this.actionId);
|
return EngineActions.findOne(this.actionId);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
watch: {
|
||||||
|
resultAction(val) {
|
||||||
|
console.log(val);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.deterministicDiceRoller = getDeterministicDiceRoller(this.actionId);
|
||||||
|
this.startAction({ stepThrough: false });
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
startAction({ stepThrough }) {
|
startAction({ stepThrough }) {
|
||||||
this.actionBusy = true;
|
this.actionBusy = true;
|
||||||
@@ -108,6 +132,7 @@ export default {
|
|||||||
applyAction(
|
applyAction(
|
||||||
this.actionResult, this, { simulate: true, stepThrough }
|
this.actionResult, this, { simulate: true, stepThrough }
|
||||||
).then(() => {
|
).then(() => {
|
||||||
|
console.log('action is done');
|
||||||
this.actionDone = true
|
this.actionDone = true
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
@@ -123,6 +148,9 @@ export default {
|
|||||||
}
|
}
|
||||||
this.resumeActionFn?.();
|
this.resumeActionFn?.();
|
||||||
},
|
},
|
||||||
|
finishAction() {
|
||||||
|
this.$store.dispatch('popDialogStack');
|
||||||
|
},
|
||||||
promiseInput() {
|
promiseInput() {
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
this.resumeActionFn = () => {
|
this.resumeActionFn = () => {
|
||||||
@@ -143,28 +171,38 @@ export default {
|
|||||||
this.$store.dispatch('popDialogStack');
|
this.$store.dispatch('popDialogStack');
|
||||||
},
|
},
|
||||||
// inputProvider methods
|
// inputProvider methods
|
||||||
async rollDice(diceArray) {
|
async rollDice(dice) {
|
||||||
console.log({diceArray});
|
console.log('Waiting for dice roll');
|
||||||
|
this.activeInputParams = {
|
||||||
|
deterministicDiceRoller: this.deterministicDiceRoller,
|
||||||
|
dice
|
||||||
|
};
|
||||||
|
this.activeInput = 'roll-input';
|
||||||
return this.promiseInput();
|
return this.promiseInput();
|
||||||
},
|
},
|
||||||
async nextStep(task) {
|
async nextStep(task) {
|
||||||
console.log({task});
|
console.log('waiting for next step');
|
||||||
|
console.log({ task });
|
||||||
return this.promiseInput();
|
return this.promiseInput();
|
||||||
},
|
},
|
||||||
async choose(choices, quantity) {
|
async choose(choices, quantity) {
|
||||||
|
console.log('Waiting for choice');
|
||||||
console.log({choices, quantity});
|
console.log({choices, quantity});
|
||||||
return this.promiseInput();
|
return this.promiseInput();
|
||||||
},
|
},
|
||||||
async advantage(suggestedAdvantage) {
|
async advantage(suggestedAdvantage) {
|
||||||
|
console.log('Waiting for advantage');
|
||||||
this.userInput = suggestedAdvantage;
|
this.userInput = suggestedAdvantage;
|
||||||
this.activeInput = 'advantage-input';
|
this.activeInput = 'advantage-input';
|
||||||
this.userInputReady = true;
|
this.userInputReady = true;
|
||||||
return this.promiseInput();
|
return this.promiseInput();
|
||||||
},
|
},
|
||||||
async check(suggestedParams) {
|
async check(suggestedParams) {
|
||||||
|
console.log('Waiting for check');
|
||||||
console.log({ suggestedParams })
|
console.log({ suggestedParams })
|
||||||
return this.promiseInput();
|
return this.promiseInput();
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
../../../../api/engine/action/functions/userInput/getDeterministicDiceRoller
|
||||||
@@ -2,7 +2,14 @@
|
|||||||
<div
|
<div
|
||||||
class="d-flex flex-column justify-center align-center"
|
class="d-flex flex-column justify-center align-center"
|
||||||
@click="rollDice"
|
@click="rollDice"
|
||||||
/>
|
>
|
||||||
|
<p
|
||||||
|
v-for="(die, index) in dice"
|
||||||
|
:key="index"
|
||||||
|
>
|
||||||
|
{{ die.number }}d{{ die.diceSize }}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="js">
|
<script lang="js">
|
||||||
@@ -18,10 +25,16 @@ export default {
|
|||||||
type: Array,
|
type: Array,
|
||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
|
deterministicDiceRoller: {
|
||||||
|
type: Function,
|
||||||
|
required: true,
|
||||||
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
rollDice() {
|
rollDice() {
|
||||||
|
const values = this.deterministicDiceRoller(this.dice);
|
||||||
|
this.emitInput(values);
|
||||||
|
this.$emit('continue');
|
||||||
},
|
},
|
||||||
emitInput(e) {
|
emitInput(e) {
|
||||||
e = e || 0;
|
e = e || 0;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import inputProviderForTests from '/imports/api/engine/action/functions/inputProviderForTests.testFn';
|
import inputProviderForTests from '../../api/engine/action/functions/userInput/inputProviderForTests.testFn';
|
||||||
import { parse } from '/imports/parser/parser';
|
import { parse } from '/imports/parser/parser';
|
||||||
import resolve from '/imports/parser/resolve';
|
import resolve from '/imports/parser/resolve';
|
||||||
import toString from '/imports/parser/toString';
|
import toString from '/imports/parser/toString';
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import inputProviderForTests from '/imports/api/engine/action/functions/inputProviderForTests.testFn';
|
import inputProviderForTests from '../../api/engine/action/functions/userInput/inputProviderForTests.testFn';
|
||||||
import { parse } from '/imports/parser/parser';
|
import { parse } from '/imports/parser/parser';
|
||||||
import resolve from '/imports/parser/resolve';
|
import resolve from '/imports/parser/resolve';
|
||||||
import toString from '/imports/parser/toString';
|
import toString from '/imports/parser/toString';
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import '/imports/parser/parseTree/array';
|
import '/imports/parser/parseTree/array';
|
||||||
import factories from '/imports/parser/parseTree';
|
import factories from '/imports/parser/parseTree';
|
||||||
import InputProvider from '/imports/api/engine/action/functions/InputProvider';
|
import InputProvider from '/imports/api/engine/action/functions/userInput/InputProvider';
|
||||||
import ParseNode from '/imports/parser/parseTree/ParseNode';
|
import ParseNode from '/imports/parser/parseTree/ParseNode';
|
||||||
import rollDice from '/imports/parser/rollDice';
|
import rollDice from '/imports/parser/rollDice';
|
||||||
import ResolveLevel from './types/ResolveLevel';
|
import ResolveLevel from './types/ResolveLevel';
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import InputProvider from '/imports/api/engine/action/functions/InputProvider';
|
import InputProvider from '/imports/api/engine/action/functions/userInput/InputProvider';
|
||||||
import ParseNode from '/imports/parser/parseTree/ParseNode';
|
import ParseNode from '/imports/parser/parseTree/ParseNode';
|
||||||
import Context from './Context';
|
import Context from './Context';
|
||||||
import ResolvedResult from './ResolvedResult';
|
import ResolvedResult from './ResolvedResult';
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import InputProvider from '/imports/api/engine/action/functions/InputProvider';
|
import InputProvider from '/imports/api/engine/action/functions/userInput/InputProvider';
|
||||||
import ParseNode from '/imports/parser/parseTree/ParseNode';
|
import ParseNode from '/imports/parser/parseTree/ParseNode';
|
||||||
import Context from './Context';
|
import Context from './Context';
|
||||||
import ResolvedResult from './ResolvedResult';
|
import ResolvedResult from './ResolvedResult';
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import InputProvider from '/imports/api/engine/action/functions/InputProvider';
|
import InputProvider from '/imports/api/engine/action/functions/userInput/InputProvider';
|
||||||
import ParseNode from '/imports/parser/parseTree/ParseNode';
|
import ParseNode from '/imports/parser/parseTree/ParseNode';
|
||||||
import Context from '/imports/parser/types/Context';
|
import Context from '/imports/parser/types/Context';
|
||||||
import ResolveLevel from '/imports/parser/types/ResolveLevel';
|
import ResolveLevel from '/imports/parser/types/ResolveLevel';
|
||||||
|
|||||||
Reference in New Issue
Block a user