WIP: Macros
							parent
							
								
									7ab45a1e49
								
							
						
					
					
						commit
						60377a2393
					
				|  | @ -143,12 +143,18 @@ | |||
|     "OSE.items.Cost": "Cost", | ||||
|     "OSE.items.Quantity": "Qt.", | ||||
|     "OSE.items.Roll": "Roll", | ||||
|     "OSE.items.BlindRoll": "Blind", | ||||
|     "OSE.items.Damage": "Damage", | ||||
|     "OSE.items.Melee": "Melee", | ||||
|     "OSE.items.Missile": "Missile", | ||||
|     "OSE.items.Slow": "Slow", | ||||
|     "OSE.items.ArmorAC": "AC", | ||||
|     "OSE.items.ArmorAAC": "AAC", | ||||
| 
 | ||||
|     "OSE.armor.type": "Armor Type", | ||||
|     "OSE.armor.unarmored": "Unarmored", | ||||
|     "OSE.armor.light": "Light", | ||||
|     "OSE.armor.heavy": "Heavy", | ||||
|      | ||||
|     "OSE.spells.Memorized": "Memorized", | ||||
|     "OSE.spells.Cast": "Cast", | ||||
|  |  | |||
|  | @ -21,4 +21,9 @@ export const OSE = { | |||
|     breath: "OSE.saves.breath.long", | ||||
|     spell: "OSE.saves.spell.long", | ||||
|   }, | ||||
|   armor : { | ||||
|     unarmored: "OSE.armor.unarmored", | ||||
|     light: "OSE.armor.light", | ||||
|     heavy: "OSE.armor.heavy", | ||||
|   } | ||||
| }; | ||||
|  |  | |||
|  | @ -47,6 +47,7 @@ export class OseDice { | |||
|       speaker: speaker, | ||||
|     }; | ||||
| 
 | ||||
| 
 | ||||
