Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add an option for flat reductions to damage multipliers #333

Open
wants to merge 8 commits into
base: develop
Choose a base branch
from
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,14 @@ function applyDamageMultipliers({ target, damage, damageProp, logValue }) {
logValue.push(`Vulnerable to ${damageTypeText}`);
damage = Math.floor(damage * 2);
}
if (
multiplier.reduction &&
some(multiplier.reductions, multiplierAppliesTo(damageProp, 'reduction'))
) {
let reductionAmount = multiplier.reductions.filter(multiplierAppliesTo(damageProp, 'reduction')).reduce((a,b) => a+b.reductionAmount.value, 0);
logValue.push(`${damageType[0].toUpperCase()}${damageTypeText.slice(1)} reduced by ${reductionAmount}`);
damage = Math.max(damage - reductionAmount, 0);
}
}
return damage;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,7 @@ function linkDamageMultiplier(dependencyGraph, prop) {
const damageName = damageType.replace(/[^a-z]/gi, '')
dependencyGraph.addLink(damageName, prop._id, prop.type);
});
dependOnCalc({ dependencyGraph, prop, key: 'reductionAmount' });
}

function linkPointBuy(dependencyGraph, prop) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export default function computeVariable(computation, node) {
scope[node.id] = node.data.definingProp
} else {
// Otherwise add an implicit variable to the scope
scope[node.id] = computeImplicitVariable(node);
scope[node.id] = computeImplicitVariable(computation, node);
}
}

Expand Down Expand Up @@ -69,6 +69,10 @@ function computeVariableProp(computation, node, prop) {
prop.vulnerability = node.data.vulnerability;
prop.vulnerabilities = node.data.vulnerabilities;
}
if (node.data.reduction) {
prop.reduction = node.data.reduction;
prop.reductions = node.data.reductions;
}

if (prop.type === 'attribute') {
computeVariableAsAttribute(computation, node, prop);
Expand Down Expand Up @@ -101,4 +105,8 @@ function combineMultiplierAggregator(node) {
node.data.vulnerability = true;
node.data.vulnerabilities = aggregator.vulnerabilities;
}
if (aggregator.reductions?.length) {
node.data.reduction = true;
node.data.reductions = aggregator.reductions;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ export default function aggregateDamageMultipliers({node, linkedNode, link}){
immunities: [],
resistances: [],
vulnerabilities: [],
reductions: [],
}
// Store a short reference to the aggregator
const aggregator = node.data.multiplierAggregator;
Expand All @@ -23,6 +24,9 @@ export default function aggregateDamageMultipliers({node, linkedNode, link}){
if (linkedNode.data.includeTags?.length){
keysToStore.push('includeTags');
}
if (linkedNode.data.value === -1){
keysToStore.push('reductionAmount');
}
const storedMultiplier = pick(linkedNode.data, keysToStore);

// Store the multiplier in the appropriate field
Expand All @@ -32,5 +36,7 @@ export default function aggregateDamageMultipliers({node, linkedNode, link}){
aggregator.resistances.push(storedMultiplier);
} else if (multiplierValue === 2){
aggregator.vulnerabilities.push(storedMultiplier);
} else if (multiplierValue === -1 && linkedNode.data.reductionAmount){
aggregator.reductions.push(storedMultiplier);
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import evaluateCalculation from '../../../utility/evaluateCalculation.js';
import getAggregatorResult from './getAggregatorResult.js';

/*
* Variables with effects, proficiencies, or damage multipliers but no defining
* properties are added to the scope as implicit variables
*/
export default function computeImplicitVariable(node){
export default function computeImplicitVariable(computation, node){
const prop = {};

// Combine damage multipliers
Expand All @@ -20,6 +21,16 @@ import getAggregatorResult from './getAggregatorResult.js';
prop.vulnerability = node.data.vulnerability;
prop.vulnerabilities = node.data.vulnerabilities;
}
if (node.data.reduction){
prop.reduction = node.data.reduction;
prop.reductions = node.data.reductions;

prop.reductionAmount = 0;
prop.reductions.forEach(r => {
evaluateCalculation(r.reductionAmount, computation.scope);
prop.reductionAmount += r.reductionAmount.value;
});
}

const result = getAggregatorResult(node);
if (result !== undefined){
Expand Down
23 changes: 19 additions & 4 deletions app/imports/api/properties/DamageMultipliers.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import createPropertySchema from './subSchemas/createPropertySchema';
import SimpleSchema from 'simpl-schema';
import STORAGE_LIMITS from '/imports/constants/STORAGE_LIMITS.js';
import VARIABLE_NAME_REGEX from '/imports/constants/VARIABLE_NAME_REGEX.js';
Expand All @@ -6,7 +7,7 @@ import VARIABLE_NAME_REGEX from '/imports/constants/VARIABLE_NAME_REGEX.js';
* DamageMultipliers are multipliers that affect how much damage is taken from
* a given damage type
*/
let DamageMultiplierSchema = new SimpleSchema({
let DamageMultiplierSchema = createPropertySchema({
name: {
type: String,
optional: true,
Expand All @@ -27,7 +28,12 @@ let DamageMultiplierSchema = new SimpleSchema({
value: {
type: Number,
defaultValue: 0.5,
allowedValues: [0, 0.5, 2],
allowedValues: [0, 0.5, 2, -1],
},
// The amount to apply for flat reductions
reductionAmount: {
type: 'fieldToCompute',
optional: true
},
// Tags which bypass this multiplier (OR)
excludeTags: {
Expand All @@ -51,6 +57,15 @@ let DamageMultiplierSchema = new SimpleSchema({
},
});

const ComputedOnlyDamageMultiplierSchema = new SimpleSchema({});
const ComputedOnlyDamageMultiplierSchema = createPropertySchema({
reductionAmount: {
type: 'computedOnlyField',
optional: true,
},
});

const ComputedDamageMultiplierSchema = new SimpleSchema()
.extend(ComputedOnlyDamageMultiplierSchema)
.extend(DamageMultiplierSchema);

export { DamageMultiplierSchema, ComputedOnlyDamageMultiplierSchema };
export { DamageMultiplierSchema, ComputedDamageMultiplierSchema, ComputedOnlyDamageMultiplierSchema };
4 changes: 2 additions & 2 deletions app/imports/api/properties/computedPropertySchemasIndex.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { ComputedClassLevelSchema } from '/imports/api/properties/ClassLevels.js
import { ConstantSchema } from '/imports/api/properties/Constants.js';
import { ComputedContainerSchema } from '/imports/api/properties/Containers.js';
import { ComputedDamageSchema } from '/imports/api/properties/Damages.js';
import { DamageMultiplierSchema } from '/imports/api/properties/DamageMultipliers.js';
import { ComputedDamageMultiplierSchema } from '/imports/api/properties/DamageMultipliers.js';
import { ComputedEffectSchema } from '/imports/api/properties/Effects.js';
import { ComputedFeatureSchema } from '/imports/api/properties/Features.js';
import { ComputedFolderSchema } from '/imports/api/properties/Folders.js';
Expand Down Expand Up @@ -39,7 +39,7 @@ const propertySchemasIndex = {
classLevel: ComputedClassLevelSchema,
constant: ConstantSchema,
damage: ComputedDamageSchema,
damageMultiplier: DamageMultiplierSchema,
damageMultiplier: ComputedDamageMultiplierSchema,
effect: ComputedEffectSchema,
feature: ComputedFeatureSchema,
folder: ComputedFolderSchema,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,12 @@
<v-list-item-content>
<v-list-item-title>
{{ title(multiplier) }}
<span v-if="multiplier.value === -1 && multiplier.reductionAmount">
by {{ Math.abs(multiplier.reductionAmount.value) }}
</span>
</v-list-item-title>
<v-list-item-subtitle v-if="multiplier.name">
{{ multiplier.name }}
{{ multiplier.name }}
</v-list-item-subtitle>
<v-list-item-subtitle class="d-flex flex-wrap align-center">
<v-chip
Expand Down Expand Up @@ -88,6 +91,7 @@ export default {
case 0: return 'Immunity';
case 0.5: return 'Resistance';
case 2: return 'Vulnerability';
case -1: return (prop.reductionAmount?.value ?? 0) >= 0 ? 'Reduction' : 'Increase';
}
}
}
Expand Down
18 changes: 18 additions & 0 deletions app/imports/client/ui/properties/forms/DamageMultiplierForm.vue
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,31 @@
}, {
value: 0,
name: 'Immunity',
}, {
value: -1,
name: 'Reduction',
}]"
:error-messages="errors.value"
@change="change('value', ...arguments)"
/>
</v-col>
</v-row>
<v-row dense>
<v-expand-transition>
<v-col
v-if="model.value === -1"
cols="12"
>
<computed-field
label="Reduction Amount"
hint="The amount by which to reduce the incoming damage"
:model="model.reductionAmount"
:error-messages="errors.reductionAmount"
@change="({path, value, ack}) =>
$emit('change', {path: ['reductionAmount', ...path], value, ack})"
/>
</v-col>
</v-expand-transition>
<v-col cols="12">
<smart-combobox
label="Damage Types"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@
name="Value"
:value="operation"
/>
<property-field
v-if="model.value === -1 && model.reductionAmount"
name="Reduction amount"
:value="model.reductionAmount.value"
/>
<property-field
name="Damage types"
wrap
Expand Down Expand Up @@ -67,6 +72,7 @@ export default {
case 0: return 'Immunity';
case 0.5: return 'Resistance';
case 2: return 'Vulnerability';
case -1: return 'Reduction';
default: return '';
}
},
Expand Down