Added point buy to computation engine

This commit is contained in:
Stefan Zermatten
2022-08-19 14:03:12 +02:00
parent 28307e26c3
commit c6ca8c1fa4
14 changed files with 443 additions and 209 deletions

View File

@@ -14,6 +14,7 @@ const linkDependenciesByType = {
effect: linkEffects,
proficiency: linkProficiencies,
roll: linkRoll,
pointBuy: linkPointBuy,
propertySlot: linkSlot,
skill: linkSkill,
spell: linkAction,
@@ -242,6 +243,23 @@ function linkDamageMultiplier(dependencyGraph, prop) {
});
}
function linkPointBuy(dependencyGraph, prop){
dependOnCalc({ dependencyGraph, prop, key: 'min' });
dependOnCalc({ dependencyGraph, prop, key: 'max' });
dependOnCalc({ dependencyGraph, prop, key: 'cost' });
prop.values?.forEach(row => {
row.type = 'pointBuyRow';
row.tableName = prop.name;
row.tableId = prop._id;
dependencyGraph.addNode(row._id, row);
linkVariableName(dependencyGraph, row);
dependOnCalc({ dependencyGraph, row, key: 'min' });
dependOnCalc({ dependencyGraph, row, key: 'max' });
dependOnCalc({ dependencyGraph, row, key: 'cost' });
});
if (prop.inactive) return;
}
function linkProficiencies(dependencyGraph, prop){
// The stats depend on the proficiency
if (prop.inactive) return;

View File

@@ -2,6 +2,7 @@ import _variable from './computeByType/computeVariable.js';
import action from './computeByType/computeAction.js';
import attribute from './computeByType/computeAttribute.js';
import skill from './computeByType/computeSkill.js';
import pointBuy from './computeByType/computePointBuy.js';
import propertySlot from './computeByType/computeSlot.js';
import container from './computeByType/computeContainer.js';
import _calculation from './computeByType/computeCalculation.js';
@@ -13,6 +14,7 @@ export default Object.freeze({
attribute,
container,
skill,
pointBuy,
propertySlot,
spell: action,
});

View File

@@ -0,0 +1,50 @@
import { has } from 'lodash';
import evaluateCalculation from '../../utility/evaluateCalculation.js';
export default function computePointBuy(computation, node) {
const prop = node.data;
const tableMin = prop.min?.value || null;
const tableMax = prop.max?.value || null;
prop.spent = 0;
prop.values?.forEach(row => {
// Clean up added properties
delete row.tableId;
delete row.tableName;
delete row.type;
row.spent = 0;
if (row.value === undefined) return;
const min = has(row, 'min.value') ? row.min.value : tableMin;
const max = has(row, 'max.value') ? row.max.value : tableMax;
const costFunction = EJSON.clone(row.cost || prop.cost);
if (costFunction) costFunction.parseLevel = 'reduce';
// Check min and max
if (min !== null && row.value < min) {
row.errors = row.errors || [];
row.errors.push('Value smaller than min value');
}
if (max !== null && row.value > max) {
row.errors = row.errors || [];
row.errors.push('Value larger than max value');
}
// Evaluate the cost function
if (!costFunction) return;
evaluateCalculation(costFunction, { ...computation.scope, value: row.value });
// Write calculation errors
costFunction.errors?.forEach(error => {
if (error?.message) {
row.errors = row.errors || [];
row.errors.push(error.message);
}
});
if (Number.isFinite(costFunction.value)) {
row.spent = costFunction.value;
prop.spent += costFunction.value;
}
});
if (prop.spent > prop.total?.value) {
prop.errors = prop.errors || [];
prop.errors.push('Spent more than total points available')
}
}

View File

@@ -8,7 +8,13 @@ export default function aggregateDefinition({node, linkedNode, link}){
// get current defining prop
const definingProp = node.data.definingProp;
// Find the last defining prop
if (!definingProp || prop.order > definingProp.order){
if (
!definingProp ||
prop.type !== 'pointBuyRow' && (
definingProp.type === 'pointBuyRow' ||
prop.order > definingProp.order
)
) {
// override the current defining prop
overrideProp(definingProp, node);
// set this prop as the new defining prop
@@ -18,9 +24,32 @@ export default function aggregateDefinition({node, linkedNode, link}){
}
// Aggregate the base value due to the defining properties
const propBaseValue = prop.baseValue?.value;
let propBaseValue = prop.baseValue?.value;
// Point buy rows use prop.value instead of prop.baseValue
if (prop.type === 'pointBuyRow') {
propBaseValue = prop.value;
}
if (propBaseValue === undefined) return;
// Store a summary of the definition as a base value effect
node.data.effects = node.data.effects || [];
if (prop.type === 'pointBuyRow') {
node.data.effects.push({
_id: prop.tableId,
name: prop.tableName,
operation: 'base',
amount: { value: propBaseValue },
type: 'pointBuy',
});
} else {
node.data.effects.push({
_id: prop._id,
name: prop.name,
operation: 'base',
amount: { value: propBaseValue },
type: prop.type,
});
}
if (node.data.baseValue === undefined || propBaseValue > node.data.baseValue){
node.data.baseValue = propBaseValue;
}

View File

@@ -24,6 +24,7 @@ export default function aggregateEffect({node, linkedNode, link}){
name: linkedNode.data.name,
operation: linkedNode.data.operation,
amount: linkedNode.data.amount && {value: linkedNode.data.amount.value},
type: linkedNode.data.type,
// ancestors: linkedNode.data.ancestors,
});