|     let templateData = { | ||||
|       title: title, | ||||
|       flavor: flavor, | ||||
|  | @ -62,6 +63,15 @@ export class OseDice { | |||
|     // Convert the roll to a chat message and return the roll
 | ||||
|     let rollMode = game.settings.get("core", "rollMode"); | ||||
|     rollMode = form ? form.rollMode.value : rollMode; | ||||
|      | ||||
|     // Force blind roll (ability formulas)
 | ||||
|     if (data.rollData.blindroll) { | ||||
|       rollMode = "blindroll"; | ||||
|     } | ||||
| 
 | ||||
|     if (["gmroll", "blindroll"].includes(rollMode)) chatData["whisper"] = ChatMessage.getWhisperRecipients("GM"); | ||||
|     if (rollMode === "selfroll") chatData["whisper"] = [game.user._id]; | ||||
|     if (rollMode === "blindroll") chatData["blind"] = true; | ||||
| 
 | ||||
|     templateData.result = OseDice.digestResult(data, roll); | ||||
| 
 | ||||
|  | @ -148,6 +158,10 @@ export class OseDice { | |||
|     // Convert the roll to a chat message and return the roll
 | ||||
|     let rollMode = game.settings.get("core", "rollMode"); | ||||
|     rollMode = form ? form.rollMode.value : rollMode; | ||||
|      | ||||
|     if (["gmroll", "blindroll"].includes(rollMode)) chatData["whisper"] = ChatMessage.getWhisperRecipients("GM"); | ||||
|     if (rollMode === "selfroll") chatData["whisper"] = [game.user._id]; | ||||
|     if (rollMode === "blindroll") chatData["blind"] = true; | ||||
| 
 | ||||
|     templateData.result = OseDice.digestAttackResult(data, roll); | ||||
| 
 | ||||
|  | @ -209,14 +223,13 @@ export class OseDice { | |||
|     title = null, | ||||
|     item = false, | ||||
|   } = {}) { | ||||
|     let rollMode = game.settings.get("core", "rollMode"); | ||||
|     let rolled = false; | ||||
| 
 | ||||
|     const template = "systems/ose/templates/chat/roll-dialog.html"; | ||||
|     let dialogData = { | ||||
|       formula: parts.join(" "), | ||||
|       data: data, | ||||
|       rollMode: rollMode, | ||||
|       rollMode: game.settings.get('core', 'rollMode'), | ||||
|       rollModes: CONFIG.Dice.rollModes, | ||||
|     }; | ||||
| 
 | ||||
|  | @ -225,7 +238,7 @@ export class OseDice { | |||
|       data: data, | ||||
|       title: title, | ||||
|       flavor: flavor, | ||||
|       speaker: speaker, | ||||
|       speaker: speaker | ||||
|     }; | ||||
| 
 | ||||
|     if (skipDialog) { | ||||
|  |  | |||
|  | @ -72,7 +72,8 @@ export class OseItem extends Item { | |||
|       ...this.data, | ||||
|       ...{ | ||||
|         rollData: { | ||||
|           type: "Formula" | ||||
|           type: "Formula", | ||||
|           blindroll: this.data.data.blindroll | ||||
|         }, | ||||
|       }, | ||||
|     }; | ||||
|  |  | |||
|  | @ -0,0 +1,61 @@ | |||
| 
 | ||||
| /* -------------------------------------------- */ | ||||
| /*  Hotbar Macros                               */ | ||||
| /* -------------------------------------------- */ | ||||
| 
 | ||||
| /** | ||||
|  * Create a Macro from an Item drop. | ||||
|  * Get an existing item macro if one exists, otherwise create a new one. | ||||
|  * @param {Object} data     The dropped data | ||||
|  * @param {number} slot     The hotbar slot to use | ||||
|  * @returns {Promise} | ||||
|  */ | ||||
| export async function createOseMacro(data, slot) { | ||||
|     if ( data.type !== "Item" ) return; | ||||
|     if (!( "data" in data ) ) return ui.notifications.warn("You can only create macro buttons for owned Items"); | ||||
|     const item = data.data; | ||||
|    | ||||
|     // Create the macro command
 | ||||
|     const command = `game.dnd5e.rollItemMacro("${item.name}");`; | ||||
|     let macro = game.macros.entities.find(m => (m.name === item.name) && (m.command === command)); | ||||
|     if ( !macro ) { | ||||
|       macro = await Macro.create({ | ||||
|         name: item.name, | ||||
|         type: "script", | ||||
|         img: item.img, | ||||
|         command: command, | ||||
|         flags: {"dnd5e.itemMacro": true} | ||||
|       }); | ||||
|     } | ||||
|     game.user.assignHotbarMacro(macro, slot); | ||||
|     return false; | ||||
|   } | ||||
|    | ||||
|   /* -------------------------------------------- */ | ||||
|    | ||||
|   /** | ||||
|    * Create a Macro from an Item drop. | ||||
|    * Get an existing item macro if one exists, otherwise create a new one. | ||||
|    * @param {string} itemName | ||||
|    * @return {Promise} | ||||
|    */ | ||||
|   export function rollItemMacro(itemName) { | ||||
|     const speaker = ChatMessage.getSpeaker(); | ||||
|     let actor; | ||||
|     if ( speaker.token ) actor = game.actors.tokens[speaker.token]; | ||||
|     if ( !actor ) actor = game.actors.get(speaker.actor); | ||||
|    | ||||
|     // Get matching items
 | ||||
|     const items = actor ? actor.items.filter(i => i.name === itemName) : []; | ||||
|     if ( items.length > 1 ) { | ||||
|       ui.notifications.warn(`Your controlled Actor ${actor.name} has more than one Item with name ${itemName}. The first matched item will be chosen.`); | ||||
|     } else if ( items.length === 0 ) { | ||||
|       return ui.notifications.warn(`Your controlled Actor does not have an item named ${itemName}`); | ||||
|     } | ||||
|     const item = items[0]; | ||||
|    | ||||
|     // Trigger the item roll
 | ||||
|     if ( item.data.type === "spell" ) return actor.useSpell(item); | ||||
|     return item.roll(); | ||||
|   } | ||||
|    | ||||
|  | @ -9,6 +9,7 @@ import { OSE } from "./module/config.js"; | |||
| import { registerSettings } from './module/settings.js'; | ||||
| import { registerHelpers } from './module/helpers.js'; | ||||
| import * as chat from "./module/chat.js"; | ||||
| import * as macros from "./module/macros.js"; | ||||
| 
 | ||||
| /* -------------------------------------------- */ | ||||
| /*  Foundry VTT Initialization                  */ | ||||
|  | @ -56,7 +57,7 @@ Hooks.once("init", async function () { | |||
|  */ | ||||
| Hooks.once("setup", function () { | ||||
|   // Localize CONFIG objects once up-front
 | ||||
|   const toLocalize = ["saves_short", "saves_long", "scores"]; | ||||
|   const toLocalize = ["saves_short", "saves_long", "scores", "armor"]; | ||||
|   for (let o of toLocalize) { | ||||
|     CONFIG.OSE[o] = Object.entries(CONFIG.OSE[o]).reduce((obj, e) => { | ||||
|       obj[e[0]] = game.i18n.localize(e[1]); | ||||
|  | @ -65,5 +66,9 @@ Hooks.once("setup", function () { | |||
|   } | ||||
| }); | ||||
| 
 | ||||
| Hooks.once("ready", () => { | ||||
|   Hooks.on("hotbarDrop", (bar, data, slot) => macros.createOseMacro(data, slot)); | ||||
| }); | ||||
| 
 | ||||
| Hooks.on("renderChatLog", (app, html, data) => OseItem.chatListeners(html)); | ||||
| Hooks.on("getChatLogEntryContext", chat.addChatMessageContextOptions); | ||||
|  | @ -178,6 +178,7 @@ | |||
|       "description": "", | ||||
|       "ac": 9, | ||||
|       "aac": 10, | ||||
|       "type": "light", | ||||
|       "cost": 0, | ||||
|       "equipped": false, | ||||
|       "weight": 0 | ||||
|  | @ -196,6 +197,7 @@ | |||
|     "ability": { | ||||
|       "requirements": "", | ||||
|       "roll": "", | ||||
|       "blindroll": false, | ||||
|       "description": "" | ||||
|     } | ||||
|   } | ||||
|  |  | |||
|  | @ -29,7 +29,7 @@ | |||
|         {{/if}} | ||||
| 
 | ||||
|         {{#if data.roll}} | ||||
|         <button data-action="formula">{{ localize "OSE.Roll"}} {{data.roll}}</button> | ||||
|         <button data-action="formula">{{ localize "OSE.Roll"}} {{data.roll}} {{#if data.blindroll}}({{localize 'OSE.items.BlindRoll'}}){{/if}}</button> | ||||
|         {{/if}} | ||||
|     </div> | ||||
| 
 | ||||
|  |  | |||
|  | @ -22,6 +22,12 @@ | |||
|             <input type="text" name="data.roll" value="{{data.roll}}" data-dtype="String" /> | ||||
|           </div> | ||||
|         </div> | ||||
|         <div class="form-group"> | ||||
|           <label>{{localize 'OSE.items.BlindRoll'}}</label> | ||||
|           <div class="form-fields"> | ||||
|             <input type="checkbox" name="data.blindroll" value="{{data.blindroll}}" {{checked data.blindroll}}  data-dtype="Number"/> | ||||
|           </div> | ||||
|         </div> | ||||
|       </div> | ||||
|       <div class="description"> | ||||
|         {{editor content=data.description target="data.description" button=true | ||||
|  |  | |||
|  | @ -22,6 +22,19 @@ | |||
|             <input type="text" name="data.aac.value" value="{{data.aac.value}}" data-dtype="Number" /> | ||||
|           </div> | ||||
|         </div> | ||||
|         <div class="form-group"> | ||||
|           <label>{{localize 'OSE.armor.type'}}</label> | ||||
|           <div class="form-fields"> | ||||
|             <select name="data.type"> | ||||
|               {{#select data.type}} | ||||
|               <option value=""></option> | ||||
|               {{#each config.armor as |armor a|}} | ||||
|               <option value="{{a}}">{{armor}}</option> | ||||
|               {{/each}} | ||||
|               {{/select}} | ||||
|             </select> | ||||
|           </div> | ||||
|         </div> | ||||
|         <div class="form-group"> | ||||
|           <label>{{localize 'OSE.items.Cost'}}</label> | ||||
|           <div class="form-fields"> | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue