0% found this document useful (0 votes)
89 views10 pages

BR Butler UI Script for Anime Music Quiz

This userscript saves BR picks and provides additional functionality on the Anime Music Quiz website. It creates a chat box to display saved picks, allows copying picks to the in-game chat, and toggles name visibility on the map with keyboard shortcuts. It also checks picks against new songs and updates the display to indicate correct or incorrect guesses.

Uploaded by

patebolooucarbo
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
89 views10 pages

BR Butler UI Script for Anime Music Quiz

This userscript saves BR picks and provides additional functionality on the Anime Music Quiz website. It creates a chat box to display saved picks, allows copying picks to the in-game chat, and toggles name visibility on the map with keyboard shortcuts. It also checks picks against new songs and updates the display to indicate correct or incorrect guesses.

Uploaded by

patebolooucarbo
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd

// ==UserScript==

// @name BR Butler UI
// @version 2.6.70
// @description Save BR picks and more.
// @author PsCid
// @match [Link]
// @grant none
// @require [Link]
// @require [Link]
// @updateURL [Link]
%[Link]
// ==/UserScript==

// ----------------------
// Mostrar nomes no mapa = Shift + 'E'
// Apagar nomes no mapa = Shift + 'Q'
// Modo hover = Shift + 'R'
// ----------------------

if ([Link]("startPage")) return;

// Main
$([Link]).keydown(function (event) {
if ([Link]("#mhShowSelectionSlider > [Link]-
[Link]").getAttribute("aria-valuenow") == 2) {
var list;
var i = 0;
if ([Link] === 69 && [Link] === true) {
list = [Link](".[Link]");
for(i = 0; i < [Link]; ++i) {
simulateMouseClick(list[i], 'on');
}
} else if ([Link] === 81 && [Link] === true) {
list = [Link](".[Link]");
for(i = 0; i < [Link]; ++i) {
simulateMouseClick(list[i], 'off');
}
} else if ([Link] === 82 && [Link] === true) {
toggleHoverMode();
}
}
});

var brChatTemplate = `<div id="brMsgBox" class="chatBox">


<div class="chatBoxContainer">
<div class="chatTopBar">
<p>BR Picks</p>
<span id="brMsgBoxCloseBtn" class="glyphicon glyphicon-remove
clickAble" aria-hidden="true"></span>
<span id="brMsgBoxCopyBtn" class="glyphicon clickAble playerProfile"
aria-hidden="true"><i class="fa fa-clipboard" aria-hidden="true"></i></span>
<span id="brMsgBoxSendCodeBtn" class="glyphicon clickAble
playerProfile" aria-hidden="true"><i class="fa fa-share-square-o" aria-
hidden="true"></i></span>
</div>
<textarea id="brPicksCodeInputBox" spellcheck="false" placeholder="Digite
um código de time"></textarea>
<ul id="brMsgBoxChatContent" class="chatContent"></ul>
</div>
<div id="brMsgBoxFooterBtn" class="chatBoxFooter text-center clickAble
leftRightButtonBottom">
<h4 id="brMsgBoxFooterHigh1" class="chatHighlight"><span>BR
Picks</span></h4>
<h4 id="brMsgBoxFooterHigh2" class="chatHighlight chatBoxTextGlow"><span>BR
Picks</span></h4>
</div>
</div>`;

function createBrChatBox(firstStage) {
var chatElement = [Link]("brMsgBox");
if (chatElement == null) {
var msgBox = $(format(brChatTemplate, "BR Picks"));
$("#activeChatScrollContainer").append(msgBox);
chatElement = [Link]("brMsgBox");
var msgBoxContainer =
[Link]("chatBoxContainer")[0];
var chatRollBtn = [Link]("brMsgBoxFooterBtn");
[Link]('click', function () {
if ([Link] != "translateY(0%)") {
[Link] = "translateY(0%)";
} else {
[Link] = "translateY(105%)";
}

[Link]("brMsgBoxFooterHigh1").[Link]("chatHighlight");

[Link]("brMsgBoxFooterHigh2").[Link]("chatHighlight");
}, false);

[Link]({delay: [800, 200]});

var copyPicksBtn = [Link]("brMsgBoxCopyBtn");


[Link]('click', function () {
sendPicksToChat();
}, false);

tippy('#brMsgBoxCopyBtn', {
content: 'Envia seus picks automaticamente para o chat'
});

var sendPicksBtn = [Link]("brMsgBoxSendCodeBtn");


[Link]('click', function () {
if (isTeamMode()) {
sendPicksCode();
} else {
[Link]("Você não está em um BR de times!");
}
}, false);

tippy('#brMsgBoxSendCodeBtn', {
content: 'Envia seu código de picks (BR de times)'
});

var closeBtn = [Link]("brMsgBoxCloseBtn");


[Link]('click', function () {
if (chatElement != null) {
removeBrChat();
}
}, false);

var codeInputBox = [Link]("brPicksCodeInputBox");


[Link]('keypress', function (e) {
if ([Link] == 13) {
getPicksFromCloud([Link]);
[Link] = "";
[Link]();
}
}, false);

if (firstStage) {
saveAndPrintBrPicks();
sendPicksToCloud();
}
}
}

function isTeamMode() {
return [Link];
}

function isOdd(num) { return num % 2;}

function addPickToBrChatBox(rowIndex, appeared, correct) {


var li;
var ul = [Link]("brMsgBoxChatContent");
if (ul == null) { return false;}
if ([Link]("brBoxPick" + rowIndex) == null) {
li = [Link]("li");
[Link]("id", "brBoxPick" + rowIndex);
[Link]("chatPicksLi");
colorPick(rowIndex, li, appeared, correct);
[Link]([Link]("• " + [Link]('pick '
+
rowIndex).replace(pickAlreadyPlayedCorrect,"").replace(pickAlreadyPlayedIncorrect,"
")));
[Link](li);

var answerPick = li;


[Link]('click', function () {
writePickToField(rowIndex, "qpAnswerInput");
}, false);
} else {
li = [Link]("brBoxPick" + rowIndex);
colorPick(rowIndex, li, appeared, correct);
}
}

function colorPick(rowIndex, li, appeared, correct) {


if (appeared) {
if (correct) {
[Link] = "darkgreen";
} else {
[Link] = "darkred";
}
} else {
if (isOdd(rowIndex)) {
[Link] = "dimgray";
}
}
}

function removeBrChat() {
if ([Link]("brMsgBox") != null) {
[Link]("brMsgBox").remove();
}
}

// Mouse simulation
function simulateMouseClick(targetNode, type) {
function triggerMouseEvent(targetNode, eventType) {
var clickEvent = [Link]('MouseEvents');
[Link](eventType, true, true);
[Link](clickEvent);
}
if (type == 'on') {
["mouseover"].forEach(function(eventType) {
triggerMouseEvent(targetNode, eventType);
});
} else {
["mouseout"].forEach(function(eventType) {
triggerMouseEvent(targetNode, eventType);
});
}
}

// BR Picks
var pickList;
var pickAlreadyPlayedCorrect = "";
var pickAlreadyPlayedIncorrect = "❌";
function saveAndPrintBrPicks() {
var currentIndex = 1;
pickList = [Link]("#brCollectedList li");
if ([Link] >= 1) {
deleteLocalStorage();
for (var i = 0; i < [Link]; ++i) {
[Link]('pick ' + currentIndex,
pickList[i].[Link](2, pickList[i].[Link]));
addPickToBrChatBox(currentIndex, false, true);
[Link]('length', [Link]());
currentIndex += 1;
}
}
}

function writePickToField(animeIndex, element) {


if ([Link]('pick ' + animeIndex) !== null) {
var input = [Link](element);
var pickName = [Link]('pick ' +
animeIndex).replace(pickAlreadyPlayedCorrect,"").replace(pickAlreadyPlayedIncorrect
,"");
[Link] = pickName;
var ev = [Link]('Event');
[Link]('keypress');
[Link] = [Link] = 13;
[Link](ev);
}
}

async function wait() {


await new Promise(resolve => setTimeout(resolve, 10));
}

function checkPicks(newSong) {
if ([Link]('length') != null) {
for (var i = 1; i <= parseInt([Link]('length')); ++i) {
var currentPick = [Link]('pick ' + i);
if
(([Link](pickAlreadyPlayedCorrect,"").replace(pickAlreadyPlayedIncorre
ct,"") == [Link]
||
[Link](pickAlreadyPlayedCorrect,"").replace(pickAlreadyPlayedIncorrect
,"") == [Link])
|| ([Link](pickAlreadyPlayedCorrect) ||
[Link](pickAlreadyPlayedIncorrect))) {
if ([Link](pickAlreadyPlayedCorrect)) {
[Link]('pick ' + i,
[Link](pickAlreadyPlayedCorrect,"") + pickAlreadyPlayedCorrect);
addPickToBrChatBox(i, true, true);
} else if ([Link](pickAlreadyPlayedIncorrect)) {
[Link]('pick ' + i,
[Link](pickAlreadyPlayedIncorrect,"") + pickAlreadyPlayedIncorrect);
addPickToBrChatBox(i, true, false);
} else {
if ([Link]) {
[Link]('pick ' + i,
[Link](pickAlreadyPlayedCorrect,"") + pickAlreadyPlayedCorrect);
} else {
[Link]('pick ' + i,
[Link](pickAlreadyPlayedIncorrect,"") + pickAlreadyPlayedIncorrect);
}
addPickToBrChatBox(i, true, [Link]);
}
} else {
addPickToBrChatBox(i, false, [Link]);
}
}
}
}

function sendPicksToChat() {
for (var i = 1; i <= parseInt([Link]('length')); ++i) {
writePickToField(i, "gcInput");
}
}

function sendPicksCode() {
if (![Link]("gcTeamChatSwitch").[Link]("active"))
{
[Link]('gcTeamChatSwitch')
.dispatchEvent(new MouseEvent('click', {shiftKey: false}));
}
var input = [Link]("gcInput");
var picksCode;
if ([Link]('sendPicksCode') !== null) {
picksCode = "Código: " + [Link]('sendPicksCode');
} else {
picksCode = "Criando código para os picks, tente novamente em alguns
segundos...";
}
[Link] = picksCode;
var ev = [Link]('Event');
[Link]('keypress');
[Link] = [Link] = 13;
[Link](ev);
}

function deleteLocalStorage() {
for (var i = 1; i <= parseInt([Link]('length')); ++i) {
[Link]('pick ' + i);
}
[Link]('length');
[Link]('sendPicksCode');
}

// Hover mode
const mutationObserver = new MutationObserver(callback);
function callback(mutationsList) {
[Link](mutation => {
if ([Link] === 'class') {
if ([Link]("active") &&
[Link]("brShowEntry")) {
[Link]();
}
}
})
}

function turnOnHoverMode() {
[Link](
[Link]('brMapContent'),
{ attributes: true, subtree: true }
);
}

function toggleHoverMode() {
if (!$("#brMapContent").is(":hidden")) {
if ([Link]("brHoverMode") != "on") {
turnOnHoverMode();
[Link]("brHoverMode", "on");
[Link]("Modo hover ligado!");
} else {
[Link]();
[Link]("brHoverMode", "off");
[Link]("Modo hover desligado!");
}
}
}

function checkHoverModeIsOn() {
return [Link]("brHoverMode") == "on";
}
// Setup
let loadInterval = setInterval(() => {
if ([Link]("loadingScreen").[Link]("hidden")) {
setup();
clearInterval(loadInterval);
}
}, 500);

function isBattleRoyale() {
return [Link]("#mhShowSelectionSlider > [Link]-
[Link]").getAttribute("aria-valuenow") == 2 && ![Link];
}

function setup() {
let resultsListener = new Listener("answer results", (result) => {
if (isBattleRoyale()) {
let newSong = {
anime: [Link]
};
let findPlayer = [Link]([Link]).find((tmpPlayer) => {
return tmpPlayer._name === selfName &&
[Link]._disabled === false
});
if (findPlayer !== undefined) {
let playerIdx = [Link]([Link]).findIndex(tmpPlayer
=> {
return [Link] === [Link]
});
[Link] = [Link][playerIdx].correct;
}
createBrChatBox(false);
checkPicks(newSong);
}
});

let brMapListener = new Listener("battle royal spawn", (data) => {


if (checkHoverModeIsOn()) {
turnOnHoverMode();
}
});

let quizReadyListener = new Listener("quiz ready", (data) => {


if (isBattleRoyale()) {
createBrChatBox(true);
[Link]();
}
});

let quizOverListener = new Listener("quiz over", (roomSettings) => {


if (isBattleRoyale()) {
deleteLocalStorage();
removeBrChat();
}
});

let quizReturnToLobbyListener = new Listener("return lobby vote result",


(payload) => {
if ([Link]) {
if (isBattleRoyale()) {
deleteLocalStorage();
removeBrChat();
}
}
});

let quizLeaveListener = new Listener("New Rooms", (rooms) => {


if (isBattleRoyale()) {
deleteLocalStorage();
removeBrChat();
}
});

[Link]();
[Link]();
[Link]();
[Link]();
[Link]();
[Link]();

addCss(`
#brMsgBoxChatContent {
overflow-x: hidden;
scrollbar-width: none;
height: 158px;
}
#brMsgBoxChatContent::-webkit-scrollbar {
width: 0px;
}
#brMsgBoxChatContent li:hover {
background-color: ` + $('#xpBarInner').css('backgroundColor') + ` !
important;
color: ` + $('.levelText').css('Color') + ` !important;
}
#brPicksCodeInputBox {
height: 10px;
min-height: 13%;
font-size: smaller;
outline: none;
}
.chatPicksLi {
border-bottom: 1px solid black;
padding-left: 3px;
cursor: pointer;
}
`);
}

function addCss(css) {
let head = [Link];
let style = [Link]("style");
[Link](style);
[Link] = "text/css";
[Link]([Link](css));
}

// Get teammates pick part


const picksUrl = "[Link]
function sendPicksToCloud() {
if (isTeamMode()) {
var picks = formatPicksToSend();
var xhr = new XMLHttpRequest();
[Link]("POST", picksUrl);
[Link] = function () {
if ([Link] === 4) {
if ([Link] === 200) {
var responseData = [Link];
var jsonResponse = [Link](responseData);
[Link]('sendPicksCode', [Link]);
} else {
[Link]("Ocorreu um erro durante o envio dos picks.
Status: " + [Link]);
}
}
};

var data = picks;


[Link](data);
}
}

function getPicksFromCloud(code) {
if (isTeamMode() && !isSelfPicksCode(code)) {
var xhr = new XMLHttpRequest();
[Link]("GET", picksUrl + "/" + code);

[Link] = function () {
if ([Link] === 4) {
if ([Link] === 200) {
var responseData = [Link];
var jsonResponse = [Link](responseData);
addTeammatesPicks([Link](" || "));
} else {
[Link]("Código inválido.");
}
}
};

[Link]();
} else if (isSelfPicksCode(code)) {
[Link]("Você não precisa adicionar os próprios picks!");
} else {
[Link]("Você não está em um BR de times!");
}
}

function isSelfPicksCode(code) {
var localCode = [Link]('sendPicksCode');
return code == localCode && localCode != null;
}

function addTeammatesPicks(pickList) {
if ([Link] >= 1) {
var currentPicksLength = parseInt([Link]('length'));
var currentIndex = currentPicksLength + 1;
for (var i = 0; i < [Link]; ++i) {
[Link]('pick ' + currentIndex, pickList[i]);
addPickToBrChatBox(currentIndex, false, true);
currentIndex++;
}
[Link]('length', currentPicksLength + [Link]);
}
}

function formatPicksToSend() {
var picks = "";
for (var i = 1; i <= parseInt([Link]('length')); ++i) {
picks = picks + [Link]('pick ' +
i).replace(pickAlreadyPlayedCorrect,"").replace(pickAlreadyPlayedIncorrect,"") + "
|| ";
}
return [Link](0, [Link] - 4);
}

Common questions

Powered by AI

The script visually differentiates between correct and incorrect picks within the chat box by setting the background color of list items. If a pick has been played and is correct, its background is set to 'darkgreen', while incorrect picks are given a 'darkred' background. If a pick has not yet appeared, it uses 'dimgray' for odd-indexed entries to provide a visual cue. This differentiation helps users quickly assess the accuracy of previous picks at a glance .

The script determines the current mode (team or solo) by checking the 'teamMode' flag in the quiz object with 'isTeamMode'. This distinction affects chat box actions significantly: for instance, sending picks codes and managing picks relies on whether the user is in team mode. If in team mode, functionalities like sending picks to the cloud and retrieving them are activated, enabling broader team collaboration. Conversely, in solo mode, certain actions are restricted, with system messages informing users of their solo status, preventing errors from attempting unsupported team actions .

The script saves user picks using local storage, specifically storing picks under keys like 'pick 1', 'pick 2', etc., and tracking the total number with 'length'. When picks are to be saved, the script first clears any existing picks using the 'deleteLocalStorage' function. It then iterates over a pick list from the DOM, storing each entry in local storage and adding them visually into the chat box with 'addPickToBrChatBox'. The system uses markers to distinguish if a pick was played correctly or incorrectly, adapting the display accordingly .

The chat box in the BR Butler UI serves multiple functions crucial for enhancing user interaction. It acts as a repository for user picks, displaying them with visual cues indicating whether they have been played and their correctness. Users can interact by copying and sending picks directly to the chat, using buttons that leverage event listeners for these actions. It supports team communication by allowing users to share picks codes and integrate them back into the game system. The chat box thus centralizes pick data management, making it easier for users to coordinate in team-based quiz modes .

When a quiz game is over or players return to the lobby, the script performs local storage management by calling 'deleteLocalStorage'. This function removes individual pick entries (e.g., 'pick 1', 'pick 2', etc.), clears the stored length of picks, and eliminates any 'sendPicksCode' entry. Additionally, it removes the visual chat box by calling 'removeBrChat', ensuring that no residual data or interface components remain, thereby preparing the environment for future quizzes without leftover data .

The script sends picks to the cloud by first formatting them into a string using 'formatPicksToSend', which concatenates all picks stored in local storage. This data string is then sent via a POST request to a specified URL ('https://br-butler.herokuapp.com/documents') using an XMLHttpRequest. Upon the request's completion, if successful, the response provides a key that is stored in local storage and designated as 'sendPicksCode'. If the request fails, an error message indicating the issue and status code is logged to the console. This mechanism enables retrieval of picks and communication with other team members .

The setup function is executed when the loading screen is no longer visible. This is confirmed by checking if the class 'hidden' is applied to the loading screen element, using a continuous interval check every 500ms until the conditions are met. The significance of the setup function is to bind various listeners needed for the quiz operations (e.g., answer results, quiz ready events), prepare the visual components like the chat box, and apply necessary CSS styles. It ensures that the script's functionality is integrated properly into the quiz environment, setting up elements like local storage cleanup and chat box appearance upon specific quiz events .

The simulation of mouse clicks in the script is achieved through the 'simulateMouseClick' function, which dispatches 'MouseEvents' on target nodes. Depending on the input type ('on' or 'off'), these events trigger 'mouseover' or 'mouseout' actions, respectively. This logic emulates the user hovering over map elements, facilitating automated interaction without physical user input. This feature assists users in selecting map-related objects programmatically, enhancing efficiency in game scenarios where quick interaction with the map is crucial .

The hover mode in the BR Butler UI script is managed through a MutationObserver that checks if elements with the class 'active' and 'brShowEntry' are present. If found, the observer triggers a click on these elements. This mode can be toggled on and off using the 'toggleHoverMode' function, which checks the current state of hover mode stored in local storage under 'brHoverMode'. If hover mode is off, 'turnOnHoverMode' is invoked, which in turn activates the MutationObserver. A message is sent to the game chat indicating the mode's status. The toggle is only applicable when elements in the map content are visible .

The methodology for formatting and managing pick data in team contexts involves creating a structured string of picks using 'formatPicksToSend', which concatenates pick names from local storage, stripping any correct or incorrect markers. This formatted string is then posted to a server, where a unique code is generated for sharing among team members. Team members can retrieve and add these picks to their local storage using the 'getPicksFromCloud' function, which parses the received data and updates their chat box and local storage. This system allows for seamless sharing and synchronizing of pick data within teams, thus enabling cohesive strategy development .

You might also like