Added overflow stops to health bars
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
import { some, intersection, difference, remove, includes } from 'lodash';
|
import { some, intersection, difference, remove, includes } from 'lodash';
|
||||||
import applyProperty from '../applyProperty.js';
|
import applyProperty from '../applyProperty.js';
|
||||||
import {insertCreatureLog} from '/imports/api/creature/log/CreatureLogs.js';
|
import { insertCreatureLog } from '/imports/api/creature/log/CreatureLogs.js';
|
||||||
import resolve, { Context, toString } from '/imports/parser/resolve.js';
|
import resolve, { Context, toString } from '/imports/parser/resolve.js';
|
||||||
import logErrors from './shared/logErrors.js';
|
import logErrors from './shared/logErrors.js';
|
||||||
import applyEffectsToCalculationParseNode from '/imports/api/engine/actions/applyPropertyByType/shared/applyEffectsToCalculationParseNode.js';
|
import applyEffectsToCalculationParseNode from '/imports/api/engine/actions/applyPropertyByType/shared/applyEffectsToCalculationParseNode.js';
|
||||||
@@ -10,9 +10,9 @@ import {
|
|||||||
} from '/imports/api/engine/loadCreatures.js';
|
} from '/imports/api/engine/loadCreatures.js';
|
||||||
import { applyNodeTriggers } from '/imports/api/engine/actions/applyTriggers.js';
|
import { applyNodeTriggers } from '/imports/api/engine/actions/applyTriggers.js';
|
||||||
|
|
||||||
export default function applyDamage(node, actionContext){
|
export default function applyDamage(node, actionContext) {
|
||||||
applyNodeTriggers(node, 'before', actionContext);
|
applyNodeTriggers(node, 'before', actionContext);
|
||||||
const applyChildren = function(){
|
const applyChildren = function () {
|
||||||
applyNodeTriggers(node, 'after', actionContext);
|
applyNodeTriggers(node, 'after', actionContext);
|
||||||
node.children.forEach(child => applyProperty(child, actionContext));
|
node.children.forEach(child => applyProperty(child, actionContext));
|
||||||
};
|
};
|
||||||
@@ -28,10 +28,10 @@ export default function applyDamage(node, actionContext){
|
|||||||
// Determine if the hit is critical
|
// Determine if the hit is critical
|
||||||
let criticalHit = scope['$criticalHit']?.value &&
|
let criticalHit = scope['$criticalHit']?.value &&
|
||||||
prop.damageType !== 'healing' // Can't critically heal
|
prop.damageType !== 'healing' // Can't critically heal
|
||||||
;
|
;
|
||||||
// Double the damage rolls if the hit is critical
|
// Double the damage rolls if the hit is critical
|
||||||
let context = new Context({
|
let context = new Context({
|
||||||
options: {doubleRolls: criticalHit},
|
options: { doubleRolls: criticalHit },
|
||||||
});
|
});
|
||||||
|
|
||||||
// Gather all the lines we need to log into an array
|
// Gather all the lines we need to log into an array
|
||||||
@@ -40,8 +40,8 @@ export default function applyDamage(node, actionContext){
|
|||||||
|
|
||||||
// roll the dice only and store that string
|
// roll the dice only and store that string
|
||||||
applyEffectsToCalculationParseNode(prop.amount, actionContext.log);
|
applyEffectsToCalculationParseNode(prop.amount, actionContext.log);
|
||||||
const {result: rolled} = resolve('roll', prop.amount.parseNode, scope, context);
|
const { result: rolled } = resolve('roll', prop.amount.parseNode, scope, context);
|
||||||
if (rolled.parseType !== 'constant'){
|
if (rolled.parseType !== 'constant') {
|
||||||
logValue.push(toString(rolled));
|
logValue.push(toString(rolled));
|
||||||
}
|
}
|
||||||
logErrors(context.errors, actionContext);
|
logErrors(context.errors, actionContext);
|
||||||
@@ -50,13 +50,13 @@ export default function applyDamage(node, actionContext){
|
|||||||
context.errors = [];
|
context.errors = [];
|
||||||
|
|
||||||
// Resolve the roll to a final value
|
// Resolve the roll to a final value
|
||||||
const {result: reduced} = resolve('reduce', rolled, scope, context);
|
const { result: reduced } = resolve('reduce', rolled, scope, context);
|
||||||
logErrors(context.errors, actionContext);
|
logErrors(context.errors, actionContext);
|
||||||
|
|
||||||
// Store the result
|
// Store the result
|
||||||
if (reduced.parseType === 'constant'){
|
if (reduced.parseType === 'constant') {
|
||||||
prop.amount.value = reduced.value;
|
prop.amount.value = reduced.value;
|
||||||
} else if (reduced.parseType === 'error'){
|
} else if (reduced.parseType === 'error') {
|
||||||
prop.amount.value = null;
|
prop.amount.value = null;
|
||||||
} else {
|
} else {
|
||||||
prop.amount.value = toString(reduced);
|
prop.amount.value = toString(reduced);
|
||||||
@@ -64,7 +64,7 @@ export default function applyDamage(node, actionContext){
|
|||||||
let damage = +reduced.value;
|
let damage = +reduced.value;
|
||||||
|
|
||||||
// If we didn't end up with a constant of finite amount, give up
|
// If we didn't end up with a constant of finite amount, give up
|
||||||
if (reduced?.parseType !== 'constant' || !isFinite(reduced.value)){
|
if (reduced?.parseType !== 'constant' || !isFinite(reduced.value)) {
|
||||||
return applyChildren();
|
return applyChildren();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -83,7 +83,7 @@ export default function applyDamage(node, actionContext){
|
|||||||
// Memoise the damage suffix for the log
|
// Memoise the damage suffix for the log
|
||||||
let suffix = (criticalHit ? ' critical ' : ' ') +
|
let suffix = (criticalHit ? ' critical ' : ' ') +
|
||||||
prop.damageType +
|
prop.damageType +
|
||||||
(prop.damageType !== 'healing' ? ' damage ': '');
|
(prop.damageType !== 'healing' ? ' damage ' : '');
|
||||||
|
|
||||||
if (damageTargets && damageTargets.length) {
|
if (damageTargets && damageTargets.length) {
|
||||||
// Iterate through all the targets
|
// Iterate through all the targets
|
||||||
@@ -107,7 +107,7 @@ export default function applyDamage(node, actionContext){
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Log the damage done
|
// Log the damage done
|
||||||
if (target._id === actionContext.creature._id){
|
if (target._id === actionContext.creature._id) {
|
||||||
// Target is same as self, log damage as such
|
// Target is same as self, log damage as such
|
||||||
logValue.push(`**${damageDealt}** ${suffix} to self`);
|
logValue.push(`**${damageDealt}** ${suffix} to self`);
|
||||||
} else {
|
} else {
|
||||||
@@ -136,33 +136,33 @@ export default function applyDamage(node, actionContext){
|
|||||||
return applyChildren();
|
return applyChildren();
|
||||||
}
|
}
|
||||||
|
|
||||||
function applyDamageMultipliers({target, damage, damageProp, logValue}){
|
function applyDamageMultipliers({ target, damage, damageProp, logValue }) {
|
||||||
const damageType = damageProp?.damageType;
|
const damageType = damageProp?.damageType;
|
||||||
if (!damageType) return damage;
|
if (!damageType) return damage;
|
||||||
|
|
||||||
const multiplier = target?.variables?.[damageType];
|
const multiplier = target?.variables?.[damageType];
|
||||||
if (!multiplier) return damage;
|
if (!multiplier) return damage;
|
||||||
|
|
||||||
const damageTypeText = damageType == 'healing' ? 'healing': `${damageType} damage`;
|
const damageTypeText = damageType == 'healing' ? 'healing' : `${damageType} damage`;
|
||||||
|
|
||||||
if (
|
if (
|
||||||
multiplier.immunity &&
|
multiplier.immunity &&
|
||||||
some(multiplier.immunities, multiplierAppliesTo(damageProp, 'immunity'))
|
some(multiplier.immunities, multiplierAppliesTo(damageProp, 'immunity'))
|
||||||
){
|
) {
|
||||||
logValue.push(`Immune to ${damageTypeText}`);
|
logValue.push(`Immune to ${damageTypeText}`);
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
if (
|
if (
|
||||||
multiplier.resistance &&
|
multiplier.resistance &&
|
||||||
some(multiplier.resistances, multiplierAppliesTo(damageProp, 'resistance'))
|
some(multiplier.resistances, multiplierAppliesTo(damageProp, 'resistance'))
|
||||||
){
|
) {
|
||||||
logValue.push(`Resistant to ${damageTypeText}`);
|
logValue.push(`Resistant to ${damageTypeText}`);
|
||||||
damage = Math.floor(damage / 2);
|
damage = Math.floor(damage / 2);
|
||||||
}
|
}
|
||||||
if (
|
if (
|
||||||
multiplier.vulnerability &&
|
multiplier.vulnerability &&
|
||||||
some(multiplier.vulnerabilities, multiplierAppliesTo(damageProp, 'vulnerability'))
|
some(multiplier.vulnerabilities, multiplierAppliesTo(damageProp, 'vulnerability'))
|
||||||
){
|
) {
|
||||||
logValue.push(`Vulnerable to ${damageTypeText}`);
|
logValue.push(`Vulnerable to ${damageTypeText}`);
|
||||||
damage = Math.floor(damage * 2);
|
damage = Math.floor(damage * 2);
|
||||||
}
|
}
|
||||||
@@ -170,7 +170,7 @@ function applyDamageMultipliers({target, damage, damageProp, logValue}){
|
|||||||
return damage;
|
return damage;
|
||||||
}
|
}
|
||||||
|
|
||||||
function multiplierAppliesTo(damageProp, multiplierType){
|
function multiplierAppliesTo(damageProp, multiplierType) {
|
||||||
return multiplier => {
|
return multiplier => {
|
||||||
// Apply the default 'ignore x' tags
|
// Apply the default 'ignore x' tags
|
||||||
if (includes(damageProp.tags, `ignore ${multiplierType}`)) return false;
|
if (includes(damageProp.tags, `ignore ${multiplierType}`)) return false;
|
||||||
@@ -187,7 +187,7 @@ function multiplierAppliesTo(damageProp, multiplierType){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function dealDamage({target, damageType, amount, actionContext}){
|
function dealDamage({ target, damageType, amount, actionContext }) {
|
||||||
// Get all the health bars and do damage to them
|
// Get all the health bars and do damage to them
|
||||||
let healthBars = getPropertiesOfType(target._id, 'attribute');
|
let healthBars = getPropertiesOfType(target._id, 'attribute');
|
||||||
|
|
||||||
@@ -239,6 +239,14 @@ function dealDamage({target, damageType, amount, actionContext}){
|
|||||||
actionContext
|
actionContext
|
||||||
});
|
});
|
||||||
damageLeft -= damageAdded;
|
damageLeft -= damageAdded;
|
||||||
|
// Prevent overflow
|
||||||
|
if (
|
||||||
|
damageType === 'healing' ?
|
||||||
|
healthBar.healthBarNoHealingOverflow :
|
||||||
|
healthBar.healthBarNoDamageOverflow
|
||||||
|
) {
|
||||||
|
damageLeft = 0;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
return totalDamage;
|
return totalDamage;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -69,6 +69,16 @@ let AttributeSchema = createPropertySchema({
|
|||||||
type: Boolean,
|
type: Boolean,
|
||||||
optional: true,
|
optional: true,
|
||||||
},
|
},
|
||||||
|
// Control how the health bar handles overflow
|
||||||
|
healthBarNoDamageOverflow: {
|
||||||
|
type: Boolean,
|
||||||
|
optional: true,
|
||||||
|
},
|
||||||
|
healthBarNoHealingOverflow: {
|
||||||
|
type: Boolean,
|
||||||
|
optional: true,
|
||||||
|
},
|
||||||
|
// Control when the health bar takes damage or healing
|
||||||
healthBarDamageOrder: {
|
healthBarDamageOrder: {
|
||||||
type: SimpleSchema.Integer,
|
type: SimpleSchema.Integer,
|
||||||
optional: true,
|
optional: true,
|
||||||
|
|||||||
@@ -106,10 +106,17 @@
|
|||||||
/>
|
/>
|
||||||
<smart-switch
|
<smart-switch
|
||||||
label="Ignore damage"
|
label="Ignore damage"
|
||||||
|
class="mr-4"
|
||||||
:value="model.healthBarNoDamage"
|
:value="model.healthBarNoDamage"
|
||||||
:error-messages="errors.healthBarNoDamage"
|
:error-messages="errors.healthBarNoDamage"
|
||||||
@change="change('healthBarNoDamage', ...arguments)"
|
@change="change('healthBarNoDamage', ...arguments)"
|
||||||
/>
|
/>
|
||||||
|
<smart-switch
|
||||||
|
label="Prevent damage overflow"
|
||||||
|
:value="model.healthBarNoDamageOverflow"
|
||||||
|
:error-messages="errors.healthBarNoDamageOverflow"
|
||||||
|
@change="change('healthBarNoDamageOverflow', ...arguments)"
|
||||||
|
/>
|
||||||
</v-layout>
|
</v-layout>
|
||||||
<v-layout wrap>
|
<v-layout wrap>
|
||||||
<text-field
|
<text-field
|
||||||
@@ -125,14 +132,20 @@
|
|||||||
/>
|
/>
|
||||||
<smart-switch
|
<smart-switch
|
||||||
label="Ignore healing"
|
label="Ignore healing"
|
||||||
|
class="mr-4"
|
||||||
:value="model.healthBarNoHealing"
|
:value="model.healthBarNoHealing"
|
||||||
:error-messages="errors.healthBarNoHealing"
|
:error-messages="errors.healthBarNoHealing"
|
||||||
@change="change('healthBarNoHealing', ...arguments)"
|
@change="change('healthBarNoHealing', ...arguments)"
|
||||||
/>
|
/>
|
||||||
|
<smart-switch
|
||||||
|
label="Prevent healing overflow"
|
||||||
|
:value="model.healthBarNoHealingOverflow"
|
||||||
|
:error-messages="errors.healthBarNoHealingOverflow"
|
||||||
|
@change="change('healthBarNoHealingOverflow', ...arguments)"
|
||||||
|
/>
|
||||||
</v-layout>
|
</v-layout>
|
||||||
</form-section>
|
</form-section>
|
||||||
</v-expand-transition>
|
</v-expand-transition>
|
||||||
|
|
||||||
<form-section
|
<form-section
|
||||||
v-if="$slots.children"
|
v-if="$slots.children"
|
||||||
name="Children"
|
name="Children"
|
||||||
|
|||||||
Reference in New Issue
Block a user