Bots Home
|
Create an App
damnyanqui's king of the hill
Author:
damnyanqui
Description
Source Code
Launch Bot
Current Users
Created by:
Damnyanqui
// King of the Hill (Bot Version) - Competitive streak-based crown system // Bot version: runs alongside any app. No panel — uses chat notices instead. // Viewers build tip streaks to claim the crown. To dethrone the King, // your streak TOTAL must exceed theirs. cb.settings_choices = [ { name: 'streak_window', type: 'int', minValue: 1, maxValue: 60, defaultValue: 5, label: "Minutes between tips to keep streak alive" }, { name: 'min_tip', type: 'int', minValue: 1, maxValue: 1000, defaultValue: 1, label: "Minimum tip to count toward streak" }, { name: 'min_streak', type: 'int', minValue: 2, maxValue: 10, defaultValue: 2, label: "Minimum tips in a streak to claim the crown" }, { name: 'show_challengers', type: 'choice', choice1: 'yes', choice2: 'no', defaultValue: 'yes', label: "Show challenger progress publicly" }, { name: 'chat_interval', type: 'int', minValue: 0, maxValue: 30, defaultValue: 5, label: "Announce the King every X minutes (0=off)" } ]; var streaks = {}; // { user: { count, lastTip, streakTotal, bestTotal } } var checkTimers = {}; var king = null; // { user, streakTotal } var reignCount = 0; function now() { return new Date().getTime(); } function checkStreak(user) { if (!streaks[user]) return; var elapsed = now() - streaks[user].lastTip; var window = cb.settings.streak_window * 60 * 1000; if (elapsed >= window) { var s = streaks[user]; var wasKing = king && king.user === user; if (s.count >= cb.settings.min_streak) { if (wasKing) { cb.sendNotice( '>> The King\'s streak has ended! ' + user + ' held the crown with ' + s.streakTotal + ' tokens over ' + s.count + ' tips. The throne is OPEN!', '', '', '#ff4444', 'bold' ); } else { cb.sendNotice( user + '\'s streak of ' + s.count + ' tips (' + s.streakTotal + ' tokens) has ended.', '', '', '#ff4444', '' ); } } s.count = 0; s.streakTotal = 0; if (wasKing) { king = null; reignCount = 0; findNewKing(); } } } function findNewKing() { var bestUser = null; var bestTotal = 0; var minCount = cb.settings.min_streak; for (var user in streaks) { if (streaks.hasOwnProperty(user) && streaks[user].count >= minCount && streaks[user].streakTotal > bestTotal) { bestTotal = streaks[user].streakTotal; bestUser = user; } } if (bestUser) { king = { user: bestUser, streakTotal: bestTotal }; reignCount = 0; cb.sendNotice( '>> ' + bestUser + ' inherits the crown! Streak: ' + streaks[bestUser].count + ' tips (' + bestTotal + ' tokens)', '', '', '#ffd700', 'bold' ); } } function scheduleCheck(user) { if (checkTimers[user]) { cb.cancelTimeout(checkTimers[user]); } var window = cb.settings.streak_window * 60 * 1000; checkTimers[user] = cb.setTimeout(function() { checkStreak(user); }, window + 1000); } cb.onTip(function(tip) { var user = tip.from_user; var amount = parseInt(tip.amount); if (amount < cb.settings.min_tip) return; if (!streaks[user]) { streaks[user] = { count: 0, lastTip: 0, streakTotal: 0, bestTotal: 0 }; } var elapsed = now() - streaks[user].lastTip; var window = cb.settings.streak_window * 60 * 1000; if (streaks[user].count === 0 || elapsed < window) { streaks[user].count++; streaks[user].streakTotal += amount; } else { streaks[user].count = 1; streaks[user].streakTotal = amount; } streaks[user].lastTip = now(); if (streaks[user].streakTotal > streaks[user].bestTotal) { streaks[user].bestTotal = streaks[user].streakTotal; } var s = streaks[user]; if (s.count >= cb.settings.min_streak) { if (!king) { king = { user: user, streakTotal: s.streakTotal }; reignCount = 0; cb.sendNotice( '>> ' + user + ' claims the crown! Streak: ' + s.count + ' tips (' + s.streakTotal + ' tokens). ' + 'Build a bigger streak to dethrone them!', '', '', '#ffd700', 'bold' ); } else if (king.user === user) { king.streakTotal = s.streakTotal; if (s.count > 1) { cb.sendNotice( 'The King extends the lead: ' + s.count + ' tips (' + s.streakTotal + ' tokens). Keep it going!', user, '', '#ffd700', '' ); } } else if (s.streakTotal > king.streakTotal) { var oldKing = king.user; var oldTotal = king.streakTotal; king = { user: user, streakTotal: s.streakTotal }; reignCount = 0; cb.sendNotice( '>> DETHRONED! ' + user + ' (' + s.streakTotal + ' tokens over ' + s.count + ' tips) overtakes ' + oldKing + ' (' + oldTotal + ' tokens)!', '', '', '#ff4444', 'bold' ); cb.sendNotice( '>> ' + user + ' is the new King of the Hill!', '', '', '#ffd700', 'bold' ); } else { var remaining = king.streakTotal - s.streakTotal; var challengeMsg = user + ' is challenging for the crown! ' + s.streakTotal + ' / ' + king.streakTotal + ' tokens (' + remaining + ' more to dethrone ' + king.user + ')'; if (cb.settings.show_challengers === 'yes') { cb.sendNotice(challengeMsg, '', '', '#ffaa00', ''); } else { cb.sendNotice(challengeMsg, user, '', '#ffaa00', ''); } } } else if (s.count > 0) { var needed = cb.settings.min_streak - s.count; cb.sendNotice( 'Streak started! ' + needed + ' more tip' + (needed === 1 ? '' : 's') + ' to qualify for the crown. Tip within ' + cb.settings.streak_window + 'min!', user, '', '#888888', '' ); } scheduleCheck(user); }); cb.onMessage(function(msg) { if (msg.m === '!king') { if (!king) { cb.sendNotice( 'No King yet! Tip ' + cb.settings.min_streak + '+ times within ' + cb.settings.streak_window + 'min windows to claim the crown.', msg.user ); } else { var ks = streaks[king.user]; var info = 'Current King: ' + king.user + ' | Streak: ' + ks.count + ' tips (' + king.streakTotal + ' tokens)'; if (reignCount > 0) { info += ' | Defended ' + reignCount + ' time' + (reignCount === 1 ? '' : 's'); } info += ' | Need ' + (king.streakTotal + 1) + '+ token streak to dethrone!'; cb.sendNotice(info, msg.user); } msg['X-Spam'] = true; } if (msg.m === '!mystats') { var user = msg.user; var s = streaks[user]; if (s && s.count > 0) { checkStreak(user); var info = 'Your streak: ' + s.count + ' tips (' + s.streakTotal + ' tokens)' + ' | Personal best: ' + s.bestTotal + ' tokens'; if (king) { if (king.user === user) { info += ' | You are the King!'; } else { var gap = king.streakTotal - s.streakTotal; info += ' | ' + gap + ' tokens behind the crown'; } } cb.sendNotice(info, user); } else { cb.sendNotice( 'No active streak. Tip ' + cb.settings.min_tip + '+ tokens to start one!', user ); } msg['X-Spam'] = true; } if (msg.m === '!hill' || msg.m === '!leaderboard') { cb.sendNotice(getLeaderboard(), msg.user); msg['X-Spam'] = true; } return msg; }); function getLeaderboard() { var sorted = []; for (var user in streaks) { if (streaks.hasOwnProperty(user) && streaks[user].bestTotal > 0) { sorted.push({ user: user, data: streaks[user] }); } } sorted.sort(function(a, b) { return b.data.bestTotal - a.data.bestTotal; }); if (sorted.length === 0) return 'No one has claimed the hill yet! Be the first.'; var lines = ['--- KING OF THE HILL ---']; if (king) { lines.push('Current King: ' + king.user + ' (' + king.streakTotal + ' tokens)'); lines.push('---'); } var max = Math.min(sorted.length, 5); for (var i = 0; i < max; i++) { var s = sorted[i]; var isKing = king && king.user === s.user; var prefix = isKing ? '[K] ' : ''; var status = s.data.count >= cb.settings.min_streak ? 'ACTIVE (' + s.data.count + ' tips, ' + s.data.streakTotal + ' tokens)' : 'idle'; lines.push('#' + (i + 1) + ' ' + prefix + s.user + ' - Best: ' + s.data.bestTotal + ' tokens | ' + status); } return lines.join('\n'); } function advertise() { if (cb.settings.chat_interval > 0) { var msg = '--- KING OF THE HILL --- '; if (king) { msg += 'Current King: ' + king.user + ' (' + king.streakTotal + ' tokens). Build a streak of ' + (king.streakTotal + 1) + '+ tokens to dethrone them!'; } else { msg += 'No King yet! Tip ' + cb.settings.min_streak + '+ times to claim the crown!'; } msg += ' Type !king for details. ---'; cb.sendNotice(msg, '', '#ffffff', '#6441a5', 'bold'); cb.setTimeout(advertise, cb.settings.chat_interval * 60 * 1000); } } cb.onStart(function() { advertise(); });
© Copyright Chaturbate 2011- 2026. All Rights Reserved.