diff --git a/manifest.json b/manifest.json new file mode 100644 index 0000000..7b0c0d0 --- /dev/null +++ b/manifest.json @@ -0,0 +1,39 @@ +{ + "manifestVersion": 1, + "name": "Daggerheart Dice Roller", + "summary": "A Symbiote to roll duality dice with advantage or disadvantage", + "entryPoint": "/roll.html", + "descriptionFilePath": "/readme.md", + "version": "0.1", +"about": { + "website": "https://example.com", + + + "authors": [ + + + "Jane Doe", + + + "John Doe" + ] + }, "license": "GPL-3.0", + "api": { + "version": "0.1", + "subscriptions": { + "dice": { + "onRollResults": "handleRollResult" + } + } + }, + "environment": { + "webViewBackgroundColor": "#000000", + "capabilities": [ + "runInBackground" + ], + "extras": [ + "fonts", + "colorStyles" + ] + } +} diff --git a/readme.md b/readme.md new file mode 100644 index 0000000..bb5172d --- /dev/null +++ b/readme.md @@ -0,0 +1,9 @@ +This is a very simple Duality Dice Roller for Daggerheart + +Just add your modifiers (if any, can be positive or negative), +and if it applies select Advantage/Disatvantage. + +As soon as you click the "Roll Duality Dice" Button the roll gets added to the tray, +from which you can roll the dice like any other roll. + +The result then gets shown int the chat with colored formatting. \ No newline at end of file diff --git a/roll.css b/roll.css new file mode 100644 index 0000000..1dd6155 --- /dev/null +++ b/roll.css @@ -0,0 +1,86 @@ +/* roll.css */ + +body { + margin: 0; + padding: 2rem; + background-color: #121212; + color: #e7c74b; + font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; +} + +h1 { + font-size: 2rem; + margin-bottom: 2rem; + color: #e7c74b; + text-align: center; +} + +.content-row { + display: flex; + flex-direction: column; + gap: 0.5rem; + margin-bottom: 1.5rem; + max-width: 300px; + margin-left: auto; + margin-right: auto; +} + +.field-title { + font-size: 1rem; + color: #e7c74b; +} + +input[type="number"], +select { + font-size: 1.25rem; + padding: 0.75rem 1rem; + border-radius: 8px; + border: 1px solid #333; + background-color: #1e1e1e; + color: #ffffff; + outline: none; + transition: border-color 0.3s; +} + +input[type="number"]:focus, +select:focus { + border-color: #5dade2; +} + +button { + padding: 0.75rem 1.5rem; + font-size: 1.25rem; + background-color: #5dade2; + color: #121212; + border: none; + border-radius: 8px; + cursor: pointer; + transition: background-color 0.3s; + align-self: center; +} + +button:hover { + background-color: #3498db; +} + +.spacer { + height: 1rem; +} + +/* Prevent scrollbar on dropdown */ +select { + appearance: none; + -webkit-appearance: none; + -moz-appearance: none; + background-image: url('data:image/svg+xml;utf8,'); + background-repeat: no-repeat; + background-position: right 0.75rem center; + background-size: 1rem; + padding-right: 2rem; +} + +/* Optional: hide scrollbar in Firefox */ +select:-moz-focusring { + color: transparent; + text-shadow: 0 0 0 #ffffff; +} diff --git a/roll.html b/roll.html new file mode 100644 index 0000000..c24ce5f --- /dev/null +++ b/roll.html @@ -0,0 +1,28 @@ + + + + Daggerheart Dice Roller + + + + + +

Duality Dice Roll

+
+ + +
+
+ + +
+
+ + +
+ + diff --git a/roll.js b/roll.js new file mode 100644 index 0000000..973c42a --- /dev/null +++ b/roll.js @@ -0,0 +1,116 @@ +let trackedIds = {}; +let isGM = false; +let me; + +function roll(type) { + let name = document.getElementById("roll-name").value || "Check"; + let dice = document.getElementById("roll-content").value || "1d20"; + let typeStr = type == "advantage" ? " (Adv)" : " (Disadv)"; + TS.dice.putDiceInTray([{ name: name + typeStr, roll: dice }, { name: name + typeStr, roll: dice }], true).then((diceSetResponse) => { + trackedIds[diceSetResponse] = type; + }); +} + +async function rollDualityDice() { + const modifier = parseInt(document.getElementById("modifier").value) || 0; + const advDisadv = document.getElementById("adv-disadv").value; + + // Define the dice groups + const diceGroups = [ + { name: "Hope", roll: "1d12", color: "yellow" }, + { name: "Fear", roll: "1d12", color: "purple" } + ]; + + // Add advantage/disadvantage if applicable + if (advDisadv === "advantage") { + diceGroups.push({ name: "Advantage", roll: "1d6" }); + } else if (advDisadv === "disadvantage") { + diceGroups.push({ name: "Disadvantage", roll: "1d6" }); + } + + // Roll the dice + const diceSetResponse = await TS.dice.putDiceInTray(diceGroups, true); + trackedIds[diceSetResponse] = { modifier, advDisadv }; +} + +async function handleRollResult(rollEvent) { + if (!trackedIds[rollEvent.payload.rollId]) { + return; + } + + const trackedData = trackedIds[rollEvent.payload.rollId]; + const { modifier, advDisadv } = trackedData; + + if (rollEvent.kind === "rollResults") { + const roll = rollEvent.payload; + let hopeResult = 0; + let fearResult = 0; + let advDisadvResult = 0; + + for (const group of roll.resultsGroups) { + const groupSum = await TS.dice.evaluateDiceResultsGroup(group); + + if (group.name === "Hope") { + hopeResult = groupSum; + } else if (group.name === "Fear") { + fearResult = groupSum; + } else if (group.name === "Advantage" || group.name === "Disadvantage") { + advDisadvResult = groupSum; + } + } + + // Calculate the final result + let totalResult = hopeResult + fearResult + modifier; + if (advDisadv === "advantage") { + totalResult += advDisadvResult; + } else if (advDisadv === "disadvantage") { + totalResult -= advDisadvResult; + } + + // Determine the outcome + let outcome = ""; + if (hopeResult === fearResult) { + outcome = "Critical Success!"; + } else if (hopeResult > fearResult) { + outcome = "With Hope"; + } else { + outcome = "With Fear"; + } + + // Display the result in the in-game chat message + let outcomeColor = "#FFFFFF"; + if (outcome === "Critical Success!") { + outcomeColor = "#00FF00"; // Green + } else if (outcome === "With Hope") { + outcomeColor = "#4FC3F7"; // Light Blue + } else if (outcome === "With Fear") { + outcomeColor = "#E57373"; // Red + } + + const chatMessage = { + content: + `Roll Result: ` + + `Hope ${hopeResult} + ` + + `Fear ${fearResult}` + + `${modifier !== 0 ? ` + Modifier ${modifier}` : ""}` + + `${advDisadvResult !== 0 ? ` + ${advDisadv === "advantage" ? "Adv" : "Dis"} ${advDisadvResult}` : ""} = ` + + `
${totalResult} ` + + ` ${outcome}`, + rollId: roll.rollId, + expanded: true + }; + + TS.chat.send(chatMessage.content, "board").catch((response) => console.error("error in sending chat message", response)); + + // Display the result in the console + console.log(`Total Result: ${totalResult} (${outcome})`); + + displayResult(roll.resultsGroups, roll.rollId); + } else if (rollEvent.kind === "rollRemoved") { + delete trackedIds[rollEvent.payload.rollId]; + } +} + +async function displayResult(resultGroup, rollId) { + TS.dice.sendDiceResult(resultGroup, rollId).catch((response) => console.error("error in sending dice result", response)); +} \ No newline at end of file