Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- * this macro rolls initiative by using the rules for the optional rule "Speed factor initiative", available in the Dungeon Master's Guide at page 270
- * select the tokens for which you want to roll initiative and click the macro.
- * Alternatively, if you have an actor assigned and no token selected, the macro will roll initiative for your assigned actor
- * the macro does not roll initiative for actors not in combat
- * requires DnD5e Game System
- * created by Gabro#4634, with the invaluable help of Freeze#2689
- */
- Hooks.on("updateCombat", async (combat, changed) => {
- if (!("round" in changed)) {
- return;
- }
- //List of actions with their relative bonuses
- const actions = {
- "Medium Action (+0)" : +0,
- "Melee, Heavy Weapon (-2)" : -2,
- "Melee, Light or Finesse Weapon (+2)" : +2,
- "Unarmed Strike (+2)" : +2,
- "Melee, Two-Handed Weapon (-2)" : -2,
- "Ranged, Loading Weapon (-5)" : -5,
- "Spellcasting, 1st level (-1)" : -1,
- "Spellcasting, 2nd level (-2)" : -2,
- "Spellcasting, 3rd level (-3)" : -3,
- "Spellcasting, 4th level (-4)" : -4,
- "Spellcasting, 5th level (-5)" : -5,
- "Spellcasting, 6th level (-6)" : -6,
- "Spellcasting, 7th level (-7)" : -7,
- "Spellcasting, 8th level (-8)" : -8,
- "Spellcasting, 9th level (-9)" : -9,
- //optional rules as suggested by AngryDM
- //(https://theangrygm.com/fine-i-wrote-about-speed-factor-initiative-in-dd-5e/)
- //remove them if you don't want them
- "Very Slow Action (-5)" : -5,
- "Slow Action (-2)" : -2,
- "Fast Action (+2)" : +2,
- "Very Fast Action (+5)" : +5
- }
- // this option, as it is, disables the possibility to modify the box relative to the size and dex initiative bonus. If you want to modify them, change it to:
- // var disableTexts = ''
- const disableTexts = '';
- // list of sizes present in 5e, optionally it's possible to modify the bonuses (but not the size names "tiny", "sm", etc)
- const sizes = {
- "tiny" : +5,
- "sm" : +2,
- "med" : +0,
- "lg" : -2,
- "huge" : -5,
- "grg" : -8
- };
- let options = new Array ()
- for (let key in actions) {
- options.push(key)
- }
- if(!game.user.isGM) {
- let data = [
- {type : `text`, label : `Base modifier : `, options : `${game.user.character.data.data.attributes.init.total}` },
- {type : `text`, label : `Size modifier : `, options : `${sizes[game.user.character.data.data.traits.size]}` },
- {type : `select`, label : `Action : `, options},
- {type: `text`, label: `Note:`, options: ""},
- ];
- let rv = await quick_dialog({data}, game.user.character.name);
- rollInit(game.user.character.getActiveTokens()[0], rv)
- }
- else {
- let combatants = combat.combatants.filter(c => !c.actor.hasPlayerOwner);
- for(let combatant of combatants) {
- let combActor = game.actors.get(combatant.data.actorId)
- let combToken = canvas.tokens.get(combatant.data.tokenId)
- let data = [
- {type : `text`, label : `Base modifier : `, options : `${combActor.data.data.attributes.init.total}` },
- {type : `text`, label : `Size modifier : `, options : `${sizes[combActor.data.data.traits.size]}` },
- {type : `select`, label : `Action : `, options},
- {type: `text`, label: `Note:`, options: ""},
- ];
- let rv = await quick_dialog({data}, combToken.name);
- await rollInit(combToken, rv)
- }
- }
- async function quick_dialog({data, title = `Select your action for `} = {}, name)
- {
- data = data instanceof Array ? data : [data];
- let value = await new Promise((resolve) => {
- let content = `
- <table style="width:100%">
- ${data.map(({type, label, options}, i)=> {
- if(type.toLowerCase() === `select`)
- {
- return `<tr><th style="width:50%"><label>${label}</label></th><td style="width:50%"><select id="${i}qd">${options.map((e,i)=> `<option value="${e}">${e}</option>`).join(``)}</td></tr>`;
- }else{
- return `<tr><th style="width:50%"><label>${label}</label></th><td style="width:50%"><input type="${type}" ${disableTexts} id="${i}qd" value="${options instanceof Array ? options[0] : options}"/></td></tr>`;
- }
- }).join(``)}
- </table>`;
- new Dialog({
- title : title + name,
- content,
- buttons : {
- Ok : {
- label : `Roll Initiative!`,
- callback : (html) => {
- resolve(Array(data.length).fill().map((e,i)=>{
- let {type} = data[i];
- if(type.toLowerCase() === `select`)
- {
- return html.find(`select#${i}qd`).val();
- }else{
- return html.find(`input#${i}qd`)[0].value;
- }
- }));
- }
- }
- }
- }).render(true);
- });
- console.log(value);
- return value;
- }
- async function rollInit(selectedToken, initBonus){
- let combatant = selectedToken.combatant;
- let formula = ''
- if (selectedToken.actor.data.flags != null && selectedToken.actor.data.flags.dnd5e != null && selectedToken.actor.data.flags.dnd5e.initiativeAdv){
- formula = '2d20kh + @dexBonus + @sizemod + @init'
- } else {
- formula = '1d20 + @dexBonus + @sizemod + @init'
- }
- let r = await new Roll(formula, {dexBonus : initBonus[0], sizemod: initBonus[1], init: actions[initBonus[2]]}).roll()
- if(!game.user.isGM) {
- await r.toMessage({flavor : `${combatant.name} chooses ${initBonus[2]} and rolls for Initiative! <br>NOTE: ${initBonus[3]}`}, {rollMode: CONST.DICE_ROLL_MODES.PUBLIC});
- }
- else {
- if (selectedToken.document._actor.type = 'npc'){
- isNPC = true
- } else {
- isNPC = false
- }
- await r.toMessage({flavor : `${combatant.name} chooses ${initBonus[2]} and rolls for Initiative! <br>NOTE: ${initBonus[3]}`}, {rollMode: isNPC ? CONST.DICE_ROLL_MODES.PRIVATE : CONST.DICE_ROLL_MODES.PUBLIC});
- }
- });
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement