//TODO add dexterity armor // jscs:disable maximumLineLength var stats = [ {stat: "strength", name: "Strength", group: "Ability Scores"}, {stat: "dexterity", name: "Dexterity", group: "Ability Scores"}, {stat: "constitution", name: "Constitution", group: "Ability Scores"}, {stat: "intelligence", name: "Intelligence", group: "Ability Scores"}, {stat: "wisdom", name: "Wisdom", group: "Ability Scores"}, {stat: "charisma", name: "Charisma", group: "Ability Scores"}, {name: "Strength Save", stat: "strengthSave", group: "Saving Throws"}, {name: "Dexterity Save", stat: "dexteritySave", group: "Saving Throws"}, {name: "Constitution Save", stat: "constitutionSave", group: "Saving Throws"}, {name: "Intelligence Save", stat: "intelligenceSave", group: "Saving Throws"}, {name: "Wisdom Save", stat: "wisdomSave", group: "Saving Throws"}, {name: "Charisma Save", stat: "charismaSave", group: "Saving Throws"}, {name: "Acrobatics", stat: "acrobatics", group: "Skills"}, {name: "Animal Handling", stat: "animalHandling", group: "Skills"}, {name: "Arcana", stat: "arcana", group: "Skills"}, {name: "Athletics", stat: "athletics", group: "Skills"}, {name: "Deception", stat: "deception", group: "Skills"}, {name: "History", stat: "history", group: "Skills"}, {name: "Insight", stat: "insight", group: "Skills"}, {name: "Intimidation", stat: "intimidation", group: "Skills"}, {name: "Investigation", stat: "investigation", group: "Skills"}, {name: "Medicine", stat: "medicine", group: "Skills"}, {name: "Nature", stat: "nature", group: "Skills"}, {name: "Perception", stat: "perception", group: "Skills"}, {name: "Performance", stat: "performance", group: "Skills"}, {name: "Persuasion", stat: "persuasion", group: "Skills"}, {name: "Religion", stat: "religion", group: "Skills"}, {name: "Sleight of Hand", stat: "sleightOfHand", group: "Skills"}, {name: "Stealth", stat: "stealth", group: "Skills"}, {name: "Survival", stat: "survival", group: "Skills"}, {name: "Initiative", stat: "initiative", group: "Skills"}, {stat: "hitPoints", name: "Hit Points", group: "Stats"}, {stat: "armor", name: "Armor", group: "Stats"}, {stat: "dexterityArmor", name: "Dexterity Armor Bonus", group: "Stats"}, {stat: "speed", name: "Speed", group: "Stats"}, {stat: "proficiencyBonus", name: "Proficiency Bonus", group: "Stats"}, {stat: "ki", name: "Ki Points", group: "Stats"}, {stat: "sorceryPoints", name: "Sorcery Points", group: "Stats"}, {stat: "rages", name: "Rages", group: "Stats"}, {stat: "rageDamage", name: "Rage Damage", group: "Stats"}, {stat: "expertiseDice", name: "Expertise Dice", group: "Stats"}, {stat: "superiorityDice", name: "Superiority Dice", group: "Stats"}, {stat: "carryMultiplier", name: "Carry Capacity Multiplier", group: "Stats"}, {stat: "level1SpellSlots", name: "level 1", group: "Spell Slots"}, {stat: "level2SpellSlots", name: "level 2", group: "Spell Slots"}, {stat: "level3SpellSlots", name: "level 3", group: "Spell Slots"}, {stat: "level4SpellSlots", name: "level 4", group: "Spell Slots"}, {stat: "level5SpellSlots", name: "level 5", group: "Spell Slots"}, {stat: "level6SpellSlots", name: "level 6", group: "Spell Slots"}, {stat: "level7SpellSlots", name: "level 7", group: "Spell Slots"}, {stat: "level8SpellSlots", name: "level 8", group: "Spell Slots"}, {stat: "level9SpellSlots", name: "level 9", group: "Spell Slots"}, {stat: "d6HitDice", name: "d6", group: "Hit Dice"}, {stat: "d8HitDice", name: "d8", group: "Hit Dice"}, {stat: "d10HitDice", name: "d10", group: "Hit Dice"}, {stat: "d12HitDice", name: "d12", group: "Hit Dice"}, {stat: "acidMultiplier", name: "Acid", group: "Weakness/Resistance"}, {stat: "bludgeoningMultiplier", name: "Bludgeoning", group: "Weakness/Resistance"}, {stat: "coldMultiplier", name: "Cold", group: "Weakness/Resistance"}, {stat: "fireMultiplier", name: "Fire", group: "Weakness/Resistance"}, {stat: "forceMultiplier", name: "Force", group: "Weakness/Resistance"}, {stat: "lightningMultiplier", name: "Lightning", group: "Weakness/Resistance"}, {stat: "necroticMultiplier", name: "Necrotic", group: "Weakness/Resistance"}, {stat: "piercingMultiplier", name: "Piercing", group: "Weakness/Resistance"}, {stat: "poisonMultiplier", name: "Poison", group: "Weakness/Resistance"}, {stat: "psychicMultiplier", name: "Psychic", group: "Weakness/Resistance"}, {stat: "radiantMultiplier", name: "Radiant", group: "Weakness/Resistance"}, {stat: "slashingMultiplier", name: "Slashing", group: "Weakness/Resistance"}, {stat: "thunderMultiplier", name: "Thunder", group: "Weakness/Resistance"}, ]; // jscs:enable maximumLineLength var statsDict = _.indexBy(stats, "stat"); var statGroups = _.groupBy(stats, "group"); var statGroupNames = _.keys(statGroups); var attributeOperations = [ {name: "Base Value", operation: "base"}, {name: "Add", operation: "add"}, {name: "Multiply", operation: "mul"}, {name: "Min", operation: "min"}, {name: "Max", operation: "max"}, ]; var skillOperations = [ {name: "Add", operation: "add"}, {name: "Multiply", operation: "mul"}, {name: "Min", operation: "min"}, {name: "Max", operation: "max"}, {name: "Advantage", operation: "advantage"}, {name: "Disadvantage", operation: "disadvantage"}, {name: "Passive Bonus", operation: "passiveAdd"}, {name: "Automatically Fail", operation: "fail"}, {name: "Conditional Benefit", operation: "conditional"}, ]; Template.effectEdit.onRendered(function(){ _.defer(() => { const statElement = this.find(".statMenu .iron-selected"); statElement && statElement.scrollIntoView(); const opElement = this.find(".operationMenu .iron-selected"); opElement && opElement.scrollIntoView(); }); }); Template.effectEdit.helpers({ effect: function(){ return Effects.findOne(this.id); }, statGroups: function(){ return statGroupNames; }, stats: function(){ var group = this; return statGroups[group]; }, operations: function(){ var stat = statsDict[this.stat]; var group = stat && stat.group; if (group === "Weakness/Resistance") return null; if (group === "Saving Throws" || group === "Skills"){ return skillOperations; } else { return attributeOperations; } }, showMultiplierOperations: function(){ var stat = statsDict[this.stat]; return stat && stat.group === "Weakness/Resistance" }, showEffectValueInput: function(){ var stat = statsDict[this.stat]; var group = stat && stat.group; if ( group === "Weakness/Resistance" ) return false; var op = this.operation; if ( !op || op === "advantage" || op === "disadvantage" || op === "fail" ) return false; return true; }, effectValue: function(){ return this.calculation || this.value; }, }); Template.effectEdit.events({ "click #deleteButton": function(event, instance){ Effects.softRemoveNode(instance.data.id); GlobalUI.deletedToast(instance.data.id, "Effects", "Effect"); popDialogStack(); }, "iron-select .statMenu": function(event){ var detail = event.originalEvent.detail; var statName = detail.item.getAttribute("name"); if (statName == this.stat) return; var setter = {stat: statName}; var group = Blaze.getData(detail.item).group; var effect = Effects.findOne(this._id); if (group === "Saving Throws" || group === "Skills"){ // Skills must have a valid skill operation if (!_.contains( _.map(skillOperations, ao => ao.operation), effect.operation )){ setter.operation = "add"; } } else if (group !== "Weakness/Resistance"){ // Attributes must have a valid attribute operation if (!_.contains( _.map(attributeOperations, ao => ao.operation), effect.operation )){ setter.operation = "base"; } } else { // Weakness/Resistance must have a mul operation and value if (effect.operation !== "mul"){ setter.operation = "mul"; } if (!_.contains([0, 0.5, 2], effect.value)){ setter.value = 0.5; } } Effects.update(this._id, {$set: setter}); }, "iron-select .operationMenu": function(event){ var detail = event.originalEvent.detail; var opName = detail.item.getAttribute("name"); if (opName == this.operation) return; Effects.update(this._id, {$set: {operation: opName}}); }, "iron-select .multiplierMenu": function(event){ var detail = event.originalEvent.detail; var value = +detail.item.getAttribute("name"); if (value == this.value) return; Effects.update(this._id, {$set: { value: value, calculation: "", operation: "mul", }}); }, "change .effectValueInput, input .effectValueInput": _.debounce(function(event){ var value = event.currentTarget.value; var numValue = value === "" ? NaN : +value; if (_.isFinite(numValue)){ if (this.value === numValue) return; Effects.update(this._id, { $set: {value: numValue}, $unset: {calculation: ""}, }); } else if (_.isString(value)){ if (this.calculation === value) return; Effects.update(this._id, { $set: {calculation: value}, $unset: {value: ""}, }, { removeEmptyStrings: false, trimStrings: false, }); } }, 400), });