Skip to content

Instantly share code, notes, and snippets.

@Corgi
Created February 11, 2023 16:19
Show Gist options
  • Save Corgi/10839bf427038afc54793f90dd7f5d3c to your computer and use it in GitHub Desktop.
Save Corgi/10839bf427038afc54793f90dd7f5d3c to your computer and use it in GitHub Desktop.
NPC Generation macro for use with Dungeon World and Foundry VTT (v10)
/* Instant NPC - v1.5
Source: https://github.com/brunocalado/mestre-digital/tree/master/Foundry%20VTT/Macros/Dungeon%20World
Updated for Foundry VTT v10 with help from the FoundryVTT Discord server
Requires Names, Knacks, and Instincts RollTables to work
Icon: https://raw.githubusercontent.com/brunocalado/mestre-digital/master/Foundry%20VTT/Macros/Dungeon%20World/Instant%20NPC.svg
Icon2: icons/environment/people/commoner.webp
*/
(async () => {
const NPCName = await drawFromTable('Names');
const NPCKnack = await drawFromTable('Knacks');
const NPCInstinct = await drawFromTable('Instincts');
const damageDieRolado = damageDie();
const randomArmorRolado = randomArmor();
let msg = `<h3>Personality</h3>`;
msg += `<p><b>Instinct:</b> ${NPCInstinct}</p>`;
msg += `<p><b>Knack:</b> ${NPCKnack}</p>`;
msg += `<h3>Treasure</h3>`;
msg += `<p>${treasureCoins(1,10)} coins.</p>`;
let message;
let npchp = randomHP(4,10);
message = `<h2><b>${NPCName}</b></h2>`;
message+=`<p><b>Damage Die:</b> ${damageDieRolado}</p>`;
message+=`<p><b>Armor:</b> ${randomArmorRolado}</p>`;
message+=msg;
addEventListenerOnHtmlElement("#createNPC", 'click', (e) => {
createRandomNPC({
name: NPCName,
type: "npc",
img: "",
sort: 12000,
data: {},
token: {},
items: [],
flags: {},
data: {
details: {
biography: msg
},
attributes: {
damage: {
value: damageDieRolado
},
ac: {
value: randomArmorRolado
},
hp: {
max: npchp,
value: npchp
}
}
}
});
});
message+=`<button id="createNPC">Create NPC</button>`;
let chatData = {
user: game.user._id,
content: message,
whisper : ChatMessage.getWhisperRecipients("GM")
};
ChatMessage.create(chatData, {});
})()
/* Functions */
async function drawFromTable(tableName){
let id;
const pack = game.packs.find(p => {
const iid = p.index.getName(tableName)?._id;
if(iid) id = iid;
return iid;
});
if (!id) {
ui.notifications.warn(`Table ${tableName} not found.`);
return;
}
const table = await pack.getDocument(id);
const draw = await table.draw({displayChat: false});
return draw.results[0].getChatText();
}
function treasureCoins(min, max) {
return Math.floor(Math.random() * (max - min) ) + min;
}
function damageDie() {
const dice = ['d4', 'd6', 'd8', 'd10', 'd12'];
return dice[ Math.floor(Math.random() * (5 - 0) ) + 0 ];
}
function randomArmor() {
return Math.floor(Math.random() * (3 - 0) ) + 0;
}
function randomHP(min, max) {
return Math.floor(Math.random() * (max - min) ) + min;
}
function addEventListenerOnHtmlElement(element, event, func){
Hooks.once("renderChatMessage", (chatItem, html) => { // Use Hook to add event to chat message html element
html[0].querySelector(element).addEventListener(event, func);
});
} // end addEventListenerOnHtmlElement
async function createRandomNPC(data) {
const instantNPC = await Actor.create(data);
await instantNPC.sheet.render(true);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment