diff --git a/lib/some-lib/some-lib.css b/lib/some-lib/some-lib.css deleted file mode 100644 index e69de29..0000000 diff --git a/lib/some-lib/some-lib.min.js b/lib/some-lib/some-lib.min.js deleted file mode 100644 index e69de29..0000000 diff --git a/module/actor/actor-sheet.js b/module/actor/actor-sheet.js index aed497b..909182e 100644 --- a/module/actor/actor-sheet.js +++ b/module/actor/actor-sheet.js @@ -1,3 +1,4 @@ +import { sendPercentileTestToChat, sendLethalityTestToChat, sendDamageRollToChat } from "../roll/roll.js" /** * Extend the basic ActorSheet with some very simple modifications * @extends {ActorSheet} @@ -73,7 +74,7 @@ export class DeltaGreenActorSheet extends ActorSheet { label: "Roll Luck", class: "test-extra-icon", icon: "fas fa-dice", - onclick: (ev) => this._sendPercentileTestToChat("Luck", 50) + onclick: (ev) => sendPercentileTestToChat(this.actor, "Luck", 50) }].concat(buttons); return buttons; @@ -277,31 +278,28 @@ export class DeltaGreenActorSheet extends ActorSheet { // check the 'data-target="something" property to determine how to grab the target for the roll if(rollType === "skill" || rollType === "typeskill"){ targetVal = dataset.target; - this._sendPercentileTestToChat(label, targetVal); + sendPercentileTestToChat(this.actor, label, targetVal); } else if(dataset.target === "statistic.x5"){ let stat = this.actor.data.data.statistics[key]; targetVal = stat.x5; - this._sendPercentileTestToChat(label, targetVal); + sendPercentileTestToChat(this.actor, label, targetVal); } else if(rollType === "sanity"){ targetVal = this.actor.data.data.sanity.value; //label += `, Target: ${targetVal}`; - this._sendPercentileTestToChat(label, targetVal); + sendPercentileTestToChat(this.actor, label, targetVal); } else if(rollType === "damage"){ // damage roll, not a skill check - label = dataset.label ? `Rolling damage for ${dataset.label.toUpperCase()}` : ''; + label = dataset.label ? dataset.label : ''; - roll.roll().toMessage({ - speaker: ChatMessage.getSpeaker({ actor: this.actor }), - flavor: label - }); + sendDamageRollToChat(this.actor, label, dataset.roll); } else if(rollType === "lethality"){ // a lethality roll targetVal = dataset.target; - this._sendLethalityTestToChat(label, targetVal); + sendLethalityTestToChat(this.actor, label, targetVal); } } } @@ -321,175 +319,4 @@ export class DeltaGreenActorSheet extends ActorSheet { this.actor.update({"data": updatedData}); } - _sendLethalityTestToChat(weaponName, target){ - let roll = new Roll('d100', this.actor.data.data).roll(); - let isCritical = false; - let skillCheckTotal = roll.total; - - - // page 57 of agent's handbook - // 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 = `Rolling LETHALITY for ${weaponName.toUpperCase()} Target ${target}`; - let resultString = ''; - let styleOverride = ''; - - if(skillCheckTotal <= target){ - isLethal = true; - resultString = "LETHAL" - styleOverride="color: red"; - } - else{ - resultString = "Fail" - } - - html = `
` - html += `
` - html += `
${resultString}
` - html += `
` - html += `
` - html += `
` - html += `

` - html += ` d100 OR d10 + d10` - html += ` ${roll.total}` - html += `

` - html += `
    ` - //html += `
  1. ${roll.total}
  2. ` - html += `
  3. ${damageDie1Label}
  4. ` - html += `
  5. ${damageDie2Label}
  6. ` - html += `
` - html += `
` - html += `
` - html += `
` - html += `

${roll.total} (${nonlethalDamage} Damage)

` - html += `
` - - let chatData = { - speaker: ChatMessage.getSpeaker({actor: this.actor}), - content: html, - flavor: label - }; - - // 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, {}); - } - - _sendPercentileTestToChat(skill, target){ - let roll = new Roll('d100', this.actor.data.data).roll(); - let total = roll.total; - let isCritical = false; - let isSuccess = false; - let html = ''; - let label = `Rolling ${skill.toUpperCase()} Target ${target}`; - let resultString = ''; - let styleOverride = ''; - - isCritical = this._skillCheckResultIsCritical(total); - - if(total <= target){ - isSuccess = true; - } - - if(isCritical){ - resultString = 'CRITICAL '; - } - - if(isSuccess){ - resultString += "Success"; - - if(isCritical){ - resultString = resultString.toUpperCase() + '!'; - styleOverride="color: green"; - } - } - else{ - resultString += "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: this.actor}), - content: html, - flavor: label - }; - - // 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, {}); - } - - _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; - } - } diff --git a/module/actor/actor.js b/module/actor/actor.js index 48dfb6a..a776119 100644 --- a/module/actor/actor.js +++ b/module/actor/actor.js @@ -86,7 +86,7 @@ export class DeltaGreenActor extends Actor { data.token = data.token || {}; if ( data.type === "agent" ) { mergeObject(data.token, { - actorLink: true + actorLink: true // this will make the 'Link Actor Data' option for a token is checked by default. So changes to the token sheet will reflect to the actor sheet. }, {overwrite: false}); } return super.create(data, options); diff --git a/module/item/item.js b/module/item/item.js index 8d634f3..643ddfe 100644 --- a/module/item/item.js +++ b/module/item/item.js @@ -1,3 +1,5 @@ +import { sendPercentileTestToChat, sendLethalityTestToChat, sendDamageRollToChat } from "../roll/roll.js" + /** * Extend the basic Item with some very simple modifications. * @extends {Item} @@ -27,14 +29,12 @@ export class DeltaGreenItem extends Item { const actorData = this.actor ? this.actor.data.data : {}; const itemData = item.data; - // this isn't correct, but just leave it like this for now - // eventually need to point towards chat message rolling functions in actors sheet - // maybe need to put those in a script file and export them... - let roll = new Roll('item.data.damage', actorData); - let label = `Rolling ${item.name}`; - roll.roll().toMessage({ - speaker: ChatMessage.getSpeaker({ actor: this.actor }), - flavor: label - }); + if(item.data.isLethal){ + sendLethalityTestToChat(this.actor, item.name, item.data.lethality) + } + else{ + // regular damage roll + sendDamageRollToChat(this.actor, item.name, item.data.damage); + } } } diff --git a/module/roll/roll.js b/module/roll/roll.js new file mode 100644 index 0000000..9a31e54 --- /dev/null +++ b/module/roll/roll.js @@ -0,0 +1,181 @@ +export function sendPercentileTestToChat(actor, skill, target){ + let roll = new Roll('d100', actor.data.data).roll(); + let total = roll.total; + let isCritical = false; + let isSuccess = false; + let html = ''; + let label = `Rolling ${skill.toUpperCase()} Target ${target}`; + let resultString = ''; + let styleOverride = ''; + + isCritical = skillCheckResultIsCritical(total); + + if(total <= target){ + isSuccess = true; + } + + if(isCritical){ + resultString = 'CRITICAL '; + } + + if(isSuccess){ + resultString += "Success"; + + if(isCritical){ + resultString = resultString.toUpperCase() + '!'; + styleOverride="color: green"; + } + } + else{ + resultString += "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 + }; + + // 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; + } + + return isCritical; + } + + export function sendLethalityTestToChat(actor, weaponName, target){ + let roll = new Roll('d100', actor.data.data).roll(); + let isCritical = false; + let skillCheckTotal = roll.total; + + + // page 57 of agent's handbook + // 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 = `Rolling LETHALITY for ${weaponName.toUpperCase()} Target ${target}`; + let resultString = ''; + let styleOverride = ''; + + if(skillCheckTotal <= target){ + isLethal = true; + resultString = "LETHAL"; + styleOverride="color: red"; + } + else{ + resultString = "Fail"; + } + + html = `
`; + html += `
`; + html += `
${resultString}
`; + html += `
`; + html += `
`; + html += `
`; + html += `

`; + html += ` d100 OR d10 + d10`; + html += ` ${roll.total}`; + html += `

`; + html += `
    `; + //html += `
  1. ${roll.total}
  2. ` + html += `
  3. ${damageDie1Label}
  4. `; + html += `
  5. ${damageDie2Label}
  6. `; + html += `
`; + html += `
`; + html += `
`; + html += `
`; + html += `

${roll.total} (${nonlethalDamage} Damage)

`; + html += `
`; + + let chatData = { + speaker: ChatMessage.getSpeaker({actor: actor}), + content: html, + flavor: label + }; + + // 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); + + label = `Rolling damage for ${label.toUpperCase()}`; + + roll.roll().toMessage({ + speaker: ChatMessage.getSpeaker({ actor: actor }), + flavor: label + }); + } \ No newline at end of file