您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Extends player appearance editor functionality
// ==UserScript== // @name CarManiac's Improved Color Picker // @namespace http://tampermonkey.net/ // @version v1.40 // @description Extends player appearance editor functionality // @author CarManiac // @run-at document-idle // @license MIT // @match https://heav.io/game.html // @match https://hitbox.io/game.html // @match https://heav.io/game2.html // @match https://hitbox.io/game2.html // @match https://hitbox.io/game-beta.html // @icon https://www.google.com/s2/favicons?sz=64&domain=heav.io // @grant none // ==/UserScript== const style = document.createElement("style"); style.textContent = ` button:hover, .crossButton:hover { background-color: #5c85b4 !important; } `; document.head.appendChild(style); const targetImage = 'graphics/ui/hitbox.svg'; const newImageSrc = 'https://i.ibb.co/F5RLpmx/hitbox-1.png'; const images = document.querySelectorAll(`img[src="${targetImage}"]`); images.forEach(img => { const overlayImage = document.createElement('img'); overlayImage.src = newImageSrc; overlayImage.style.position = 'absolute'; overlayImage.style.left = img.offsetLeft + 'px'; overlayImage.style.top = img.offsetTop + 'px'; overlayImage.style.width = img.width + 'px'; overlayImage.style.height = img.height + 'px'; overlayImage.style.pointerEvents = 'none'; img.parentNode.appendChild(overlayImage); }); const originalSend = window.WebSocket.prototype.send; let WSS = 0; window.WebSocket.prototype.send = async function(args) { if (this.url && this.url.includes("peer")) { return; } if (this.url.includes("/socket.io/?EIO=3&transport=websocket&sid=")) { if (typeof args === "string") { if (!WSS) { WSS = this; } } } return originalSend.call(this, args); }; const iroScript = document.createElement("script"); iroScript.src = "https://unpkg.com/@jaames/iro/dist/iro.min.js"; document.head.appendChild(iroScript); const savedColors = JSON.parse(localStorage.getItem('savedColors')) || []; let colorPickerContainer; let deletionMode = false; function hexToDecimal(hex) { if (hex.startsWith("#")) hex = hex.slice(1); return parseInt(hex, 16); } function rgbToDecimal(rgb) { const rgbValues = rgb.match(/\d+/g); return rgbValues.reduce((acc, val) => (acc << 8) + parseInt(val), 0); } function createColorInput() { if (colorPickerContainer) return; colorPickerContainer = document.createElement("div"); colorPickerContainer.id = "colorPickerContainer"; colorPickerContainer.style.cssText = "background-color: rgb(37, 38, 42); border-radius: 7px; color: rgb(235, 235, 235); display: flex; flex-direction: column; font-family: 'Bai Jamjuree', sans-serif; position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%); padding: 10px; width: 300px;"; const crossButton = document.createElement("div"); crossButton.className = "crossButton"; crossButton.style.cssText = ` background-color: rgb(74, 122, 177); background-image: url(https://hitbox.io/graphics/ui/close.svg); background-position: 50% 50%; background-repeat: no-repeat; border-radius: 20px; color: rgb(235, 235, 235); cursor: pointer; display: block; height: 25.9929px; position: absolute; right: -9px; top: -9px; width: 25.9929px; `; crossButton.addEventListener("click", closeBoth); const label = document.createElement("label"); label.textContent = "Select Color"; label.style.cssText = "color: rgb(235, 235, 235); font-weight: bold; font-size: 15px; margin-bottom: 10px;"; const colorWheelContainer = document.createElement("div"); colorWheelContainer.style.textAlign = "center"; const colorInput = document.createElement("input"); colorInput.type = "text"; colorInput.style.cssText = ` background-color: rgb(100, 100, 100); color: white; padding: 5px; border: 1px solid #ccc; border-radius: 5px; margin-top: 5px; font-family: 'Bai Jamjuree', sans-serif; `; colorInput.placeholder = "Hex (#RRGGBB) or rgb(R, G, B)"; const buttonContainer = document.createElement("div"); buttonContainer.style.display = "flex"; buttonContainer.style.justifyContent = "space-between"; buttonContainer.style.marginTop = "10px"; const applyButton = createButton("APPLY COLOR", "margin: 5px;"); const randomButton = createButton("RANDOM COLOR", "margin: 5px;"); const saveButton = createButton("SAVE COLOR", "margin: 5px;"); const feedbackMessage = document.createElement("div"); feedbackMessage.style.cssText = "margin-top: 10px; color: green; font-size: 15px;"; const savedColorsContainer = document.createElement("div"); savedColorsContainer.style.cssText = "margin-top: 10px; padding-top: 10px; border-top: 1px solid #ccc; color: rgb(235, 235, 235);"; const savedColorsTitle = document.createElement("h4"); savedColorsTitle.textContent = "Saved Colors"; savedColorsTitle.style.cssText = "margin-bottom: 10px; font-size: 14px;"; const savedColorsList = document.createElement("div"); savedColorsList.style.display = "flex"; savedColorsList.style.flexWrap = "wrap"; savedColorsList.style.gap = "10px"; const deleteButton = createButton("DELETE COLORS", "margin-top: 10px; width: 100px;"); colorPickerContainer.append(crossButton, label, colorWheelContainer, colorInput, buttonContainer, saveButton, feedbackMessage, savedColorsContainer); buttonContainer.append(applyButton, randomButton); savedColorsContainer.append(savedColorsTitle, savedColorsList, deleteButton); document.body.appendChild(colorPickerContainer); displaySavedColors(); const colorWheel = new iro.ColorPicker(colorWheelContainer, { width: 225, color: "#ff0000" }); function getLuminance(hex) { let r = parseInt(hex.slice(1, 3), 16); let g = parseInt(hex.slice(3, 5), 16); let b = parseInt(hex.slice(5, 7), 16); return (0.299 * r + 0.587 * g + 0.114 * b) / 255; } colorWheel.on('color:change', function(color) { const hexColor = color.hexString; colorInput.value = hexColor; colorInput.style.backgroundColor = hexColor; const luminance = getLuminance(hexColor); colorInput.style.color = luminance > 0.5 ? 'black' : 'white'; }); saveButton.addEventListener("click", () => saveColor(colorInput.value.trim(), feedbackMessage, savedColorsList)); applyButton.addEventListener("click", () => applyColor(colorInput.value.trim(), feedbackMessage)); randomButton.addEventListener("click", () => generateRandomColor(colorInput, feedbackMessage)); deleteButton.addEventListener("click", () => toggleDeletionMode()); function createButton(text, additionalStyles = "") { const button = document.createElement("button"); button.textContent = text; button.style.cssText = `padding: 5px; border: none; font-family: 'Bai Jamjuree', sans-serif; border-radius: 2px; cursor: pointer; color: rgb(235, 235, 235); background-color: rgb(74, 122, 177); ${additionalStyles}`; return button; } function displaySavedColors() { savedColorsList.innerHTML = ''; savedColors.forEach(color => { const colorBox = document.createElement("div"); colorBox.style.cssText = `width: 30px; height: 30px; background-color: ${color}; cursor: pointer; border: 1px solid #ccc; border-radius: 3px;`; colorBox.addEventListener("click", () => { if (deletionMode) { confirmDeletion(color); } else { colorInput.value = color; colorInput.style.backgroundColor = color; const luminance = getLuminance(color); colorInput.style.color = luminance > 0.5 ? 'black' : 'white'; feedbackMessage.textContent = `Color selected: ${color}`; feedbackMessage.style.color = "green"; } }); savedColorsList.appendChild(colorBox); }); } function saveColor(colorValue, feedback, list) { if (colorValue && !savedColors.includes(colorValue)) { savedColors.push(colorValue); localStorage.setItem('savedColors', JSON.stringify(savedColors)); displaySavedColors(); feedback.textContent = `Color ${colorValue} saved!`; feedback.style.color = "green"; } else { feedback.textContent = "Color is either empty or already saved!"; feedback.style.color = "red"; } } function applyColor(colorValue, feedback) { let decimalValue; if (colorValue.startsWith("#")) { decimalValue = hexToDecimal(colorValue); } else if (colorValue.startsWith("rgb")) { decimalValue = rgbToDecimal(colorValue); } else { feedback.textContent = "Please enter a valid color!"; feedback.style.color = "red"; return; } feedback.textContent = `Color applied successfully: ${colorValue}`; feedback.style.color = "green"; localStorage.setItem("basic_col_1", decimalValue); if (WSS) { WSS.send(`42[1,[40,{"1": ${decimalValue}}]]`); } } function generateRandomColor(input, feedback) { const randomColor = "#" + Math.floor(Math.random() * 16777215).toString(16); input.value = randomColor; input.style.backgroundColor = randomColor; const luminance = getLuminance(randomColor); input.style.color = luminance > 0.5 ? 'black' : 'white'; feedback.textContent = `Random color generated: ${randomColor}`; feedback.style.color = "green"; } function toggleDeletionMode() { if (deletionMode) { deletionMode = false; deleteButton.style.backgroundColor = "rgb(74, 122, 177)"; deleteButton.textContent = "DELETE COLORS"; deleteButton.classList.remove("cancel-delete-hover"); } else { if (localStorage.getItem("noAskAgain") !== "true") { createConfirmationPopup(() => { deletionMode = true; deleteButton.style.backgroundColor = "rgb(255, 0, 0)"; deleteButton.textContent = "CANCEL DELETE"; deleteButton.classList.add("cancel-delete-hover"); }); } else { deletionMode = true; deleteButton.style.backgroundColor = "rgb(255, 0, 0)"; deleteButton.textContent = "CANCEL DELETE"; deleteButton.classList.add("cancel-delete-hover"); } } } const style = document.createElement('style'); style.textContent = ` .cancel-delete-hover:hover { background-color: #ff171b !important; } `; document.head.appendChild(style); function confirmDeletion(color) { const index = savedColors.indexOf(color); if (index > -1) { savedColors.splice(index, 1); localStorage.setItem('savedColors', JSON.stringify(savedColors)); displaySavedColors(); } } function createConfirmationPopup(callback) { const popupContainer = document.createElement("div"); popupContainer.style.cssText = "position: fixed; left: 50%; top: 50%; transform: translate(-50%, -50%); background: rgba(0, 0, 0, 0.8); color: white; padding: 20px; border-radius: 10px; z-index: 1000;"; const message = document.createElement("p"); message.textContent = "Are you sure you want to enable deletion mode?"; const checkbox = document.createElement("input"); checkbox.type = "checkbox"; checkbox.id = "noAskAgain"; const checkboxLabel = document.createElement("label"); checkboxLabel.setAttribute("for", "noAskAgain"); checkboxLabel.textContent = "Don't ask again"; const buttonContainer = document.createElement("div"); buttonContainer.style.display = "flex"; buttonContainer.style.justifyContent = "space-between"; const cancelButton = createButton("CANCEL", "margin-right: 5px; background-color: red;"); const confirmButton = createButton("CONFIRM"); buttonContainer.append(cancelButton, confirmButton); popupContainer.append(message, checkboxLabel, checkbox, buttonContainer); document.body.appendChild(popupContainer); cancelButton.addEventListener("click", () => { popupContainer.remove(); }); confirmButton.addEventListener("click", () => { if (checkbox.checked) { localStorage.setItem("noAskAgain", "true"); } callback(); popupContainer.remove(); }); } } const appearancePageObserver = new MutationObserver(() => { const appearancePage = document.querySelector('.cosmeticWindow'); if (appearancePage) { createColorInput(); } else { closeBoth(); } }); function checkAppearancePage() { appearancePageObserver.observe(document.body, { childList: true, subtree: true }); } function closeColorPicker() { if (colorPickerContainer) { colorPickerContainer.remove(); colorPickerContainer = null; } } function closeBoth() { closeColorPicker(); const cosmeticWindow = document.querySelector('.cosmeticWindow'); if (cosmeticWindow) { cosmeticWindow.remove(); } const blockerContainer = document.querySelector('.blockerContainer'); if (blockerContainer) { blockerContainer.remove(); } } checkAppearancePage();