Skip to content

New Script: Daggerheart Fear Points Tracker #2059

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
107 changes: 107 additions & 0 deletions DaggerheartFearPointsTracker/feartracker.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
// Daggerheart Fear Points Tracker (Card Style, Max Cap, No Token Needed, Set Command)
// Version 1.0 – May 2025
// Author: Kim Jacobsen
//
// Description:
// Tracks Fear Points for a single character with immersive chat cards.
// Works without needing a token or custom character sheet.
//
// 📌 Setup Instructions:
// 1. Create a character in your Roll20 Journal with the exact name below:
// let characterName = "Kim the Brave"; // <-- Change this if needed
// 2. The script will automatically create an attribute called "fear_points".
//
// 🛠️ Customization:
// - Change the name in `characterName` to target another character
// - Change `MAX_FEAR` to increase or decrease the fear cap
//
// 💬 Chat Commands:
// !fear +2 → Add 2 fear points
// !fear -1 → Remove 1 fear point
// !fear set 5 → Set fear points to exactly 5
// !fear show → Display current fear points
//
// 🧠 Tip: You can create macros or abilities for these commands
// for easier in-game use.

on('chat:message', function(msg) {
if (msg.type !== 'api') return;
if (!msg.content.startsWith('!fear')) return;

let args = msg.content.split(' ');
let cmd = args[1] || 'show';
let amount = parseInt(args[1], 10);

// Set your maximum here!
const MAX_FEAR = 12;

// Always use the same character (set your character's name here)
let characterName = "Kim the Brave";
let character = findObjs({ type: 'character', name: characterName })[0];

if (!character) {
sendChat('Fear Points', '/w "' + msg.who + '" Character sheet not found! Please check the name in the script.');
return;
}

let attr = findObjs({ type: 'attribute', characterid: character.id, name: 'fear_points' })[0];

if (!attr) {
attr = createObj('attribute', {
characterid: character.id,
name: 'fear_points',
current: 0
});
}
let current = parseInt(attr.get('current'), 10) || 0;

function fearCard(title, body, total, maxed = false) {
return `/direct <div style="border: 2px solid #c53030; border-radius: 10px; background: #fff8b3; padding: 10px 20px; color: #1a1a1a; box-shadow: 0 2px 10px #c5303030; max-width: 350px;">
<div style="font-size:1.2em; font-weight:bold; color: #b7791f; letter-spacing:1px; margin-bottom: 3px;">
😱 ${title}
</div>
<div style="font-size:1em; margin-bottom:5px;">
${body}
${maxed ? "<div style='color:#c53030;font-weight:bold;'>⚠️ Maximum Fear reached!</div>" : ""}
</div>
<div style="font-size:1.1em; font-weight:bold; color:#b7791f; text-align:right;">
Total: <span style="font-size:1.4em; color: #c53030;">${total}</span> / ${MAX_FEAR}
</div>
</div>`;
}

if (cmd === 'set' && !isNaN(args[2])) {
let setTo = Math.max(0, Math.min(parseInt(args[2], 10), MAX_FEAR));
attr.set('current', setTo);
sendChat('Fear Points', fearCard(
character.get('name') + "'s Fear Points Set!",
`Fear Points set to <b>${setTo}</b>.`,
setTo,
setTo === MAX_FEAR
));
} else if (cmd === 'show' || isNaN(amount)) {
sendChat('Fear Points', fearCard(
character.get('name') + "'s Fear Points",
`You currently have <b>${current}</b> Fear Point${current === 1 ? '' : 's'}.`,
current,
current >= MAX_FEAR
));
} else if (amount > 0) {
let newTotal = Math.min(current + amount, MAX_FEAR);
attr.set('current', newTotal);
sendChat('Fear Points', fearCard(
character.get('name') + ' Gained Fear!',
`Gained <b>${Math.min(amount, MAX_FEAR - current)}</b> Fear Point${Math.min(amount, MAX_FEAR - current) === 1 ? '' : 's'}!`,
newTotal,
newTotal === MAX_FEAR
));
} else if (amount < 0) {
let newTotal = Math.max(0, current + amount);
attr.set('current', newTotal);
sendChat('Fear Points', fearCard(
character.get('name') + ' Lost Fear',
`Lost <b>${Math.abs(amount)}</b> Fear Point${Math.abs(amount) === 1 ? '' : 's'}.`,
newTotal
));
}
});
20 changes: 20 additions & 0 deletions DaggerheartFearPointsTracker/script.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"name": "Daggerheart Fear Points Tracker",
"script": "feartracker.js",
"version": "1.0",
"previousversions": [],
"description": "Tracks Fear Points for a specific character in Daggerheart-style games, using chat card visuals with a max cap and no token dependency.\n\tUse commands like `!fear +1`, `!fear -1`, `!fear show`, or `!fear set 5`.\n\tAutomatically creates the attribute `fear_points` if it doesn't exist.\n\tCustomize max value and character name directly in the script.\n\tStyled output for immersive chat cards.",
"authors": "Kim Jacobsen",
"roll20userid": "4642624",
"patreon": "",
"tipeee": "",
"useroptions": [],
"dependencies": [],
"modifies": {
"attribute": [
"read",
"write"
]
},
"conflicts": []
}
Loading