From 57d58e28423b6781c9b25b87f904781f267e4f6d Mon Sep 17 00:00:00 2001 From: The Last Scrub Date: Mon, 15 Feb 2021 21:12:10 -0800 Subject: [PATCH 01/10] fix lack of translation breaking adding new skills --- module/actor/actor-sheet.js | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/module/actor/actor-sheet.js b/module/actor/actor-sheet.js index b4ce9c5..f56b3e3 100644 --- a/module/actor/actor-sheet.js +++ b/module/actor/actor-sheet.js @@ -203,29 +203,29 @@ export class DeltaGreenActorSheet extends ActorSheet { let htmlContent = ""; htmlContent += `
`; - htmlContent += ` `; + htmlContent += ` `; htmlContent += ` `; htmlContent += `
`; htmlContent += `
`; - htmlContent += ` `; + htmlContent += ` `; htmlContent += ` `; htmlContent += `
`; new Dialog({ content: htmlContent, - title: game.i18n.translations.DG.Skills.AddTypedOrCustomSkill, + title: game.i18n.translations.DG?.Skills?.AddTypedOrCustomSkill ?? "Add Typed or Custom Skill", buttons: { add:{ - label: game.i18n.translations.DG.Skills.AddSkill, + label: game.i18n.translations.DG?.Skills?.AddSkill ?? "Add Skill", callback: btn =>{ let newTypeSkillLabel = btn.find("[name='new-type-skill-label']").val(); let newTypeSkillGroup = btn.find("[name='new-type-skill-group']").val(); From 8c500a14a6b3d2ce2c8362b5ea1c005113ca1d3a Mon Sep 17 00:00:00 2001 From: TheLastScrub <67403321+TheLastScrub@users.noreply.github.com> Date: Fri, 12 Mar 2021 21:50:41 -0800 Subject: [PATCH 02/10] added spanish language pack --- lang/es.json | 216 +++++++++++++++++++++++++++++++++++++++++++++++++++ system.json | 5 ++ 2 files changed, 221 insertions(+) create mode 100644 lang/es.json diff --git a/lang/es.json b/lang/es.json new file mode 100644 index 0000000..ab6ba54 --- /dev/null +++ b/lang/es.json @@ -0,0 +1,216 @@ +{ + "DG.SystemName": "Delta Green", + "DG.AgentNameFieldTooltip": "APELLIDO, NOMBRE (Y ALIAS SI CORRESPONDE)", + "DG.RollLuck": "Tira Suerte", + "DG.Luck": "Suerte", + + "DG.FallbackText.ProfessionAndOrRank": "PROFESION (RANGO SI CORRESPONDE)", + + "DG.Skills.accounting": "Contabilidad", + "DG.Skills.alertness": "Alerta", + "DG.Skills.anthropology": "Antropología", + "DG.Skills.archeology": "Arqueología", + "DG.Skills.artillery": "Artillería", + "DG.Skills.athletics": "Atletismo", + "DG.Skills.bureaucracy": "Burocracia", + "DG.Skills.computer_science": "Informatica", + "DG.Skills.criminology": "Criminología", + "DG.Skills.demolitions": "Explosivos", + "DG.Skills.disguise": "Disfrazarse", + "DG.Skills.dodge": "Esquivar", + "DG.Skills.drive": "Conducir", + "DG.Skills.firearms": "Armas de Fuego", + "DG.Skills.first_aid": "Primeros Auxilios", + "DG.Skills.forensics": "Medicina Forense", + "DG.Skills.heavy_machiner": "Maquinaria Pesada", + "DG.Skills.heavy_weapons": "Armas Pesadas", + "DG.Skills.history": "Historia", + "DG.Skills.humint": "HUMINT", + "DG.Skills.law": "Derecho", + "DG.Skills.medicine": "Medicina", + "DG.Skills.melee_weapons": "Armas Cuerpo a Cuerpo", + "DG.Skills.navigate": "Orientarse", + "DG.Skills.occult": "Ocultismo", + "DG.Skills.persuade": "Persuadir", + "DG.Skills.pharmacy": "Farmacología", + "DG.Skills.psychotherapy": "Psicoterapia", + "DG.Skills.ride": "Equitación", + "DG.Skills.search": "Buscar", + "DG.Skills.sigint": "SIGINT", + "DG.Skills.stealth": "Sigilo", + "DG.Skills.surgery": "Cirugia", + "DG.Skills.survival": "Supervivemcia", + "DG.Skills.swim": "Nadar", + "DG.Skills.unarmed_combat": "Combate sin Armas", + "DG.Skills.unnatural": "Antinatural", + + "DG.Skills.AddTypedOrCustomSkill": "Añadir Tipo o Habilidad Personalizada", + "DG.Skills.AddSkill": "Añadir Habilidad", + "DG.Skills.SkillGroup": "Habilidad Grupal", + "DG.Skills.SkillName": "Nombre de la Habilidad", + + "DG.TypeSkills.Art": "Arte", + "DG.TypeSkills.Craft": "Fabricar", + "DG.TypeSkills.ForeignLanguage": "Lengua Extranjera", + "DG.TypeSkills.MilitaryScience": "Ciencia Militar", + "DG.TypeSkills.Pilot": "Pilotar", + "DG.TypeSkills.Science": "Ciencia", + "DG.TypeSkills.Other": "Otra", + + "DG.Attributes.HP": "PV", + "DG.Attributes.WP": "PV", + "DG.Attributes.SAN": "COR", + "DG.Attributes.str": "FUE", + "DG.Attributes.con": "CON", + "DG.Attributes.dex": "DES", + "DG.Attributes.int": "INT", + "DG.Attributes.pow": "POD", + "DG.Attributes.cha": "CAR", + + "DG.Navigation.Skills": "Habilidades", + "DG.Navigation.Physical": "Físico", + "DG.Navigation.Mental": "Mental", + "DG.Navigation.Gear": "Equipo", + "DG.Navigation.CV": "C.V.", + "DG.Navigation.Contacts": "Contactos", + + "DG.About.OnlineHelp": "Documentación del sistema abierto en (EN LÍNEA)", + "DG.About.OnlineHelpTooltip": "Inicie el navegador con la ayuda en línea de GitHub.", + "DG.About.OnlineBugTracker": "Preguntas, informes de errores o solicitudes de funciones (EN LÍNEA)", + "DG.About.OnlineBugTrackerTooltip": "Inicie el navegador con el rastreador de problemas de GitHub. ", + + "DG.Roll.Rolling": "Tirando", + "DG.Roll.Target": "Objetivo: ", + "DG.Roll.Success": "Exito", + "DG.Roll.Failure": "Fallo", + "DG.Roll.Critical": "Critico", + "DG.Roll.Lethality": "Letalidad", + "DG.Roll.Lethal": "Letal", + "DG.Roll.For": "Para", + "DG.Roll.Damage": "Daño", + "DG.Roll.RollingDamageFor": "Tirando DAÑO para", + "DG.Roll.Or": "O", + "DG.Roll.Roll": "Tirar", + + "DG.Physical.Wounds": "Heridas", + "DG.Physical.FirstAidLabel": "Los Primeros Auxilios Ya Han Sido Aplicados: ", + + "DG.Generic.AddButtonLabel": "Añadir", + + "DG.Mental.BreakingPoint": "Punto Ruptura: ", + "DG.Mental.Reset": "Borrar", + "DG.Mental.SanityLossIncidentsLabel": "Incidentes o perdida de COR sin Locura", + "DG.Mental.Violence": "Violencia", + "DG.Mental.Helplessness": "Impotencia", + "DG.Mental.AdaptedToViolence": "Adaptado a la Violencia", + "DG.Mental.AdaptedToHelplessness": "Adaptado a la Impotencia", + "DG.Mental.Motivations": "Motivaciones", + "DG.Mental.Disorders": "Desordenes", + + "DG.Gear.Weapons": "ARMAS", + "DG.Gear.Armor": "ARMADURA", + "DG.Gear.OtherGear": "OTRO EQUIPO", + "DG.Gear.Name": "Nombre", + "DG.Gear.DamageOrLethality": "Daño/Letalidad", + "DG.Gear.ArmorPiercing": "Perforación de Armadura", + "DG.Gear.ArmorRating": "Clasificación de Armadura", + "DG.Gear.Equipped": "Equipado", + + "DG.CV.Sex": "Sexo", + "DG.CV.SexPlaceholder": "Sexo", + "DG.CV.AgeAndDoB": "Edad y F.D.N.", + "DG.CV.AgeAndDoBPlaceholder": "Edad & Fecha de Nacimiento", + "DG.CV.Employer": "Empleador", + "DG.CV.EmployerPlaceholder": "Empleador o Historial laboral", + "DG.CV.Nationality": "Nacionalidad", + "DG.CV.NationalityPlaceholder": "Nacionalidad", + "DG.CV.Education": "Educación", + "DG.CV.EducationPlaceholder": "Educación o Entrenamiento", + "DG.CV.PhysicalDescriptionLabel": "Descripción Física/Notas", + + "DG.Bonds.Bond": "Vículo", + "DG.Bonds.Name": "Nombre", + "DG.Bonds.Score": "Puntuación", + "DG.Bonds.NewBond": "Nuevo Vínculo", + + "DG.ItemTypes.weapon": "Arma", + "DG.ItemTypes.armor": "Armadura", + "DG.ItemTypes.motivation": "Motivación", + "DG.ItemTypes.bond": "Vínculo", + "DG.ItemTypes.gear": "Equipo", + "DG.ItemTypes.NewPrefix": "Nuevo ", + + "DG.Tooltip.HP": "Puntos de Vida, un personaje cae inconsciente a los 2 PV, y muere con 0 PV.", + "DG.Tooltip.MaximumHP": "La salud máxima es el promedio de FUE + CON, redondeado hacia arriba.", + "DG.Tooltip.WP": "Los Puntos de Voluntad son el combustible mental. Los agentes requieren puntos de voluntad para seguir adelante a pesar del agotamiento o situaciones mentalmente graves. Consulte la página 47 del Manual del Agente para obtener más detalles.", + "DG.Tooltip.MaximumWP": "Los Ptos Voluntad máximos son iguales al POD.", + "DG.Tooltip.SanityLabel": "Click para hacer una tirada de Cordura...", + "DG.Tooltip.CurrentSanityPartOne": "Cordura actual, punto de ruptura actual es ", + "DG.Tooltip.CurrentSanityPartTwo": ", haga clic en la etiqueta COR anterior para realizar una tirada de de cordura.", + "DG.Tooltip.MaximumSanity": "La cordura máxima es igual a 99 - la habilidad Antinatural.", + "DG.Tooltip.SkillLabel": "Click para hacer una tirada de habilidad.", + "DG.Tooltip.CannotRollSkillLabel": "No se puede usar una habilidad al 0%. Consulte la página 28 del Manual del Agente.", + "DG.Tooltip.SkillFailCheckbox": "Después de fallar una prueba sobre esta habilidad (si el dominio es de al menos 1%), marque esta casilla. Al final de la sesión, agregue puntos porcentuales 1D4-1 a la habilidad y desmarque la casilla. No se aplica a la habilidad Antinatural. Consulte la página 29 del Manual del Agente.", + "DG.Tooltip.DistinguishingFeature": "Característica Distintiva (rellene si la puntuación es 12 o superior, u 8 o inferior).", + "DG.Tooltip.x5AttributeLabel": "Click para una tirada x5.", + "DG.Tooltip.FirstAidAttempted": "Una vez que un agente recibe primeros auxilios, no puede beneficiarse de él de nuevo hasta que reciba más daños de una fuente diferente.", + "DG.Tooltip.AdaptedToViolence": "Adaptarse a la violencia significa que la empatía de su agente sufre al ser testigo de tanta violencia. Pierde permanentemente 1D6 CAR y la misma cantidad de cada uno de sus vínculos.", + "DG.Tooltip.AdaptedToHelplessness": "Estar adaptado a la impotencia significa que el impulso personal de su Agente sufre cuando se aleja del mundo que lo rodea. Tan pronto como su Agente se adapte a la indefensión, perderá permanentemente 1D6 POD. ", + "DG.Tooltip.ToggleEquippedState": "Haga clic para alternar si este artículo está equipado o no. ", + + "DG.Gear.Expense.Incidental": "Incidental", + "DG.Gear.Expense.Standard": "Estándar", + "DG.Gear.Expense.Unusual": "Inusual", + "DG.Gear.Expense.Major": "Destacado", + "DG.Gear.Expense.Extreme": "Extremo", + + "DG.ItemWindow.Bonds.Description": "Descripción / Desarrollos ", + "DG.ItemWindow.Bonds.ScoreTooltip": "Una puntuación más alta representa una relación más fuerte entre el agente y el vínculo. ", + + "DG.ItemWindow.Motivations.Attributes": "Atributos", + "DG.ItemWindow.Motivations.Motivation": "Motivación", + "DG.ItemWindow.Motivations.Description": "Descripción / Notas", + "DG.ItemWindow.Motivations.Disorder": "Trastorno", + "DG.ItemWindow.Motivations.IsDisorder": "Es Trastorno", + "DG.ItemWindow.Motivations.MotivationNameTooltip": "Algo que impulsa al personaje. ", + "DG.ItemWindow.Motivations.DisorderNameTooltip": "Un trastorno reemplaza una motivación después de llegar al punto de ruptura.", + "DG.ItemWindow.Motivations.IsDisorderTooltip": "Marque esta opción si agrega un trastorno o si se ha perdido una motivación existente debido a la adquisición de un trastorno.", + "DG.ItemWindow.Motivations.DisorderHasBeenCured": "El trastorno ha sido \"curado \" ", + "DG.ItemWindow.Motivations.DisorderHasBeenCuredTooltip": "Un éxito crítico en una tirada de suerte terapéutica puede curar un trastorno. Sin embargo, puede regresar la próxima vez que se alcance un punto de ruptura. ", + + "DG.ItemWindow.Gear.Attributes": "Atributos", + "DG.ItemWindow.Gear.Description": "Descripción", + "DG.ItemWindow.Gear.NamePlaceholder": "Nombre", + "DG.ItemWindow.Gear.Expense": "Gasto", + "DG.ItemWindow.Gear.Equipped": "Equipado", + + "DG.ItemWindow.Armor.Description": "Descripción", + "DG.ItemWindow.Armor.NamePlaceholder": "Nombre", + "DG.ItemWindow.Armor.ArmorRating": "Tasa Armadura", + "DG.ItemWindow.Armor.Expense": "Gasto", + "DG.ItemWindow.Armor.Equipped": "Equipado", + + "DG.ItemWindow.Weapons.Description": "Descripción", + "DG.ItemWindow.Weapons.NamePlaceholder": "Nombre", + "DG.ItemWindow.Weapons.Skill": "Habilidad", + "DG.ItemWindow.Weapons.Expense": "Gasto", + "DG.ItemWindow.Weapons.Damage": "Daño", + "DG.ItemWindow.Weapons.Lethality": "Letalidad", + "DG.ItemWindow.Weapons.IsLethality": "Es Letal", + "DG.ItemWindow.Weapons.LethalityTooltip": "Un arma letal tiene la oportunidad de matar instantáneamente a un objetivo. Tira 1D100 en lugar de un dado de daño. Si no es letal, el daño se calcula en su lugar tirando 2d10, donde un '00' en el primer d10 es igual a 10.", + "DG.ItemWindow.Weapons.IsLethalityTooltip": "Marca si el arma tiene un % de letalidad asociada.", + "DG.ItemWindow.Weapons.ArmorPiercing": "Perforación de armaduras", + "DG.ItemWindow.Weapons.Ammo": "Munición (Cantidad/Tipo)", + "DG.ItemWindow.Weapons.Range": "Alcance", + "DG.ItemWindow.Weapons.KillRadius": "Radio de muerte", + + "DG.ModifySkillRollDialogue.Title": "Modificar Tirada", + "DG.ModifySkillRollDialogue.Test": "Test:", + "DG.ModifySkillRollDialogue.OriginalTarget": "Objetivo Original:", + "DG.ModifySkillRollDialogue.TargetModifier": "Modificar Objetivo:", + "DG.ModifySkillRollDialogue.ModifierTooltip": "Dar un modificador positivo o negativo aquí para sumar o restar al objetivo en la chequeo de habilidades.", + + "DG.ModifyDamageRollDialogue.Weapon": "Arma:", + "DG.ModifyDamageRollDialogue.OuterModifierTooltip": "Utilice este campo para modificar la fórmula, como duplicar el resultado.", + "DG.ModifyDamageRollDialogue.InnerModifierTooltip": "Utilice este campo para añadir un modificador como '+1' u otro término como '+1d4'." +} \ No newline at end of file diff --git a/system.json b/system.json index 8881bb3..af1e0c2 100644 --- a/system.json +++ b/system.json @@ -46,6 +46,11 @@ "lang": "ja", "name": "日本語", "path": "lang/ja.json" + }, + { + "lang": "es", + "name": "Español", + "path": "lang/es.json" } ], "gridDistance": 1, From 5c66a39cc1d7ecbac15abb0212de6549d885aa04 Mon Sep 17 00:00:00 2001 From: TheLastScrub <67403321+TheLastScrub@users.noreply.github.com> Date: Fri, 12 Mar 2021 23:15:51 -0800 Subject: [PATCH 03/10] added roll skill macro --- module/deltagreen.js | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/module/deltagreen.js b/module/deltagreen.js index aa8b92b..9ee2a76 100644 --- a/module/deltagreen.js +++ b/module/deltagreen.js @@ -3,6 +3,7 @@ import { DeltaGreenActor } from "./actor/actor.js"; import { DeltaGreenActorSheet } from "./actor/actor-sheet.js"; import { DeltaGreenItem } from "./item/item.js"; import { DeltaGreenItemSheet } from "./item/item-sheet.js"; +import { sendPercentileTestToChat, sendLethalityTestToChat, sendDamageRollToChat } from "./roll/roll.js"; import { preloadHandlebarsTemplates } from "./templates.js"; @@ -11,7 +12,8 @@ Hooks.once('init', async function() { game.deltagreen = { DeltaGreenActor, DeltaGreenItem, - rollItemMacro + rollItemMacro, + rollSkillMacro }; /** @@ -158,4 +160,20 @@ function rollItemMacro(itemName) { // Trigger the item roll return item.roll(); +} + + +function rollSkillMacro(skillName) { + 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.'); + + let skill = actor.data.data.skills[skillName]; + + if(!skill) return ui.notifications.warn('Bad skill name passed to macro.'); + + sendPercentileTestToChat(actor, skill.label, skill.proficiency); } \ No newline at end of file From 97e8d461de400b820d4dc7fa56b3d4b2e135efd9 Mon Sep 17 00:00:00 2001 From: TheLastScrub <67403321+TheLastScrub@users.noreply.github.com> Date: Fri, 12 Mar 2021 23:16:33 -0800 Subject: [PATCH 04/10] fixed (?) broken dragging item to macro bar --- module/actor/actor-sheet.js | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/module/actor/actor-sheet.js b/module/actor/actor-sheet.js index f56b3e3..b2bfbbe 100644 --- a/module/actor/actor-sheet.js +++ b/module/actor/actor-sheet.js @@ -161,7 +161,7 @@ export class DeltaGreenActorSheet extends ActorSheet { // Drag events for macros. if (this.actor.owner) { - let handler = ev => this._onDragItemStart(ev); + let handler = ev => this._onDragStart(ev); html.find('li.item').each((i, li) => { if (li.classList.contains("inventory-header")) return; li.setAttribute("draggable", true); @@ -399,4 +399,33 @@ export class DeltaGreenActorSheet extends ActorSheet { console.log(ex); } } + + _onDragStart(event) { + const li = event.currentTarget; + if ( event.target.classList.contains("entity-link") ) return; + + // Create drag data + const dragData = { + actorId: this.actor.id, + sceneId: this.actor.isToken ? canvas.scene?.id : null, + tokenId: this.actor.isToken ? this.actor.token.id : null + }; + + // Owned Items + if ( li.dataset.itemId ) { + const item = this.actor.items.get(li.dataset.itemId); + dragData.type = "Item"; + dragData.data = item.data; + } + + // Active Effect + if ( li.dataset.effectId ) { + const effect = this.actor.effects.get(li.dataset.effectId); + dragData.type = "ActiveEffect"; + dragData.data = effect.data; + } + + // Set data transfer + event.dataTransfer.setData("text/plain", JSON.stringify(dragData)); + } } From 2783e6420f7995165755f286610b3a6fb3c5c575 Mon Sep 17 00:00:00 2001 From: TheLastScrub <67403321+TheLastScrub@users.noreply.github.com> Date: Fri, 12 Mar 2021 23:23:56 -0800 Subject: [PATCH 05/10] fixed issue with localization on item skill checks --- templates/actor/actor-sheet.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/templates/actor/actor-sheet.html b/templates/actor/actor-sheet.html index 33f0102..faa99e5 100644 --- a/templates/actor/actor-sheet.html +++ b/templates/actor/actor-sheet.html @@ -262,8 +262,8 @@ data-roll="d100" data-rolltype="skill" data-target="{{getActorSkillProp ../data item.data.skill 'proficiency'}}" - data-label="{{getActorSkillProp ../data item.data.skill 'label'}}" - title="Click to roll {{getActorSkillProp ../data item.data.skill 'label'}}" + data-label="{{localize (concat 'DG.Skills.' item.data.skill)}}" + title="{{localize 'DG.Tooltip.SkillLabel'}} ({{localize (concat 'DG.Skills.' item.data.skill)}})" > {{item.name}} From e8d069d47b03e18c3debb3fd5457f97b2ffe3487 Mon Sep 17 00:00:00 2001 From: TheLastScrub <67403321+TheLastScrub@users.noreply.github.com> Date: Fri, 12 Mar 2021 23:37:19 -0800 Subject: [PATCH 06/10] error on localization of 'roll luck' chat card --- module/actor/actor-sheet.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/module/actor/actor-sheet.js b/module/actor/actor-sheet.js index b2bfbbe..20cf667 100644 --- a/module/actor/actor-sheet.js +++ b/module/actor/actor-sheet.js @@ -79,12 +79,14 @@ export class DeltaGreenActorSheet extends ActorSheet { // Can add extra buttons to form header here if necessary _getHeaderButtons(){ let buttons = super._getHeaderButtons(); - let label = ""; + let label = "Roll Luck"; + let label2 = "Luck"; try{ label = game.i18n.translations.DG.RollLuck; + label2 = game.i18n.translations.DG.Luck; } catch{ - label = "Roll Luck" + ui.notifications.warn('Missing translation key for either DG.RollLuck or DG.Luck key.') } buttons = [ @@ -92,7 +94,7 @@ export class DeltaGreenActorSheet extends ActorSheet { label: label, class: "test-extra-icon", icon: "fas fa-dice", - onclick: (ev) => sendPercentileTestToChat(this.actor, "Luck", 50) + onclick: (ev) => sendPercentileTestToChat(this.actor, label2, 50) }].concat(buttons); //buttons = [ From bf95913e7b95a00180d3534c0ea185ba04ee5af5 Mon Sep 17 00:00:00 2001 From: TheLastScrub <67403321+TheLastScrub@users.noreply.github.com> Date: Fri, 12 Mar 2021 23:42:02 -0800 Subject: [PATCH 07/10] updated translation of WP --- lang/es.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lang/es.json b/lang/es.json index ab6ba54..163d200 100644 --- a/lang/es.json +++ b/lang/es.json @@ -58,7 +58,7 @@ "DG.TypeSkills.Other": "Otra", "DG.Attributes.HP": "PV", - "DG.Attributes.WP": "PV", + "DG.Attributes.WP": "PVOL", "DG.Attributes.SAN": "COR", "DG.Attributes.str": "FUE", "DG.Attributes.con": "CON", From e23c95c7f894de3951e138b9980919b2a96c0d49 Mon Sep 17 00:00:00 2001 From: TheLastScrub <67403321+TheLastScrub@users.noreply.github.com> Date: Fri, 12 Mar 2021 23:51:10 -0800 Subject: [PATCH 08/10] made lethality & damange bold in chat card --- module/roll/roll.js | 511 ++++++++++++++++++++++---------------------- 1 file changed, 258 insertions(+), 253 deletions(-) diff --git a/module/roll/roll.js b/module/roll/roll.js index c607e67..53a98af 100644 --- a/module/roll/roll.js +++ b/module/roll/roll.js @@ -1,289 +1,294 @@ 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 = ''; + 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); + isCritical = skillCheckResultIsCritical(total); - if(total <= target){ - isSuccess = true; - } + if(total <= target){ + isSuccess = true; + } + + if(isCritical){ + resultString = `${game.i18n.localize("DG.Roll.Critical")} `; + } + + if(isSuccess){ + resultString += `${game.i18n.localize("DG.Roll.Success")}`; if(isCritical){ - resultString = `${game.i18n.localize("DG.Roll.Critical")} `; + resultString = resultString.toUpperCase() + '!'; + styleOverride="color: green"; } - - if(isSuccess){ - resultString += `${game.i18n.localize("DG.Roll.Success")}`; - - if(isCritical){ - resultString = resultString.toUpperCase() + '!'; - styleOverride="color: green"; - } - } - else{ - resultString += `${game.i18n.localize("DG.Roll.Failure")}`; - - if(isCritical){ - resultString = resultString.toUpperCase() + '!'; - styleOverride="color: red"; - } - } - - html = `
` - html += `
` - html += `
${resultString}
` - html += `
` - html += `
` - html += `
` - html += `

` - html += ` ${roll.formula}` - html += ` ${roll.total}` - html += `

` - html += `
    ` - html += `
  1. ${roll.total}
  2. ` - html += `
` - html += `
` - html += `
` - html += `
` - html += `

${roll.total}

` - html += `
` - - let chatData = { - speaker: ChatMessage.getSpeaker({actor: actor}), - content: html, - flavor: label, - type: CHAT_MESSAGE_TYPES.ROLL, - roll: roll, - rollMode: game.settings.get("core", "rollMode") - }; - - // play the dice rolling sound, like a regular in-chat roll - AudioHelper.play({src: "sounds/dice.wav", volume: 0.8, autoplay: true, loop: false}, true); - - ChatMessage.create(chatData, {}); } + else{ + resultString += `${game.i18n.localize("DG.Roll.Failure")}`; - export function skillCheckResultIsCritical(rollResult){ - let isCritical = false; - - if(rollResult === 1 || rollResult === 100){ - // really good, or reeaaaally bad - isCritical = true; - } - else if(rollResult % 11 === 0){ - // any matching dice are a crit, i.e. 11, 22, 33...99. - isCritical = true; - } - - return isCritical; - } - - export function sendLethalityTestToChat(actor, weaponName, target){ - let roll = new Roll('1D100', actor.data.data).roll(); - let isCritical = false; - let skillCheckTotal = roll.total; - - - // page 57 of agent's handbook - // For a failed lethality check, the damage on the tens die is a 10 for a roll of '0'. E.g. '30' + '0' = 13 damage. - // Lethality rolls do not fumble or critically succeed, but the attack roll can. - // In this situation, the lethality threshold doubles (e.g. 20% would become 40%), - // and if the lethality roll fails, the damage is doubled per normal. However right now - // the attack roll and damage roll are completely separate... Perhaps in the future, use a - // button in the skill check roll to allow doubling this logic? - - // try to determine what the d100 result would be as if it was two d10's being rolled - let damageDie1 = Math.floor(skillCheckTotal / 10); - let damageDie2 = skillCheckTotal - (damageDie1 * 10); - if(damageDie2 === 0){ - // if the result is evenly divisible by 10 (e.g. 30, 40, 50...) - // then the percentile die result was actually one lower than the calculation above would show. - // For example, a '70' is actually a 60 + 10, so the damage die should be 6 + 10 = 16, not 7 + 0 = 7. - damageDie1 -= 1; - damageDie2 = 10; - } - - let damageDie1Label = damageDie1.toString(); - let damageDie2Label = damageDie2.toString(); - - if(damageDie1 === 0){ - // a roll of 00 on the tens part of the d100 counts as a ten if it becomes a damage die - // Will leave the labeling as a '0' though, to be consistent with a regular d10 roll - damageDie1 = 10; - } - - if(damageDie2 === 10){ - // keep the labelling consistent, show a '0' for a ten - damageDie2Label = '0'; - } - - let nonlethalDamage = damageDie1 + damageDie2; - - let isLethal = false; - let html = ''; - let label = `${game.i18n.localize("DG.Roll.Rolling")} ${game.i18n.localize("DG.Roll.Lethality").toUpperCase()} ${game.i18n.localize("DG.Roll.For")} ${weaponName.toUpperCase()} ${game.i18n.localize("DG.Roll.Target")} ${target}`; - let resultString = ''; - let styleOverride = ''; - - if(skillCheckTotal <= target){ - isLethal = true; - resultString = `${game.i18n.localize("DG.Roll.Lethal").toUpperCase()}`; + if(isCritical){ + resultString = resultString.toUpperCase() + '!'; styleOverride="color: red"; } - else{ - resultString = `${game.i18n.localize("DG.Roll.Failure")}`; - } - - html = `
`; - html += `
`; - html += `
${resultString}
`; - html += `
`; - html += `
`; - html += `
`; - html += `

`; - html += ` d100 ${game.i18n.localize("DG.Roll.Or").toUpperCase()} d10 + d10`; - html += ` ${roll.total}`; - html += `

`; - html += `
    `; - html += `
  1. ${damageDie1Label}
  2. `; - html += `
  3. ${damageDie2Label}
  4. `; - html += `
`; - html += `
`; - html += `
`; - html += `
`; - html += `

${roll.total} (${nonlethalDamage} ${game.i18n.localize("DG.Roll.Damage")})

`; - html += `
`; - - let chatData = { - speaker: ChatMessage.getSpeaker({actor: actor}), - content: html, - flavor: label, - type: CHAT_MESSAGE_TYPES.ROLL, - roll: roll, - rollMode: game.settings.get("core", "rollMode") - }; - - // play the dice rolling sound, like a regular in-chat roll - AudioHelper.play({src: "sounds/dice.wav", volume: 0.8, autoplay: true, loop: false}, true); - - ChatMessage.create(chatData, {}); } - export function sendDamageRollToChat(actor, label, diceFormula){ - let roll = new Roll(diceFormula, actor.data.data); + html = `
` + html += `
` + html += `
${resultString}
` + html += `
` + html += `
` + html += `
` + html += `

` + html += ` ${roll.formula}` + html += ` ${roll.total}` + html += `

` + html += `
    ` + html += `
  1. ${roll.total}
  2. ` + html += `
` + html += `
` + html += `
` + html += `
` + html += `

${roll.total}

` + html += `
` - label = `${game.i18n.localize("DG.Roll.RollingDamageFor")} ${label.toUpperCase()}`; - - roll.roll().toMessage({ - speaker: ChatMessage.getSpeaker({ actor: actor }), + let chatData = { + speaker: ChatMessage.getSpeaker({actor: actor}), + content: html, flavor: label, type: CHAT_MESSAGE_TYPES.ROLL, roll: roll, rollMode: game.settings.get("core", "rollMode") - }); + }; + + // play the dice rolling sound, like a regular in-chat roll + AudioHelper.play({src: "sounds/dice.wav", volume: 0.8, autoplay: true, loop: false}, true); + + ChatMessage.create(chatData, {}); +} + +export function skillCheckResultIsCritical(rollResult){ + let isCritical = false; + + if(rollResult === 1 || rollResult === 100){ + // really good, or reeaaaally bad + isCritical = true; + } + else if(rollResult % 11 === 0){ + // any matching dice are a crit, i.e. 11, 22, 33...99. + isCritical = true; } - export async function showModifyPercentileTestDialogue(actor, label, originalTarget, isLethalityTest){ - - let template = "systems/deltagreen/templates/dialog/modify-percentile-roll.html"; - let backingData = { - data:{ - label: label, - originalTarget: originalTarget, - targetModifier: 20 - }, + return isCritical; +} + +export function sendLethalityTestToChat(actor, weaponName, target){ + let roll = new Roll('1D100', actor.data.data).roll(); + let isCritical = false; + let skillCheckTotal = roll.total; + + + // page 57 of agent's handbook + // For a failed lethality check, the damage on the tens die is a 10 for a roll of '0'. E.g. '30' + '0' = 13 damage. + // Lethality rolls do not fumble or critically succeed, but the attack roll can. + // In this situation, the lethality threshold doubles (e.g. 20% would become 40%), + // and if the lethality roll fails, the damage is doubled per normal. However right now + // the attack roll and damage roll are completely separate... Perhaps in the future, use a + // button in the skill check roll to allow doubling this logic? + + // try to determine what the d100 result would be as if it was two d10's being rolled + let damageDie1 = Math.floor(skillCheckTotal / 10); + let damageDie2 = skillCheckTotal - (damageDie1 * 10); + if(damageDie2 === 0){ + // if the result is evenly divisible by 10 (e.g. 30, 40, 50...) + // then the percentile die result was actually one lower than the calculation above would show. + // For example, a '70' is actually a 60 + 10, so the damage die should be 6 + 10 = 16, not 7 + 0 = 7. + damageDie1 -= 1; + damageDie2 = 10; + } + + let damageDie1Label = damageDie1.toString(); + let damageDie2Label = damageDie2.toString(); + + if(damageDie1 === 0){ + // a roll of 00 on the tens part of the d100 counts as a ten if it becomes a damage die + // Will leave the labeling as a '0' though, to be consistent with a regular d10 roll + damageDie1 = 10; + } + + if(damageDie2 === 10){ + // keep the labelling consistent, show a '0' for a ten + damageDie2Label = '0'; + } + + let nonlethalDamage = damageDie1 + damageDie2; + + let isLethal = false; + let html = ''; + let label = `${game.i18n.localize("DG.Roll.Rolling")} ${game.i18n.localize("DG.Roll.Lethality").toUpperCase()} ${game.i18n.localize("DG.Roll.For")} ${weaponName.toUpperCase()} ${game.i18n.localize("DG.Roll.Target")} ${target}`; + let resultString = ''; + let styleOverride = ''; + + if(skillCheckTotal <= target){ + isLethal = true; + resultString = `${game.i18n.localize("DG.Roll.Lethal").toUpperCase()}`; + styleOverride="color: red"; + } + else{ + resultString = `${game.i18n.localize("DG.Roll.Failure")}`; + } + + html = `
`; + html += `
`; + html += `
${resultString}
`; + html += `
`; + html += `
`; + html += `
`; + html += `

`; + html += ` d100 ${game.i18n.localize("DG.Roll.Or").toUpperCase()} d10 + d10`; + html += ` ${roll.total}`; + html += `

`; + html += `
    `; + html += `
  1. ${damageDie1Label}
  2. `; + html += `
  3. ${damageDie2Label}
  4. `; + html += `
`; + html += `
`; + html += `
`; + html += `
`; + html += `

${roll.total} (${nonlethalDamage} ${game.i18n.localize("DG.Roll.Damage")})

`; + html += `
`; + + let chatData = { + speaker: ChatMessage.getSpeaker({actor: actor}), + content: html, + flavor: label, + type: CHAT_MESSAGE_TYPES.ROLL, + roll: roll, + rollMode: game.settings.get("core", "rollMode") }; - - let html = await renderTemplate(template, backingData); - new Dialog({ - content: html, - title: game.i18n.localize("DG.ModifySkillRollDialogue.Title"), - default: "roll", - buttons: { - roll:{ - label: game.i18n.translations.DG.Roll.Roll, + // play the dice rolling sound, like a regular in-chat roll + AudioHelper.play({src: "sounds/dice.wav", volume: 0.8, autoplay: true, loop: false}, true); - callback: html => { - try{ - let targetModifier = html.find("[name='targetModifier']").val(); // this is text as a heads up + ChatMessage.create(chatData, {}); +} + +export function sendDamageRollToChat(actor, label, diceFormula){ + let roll = new Roll(diceFormula, actor.data.data); + + try{ + label = `${game.i18n.localize("DG.Roll.Rolling")} ${game.i18n.localize("DG.Roll.Damage").toUpperCase()} ${game.i18n.localize("DG.Roll.For")} ${label.toUpperCase()}`; + } + catch{ + label = `Rolling DAMAGE for ${label.toUpperCase()}` + } + + roll.roll().toMessage({ + speaker: ChatMessage.getSpeaker({ actor: actor }), + flavor: label, + type: CHAT_MESSAGE_TYPES.ROLL, + roll: roll, + rollMode: game.settings.get("core", "rollMode") + }); +} + +export async function showModifyPercentileTestDialogue(actor, label, originalTarget, isLethalityTest){ + + let template = "systems/deltagreen/templates/dialog/modify-percentile-roll.html"; + let backingData = { + data:{ + label: label, + originalTarget: originalTarget, + targetModifier: 20 + }, + }; + + let html = await renderTemplate(template, backingData); + + new Dialog({ + content: html, + title: game.i18n.localize("DG.ModifySkillRollDialogue.Title"), + default: "roll", + buttons: { + roll:{ + label: game.i18n.translations.DG.Roll.Roll, + + callback: html => { + try{ + let targetModifier = html.find("[name='targetModifier']").val(); // this is text as a heads up + + 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); + } - 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); - } + if(isLethalityTest){ + sendLethalityTestToChat(actor, label, newTarget); } - catch(ex){ - console.log(ex); + else{ + sendPercentileTestToChat(actor, label, newTarget); } } + catch(ex){ + console.log(ex); + } } } - } - ).render(true); - } + } + } + ).render(true); +} - export async function showModifyDamageRollDialogue(actor, label, originalFormula){ - - let template = "systems/deltagreen/templates/dialog/modify-damage-roll.html"; - let backingData = { - data:{ - label: label, - originalFormula: originalFormula, - outerModifier: "2 * ", - innerModifier: "+ 0" - }, - }; - - let html = await renderTemplate(template, backingData); +export async function showModifyDamageRollDialogue(actor, label, originalFormula){ + + let template = "systems/deltagreen/templates/dialog/modify-damage-roll.html"; + let backingData = { + data:{ + label: label, + originalFormula: originalFormula, + outerModifier: "2 * ", + innerModifier: "+ 0" + }, + }; + + let html = await renderTemplate(template, backingData); - new Dialog({ - content: html, - title: game.i18n.localize("DG.ModifySkillRollDialogue.Title"), - default: "roll", - buttons: { - roll:{ - label: game.i18n.translations.DG.Roll.Roll, + new Dialog({ + content: html, + title: game.i18n.localize("DG.ModifySkillRollDialogue.Title"), + default: "roll", + buttons: { + roll:{ + label: game.i18n.translations.DG.Roll.Roll, - callback: html => { - try{ - let outerModifier = html.find("[name='outerModifier']").val(); // this is text as a heads up - let innerModifier = html.find("[name='innerModifier']").val(); // this is text as a heads up - let modifiedBaseRoll = html.find("[name='originalFormula']").val(); // this is text as a heads up - - if(innerModifier.replace(" ", "") === "+0"){ - innerModifier = ""; - } - - let newRoll = ""; - if(outerModifier.trim() != ""){ - newRoll += outerModifier + "(" + modifiedBaseRoll + innerModifier.trim() + ")"; - } - else{ - newRoll += modifiedBaseRoll + innerModifier.trim(); - } - - sendDamageRollToChat(actor, label, newRoll); + callback: html => { + try{ + let outerModifier = html.find("[name='outerModifier']").val(); // this is text as a heads up + let innerModifier = html.find("[name='innerModifier']").val(); // this is text as a heads up + let modifiedBaseRoll = html.find("[name='originalFormula']").val(); // this is text as a heads up + + if(innerModifier.replace(" ", "") === "+0"){ + innerModifier = ""; } - catch(ex){ - console.log(ex); + + let newRoll = ""; + if(outerModifier.trim() != ""){ + newRoll += outerModifier + "(" + modifiedBaseRoll + innerModifier.trim() + ")"; } + else{ + newRoll += modifiedBaseRoll + innerModifier.trim(); + } + + sendDamageRollToChat(actor, label, newRoll); + } + catch(ex){ + console.log(ex); } } } - } - ).render(true); - } \ No newline at end of file + } + } + ).render(true); +} \ No newline at end of file From 8f6b41d1291e1eda188f141334579d1a2bace5da Mon Sep 17 00:00:00 2001 From: TheLastScrub <67403321+TheLastScrub@users.noreply.github.com> Date: Sat, 13 Mar 2021 00:06:31 -0800 Subject: [PATCH 09/10] added +/- to label --- lang/en.json | 2 +- lang/es.json | 2 +- lang/ja.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) 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/es.json b/lang/es.json index 163d200..1a12737 100644 --- a/lang/es.json +++ b/lang/es.json @@ -207,7 +207,7 @@ "DG.ModifySkillRollDialogue.Title": "Modificar Tirada", "DG.ModifySkillRollDialogue.Test": "Test:", "DG.ModifySkillRollDialogue.OriginalTarget": "Objetivo Original:", - "DG.ModifySkillRollDialogue.TargetModifier": "Modificar Objetivo:", + "DG.ModifySkillRollDialogue.TargetModifier": "Modificar Objetivo (+/-):", "DG.ModifySkillRollDialogue.ModifierTooltip": "Dar un modificador positivo o negativo aquí para sumar o restar al objetivo en la chequeo de habilidades.", "DG.ModifyDamageRollDialogue.Weapon": "Arma:", 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": "武器:", From 686cd77ef8f900d007b3548b00f2bd7dafc5b5be Mon Sep 17 00:00:00 2001 From: TheLastScrub <67403321+TheLastScrub@users.noreply.github.com> Date: Sat, 13 Mar 2021 00:24:10 -0800 Subject: [PATCH 10/10] added localization for new macros --- module/deltagreen.js | 40 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) 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