Progress on action choices

This commit is contained in:
Thaum Rystra
2024-03-30 21:12:35 +02:00
parent 6c3d4b91eb
commit 6138be8083
33 changed files with 210 additions and 55 deletions

View File

@@ -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

View File

@@ -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();

View File

@@ -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[];

View File

@@ -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(

View File

@@ -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';

View File

@@ -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';

View File

@@ -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

View File

@@ -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';

View File

@@ -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';

View File

@@ -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';

View File

@@ -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';

View File

@@ -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';

View File

@@ -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
*/ */

View File

@@ -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;

View File

@@ -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

View File

@@ -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

View File

@@ -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,

View File

@@ -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;

View File

@@ -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);
}
}

View File

@@ -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;
}

View File

@@ -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 = {
/** /**

View File

@@ -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;
}

View File

@@ -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;
}, },

View File

@@ -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';

View File

@@ -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(

View File

@@ -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

View File

@@ -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;

View File

@@ -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';

View File

@@ -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';

View File

@@ -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';

View File

@@ -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';

View File

@@ -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';

View File

@@ -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';