Bug: Weapon damage calculations corrupting Attribute values As reported in this thread (and another one linked in that thread, and others that pop up from time to time), sometimes a character sheet will bug out and an Attribute will be massively boosted and can't be brought back down to earth. I think I've found the cause. When the Damage or Secondary Damage fields (and corresponding _itemmodifiers repeating field entries) contain an @{Attribute call}, and are not the last comma-separated entry in the _itemmodifiers field, they fall through the itemmod part of the update_attr sheetworker, have everything but integers stripped out and are applied as a bonus. For example, pasting these into the item mods field of a weapon in the inventory will not bug out an Attribute (replacing the entire field): Damage: 1d10 + @{dexterity_mod} or Secondary Damage: 2d4 + @{strength} But if you paste these in then tab out of the field, they should give a big old boost to the corresponding Attribute: Damage: 1d10 + @{dexterity_mod}, Secondary Damage: 1d8 or Secondary Damage: 2d4 + 5 + @{strength}, Damage: 3d4 The main offender is the update_attr function, line 766 in the 5e Legacy code. I'm assuming this function is still almost the same, as the functionality matches the Legacy version pretty closely. I'm not understanding why this bug only occurs if the Attribute call is not the last entry in _itemmodifiers , but the solution doesn't really rely on that. So this bit: var mods = v["repeating_inventory_" + currentID + "_itemmodifiers"].toLowerCase().split(","); _.each(mods, function(mod) { if(mod.indexOf(attr) > -1 && mod.indexOf("save") === -1) { if(mod.indexOf(":") > -1) { var new_base = !isNaN(parseInt(mod.replace(/[^0-9]/g, ""), 10)) ? parseInt(mod.replace(/[^0-9]/g, ""), 10) : false; item_base = new_base && new_base > item_base ? new_base : item_base; } else if(mod.indexOf("-") > -1) { var new_mod = !isNaN(parseInt(mod.replace(/[^0-9]/g, ""), 10)) ? parseInt(mod.replace(/[^0-9]/g, ""), 10) : false; item_bonus = new_mod ? item_bonus - new_mod : item_bonus; } else { var new_mod = !isNaN(parseInt(mod.replace(/[^0-9]/g, ""), 10)) ? parseInt(mod.replace(/[^0-9]/g, ""), 10) : false; item_bonus = new_mod ? item_bonus + new_mod : item_bonus; } }; }); I'm an absolute novice with JS, but since I've already looked at it, a couple of suggestions that might save time: Change the third line to a RegExp search, though this might not be necessary if the below 'if' structure is changed: const regex = new RegExp (`^\\s*${attr}`,'i'); // attribute name must be the first characters, excepting whitespace or const regex = new RegExp (`[^{]*${attr}`,'i'); // ignore attribute name if it is preceded by more than 0 braces { Still though, may as well stop the garbage falling in in the first place I guess. And change the 'if' statement... obviously the big problem is having everything that isn't a static bonus (a la Belt of Giant Strength) or a - malus fall through to the + bonus section... then strip out everything that isn't an integer, turning garbage into a massive Attribute bonus. I'd also rearrange it (though this bit is personal preference), as I think it's unintuitive to have the colon : (Belt of Giant Strength style) as the priority 'if'. I would expect "Strength: +4" to add 4 to Strength, rather than set Strength to a static 4 (if it is lower than 4). So I would shift the colon to the bottom, so it only kicks in in the absence of a '+' or a '-', then put a bin under it, but that might just be me! It seems people would be more likely to put "Strength: +4" in to give a 4 strength bonus, than they would be to put "Strength +28" in to indicate a minimum strength score of 28. Maybe also sneak an '=' in to the colon 'if', since Strength=28 might be a valid assumption to set an Attribute to 28??? Not sure about that one. So... if (mod.indexOf('+') > -1) { apply +bonus to attr } else if (mod.indexOf('-') > -1) { apply -malus to attr } else if (mod.indexOf(':') > -1 || mod.indexOf('=')) { set attr at 'X' if attr is less than 'X', Giant Strength style item} else { ignore.... surely people can get their syntax close enough that turning garbage into a legal modifier is not necessary } Maybe a regex match() with the \digits already (grouped up)? const regexBonus = new RegExp (`${attr}:?\\s*\\+\\s*(\\d*)`,'i'); if (mod.match(regexBonus)) {item_bonus = mod.match(regex)[1]} Well that was quite the rabbit hole.... I guess I should go and do my actual job now.