diff --git a/lang/en.json b/lang/en.json index f6f43b9..8a2f345 100644 --- a/lang/en.json +++ b/lang/en.json @@ -207,7 +207,7 @@ "DG.ModifySkillRollDialogue.Title": "Modify Roll", "DG.ModifySkillRollDialogue.Test": "Test:", "DG.ModifySkillRollDialogue.OriginalTarget": "Original Target:", - "DG.ModifySkillRollDialogue.TargetModifier": "Modify Target:", + "DG.ModifySkillRollDialogue.TargetModifier": "Modify Target (+/-):", "DG.ModifySkillRollDialogue.ModifierTooltip": "Give a positive or negative modifier here to add/subtract from the target for the skill check.", "DG.ModifyDamageRollDialogue.Weapon": "Weapon:", diff --git a/lang/ja.json b/lang/ja.json index 638e25f..46a4e59 100644 --- a/lang/ja.json +++ b/lang/ja.json @@ -207,7 +207,7 @@ "DG.ModifySkillRollDialogue.Title": "ロールの変更", "DG.ModifySkillRollDialogue.Test": "テスト:", "DG.ModifySkillRollDialogue.OriginalTarget": "元のターゲット:", - "DG.ModifySkillRollDialogue.TargetModifier": "変換:", + "DG.ModifySkillRollDialogue.TargetModifier": "変換(+/-):", "DG.ModifySkillRollDialogue.ModifierTooltip": "スキルチェックのターゲットに加算/減算します。", "DG.ModifyDamageRollDialogue.Weapon": "武器:", diff --git a/module/actor/actor-sheet.js b/module/actor/actor-sheet.js index 20cf667..c5c6ec1 100644 --- a/module/actor/actor-sheet.js +++ b/module/actor/actor-sheet.js @@ -322,13 +322,19 @@ export class DeltaGreenActorSheet extends ActorSheet { let requestedModifyRoll = (event && event.shiftKey || event.which === 3); //(event && (event.shiftKey || event.altKey || event.ctrlKey || event.metaKey)); // check the 'data-target="something" property to determine how to grab the target for the roll + let inhuman_flag = false; // inhuman_flag to be used for stats above 20 if(rollType === "skill" || rollType === "typeskill"){ targetVal = dataset.target; label = game.i18n.localize(label).toUpperCase(); } else if(dataset.target === "statistic.x5"){ let stat = this.actor.data.data.statistics[key]; - targetVal = stat.x5; + if (stat.value>=20){ + targetVal = stat.value; + inhuman_flag = true; // you use the value instead of the x5 but you set the inhuman_flag to true + }else{ + targetVal = stat.x5; + } label = game.i18n.localize("DG.Attributes." + key).toUpperCase(); } else if(rollType === "sanity"){ @@ -356,7 +362,7 @@ export class DeltaGreenActorSheet extends ActorSheet { } else{ if(requestedModifyRoll){ - showModifyPercentileTestDialogue(this.actor, label, targetVal, isLethalityRoll); + showModifyPercentileTestDialogue(this.actor, label, targetVal, isLethalityRoll,inhuman_flag); } else{ if(isLethalityRoll) @@ -364,7 +370,7 @@ export class DeltaGreenActorSheet extends ActorSheet { sendLethalityTestToChat(this.actor, label, targetVal); } else{ - sendPercentileTestToChat(this.actor, label, targetVal); + sendPercentileTestToChat(this.actor, label, targetVal,inhuman_flag); } } } diff --git a/module/deltagreen.js b/module/deltagreen.js index 9ee2a76..0b58375 100644 --- a/module/deltagreen.js +++ b/module/deltagreen.js @@ -13,6 +13,7 @@ Hooks.once('init', async function() { DeltaGreenActor, DeltaGreenItem, rollItemMacro, + rollItemSkillCheckMacro, rollSkillMacro }; @@ -155,6 +156,9 @@ function rollItemMacro(itemName) { let actor; if (speaker.token) actor = game.actors.tokens[speaker.token]; if (!actor) actor = game.actors.get(speaker.actor); + + if(!actor) return ui.notifications.warn('Must have an Actor selected first.'); + const item = actor ? actor.items.find(i => i.name === itemName) : null; if (!item) return ui.notifications.warn(`Your controlled Actor does not have an item named ${itemName}`); @@ -162,6 +166,31 @@ function rollItemMacro(itemName) { return item.roll(); } +function rollItemSkillCheckMacro(itemName) { + const speaker = ChatMessage.getSpeaker(); + let actor; + if (speaker.token) actor = game.actors.tokens[speaker.token]; + if (!actor) actor = game.actors.get(speaker.actor); + + if(!actor) return ui.notifications.warn('Must have an Actor selected first.'); + + const item = actor ? actor.items.find(i => i.name === itemName) : null; + if (!item) return ui.notifications.warn(`Your controlled Actor does not have an item named ${itemName}`); + + let skillName = item.data.data.skill.toString(); + + let skill = actor.data.data.skills[skillName]; + let translatedSkillLabel = ""; + + try{ + translatedSkillLabel = game.i18n.localize("DG.Skills." + skillName) + } + catch{ + translatedSkillLabel = skillName; + } + + sendPercentileTestToChat(actor, translatedSkillLabel, skill.proficiency); +} function rollSkillMacro(skillName) { const speaker = ChatMessage.getSpeaker(); @@ -175,5 +204,14 @@ function rollSkillMacro(skillName) { if(!skill) return ui.notifications.warn('Bad skill name passed to macro.'); - sendPercentileTestToChat(actor, skill.label, skill.proficiency); + let translatedSkillLabel = ""; + + try{ + translatedSkillLabel = game.i18n.localize("DG.Skills." + skillName) + } + catch{ + translatedSkillLabel = skillName; + } + + sendPercentileTestToChat(actor, translatedSkillLabel, skill.proficiency); } \ No newline at end of file diff --git a/module/roll/roll.js b/module/roll/roll.js index 53a98af..39b58de 100644 --- a/module/roll/roll.js +++ b/module/roll/roll.js @@ -1,18 +1,31 @@ -export function sendPercentileTestToChat(actor, skill, target){ - let roll = new Roll('1D100', actor.data.data).roll(); - let total = roll.total; - let isCritical = false; - let isSuccess = false; - let html = ''; - let label = `${game.i18n.localize("DG.Roll.Rolling")} ${skill} ${game.i18n.localize("DG.Roll.Target")} ${target}`; - let resultString = ''; - let styleOverride = ''; +export function sendPercentileTestToChat(actor, skill, target, inhuman_flag=false){ // flag check if the stat is above 20 + let roll = new Roll('1D100', actor.data.data).roll(); + let total = roll.total; + let isCritical = false; + let isSuccess = false; + let html = ''; + let label = `${game.i18n.localize("DG.Roll.Rolling")} ${skill} ${game.i18n.localize("DG.Roll.Target")} ${target}`; + let resultString = ''; + let styleOverride = ''; - isCritical = skillCheckResultIsCritical(total); - - if(total <= target){ - isSuccess = true; - } + isCritical = skillCheckResultIsCritical(total); // up to this point everything works as intended + + if (inhuman_flag){ // pag 188 of the Handler guide: inhuman stats + //an entity with a stat at 20 or higher succeeds at any stat test except with a roll of 100, which fails + //and fumbles. It gets a critical success on any success with matching digits, and with any roll equal + //to or less than the stat’s value. + + if(total <= 99){ + isSuccess = true; + if(total <= target){ + isCritical = true; + } + } + }else{ // general case + if(total <= target){ + isSuccess = true; + } + } if(isCritical){ resultString = `${game.i18n.localize("DG.Roll.Critical")} `; @@ -167,6 +180,18 @@ export function sendLethalityTestToChat(actor, weaponName, target){ type: CHAT_MESSAGE_TYPES.ROLL, roll: roll, rollMode: game.settings.get("core", "rollMode") + }); + } + + export async function showModifyPercentileTestDialogue(actor, label, originalTarget, isLethalityTest,inhuman_flag=false){ + + let template = "systems/deltagreen/templates/dialog/modify-percentile-roll.html"; + let backingData = { + data:{ + label: label, + originalTarget: originalTarget, + targetModifier: 20 + }, }; // play the dice rolling sound, like a regular in-chat roll @@ -223,7 +248,17 @@ export async function showModifyPercentileTestDialogue(actor, label, originalTar if(targetModifier.trim() != "" && !isNaN(targetModifier)){ newTarget += parseInt(targetModifier); } - + let newTarget = parseInt(originalTarget); // this should be an int, but technically the incoming value is text, so parse it just to be safe + if(targetModifier.trim() != "" && !isNaN(targetModifier)){ + newTarget += parseInt(targetModifier); + } + + if(isLethalityTest){ + sendLethalityTestToChat(actor, label, newTarget); + } + else{ + sendPercentileTestToChat(actor, label, newTarget,inhuman_flag); //take care of inhuman stat, by default the value is false + } if(isLethalityTest){ sendLethalityTestToChat(actor, label, newTarget); }