From e1319b6215f14267b99ef7bf1a61bd3af0608e89 Mon Sep 17 00:00:00 2001 From: U~man Date: Sun, 5 Jul 2020 18:02:28 +0200 Subject: [PATCH] WIP: Treasure tables, hp rolls --- gulpfile.js | 1 + src/lang/en.json | 4 ++ src/module/actor/actor-sheet.js | 5 ++ src/module/actor/character-sheet.js | 5 -- src/module/actor/entity.js | 48 ++++++++++++------ src/module/actor/monster-sheet.js | 5 ++ src/module/dice.js | 49 +++++++++++-------- src/packs/macros.db | 0 src/scss/apps.scss | 17 ++++--- src/scss/monster.scss | 15 ++++++ src/system.json | 10 +++- src/template.json | 5 +- .../partials/monster-attributes-tab.html | 6 +-- .../actors/partials/monster-header.html | 10 ++-- src/templates/chat/roll-attack.html | 4 +- 15 files changed, 128 insertions(+), 56 deletions(-) create mode 100644 src/packs/macros.db diff --git a/gulpfile.js b/gulpfile.js index f4ef62b..0023a64 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -222,6 +222,7 @@ async function clean() { "lang", "templates", "assets", + "packs", "module", `${name}.js`, "module.json", diff --git a/src/lang/en.json b/src/lang/en.json index 08b3092..926d824 100644 --- a/src/lang/en.json +++ b/src/lang/en.json @@ -5,6 +5,8 @@ "OSE.Ok": "Ok", "OSE.Cancel": "Cancel", "OSE.Roll": "Roll", + "OSE.Success": "Success", + "OSE.Failure": "Failure", "OSE.Formula": "Formula", "OSE.SitMod": "Situational Modifier", @@ -20,6 +22,8 @@ "OSE.Experience": "Experience", "OSE.ExperienceBonus": "Bonus Experience", "OSE.Treasure": "Treasure type", + "OSE.TreasureTable": "Table", + "OSE.TreasureTableHint": "Drop a rollable table here to roll the monster treasure", "OSE.Size": "Size", "OSE.Morale": "Morale", "OSE.Retainer": "Retainer", diff --git a/src/module/actor/actor-sheet.js b/src/module/actor/actor-sheet.js index 102bd16..da2e953 100644 --- a/src/module/actor/actor-sheet.js +++ b/src/module/actor/actor-sheet.js @@ -125,6 +125,11 @@ export class OseActorSheet extends ActorSheet { actorObject.rollAttack({label: this.actor.name, type: attack}, { event: event }); }); + html.find(".hit-dice .attribute-name a").click((ev) => { + let actorObject = this.actor; + actorObject.rollHitDice({ event: event }); + }); + super.activateListeners(html); } diff --git a/src/module/actor/character-sheet.js b/src/module/actor/character-sheet.js index 4d04279..d755b6f 100644 --- a/src/module/actor/character-sheet.js +++ b/src/module/actor/character-sheet.js @@ -146,11 +146,6 @@ export class OseActorSheetCharacter extends OseActorSheet { actorObject.rollCheck(score, { event: event }); }); - html.find(".hit-dice .attribute-name a").click((ev) => { - let actorObject = this.actor; - actorObject.rollHitDice({ event: event }); - }); - html.find(".exploration .attribute-name a").click((ev) => { let actorObject = this.actor; let element = event.currentTarget; diff --git a/src/module/actor/entity.js b/src/module/actor/entity.js index 605bcaf..7b2d751 100644 --- a/src/module/actor/entity.js +++ b/src/module/actor/entity.js @@ -26,22 +26,42 @@ export class OseActor extends Actor { /* Socket Listeners and Handlers /* -------------------------------------------- */ getExperience(value, options = {}) { - console.log(this.data); - if (this.data.type != 'character') { + if (this.data.type != "character") { return; } - let modified = value + (this.data.data.details.xp.bonus * value) / 100; - console.log(modified); + let modified = Math.floor( + value + (this.data.data.details.xp.bonus * value) / 100 + ); return this.update({ - "data.details.xp.value": modified + this.data.data.details.xp.value + "data.details.xp.value": modified + this.data.data.details.xp.value, }).then(() => { - const speaker = ChatMessage.getSpeaker({actor: this}); - ChatMessage.create({content: game.i18n.format("OSE.messages.getExperience", {name: this.name, value: modified}), speaker}); + const speaker = ChatMessage.getSpeaker({ actor: this }); + ChatMessage.create({ + content: game.i18n.format("OSE.messages.getExperience", { + name: this.name, + value: modified, + }), + speaker, + }); }); } /* -------------------------------------------- */ /* Rolls */ /* -------------------------------------------- */ + + rollHP(options = {}) { + let roll = new Roll(this.data.data.hp.hd).roll(); + console.log(roll); + return this.update({ + data: { + hp: { + max: roll.total, + value: roll.total, + }, + }, + }); + } + rollSave(save, options = {}) { const label = game.i18n.localize(`OSE.saves.${save}.long`); const rollParts = ["1d20"]; @@ -57,7 +77,7 @@ export class OseActor extends Actor { }; let skip = options.event && options.event.ctrlKey; - + // Roll and return return OseDice.Roll({ event: options.event, @@ -132,7 +152,7 @@ export class OseActor extends Actor { ...this.data, ...{ rollData: { - type: "Hit Dice" + type: "Hit Dice", }, }, }; @@ -186,20 +206,20 @@ export class OseActor extends Actor { rollData: { type: "Damage", stat: attData.type, - scores: data.scores + scores: data.scores, }, }, }; let dmgParts = []; - if (!attData.dmg || !game.settings.get('ose', 'variableWeaponDamage')) { + if (!attData.dmg || !game.settings.get("ose", "variableWeaponDamage")) { dmgParts.push("1d6"); } else { dmgParts.push(attData.dmg); } // Add Str to damage - if (attData.type == 'melee') { + if (attData.type == "melee") { dmgParts.push(data.scores.str.mod); } @@ -212,7 +232,7 @@ export class OseActor extends Actor { speaker: ChatMessage.getSpeaker({ actor: this }), flavor: `${attData.label} - ${game.i18n.localize("OSE.Damage")}`, title: `${attData.label} - ${game.i18n.localize("OSE.Damage")}`, - }) + }); } rollAttack(attData, options = {}) { @@ -240,7 +260,7 @@ export class OseActor extends Actor { rollData: { type: "Attack", stat: attData.type, - scores: data.scores + scores: data.scores, }, }, }; diff --git a/src/module/actor/monster-sheet.js b/src/module/actor/monster-sheet.js index 2a2eed8..8f7c827 100644 --- a/src/module/actor/monster-sheet.js +++ b/src/module/actor/monster-sheet.js @@ -140,6 +140,11 @@ export class OseActorSheetMonster extends OseActorSheet { actorObject.rollMorale({ event: event }); }); + html.find(".hp-roll").click((ev) => { + let actorObject = this.actor; + actorObject.rollHP({ event: event }); + }); + // Handle default listeners last so system listeners are triggered first super.activateListeners(html); } diff --git a/src/module/dice.js b/src/module/dice.js index 5090c68..24851a9 100644 --- a/src/module/dice.js +++ b/src/module/dice.js @@ -1,6 +1,10 @@ export class OseDice { static digestResult(data, roll) { - let details = ""; + let result = { + isSuccess: false, + isFailure: false, + target: "", + }; // ATTACKS let die = roll.parts[0].total; if (data.rollData.type == "Attack") { @@ -11,12 +15,12 @@ export class OseDice { } else if (data.rollData.stat == "missile") { bba += data.data.thac0.mod.missile + data.rollData.scores.dex.mod; } - - details = `
Failure (${bba})
`; + result.target = bba; if (die == 1) { - return details; + result.isFailure = true; + return result; } - details = `
Hits AC ${roll.total} (${bba})
`; + result.isSuccess = true; } else { // B/X Historic THAC0 Calculation let thac = data.data.thac0.value; @@ -25,11 +29,12 @@ export class OseDice { } else if (data.rollData.stat == "missile") { thac -= data.data.thac0.mod.missile + data.rollData.scores.dex.mod; } - details = `
Failure (${thac})
`; + result.target = thac; if (thac - roll.total > 9) { - return details; + result.isFailure = true; + return result; } - details = `
Hits AC ${Math.clamped( + result.details = `
Hits AC ${Math.clamped( thac - roll.total, -3, 9 @@ -38,37 +43,41 @@ export class OseDice { } else if (data.rollData.type == "Above") { // SAVING THROWS let sv = data.rollData.target; + result.target = sv; if (roll.total >= sv) { - details = `
Success! (${sv})
`; + result.isSuccess = true; } else { - details = `
Failure (${sv})
`; + result.isFailure = true; } } else if (data.rollData.type == "Below") { // Morale let m = data.rollData.target; + result.target = m; if (roll.total <= m) { - details = `
Success! (${m})
`; + result.isSuccess = true; } else { - details = `
Failure (${m})
`; + result.isFailure = true; } } else if (data.rollData.type == "Check") { // SCORE CHECKS let sc = data.rollData.target; + result.target = sc; if (die == 1 || (roll.total <= sc && die < 20)) { - details = `
Success! (${sc})
`; + result.isSuccess = true; } else { - details = `
Failure (${sc})
`; + 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) { - details = `
Success! (${sc})
`; + result.isSuccess = true; } else { - details = `
Failure (${sc})
`; + result.isFailure = true; } } - return details; + return result; } static async sendRoll({ @@ -91,18 +100,18 @@ export class OseDice { 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(); // 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.details = OseDice.digestResult(data, roll); + templateData.result = OseDice.digestResult(data, roll); return new Promise((resolve) => { roll.render().then((r) => { diff --git a/src/packs/macros.db b/src/packs/macros.db new file mode 100644 index 0000000..e69de29 diff --git a/src/scss/apps.scss b/src/scss/apps.scss index 9f15969..80cadc6 100644 --- a/src/scss/apps.scss +++ b/src/scss/apps.scss @@ -14,14 +14,15 @@ .chat-details { padding: 4px; font-size: 13px; - .roll-result { - text-align: center; - &.roll-success { - color: #18520b; - } - &.roll-fail { - color: #aa0200; - } + } + .roll-result { + font-size: 13px; + text-align: center; + &.roll-success { + color: #18520b; + } + &.roll-fail { + color: #aa0200; } } } diff --git a/src/scss/monster.scss b/src/scss/monster.scss index de947aa..0ecb10a 100644 --- a/src/scss/monster.scss +++ b/src/scss/monster.scss @@ -20,6 +20,21 @@ min-width: 75px; } } + .attributes { + .attribute.health { + position: relative; + .attribute-name .hp-roll { + font-size: 12px; + position: absolute; + right: 5px; + top: 5px; + color: $colorFaint; + &:hover { + color: white; + } + } + } + } .attribute-group { .attacks-description { margin: 2px; diff --git a/src/system.json b/src/system.json index 75e2560..77827ae 100644 --- a/src/system.json +++ b/src/system.json @@ -9,7 +9,15 @@ "author": "U~man", "esmodules": ["ose.js"], "styles": ["ose.css"], - "packs": [], + "packs": [ + { + "name": "OSEMacros", + "label": "Old School Essentials Macros", + "system": "ose", + "path": "./packs/macros.db", + "entity": "Macro" + } + ], "languages": [ { "lang": "en", diff --git a/src/template.json b/src/template.json index 82e1716..e8420b2 100644 --- a/src/template.json +++ b/src/template.json @@ -141,7 +141,10 @@ "biography": "", "alignment": "", "xp": 0, - "treasure": "", + "treasure": { + "table": "", + "type": "" + }, "appearing": "", "morale": 0 }, diff --git a/src/templates/actors/partials/monster-attributes-tab.html b/src/templates/actors/partials/monster-attributes-tab.html index 2cc5cf7..bd343de 100644 --- a/src/templates/actors/partials/monster-attributes-tab.html +++ b/src/templates/actors/partials/monster-attributes-tab.html @@ -1,15 +1,15 @@
  • -

    {{ localize "OSE.HealthShort" }}

    +

    {{ localize "OSE.HealthShort" }}

    /
  • -
  • -

    {{ localize "OSE.HitDiceShort" }} +
  • +

    {{ localize "OSE.HitDiceShort" }}

    diff --git a/src/templates/actors/partials/monster-header.html b/src/templates/actors/partials/monster-header.html index dacedd6..843ac48 100644 --- a/src/templates/actors/partials/monster-header.html +++ b/src/templates/actors/partials/monster-header.html @@ -23,13 +23,17 @@ {{/if}}
    -
  • +
  • -
  • - +
  • +
  • +
  • +
    {{data.details.treasure.table}}
    + +
\ No newline at end of file diff --git a/src/templates/chat/roll-attack.html b/src/templates/chat/roll-attack.html index 81cca7a..96bcd4a 100644 --- a/src/templates/chat/roll-attack.html +++ b/src/templates/chat/roll-attack.html @@ -1,7 +1,9 @@

{{title}}

- {{#if details}}
{{{details}}}
{{/if}} + {{#if result.details}}
{{{result.details}}}
{{/if}} + {{#if result.isFailure}}
{{localize 'OSE.Failure'}} ({{result.target}})
{{/if}} + {{#if result.isSuccess}}
{{localize 'OSE.Success'}} ({{result.target}})
{{/if}} {{#if rollOSE}}
{{{rollOSE}}}
{{/if}}
\ No newline at end of file