diff --git a/.gitignore b/.gitignore index 35cce91..890a065 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,7 @@ # IDE .idea/ -.vs/ \ No newline at end of file +.vs/ +node_modules/ +.eslintrc.js +package.json +package-lock.json \ No newline at end of file diff --git a/fonts/eb-garamond-v14-latin-ext_latin-700.woff b/fonts/eb-garamond-v14-latin-ext_latin-700.woff new file mode 100644 index 0000000..33be1e8 Binary files /dev/null and b/fonts/eb-garamond-v14-latin-ext_latin-700.woff differ diff --git a/fonts/eb-garamond-v14-latin-ext_latin-700.woff2 b/fonts/eb-garamond-v14-latin-ext_latin-700.woff2 new file mode 100644 index 0000000..683bf5f Binary files /dev/null and b/fonts/eb-garamond-v14-latin-ext_latin-700.woff2 differ diff --git a/fonts/eb-garamond-v14-latin-ext_latin-700italic.woff b/fonts/eb-garamond-v14-latin-ext_latin-700italic.woff new file mode 100644 index 0000000..541cb48 Binary files /dev/null and b/fonts/eb-garamond-v14-latin-ext_latin-700italic.woff differ diff --git a/fonts/eb-garamond-v14-latin-ext_latin-700italic.woff2 b/fonts/eb-garamond-v14-latin-ext_latin-700italic.woff2 new file mode 100644 index 0000000..7b8d7d3 Binary files /dev/null and b/fonts/eb-garamond-v14-latin-ext_latin-700italic.woff2 differ diff --git a/fonts/eb-garamond-v14-latin-ext_latin-italic.woff b/fonts/eb-garamond-v14-latin-ext_latin-italic.woff new file mode 100644 index 0000000..51fad60 Binary files /dev/null and b/fonts/eb-garamond-v14-latin-ext_latin-italic.woff differ diff --git a/fonts/eb-garamond-v14-latin-ext_latin-italic.woff2 b/fonts/eb-garamond-v14-latin-ext_latin-italic.woff2 new file mode 100644 index 0000000..1364780 Binary files /dev/null and b/fonts/eb-garamond-v14-latin-ext_latin-italic.woff2 differ diff --git a/fonts/eb-garamond-v14-latin-ext_latin-regular.woff b/fonts/eb-garamond-v14-latin-ext_latin-regular.woff new file mode 100644 index 0000000..c157ccd Binary files /dev/null and b/fonts/eb-garamond-v14-latin-ext_latin-regular.woff differ diff --git a/fonts/eb-garamond-v14-latin-ext_latin-regular.woff2 b/fonts/eb-garamond-v14-latin-ext_latin-regular.woff2 new file mode 100644 index 0000000..0bb7043 Binary files /dev/null and b/fonts/eb-garamond-v14-latin-ext_latin-regular.woff2 differ diff --git a/lang/en.json b/lang/en.json index 29057b3..39fce35 100644 --- a/lang/en.json +++ b/lang/en.json @@ -2,7 +2,13 @@ "dishonored.__comment": "The Dishonored System allows for dynamic location of variables. These are indicated via |#|.", - "dishonored.notifications.momentumTrackerPermissions": "The Momentum Tracker User Role does not have permissions to Modify Configuration Settings. Please change one of these in Permission Configuration or System Settings.", + "dishonored.notifications.momentum.trackerPermissions1": "The Momentum Tracker User Role does not have permissions to Modify Configuration Settings. Please either change ", + "dishonored.notifications.chaos.trackerPermissions1": "The Chaos Tracker User Role does not have permissions to Modify Configuration Settings. Please either change ", + "dishonored.notifications.trackerPermissions2": " so that User Role: ", + "dishonored.notifications.momentum.trackerPermissions3": " has permission to Modify Configuration Settings or, increase the User Role requirement for Momentum Tracker User Role in ", + "dishonored.notifications.chaos.trackerPermissions3": " has permission to Modify Configuration Settings or, increase the User Role requirement for Chaos Tracker User Role in ", + "dishonored.notifications.trackerPermissions4": ".", + "dishonored.notifications.trackerPermissionsClickHere": "To ignore this message until next update Click Here.", "dishonored.notifications.lackPermission": "You do not have permission to view this item!", "dishonored.notifications.tooManyBonecharms": "The current actor has 3 equipped bonecharms already! Doing Nothing.", "dishonored.notifications.armorAlreadyEquipped": "The current actor has an equipped armor already! Doing Nothing.", @@ -55,6 +61,12 @@ "dishonored.actor.item.adjectiveNew": "New", + "dishonored.actor.npc.types": "NPC Type", + "dishonored.actor.npc.incidental": "Incidental", + "dishonored.actor.npc.notable": "Notable", + "dishonored.actor.npc.minor": "Minor", + "dishonored.actor.npc.major": "Major", + "dishonored.actor.character.momentum": "Momentum Track", "dishonored.actor.character.experience": "Experience Track", "dishonored.actor.character.name": "Name", @@ -67,7 +79,7 @@ "dishonored.actor.character.outlook": "Outlook", "dishonored.actor.character.void": "Void Points Track", - "dishonored.actor.skisty.mod": "Modifier", + "dishonored.actor.skisty.mod": "Mod", "dishonored.actor.skisty.check": "Perform Check", "dishonored.actor.skill.title": "Skills", @@ -91,16 +103,13 @@ "dishonored.actor.genericitem.name": "Name", "dishonored.actor.genericitem.cost": "Value", - "dishonored.actor.contact.title": "Contacts", - "dishonored.actor.contact.relation": "Relation", - - "dishonored.actor.talent.title": "Talents", - "dishonored.actor.talent.type": "Type", - "dishonored.actor.focus.title": "Focuses", "dishonored.actor.focus.rating": "Rating", - "dishonored.actor.note.title": "Notes", + "dishonored.actor.abilities.mana": "Mana Points", + + "dishonored.actor.talent.title": "Talents", + "dishonored.actor.talent.type": "Type", "dishonored.actor.power.title": "Powers", "dishonored.actor.power.rune": "Rune", @@ -109,7 +118,8 @@ "dishonored.actor.belonging.title": "Belongings", "dishonored.actor.belonging.collectable.coin": "Coins", "dishonored.actor.belonging.collectable.rune": "Runes", - "dishonored.actor.belonging.weapon.title": "Weapons", + "dishonored.actor.belonging.collectable.bonecharm": "Bonecharms", + "dishonored.actor.belonging.weapon.title": "Weapon Name", "dishonored.actor.belonging.weapon.dmg": "Dmg", "dishonored.actor.belonging.weapon.damage": "Damage", "dishonored.actor.belonging.weapon.armorpierce": "Armor Piercing", @@ -125,14 +135,22 @@ "dishonored.actor.belonging.weapon.distant": "Distant", "dishonored.actor.belonging.weapon.rangednearby": "Ranged (Nearby)", "dishonored.actor.belonging.weapon.nearby": "Nearby", - "dishonored.actor.belonging.armor.title": "Armor", + "dishonored.actor.belonging.armor.title": "Armor Name", "dishonored.actor.belonging.armor.protect": "Protect", "dishonored.actor.belonging.armor.protection": "Protection", - "dishonored.actor.belonging.bonecharm.title": "Bonecharms", - "dishonored.actor.belonging.other.title": "Other Items", + "dishonored.actor.belonging.bonecharm.title": "Bonecharm Name", + "dishonored.actor.belonging.other.title": "Item Name", "dishonored.actor.belonging.other.qty": "Qty", "dishonored.actor.belonging.other.quantity": "Quantity", + "dishonored.actor.truth.title": "Truths", + "dishonored.actor.truth.content": "Content of Truth", + + "dishonored.actor.contact.title": "Contacts", + "dishonored.actor.contact.relation": "Relation", + + "dishonored.actor.note.title": "Notes", + "dishonored.contact.relation.great": "Great", "dishonored.contact.relation.fair": "Fair", @@ -141,6 +159,9 @@ "dishonored.contact.relation.dire": "Dire", + "dishonored.item.truth": "Truth", + + "dishonored.item.armor.helmet": "Is Helmet?", "dishonored.item.contact.send2actor": "Send to Actor", @@ -176,5 +197,5 @@ "dishonored.tracker.momentum": "Momentum", - "dishonored.__eof": "This is an end of file because I'm lazy and keep forgetting commas. This shouldn't be in the final commit (sorry if it is - see previous statement)." + "dishonored.__eof": "This is an end of file because I'm lazy and keep forgetting commas. This shouldn't be in the final commit (sorry if it is - see previous sentence)." } \ No newline at end of file diff --git a/lang/es.json b/lang/es.json index c0581f4..5f0dc6b 100644 --- a/lang/es.json +++ b/lang/es.json @@ -17,7 +17,7 @@ "dishonored.actor.character.archetype": "Arquetipo", "dishonored.actor.character.outlook": "Perspectiva", "dishonored.actor.character.void": "Puntos de Vacío", - "dishonored.actor.skisty.mod": "Modificador", + "dishonored.actor.skisty.mod": "Mod", "dishonored.actor.skisty.check": "Tirada de Acción", "dishonored.actor.skill.title": "Habilidades", "dishonored.actor.skill.name": "Habilidades", diff --git a/module/actors/actor.js b/module/actors/actor.js index f9c4f5e..e77d016 100644 --- a/module/actors/actor.js +++ b/module/actors/actor.js @@ -1,107 +1,90 @@ import { DishonoredRollDialog -} from '../apps/roll-dialog.js' +} from "../apps/roll-dialog.js"; import { DishonoredRoll -} from '../roll.js' +} from "../roll.js"; export class DishonoredActor extends Actor { - prepareData() { - this.data.img = '/systems/FVTT-Dishonored/icons/dishonoredlogo.webp'; - this.data.token.img = '/systems/FVTT-Dishonored/icons/dishonoredlogo.webp'; - this.data.token.bar1.attribute = "stress"; - if(this.data.type == "character") { - this.data.token.bar2.attribute = "void"; - this.data.token.actorLink = "true"; - this.data.token.brightSight = 30; - this.data.token.dimSight = 60; - this.data.token.displayBars = 50; - this.data.token.displayName = 50; - this.data.token.disposition = 1; - this.data.token.vision = true; - } - else { - this.data.token.displayBars = 40; - this.data.token.displayName = 40; - this.data.token.disposition = -1; - } - super.prepareData(); - // const actorData = this.data; - } + prepareData() { + if (this.data.img == "icons/svg/mystery-man.svg") this.data.img = "/systems/FVTT-Dishonored/icons/dishonoredlogo.webp"; + if (this.data.token.img == "icons/svg/mystery-man.svg") this.data.token.img = "/systems/FVTT-Dishonored/icons/dishonoredlogo.webp"; + return this.data; + } } export class DishonoredSharedActorFunctions { - // This function renders all the tracks. This will be used every time the character sheet is loaded. It is a vital element as such it runs before most other code! - dishonoredRenderTracks(html, stressTrackMax, voidPointsMax, expPointsMax, momentumMax) { - var i; - // Checks if details for the Stress Track was included, this should happen in all cases! - if (stressTrackMax) { - for (i = 0; i < stressTrackMax; i++) { - if (i + 1 <= html.find('#total-stress')[0].value) { - html.find('[id^="stress"]')[i].setAttribute("data-selected", "true"); - html.find('[id^="stress"]')[i].style.backgroundColor = "#191813"; - html.find('[id^="stress"]')[i].style.color = "#ffffff"; - } else { - html.find('[id^="stress"]')[i].removeAttribute("data-selected"); - html.find('[id^="stress"]')[i].style.backgroundColor = "rgb(255, 255, 255, 0.3)"; - html.find('[id^="stress"]')[i].style.color = ""; - } - } - } - // Checks if details for the Void Track was included, this should happen for all Characters! - if (voidPointsMax) { - for (i = 0; i < voidPointsMax; i++) { - if (i + 1 <= html.find('#total-void')[0].value) { - html.find('[id^="void"]')[i].setAttribute("data-selected", "true"); - html.find('[id^="void"]')[i].style.backgroundColor = "#191813"; - html.find('[id^="void"]')[i].style.color = "#ffffff"; - } else { - html.find('[id^="void"]')[i].removeAttribute("data-selected"); - html.find('[id^="void"]')[i].style.backgroundColor = "rgb(255, 255, 255, 0.3)"; - html.find('[id^="void"]')[i].style.color = ""; - } - } - } - // Checks if details for the Experience Track was included, this should happen for all Characters! - if (expPointsMax) { - for (i = 0; i < expPointsMax; i++) { - if (i + 1 <= html.find('#total-exp')[0].value) { - html.find('[id^="exp"]')[i].setAttribute("data-selected", "true"); - html.find('[id^="exp"]')[i].style.backgroundColor = "#191813"; - html.find('[id^="exp"]')[i].style.color = "#ffffff"; - } else { - html.find('[id^="exp"]')[i].removeAttribute("data-selected"); - html.find('[id^="exp"]')[i].style.backgroundColor = "rgb(255, 255, 255, 0.3)"; - html.find('[id^="exp"]')[i].style.color = ""; - } - } - } - // Checks if details for the Momentum Track was included, this should happen for all Characters! - if(momentumMax) { - for (i = 0; i < 6; i++) { - if (i + 1 <= html.find('#total-mom')[0].value) { - html.find('[id^="mom"]')[i].setAttribute("data-selected", "true"); - html.find('[id^="mom"]')[i].style.backgroundColor = "#191813"; - html.find('[id^="mom"]')[i].style.color = "#ffffff"; - } else { - html.find('[id^="mom"]')[i].removeAttribute("data-selected"); - html.find('[id^="mom"]')[i].style.backgroundColor = "rgb(255, 255, 255, 0.3)"; - html.find('[id^="mom"]')[i].style.color = ""; - } - } - } - } + // This function renders all the tracks. This will be used every time the character sheet is loaded. It is a vital element as such it runs before most other code! + dishonoredRenderTracks(html, stressTrackMax, voidPointsMax, expPointsMax, momentumMax) { + let i; + // Checks if details for the Stress Track was included, this should happen in all cases! + if (stressTrackMax) { + for (i = 0; i < stressTrackMax; i++) { + if (i + 1 <= html.find("#total-stress")[0].value) { + html.find("[id^=\"stress\"]")[i].setAttribute("data-selected", "true"); + html.find("[id^=\"stress\"]")[i].style.backgroundColor = "#191813"; + html.find("[id^=\"stress\"]")[i].style.color = "#ffffff"; + } else { + html.find("[id^=\"stress\"]")[i].removeAttribute("data-selected"); + html.find("[id^=\"stress\"]")[i].style.backgroundColor = "rgb(255, 255, 255, 0.3)"; + html.find("[id^=\"stress\"]")[i].style.color = ""; + } + } + } + // Checks if details for the Void Track was included, this should happen for all Characters! + if (voidPointsMax) { + for (i = 0; i < voidPointsMax; i++) { + if (i + 1 <= html.find("#total-void")[0].value) { + html.find("[id^=\"void\"]")[i].setAttribute("data-selected", "true"); + html.find("[id^=\"void\"]")[i].style.backgroundColor = "#191813"; + html.find("[id^=\"void\"]")[i].style.color = "#ffffff"; + } else { + html.find("[id^=\"void\"]")[i].removeAttribute("data-selected"); + html.find("[id^=\"void\"]")[i].style.backgroundColor = "rgb(255, 255, 255, 0.3)"; + html.find("[id^=\"void\"]")[i].style.color = ""; + } + } + } + // Checks if details for the Experience Track was included, this should happen for all Characters! + if (expPointsMax) { + for (i = 0; i < expPointsMax; i++) { + if (i + 1 <= html.find("#total-exp")[0].value) { + html.find("[id^=\"exp\"]")[i].setAttribute("data-selected", "true"); + html.find("[id^=\"exp\"]")[i].style.backgroundColor = "#191813"; + html.find("[id^=\"exp\"]")[i].style.color = "#ffffff"; + } else { + html.find("[id^=\"exp\"]")[i].removeAttribute("data-selected"); + html.find("[id^=\"exp\"]")[i].style.backgroundColor = "rgb(255, 255, 255, 0.8)"; + html.find("[id^=\"exp\"]")[i].style.color = ""; + } + } + } + // Checks if details for the Momentum Track was included, this should happen for all Characters! + if(momentumMax) { + for (i = 0; i < 6; i++) { + if (i + 1 <= html.find("#total-mom")[0].value) { + html.find("[id^=\"mom\"]")[i].setAttribute("data-selected", "true"); + html.find("[id^=\"mom\"]")[i].style.backgroundColor = "#191813"; + html.find("[id^=\"mom\"]")[i].style.color = "#ffffff"; + } else { + html.find("[id^=\"mom\"]")[i].removeAttribute("data-selected"); + html.find("[id^=\"mom\"]")[i].style.backgroundColor = "rgb(255, 255, 255, 0.3)"; + html.find("[id^=\"mom\"]")[i].style.color = ""; + } + } + } + } // This handles performing a skill test using the "Perform Check" button. async rollSkillTest(event, checkTarget, selectedSkill, selectedStyle, speaker) { - event.preventDefault(); - // This creates a dialog to gather details regarding the roll and waits for a response + event.preventDefault(); + // This creates a dialog to gather details regarding the roll and waits for a response let rolldialog = await DishonoredRollDialog.create(); if (rolldialog) { let dicePool = rolldialog.get("dicePoolSlider"); - let focusTarget = parseInt(rolldialog.get("dicePoolFocus")); - // Once the response has been collected it then sends it to be rolled. + let focusTarget = parseInt(rolldialog.get("dicePoolFocus")); + // Once the response has been collected it then sends it to be rolled. let dishonoredRoll = new DishonoredRoll(); dishonoredRoll.performSkillTest(dicePool, checkTarget, focusTarget, selectedSkill, selectedStyle, speaker); } @@ -110,34 +93,34 @@ export class DishonoredSharedActorFunctions { // This handles performing an "item" roll by clicking the item's image. async rollGenericItem(event, type, id, speaker) { event.preventDefault(); - var item = speaker.items.get(id); + let item = speaker.items.get(id); let dishonoredRoll = new DishonoredRoll(); // It will send it to a different method depending what item type was sent to it. switch(type) { - case "item": - dishonoredRoll.performItemRoll(item, speaker); - break; - case "focus": - dishonoredRoll.performFocusRoll(item, speaker); - break; - case "bonecharm": - dishonoredRoll.performBonecharmRoll(item, speaker); - break; - case "weapon": - dishonoredRoll.performWeaponRoll(item, speaker); - break; - case "armor": - dishonoredRoll.performArmorRoll(item, speaker); - break; - case "talent": - dishonoredRoll.performTalentRoll(item, speaker); - break; - case "contact": - dishonoredRoll.performContactRoll(item, speaker); - break; - case "power": - dishonoredRoll.performPowerRoll(item, speaker); - break; + case "item": + dishonoredRoll.performItemRoll(item, speaker); + break; + case "focus": + dishonoredRoll.performFocusRoll(item, speaker); + break; + case "bonecharm": + dishonoredRoll.performBonecharmRoll(item, speaker); + break; + case "weapon": + dishonoredRoll.performWeaponRoll(item, speaker); + break; + case "armor": + dishonoredRoll.performArmorRoll(item, speaker); + break; + case "talent": + dishonoredRoll.performTalentRoll(item, speaker); + break; + case "contact": + dishonoredRoll.performContactRoll(item, speaker); + break; + case "power": + dishonoredRoll.performPowerRoll(item, speaker); + break; } } } \ No newline at end of file diff --git a/module/actors/sheets/character-sheet.js b/module/actors/sheets/character-sheet.js index 16deb14..f743b5a 100644 --- a/module/actors/sheets/character-sheet.js +++ b/module/actors/sheets/character-sheet.js @@ -1,15 +1,20 @@ import { DishonoredSharedActorFunctions -} from '../actor.js' +} from "../actor.js"; export class DishonoredCharacterSheet extends ActorSheet { - /** @override */ - static get defaultOptions() { + static get defaultOptions () { return mergeObject(super.defaultOptions, { classes: ["dishonored", "sheet", "actor", "character"], width: 700, - height: 735, + height: 800, + tabs: [{ + navSelector: ".sheet-tabs", + contentSelector: ".sheet-body", + initial: "focuses" + }], + scrollY: [".focuses", ".abilities", ".belongings", ".biography", ".notes"], dragDrop: [{ dragSelector: ".item-list .item", dropSelector: null @@ -21,66 +26,70 @@ export class DishonoredCharacterSheet extends ActorSheet { // If the player is not a GM and has limited permissions - send them to the limited sheet, otherwise, continue as usual. /** @override */ - get template() { - if ( !game.user.isGM && this.actor.limited) return "systems/FVTT-Dishonored/templates/actors/limited-sheet.html"; - return `systems/FVTT-Dishonored/templates/actors/character-sheet.html`; - } + get template () { + let versionInfo; + if (game.world.data) versionInfo = game.world.data.coreVersion; + else game.world.coreVersion; + if (!game.user.isGM && this.actor.limited) return "systems/FVTT-Dishonored/templates/actors/limited-sheet.html"; + if (isNewerVersion(versionInfo,"0.8.-1")) return "systems/FVTT-Dishonored/templates/actors/character-sheet.html"; + else return "systems/FVTT-Dishonored/templates/actors/character-sheet-0.7.9.html"; + } /* -------------------------------------------- */ /** @override */ getData() { - const data = super.getData(); + const sheetData = this.object; //Ensure skill and style values don't weigh over the max of 8. - if (data.data.skills.fight.value > 8) data.data.skills.fight.value = 8; - if (data.data.skills.move.value > 8) data.data.skills.move.value = 8; - if (data.data.skills.study.value > 8) data.data.skills.study.value = 8; - if (data.data.skills.survive.value > 8) data.data.skills.survive.value = 8; - if (data.data.skills.talk.value > 8) data.data.skills.talk.value = 8; - if (data.data.skills.tinker.value > 8) data.data.skills.tinker.value = 8; - if (data.data.styles.boldly.value > 8) data.data.styles.boldly.value = 8; - if (data.data.styles.carefully.value > 8) data.data.styles.carefully.value = 8; - if (data.data.styles.cleverly.value > 8) data.data.styles.cleverly.value = 8; - if (data.data.styles.forcefully.value > 8) data.data.styles.forcefully.value = 8; - if (data.data.styles.quietly.value > 8) data.data.styles.quietly.value = 8; - if (data.data.styles.swiftly.value > 8) data.data.styles.swiftly.value = 8; + if (sheetData.data.data.skills.fight.value > 8) sheetData.data.data.skills.fight.value = 8; + if (sheetData.data.data.skills.move.value > 8) sheetData.data.data.skills.move.value = 8; + if (sheetData.data.data.skills.study.value > 8) sheetData.data.data.skills.study.value = 8; + if (sheetData.data.data.skills.survive.value > 8) sheetData.data.data.skills.survive.value = 8; + if (sheetData.data.data.skills.talk.value > 8) sheetData.data.data.skills.talk.value = 8; + if (sheetData.data.data.skills.tinker.value > 8) sheetData.data.data.skills.tinker.value = 8; + if (sheetData.data.data.styles.boldly.value > 8) sheetData.data.data.styles.boldly.value = 8; + if (sheetData.data.data.styles.carefully.value > 8) sheetData.data.data.styles.carefully.value = 8; + if (sheetData.data.data.styles.cleverly.value > 8) sheetData.data.data.styles.cleverly.value = 8; + if (sheetData.data.data.styles.forcefully.value > 8) sheetData.data.data.styles.forcefully.value = 8; + if (sheetData.data.data.styles.quietly.value > 8) sheetData.data.data.styles.quietly.value = 8; + if (sheetData.data.data.styles.swiftly.value > 8) sheetData.data.data.styles.swiftly.value = 8; // Checks if any values are larger than their relevant max, if so, set to max. - if (data.data.void.value > data.data.void.max) data.data.void.value = data.data.void.max; - if (data.data.stress.value > data.data.stress.max) data.data.stress.value = data.data.stress.max; + if (sheetData.data.data.void.value > sheetData.data.data.void.max) sheetData.data.data.void.value = sheetData.data.data.void.max; + if (sheetData.data.data.stress.value > sheetData.data.data.stress.max) sheetData.data.data.stress.value = sheetData.data.data.stress.max; // For some reason - this is treated as a string, so this enforce use of integers here. - if (parseInt(data.data.mana.value) > parseInt(data.data.mana.max)) data.data.mana.value = data.data.mana.max; + if (parseInt(sheetData.data.data.mana.value) > parseInt(sheetData.data.data.mana.max)) sheetData.data.data.mana.value = sheetData.data.data.mana.max; // Checks if mana max is not equal to double the void max, if it isn't, set it so. - if (data.data.mana.max != 2*data.data.void.max) data.data.mana.max = 2*data.data.void.max; + if (sheetData.data.data.mana.max != 2*sheetData.data.data.void.max) sheetData.data.data.mana.max = 2*sheetData.data.data.void.max; //Ensure skill and style values aren't lower than 4. - if (data.data.skills.fight.value < 4) data.data.skills.fight.value = 4; - if (data.data.skills.move.value < 4) data.data.skills.move.value = 4; - if (data.data.skills.study.value < 4) data.data.skills.study.value = 4; - if (data.data.skills.survive.value < 4) data.data.skills.survive.value = 4; - if (data.data.skills.talk.value < 4) data.data.skills.talk.value = 4; - if (data.data.skills.tinker.value < 4) data.data.skills.tinker.value = 4; - if (data.data.styles.boldly.value < 4) data.data.styles.boldly.value = 4; - if (data.data.styles.carefully.value < 4) data.data.styles.carefully.value = 4; - if (data.data.styles.cleverly.value < 4) data.data.styles.cleverly.value = 4; - if (data.data.styles.forcefully.value < 4) data.data.styles.forcefully.value = 4; - if (data.data.styles.quietly.value < 4) data.data.styles.quietly.value = 4; - if (data.data.styles.swiftly.value < 4) data.data.styles.swiftly.value = 4; - - // Checks if any values are below their theoretical minimum, if so - set it to the very minimum. - if (data.data.void.value < 0) data.data.void.value = 0; - if (data.data.void.max < 1) data.data.void.max = 1; - if (data.data.stress.value < 0) data.data.stress.value = 0; - if (data.data.experience < 0) data.data.experience = 0; - if (data.data.mana.value < 0) data.data.mana.value = 0; - if (data.data.mana.max < 2) data.data.mana.max = 2; + if (sheetData.data.data.skills.fight.value < 4) sheetData.data.data.skills.fight.value = 4; + if (sheetData.data.data.skills.move.value < 4) sheetData.data.data.skills.move.value = 4; + if (sheetData.data.data.skills.study.value < 4) sheetData.data.data.skills.study.value = 4; + if (sheetData.data.data.skills.survive.value < 4) sheetData.data.data.skills.survive.value = 4; + if (sheetData.data.data.skills.talk.value < 4) sheetData.data.data.skills.talk.value = 4; + if (sheetData.data.data.skills.tinker.value < 4) sheetData.data.data.skills.tinker.value = 4; + if (sheetData.data.data.styles.boldly.value < 4) sheetData.data.data.styles.boldly.value = 4; + if (sheetData.data.data.styles.carefully.value < 4) sheetData.data.data.styles.carefully.value = 4; + if (sheetData.data.data.styles.cleverly.value < 4) sheetData.data.data.styles.cleverly.value = 4; + if (sheetData.data.data.styles.forcefully.value < 4) sheetData.data.data.styles.forcefully.value = 4; + if (sheetData.data.data.styles.quietly.value < 4) sheetData.data.data.styles.quietly.value = 4; + if (sheetData.data.data.styles.swiftly.value < 4) sheetData.data.data.styles.swiftly.value = 4; + + // Checks if any values are below their theoretical minimum, if so set it to the very minimum. + if (sheetData.data.data.void.value < 0) sheetData.data.data.void.value = 0; + if (sheetData.data.data.void.max < 1) sheetData.data.data.void.max = 1; + if (sheetData.data.data.stress.value < 0) sheetData.data.data.stress.value = 0; + if (sheetData.data.data.experience < 0) sheetData.data.data.experience = 0; + if (sheetData.data.data.mana.value < 0) sheetData.data.data.mana.value = 0; + if (sheetData.data.data.mana.max < 2) sheetData.data.data.mana.max = 2; + $.each(sheetData.data.items, (key, item) => { + if (item.img == "icons/svg/item-bag.svg") item.img = "/systems/FVTT-Dishonored/icons/dishonoredlogo.webp"; + if (item.img == "icons/svg/mystery-man.svg") item.img = "/systems/FVTT-Dishonored/icons/dishonoredlogo.webp"; + }); + return sheetData.data; - $.each(data.items, (key, item) => { - if (!item.img) item.img = '/systems/FVTT-Dishonored/icons/dishonoredlogo.webp'; - }) - - return data; } /* -------------------------------------------- */ @@ -89,6 +98,11 @@ export class DishonoredCharacterSheet extends ActorSheet { activateListeners(html) { super.activateListeners(html); + // Sets up a declaration to be able to check the version easily. + let versionInfo; + if (game.world.data) versionInfo = game.world.data.coreVersion; + else game.world.coreVersion; + // Opens the class DishonoredSharedActorFunctions for access at various stages. let dishonoredActor = new DishonoredSharedActorFunctions(); @@ -96,206 +110,176 @@ export class DishonoredCharacterSheet extends ActorSheet { if ( !game.user.isGM && this.actor.limited) return; // We use i alot in for loops. Best to assign it now for use later in multiple places. - var i; + let i; + + // We use div alot to define text blocks. Define here. + let div; // Here we are checking how many bonecharms, helmets and armors are equipped. // The player can only have three bonecharms, and one of each armor type. As such, we will use this later. - var armorNumber = 0; - var bonecharmNumber = 0; - var helmetNumber = 0; - var stressTrackMax = 0; - function armorCount(currentActor) { - armorNumber = 0; - helmetNumber = 0; - currentActor.actor.items.forEach((values) => { - if (values.type == "armor") { - if (values.data.data.helmet == true && values.data.data.equipped == true) helmetNumber+= 1; - if (values.data.data.helmet == false && values.data.data.equipped == true) armorNumber+= 1; - } - }); - } - function bonecharmCount(currentActor) { - bonecharmNumber = 0; - currentActor.actor.items.forEach((values) => { - if (values.type == "bonecharm" && values.data.data.equipped == true) bonecharmNumber+= 1; - }); - html.find('[name ="data.bonecharmequipped"]')[0].value = bonecharmNumber; - } - armorCount(this); - bonecharmCount(this); + let armorNumber = 0; + let bonecharmNumber = 0; + let helmetNumber = 0; + let stressTrackMax = 0; + armorNumber = 0; + bonecharmNumber = 0; + helmetNumber = 0; + this.actor.items.forEach((values) => { + if (values.type == "armor") { + if (values.data.data.helmet == true && values.data.data.equipped == true) helmetNumber+= 1; + if (values.data.data.helmet == false && values.data.data.equipped == true) armorNumber+= 1; + } + else if (values.type == "bonecharm" && values.data.data.equipped == true) bonecharmNumber+= 1; + }); + html.find("[name =\"data.bonecharmequipped\"]")[0].value = bonecharmNumber; + // For ease of access we may as well turn the tooltip for bonecharm counts red. if(bonecharmNumber > 3) { - html.find('.bonecharmCount')[0].style.backgroundColor = "#fd0000"; - html.find('.bonecharmCount')[0].style.color = "#ffffff"; + html.find(".bonecharmCount")[0].style.backgroundColor = "#fd0000"; + html.find(".bonecharmCount")[0].style.color = "#ffffff"; } // This creates a dynamic Void Point tracker. It polls for the hidden control "max-void" and for the value, // creates a new div for each and places it under a child called "bar-void-renderer" - var voidPointsMax = html.find('#max-void')[0].value; + let voidPointsMax = html.find("#max-void")[0].value; for (i = 1; i <= voidPointsMax; i++) { - var div = document.createElement("DIV"); + div = document.createElement("DIV"); div.className = "box"; div.id = "void-" + i; div.innerHTML = i; - div.style = "width: calc(100% / " + html.find('#max-void')[0].value + ");" - html.find('#bar-void-renderer')[0].appendChild(div); + div.style = "width: calc(100% / " + html.find("#max-void")[0].value + ");"; + html.find("#bar-void-renderer")[0].appendChild(div); } // This creates a dynamic Stress tracker. It polls for the value of the survive skill, adds any protection from armor. // With the total value, creates a new div for each and places it under a child called "bar-stress-renderer". function stressTrackUpdate() { - stressTrackMax = parseInt(html.find('#survive')[0].value); - var armor = html.find('[data-item-type="armor"]'); + stressTrackMax = parseInt(html.find("#survive")[0].value); + let armor = html.find("[data-item-type=\"armor\"]"); for (i = 0; i < armor.length; i++) { - if (armor[i].getAttribute("data-item-equipped") == 'true') { + if (armor[i].getAttribute("data-item-equipped") == "true") { stressTrackMax += parseInt($(armor[i]).children()[2].innerHTML); } } // This checks that the max-stress hidden field is equal to the calculated Max Stress value, if not it makes it so. - if (html.find('#max-stress')[0].value != stressTrackMax) + if (html.find("#max-stress")[0].value != stressTrackMax) { - html.find('#max-stress')[0].value = stressTrackMax; + html.find("#max-stress")[0].value = stressTrackMax; } - html.find('#bar-stress-renderer').empty(); + html.find("#bar-stress-renderer").empty(); for (i = 1; i <= stressTrackMax; i++) { - var div = document.createElement("DIV"); + div = document.createElement("DIV"); div.className = "box"; div.id = "stress-" + i; div.innerHTML = i; - div.style = "width: calc(100% / " + html.find('#max-stress')[0].value + ");" - html.find('#bar-stress-renderer')[0].appendChild(div); + div.style = "width: calc(100% / " + html.find("#max-stress")[0].value + ");"; + html.find("#bar-stress-renderer")[0].appendChild(div); } } stressTrackUpdate(); // This creates a dynamic Experience tracker. For this it uses a max value of 30. This can be configured here. // It creates a new div for each and places it under a child called "bar-void-renderer" - var expPointsMax = game.settings.get("FVTT-Dishonored", "maxNumberOfExperience"); - var i; + let expPointsMax = game.settings.get("FVTT-Dishonored", "maxNumberOfExperience"); for (i = 1; i <= expPointsMax; i++) { - var div = document.createElement("DIV"); + div = document.createElement("DIV"); div.className = "box"; div.id = "exp-" + i; div.innerHTML = i; - div.style = "width: calc(100% / " + expPointsMax + ");" - html.find('#bar-exp-renderer')[0].appendChild(div); + div.style = "width: calc(100% / " + expPointsMax + ");"; + html.find("#bar-exp-renderer")[0].appendChild(div); } - // This creates a dynamic Momentum tracker. Dishonored only has 6 momentum, so this should never be changed. But this can be configured here. - // It creates a new div for each and places it under a child called "bar-mom-renderer" - // var momPointsMax = 6; - // var i; - // for (i = 1; i <= momPointsMax; i++) { - // var div = document.createElement("DIV"); - // div.className = "box"; - // div.id = "mom-" + i; - // div.innerHTML = i; - // div.style = "width: calc(100% / " + momPointsMax + ");" - // html.find('#bar-mom-renderer')[0].appendChild(div); - // } - // Fires the function dishonoredRenderTracks as soon as the parameters exist to do so. - // dishonoredActor.dishonoredRenderTracks(html, stressTrackMax, voidPointsMax, expPointsMax, momPointsMax); dishonoredActor.dishonoredRenderTracks(html, stressTrackMax, voidPointsMax, expPointsMax); // This allows for each item-edit image to link open an item sheet. This uses Simple Worldbuilding System Code. - html.find('.control.edit').click(ev => { + html.find(".control.edit").click(ev => { const li = $(ev.currentTarget).parents(".entry"); - const item = this.actor.getOwnedItem(li.data("itemId")); + const item = this.actor.items.get(li.data("itemId")); item.sheet.render(true); }); // This if statement checks if the form is editable, if not it hides control used by the owner, then aborts any more of the script. if (!this.options.editable) { // This hides the ability to Perform a Skill Test for the character. - for (i = 0; i < html.find('.check-button').length; i++) { - html.find('.check-button')[i].style.display = 'none'; + for (i = 0; i < html.find(".check-button").length; i++) { + html.find(".check-button")[i].style.display = "none"; } // This hides the ability to change the amount of Void Points the character has. - for (i = 0; i < html.find('.voidchange').length; i++) { - html.find('.voidchange')[i].style.display = 'none'; + for (i = 0; i < html.find(".voidchange").length; i++) { + html.find(".voidchange")[i].style.display = "none"; } // This hides all toggle, add and delete item images. - for (i = 0; i < html.find('.control.create').length; i++) { - html.find('.control.create')[i].style.display = 'none'; + for (i = 0; i < html.find(".control.create").length; i++) { + html.find(".control.create")[i].style.display = "none"; } - for (i = 0; i < html.find('.control.delete').length; i++) { - html.find('.control.delete')[i].style.display = 'none'; + for (i = 0; i < html.find(".control.delete").length; i++) { + html.find(".control.delete")[i].style.display = "none"; } - for (i = 0; i < html.find('.control.toggle').length; i++) { - html.find('.control.delete')[i].style.display = 'none'; + for (i = 0; i < html.find(".control.toggle").length; i++) { + html.find(".control.delete")[i].style.display = "none"; } // This hides all skill and style check boxes (and titles) - for (i = 0; i < html.find('.selector').length; i++) { - html.find('.selector')[i].style.display = 'none'; + for (i = 0; i < html.find(".selector").length; i++) { + html.find(".selector")[i].style.display = "none"; } - for (i = 0; i < html.find('.selector').length; i++) { - html.find('.selector')[i].style.display = 'none'; + for (i = 0; i < html.find(".selector").length; i++) { + html.find(".selector")[i].style.display = "none"; } // Remove hover CSS from clickables that are no longer clickable. - for (i = 0; i < html.find('.box').length; i++) { - html.find('.box')[i].classList.add("unset-clickables"); + for (i = 0; i < html.find(".box").length; i++) { + html.find(".box")[i].classList.add("unset-clickables"); } - for (i = 0; i < html.find('.rollable').length; i++) { - html.find('.rollable')[i].classList.add("unset-clickables"); + for (i = 0; i < html.find(".rollable").length; i++) { + html.find(".rollable")[i].classList.add("unset-clickables"); } return; - }; + } // This toggles whether the item is equipped or not. Equipped items count towards item caps. - html.find('.control.toggle').click(ev => { - var itemType = $(ev.currentTarget).parents(".entry")[0].getAttribute("data-item-type"); - var itemId = $(ev.currentTarget).parents(".entry")[0].getAttribute("data-item-id"); - var item = this.actor.getOwnedItem(itemId); - var itemData = item.data; + html.find(".control.toggle").click(ev => { + let itemId = ev.currentTarget.closest(".entry").dataset.itemId; + let item = this.actor.items.get(itemId); + let itemType = ev.currentTarget.closest(".entry").dataset.itemType; if (itemType == "armor") var isHelmet = $(ev.currentTarget).parents(".entry")[0].getAttribute("data-item-helmet"); - if (this.actor.items.get(itemId).data.data.equipped == true) { - itemData.data.equipped = false; - $(ev.currentTarget).children()[0].classList.remove("fa-toggle-on"); - $(ev.currentTarget).children()[0].classList.add("fa-toggle-off"); - $(ev.currentTarget).parents(".entry")[0].setAttribute("data-item-equipped", "false") - } - else if (itemType == "bonecharm" && bonecharmNumber >= 3) { - ui.notifications.error(game.i18n.localize('dishonored.notifications.tooManyBonecharms')); - } - else if (itemType == "armor" && isHelmet == 'false' && armorNumber >= 1) { - ui.notifications.error(game.i18n.localize('dishonored.notifications.armorAlreadyEquipped')); - } - else if (itemType == "armor" && isHelmet == 'true' && helmetNumber >= 1) { - ui.notifications.error(game.i18n.localize('dishonored.notifications.helmentAlreadyEquipped')); - } - else { - itemData.data.equipped = true; - $(ev.currentTarget).children()[0].classList.remove("fa-toggle-off"); - $(ev.currentTarget).children()[0].classList.add("fa-toggle-on"); - $(ev.currentTarget).parents(".entry")[0].setAttribute("data-item-equipped", "true") + if (item.data.data.equipped === false) { + if (itemType == "bonecharm" && bonecharmNumber >= 3) { + ui.notifications.error(game.i18n.localize("dishonored.notifications.tooManyBonecharms")); + return false; + } + else if (itemType == "armor" && isHelmet == "false" && armorNumber >= 1) { + ui.notifications.error(game.i18n.localize("dishonored.notifications.armorAlreadyEquipped")); + return false; + } + else if (itemType == "armor" && isHelmet == "true" && helmetNumber >= 1) { + ui.notifications.error(game.i18n.localize("dishonored.notifications.helmetAlreadyEquipped")); + return false; + } } - item.update(itemData); - stressTrackUpdate(); - dishonoredActor.dishonoredRenderTracks(html, stressTrackMax); - this.submit(); + return this.actor.items.get(itemId).update({["data.equipped"]: !getProperty(item.data, "data.equipped")}); }); // This allows for all items to be rolled, it gets the current targets type and id and sends it to the rollGenericItem function. - html.find('.rollable').click(ev =>{ - var itemType = $(ev.currentTarget).parents(".entry")[0].getAttribute("data-item-type"); - var itemId = $(ev.currentTarget).parents(".entry")[0].getAttribute("data-item-id"); + html.find(".rollable").click(ev =>{ + let itemType = $(ev.currentTarget).parents(".entry")[0].getAttribute("data-item-type"); + let itemId = $(ev.currentTarget).parents(".entry")[0].getAttribute("data-item-id"); dishonoredActor.rollGenericItem(ev, itemType, itemId, this.actor); - }) + }); // Allows item-create images to create an item of a type defined individually by each button. This uses code found via the Foundry VTT System Tutorial. - html.find('.control.create').click(ev => { + html.find(".control.create").click(ev => { ev.preventDefault(); const header = ev.currentTarget; const type = header.dataset.type; const data = duplicate(header.dataset); - const name = game.i18n.format("dishonored.actor.item.adjectiveNew") + ' ' + type.charAt(0).toUpperCase() + type.slice(1); + const name = game.i18n.format("dishonored.actor.item.adjectiveNew") + " " + type.charAt(0).toUpperCase() + type.slice(1); if (type == "bonecharm" && bonecharmNumber >= 3) { - ui.notifications.info(game.i18n.localize('dishonored.notifications.tooManyBonecharmsNew')); + ui.notifications.info(game.i18n.localize("dishonored.notifications.tooManyBonecharmsNew")); data.equipped = false; } if (type == "armor" && armorNumber >= 1) { - ui.notifications.info(game.i18n.localize('dishonored.notifications.armorAlreadyEquippedNew')); + ui.notifications.info(game.i18n.localize("dishonored.notifications.armorAlreadyEquippedNew")); data.equipped = false; } const itemData = { @@ -305,70 +289,49 @@ export class DishonoredCharacterSheet extends ActorSheet { }; delete itemData.data["type"]; stressTrackUpdate(); - return this.actor.createOwnedItem(itemData); + // Check if we are using a Foundry version above 0.8.0, use new code. + if (isNewerVersion(versionInfo,"0.8.-1")) return this.actor.createEmbeddedDocuments("Item",[(itemData)]); + else return this.actor.createOwnedItem(itemData); }); // Allows item-delete images to allow deletion of the selected item. This uses Simple Worldbuilding System Code. - html.find('.control.delete').click(ev => { + html.find(".control.delete").click(ev => { const li = $(ev.currentTarget).parents(".entry"); - this.actor.deleteOwnedItem(li.data("itemId")); - li.slideUp(200, () => this.render(false)); + // Check if we are using a Foundry version above 0.8.0, use new code. + if (isNewerVersion(versionInfo,"0.8.-1")) this.actor.deleteEmbeddedDocuments("Item",[li.data("itemId")]); + else this.actor.deleteOwnedItem(li.data("itemId")); + return li.slideUp(200, () => this.render(false)); }); // Reads if a experience track box has been clicked, and if it has will either: set the value to the clicked box, or reduce the value by one. // This check is dependent on various requirements, see comments in code. - html.find('[id^="exp"]').click(ev => { - var newTotalObject = $(ev.currentTarget)[0]; - var newTotal = newTotalObject.id.replace(/\D/g, ''); + html.find("[id^=\"exp\"]").click(ev => { + let newTotalObject = $(ev.currentTarget)[0]; + let newTotal = newTotalObject.id.replace(/\D/g, ""); + let total; // data-selected stores whether the track box is currently activated or not. This checks that the box is activated if (newTotalObject.getAttribute("data-selected") === "true") { // Now we check that the "next" track box is not activated. // If there isn't one, or it isn't activated, we only want to decrease the value by 1 rather than setting the value. - var nextCheck = 'exp-' + (parseInt(newTotal) + 1); - if (!html.find('#'+nextCheck)[0] || html.find('#'+nextCheck)[0].getAttribute("data-selected") != "true") { - html.find('#total-exp')[0].value = html.find('#total-exp')[0].value - 1; + let nextCheck = "exp-" + (parseInt(newTotal) + 1); + if (!html.find("#"+nextCheck)[0] || html.find("#"+nextCheck)[0].getAttribute("data-selected") != "true") { + html.find("#total-exp")[0].value = html.find("#total-exp")[0].value - 1; this.submit(); } // If it isn't caught by the if, the next box is likely activated. If something happened, its safer to set the value anyway. else { - var total = html.find('#total-exp')[0].value; + total = html.find("#total-exp")[0].value; if (total != newTotal) { - html.find('#total-exp')[0].value = newTotal; + html.find("#total-exp")[0].value = newTotal; this.submit(); } } } // If the clicked box wasn't activated, we need to activate it now. else { - var total = html.find('#total-exp')[0].value; - if (total != newTotal) { - html.find('#total-exp')[0].value = newTotal; - this.submit(); - } - } - }); - - // Reads if a momentum track box has been clicked, and if it has will either: set the value to the clicked box, or reduce the value by one. - // See line 186-220 for a more detailed break down on the context of each scenario. Momentum uses the same logic. - html.find('[id^="mom"]').click(ev => { - var newTotalObject = $(ev.currentTarget)[0]; - var newTotal = newTotalObject.id.substring(4); - if (newTotalObject.getAttribute("data-selected") === "true") { - var nextCheck = 'mom-' + (parseInt(newTotal) + 1); - if (!html.find('#'+nextCheck)[0] || html.find('#'+nextCheck)[0].getAttribute("data-selected") != "true") { - html.find('#total-mom')[0].value = html.find('#total-mom')[0].value - 1; - this.submit(); - } else { - var total = html.find('#total-mom')[0].value; - if (total != newTotal) { - html.find('#total-mom')[0].value = newTotal; - this.submit(); - } - } - } else { - var total = html.find('#total-mom')[0].value; + total = html.find("#total-exp")[0].value; if (total != newTotal) { - html.find('#total-mom')[0].value = newTotal; + html.find("#total-exp")[0].value = newTotal; this.submit(); } } @@ -376,25 +339,26 @@ export class DishonoredCharacterSheet extends ActorSheet { // Reads if a stress track box has been clicked, and if it has will either: set the value to the clicked box, or reduce the value by one. // See line 186-220 for a more detailed break down on the context of each scenario. Stress uses the same logic. - html.find('[id^="stress"]').click(ev => { - var newTotalObject = $(ev.currentTarget)[0]; - var newTotal = newTotalObject.id.substring(7); + html.find("[id^=\"stress\"]").click(ev => { + let newTotalObject = $(ev.currentTarget)[0]; + let newTotal = newTotalObject.id.substring(7); + let total; if (newTotalObject.getAttribute("data-selected") === "true") { - var nextCheck = 'stress-' + (parseInt(newTotal) + 1); - if (!html.find('#'+nextCheck)[0] || html.find('#'+nextCheck)[0].getAttribute("data-selected") != "true") { - html.find('#total-stress')[0].value = html.find('#total-stress')[0].value - 1; + let nextCheck = "stress-" + (parseInt(newTotal) + 1); + if (!html.find("#"+nextCheck)[0] || html.find("#"+nextCheck)[0].getAttribute("data-selected") != "true") { + html.find("#total-stress")[0].value = html.find("#total-stress")[0].value - 1; this.submit(); } else { - var total = html.find('#total-stress')[0].value; + total = html.find("#total-stress")[0].value; if (total != newTotal) { - html.find('#total-stress')[0].value = newTotal; + html.find("#total-stress")[0].value = newTotal; this.submit(); } } } else { - var total = html.find('#total-stress')[0].value; + total = html.find("#total-stress")[0].value; if (total != newTotal) { - html.find('#total-stress')[0].value = newTotal; + html.find("#total-stress")[0].value = newTotal; this.submit(); } } @@ -402,51 +366,52 @@ export class DishonoredCharacterSheet extends ActorSheet { // Reads if a void track box has been clicked, and if it has will either: set the value to the clicked box, or reduce the value by one. // See line 186-220 for a more detailed break down on the context of each scenario. Void uses the same logic. - html.find('[id^="void"]').click(ev => { - var newTotalObject = $(ev.currentTarget)[0]; - var newTotal = newTotalObject.id.replace(/\D/g, ''); + html.find("[id^=\"void\"]").click(ev => { + let newTotalObject = $(ev.currentTarget)[0]; + let newTotal = newTotalObject.id.replace(/\D/g, ""); + let total; if (newTotalObject.getAttribute("data-selected") === "true") { - var nextCheck = 'void-' + (parseInt(newTotal) + 1); - if (!html.find('#'+nextCheck)[0] || html.find('#'+nextCheck)[0].getAttribute("data-selected") != "true") { - html.find('#total-void')[0].value = html.find('#total-void')[0].value - 1; + let nextCheck = "void-" + (parseInt(newTotal) + 1); + if (!html.find("#"+nextCheck)[0] || html.find("#"+nextCheck)[0].getAttribute("data-selected") != "true") { + html.find("#total-void")[0].value = html.find("#total-void")[0].value - 1; this.submit(); } else { - var total = html.find('#total-void')[0].value; + total = html.find("#total-void")[0].value; if (total != newTotal) { - html.find('#total-void')[0].value = newTotal; + html.find("#total-void")[0].value = newTotal; this.submit(); } } } else { - var total = html.find('#total-void')[0].value; + total = html.find("#total-void")[0].value; if (total != newTotal) { - html.find('#total-void')[0].value = newTotal; + html.find("#total-void")[0].value = newTotal; this.submit(); } } }); // If the decrease-void-max button is clicked it removes a point off the max-void and two points from max-mana. - html.find('[id="decrease-void-max"]').click(ev => { - html.find('#max-void')[0].value--; - html.find('#max-mana')[0].value--; - html.find('#max-mana')[0].value--; + html.find("[id=\"decrease-void-max\"]").click(ev => { + html.find("#max-void")[0].value--; + html.find("#max-mana")[0].value--; + html.find("#max-mana")[0].value--; this.submit(); }); // If the increase-void-max button is clicked it adds a point to the max-void and two points to max-mana. - html.find('[id="increase-void-max"]').click(ev => { - html.find('#max-void')[0].value++; - html.find('#max-mana')[0].value++; - html.find('#max-mana')[0].value++; + html.find("[id=\"increase-void-max\"]").click(ev => { + html.find("#max-void")[0].value++; + html.find("#max-mana")[0].value++; + html.find("#max-mana")[0].value++; this.submit(); }); // Turns the Skill checkboxes into essentially a radio button. It removes any other ticks, and then checks the new skill. // Finally a submit is required as data has changed. - html.find('.selector.skill').click(ev => { + html.find(".selector.skill").click(ev => { for (i = 0; i <= 5; i++) { - html.find('.selector.skill')[i].checked = false; + html.find(".selector.skill")[i].checked = false; } $(ev.currentTarget)[0].checked = true; this.submit(); @@ -454,31 +419,35 @@ export class DishonoredCharacterSheet extends ActorSheet { // Turns the Style checkboxes into essentially a radio button. It removes any other ticks, and then checks the new style. // Finally a submit is required as data has changed. - html.find('.selector.style').click(ev => { + html.find(".selector.style").click(ev => { for (i = 0; i <= 5; i++) { - html.find('.selector.style')[i].checked = false; + html.find(".selector.style")[i].checked = false; } $(ev.currentTarget)[0].checked = true; this.submit(); }); // If the check-button is clicked it grabs the selected skill and the selected style and fires the method rollSkillTest. See actor.js for further info. - html.find('.check-button').click(ev => { + html.find(".check-button").click(ev => { + let selectedSkill; + let selectedSkillValue; + let selectedStyle; + let selectedStyleValue; for (i = 0; i <= 5; i++) { - if (html.find('.selector.skill')[i].checked === true) { - var selectedSkill = html.find('.selector.skill')[i].id; - var selectedSkill = selectedSkill.slice(0, -9) - var selectedSkillValue = html.find('#'+selectedSkill)[0].value; + if (html.find(".selector.skill")[i].checked === true) { + let selectedSkillHTML = html.find(".selector.skill")[i].id; + selectedSkill = selectedSkillHTML.slice(0, -9); + selectedSkillValue = html.find("#"+selectedSkill)[0].value; } } for (i = 0; i <= 5; i++) { - if (html.find('.selector.style')[i].checked === true) { - var selectedStyle = html.find('.selector.style')[i].id; - var selectedStyle = selectedStyle.slice(0, -9) - var selectedStyleValue = html.find('#'+selectedStyle)[0].value; + if (html.find(".selector.style")[i].checked === true) { + let selectedStyleHTML = html.find(".selector.style")[i].id; + selectedStyle = selectedStyleHTML.slice(0, -9); + selectedStyleValue = html.find("#"+selectedStyle)[0].value; } } - var checkTarget = parseInt(selectedSkillValue) + parseInt(selectedStyleValue); + let checkTarget = parseInt(selectedSkillValue) + parseInt(selectedStyleValue); dishonoredActor.rollSkillTest(ev, checkTarget, selectedSkill, selectedStyle, this.actor); }); diff --git a/module/actors/sheets/npc-sheet.js b/module/actors/sheets/npc-sheet.js index 4fd94fb..67393d4 100644 --- a/module/actors/sheets/npc-sheet.js +++ b/module/actors/sheets/npc-sheet.js @@ -1,15 +1,20 @@ import { DishonoredSharedActorFunctions -} from '../actor.js' +} from "../actor.js"; export class DishonoredNPCSheet extends ActorSheet { - /** @override */ - static get defaultOptions() { + static get defaultOptions () { return mergeObject(super.defaultOptions, { classes: ["dishonored", "sheet", "actor", "npc"], width: 700, - height: 735, + height: 700, + tabs: [{ + navSelector: ".sheet-tabs", + contentSelector: ".sheet-body", + initial: "focuses" + }], + scrollY: [".focuses", ".abilities", ".belongings", ".biography", ".notes"], dragDrop: [{ dragSelector: ".item-list .item", dropSelector: null @@ -18,59 +23,58 @@ export class DishonoredNPCSheet extends ActorSheet { } /* -------------------------------------------- */ + // If the player is not a GM and has limited permissions - send them to the limited sheet, otherwise, continue as usual. /** @override */ - get template() { - if ( !game.user.isGM && this.actor.limited) return "systems/FVTT-Dishonored/templates/actors/limited-sheet.html"; - return `systems/FVTT-Dishonored/templates/actors/npc-sheet.html`; - } + get template () { + if (!game.user.isGM && this.actor.limited) return "systems/FVTT-Dishonored/templates/actors/limited-sheet.html"; + return "systems/FVTT-Dishonored/templates/actors/npc-sheet.html"; + } /* -------------------------------------------- */ /** @override */ getData() { - const data = super.getData(); - data.dtypes = ["String", "Number", "Boolean"]; - + const sheetData = this.object; //Ensure skill and style values don't weigh over the max of 8. - if (data.data.skills.fight.value > 8) data.data.skills.fight.value = 8; - if (data.data.skills.move.value > 8) data.data.skills.move.value = 8; - if (data.data.skills.study.value > 8) data.data.skills.study.value = 8; - if (data.data.skills.survive.value > 8) data.data.skills.survive.value = 8; - if (data.data.skills.talk.value > 8) data.data.skills.talk.value = 8; - if (data.data.skills.tinker.value > 8) data.data.skills.tinker.value = 8; - if (data.data.styles.boldly.value > 8) data.data.styles.boldly.value = 8; - if (data.data.styles.carefully.value > 8) data.data.styles.carefully.value = 8; - if (data.data.styles.cleverly.value > 8) data.data.styles.cleverly.value = 8; - if (data.data.styles.forcefully.value > 8) data.data.styles.forcefully.value = 8; - if (data.data.styles.quietly.value > 8) data.data.styles.quietly.value = 8; - if (data.data.styles.swiftly.value > 8) data.data.styles.swiftly.value = 8; - - // Checks if stress is larger than its max, if so, set to max. - if (data.data.stress.value > data.data.stress.max) data.data.stress.value = data.data.stress.max; + if (sheetData.data.data.skills.fight.value > 8) sheetData.data.data.skills.fight.value = 8; + if (sheetData.data.data.skills.move.value > 8) sheetData.data.data.skills.move.value = 8; + if (sheetData.data.data.skills.study.value > 8) sheetData.data.data.skills.study.value = 8; + if (sheetData.data.data.skills.survive.value > 8) sheetData.data.data.skills.survive.value = 8; + if (sheetData.data.data.skills.talk.value > 8) sheetData.data.data.skills.talk.value = 8; + if (sheetData.data.data.skills.tinker.value > 8) sheetData.data.data.skills.tinker.value = 8; + if (sheetData.data.data.styles.boldly.value > 8) sheetData.data.data.styles.boldly.value = 8; + if (sheetData.data.data.styles.carefully.value > 8) sheetData.data.data.styles.carefully.value = 8; + if (sheetData.data.data.styles.cleverly.value > 8) sheetData.data.data.styles.cleverly.value = 8; + if (sheetData.data.data.styles.forcefully.value > 8) sheetData.data.data.styles.forcefully.value = 8; + if (sheetData.data.data.styles.quietly.value > 8) sheetData.data.data.styles.quietly.value = 8; + if (sheetData.data.data.styles.swiftly.value > 8) sheetData.data.data.styles.swiftly.value = 8; + + // Checks if any values are larger than their relevant max, if so, set to max. + if (sheetData.data.data.stress.value > sheetData.data.data.stress.max) sheetData.data.data.stress.value = sheetData.data.data.stress.max; //Ensure skill and style values aren't lower than 4. - if (data.data.skills.fight.value < 4) data.data.skills.fight.value = 4; - if (data.data.skills.move.value < 4) data.data.skills.move.value = 4; - if (data.data.skills.study.value < 4) data.data.skills.study.value = 4; - if (data.data.skills.survive.value < 4) data.data.skills.survive.value = 4; - if (data.data.skills.talk.value < 4) data.data.skills.talk.value = 4; - if (data.data.skills.tinker.value < 4) data.data.skills.tinker.value = 4; - if (data.data.styles.boldly.value < 4) data.data.styles.boldly.value = 4; - if (data.data.styles.carefully.value < 4) data.data.styles.carefully.value = 4; - if (data.data.styles.cleverly.value < 4) data.data.styles.cleverly.value = 4; - if (data.data.styles.forcefully.value < 4) data.data.styles.forcefully.value = 4; - if (data.data.styles.quietly.value < 4) data.data.styles.quietly.value = 4; - if (data.data.styles.swiftly.value < 4) data.data.styles.swiftly.value = 4; - - // Checks if stress is below 0, if so - set it to 0. - if (data.data.stress.value < 0) data.data.stress.value = 0; + if (sheetData.data.data.skills.fight.value < 4) sheetData.data.data.skills.fight.value = 4; + if (sheetData.data.data.skills.move.value < 4) sheetData.data.data.skills.move.value = 4; + if (sheetData.data.data.skills.study.value < 4) sheetData.data.data.skills.study.value = 4; + if (sheetData.data.data.skills.survive.value < 4) sheetData.data.data.skills.survive.value = 4; + if (sheetData.data.data.skills.talk.value < 4) sheetData.data.data.skills.talk.value = 4; + if (sheetData.data.data.skills.tinker.value < 4) sheetData.data.data.skills.tinker.value = 4; + if (sheetData.data.data.styles.boldly.value < 4) sheetData.data.data.styles.boldly.value = 4; + if (sheetData.data.data.styles.carefully.value < 4) sheetData.data.data.styles.carefully.value = 4; + if (sheetData.data.data.styles.cleverly.value < 4) sheetData.data.data.styles.cleverly.value = 4; + if (sheetData.data.data.styles.forcefully.value < 4) sheetData.data.data.styles.forcefully.value = 4; + if (sheetData.data.data.styles.quietly.value < 4) sheetData.data.data.styles.quietly.value = 4; + if (sheetData.data.data.styles.swiftly.value < 4) sheetData.data.data.styles.swiftly.value = 4; + + // Checks if any values are below their theoretical minimum, if so set it to the very minimum. + if (sheetData.data.data.stress.value < 0) sheetData.data.data.stress.value = 0; - $.each(data.items, (key, item) => { - if (!item.img) item.img = '/systems/FVTT-Dishonored/icons/dishonoredlogo.webp'; - }) + $.each(sheetData.data.items, (key, item) => { + if (!item.img) item.img = "/systems/FVTT-Dishonored/icons/dishonoredlogo.webp"; + }); - return data; + return sheetData.data; } /* -------------------------------------------- */ @@ -79,6 +83,11 @@ export class DishonoredNPCSheet extends ActorSheet { activateListeners(html) { super.activateListeners(html); + // Sets up a declaration to be able to check the version easily. + let versionInfo; + if (game.world.data) versionInfo = game.world.data.coreVersion; + else game.world.coreVersion; + // Opens the class DishonoredSharedActorFunctions for access at various stages. let dishonoredActor = new DishonoredSharedActorFunctions(); @@ -86,134 +95,212 @@ export class DishonoredNPCSheet extends ActorSheet { if ( !game.user.isGM && this.actor.limited) return; // We use i alot in for loops. Best to assign it now for use later in multiple places. - var i; + let i; + // We use div alot to define text blocks. Define here. + let div; + + // Here we are checking how many bonecharms, helmets and armors are equipped. + // The player can only have three bonecharms, and one of each armor type. As such, we will use this later. + let armorNumber = 0; + let bonecharmNumber = 0; + let helmetNumber = 0; + let stressTrackMax = 0; + function armorCount(currentActor) { + armorNumber = 0; + helmetNumber = 0; + currentActor.actor.items.forEach((values) => { + if (values.type == "armor") { + if (values.data.data.helmet == true && values.data.data.equipped == true) helmetNumber+= 1; + if (values.data.data.helmet == false && values.data.data.equipped == true) armorNumber+= 1; + } + }); + } + armorCount(this); // This creates a dynamic Stress tracker. It polls for the value of the survive skill, adds any protection from armor. // With the total value, creates a new div for each and places it under a child called "bar-stress-renderer". - var stressTrackMax = parseInt(html.find('#survive')[0].value); - var armor = html.find('[id^="protectval-armor"]'); - for (i = 0; i < armor.length; i++) { - stressTrackMax += parseInt(armor[i].innerHTML); - } - if (html.find('#max-stress')[0].value != stressTrackMax) - { - html.find('#max-stress')[0].value = stressTrackMax; - this.submit(); - } - for (i = 1; i <= stressTrackMax; i++) { - var div = document.createElement("DIV"); - div.className = "box"; - div.id = "stress-" + i; - div.innerHTML = i; - div.style = "width: calc(100% / " + html.find('#max-stress')[0].value + ");" - html.find('#bar-stress-renderer')[0].appendChild(div); + function stressTrackUpdate() { + stressTrackMax = parseInt(html.find("#survive")[0].value); + let armor = html.find("[data-item-type=\"armor\"]"); + for (i = 0; i < armor.length; i++) { + if (armor[i].getAttribute("data-item-equipped") == "true") { + stressTrackMax += parseInt($(armor[i]).children()[2].innerHTML); + } + } + // This checks that the max-stress hidden field is equal to the calculated Max Stress value, if not it makes it so. + if (html.find("#max-stress")[0].value != stressTrackMax) + { + html.find("#max-stress")[0].value = stressTrackMax; + } + html.find("#bar-stress-renderer").empty(); + for (i = 1; i <= stressTrackMax; i++) { + div = document.createElement("DIV"); + div.className = "box"; + div.id = "stress-" + i; + div.innerHTML = i; + div.style = "width: calc(100% / " + html.find("#max-stress")[0].value + ");"; + html.find("#bar-stress-renderer")[0].appendChild(div); + } } + stressTrackUpdate(); // Fires the function dishonoredRenderTracks as soon as the parameters exist to do so. dishonoredActor.dishonoredRenderTracks(html, stressTrackMax); // This allows for each item-edit image to link open an item sheet. This uses Simple Worldbuilding System Code. - html.find('.control.edit').click(ev => { + html.find(".control.edit").click(ev => { const li = $(ev.currentTarget).parents(".entry"); - const item = this.actor.getOwnedItem(li.data("itemId")); + const item = this.actor.items.get(li.data("itemId")); item.sheet.render(true); }); - // This if statement checks if the form is editable, if not it hides controls used by the owner, then aborts any more of the script. + // This if statement checks if the form is editable, if not it hides control used by the owner, then aborts any more of the script. if (!this.options.editable) { - // This hides the ability to Perform a Skill Test for the character - for (i = 0; i < html.find('.check-button').length; i++) { - html.find('.check-button')[i].style.display = 'none'; + // This hides the ability to Perform a Skill Test for the character. + for (i = 0; i < html.find(".check-button").length; i++) { + html.find(".check-button")[i].style.display = "none"; + } + // This hides the ability to change the amount of Void Points the character has. + for (i = 0; i < html.find(".voidchange").length; i++) { + html.find(".voidchange")[i].style.display = "none"; } - // This hides all add and delete item images. - for (i = 0; i < html.find('.control.create').length; i++) { - html.find('.control.create')[i].style.display = 'none'; + // This hides all toggle, add and delete item images. + for (i = 0; i < html.find(".control.create").length; i++) { + html.find(".control.create")[i].style.display = "none"; } - for (i = 0; i < html.find('.control.delete').length; i++) { - html.find('.control.delete')[i].style.display = 'none'; + for (i = 0; i < html.find(".control.delete").length; i++) { + html.find(".control.delete")[i].style.display = "none"; + } + for (i = 0; i < html.find(".control.toggle").length; i++) { + html.find(".control.delete")[i].style.display = "none"; } // This hides all skill and style check boxes (and titles) - for (i = 0; i < html.find('.selector').length; i++) { - html.find('.selector')[i].style.display = 'none'; + for (i = 0; i < html.find(".selector").length; i++) { + html.find(".selector")[i].style.display = "none"; + } + for (i = 0; i < html.find(".selector").length; i++) { + html.find(".selector")[i].style.display = "none"; } // Remove hover CSS from clickables that are no longer clickable. - for (i = 0; i < html.find('.box').length; i++) { - html.find('.box')[i].classList.add("unset-clickables"); + for (i = 0; i < html.find(".box").length; i++) { + html.find(".box")[i].classList.add("unset-clickables"); } - for (i = 0; i < html.find('.rollable').length; i++) { - html.find('.rollable')[i].classList.add("unset-clickables"); + for (i = 0; i < html.find(".rollable").length; i++) { + html.find(".rollable")[i].classList.add("unset-clickables"); } return; - }; + } + + // This toggles whether the item is equipped or not. Equipped items count towards item caps. + html.find(".control.toggle").click(ev => { + let itemType = $(ev.currentTarget).parents(".entry")[0].getAttribute("data-item-type"); + let itemId = $(ev.currentTarget).parents(".entry")[0].getAttribute("data-item-id"); + let item = this.actor.items.get(itemId); + let itemData = item.data; + if (itemType == "armor") var isHelmet = $(ev.currentTarget).parents(".entry")[0].getAttribute("data-item-helmet"); + if (this.actor.items.get(itemId).data.data.equipped == true) { + itemData.data.equipped = false; + $(ev.currentTarget).children()[0].classList.remove("fa-toggle-on"); + $(ev.currentTarget).children()[0].classList.add("fa-toggle-off"); + $(ev.currentTarget).parents(".entry")[0].setAttribute("data-item-equipped", "false"); + } + else if (itemType == "bonecharm" && bonecharmNumber >= 3) { + ui.notifications.error(game.i18n.localize("dishonored.notifications.tooManyBonecharms")); + } + else if (itemType == "armor" && isHelmet == "false" && armorNumber >= 1) { + ui.notifications.error(game.i18n.localize("dishonored.notifications.armorAlreadyEquipped")); + } + else if (itemType == "armor" && isHelmet == "true" && helmetNumber >= 1) { + ui.notifications.error(game.i18n.localize("dishonored.notifications.helmentAlreadyEquipped")); + } + else { + itemData.data.equipped = true; + $(ev.currentTarget).children()[0].classList.remove("fa-toggle-off"); + $(ev.currentTarget).children()[0].classList.add("fa-toggle-on"); + $(ev.currentTarget).parents(".entry")[0].setAttribute("data-item-equipped", "true"); + } + item.update(itemData); + stressTrackUpdate(); + dishonoredActor.dishonoredRenderTracks(html, stressTrackMax); + this.submit(); + }); // This allows for all items to be rolled, it gets the current targets type and id and sends it to the rollGenericItem function. - html.find('.rollable').click(ev =>{ - var itemType = $(ev.currentTarget).parents(".entry")[0].getAttribute("data-item-type"); - var itemId = $(ev.currentTarget).parents(".entry")[0].getAttribute("data-item-id"); + html.find(".rollable").click(ev =>{ + let itemType = $(ev.currentTarget).parents(".entry")[0].getAttribute("data-item-type"); + let itemId = $(ev.currentTarget).parents(".entry")[0].getAttribute("data-item-id"); dishonoredActor.rollGenericItem(ev, itemType, itemId, this.actor); - }) + }); // Allows item-create images to create an item of a type defined individually by each button. This uses code found via the Foundry VTT System Tutorial. - html.find('.control.create').click(ev => { + html.find(".control.create").click(ev => { ev.preventDefault(); const header = ev.currentTarget; const type = header.dataset.type; const data = duplicate(header.dataset); - const name = game.i18n.format("dishonored.actor.item.adjectiveNew") + ' ' + type.charAt(0).toUpperCase() + type.slice(1); + const name = game.i18n.format("dishonored.actor.item.adjectiveNew") + " " + type.charAt(0).toUpperCase() + type.slice(1); + if (type == "bonecharm" && bonecharmNumber >= 3) { + ui.notifications.info(game.i18n.localize("dishonored.notifications.tooManyBonecharmsNew")); + data.equipped = false; + } + if (type == "armor" && armorNumber >= 1) { + ui.notifications.info(game.i18n.localize("dishonored.notifications.armorAlreadyEquippedNew")); + data.equipped = false; + } const itemData = { name: name, type: type, data: data }; delete itemData.data["type"]; - return this.actor.createOwnedItem(itemData); + stressTrackUpdate(); + // Check if we are using a Foundry version above 0.8.0, use new code. + if (isNewerVersion(versionInfo,"0.8.-1")) return this.actor.createEmbeddedDocuments("Item",[(itemData)]); + else return this.actor.createOwnedItem(itemData); }); // Allows item-delete images to allow deletion of the selected item. This uses Simple Worldbuilding System Code. - html.find('.control.delete').click(ev => { + html.find(".control.delete").click(ev => { const li = $(ev.currentTarget).parents(".entry"); - this.actor.deleteOwnedItem(li.data("itemId")); + // Check if we are using a Foundry version above 0.8.0, use new code. + if (isNewerVersion(versionInfo,"0.8.-1")) this.actor.deleteEmbeddedDocuments("Item",[li.data("itemId")]); + else this.actor.deleteOwnedItem(li.data("itemId")); li.slideUp(200, () => this.render(false)); }); // Reads if a stress track box has been clicked, and if it has will either: set the value to the clicked box, or reduce the value by one. - // This check is dependent on various requirements, see comments in code. - html.find('[id^="stress"]').click(ev => { - var newTotalObject = $(ev.currentTarget)[0]; - var newTotal = newTotalObject.id.substring(7); - // data-selected stores whether the track box is currently activated or not. This checks that the box is activated + // See line 186-220 for a more detailed break down on the context of each scenario. Stress uses the same logic. + html.find("[id^=\"stress\"]").click(ev => { + let newTotalObject = $(ev.currentTarget)[0]; + let newTotal = newTotalObject.id.substring(7); + let total; if (newTotalObject.getAttribute("data-selected") === "true") { - // Now we check that the "next" track box is not activated. - // If there isn't one, or it isn't activated, we only want to decrease the value by 1 rather than setting the value. - var nextCheck = 'stress-' + (parseInt(newTotal) + 1); - if (!html.find('#'+nextCheck)[0] || html.find('#'+nextCheck)[0].getAttribute("data-selected") != "true") { - html.find('#total-stress')[0].value = html.find('#total-stress')[0].value - 1; + let nextCheck = "stress-" + (parseInt(newTotal) + 1); + if (!html.find("#"+nextCheck)[0] || html.find("#"+nextCheck)[0].getAttribute("data-selected") != "true") { + html.find("#total-stress")[0].value = html.find("#total-stress")[0].value - 1; this.submit(); - } - // If it isn't caught by the if, the next box is likely activated. If something happened, its safer to set the value anyway. - else { - var total = html.find('#total-stress')[0].value; + } else { + total = html.find("#total-stress")[0].value; if (total != newTotal) { - html.find('#total-stress')[0].value = newTotal; + html.find("#total-stress")[0].value = newTotal; this.submit(); } } - } - // If the clicked box wasn't activated, we need to activate it now. - else { - var total = html.find('#total-stress')[0].value; + } else { + total = html.find("#total-stress")[0].value; if (total != newTotal) { - html.find('#total-stress')[0].value = newTotal; + html.find("#total-stress")[0].value = newTotal; this.submit(); } } }); + // Turns the Skill checkboxes into essentially a radio button. It removes any other ticks, and then checks the new skill. // Finally a submit is required as data has changed. - html.find('.selector.skill').click(ev => { + html.find(".selector.skill").click(ev => { for (i = 0; i <= 5; i++) { - html.find('.selector.skill')[i].checked = false; + html.find(".selector.skill")[i].checked = false; } $(ev.currentTarget)[0].checked = true; this.submit(); @@ -221,31 +308,36 @@ export class DishonoredNPCSheet extends ActorSheet { // Turns the Style checkboxes into essentially a radio button. It removes any other ticks, and then checks the new style. // Finally a submit is required as data has changed. - html.find('.selector.style').click(ev => { + html.find(".selector.style").click(ev => { for (i = 0; i <= 5; i++) { - html.find('.selector.style')[i].checked = false; + html.find(".selector.style")[i].checked = false; } $(ev.currentTarget)[0].checked = true; this.submit(); }); // If the check-button is clicked it grabs the selected skill and the selected style and fires the method rollSkillTest. See actor.js for further info. - html.find('.check-button').click(ev => { + html.find(".check-button").click(ev => { + let selectedSkill; + let selectedSkillValue; + let selectedStyle; + let selectedStyleValue; for (i = 0; i <= 5; i++) { - if (html.find('.selector.skill')[i].checked === true) { - var selectedSkill = html.find('.selector.skill')[i].id; - var selectedSkill = selectedSkill.slice(0, -9) - var selectedSkillValue = html.find('#'+selectedSkill)[0].value; + if (html.find(".selector.skill")[i].checked === true) { + let selectedSkillHTML = html.find(".selector.skill")[i].id; + selectedSkill = selectedSkillHTML.slice(0, -9); + selectedSkillValue = html.find("#"+selectedSkill)[0].value; } } for (i = 0; i <= 5; i++) { - if (html.find('.selector.style')[i].checked === true) { - var selectedStyle = html.find('.selector.style')[i].id; - var selectedStyle = selectedStyle.slice(0, -9) - var selectedStyleValue = html.find('#'+selectedStyle)[0].value; + if (html.find(".selector.style")[i].checked === true) { + let selectedStyleHTML = html.find(".selector.style")[i].id; + selectedStyle = selectedStyleHTML.slice(0, -9); + selectedStyleValue = html.find("#"+selectedStyle)[0].value; } } - var checkTarget = parseInt(selectedSkillValue) + parseInt(selectedStyleValue); + let checkTarget = parseInt(selectedSkillValue) + parseInt(selectedStyleValue); + dishonoredActor.rollSkillTest(ev, checkTarget, selectedSkill, selectedStyle, this.actor); }); } diff --git a/module/apps/logo.js b/module/apps/logo.js index 13c03ea..bf311c2 100644 --- a/module/apps/logo.js +++ b/module/apps/logo.js @@ -10,7 +10,7 @@ export class DishonoredLogo extends Application { activateListeners(html) { html[0].href += game.system.data.version; - html.find('#dishonored-logo-verID')[0].innerHTML = game.system.data.version; + html.find("#dishonored-logo-verID")[0].innerHTML = game.system.data.version; } } diff --git a/module/apps/roll-dialog.js b/module/apps/roll-dialog.js index 54c32a0..864a6cc 100644 --- a/module/apps/roll-dialog.js +++ b/module/apps/roll-dialog.js @@ -8,11 +8,11 @@ export class DishonoredRollDialog { let formData = null; // Create a new dialog. const dlg = new Dialog({ - title: game.i18n.localize('dishonored.apps.dicepoolwindow'), + title: game.i18n.localize("dishonored.apps.dicepoolwindow"), content: html, buttons: { roll: { - label: game.i18n.localize('dishonored.apps.rolldice'), + label: game.i18n.localize("dishonored.apps.rolldice"), callback: html => { formData = new FormData(html[0].querySelector("#dice-pool-form")); return resolve(formData); diff --git a/module/apps/tracker.js b/module/apps/tracker.js index 77629ae..d98e333 100644 --- a/module/apps/tracker.js +++ b/module/apps/tracker.js @@ -13,33 +13,26 @@ export class DishonoredTracker extends Application { let chaos = game.settings.get("FVTT-Dishonored", "chaos"); let momentum = game.settings.get("FVTT-Dishonored", "momentum"); // Fire renderTracker once which populates the Momentum and Chaos windows, then consistently check for updates, this should be seperate as we want the check function to be asyncherous. - renderTracker() + renderTracker(); this.checkUpdates(); // Hide the increase and decrease buttons if the user doesn't have permissions. if (!game.user.hasRole(game.settings.get("FVTT-Dishonored", "chaosPermissionLevel"))) { - html.find('#dishonored-chaos-track-decrease')[0].style.display = 'none'; - html.find('#dishonored-chaos-track-increase')[0].style.display = 'none'; - html.find('#dishonored-track-chaos')[0].disabled = true; - } - - // Hide the increase and decrease buttons if the user doesn't have permissions. - if (!game.user.hasRole(game.settings.get("FVTT-Dishonored", "momentumPermissionLevel"))) { - html.find('#dishonored-momentum-track-decrease')[0].style.display = 'none'; - html.find('#dishonored-momentum-track-increase')[0].style.display = 'none'; - html.find('#dishonored-track-momentum')[0].disabled = true; + html.find("#dishonored-chaos-track-decrease")[0].style.display = "none"; + html.find("#dishonored-chaos-track-increase")[0].style.display = "none"; + html.find("#dishonored-track-chaos")[0].disabled = true; } // Find the button which has the class #dishonored-chaos-track-increase and tie the following to the onClick - html.find('#dishonored-chaos-track-increase').click(ev => { + html.find("#dishonored-chaos-track-increase").click(function() { // Check if the player has permissions before moving on! if (game.user.hasRole(game.settings.get("FVTT-Dishonored", "chaosPermissionLevel"))) { // Set momentum, we do this as otherwise when we render the tracker it will use the old initial load momentum (THANKS mkscho63) momentum = game.settings.get("FVTT-Dishonored", "momentum"); chaos = parseInt(document.getElementById("dishonored-track-chaos").value); - // Check if chaos is currently 99999999, anything past this is unable to render. If it is error. This is a meme. - if (chaos === 99999999) { - ui.notifications.error(game.i18n.localize('dishonored.notifications.chaosGreater')); + // Check if chaos is currently 99, anything past this is unable to render. If it does error it becomes a meme. + if (chaos === 99) { + ui.notifications.error(game.i18n.localize("dishonored.notifications.chaosGreater")); return false; } // Otherwise we are good to add +1 and set the value and re-render the track. @@ -49,36 +42,12 @@ export class DishonoredTracker extends Application { } // If the played does not have permissions - error! else { - ui.notifications.error(game.i18n.localize('dishonored.notifications.chaosButtonInvalidPermissions')); - return false; - } - }); - - // Find the button which has the class #dishonored-momentum-track-increase and tie the following to the onClick - html.find('#dishonored-momentum-track-increase').click(ev => { - // Check if the player has permissions before moving on! - if (game.user.hasRole(game.settings.get("FVTT-Dishonored", "momentumPermissionLevel"))) { - // Set chaos, we do this as otherwise when we render the tracker it will use the old initial load chaos (THANKS mkscho63) - chaos = game.settings.get("FVTT-Dishonored", "chaos"); - momentum = parseInt(document.getElementById("dishonored-track-momentum").value); - // check if momentum is currently 6, if so it cannot be increased so error. - if (momentum === 6) { - ui.notifications.error(game.i18n.localize('dishonored.notifications.momentumGreater')); - return false; - } - // Otherwise we are good to add +1 and set the value and re-render the track. - momentum = momentum + 1; - game.settings.set("FVTT-Dishonored", "momentum", momentum); - renderTracker(); - } - // If the played does not have permissions - error! - else { - ui.notifications.error(game.i18n.localize('dishonored.notifications.momentumButtonInvalidPermissions')); + ui.notifications.error(game.i18n.localize("dishonored.notifications.chaosButtonInvalidPermissions")); return false; } }); - html.find('#dishonored-chaos-track-decrease').click(ev => { + html.find("#dishonored-chaos-track-decrease").click(function() { // Check if the player has permissions before moving on! if (game.user.hasRole(game.settings.get("FVTT-Dishonored", "chaosPermissionLevel"))) { // Set momentum, we do this as otherwise when we render the tracker it will use the old initial load momentum (THANKS mkscho63) @@ -86,7 +55,7 @@ export class DishonoredTracker extends Application { chaos = parseInt(document.getElementById("dishonored-track-chaos").value); // check if chaos is currently 0, if so it cannot be decreased so error. if (chaos === 0) { - ui.notifications.warn(game.i18n.localize('dishonored.notifications.chaosLess')); + ui.notifications.warn(game.i18n.localize("dishonored.notifications.chaosLess")); return false; } // Otherwise we are good to take -1 and set the value and re-render the track. @@ -96,49 +65,20 @@ export class DishonoredTracker extends Application { } // If the played does not have permissions - error! else { - ui.notifications.error(game.i18n.localize('dishonored.notifications.chaosButtonInvalidPermissions')); - return false; - } - }); - - html.find('#dishonored-momentum-track-decrease').click(ev => { - // Check if the player has permissions before moving on! - if (game.user.hasRole(game.settings.get("FVTT-Dishonored", "momentumPermissionLevel"))) { - // Set chaos, we do this as otherwise when we render the tracker it will use the old initial load chaos (THANKS mkscho63) - chaos = game.settings.get("FVTT-Dishonored", "chaos"); - momentum = parseInt(document.getElementById("dishonored-track-momentum").value); - // check if momentum is currently 0, if so it cannot be decreased so error. - if (momentum === 0) { - ui.notifications.warn(game.i18n.localize('dishonored.notifications.momentumLess')); - return false; - } - // Otherwise we are good to take -1 and set the value and re-render the track. - momentum = momentum - 1; - game.settings.set("FVTT-Dishonored", "momentum", momentum); - renderTracker(); - } - // If the played does not have permissions - error! - else { - ui.notifications.error(game.i18n.localize('dishonored.notifications.momentumButtonInvalidPermissions')); + ui.notifications.error(game.i18n.localize("dishonored.notifications.chaosButtonInvalidPermissions")); return false; } }); // We want it so that we unfocus if the enter key is pressed, we do this by recording the keycode 13 and bluring. - html.find('#dishonored-track-chaos').keydown(ev => { + html.find("#dishonored-track-chaos").keydown(ev => { if (ev.keyCode == 13) { - html.find('#dishonored-track-chaos').blur(); + html.find("#dishonored-track-chaos").blur(); } - }) - - html.find('#dishonored-track-momentum').keydown(ev => { - if (ev.keyCode == 13) { - html.find('#dishonored-track-momentum').blur(); - } - }) + }); // This is what is fired when the chaos tracker text box is edited. - html.find('#dishonored-track-chaos').change(ev => { + html.find("#dishonored-track-chaos").change(function() { // Check if the player has permissions before moving on! if (game.user.hasRole(game.settings.get("FVTT-Dishonored", "chaosPermissionLevel"))) { // Set chaos and momentum, we do this as otherwise when we render the tracker it will use the old initial load chaos (THANKS mkscho63) @@ -147,19 +87,19 @@ export class DishonoredTracker extends Application { let len = document.getElementById("dishonored-track-chaos").value.length; // If the value is NaN and doesn't start with + or -, then error. if (isNaN(document.getElementById("dishonored-track-chaos").value) && document.getElementById("dishonored-track-chaos").value.substr(0,1) != "+" && document.getElementById("dishonored-track-chaos").value.substr(0,1) != "-") { - ui.notifications.error(game.i18n.localize('dishonored.notifications.NaN')); + ui.notifications.error(game.i18n.localize("dishonored.notifications.NaN")); document.getElementById("dishonored-track-chaos").value = chaos; } else { // If a blank value is input, default to 0 - if (document.getElementById("dishonored-track-chaos").value == '') { + if (document.getElementById("dishonored-track-chaos").value == "") { document.getElementById("dishonored-track-chaos").value = 0; } // If a value begins with +, then add the two together if (document.getElementById("dishonored-track-chaos").value.substr(0,1) == "+") { // As we allow any + value through we want to check the rest is actually a number, this is caught here. if (isNaN(document.getElementById("dishonored-track-chaos").value.substr(1,len-1))) { - ui.notifications.error(game.i18n.localize('dishonored.notifications.NaN')); + ui.notifications.error(game.i18n.localize("dishonored.notifications.NaN")); document.getElementById("dishonored-track-chaos").value = chaos; } else { @@ -170,7 +110,7 @@ export class DishonoredTracker extends Application { if (document.getElementById("dishonored-track-chaos").value.substr(0,1) == "-") { // As we allow any - value through we want to check the rest is actually a number, this is caught here. if (isNaN(document.getElementById("dishonored-track-chaos").value.substr(1,len-1))) { - ui.notifications.error(game.i18n.localize('dishonored.notifications.NaN')); + ui.notifications.error(game.i18n.localize("dishonored.notifications.NaN")); document.getElementById("dishonored-track-chaos").value = chaos; } else { @@ -180,13 +120,13 @@ export class DishonoredTracker extends Application { // If the new value is going to be below 0, warn and return false. if (document.getElementById("dishonored-track-chaos").value < 0) { document.getElementById("dishonored-track-chaos").value = chaos; - ui.notifications.warn(game.i18n.localize('dishonored.notifications.chaosLess')); + ui.notifications.warn(game.i18n.localize("dishonored.notifications.chaosLess")); return false; } - // If the new value is going to be above 99999999, error and return false. - if (document.getElementById("dishonored-track-chaos").value > 99999999) { + // If the new value is going to be above 99, error and return false. + if (document.getElementById("dishonored-track-chaos").value > 99) { document.getElementById("dishonored-track-chaos").value = chaos; - ui.notifications.error(game.i18n.localize('dishonored.notifications.chaosGreaterSet')); + ui.notifications.error(game.i18n.localize("dishonored.notifications.chaosGreaterSet")); return false; } } @@ -197,91 +137,82 @@ export class DishonoredTracker extends Application { } // If the played does not have permissions - error! else { - ui.notifications.error(game.i18n.localize('dishonored.notifications.chaosButtonInvalidPermissions')); + ui.notifications.error(game.i18n.localize("dishonored.notifications.chaosButtonInvalidPermissions")); return false; } }); - // This is what is fired when the momentum tracker text box is edited. - html.find('#dishonored-track-momentum').change(ev => { - // Check if the player has permissions before moving on! - if (game.user.hasRole(game.settings.get("FVTT-Dishonored", "momentumPermissionLevel"))) { - // Set chaos and momentum, we do this as otherwise when we render the tracker it will use the old initial load chaos (THANKS mkscho63) - momentum = game.settings.get("FVTT-Dishonored", "momentum"); - chaos = game.settings.get("FVTT-Dishonored", "chaos"); - // If the value is NaN and doesn't start with + or -, then error. - if (isNaN(document.getElementById("dishonored-track-momentum").value) && document.getElementById("dishonored-track-momentum").value.substr(0,1) != "+" && document.getElementById("dishonored-track-momentum").value.substr(0,1) != "-") { - ui.notifications.error(game.i18n.localize('dishonored.notifications.NaN')); - document.getElementById("dishonored-track-momentum").value = momentum; - } + html.find("[id^=\"dishonored-momentum-tracker\"]").click(ev => { + momentum = game.settings.get("FVTT-Dishonored", "momentum"); + chaos = game.settings.get("FVTT-Dishonored", "chaos"); + let captureObject = $(ev.currentTarget)[0]; + let newTotalObjectBG = html.find("#" + captureObject.id.substr(0,captureObject.id.length-2) + "bg")[0]; + let newTotal = captureObject.id.replace(/\D/g, ""); + // data-selected stores whether the track box is currently activated or not. This checks that the box is activated + if (newTotalObjectBG.getAttribute("data-selected") === "true") { + // Now we check that the "next" track box is not activated. + // If there isn't one, or it isn't activated, we only want to decrease the value by 1 rather than setting the value. + let nextCheck = "dishonored-momentum-tracker-" + (parseInt(newTotal) + 1 + "-bg"); + if (!html.find("#"+nextCheck)[0] || html.find("#"+nextCheck)[0].getAttribute("data-selected") != "true") { + momentum = momentum - 1; + game.settings.set("FVTT-Dishonored", "momentum", momentum); + renderTracker(); + } + // If it isn't caught by the if, the next box is likely activated. If something happened, its safer to set the value anyway. else { - // If a blank value is input, default to 0 - if (document.getElementById("dishonored-track-momentum").value == '') { - document.getElementById("dishonored-track-momentum").value = 0; - } - // If a value begins with +, then add the two together - if (document.getElementById("dishonored-track-momentum").value.substr(0,1) == "+") { - // As we allow any + value through we want to check the rest is actually a number, this is caught here. - if (isNaN(document.getElementById("dishonored-track-momentum").value.substr(1,len-1))) { - ui.notifications.error(game.i18n.localize('dishonored.notifications.NaN')); - document.getElementById("dishonored-track-momentum").value = momentum; - } - else { - document.getElementById("dishonored-track-momentum").value = momentum + parseInt(document.getElementById("dishonored-track-momentum").value.substr(1,document.getElementById("dishonored-track-momentum").value.length - 1)); - } - } - // If a value begins with -, then take the new value from the older. - if (document.getElementById("dishonored-track-momentum").value.substr(0,1) == "-") { - // As we allow any + value through we want to check the rest is actually a number, this is caught here. - if (isNaN(document.getElementById("dishonored-track-momentum").value.substr(1,len-1))) { - ui.notifications.error(game.i18n.localize('dishonored.notifications.NaN')); - document.getElementById("dishonored-track-momentum").value = momentum; - } - else { - document.getElementById("dishonored-track-momentum").value = momentum - parseInt(document.getElementById("dishonored-track-momentum").value.substr(1,document.getElementById("dishonored-track-momentum").value.length - 1)); - } - } - // If the new value is going to be below 0, warn and return false. - if (document.getElementById("dishonored-track-momentum").value < 0) { - document.getElementById("dishonored-track-momentum").value = momentum; - ui.notifications.warn(game.i18n.localize('dishonored.notifications.momentumLess')); - return false; - } - // If the new value is going to be above 6, warn and return false. - if (document.getElementById("dishonored-track-momentum").value > 6) { - document.getElementById("dishonored-track-momentum").value = momentum; - ui.notifications.warn(game.i18n.localize('dishonored.notifications.momentumGreaterSet')); - return false; + // let total = html.find('#total-exp')[0].value; + if (momentum != newTotal) { + momentum = newTotal; + game.settings.set("FVTT-Dishonored", "momentum", momentum); + renderTracker(); } } - // Set the value and re-render - momentum = document.getElementById("dishonored-track-momentum").value; - game.settings.set("FVTT-Dishonored", "momentum", momentum); - renderTracker(); - } - // If the played does not have permissions - error! + } + // If the clicked box wasn't activated, we need to activate it now. else { - ui.notifications.error(game.i18n.localize('dishonored.notifications.momentumButtonInvalidPermissions')); - return false; + if (momentum != newTotal) { + momentum = newTotal; + game.settings.set("FVTT-Dishonored", "momentum", momentum); + renderTracker(); + } } }); // Set the element value to its respective variable. function renderTracker() { document.getElementById("dishonored-track-chaos").value = chaos; - document.getElementById("dishonored-track-momentum").value = momentum; + for (let i=1;i<=6;i++) { + if (i<=momentum) { + html.find("#dishonored-momentum-tracker-"+i+"-bg")[0].setAttribute("data-selected", "true"); + html.find("#dishonored-momentum-tracker-"+i+"-bg")[0].style.fill = "white"; + html.find("#dishonored-momentum-tracker-"+i+"-fg")[0].style.color = ""; + html.find("#dishonored-momentum-tracker-"+i+"-fg")[0].style.textShadow = ""; + } + else { + html.find("#dishonored-momentum-tracker-"+i+"-bg")[0].removeAttribute("data-selected"); + html.find("#dishonored-momentum-tracker-"+i+"-bg")[0].style.fill = ""; + html.find("#dishonored-momentum-tracker-"+i+"-fg")[0].style.color = "white"; + html.find("#dishonored-momentum-tracker-"+i+"-fg")[0].style.textShadow = "-1px 0 black, 0 1px black, 1px 0 black, 0 -1px black"; + } + } } - } async checkUpdates() { + // We use i in loops, defining at top-level + let i; // Grab the Refresh Rate from the system settings (*1000 as JS counts in ms) let refreshRate = game.settings.get("FVTT-Dishonored", "trackerRefreshRate") * 1000; // Create function that will cycle regularly - function check() { + setInterval(function check() { // Define Chaos and Momentum as the value displayed and the storedChaos and Momentum as the value saved to the settings let chaos = document.getElementById("dishonored-track-chaos").value; - let momentum = document.getElementById("dishonored-track-momentum").value; + let momentum; + for (i=1;i<=6;i++) { + if (document.getElementById("dishonored-momentum-tracker-"+i+"-bg").getAttribute("data-selected")==="true") { + momentum = i; + } + } let storedChaos = game.settings.get("FVTT-Dishonored", "chaos"); let storedMomentum = game.settings.get("FVTT-Dishonored", "momentum"); // Get out clause that checks if the chaos or momentum is below 0 and if so, change it to 0. @@ -292,23 +223,29 @@ export class DishonoredTracker extends Application { game.settings.set("FVTT-Dishonored", "momentum", 0); } // Check if the field is currently focused, we don't want to interupt the user if they have the field focused! - if ($("#dishonored-track-chaos").is(':focus') == false) { + if ($("#dishonored-track-chaos").is(":focus") == false) { // If the displayed and stored value is not equal, make the displayed value equal the stored value! if (storedChaos != chaos) { document.getElementById("dishonored-track-chaos").value = storedChaos; } } - // Check if the field is currently focused, we don't want to interupt the user if they have the field focused! - if ($("#dishonored-track-momentum").is(':focus') == false) { - // If the displayed and stored value is not equal, make the displayed value equal the stored value! - if (storedMomentum != momentum) { - document.getElementById("dishonored-track-momentum").value = storedMomentum; + + if (storedMomentum != momentum) { + for (i=1;i<=6;i++) { + if (i<=storedMomentum) { + document.getElementById("dishonored-momentum-tracker-"+i+"-bg").setAttribute("data-selected", "true"); + document.getElementById("dishonored-momentum-tracker-"+i+"-bg").style.fill = "white"; + document.getElementById("dishonored-momentum-tracker-"+i+"-fg").style.color = ""; + document.getElementById("dishonored-momentum-tracker-"+i+"-fg").style.textShadow = ""; + } + else { + document.getElementById("dishonored-momentum-tracker-"+i+"-bg").removeAttribute("data-selected"); + document.getElementById("dishonored-momentum-tracker-"+i+"-bg").style.fill = ""; + document.getElementById("dishonored-momentum-tracker-"+i+"-fg").style.color = "white"; + document.getElementById("dishonored-momentum-tracker-"+i+"-fg").style.textShadow = "-1px 0 black, 0 1px black, 1px 0 black, 0 -1px black"; + } } - } - // Tell script to wait for refresh, and then fire this function again - setTimeout(check, refreshRate); - } - // Initially fire the function. - check(); + } + }, refreshRate); } } diff --git a/module/dishonored.js b/module/dishonored.js index 6e79bfe..913e643 100644 --- a/module/dishonored.js +++ b/module/dishonored.js @@ -35,6 +35,9 @@ import { import { DishonoredPowerSheet } from "./items/power-sheet.js"; +import { + DishonoredTruthSheet +} from "./items/truth-sheet.js"; import { DishonoredTracker } from "./apps/tracker.js"; @@ -42,13 +45,16 @@ import { DishonoredLogo } from "./apps/logo.js"; import * as macros -from "./macro.js"; + from "./macro.js"; /* -------------------------------------------- */ /* Foundry VTT Initialization */ /* -------------------------------------------- */ Hooks.once("init", function() { + let versionInfo; + if (game.world.data) versionInfo = game.world.data.coreVersion; + else game.world.coreVersion; // Splash Screen console.log(`Initializing Dishonored Tabletop Roleplaying Game System @@ @@ -73,8 +79,7 @@ Hooks.once("init", function() { @ @@@@ @@@ @@@ - @@`) - + @@`); // Create a namespace within the game global game.dishonored = { @@ -89,6 +94,7 @@ Hooks.once("init", function() { DishonoredTalentSheet, DishonoredContactSheet, DishonoredPowerSheet, + DishonoredTruthSheet, }, entities: { DishonoredActor, @@ -104,8 +110,8 @@ Hooks.once("init", function() { }; // Define custom Entity classes - CONFIG.Actor.entityClass = DishonoredActor; - CONFIG.Item.entityClass = DishonoredItem; + CONFIG.Actor.documentClass = DishonoredActor; + CONFIG.Item.documentClass = DishonoredItem; // Register sheet application classes Actors.unregisterSheet("core", ActorSheet); @@ -142,12 +148,15 @@ Hooks.once("init", function() { Items.registerSheet("dishonored", DishonoredPowerSheet, { types: ["power"], }); + Items.registerSheet("dishonored", DishonoredTruthSheet, { + types: ["truth"], + }); // Code taken from FFG Star Wars which also flips their health system! (Plus I like the increasing height that it implements) Token.prototype._drawBar = function (number, bar, data) { let val = Number(data.value); if (data.attribute === "stress") { - val = Number(data.max - data.value); + val = Number(data.max - data.value); } const pct = Math.clamped(val, 0, data.max) / data.max; let h = Math.max(canvas.dimensions.size / 12, 8); @@ -155,22 +164,22 @@ Hooks.once("init", function() { // Draw the bar let color = number === 0 ? [1 - pct / 2, pct, 0] : [0.5 * pct, 0.7 * pct, 0.5 + pct / 2]; bar - .clear() - .beginFill(0x000000, 0.5) - .lineStyle(2, 0x000000, 0.9) - .drawRoundedRect(0, 0, this.w, h, 3) - .beginFill(PIXI.utils.rgb2hex(color), 0.8) - .lineStyle(1, 0x000000, 0.8) - .drawRoundedRect(1, 1, pct * (this.w - 2), h - 2, 2); + .clear() + .beginFill(0x000000, 0.5) + .lineStyle(2, 0x000000, 0.9) + .drawRoundedRect(0, 0, this.w, h, 3) + .beginFill(PIXI.utils.rgb2hex(color), 0.8) + .lineStyle(1, 0x000000, 0.8) + .drawRoundedRect(1, 1, pct * (this.w - 2), h - 2, 2); // Set position let posY = number === 0 ? this.h - h : 0; bar.position.set(0, posY); - }; + }; // Register system settings game.settings.register("FVTT-Dishonored", "multipleComplications", { - name: game.i18n.localize('dishonored.settings.names.multipleComplications'), - hint: game.i18n.localize('dishonored.settings.hints.multipleComplications'), + name: game.i18n.localize("dishonored.settings.names.multipleComplications"), + hint: game.i18n.localize("dishonored.settings.hints.multipleComplications"), scope: "world", type: Boolean, default: true, @@ -178,54 +187,54 @@ Hooks.once("init", function() { }); game.settings.register("FVTT-Dishonored", "send2ActorPermissionLevel", { - name: game.i18n.localize('dishonored.settings.names.send2ActorPermissionLevel'), - hint: game.i18n.localize('dishonored.settings.hints.send2ActorPermissionLevel'), + name: game.i18n.localize("dishonored.settings.names.send2ActorPermissionLevel"), + hint: game.i18n.localize("dishonored.settings.hints.send2ActorPermissionLevel"), scope: "world", type: String, default: "ASSISTANT", config: true, choices: { - "NONE": "Switch Off Send2Actor", - "PLAYER": "Players", - "TRUSTED": "Trusted Players", - "ASSISTANT": "Assistant Gamemaster", - "GAMEMASTER": "Gamemasters", + "NONE": "Switch Off Send2Actor", + "PLAYER": game.i18n.localize("USER.RolePlayer"), + "TRUSTED": game.i18n.localize("USER.RoleTrusted"), + "ASSISTANT": game.i18n.localize("USER.RoleAssistant"), + "GAMEMASTER": game.i18n.localize("USER.RoleGamemaster"), } }); game.settings.register("FVTT-Dishonored", "chaosPermissionLevel", { - name: game.i18n.localize('dishonored.settings.names.chaosPermissionLevel'), - hint: game.i18n.localize('dishonored.settings.hints.chaosPermissionLevel'), + name: game.i18n.localize("dishonored.settings.names.chaosPermissionLevel"), + hint: game.i18n.localize("dishonored.settings.hints.chaosPermissionLevel"), scope: "world", type: String, default: "ASSISTANT", config: true, choices: { - "PLAYER": "Players", - "TRUSTED": "Trusted Players", - "ASSISTANT": "Assistant Gamemaster", - "GAMEMASTER": "Gamemasters", + "PLAYER": game.i18n.localize("USER.RolePlayer"), + "TRUSTED": game.i18n.localize("USER.RoleTrusted"), + "ASSISTANT": game.i18n.localize("USER.RoleAssistant"), + "GAMEMASTER": game.i18n.localize("USER.RoleGamemaster"), } }); game.settings.register("FVTT-Dishonored", "momentumPermissionLevel", { - name: game.i18n.localize('dishonored.settings.names.momentumPermissionLevel'), - hint: game.i18n.localize('dishonored.settings.hints.momentumPermissionLevel'), + name: game.i18n.localize("dishonored.settings.names.momentumPermissionLevel"), + hint: game.i18n.localize("dishonored.settings.hints.momentumPermissionLevel"), scope: "world", type: String, default: "PLAYER", config: true, choices: { - "PLAYER": "Players", - "TRUSTED": "Trusted Players", - "ASSISTANT": "Assistant Gamemaster", - "GAMEMASTER": "Gamemasters", + "PLAYER": game.i18n.localize("USER.RolePlayer"), + "TRUSTED": game.i18n.localize("USER.RoleTrusted"), + "ASSISTANT": game.i18n.localize("USER.RoleAssistant"), + "GAMEMASTER": game.i18n.localize("USER.RoleGamemaster"), } }); game.settings.register("FVTT-Dishonored", "maxNumberOfExperience", { - name: game.i18n.localize('dishonored.settings.names.maxNumberOfExperience'), - hint: game.i18n.localize('dishonored.settings.hints.maxNumberOfExperience'), + name: game.i18n.localize("dishonored.settings.names.maxNumberOfExperience"), + hint: game.i18n.localize("dishonored.settings.hints.maxNumberOfExperience"), scope: "world", type: Number, default: 30, @@ -233,14 +242,21 @@ Hooks.once("init", function() { }); game.settings.register("FVTT-Dishonored", "trackerRefreshRate", { - name: game.i18n.localize('dishonored.settings.names.trackerRefreshRate'), - hint: game.i18n.localize('dishonored.settings.hints.trackerRefreshRate'), + name: game.i18n.localize("dishonored.settings.names.trackerRefreshRate"), + hint: game.i18n.localize("dishonored.settings.hints.trackerRefreshRate"), scope: "world", type: Number, default: 5, config: true }); + game.settings.register("FVTT-Dishonored", "ignoreTrackerPermissionsAlert", { + scope: "world", + type: Boolean, + default: false, + config: true + }); + game.settings.register("FVTT-Dishonored", "chaos", { scope: "world", type: Number, @@ -255,22 +271,97 @@ Hooks.once("init", function() { config: false }); + game.settings.register("FVTT-Dishonored", "currentMigrationVersion", { + scope: "world", + type: String, + default: 0, + config: false + }); + Hooks.on("ready", function() { - let i = USER_ROLES[game.settings.get("FVTT-Dishonored", "momentumPermissionLevel")]; + var currentMigVer = game.settings.get("FVTT-Dishonored", "currentMigrationVersion") == 0 ? "0.4.1": game.settings.get("FVTT-Dishonored", "currentMigrationVersion"); + if (isNewerVersion(game.system.data.version, currentMigVer ?? "0.4.1")) { + ui.notifications.notify("Current Migration Version does not match Current Version, running Migration Script."); + console.log("Current Migration Version does not match Current Version, running Migration Script."); + game.dishonored.migration(currentMigVer); + } + let i; + let error; + if (isNewerVersion(versionInfo,"0.8.-1")) { + i = foundry.CONST.USER_ROLES[game.settings.get("FVTT-Dishonored", "momentumPermissionLevel")]; + } + else { + i = USER_ROLES[game.settings.get("FVTT-Dishonored", "momentumPermissionLevel")]; + } for (i; i <= 4; i++) { - if (!game.permissions.SETTINGS_MODIFY.includes(i)) var error = true; + if (!game.permissions.SETTINGS_MODIFY.includes(i)) { + error = "momentum"; + } + } + if (isNewerVersion(versionInfo,"0.8.-1")) { + i = foundry.CONST.USER_ROLES[game.settings.get("FVTT-Dishonored", "chaosPermissionLevel")]; + } + else { + i = USER_ROLES[game.settings.get("FVTT-Dishonored", "chaosPermissionLevel")]; + } + for (i; i <= 4; i++) { + if (!game.permissions.SETTINGS_MODIFY.includes(i)) { + error = "chaos"; + } } if (error) { - console.error(game.i18n.localize('dishonored.notifications.momentumTrackerPermissions')); - ui.notifications.error(game.i18n.localize('dishonored.notifications.momentumTrackerPermissions')); + let string = ""; + string += ""; + string += game.i18n.localize("dishonored.notifications."+error+".trackerPermissions1"); + string += ""; + string += game.i18n.localize("PERMISSION.Title"); + string += ""; + string += game.i18n.localize("dishonored.notifications.trackerPermissions2"); + string += error == "momentum" ? game.settings.get("FVTT-Dishonored", "momentumPermissionLevel") : game.settings.get("FVTT-Dishonored", "chaosPermissionLevel"); + string += game.i18n.localize("dishonored.notifications."+error+".trackerPermissions3"); + string += ""+game.i18n.localize("SETTINGS.TabSystem")+""; + string += game.i18n.localize("dishonored.notifications.trackerPermissions4"); + let tmp = document.createElement("DIV"); + tmp.innerHTML = string; + console.error(tmp.textContent); + if (game.settings.get("FVTT-Dishonored", "ignoreTrackerPermissionsAlert") == false && game.user.isGM ) { + string +=" "; + string += game.i18n.localize("dishonored.notifications.trackerPermissionsClickHere"); + string += ""; + ui.notifications.error(string,{"permanent":true}); + } } - let t = new DishonoredTracker() - renderTemplate("systems/FVTT-Dishonored/templates/apps/tracker.html").then(html => { + let t = new DishonoredTracker(); + renderTemplate("systems/FVTT-Dishonored/templates/apps/tracker.html").then(function() { t.render(true); }); - let l = new DishonoredLogo() - renderTemplate("systems/FVTT-Dishonored/templates/apps/logo.html").then(html => { + let l = new DishonoredLogo(); + renderTemplate("systems/FVTT-Dishonored/templates/apps/logo.html").then(function() { l.render(true); }); }); -}); \ No newline at end of file + + game.dishonored.migration = function(currentMigVer) { + var recheck = false; + switch (currentMigVer) { + case "0.4.1": + ui.notifications.notify("Migrating from 0.4.1 to 0.5.0"); + console.log("Migrating from 0.4.1 to 0.5.0"); + game.actors.forEach(function(actor) { + if (actor.data.type == "character") { + if (actor.data.data.truth1) actor.createOwnedItem({name:actor.data.data.truth1, type: "truth", img:"systems/FVTT-Dishonored/icons/dishonoredlogo.webp"}); + if (actor.data.data.truth2) actor.createOwnedItem({name:actor.data.data.truth2, type: "truth", img:"systems/FVTT-Dishonored/icons/dishonoredlogo.webp"}); + } + }); + game.settings.set("FVTT-Dishonored", "currentMigrationVersion", "0.5.0"); + currentMigVer = "0.5.0"; + recheck = true; + break; + default: + recheck = false; + break; + } + if (recheck == true) {game.dishonored.migration(currentMigVer);} + }; +}); + diff --git a/module/items/armor-sheet.js b/module/items/armor-sheet.js index 2ca170d..d19c515 100644 --- a/module/items/armor-sheet.js +++ b/module/items/armor-sheet.js @@ -16,17 +16,17 @@ export class DishonoredArmorSheet extends ItemSheet { /** @override */ get template() { if ( !game.user.isGM && this.item.limited) { - ui.notifications.warn(game.i18n.localize('dishonored.notifications.lackPermission')); + ui.notifications.warn(game.i18n.localize("dishonored.notifications.lackPermission")); return; } - return `systems/FVTT-Dishonored/templates/items/armor-sheet.html`; - } + return "systems/FVTT-Dishonored/templates/items/armor-sheet.html"; + } /* -------------------------------------------- */ /** @override */ getData() { - const data = super.getData(); + const data = this.object.data; data.dtypes = ["String", "Number", "Boolean"]; return data; diff --git a/module/items/bonecharm-sheet.js b/module/items/bonecharm-sheet.js index 3687a53..93f8aa6 100644 --- a/module/items/bonecharm-sheet.js +++ b/module/items/bonecharm-sheet.js @@ -16,17 +16,17 @@ export class DishonoredBonecharmSheet extends ItemSheet { /** @override */ get template() { if ( !game.user.isGM && this.item.limited) { - ui.notifications.warn(game.i18n.localize('dishonored.notifications.lackPermission')); + ui.notifications.warn(game.i18n.localize("dishonored.notifications.lackPermission")); return; } - return `systems/FVTT-Dishonored/templates/items/bonecharm-sheet.html`; - } + return "systems/FVTT-Dishonored/templates/items/bonecharm-sheet.html"; + } /* -------------------------------------------- */ /** @override */ getData() { - const data = super.getData(); + const data = this.object.data; data.dtypes = ["String", "Number", "Boolean"]; return data; diff --git a/module/items/contact-sheet.js b/module/items/contact-sheet.js index 6df1fdd..50243ea 100644 --- a/module/items/contact-sheet.js +++ b/module/items/contact-sheet.js @@ -16,17 +16,17 @@ export class DishonoredContactSheet extends ItemSheet { /** @override */ get template() { if ( !game.user.isGM && this.item.limited) { - ui.notifications.warn(game.i18n.localize('dishonored.notifications.lackPermission')); + ui.notifications.warn(game.i18n.localize("dishonored.notifications.lackPermission")); return; } - return `systems/FVTT-Dishonored/templates/items/contact-sheet.html`; - } + return "systems/FVTT-Dishonored/templates/items/contact-sheet.html"; + } /* -------------------------------------------- */ /** @override */ getData() { - const data = super.getData(); + const data = this.object.data; data.dtypes = ["String", "Number", "Boolean"]; return data; @@ -51,30 +51,30 @@ export class DishonoredContactSheet extends ItemSheet { // If the sheet is not editable, hide the Send2Actor button (as the player shouldn't be able to edit this!). Also bump up the size of the Description editor. if (!this.options.editable) { - html.find('.send2actor')[0].style.display = 'none'; - html.find('.description')[0].style.height = 'calc(100% - 50px)'; + html.find(".send2actor")[0].style.display = "none"; + html.find(".description")[0].style.height = "calc(100% - 50px)"; return; } // Check if the user has the role set in the system settings. If not hide the button from the user. if (!game.user.hasRole(game.settings.get("FVTT-Dishonored", "send2ActorPermissionLevel"))) { - html.find('.send2actor')[0].style.display = 'none'; + html.find(".send2actor")[0].style.display = "none"; } else { - html.find('.send2actor').click(ev => { + html.find(".send2actor").click(ev => { // Grab the value of the name field, the editor content and the img src and send this to the send2Actor method. - var name = html.find('#name')[0].value; - var description = html.find('.editor-content')[0].innerHTML; - var img = html.find('.img')[0].getAttribute("src"); - var localisedText = game.i18n.localize('dishonored.notifications.s2A'); - this.send2Actor(name, description, img).then(created => ui.notifications.info(localisedText.replace('|#|', name))); + let name = html.find("#name")[0].value; + let description = html.find(".editor-content")[0].innerHTML; + let img = html.find(".img")[0].getAttribute("src"); + let localisedText = game.i18n.localize("dishonored.notifications.s2A"); + this.send2Actor(name, description, img).then(ui.notifications.info(localisedText.replace("|#|", name))); }); } } // Create an actor with the name, img and notes set from the contact - the actor is hardcoded as NPC here. async send2Actor(name, description, img) { - let actor = await Actor.create({ + await Actor.create({ name: name, type: "npc", img: img, @@ -85,6 +85,6 @@ export class DishonoredContactSheet extends ItemSheet { token: {}, items: [], flags: {} - }); + }); } } \ No newline at end of file diff --git a/module/items/focus-sheet.js b/module/items/focus-sheet.js index 9e8f6cd..e100463 100644 --- a/module/items/focus-sheet.js +++ b/module/items/focus-sheet.js @@ -16,17 +16,17 @@ export class DishonoredFocusSheet extends ItemSheet { /** @override */ get template() { if ( !game.user.isGM && this.item.limited) { - ui.notifications.warn(game.i18n.localize('dishonored.notifications.lackPermission')); + ui.notifications.warn(game.i18n.localize("dishonored.notifications.lackPermission")); return; } - return `systems/FVTT-Dishonored/templates/items/focus-sheet.html`; - } + return "systems/FVTT-Dishonored/templates/items/focus-sheet.html"; + } /* -------------------------------------------- */ /** @override */ getData() { - const data = super.getData(); + const data = this.object.data; data.dtypes = ["String", "Number", "Boolean"]; //Checks if the rating of the focus is above 5 or 2. If it exceeds these bounds it sets it to the closest limit. (i.e. 1 is set to 2) diff --git a/module/items/item-sheet.js b/module/items/item-sheet.js index 942023a..d3fb0bc 100644 --- a/module/items/item-sheet.js +++ b/module/items/item-sheet.js @@ -16,17 +16,17 @@ export class DishonoredItemSheet extends ItemSheet { /** @override */ get template() { if ( !game.user.isGM && this.item.limited) { - ui.notifications.warn(game.i18n.localize('dishonored.notifications.lackPermission')); + ui.notifications.warn(game.i18n.localize("dishonored.notifications.lackPermission")); return; } - return `systems/FVTT-Dishonored/templates/items/item-sheet.html`; - } + return "systems/FVTT-Dishonored/templates/items/item-sheet.html"; + } /* -------------------------------------------- */ /** @override */ getData() { - const data = super.getData(); + const data = this.object.data; data.dtypes = ["String", "Number", "Boolean"]; return data; diff --git a/module/items/item.js b/module/items/item.js index bd903cb..03b0b36 100644 --- a/module/items/item.js +++ b/module/items/item.js @@ -1,6 +1,7 @@ export class DishonoredItem extends Item { - prepareData() { - this.data.img = '/systems/FVTT-Dishonored/icons/dishonoredlogo.webp'; - super.prepareData(); - } + prepareData() { + if (this.data.img == "icons/svg/item-bag.svg") this.data.img = "/systems/FVTT-Dishonored/icons/dishonoredlogo.webp"; + if (this.data.img == "icons/svg/mystery-man.svg") this.data.img = "/systems/FVTT-Dishonored/icons/dishonoredlogo.webp"; + return this.data; + } } \ No newline at end of file diff --git a/module/items/power-sheet.js b/module/items/power-sheet.js index fd8d69a..e2d1759 100644 --- a/module/items/power-sheet.js +++ b/module/items/power-sheet.js @@ -16,17 +16,17 @@ export class DishonoredPowerSheet extends ItemSheet { /** @override */ get template() { if ( !game.user.isGM && this.item.limited) { - ui.notifications.warn(game.i18n.localize('dishonored.notifications.lackPermission')); + ui.notifications.warn(game.i18n.localize("dishonored.notifications.lackPermission")); return; } - return `systems/FVTT-Dishonored/templates/items/power-sheet.html`; - } + return "systems/FVTT-Dishonored/templates/items/power-sheet.html"; + } /* -------------------------------------------- */ /** @override */ getData() { - const data = super.getData(); + const data = this.object.data; data.dtypes = ["String", "Number", "Boolean"]; return data; diff --git a/module/items/talent-sheet.js b/module/items/talent-sheet.js index 6fbf40b..1e4d7df 100644 --- a/module/items/talent-sheet.js +++ b/module/items/talent-sheet.js @@ -16,17 +16,17 @@ export class DishonoredTalentSheet extends ItemSheet { /** @override */ get template() { if ( !game.user.isGM && this.item.limited) { - ui.notifications.warn(game.i18n.localize('dishonored.notifications.lackPermission')); + ui.notifications.warn(game.i18n.localize("dishonored.notifications.lackPermission")); return; } - return `systems/FVTT-Dishonored/templates/items/talent-sheet.html`; - } + return "systems/FVTT-Dishonored/templates/items/talent-sheet.html"; + } /* -------------------------------------------- */ /** @override */ getData() { - const data = super.getData(); + const data = this.object.data; data.dtypes = ["String", "Number", "Boolean"]; return data; diff --git a/module/items/truth-sheet.js b/module/items/truth-sheet.js new file mode 100644 index 0000000..5381e29 --- /dev/null +++ b/module/items/truth-sheet.js @@ -0,0 +1,56 @@ +export class DishonoredTruthSheet extends ItemSheet { + + /** @override */ + static get defaultOptions() { + return mergeObject(super.defaultOptions, { + classes: ["dishonored", "sheet", "item", "truth"], + width: 500, + height: 100, + tabs: [{ navSelector: ".sheet-tabs", contentSelector: ".sheet-body", initial: "description" }] + }); + } + + /* -------------------------------------------- */ + + // If the player is not a GM and has limited permissions - send them to the limited sheet, otherwise, continue as usual. + /** @override */ + get template() { + if ( !game.user.isGM && this.item.limited) { + ui.notifications.warn(game.i18n.localize("dishonored.notifications.lackPermission")); + return; + } + return "systems/FVTT-Dishonored/templates/items/truth-sheet.html"; + } + + /* -------------------------------------------- */ + + /** @override */ + getData() { + const data = this.object.data; + data.dtypes = ["String", "Number", "Boolean"]; + + return data; + } + + /* -------------------------------------------- */ + + /** @override */ + setPosition(options = {}) { + const position = super.setPosition(options); + const sheetBody = this.element.find(".sheet-body"); + const bodyHeight = position.height - 192; + sheetBody.css("height", bodyHeight); + return position; + } + + /* -------------------------------------------- */ + + /** @override */ + activateListeners(html) { + super.activateListeners(html); + + // Everything below here is only needed if the sheet is editable + if (!this.options.editable) return; + + } +} \ No newline at end of file diff --git a/module/items/weapon-sheet.js b/module/items/weapon-sheet.js index d05352f..eb0cef3 100644 --- a/module/items/weapon-sheet.js +++ b/module/items/weapon-sheet.js @@ -16,17 +16,17 @@ export class DishonoredWeaponSheet extends ItemSheet { /** @override */ get template() { if ( !game.user.isGM && this.item.limited) { - ui.notifications.warn(game.i18n.localize('dishonored.notifications.lackPermission')); + ui.notifications.warn(game.i18n.localize("dishonored.notifications.lackPermission")); return; } - return `systems/FVTT-Dishonored/templates/items/weapon-sheet.html`; - } + return "systems/FVTT-Dishonored/templates/items/weapon-sheet.html"; + } /* -------------------------------------------- */ /** @override */ getData() { - const data = super.getData(); + const data = this.object.data; data.dtypes = ["String", "Number", "Boolean"]; return data; diff --git a/module/macro.js b/module/macro.js index 7fd4a41..059b3a4 100644 --- a/module/macro.js +++ b/module/macro.js @@ -1,31 +1,31 @@ import { DishonoredRoll -} from './roll.js' +} from "./roll.js"; export function skillTest(actor, skillName, styleName, focusRating, numberOfDice) { let fail = false; if (actor === undefined) { - ui.notifications.warn(game.i18n.localize('dishonored.notifications.macroActor')); + ui.notifications.warn(game.i18n.localize("dishonored.notifications.macroActor")); fail = true; } if (skillName === undefined) { - ui.notifications.warn(game.i18n.localize('dishonored.notifications.macroSkill')); + ui.notifications.warn(game.i18n.localize("dishonored.notifications.macroSkill")); fail = true; } if (styleName === undefined) { - ui.notifications.warn(game.i18n.localize('dishonored.notifications.macroStyle')); + ui.notifications.warn(game.i18n.localize("dishonored.notifications.macroStyle")); fail = true; } if (focusRating < 1) { - ui.notifications.warn(game.i18n.localize('dishonored.notifications.macroFocus')); + ui.notifications.warn(game.i18n.localize("dishonored.notifications.macroFocus")); fail = true; } if (numberOfDice > 5) { - ui.notifications.warn(game.i18n.localize('dishonored.notifications.macroDiceGreater')); + ui.notifications.warn(game.i18n.localize("dishonored.notifications.macroDiceGreater")); fail = true; } else if (numberOfDice < 1) { - ui.notifications.warn(game.i18n.localize('dishonored.notifications.macroDiceLess')); + ui.notifications.warn(game.i18n.localize("dishonored.notifications.macroDiceLess")); fail = true; } if (fail === true) { diff --git a/module/roll.js b/module/roll.js index 7945db7..3929bea 100644 --- a/module/roll.js +++ b/module/roll.js @@ -2,74 +2,82 @@ export class DishonoredRoll { async performSkillTest(dicePool, checkTarget, focusTarget, selectedSkill, selectedStyle, speaker) { // Define some variables that we will be using later. + let r; let i; + let successText; + let complicationText; let result = 0; let diceString = ""; let success = 0; let complication = 0; - // Check if we are using a Foundry version below 0.7.0, if so use the old code. - if (!isNewerVersion(game.world.coreVersion,'0.7.0')) { + let versionInfo; + if (game.world.data) versionInfo = game.world.data.coreVersion; + else game.world.coreVersion; + // Check if we are using a Foundry version above 0.7.0, use new code. + if (isNewerVersion(versionInfo,"0.8.-1")) { // Define r as our dice roll we want to perform (1d20, 2d20, 3d20, 4d20 or 5d20). We will then roll it. - var r = new Roll(dicePool+"d20") - r.roll(); - // Now for each dice in the dice pool we want to check what the individual result was. - for (i = 0; i < dicePool; i++) { - result = r.dice[0].rolls[i].roll; - // If the result is less than or equal to the focus, that counts as 2 successes and we want to show the dice as green. - if (result <= focusTarget) { - diceString += '
` + dicePool + `d20 | -` + game.i18n.format("dishonored.roll.html.target") + `:` + checkTarget + ` | -` + game.i18n.format("dishonored.roll.html.focus") + `:` + focusTarget + ` | +` + game.i18n.format("dishonored.roll.html.target") + ":" + checkTarget + ` | +` + game.i18n.format("dishonored.roll.html.focus") + ":" + focusTarget + ` |