Tested and fixed adjustments
This commit is contained in:
@@ -22,11 +22,16 @@ let LogContentSchema = new SimpleSchema({
|
|||||||
type: Boolean,
|
type: Boolean,
|
||||||
optional: true,
|
optional: true,
|
||||||
},
|
},
|
||||||
|
// This log entry was silenced
|
||||||
|
silenced: {
|
||||||
|
type: Boolean,
|
||||||
|
optional: true,
|
||||||
|
},
|
||||||
context: {
|
context: {
|
||||||
type: Object,
|
type: Object,
|
||||||
optional: true,
|
optional: true,
|
||||||
},
|
},
|
||||||
'context.errors':{
|
'context.errors': {
|
||||||
type: Array,
|
type: Array,
|
||||||
defaultValue: [],
|
defaultValue: [],
|
||||||
maxCount: STORAGE_LIMITS.errorCount,
|
maxCount: STORAGE_LIMITS.errorCount,
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import rollDice from '/imports/parser/rollDice';
|
|||||||
|
|
||||||
const Actions = new Mongo.Collection<ActionWithId>('actions');
|
const Actions = new Mongo.Collection<ActionWithId>('actions');
|
||||||
|
|
||||||
interface Action {
|
export interface Action {
|
||||||
creatureId: string;
|
creatureId: string;
|
||||||
rootPropId: string;
|
rootPropId: string;
|
||||||
targetIds?: string[];
|
targetIds?: string[];
|
||||||
@@ -27,6 +27,7 @@ interface ActionWithId extends Action {
|
|||||||
type Task = {
|
type Task = {
|
||||||
propId: string;
|
propId: string;
|
||||||
targetIds: string[];
|
targetIds: string[];
|
||||||
|
step?: number,
|
||||||
}
|
}
|
||||||
|
|
||||||
type TaskResult = {
|
type TaskResult = {
|
||||||
@@ -34,17 +35,11 @@ type TaskResult = {
|
|||||||
targetIds: string[];
|
targetIds: string[];
|
||||||
scope: any;
|
scope: any;
|
||||||
mutations: Mutation[];
|
mutations: Mutation[];
|
||||||
step?: number;
|
|
||||||
deferred?: boolean;
|
|
||||||
deferredState?: any;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class PartialTaskResult {
|
class PartialTaskResult {
|
||||||
scope: any;
|
scope: any;
|
||||||
mutations: Mutation[];
|
mutations: Mutation[];
|
||||||
step?: number;
|
|
||||||
deferred?: boolean;
|
|
||||||
deferredState?: any;
|
|
||||||
constructor() {
|
constructor() {
|
||||||
this.scope = {};
|
this.scope = {};
|
||||||
this.mutations = [];
|
this.mutations = [];
|
||||||
@@ -66,17 +61,19 @@ type Mutation = {
|
|||||||
// Which creatures the mutation is applied to
|
// Which creatures the mutation is applied to
|
||||||
targetIds: string[];
|
targetIds: string[];
|
||||||
// What changes in the database
|
// What changes in the database
|
||||||
updates?: {
|
updates?: Update[];
|
||||||
propId: string;
|
|
||||||
set?: any;
|
|
||||||
inc?: any;
|
|
||||||
type: string,
|
|
||||||
}[];
|
|
||||||
// Logged when this is applied
|
// Logged when this is applied
|
||||||
contents?: LogContent[];
|
contents?: LogContent[];
|
||||||
}
|
}
|
||||||
|
|
||||||
type LogContent = {
|
export type Update = {
|
||||||
|
propId: string;
|
||||||
|
type: string,
|
||||||
|
set?: any;
|
||||||
|
inc?: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type LogContent = {
|
||||||
name?: string;
|
name?: string;
|
||||||
value?: string;
|
value?: string;
|
||||||
inline?: boolean;
|
inline?: boolean;
|
||||||
@@ -123,6 +120,10 @@ const ActionSchema = new SimpleSchema({
|
|||||||
type: String,
|
type: String,
|
||||||
regEx: SimpleSchema.RegEx.Id,
|
regEx: SimpleSchema.RegEx.Id,
|
||||||
},
|
},
|
||||||
|
'taskQueue.$.step': {
|
||||||
|
type: Number,
|
||||||
|
optional: true,
|
||||||
|
},
|
||||||
'taskQueue.$.targetIds': {
|
'taskQueue.$.targetIds': {
|
||||||
type: Array,
|
type: Array,
|
||||||
defaultValue: [],
|
defaultValue: [],
|
||||||
@@ -202,11 +203,20 @@ const ActionSchema = new SimpleSchema({
|
|||||||
type: String,
|
type: String,
|
||||||
regEx: SimpleSchema.RegEx.Id,
|
regEx: SimpleSchema.RegEx.Id,
|
||||||
},
|
},
|
||||||
|
// Required, because CreatureProperties.update requires a selector of { type }
|
||||||
|
'results.$.mutations.$.updates.$.type': {
|
||||||
|
type: String,
|
||||||
|
},
|
||||||
'results.$.mutations.$.updates.$.set': {
|
'results.$.mutations.$.updates.$.set': {
|
||||||
type: Object,
|
type: Object,
|
||||||
optional: true,
|
optional: true,
|
||||||
blackbox: true,
|
blackbox: true,
|
||||||
},
|
},
|
||||||
|
'results.$.mutations.$.updates.$.inc': {
|
||||||
|
type: Object,
|
||||||
|
optional: true,
|
||||||
|
blackbox: true,
|
||||||
|
},
|
||||||
'results.$.mutations.$.contents': {
|
'results.$.mutations.$.contents': {
|
||||||
type: Array,
|
type: Array,
|
||||||
optional: true,
|
optional: true,
|
||||||
@@ -262,9 +272,13 @@ export async function runAction(actionId: string, userInput?) {
|
|||||||
return writePromise;
|
return writePromise;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function applyNextTask(action, userInput?) {
|
// TODO create a function to get the effective value of a property,
|
||||||
|
// simulating all the result updates in the action so far
|
||||||
|
|
||||||
|
async function applyNextTask(action: Action, userInput?) {
|
||||||
// Get the next task
|
// Get the next task
|
||||||
const task = action.taskQueue[0];
|
const task = action.taskQueue.shift();
|
||||||
|
if (!task) throw 'Next task does not exist';
|
||||||
// Get the property from the action's task properties or the creature's properties
|
// Get the property from the action's task properties or the creature's properties
|
||||||
let prop;
|
let prop;
|
||||||
const taskProp = action.taskProperties[task.propId];
|
const taskProp = action.taskProperties[task.propId];
|
||||||
@@ -278,26 +292,15 @@ async function applyNextTask(action, userInput?) {
|
|||||||
if (prop.deactivatedByToggle) return;
|
if (prop.deactivatedByToggle) return;
|
||||||
|
|
||||||
// Apply the property
|
// Apply the property
|
||||||
const result: TaskResult | undefined = await applyPropertyByType[prop.type]?.(prop, task, action, userInput);
|
const result: PartialTaskResult = await applyPropertyByType[prop.type]?.(prop, task, action, userInput);
|
||||||
|
// store the task's details and save the result
|
||||||
if (result) {
|
result.scope[`#${prop.type}`] = prop;
|
||||||
// store the task's details and save the result
|
action.results.push({
|
||||||
result.scope[`#${prop.type}`] = prop;
|
propId: task.propId,
|
||||||
result.propId = task.propId;
|
targetIds: task.targetIds,
|
||||||
result.targetIds = task.targetIds;
|
scope: result.scope,
|
||||||
if (result.deferred) {
|
mutations: result.mutations,
|
||||||
delete result.deferred;
|
});
|
||||||
result.step = (result.step || 0) + 1;
|
|
||||||
action.deferredResults[task.propId] = result;
|
|
||||||
} else {
|
|
||||||
// There was a result and it wasn't deferred, we can remove this task from the queue
|
|
||||||
action.taskQueue.shift();
|
|
||||||
action.results.push(result);
|
|
||||||
}
|
|
||||||
} else if (!action.userInputNeeded) {
|
|
||||||
// Prevent accidental infinite loops if we don't remove the task, but also don't break for input
|
|
||||||
throw 'The only time result can be undefined is if we are waiting for user input';
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function writeChangedAction(original: ActionWithId, changed: ActionWithId) {
|
function writeChangedAction(original: ActionWithId, changed: ActionWithId) {
|
||||||
@@ -360,15 +363,21 @@ function createResult(): PartialTaskResult {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Combine all the action results into the scope at present
|
// Combine all the action results into the scope at present
|
||||||
export function getEffectiveActionScope(action) {
|
export function getEffectiveActionScope(action: Action) {
|
||||||
const scope = getVariables(action.creatureId);
|
const scope = getVariables(action.creatureId);
|
||||||
|
// First combine the applied results
|
||||||
for (const result of action.results) {
|
for (const result of action.results) {
|
||||||
Object.assign(scope, result.scope);
|
Object.assign(scope, result.scope);
|
||||||
}
|
}
|
||||||
|
// Then the deferred results
|
||||||
|
// Warning: order is not guaranteed here
|
||||||
|
for (const id in action.deferredResults) {
|
||||||
|
const result = action.deferredResults[id];
|
||||||
|
Object.assign(scope, result.scope);
|
||||||
|
}
|
||||||
return scope;
|
return scope;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
type DamageProp = {
|
type DamageProp = {
|
||||||
_id?: string;
|
_id?: string;
|
||||||
operation: 'increment' | 'set';
|
operation: 'increment' | 'set';
|
||||||
@@ -547,18 +556,30 @@ const applyPropertyByType = {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'choice': {
|
case 'choice': {
|
||||||
// If there is no input to consume, return no result, but mark the action as requiring input
|
// Step 0, halt the action to get user input
|
||||||
if (!userInput) {
|
if (!task.step) {
|
||||||
|
// Mark the action as needing user input so that it halts
|
||||||
action.userInputNeeded = pick(prop, ['_id', 'type', 'branchType']);
|
action.userInputNeeded = pick(prop, ['_id', 'type', 'branchType']);
|
||||||
return;
|
// Put this task back in the queue, but at step 1
|
||||||
|
action.taskQueue.push({
|
||||||
|
...task,
|
||||||
|
step: 1,
|
||||||
|
});
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
const children = await getPropertyChildren(action.creatureId, prop._id);
|
// Step 1 consume the user input
|
||||||
let index = userInput.choice;
|
else if (task.step === 1) {
|
||||||
if (!isFinite(index) || index < 0) index = 0;
|
if (!userInput) {
|
||||||
if (index > children.length - 1) index = children.length - 1;
|
throw 'User input was required for this step'
|
||||||
pushPropAndTriggers(action, children[index], targets);
|
}
|
||||||
pushAfterChildrenTriggers(action, prop, targets);
|
const children = await getPropertyChildren(action.creatureId, prop._id);
|
||||||
break;
|
let index = userInput.choice;
|
||||||
|
if (!isFinite(index) || index < 0) index = 0;
|
||||||
|
if (index > children.length - 1) index = children.length - 1;
|
||||||
|
pushPropAndTriggers(action, children[index], targets);
|
||||||
|
pushAfterChildrenTriggers(action, prop, targets);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -566,9 +587,7 @@ const applyPropertyByType = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
async adjustment(prop, task: Task, action: Action): Promise<PartialTaskResult> {
|
async adjustment(prop, task: Task, action: Action): Promise<PartialTaskResult> {
|
||||||
|
const result = createResult();
|
||||||
let result = action.deferredResults[task.propId];
|
|
||||||
if (!result) result = createResult();
|
|
||||||
|
|
||||||
const queueChildren = async function (targetIds) {
|
const queueChildren = async function (targetIds) {
|
||||||
await pushChildren(action, prop, targetIds);
|
await pushChildren(action, prop, targetIds);
|
||||||
@@ -576,9 +595,10 @@ const applyPropertyByType = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const damageTargets = prop.target === 'self' ? [action.creatureId] : task.targetIds;
|
const damageTargets = prop.target === 'self' ? [action.creatureId] : task.targetIds;
|
||||||
|
task.targetIds = damageTargets;
|
||||||
|
|
||||||
// Step 0, get the operation and value and push the damage pseudo prop to the queue
|
// Step 0, get the operation and value and push the damage pseudo prop to the queue
|
||||||
if (!result.step) {
|
if (!task.step) {
|
||||||
|
|
||||||
if (!prop.amount) {
|
if (!prop.amount) {
|
||||||
queueChildren(task.targetIds);
|
queueChildren(task.targetIds);
|
||||||
@@ -587,7 +607,6 @@ const applyPropertyByType = {
|
|||||||
|
|
||||||
// Evaluate the amount
|
// Evaluate the amount
|
||||||
recalculateCalculation(prop.amount, action, 'reduce');
|
recalculateCalculation(prop.amount, action, 'reduce');
|
||||||
|
|
||||||
const value = +prop.amount.value;
|
const value = +prop.amount.value;
|
||||||
if (!isFinite(value)) {
|
if (!isFinite(value)) {
|
||||||
queueChildren(task.targetIds);
|
queueChildren(task.targetIds);
|
||||||
@@ -596,7 +615,6 @@ const applyPropertyByType = {
|
|||||||
|
|
||||||
if (damageTargets?.length) {
|
if (damageTargets?.length) {
|
||||||
for (const targetId of damageTargets) {
|
for (const targetId of damageTargets) {
|
||||||
queueChildren([targetId]);
|
|
||||||
const statId = getVariables(targetId)?.[prop.stat]?._propId;
|
const statId = getVariables(targetId)?.[prop.stat]?._propId;
|
||||||
if (!statId) continue;
|
if (!statId) continue;
|
||||||
|
|
||||||
@@ -610,22 +628,37 @@ const applyPropertyByType = {
|
|||||||
}, [targetId]);
|
}, [targetId]);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
// Do the damage
|
||||||
pushDamagePropertyTasks(action, {
|
pushDamagePropertyTasks(action, {
|
||||||
type: 'damageProp',
|
type: 'damageProp',
|
||||||
value,
|
value,
|
||||||
operation: prop.operation,
|
operation: prop.operation,
|
||||||
targetPropId: stat._id,
|
targetPropId: stat._id,
|
||||||
}, stat, [targetId], result);
|
}, stat, [targetId], result);
|
||||||
|
// Do the next step of this property
|
||||||
|
action.taskQueue.push({
|
||||||
|
...task,
|
||||||
|
step: 1,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
result.deferred = true;
|
|
||||||
result.deferredState = { value };
|
|
||||||
}
|
}
|
||||||
// Step 1, Log the results
|
// Step 1, Log the results
|
||||||
else if (result.step === 1) {
|
else if (task.step === 1) {
|
||||||
const value = result.deferredState.value;
|
const scope = getEffectiveActionScope(action);
|
||||||
|
let value;
|
||||||
|
if (prop.operation === 'increment') {
|
||||||
|
if (prop.value >= 0) {
|
||||||
|
value = scope['~damage']?.value;
|
||||||
|
} else {
|
||||||
|
value = -scope['~healing']?.value;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
value = scope['~set']?.value;
|
||||||
|
}
|
||||||
if (damageTargets?.length) {
|
if (damageTargets?.length) {
|
||||||
for (const targetId of damageTargets) {
|
for (const targetId of damageTargets) {
|
||||||
|
await queueChildren([targetId]);
|
||||||
result.appendLog({
|
result.appendLog({
|
||||||
name: 'Attribute damage',
|
name: 'Attribute damage',
|
||||||
value: `${prop.stat}${prop.operation === 'set' ? ' set to' : ''}` +
|
value: `${prop.stat}${prop.operation === 'set' ? ' set to' : ''}` +
|
||||||
@@ -635,6 +668,7 @@ const applyPropertyByType = {
|
|||||||
}, [targetId]);
|
}, [targetId]);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
await queueChildren(task.targetIds);
|
||||||
result.appendLog({
|
result.appendLog({
|
||||||
name: 'Attribute damage',
|
name: 'Attribute damage',
|
||||||
value: `${prop.stat}${prop.operation === 'set' ? ' set to' : ''}` +
|
value: `${prop.stat}${prop.operation === 'set' ? ' set to' : ''}` +
|
||||||
@@ -662,7 +696,6 @@ const applyPropertyByType = {
|
|||||||
} else {
|
} else {
|
||||||
value = scope['~set']?.value;
|
value = scope['~set']?.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
let damage, newValue, increment;
|
let damage, newValue, increment;
|
||||||
if (task.targetIds.length) {
|
if (task.targetIds.length) {
|
||||||
for (const targetId of task.targetIds) {
|
for (const targetId of task.targetIds) {
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import CreatureProperties from '/imports/api/creature/creatureProperties/Creatur
|
|||||||
import { propsFromForest } from '/imports/api/properties/tests/propTestBuilder.testFn';
|
import { propsFromForest } from '/imports/api/properties/tests/propTestBuilder.testFn';
|
||||||
import Creatures from '/imports/api/creature/creatures/Creatures';
|
import Creatures from '/imports/api/creature/creatures/Creatures';
|
||||||
import CreatureVariables from '/imports/api/creature/creatures/CreatureVariables';
|
import CreatureVariables from '/imports/api/creature/creatures/CreatureVariables';
|
||||||
import Actions, { createAction, runAction } from '/imports/api/engine/actions/Actions';
|
import Actions, { Action, Update, LogContent, createAction, runAction } from '/imports/api/engine/actions/Actions';
|
||||||
import computeCreature from '/imports/api/engine/computeCreature';
|
import computeCreature from '/imports/api/engine/computeCreature';
|
||||||
|
|
||||||
let creatureId;
|
let creatureId;
|
||||||
@@ -23,31 +23,60 @@ describe('Interrupt action system', function () {
|
|||||||
computeCreature(creatureId);
|
computeCreature(creatureId);
|
||||||
});
|
});
|
||||||
it('writes notes to the log', async function () {
|
it('writes notes to the log', async function () {
|
||||||
assert.equal(
|
const action = await runActionById(note1Id);
|
||||||
await testRunActionById(note1Id),
|
assert.deepEqual(
|
||||||
'Note 1 summary. 1 + 1 = 2'
|
allLogContent(action),
|
||||||
|
[{ value: 'Note 1 summary. 1 + 1 = 2' }]
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
it('Applies the children of if branches', async function () {
|
it('Applies the children of if branches', async function () {
|
||||||
assert.equal(
|
let action = await runActionById(ifTruthyBranchId);
|
||||||
await testRunActionById(ifTruthyBranchId),
|
assert.deepEqual(
|
||||||
'child of if branch'
|
allLogContent(action),
|
||||||
|
[{ value: 'child of if branch' }]
|
||||||
);
|
);
|
||||||
assert.isUndefined(
|
action = await runActionById(ifFalsyBranchId);
|
||||||
await testRunActionById(ifFalsyBranchId)
|
assert.deepEqual(
|
||||||
|
allLogContent(action),
|
||||||
|
[]
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
it('Applies the children of index branches', async function () {
|
it('Applies the children of index branches', async function () {
|
||||||
assert.equal(
|
const action = await runActionById(indexBranchId);
|
||||||
await testRunActionById(indexBranchId),
|
assert.deepEqual(
|
||||||
'child 2 of index branch'
|
allLogContent(action),
|
||||||
|
[{ value: 'child 2 of index branch' }]
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
it('Halts execution of choice branches', async function () {
|
it('Halts execution of choice branches', async function () {
|
||||||
const action = await runActionById(choiceBranchId);
|
const action = await runActionById(choiceBranchId);
|
||||||
if (!action) throw 'Action is expected to exist';
|
|
||||||
assert.isUndefined(action.results[0]);
|
|
||||||
assert.exists(action.userInputNeeded);
|
assert.exists(action.userInputNeeded);
|
||||||
|
assert.deepEqual(
|
||||||
|
allLogContent(action),
|
||||||
|
[]
|
||||||
|
);
|
||||||
|
});
|
||||||
|
it('Applies adjustments', async function () {
|
||||||
|
let action = await runActionById(adjustmentSetId)
|
||||||
|
assert.deepEqual(
|
||||||
|
allUpdates(action),
|
||||||
|
[{
|
||||||
|
propId: adjustedStatId,
|
||||||
|
type: 'attribute',
|
||||||
|
set: { damage: 5, value: 3 },
|
||||||
|
}],
|
||||||
|
'Applying set adjustments should return the correct updates'
|
||||||
|
);
|
||||||
|
action = await runActionById(adjustmentIncrementId)
|
||||||
|
assert.deepEqual(
|
||||||
|
allUpdates(action),
|
||||||
|
[{
|
||||||
|
propId: adjustedStatId,
|
||||||
|
type: 'attribute',
|
||||||
|
inc: { damage: 2, value: -2 }, // damage goes up by 2, value down by 2
|
||||||
|
}],
|
||||||
|
'Applying increment adjustments should return the correct updates'
|
||||||
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -56,15 +85,35 @@ async function runActionById(propId) {
|
|||||||
const actionId = await createAction(prop);
|
const actionId = await createAction(prop);
|
||||||
await runAction(actionId);
|
await runAction(actionId);
|
||||||
const action = await Actions.findOneAsync(actionId);
|
const action = await Actions.findOneAsync(actionId);
|
||||||
|
if (!action) throw 'Action is expected to exist'
|
||||||
return action;
|
return action;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function testRunActionById(propId) {
|
function allUpdates(action: Action) {
|
||||||
const action = await runActionById(propId);
|
const updates: Update[] = [];
|
||||||
return action?.results?.[action.results.length - 1]?.mutations?.[0]?.contents?.[0]?.value;
|
action.results.forEach(result => {
|
||||||
|
result.mutations.forEach(mutation => {
|
||||||
|
mutation.updates?.forEach(update => {
|
||||||
|
updates.push(update);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
return updates;
|
||||||
}
|
}
|
||||||
|
|
||||||
let note1Id, ifTruthyBranchId, ifFalsyBranchId, indexBranchId, choiceBranchId;
|
function allLogContent(action: Action) {
|
||||||
|
const contents: LogContent[] = [];
|
||||||
|
action.results.forEach(result => {
|
||||||
|
result.mutations.forEach(mutation => {
|
||||||
|
mutation.contents?.forEach(logContent => {
|
||||||
|
contents.push(logContent);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
return contents;
|
||||||
|
}
|
||||||
|
|
||||||
|
let note1Id, ifTruthyBranchId, ifFalsyBranchId, indexBranchId, choiceBranchId, adjustedStatId, adjustmentIncrementId, adjustmentSetId;
|
||||||
|
|
||||||
const propForest = [
|
const propForest = [
|
||||||
// Apply a simple note
|
// Apply a simple note
|
||||||
@@ -114,6 +163,34 @@ const propForest = [
|
|||||||
{ type: 'note', summary: { text: 'child 3 of choice branch' } },
|
{ type: 'note', summary: { text: 'child 3 of choice branch' } },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
// Apply adjustments
|
||||||
|
{
|
||||||
|
_id: adjustedStatId = Random.id(),
|
||||||
|
type: 'attribute',
|
||||||
|
attributeType: 'stat',
|
||||||
|
variableName: 'adjustedStat',
|
||||||
|
baseValue: { calculation: '8' },
|
||||||
|
}, {
|
||||||
|
_id: adjustmentSetId = Random.id(),
|
||||||
|
type: 'adjustment',
|
||||||
|
stat: 'adjustedStat',
|
||||||
|
operation: 'set',
|
||||||
|
amount: { calculation: '3' },
|
||||||
|
target: 'self',
|
||||||
|
children: [
|
||||||
|
{ type: 'note', summary: { text: 'adjustment set applied' } },
|
||||||
|
],
|
||||||
|
}, {
|
||||||
|
_id: adjustmentIncrementId = Random.id(),
|
||||||
|
type: 'adjustment',
|
||||||
|
stat: 'adjustedStat',
|
||||||
|
operation: 'increment',
|
||||||
|
amount: { calculation: '2' },
|
||||||
|
target: 'self',
|
||||||
|
children: [
|
||||||
|
{ type: 'note', summary: { text: 'adjustment increment applied' } },
|
||||||
|
],
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
function insertActionTestProps() {
|
function insertActionTestProps() {
|
||||||
|
|||||||
Reference in New Issue
Block a user