initial commit of symbiote files
This commit is contained in:
parent
f68347fb48
commit
b4c05b8e84
5 changed files with 278 additions and 0 deletions
39
manifest.json
Normal file
39
manifest.json
Normal file
|
|
@ -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"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
9
readme.md
Normal file
9
readme.md
Normal file
|
|
@ -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.
|
||||||
86
roll.css
Normal file
86
roll.css
Normal file
|
|
@ -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,<svg fill="white" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"><path d="M7 10l5 5 5-5z"/></svg>');
|
||||||
|
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;
|
||||||
|
}
|
||||||
28
roll.html
Normal file
28
roll.html
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Daggerheart Dice Roller</title>
|
||||||
|
<link rel="stylesheet" href="roll.css">
|
||||||
|
<script src="roll.js"></script>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<h1 style="margin-top: 0">Duality Dice Roll</h1>
|
||||||
|
<div class="content-row">
|
||||||
|
<label class="field-title" for="modifier">Modifier</label>
|
||||||
|
<input id="modifier" type="number" placeholder="0"></input>
|
||||||
|
</div>
|
||||||
|
<div class="content-row">
|
||||||
|
<label class="field-title" for="adv-disadv">Advantage/Disadvantage</label>
|
||||||
|
<select id="adv-disadv" size="1">
|
||||||
|
<option value="none">None</option>
|
||||||
|
<option value="advantage">Advantage</option>
|
||||||
|
<option value="disadvantage">Disadvantage</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="content-row">
|
||||||
|
<span class="spacer"></span>
|
||||||
|
<button id="roll-duality" onclick="rollDualityDice()">Roll Duality Dice</button>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
116
roll.js
Normal file
116
roll.js
Normal file
|
|
@ -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:
|
||||||
|
`<b>Roll Result:</b> ` +
|
||||||
|
`<color=#FFD700>Hope ${hopeResult}</color> + ` +
|
||||||
|
`<color=#B388FF>Fear ${fearResult}</color>` +
|
||||||
|
`${modifier !== 0 ? ` + Modifier ${modifier}` : ""}` +
|
||||||
|
`${advDisadvResult !== 0 ? ` + <i>${advDisadv === "advantage" ? "Adv" : "Dis"} ${advDisadvResult}</i>` : ""} = ` +
|
||||||
|
`<br><b><color=#FFFFFF>${totalResult}</color></b> ` +
|
||||||
|
` <i><color=${outcomeColor}>${outcome}</color></i>`,
|
||||||
|
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));
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue