Merge commit 'd9b978cb82109b71c05d03807a8558ba1dc537a4' into feature-tabletop
This commit is contained in:
@@ -2,22 +2,22 @@
|
||||
* Performs a depth first traversal of the character tree, summing the container
|
||||
* and inventory contents on the way up the tree
|
||||
*/
|
||||
export default function linkInventory(forest, dependencyGraph){
|
||||
export default function linkInventory(forest, dependencyGraph) {
|
||||
// The stack of properties to still navigate
|
||||
const stack = [...forest];
|
||||
// The current containers we are inside of
|
||||
const containerStack = [];
|
||||
|
||||
while(stack.length){
|
||||
while (stack.length) {
|
||||
const top = stack[stack.length - 1];
|
||||
const prop = top.node;
|
||||
if (prop._computationDetails.inventoryChildrenVisited){
|
||||
if (prop._computationDetails.inventoryChildrenVisited) {
|
||||
if (prop.type === 'container') containerStack.pop();
|
||||
stack.pop();
|
||||
handleProp(prop, containerStack, dependencyGraph);
|
||||
} else {
|
||||
// Add all containers to the stack when we first visit them
|
||||
if (prop.type === 'container'){
|
||||
if (prop.type === 'container') {
|
||||
containerStack.push(top.node);
|
||||
}
|
||||
// Push children onto the stack and mark this as children are visited
|
||||
@@ -27,18 +27,18 @@ export default function linkInventory(forest, dependencyGraph){
|
||||
}
|
||||
}
|
||||
|
||||
function handleProp(prop, containerStack, dependencyGraph){
|
||||
function handleProp(prop, containerStack, dependencyGraph) {
|
||||
// Skip props that aren't part of the inventory
|
||||
if (prop.type !== 'item' && prop.type !== 'container') return;
|
||||
// Determine if this property is carried, items are carried by default
|
||||
let carried = prop.type === 'container' ? prop.carried : true;
|
||||
|
||||
// Item-specific links
|
||||
if (prop.type === 'item'){
|
||||
if (prop.attuned){
|
||||
if (prop.type === 'item') {
|
||||
if (prop.attuned) {
|
||||
dependencyGraph.addLink('itemsAttuned', prop._id, 'attunedItem');
|
||||
}
|
||||
if (prop.equipped){
|
||||
if (prop.equipped) {
|
||||
dependencyGraph.addLink('weightEquipment', prop._id, 'equippedItem');
|
||||
dependencyGraph.addLink('valueEquipment', prop._id, 'equippedItem');
|
||||
}
|
||||
@@ -47,14 +47,14 @@ function handleProp(prop, containerStack, dependencyGraph){
|
||||
// Get the parent container
|
||||
const container = containerStack[containerStack.length - 1];
|
||||
|
||||
if (container){
|
||||
if (container) {
|
||||
// The container depends on this prop for its contents data
|
||||
dependencyGraph.addLink(container._id, prop._id, 'containerContents');
|
||||
} else {
|
||||
// There is no parent container, the character totals depend on this prop
|
||||
dependencyGraph.addLink('weightTotal', prop._id, 'inventoryStats');
|
||||
dependencyGraph.addLink('valueTotal', prop._id, 'inventoryStats');
|
||||
if (carried){
|
||||
if (carried) {
|
||||
dependencyGraph.addLink('weightCarried', prop._id, 'inventoryStats');
|
||||
dependencyGraph.addLink('valueCarried', prop._id, 'inventoryStats');
|
||||
}
|
||||
|
||||
@@ -80,6 +80,15 @@ function linkAction(dependencyGraph, prop, { propsById }) {
|
||||
key: `resources.attributesConsumed[${index}].quantity`,
|
||||
});
|
||||
});
|
||||
// Link conditions
|
||||
prop.resources.conditions?.forEach((con, index) => {
|
||||
// Link the property to its condition calculation
|
||||
dependOnCalc({
|
||||
dependencyGraph,
|
||||
prop,
|
||||
key: `resources.conditions[${index}].condition`,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function linkAdjustment(dependencyGraph, prop) {
|
||||
|
||||
@@ -8,14 +8,21 @@ export default function computeAction(computation, node) {
|
||||
}
|
||||
computeResources(computation, node);
|
||||
if (!prop.resources) return;
|
||||
prop.resources.itemsConsumed.forEach(itemConsumed => {
|
||||
prop.resources.conditions?.forEach(conObj => {
|
||||
const condition = conObj.condition;
|
||||
if (!condition) return;
|
||||
if (condition.calculation && !condition.value) {
|
||||
prop.insufficientResources = true;
|
||||
}
|
||||
});
|
||||
prop.resources.itemsConsumed?.forEach(itemConsumed => {
|
||||
if (!itemConsumed.itemId || itemConsumed.available < itemConsumed.quantity?.value) {
|
||||
prop.insufficientResources = true;
|
||||
}
|
||||
});
|
||||
prop.resources.attributesConsumed.forEach(attConsumed => {
|
||||
prop.resources.attributesConsumed?.forEach(attConsumed => {
|
||||
if (!attConsumed.variableName) return;
|
||||
if (attConsumed.available < attConsumed.quantity?.value) {
|
||||
if (!(attConsumed.available >= attConsumed.quantity?.value)) {
|
||||
prop.insufficientResources = true;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1,11 +1,17 @@
|
||||
import aggregate from './computeVariable/aggregate/index.js';
|
||||
import { safeStrip } from '/imports/api/engine/computation/utility/stripFloatingPointOddities.js';
|
||||
|
||||
export default function computeContainer(computation, node){
|
||||
export default function computeContainer(computation, node) {
|
||||
if (!node.data) node.data = {};
|
||||
aggregateLinks(computation, node);
|
||||
|
||||
// Clean up floating points
|
||||
const prop = node.data;
|
||||
prop.contentsWeight = safeStrip(prop.contentsWeight);
|
||||
prop.carriedWeight = safeStrip(prop.carriedWeight);
|
||||
}
|
||||
|
||||
function aggregateLinks(computation, node){
|
||||
function aggregateLinks(computation, node) {
|
||||
computation.dependencyGraph.forEachLinkedNode(
|
||||
node.id,
|
||||
(linkedNode, link) => {
|
||||
@@ -13,7 +19,7 @@ function aggregateLinks(computation, node){
|
||||
// Ignore inactive props
|
||||
if (linkedNode.data.inactive) return;
|
||||
// Aggregate inventory links
|
||||
aggregate.inventory({node, linkedNode, link});
|
||||
aggregate.inventory({ node, linkedNode, link });
|
||||
},
|
||||
true // enumerate only outbound links
|
||||
);
|
||||
|
||||
@@ -1,25 +1,25 @@
|
||||
export default function aggregateInventory({node, linkedNode, link}){
|
||||
export default function aggregateInventory({ node, linkedNode, link }) {
|
||||
let linkedProp = linkedNode.data || {};
|
||||
const prop = node.data;
|
||||
|
||||
switch (link.data){
|
||||
switch (link.data) {
|
||||
case 'attunedItem':
|
||||
prop.baseValue = (prop.baseValue || 0) + 1;
|
||||
return;
|
||||
|
||||
case 'equippedItem':
|
||||
if (node.id === 'weightEquipment'){
|
||||
if (node.id === 'weightEquipment') {
|
||||
prop.baseValue = (prop.baseValue || 0) + weight(linkedProp);
|
||||
} else if (node.id === 'valueEquipment'){
|
||||
} else if (node.id === 'valueEquipment') {
|
||||
prop.baseValue = (prop.baseValue || 0) + value(linkedProp);
|
||||
}
|
||||
return;
|
||||
|
||||
case 'containerContents':
|
||||
// Add this property's weights and values to the container
|
||||
if (!prop.weightless){
|
||||
if (!prop.weightless) {
|
||||
prop.contentsWeight = (prop.contentsWeight || 0) + weight(linkedProp);
|
||||
if (prop.carried){
|
||||
if (prop.carried && !prop.contentsWeightless) {
|
||||
prop.carriedWeight = (prop.carriedWeight || 0) + carriedWeight(linkedProp);
|
||||
}
|
||||
}
|
||||
@@ -30,39 +30,39 @@ export default function aggregateInventory({node, linkedNode, link}){
|
||||
return;
|
||||
|
||||
case 'inventoryStats':
|
||||
if (node.id === 'weightTotal'){
|
||||
if (node.id === 'weightTotal') {
|
||||
prop.baseValue = (prop.baseValue || 0) + weight(linkedProp);
|
||||
} else if (node.id === 'valueTotal'){
|
||||
} else if (node.id === 'valueTotal') {
|
||||
prop.baseValue = (prop.baseValue || 0) + value(linkedProp);
|
||||
} else if (node.id === 'weightCarried'){
|
||||
} else if (node.id === 'weightCarried') {
|
||||
prop.baseValue = (prop.baseValue || 0) + carriedWeight(linkedProp);
|
||||
} else if (node.id === 'valueCarried'){
|
||||
} else if (node.id === 'valueCarried') {
|
||||
prop.baseValue = (prop.baseValue || 0) + carriedValue(linkedProp);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
function quantity(prop){
|
||||
if (typeof prop.quantity === 'number'){
|
||||
function quantity(prop) {
|
||||
if (typeof prop.quantity === 'number') {
|
||||
return prop.quantity;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
function weight(prop){
|
||||
function weight(prop) {
|
||||
return (prop.weight || 0) * quantity(prop) + (prop.contentsWeight || 0);
|
||||
}
|
||||
|
||||
function carriedWeight(prop){
|
||||
function carriedWeight(prop) {
|
||||
return (prop.weight || 0) * quantity(prop) + (prop.carriedWeight || 0);
|
||||
}
|
||||
|
||||
function value (prop){
|
||||
function value(prop) {
|
||||
return (prop.value || 0) * quantity(prop) + (prop.contentsValue || 0);
|
||||
}
|
||||
|
||||
function carriedValue (prop){
|
||||
function carriedValue(prop) {
|
||||
return (prop.value || 0) * quantity(prop) + (prop.carriedValue || 0);
|
||||
}
|
||||
|
||||
@@ -5,8 +5,26 @@ export default function evaluateToggles(computation, node) {
|
||||
if (!toggles) return;
|
||||
toggles.forEach(toggle => {
|
||||
if (
|
||||
(!toggle.enabled && !toggle.disabled && toggle.condition && !toggle.condition.value)
|
||||
|| (toggle.disabled)
|
||||
(
|
||||
// Toggle isn't set to constantly enabled or disabled
|
||||
!toggle.enabled &&
|
||||
!toggle.disabled &&
|
||||
// Toggle is not disabled by another toggle targeting it
|
||||
// Ancestor toggles would've handled this child anyway,
|
||||
// and tag targeted toggles break the link
|
||||
!toggle.deactivatedByToggle &&
|
||||
!toggle.deactivatedByAncestor &&
|
||||
// Toggle has a condition with a falsy value
|
||||
toggle.condition &&
|
||||
!toggle.condition.value
|
||||
)
|
||||
|| (
|
||||
// Toggle is disabled manually
|
||||
toggle.disabled &&
|
||||
// Toggle isn't deactivated by something else
|
||||
!toggle.deactivatedByToggle &&
|
||||
!toggle.deactivatedByAncestor
|
||||
)
|
||||
) {
|
||||
prop.inactive = true;
|
||||
prop.deactivatedByToggle = true;
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
export default function stripFloatingPointOddities(num, precision = 12){
|
||||
export default function stripFloatingPointOddities(num, precision = 12) {
|
||||
return +parseFloat(num.toPrecision(precision))
|
||||
}
|
||||
|
||||
export function safeStrip(num, precision = 12) {
|
||||
if (!Number.isFinite(num)) return num;
|
||||
return stripFloatingPointOddities(num, precision);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user