ENH: Attack rolls !
							parent
							
								
									e1319b6215
								
							
						
					
					
						commit
						7106f138d9
					
				|  | @ -167,5 +167,8 @@ | ||||||
|     "OSE.exploration.ft.long": "Find Room Trap", |     "OSE.exploration.ft.long": "Find Room Trap", | ||||||
|     "OSE.exploration.ft.short": "Find Trap", |     "OSE.exploration.ft.short": "Find Trap", | ||||||
| 
 | 
 | ||||||
|     "OSE.messages.getExperience": "{name} gained {value} experience points!" |     "OSE.messages.GetExperience": "{name} gained {value} experience points!", | ||||||
|  |     "OSE.messages.AttackSuccess": "<b>Hits AC {result}!</b> ({bonus})", | ||||||
|  |     "OSE.messages.AttackFailure": "<b>Attack fails</b> ({bonus})", | ||||||
|  |     "OSE.messages.InflictsDamage": "Inflicts damage!" | ||||||
| } | } | ||||||
|  | @ -11,6 +11,7 @@ export class OseActor extends Actor { | ||||||
| 
 | 
 | ||||||
|     // Compute modifiers from actor scores
 |     // Compute modifiers from actor scores
 | ||||||
|     this.computeModifiers(); |     this.computeModifiers(); | ||||||
|  |     this.computeAttack(); | ||||||
| 
 | 
 | ||||||
|     // Determine Initiative
 |     // Determine Initiative
 | ||||||
|     if (game.settings.get("ose", "individualInit")) { |     if (game.settings.get("ose", "individualInit")) { | ||||||
|  | @ -37,7 +38,7 @@ export class OseActor extends Actor { | ||||||
|     }).then(() => { |     }).then(() => { | ||||||
|       const speaker = ChatMessage.getSpeaker({ actor: this }); |       const speaker = ChatMessage.getSpeaker({ actor: this }); | ||||||
|       ChatMessage.create({ |       ChatMessage.create({ | ||||||
|         content: game.i18n.format("OSE.messages.getExperience", { |         content: game.i18n.format("OSE.messages.GetExperience", { | ||||||
|           name: this.name, |           name: this.name, | ||||||
|           value: modified, |           value: modified, | ||||||
|         }), |         }), | ||||||
|  | @ -51,7 +52,6 @@ export class OseActor extends Actor { | ||||||
| 
 | 
 | ||||||
|   rollHP(options = {}) { |   rollHP(options = {}) { | ||||||
|     let roll = new Roll(this.data.data.hp.hd).roll(); |     let roll = new Roll(this.data.data.hp.hd).roll(); | ||||||
|     console.log(roll); |  | ||||||
|     return this.update({ |     return this.update({ | ||||||
|       data: { |       data: { | ||||||
|         hp: { |         hp: { | ||||||
|  | @ -177,8 +177,8 @@ export class OseActor extends Actor { | ||||||
|       ...this.data, |       ...this.data, | ||||||
|       ...{ |       ...{ | ||||||
|         rollData: { |         rollData: { | ||||||
|           type: "Exploration", |           type: "Below", | ||||||
|           stat: expl, |           target: this.data.data.exploration[expl], | ||||||
|         }, |         }, | ||||||
|       }, |       }, | ||||||
|     }; |     }; | ||||||
|  | @ -236,22 +236,40 @@ export class OseActor extends Actor { | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   rollAttack(attData, options = {}) { |   rollAttack(attData, options = {}) { | ||||||
|     const rollParts = ["1d20"]; |  | ||||||
|     const data = this.data.data; |     const data = this.data.data; | ||||||
| 
 | 
 | ||||||
|     if (attData.type == "missile") { |     const rollParts = ["1d20"]; | ||||||
|       rollParts.push( |     const dmgParts = []; | ||||||
|         data.scores.dex.mod.toString(), | 
 | ||||||
|         data.thac0.mod.missile.toString() |     if (!attData.dmg || !game.settings.get("ose", "variableWeaponDamage")) { | ||||||
|       ); |       dmgParts.push("1d6"); | ||||||
|     } else if (attData.type == "melee") { |     } else { | ||||||
|       rollParts.push( |       dmgParts.push(attData.dmg); | ||||||
|         data.scores.str.mod.toString(), |  | ||||||
|         data.thac0.mod.melee.toString() |  | ||||||
|       ); |  | ||||||
|     } |     } | ||||||
|     if (game.settings.get("ose", "ascendingAC")) { | 
 | ||||||
|       rollParts.push(this.data.data.thac0.bba.toString()); | 
 | ||||||
|  |     let ascending = game.settings.get("ose", "ascendingAC"); | ||||||
|  |     if (ascending) { | ||||||
|  |       rollParts.push(data.thac0.bba.toString()); | ||||||
|  |       if (attData.type == "missile") { | ||||||
|  |         rollParts.push( | ||||||
|  |           data.scores.dex.mod.toString(), | ||||||
|  |           data.thac0.mod.missile.toString() | ||||||
|  |         ); | ||||||
|  |       } else if (attData.type == "melee") { | ||||||
|  |         rollParts.push( | ||||||
|  |           data.scores.str.mod.toString(), | ||||||
|  |           data.thac0.mod.melee.toString() | ||||||
|  |         ); | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     let thac0 = 0; | ||||||
|  |     if (attData.type == "melee") { | ||||||
|  |       dmgParts.push(data.scores.str.mod); | ||||||
|  |       thac0 = data.thac0.melee; | ||||||
|  |     } else if (attData.type == "missile") { | ||||||
|  |       thac0 = data.thac0.missile; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     const rollData = { |     const rollData = { | ||||||
|  | @ -259,12 +277,15 @@ export class OseActor extends Actor { | ||||||
|       ...{ |       ...{ | ||||||
|         rollData: { |         rollData: { | ||||||
|           type: "Attack", |           type: "Attack", | ||||||
|           stat: attData.type, |           thac0: thac0, | ||||||
|           scores: data.scores, |           weapon: { | ||||||
|  |             parts: dmgParts, | ||||||
|  |           }, | ||||||
|         }, |         }, | ||||||
|       }, |       }, | ||||||
|     }; |     }; | ||||||
|     let skip = options.event && options.event.ctrlKey; |     let skip = options.event && options.event.ctrlKey; | ||||||
|  | 
 | ||||||
|     // Roll and return
 |     // Roll and return
 | ||||||
|     return OseDice.Roll({ |     return OseDice.Roll({ | ||||||
|       event: options.event, |       event: options.event, | ||||||
|  | @ -274,8 +295,6 @@ export class OseActor extends Actor { | ||||||
|       speaker: ChatMessage.getSpeaker({ actor: this }), |       speaker: ChatMessage.getSpeaker({ actor: this }), | ||||||
|       flavor: `${attData.label} - ${game.i18n.localize("OSE.Attack")}`, |       flavor: `${attData.label} - ${game.i18n.localize("OSE.Attack")}`, | ||||||
|       title: `${attData.label} - ${game.i18n.localize("OSE.Attack")}`, |       title: `${attData.label} - ${game.i18n.localize("OSE.Attack")}`, | ||||||
|     }).then(() => { |  | ||||||
|       this.rollDamage(attData, {}); |  | ||||||
|     }); |     }); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|  | @ -334,4 +353,21 @@ export class OseActor extends Actor { | ||||||
|     data.scores.dex.init = OseActor._cappedMod(this.data.data.scores.dex.value); |     data.scores.dex.init = OseActor._cappedMod(this.data.data.scores.dex.value); | ||||||
|     data.scores.cha.npc = OseActor._cappedMod(this.data.data.scores.cha.value); |     data.scores.cha.npc = OseActor._cappedMod(this.data.data.scores.cha.value); | ||||||
|   } |   } | ||||||
|  | 
 | ||||||
|  |   computeAttack() { | ||||||
|  |     const data = this.data.data; | ||||||
|  |     let ascending = game.settings.get("ose", "ascendingAC"); | ||||||
|  |     data.thac0.missile = ascending ? data.thac0.bba : data.thac0.value; | ||||||
|  |     data.thac0.melee = ascending ? data.thac0.bba : data.thac0.value; | ||||||
|  |     if (this.data.type != "character") { | ||||||
|  |       return; | ||||||
|  |     } | ||||||
|  |     if (ascending) { | ||||||
|  |       data.thac0.missile += data.scores.dex.mod + data.thac0.mod.missile; | ||||||
|  |       data.thac0.melee += data.scores.str.mod + data.thac0.mod.melee; | ||||||
|  |     } else { | ||||||
|  |       data.thac0.missile -= data.scores.dex.mod - data.thac0.mod.missile; | ||||||
|  |       data.thac0.melee -= data.scores.str.mod - data.thac0.mod.melee; | ||||||
|  |     } | ||||||
|  |   } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -3,75 +3,27 @@ export class OseDice { | ||||||
|     let result = { |     let result = { | ||||||
|       isSuccess: false, |       isSuccess: false, | ||||||
|       isFailure: false, |       isFailure: false, | ||||||
|       target: "", |       target: data.rollData.target, | ||||||
|     }; |     }; | ||||||
|     // ATTACKS
 | 
 | ||||||
|     let die = roll.parts[0].total; |     let die = roll.parts[0].total; | ||||||
|     if (data.rollData.type == "Attack") { |     if (data.rollData.type == "Above") { | ||||||
|       if (game.settings.get("ose", "ascendingAC")) { |  | ||||||
|         let bba = data.data.thac0.bba; |  | ||||||
|         if (data.rollData.stat == "melee") { |  | ||||||
|           bba += data.data.thac0.mod.melee + data.rollData.scores.str.mod; |  | ||||||
|         } else if (data.rollData.stat == "missile") { |  | ||||||
|           bba += data.data.thac0.mod.missile + data.rollData.scores.dex.mod; |  | ||||||
|         } |  | ||||||
|         result.target = bba; |  | ||||||
|         if (die == 1) { |  | ||||||
|           result.isFailure = true; |  | ||||||
|           return result; |  | ||||||
|         } |  | ||||||
|         result.isSuccess = true; |  | ||||||
|       } else { |  | ||||||
|         // B/X Historic THAC0 Calculation
 |  | ||||||
|         let thac = data.data.thac0.value; |  | ||||||
|         if (data.rollData.stat == "melee") { |  | ||||||
|           thac -= data.data.thac0.mod.melee + data.rollData.scores.str.mod; |  | ||||||
|         } else if (data.rollData.stat == "missile") { |  | ||||||
|           thac -= data.data.thac0.mod.missile + data.rollData.scores.dex.mod; |  | ||||||
|         } |  | ||||||
|         result.target = thac; |  | ||||||
|         if (thac - roll.total > 9) { |  | ||||||
|           result.isFailure = true; |  | ||||||
|           return result; |  | ||||||
|         } |  | ||||||
|         result.details = `<div class='roll-result'><b>Hits AC ${Math.clamped( |  | ||||||
|           thac - roll.total, |  | ||||||
|           -3, |  | ||||||
|           9 |  | ||||||
|         )}</b> (${thac})</div>`; |  | ||||||
|       } |  | ||||||
|     } else if (data.rollData.type == "Above") { |  | ||||||
|       // SAVING THROWS
 |       // SAVING THROWS
 | ||||||
|       let sv = data.rollData.target; |       if (roll.total >= result.target) { | ||||||
|       result.target = sv; |  | ||||||
|       if (roll.total >= sv) { |  | ||||||
|         result.isSuccess = true; |         result.isSuccess = true; | ||||||
|       } else { |       } else { | ||||||
|         result.isFailure = true; |         result.isFailure = true; | ||||||
|       } |       } | ||||||
|     } else if (data.rollData.type == "Below") { |     } else if (data.rollData.type == "Below") { | ||||||
|       // Morale
 |       // MORALE, EXPLORATION
 | ||||||
|       let m = data.rollData.target; |       if (roll.total <= result.target) { | ||||||
|       result.target = m; |  | ||||||
|       if (roll.total <= m) { |  | ||||||
|         result.isSuccess = true; |         result.isSuccess = true; | ||||||
|       } else { |       } else { | ||||||
|         result.isFailure = true; |         result.isFailure = true; | ||||||
|       } |       } | ||||||
|     } else if (data.rollData.type == "Check") { |     } else if (data.rollData.type == "Check") { | ||||||
|       // SCORE CHECKS
 |       // SCORE CHECKS (1s and 20s)
 | ||||||
|       let sc = data.rollData.target; |       if (die == 1 || (roll.total <= result.target && die < 20)) { | ||||||
|       result.target = sc; |  | ||||||
|       if (die == 1 || (roll.total <= sc && die < 20)) { |  | ||||||
|         result.isSuccess = true; |  | ||||||
|       } else { |  | ||||||
|         result.isFailure = true; |  | ||||||
|       } |  | ||||||
|     } else if (data.rollData.type == "Exploration") { |  | ||||||
|       // EXPLORATION CHECKS
 |  | ||||||
|       let sc = data.data.exploration[data.rollData.stat]; |  | ||||||
|       result.target = sc; |  | ||||||
|       if (roll.total <= sc) { |  | ||||||
|         result.isSuccess = true; |         result.isSuccess = true; | ||||||
|       } else { |       } else { | ||||||
|         result.isFailure = true; |         result.isFailure = true; | ||||||
|  | @ -88,7 +40,7 @@ export class OseDice { | ||||||
|     speaker = null, |     speaker = null, | ||||||
|     form = null, |     form = null, | ||||||
|   } = {}) { |   } = {}) { | ||||||
|     const template = "systems/ose/templates/chat/roll-attack.html"; |     const template = "systems/ose/templates/chat/roll-result.html"; | ||||||
| 
 | 
 | ||||||
|     let chatData = { |     let chatData = { | ||||||
|       user: game.user._id, |       user: game.user._id, | ||||||
|  | @ -142,6 +94,110 @@ export class OseDice { | ||||||
|     }); |     }); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|  |   static digestAttackResult(data, roll) { | ||||||
|  |     let result = { | ||||||
|  |       isSuccess: false, | ||||||
|  |       isFailure: false, | ||||||
|  |       target: "", | ||||||
|  |     }; | ||||||
|  |     result.target = data.rollData.thac0; | ||||||
|  |     if (game.settings.get("ose", "ascendingAC")) { | ||||||
|  |       result.details = game.i18n.format('OSE.messages.AttackSuccess', {result: roll.total, bonus: result.target}); | ||||||
|  |       result.isSuccess = true; | ||||||
|  |     } else { | ||||||
|  |       // B/X Historic THAC0 Calculation
 | ||||||
|  |       if (result.target - roll.total > 9) { | ||||||
|  |         result.details = game.i18n.format('OSE.messages.AttackFailure', {bonus: result.target}); | ||||||
|  |         return result; | ||||||
|  |       } | ||||||
|  |       result.isSuccess = true; | ||||||
|  |       let value = Math.clamped(result.target - roll.total, -3, 9); | ||||||
|  |       result.details = game.i18n.format('OSE.messages.AttackSuccess', {result: value, bonus: result.target}); | ||||||
|  |     } | ||||||
|  |     return result; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   static async sendAttackRoll({ | ||||||
|  |     parts = [], | ||||||
|  |     data = {}, | ||||||
|  |     title = null, | ||||||
|  |     flavor = null, | ||||||
|  |     speaker = null, | ||||||
|  |     form = null, | ||||||
|  |   } = {}) { | ||||||
|  |     const template = "systems/ose/templates/chat/roll-attack.html"; | ||||||
|  | 
 | ||||||
|  |     let chatData = { | ||||||
|  |       user: game.user._id, | ||||||
|  |       speaker: speaker, | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     let templateData = { | ||||||
|  |       title: title, | ||||||
|  |       flavor: flavor, | ||||||
|  |       data: data, | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     // Optionally include a situational bonus
 | ||||||
|  |     if (form !== null) data["bonus"] = form.bonus.value; | ||||||
|  |     if (data["bonus"]) parts.push(data["bonus"]); | ||||||
|  | 
 | ||||||
|  |     const roll = new Roll(parts.join("+"), data).roll(); | ||||||
|  |     const dmgRoll = new Roll(data.rollData.weapon.parts.join("+"), data).roll(); | ||||||
|  | 
 | ||||||
|  |     // Convert the roll to a chat message and return the roll
 | ||||||
|  |     let rollMode = game.settings.get("core", "rollMode"); | ||||||
|  |     rollMode = form ? form.rollMode.value : rollMode; | ||||||
|  | 
 | ||||||
|  |     templateData.result = OseDice.digestAttackResult(data, roll); | ||||||
|  | 
 | ||||||
|  |     return new Promise((resolve) => { | ||||||
|  |       roll.render().then((r) => { | ||||||
|  |         templateData.rollOSE = r; | ||||||
|  |         dmgRoll.render().then((dr) => { | ||||||
|  |           templateData.rollDamage = dr; | ||||||
|  |           renderTemplate(template, templateData).then((content) => { | ||||||
|  |             chatData.content = content; | ||||||
|  |             // 2 Step Dice So Nice
 | ||||||
|  |             if (game.dice3d) { | ||||||
|  |               game.dice3d | ||||||
|  |                 .showForRoll( | ||||||
|  |                   roll, | ||||||
|  |                   game.user, | ||||||
|  |                   true, | ||||||
|  |                   chatData.whisper, | ||||||
|  |                   chatData.blind | ||||||
|  |                 ) | ||||||
|  |                 .then(() => { | ||||||
|  |                   if (templateData.result.isSuccess) { | ||||||
|  |                     game.dice3d | ||||||
|  |                     .showForRoll( | ||||||
|  |                       dmgRoll, | ||||||
|  |                       game.user, | ||||||
|  |                       true, | ||||||
|  |                       chatData.whisper, | ||||||
|  |                       chatData.blind | ||||||
|  |                     ) | ||||||
|  |                     .then(() => { | ||||||
|  |                       ChatMessage.create(chatData); | ||||||
|  |                       resolve(); | ||||||
|  |                     }); | ||||||
|  |                   } else { | ||||||
|  |                     ChatMessage.create(chatData); | ||||||
|  |                     resolve(); | ||||||
|  |                   } | ||||||
|  |                 }); | ||||||
|  |             } else { | ||||||
|  |               chatData.sound = CONFIG.sounds.dice; | ||||||
|  |               ChatMessage.create(chatData); | ||||||
|  |               resolve(); | ||||||
|  |             } | ||||||
|  |           }); | ||||||
|  |         }); | ||||||
|  |       }); | ||||||
|  |     }); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|   static async Roll({ |   static async Roll({ | ||||||
|     parts = [], |     parts = [], | ||||||
|     data = {}, |     data = {}, | ||||||
|  | @ -164,37 +220,40 @@ export class OseDice { | ||||||
|       rollModes: CONFIG.Dice.rollModes, |       rollModes: CONFIG.Dice.rollModes, | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|  |     let rollData = { | ||||||
|  |       parts: parts, | ||||||
|  |       data: data, | ||||||
|  |       title: title, | ||||||
|  |       flavor: flavor, | ||||||
|  |       speaker: speaker, | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     if (skipDialog) { | ||||||
|  |       return data.rollData.type === "Attack" | ||||||
|  |         ? OseDice.sendAttackRoll(rollData) | ||||||
|  |         : OseDice.sendRoll(rollData); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     let buttons = { |     let buttons = { | ||||||
|       ok: { |       ok: { | ||||||
|         label: game.i18n.localize("OSE.Roll"), |         label: game.i18n.localize("OSE.Roll"), | ||||||
|         icon: '<i class="fas fa-dice-d20"></i>', |         icon: '<i class="fas fa-dice-d20"></i>', | ||||||
|         callback: (html) => { |         callback: (html) => { | ||||||
|           roll = OseDice.sendRoll({ |           rolled = true; | ||||||
|             parts: parts, |           rollData.form = html[0].children[0]; | ||||||
|             data: data, |           roll = | ||||||
|             title: title, |             data.rollData.type === "Attack" | ||||||
|             flavor: flavor, |               ? OseDice.sendAttackRoll(rollData) | ||||||
|             speaker: speaker, |               : OseDice.sendRoll(rollData); | ||||||
|             form: html[0].children[0], |  | ||||||
|           }); |  | ||||||
|         }, |         }, | ||||||
|       }, |       }, | ||||||
|       cancel: { |       cancel: { | ||||||
|         icon: '<i class="fas fa-times"></i>', |         icon: '<i class="fas fa-times"></i>', | ||||||
|         label: game.i18n.localize("OSE.Cancel"), |         label: game.i18n.localize("OSE.Cancel"), | ||||||
|  |         callback: (html) => {}, | ||||||
|       }, |       }, | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|     if (skipDialog) { |  | ||||||
|       return OseDice.sendRoll({ |  | ||||||
|         parts, |  | ||||||
|         data, |  | ||||||
|         title, |  | ||||||
|         flavor, |  | ||||||
|         speaker, |  | ||||||
|       }); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     const html = await renderTemplate(template, dialogData); |     const html = await renderTemplate(template, dialogData); | ||||||
|     let roll; |     let roll; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -156,12 +156,12 @@ | ||||||
|                         {{#if config.ascendingAC}} |                         {{#if config.ascendingAC}} | ||||||
|                         <div class="attribute-value" |                         <div class="attribute-value" | ||||||
|                             title="{{localize 'OSE.AB'}}({{data.thac0.bba}}) + {{localize 'OSE.scores.str.long'}}({{data.scores.str.mod}}) + {{localize 'OSE.Modifier'}}({{data.thac0.mod.melee}})"> |                             title="{{localize 'OSE.AB'}}({{data.thac0.bba}}) + {{localize 'OSE.scores.str.long'}}({{data.scores.str.mod}}) + {{localize 'OSE.Modifier'}}({{data.thac0.mod.melee}})"> | ||||||
|                             {{add data.thac0.mod.melee (add data.scores.str.mod data.thac0.bba)}} |                             {{data.thac0.melee}} | ||||||
|                         </div> |                         </div> | ||||||
|                         {{else}} |                         {{else}} | ||||||
|                         <div class="attribute-value" |                         <div class="attribute-value" | ||||||
|                             title="{{localize 'OSE.Thac0'}}({{data.thac0.value}}) - {{localize 'OSE.scores.str.long'}}({{data.scores.str.mod}}) - {{localize 'OSE.Modifier'}}({{data.thac0.mod.melee}})"> |                             title="{{localize 'OSE.Thac0'}}({{data.thac0.value}}) - {{localize 'OSE.scores.str.long'}}({{data.scores.str.mod}}) - {{localize 'OSE.Modifier'}}({{data.thac0.mod.melee}})"> | ||||||
|                             {{subtract data.thac0.mod.melee (subtract data.scores.str.mod data.thac0.value)}} |                             {{data.thac0.melee}} | ||||||
|                         </div> |                         </div> | ||||||
|                         {{/if}} |                         {{/if}} | ||||||
|                     </div> |                     </div> | ||||||
|  | @ -196,12 +196,12 @@ | ||||||
|                         {{#if config.ascendingAC}} |                         {{#if config.ascendingAC}} | ||||||
|                         <div class="attribute-value" |                         <div class="attribute-value" | ||||||
|                             title="{{localize 'OSE.AB'}}({{data.thac0.bba}}) + {{localize 'OSE.scores.dex.long'}}({{data.scores.dex.mod}}) + {{localize 'OSE.Modifier'}}({{data.thac0.mod.missile}})"> |                             title="{{localize 'OSE.AB'}}({{data.thac0.bba}}) + {{localize 'OSE.scores.dex.long'}}({{data.scores.dex.mod}}) + {{localize 'OSE.Modifier'}}({{data.thac0.mod.missile}})"> | ||||||
|                             {{add data.thac0.mod.missile (add data.scores.dex.mod data.thac0.bba)}} |                             {{data.thac0.missile}} | ||||||
|                         </div> |                         </div> | ||||||
|                         {{else}} |                         {{else}} | ||||||
|                         <div class="attribute-value" |                         <div class="attribute-value" | ||||||
|                             title="{{localize 'OSE.Thac0'}}({{data.thac0.value}}) - {{localize 'OSE.scores.dex.long'}}({{data.scores.dex.mod}}) - {{localize 'OSE.Modifier'}}({{data.thac0.mod.missile}})"> |                             title="{{localize 'OSE.Thac0'}}({{data.thac0.value}}) - {{localize 'OSE.scores.dex.long'}}({{data.scores.dex.mod}}) - {{localize 'OSE.Modifier'}}({{data.thac0.mod.missile}})"> | ||||||
|                             {{subtract data.thac0.mod.missile (subtract data.scores.dex.mod data.thac0.value)}} |                             {{data.thac0.missile}} | ||||||
|                         </div> |                         </div> | ||||||
|                         {{/if}} |                         {{/if}} | ||||||
|                     </div> |                     </div> | ||||||
|  |  | ||||||
|  | @ -1,9 +1,15 @@ | ||||||
| <section class="ose chat-message"> | <section class="ose chat-message"> | ||||||
|     <div class="ose chat-block"> |     <div class="ose chat-block"> | ||||||
|         <h2 class="chat-title">{{title}}</h2> |         <h2 class="chat-title">{{title}}</h2> | ||||||
|         {{#if result.details}}<div class="chat-details">{{{result.details}}}</div>{{/if}} |         <div class="chat-details"> | ||||||
|         {{#if result.isFailure}}<div class='roll-result roll-fail'><b>{{localize 'OSE.Failure'}}</b> ({{result.target}})</div>{{/if}} |             <div class="roll-result">{{{result.details}}}</div> | ||||||
|         {{#if result.isSuccess}}<div class='roll-result roll-success'><b>{{localize 'OSE.Success'}}</b> ({{result.target}})</div>{{/if}} |         </div> | ||||||
|         {{#if rollOSE}}<div>{{{rollOSE}}}</div>{{/if}} |         {{#if rollOSE}}<div>{{{rollOSE}}}</div>{{/if}} | ||||||
|  |         {{#if result.isSuccess}} | ||||||
|  |         <div class="chat-details"> | ||||||
|  |             <div class="roll-result"><b>{{localize 'OSE.messages.InflictsDamage'}}</b></div> | ||||||
|  |         </div> | ||||||
|  |         <div>{{{rollDamage}}}</div> | ||||||
|  |         {{/if}} | ||||||
|     </div> |     </div> | ||||||
| </section> | </section> | ||||||
|  | @ -0,0 +1,11 @@ | ||||||
|  | <section class="ose chat-message"> | ||||||
|  |     <div class="ose chat-block"> | ||||||
|  |         <h2 class="chat-title">{{title}}</h2> | ||||||
|  |         {{#if result.details}}<div class="chat-details">{{{result.details}}}</div>{{/if}} | ||||||
|  |         {{#if result.isFailure}}<div class='roll-result roll-fail'><b>{{localize 'OSE.Failure'}}</b> ({{result.target}}) | ||||||
|  |         </div>{{/if}} | ||||||
|  |         {{#if result.isSuccess}}<div class='roll-result roll-success'><b>{{localize 'OSE.Success'}}</b> | ||||||
|  |             ({{result.target}})</div>{{/if}} | ||||||
|  |         {{#if rollOSE}}<div>{{{rollOSE}}}</div>{{/if}} | ||||||
|  |     </div> | ||||||
|  | </section> | ||||||
		Loading…
	
		Reference in New Issue