Ajout d'un overlay Killathon¶
Cet overlay a été conçu pour fonctionner avec le service StreamElements et son Chatbot.
Une commande (personnalisable) vous permet de modifier le compteur (par ajouter, retrait ou définition de la valeur).
Des permissions sont aussi à définir : est-ce que les modos, les vips voire une liste de comptes Twitch particuliers peuvent utiliser la commande.
Le style du widget est personnalisables (titre, cadre et emote).
Le compteur se met également à jour en fonction des évenements de type bits, sub (prime, T1, T2, T3), subgift (T1, T2, T3) et don paypal par StreamElements avec un taux de conversion personnalisable par type et tier.
Mise en place¶
Partie Dashboard¶
-
Se connecter : https://streamelements.com/
-
Désactiver les modules Chatbot inutiles
- Aller dans Dashboard > Chatbot > Modules : https://streamelements.com/dashboard/bot/modules
- Désactiver les commandes par défaut inutiles
- Aller dans Dashboard > Chatbot > Commands > Default commands : https://streamelements.com/dashboard/bot/commands/default
Partie Overlay¶
- Aller dans Outils de streaming > Overlays : https://streamelements.com/dashboard/overlays
-
Ajouter un overlay de 1080p (résolution courante pour du streaming) avec un nom parlant ("killathon" par exemple)
-
Ajouter un widget de type Custom widget (Static / custom > Custom widget)
- Sélectionner le nouveau widget et cliquer sur le menu Layers
- Sous l'intitulé "Custom widget 1", vous devriez avoir 3 sous-menu : "Settings", "Position, size and style" et "animation settings"
- Cliquer sur "Position, size and style" pour développer le sous-menu
- Mettre les settings suivants :
- Width: 300
- Height: 85
- Top: 0
- Left: 0
- Cliquer sur le sous-menu "Settings" maintenant puis le bouton "Open Editor"
- Vider les contenus des 5 onglets : HTML, CSS, JS, FIELDS et data
-
Mettre les nouveaux contenus suivants dans les onglets correspondants
Contenu à copier-coller
#widget { font-family: Arial, sans-serif; font-size: 2rem; color: white; display: flex; align-items: center; justify-content: left; height: 100vh; } #cadre { position: relative; border: 5px {{cadreBorder}} rgba(255, 255, 255, 0.5); padding: 10px; display: inline-block; text-align: center; background-color: {{cadreBackground}}; border-radius: 15px; } #title { position: absolute; top: -0.5rem; left: 50%; transform: translateX(-50%); color: white; background-color: {{titleBackground}}; padding: 0 10px; font-size: 1rem; border-radius: 10px; white-space: nowrap; display: inline-block; } #content { display: flex; align-items: center; padding-right: 1rem; } #killCountDisplay { color: {{killCountColor}}; font-weight: bold; text-shadow: 0 0 2px white, 0 0 2px white; } #killSuffix { color: white; font-weight: normal; }
let killCount = 0; let fieldData; function updateDisplay() { $('#killCountDisplay').text(killCount); } function saveCounter() { SE_API.store.set('killCount', killCount); } function loadCounter() { SE_API.store.get('killCount').then(obj => { if (obj && obj.value !== null) { killCount = parseInt(obj.value); updateDisplay(); } }).catch(error => { console.error('Erreur lors du chargement du compteur:', error); }); } function isUserAuthorized(username, badges, checkMods, checkVips) { console.log('Badges:', badges, 'Typeof:', typeof badges); is_mod = false; is_vip = false; is_broadcaster = badges.broadcaster || badges.hasOwnProperty('broadcaster') || badges.includes('broadcaster/1'); if (checkMods) { is_mod = badges.moderator || badges.hasOwnProperty('moderator') || badges.includes('moderator/1'); } if (checkVips) { is_vip = badges.vip || badges.hasOwnProperty('vip') || badges.includes('vip/1'); } return is_broadcaster || is_mod || is_vip || authorizedUsers.includes(username.toLowerCase()); } function handleKillCommand(data) { let checkMods = fieldData.allowModerators; let checkVips = fieldData.allowVips; if (!isUserAuthorized(data.nick, data.tags.badges, checkMods, checkVips)) { console.log(`Utilisateur non autorisé: ${data.nick} ${data.tags.badges}`); return; } const parts = data.text.toLowerCase().split(' '); if (parts.length === 3) { const action = parts[1]; const value = parseInt(parts[2]); if (!isNaN(value)) { switch (action) { case 'add': killCount += value; break; case 'del': killCount = Math.max(0, killCount - value); break; case 'set': killCount = Math.max(0, value); break; } updateDisplay(); saveCounter(); } } } function handleDonation(amount) { killCount += Math.floor(amount * fieldData.paypalRate); updateDisplay(); saveCounter(); } function handleCheer(bits) { killCount += Math.floor((bits / 100) * fieldData.cheerRate); updateDisplay(); saveCounter(); } function handleSubscription(tier) { switch (tier) { case 'prime': killCount += fieldData.subPrimeRate; break; case '1000': killCount += fieldData.subT1Rate; break; case '2000': killCount += fieldData.subT2Rate; break; case '3000': killCount += fieldData.subT3Rate; break; } updateDisplay(); saveCounter(); } function handleSubGift(tier, count) { let giftRate = fieldData.subT1Rate; if (tier === '2000') { giftRate = fieldData.subT2Rate; } else if (tier === '3000') { giftRate = fieldData.subT3Rate; } killCount += count * giftRate; updateDisplay(); saveCounter(); } window.addEventListener('onEventReceived', function (obj) { const { listener, event } = obj.detail; switch (listener) { case 'message': //if (event.data.text.startsWith('!kill')) { // {{command}} if (event.data.text.startsWith('{{command}}')) { handleKillCommand(event.data); } break; case 'tip-latest': handleDonation(event.amount); break; case 'cheer-latest': handleCheer(event.amount); break; case 'subscriber-latest': if (event.gifted) { handleSubGift(event.tier, event.amount); } else { handleSubscription(event.tier); } break; } }); window.addEventListener('onWidgetLoad', function (obj) { fieldData = obj.detail.fieldData; authorizedUsers = fieldData.authorizedUsers.toLowerCase().split(',').map(user => user.trim()); loadCounter(); });
{ "command": { "type": "text", "label": "Commande de tchat (!xxx)", "value": "!kill", "group": "Commande" }, "allowModerators": { "type": "checkbox", "label": "Autoriser les modos", "group": "Permissions" }, "allowVips": { "type": "checkbox", "label": "Autoriser les VIPs", "group": "Permissions" }, "authorizedUsers": { "type": "text", "label": "Utilisateurs autorisés (séparés par des virgules)", "value": "", "group": "Permissions" }, "cadreBorder": { "type": "dropdown", "label": "Bordure du cadre :", "value": "double", "options": { "none": "Aucune", "double": "Double", "solid": "Solide" }, "group": "Style" }, "cadreBackground": { "type": "colorpicker", "value": "rgba(255, 255, 255, 0.5)", "label": "Couleur fond cadre", "group": "Style" }, "titleBackground": { "type": "colorpicker", "value": "rgba(0, 0, 255, 0.3)", "label": "Couleur fond titre", "group": "Style" }, "title": { "type": "text", "label": "Titre du cadre", "value": "Restant à faire", "group": "Style" }, "killCountColor": { "type": "colorpicker", "value": "rgba(255,0,0,1)", "label": "Couleur compteur kill", "group": "Style" }, "emoteUrl": { "type": "text", "label": "URL de l'emote", "value": "https://media2.giphy.com/media/GaqnjVbSLs2uA/giphy.gif", "group": "Style" }, "paypalRate": { "type": "number", "label": "Taux PayPal (kills par €)", "value": 1, "step": 0.1, "group": "Conversion" }, "cheerRate": { "type": "number", "label": "Taux Cheers (kills par 100 bits)", "value": 1, "step": 0.1, "group": "Conversion" }, "subPrimeRate": { "type": "number", "label": "Taux Sub Prime (kills)", "value": 1, "step": 1, "group": "Conversion" }, "subT1Rate": { "type": "number", "label": "Taux Sub T1 (kills)", "value": 1, "step": 1, "group": "Conversion" }, "subT2Rate": { "type": "number", "label": "Taux Sub T2 (kills)", "value": 2, "step": 1, "group": "Conversion" }, "subT3Rate": { "type": "number", "label": "Taux Sub T3 (kills)", "value": 5, "step": 1, "group": "Conversion" }, "widgetName": { "type": "hidden", "value": "Killathon" }, "widgetAuthor": { "type": "hidden", "value": "vignemail1@gmail.com" } }
- Valider avec Done
- Pensez à cliquer sur "Save" en haut à droite pour enregistrer les modifications de l'overlay
- Rafraîchir la fenêtre du navigateur (StreamElements souffre d'un défaut de mise à jour en temps-réel) et recontrôler les configurations faites sur l'overlay
- Copier l'URL de l'overlay en cliquant sur le bouton "maillon de chaine" en haut à droite, c'est l'URL pour OBS
Partie OBS¶
- Aller sur la scène qui vous intéresse
- Ajouter une source navigateur web et ajouter les paramètres suivants :
- url: l'url que vous avez copié à la fin de la configuration de l'overlay
- height: 100
- width: 300
- Disable when inactive : coché
Commandes type¶
Commandes streameur (et modos, vips et extra users)¶
Sur la base d'avoir conservé !kill
comme commande (possible de changer dans le panel Settings de l'overlay)
!kill add <x>
: ajoute x au compteur (ex:!kill add 10
)!kill del <x>
: retirer x au compteur (ex:!kill del 10
)!kill set 0
: met à 0 le compteur (ex:!kill set 100
)