Roll20 uses cookies to improve your experience on our site. Cookies enable you to enjoy certain features, social sharing functionality, and tailor message and display ads to your interests on our site and others. They also help us understand how our site is being used. By continuing to use our site, you consent to our use of cookies. Update your cookie preferences .
×

Mork Borg Initiative to Turn Tracker

I'm trying to write a script where a d6 is rolled and On d6 roll 1-3: Party members get initiative 2. Non-party members get initiative 1. On d6 roll 4-6: Party members get initiative 1. Non-party members get initiative 2. And the selected tokens are added to the Turn Tracker with the assigned value. This script accomplishes the assignment, but does not populate the Turn Tracker. Any suggestions? // Roll20 API Script: Party d6 Initiative // Command: !party-init // // Select tokens, then run: // !party-init // // Party membership is determined by whether the represented character has this Roll20 tag: // _roll20_internal_party_tag_ // // On d6 roll 1-3: // Party members get initiative 2. // Non-party members get initiative 1. // // On d6 roll 4-6: // Party members get initiative 1. // Non-party members get initiative 2. // // This version ADDS the selected tokens to the existing turn tracker, // instead of replacing the whole turn order. var PartyD6Init = (function () { var COMMAND = "!party-init"; var PARTY_TAG = "_roll20_internal_party_tag_"; var htmlEscape = function (text) { return String(text || "") .replace(/&/g, "&") .replace(/</g, "<") .replace(/>/g, ">") .replace(/"/g, """) .replace(/'/g, "'"); }; var getPartyCharacters = function () { return findObjs({ type: "character" }) .filter(function (c) { var tags = c.get("tags") || []; return tags.indexOf(PARTY_TAG) !== -1; }); }; var getPartyCharacterIds = function () { var ids = {}; getPartyCharacters().forEach(function (character) { ids[character.get("_id")] = true; }); return ids; }; var getSelectedTokens = function (msg) { if (!msg.selected || msg.selected.length === 0) return []; return msg.selected .map(function (sel) { return getObj("graphic", sel._id); }) .filter(function (token) { return token && token.get("subtype") === "token"; }); }; var getCharacterName = function (characterId) { var character = characterId ? getObj("character", characterId) : null; return character ? character.get("name") : ""; }; var makeEntry = function (token, partyCharacterIds) { var characterId = token.get("represents"); var tokenName = token.get("name") || ""; var characterName = getCharacterName(characterId); var displayName = tokenName || characterName || "Unnamed Token"; var isParty = !!(characterId && partyCharacterIds[characterId]); return { id: token.get("_id"), tokenName: tokenName, characterName: characterName, characterId: characterId, displayName: displayName, isParty: isParty, pr: 0, custom: "" }; }; var getExistingTurnOrder = function () { var turnOrder = Campaign().get("turnorder"); if (!turnOrder || turnOrder === "") { return []; } try { return JSON.parse(turnOrder); } catch (e) { log("Party Initiative: Could not parse existing turn order. Starting fresh."); return []; } }; var removeExistingCopiesOfSelectedTokens = function (existingTurnOrder, selectedEntries) { var selectedIds = {}; selectedEntries.forEach(function (entry) { selectedIds[entry.id] = true; }); return existingTurnOrder.filter(function (turn) { return !selectedIds[turn.id]; }); }; var handleInitiative = function (msg) { var selectedTokens = getSelectedTokens(msg); if (selectedTokens.length === 0) { sendChat("Initiative", "/w gm Select one or more tokens first."); return; } var roll = randomInteger(6); var partyGetsHigh = roll <= 3; var partyCharacterIds = getPartyCharacterIds(); var partyEntries = []; var nonPartyEntries = []; selectedTokens.forEach(function (token) { var entry = makeEntry(token, partyCharacterIds); if (entry.isParty) { partyEntries.push(entry); } else { nonPartyEntries.push(entry); } }); partyEntries.forEach(function (entry) { entry.pr = partyGetsHigh ? 2 : 1; }); nonPartyEntries.forEach(function (entry) { entry.pr = partyGetsHigh ? 1 : 2; }); var orderedEntries = partyGetsHigh ? partyEntries.concat(nonPartyEntries) : nonPartyEntries.concat(partyEntries); var newTurnEntries = orderedEntries.map(function (entry) { return { id: entry.id, pr: entry.pr, custom: "" }; }); /* * Add selected tokens to the existing turn tracker. * Existing entries for the same selected tokens are removed first, * so rerunning !party-init updates them instead of duplicating them. */ var existingTurnOrder = getExistingTurnOrder(); var cleanedExistingTurnOrder = removeExistingCopiesOfSelectedTokens(existingTurnOrder, orderedEntries); var finalTurnOrder = cleanedExistingTurnOrder.concat(newTurnEntries); /* * Sort the full tracker by initiative descending. * This keeps existing turns and newly added turns ordered together. */ finalTurnOrder.sort(function (a, b) { var apr = parseFloat(a.pr); var bpr = parseFloat(b.pr); if (isNaN(apr)) apr = 0; if (isNaN(bpr)) bpr = 0; return bpr - apr; }); Campaign().set("turnorder", JSON.stringify(finalTurnOrder)); Campaign().set("initiativepage", true); var resultText = partyGetsHigh ? "Roll 1-3: party-tagged characters get initiative 2; all others get initiative 1." : "Roll 4-6: party-tagged characters get initiative 1; all others get initiative 2."; var orderList = orderedEntries.map(function (entry, index) { return "" + '<div style="padding:4px 0; border-bottom:1px solid #ddd;">' + '<b>' + (index + 1) + ".</b> " + htmlEscape(entry.displayName) + ' <span style="font-size:90%; color:#666;">' + "(" + (entry.isParty ? "Party" : "Non-party") + ")" + "</span>" + '<b style="float:right;">' + entry.pr + "</b>" + "</div>"; }).join(""); sendChat( "Initiative", '<div style="border:1px solid #000; padding:6px; background:#fff;">' + '<div style="font-weight:bold; font-size:110%;">Party Initiative</div>' + '<div><b>d6 Roll:</b> ' + roll + "</div>" + '<div><b>Result:</b> ' + resultText + "</div>" + '<div><b>Added to Turn Tracker:</b> ' + orderedEntries.length + " token(s)</div>" + '<div><b>Party Count:</b> ' + partyEntries.length + "</div>" + '<div><b>Non-party Count:</b> ' + nonPartyEntries.length + "</div>" + "<hr>" + "<div><b>New/Updated Entries:</b></div>" + orderList + "</div>" ); log("Party Initiative Debug:"); log("Roll: " + roll); log("Party character count found by tag: " + Object.keys(partyCharacterIds).length); log("Selected party count: " + partyEntries.length); log("Selected non-party count: " + nonPartyEntries.length); log("Existing tracker entries before update: " + existingTurnOrder.length); log("Final tracker entries after update: " + finalTurnOrder.length); orderedEntries.forEach(function (entry) { log( entry.displayName + " | character=" + entry.characterName + " | characterId=" + entry.characterId + " | group=" + (entry.isParty ? "Party" : "Non-party") + " | initiative=" + entry.pr ); }); log("Final turn order JSON:"); log(JSON.stringify(finalTurnOrder)); }; var registerEventHandlers = function () { on("chat:message", function (msg) { if (msg.type !== "api") return; var command = String(msg.content || "").split(/\s+/)[0]; if (command !== COMMAND) return; handleInitiative(msg); }); }; return { registerEventHandlers: registerEventHandlers }; }()); on("ready", function () { log("Party d6 Initiative script loaded. Command: !party-init"); PartyD6Init.registerEventHandlers(); });
I think the issue may be the shape of the turn order entries. For token entries, try omitting the custom field entirely. The custom field is normally used with id: "-1" for custom tracker rows, not token rows. Change this: return { id: entry.id, pr: entry.pr, custom: "" }; to: return { id: entry.id, pr: String(entry.pr) }; You could also change the Campaign set call to the object form: Campaign().set({   turnorder: JSON.stringify(finalTurnOrder),   initiativepage: true }); So the mapped entries become: var newTurnEntries = orderedEntries.map(function (entry) {   return {     id: entry.id,     pr: String(entry.pr)   }; });
1779221993
timmaugh
Pro
API Scripter
I also do not see you committing a pageid as a part of the Turn Order entries (actually  _pageid ). That could be causing some portion of your problem, as well.