您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
More Legible Font and custom color outlines for player names on honor bars. No API key required. Set your player ID manually for full reliability.
// ==UserScript== // @name Torn: More Legible Player Names With Custom Color Outlines // @namespace http://tampermonkey.net/ // @version 2 // @description More Legible Font and custom color outlines for player names on honor bars. No API key required. Set your player ID manually for full reliability. // @author Gingerbeardman // @match https://www.torn.com/* // @grant none // @license GNU GPLv3 // ==/UserScript== (function () { 'use strict'; const MY_PLAYER_ID = 'USER ID #'; // ← Your player ID here const CONFIG_KEY = 'mlpn-config'; const COLOR_OPTIONS = [ { name: 'Black (Default)', value: '#000000' }, { name: 'Red', value: '#ff4d4d' }, { name: 'Blue', value: '#310AF5' }, { name: 'Green', value: '#3B9932' }, { name: 'Orange', value: '#ff9c40' }, { name: 'Purple', value: '#c080ff' }, { name: 'Yellow', value: '#f5d142' }, { name: 'Pink', value: '#ff69b4' }, { name: 'Teal', value: '#00d9c0' }, { name: 'White', value: '#ffffff' }, { name: 'Custom…', value: 'custom' } ]; const loadFont = () => { const link = document.createElement('link'); link.href = 'https://fonts.googleapis.com/css2?family=Manrope:wght@700&display=swap'; link.rel = 'stylesheet'; document.head.appendChild(link); }; const injectStyles = () => { const style = document.createElement('style'); style.textContent = COLOR_OPTIONS.filter(c => c.value !== 'custom').map(c => { const hex = c.value.replace('#', ''); return `.mlpn-color-${hex} .custom-honor-text { text-shadow: -1px -1px 0 ${c.value}, 1px -1px 0 ${c.value}, -1px 1px 0 ${c.value}, 1px 1px 0 ${c.value} !important; }`; }).join('\n') + ` .custom-honor-text { font-family: 'Manrope', sans-serif !important; font-weight: 700 !important; color: white !important; text-transform: uppercase !important; letter-spacing: 0.5px !important; pointer-events: none !important; position: absolute !important; top: 50%; left: 0; transform: translateY(-50%); width: 100% !important; display: flex !important; align-items: center; justify-content: center; text-align: center !important; line-height: 1 !important; margin: 0 !important; padding: 0 !important; z-index: 10 !important; } .honor-text-svg { display: none !important; } .mlpn-panel { position: absolute; top: 50px; left: 50%; transform: translateX(-50%); background: #222; color: white; border: 1px solid #444; padding: 12px; z-index: 99999; font-size: 14px; border-radius: 6px; width: max-content; } .mlpn-panel label { display: block; margin-top: 10px; } .mlpn-button { background: #339CFF; color: white; border: none; padding: 6px 10px; font-weight: bold; border-radius: 4px; cursor: pointer; margin-top: 10px; } .mlpn-note { font-size: 12px; margin-top: 6px; color: #aaa; } `; document.head.appendChild(style); }; const getConfig = () => JSON.parse(localStorage.getItem(CONFIG_KEY) || '{}'); const saveConfig = config => localStorage.setItem(CONFIG_KEY, JSON.stringify(config)); const createColorDropdown = (id, selectedValue) => { const select = document.createElement('select'); select.id = id; COLOR_OPTIONS.forEach(c => { const opt = document.createElement('option'); opt.value = c.value; opt.textContent = c.name; select.appendChild(opt); }); select.value = COLOR_OPTIONS.some(c => c.value === selectedValue) ? selectedValue : 'custom'; return select; }; const showSettingsPanel = (isOwn, playerId) => { const config = getConfig(); const panel = document.createElement('div'); panel.id = 'mlpn-panel'; panel.className = 'mlpn-panel'; const closeBtn = document.createElement('button'); closeBtn.className = 'mlpn-button'; closeBtn.textContent = 'Done'; closeBtn.onclick = () => panel.remove(); if (isOwn) { panel.innerHTML = ` <label>Font Size: <input id="mlpn-font-size" type="number" min="8" max="24" value="${config.fontSize || 12}" /> </label> <label>Color for Your Name:</label> `; const dropdown = createColorDropdown('mlpn-my-color', config.myColor || '#000000'); const customInput = document.createElement('input'); customInput.id = 'mlpn-my-custom'; customInput.placeholder = '#hex'; customInput.style.display = dropdown.value === 'custom' ? 'block' : 'none'; customInput.value = config.myColor?.startsWith('#') ? config.myColor : ''; dropdown.onchange = () => { customInput.style.display = dropdown.value === 'custom' ? 'block' : 'none'; config.myColor = dropdown.value === 'custom' ? customInput.value : dropdown.value; saveConfig(config); }; customInput.oninput = () => { config.myColor = customInput.value; saveConfig(config); }; const fontInput = panel.querySelector('#mlpn-font-size'); fontInput.oninput = () => { config.fontSize = parseInt(fontInput.value); saveConfig(config); }; document.body.appendChild(panel); panel.appendChild(dropdown); panel.appendChild(customInput); } else { panel.innerHTML = `<label>Assign a color to this player's name:</label>`; const dropdown = createColorDropdown('mlpn-other-color', config.players?.[playerId] || '#000000'); const customInput = document.createElement('input'); customInput.id = 'mlpn-other-custom'; customInput.placeholder = '#hex'; customInput.style.display = dropdown.value === 'custom' ? 'block' : 'none'; customInput.value = config.players?.[playerId]?.startsWith('#') ? config.players[playerId] : ''; dropdown.onchange = () => { if (!config.players) config.players = {}; customInput.style.display = dropdown.value === 'custom' ? 'block' : 'none'; config.players[playerId] = dropdown.value === 'custom' ? customInput.value : dropdown.value; saveConfig(config); }; customInput.oninput = () => { if (!config.players) config.players = {}; config.players[playerId] = customInput.value; saveConfig(config); }; document.body.appendChild(panel); panel.appendChild(dropdown); panel.appendChild(customInput); } const note = document.createElement('div'); note.className = 'mlpn-note'; note.textContent = 'Refresh the page to apply settings.'; panel.appendChild(note); panel.appendChild(closeBtn); }; const getProfileIdFromUrl = () => { const match = window.location.href.match(/profiles\.php\?XID=(\d+)/); return match ? match[1] : null; }; const applyHonorStyles = () => { const config = getConfig(); const fontSize = parseInt(config.fontSize) || 12; const profileId = getProfileIdFromUrl(); document.querySelectorAll('.honor-text-wrap').forEach(wrap => { if (wrap.querySelector('.custom-honor-text')) return; const anchor = wrap.closest('a[href*="XID="]'); let playerId = null; if (anchor) { const match = anchor.href.match(/XID=(\d+)/); if (match) playerId = match[1]; } else if (profileId) { playerId = profileId; // Fallback for profile pages } const text = wrap.getAttribute('data-title') || wrap.getAttribute('aria-label') || wrap.innerText || ''; const cleaned = text.trim().toUpperCase(); if (!cleaned) return; let color = '#000000'; if (playerId === MY_PLAYER_ID && config.myColor) { color = config.myColor; } else if (config.players?.[playerId]) { color = config.players[playerId]; } const colorClass = `mlpn-color-${color.replace('#', '')}`; wrap.classList.add(colorClass); if (fontSize > 12) wrap.style.height = `${fontSize + 6}px`; const div = document.createElement('div'); div.className = 'custom-honor-text'; div.style.fontSize = `${fontSize}px`; div.textContent = cleaned; wrap.appendChild(div); }); }; const injectSettingsButton = (isSelfProfile, profileId) => { if (document.getElementById('mlpn-settings-btn')) return; const target = document.querySelector('.content-title'); if (!target) return; const btn = document.createElement('button'); btn.id = 'mlpn-settings-btn'; btn.className = 'mlpn-button'; btn.textContent = 'Custom Player Names'; btn.onclick = () => showSettingsPanel(isSelfProfile, profileId); target.appendChild(btn); }; const init = () => { const profileId = getProfileIdFromUrl(); if (profileId) { injectSettingsButton(profileId === MY_PLAYER_ID, profileId); } applyHonorStyles(); new MutationObserver(applyHonorStyles).observe(document.body, { childList: true, subtree: true }); }; loadFont(); injectStyles(); init(); })();