您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Scroll to zoom in/out, items filtered and highlighted based on rarity and type.
// ==UserScript== // @name Cowz+ // @namespace namespace // @match *://cowz.io/* // @grant none // @version 1.2 // @author dsim // @description Scroll to zoom in/out, items filtered and highlighted based on rarity and type. // @license MIT // ==/UserScript== const brandColors = { 13: "hsl(250 33.9% 49.8%)", 14: "hsl(250 33.9% 49.8%)", 15: "hsl(250 33.9% 49.8%)", 16: "hsl(250 33.9% 49.8%)", 17: "hsl(285 100% 47.1%)", 18: "hsl(285 100% 47.1%)", 19: "hsl(285 100% 47.1%)", 20: "hsl(285 100% 47.1%)", 21: "hsl(285 100% 47.1%)", 22: "hsl(333 100% 47.1%)", 23: "hsl(333 100% 47.1%)", 24: "hsl(333 100% 47.1%)", 25: "hsl(333 100% 47.1%)", 26: "hsl(333 100% 47.1%)" }; let c, ctx; let menuVisible = false; let settings = { darkMode: false, filter: true, highlight: true }; function createElement(tag, styles, text) { const element = document.createElement(tag); Object.assign(element.style, styles); if (text) element.textContent = text; return element; } const menu = createElement('div', { position: 'fixed', top: '15%', left: '20px', background: 'rgba(0,0,0,0.7)', padding: '20px 30px', minWidth: '200px', textAlign: 'center', color: 'white', zIndex: 10001, display: 'none' }); function createButton(text, onClick) { const button = createElement('div', { padding: '12px 20px', fontSize: '16px', color: '#999999', userSelect: 'none' }); let isHovering = false; function updateButton() { const isToggleButton = text !== 'Close'; const settingKey = text === 'Dark Mode' ? 'darkMode' : text === 'Item Filter' ? 'filter' : text === 'Item Highlight' ? 'highlight' : text.toLowerCase().replace(' ', ''); if (isToggleButton) { button.textContent = `${text}: ${settings[settingKey] ? 'ON' : 'OFF'}`; } else { button.textContent = text; } button.style.color = isHovering ? 'white' : '#999999'; } button.onclick = () => { onClick(); if (text !== 'Close') updateButton(); }; button.onmouseenter = () => { isHovering = true; button.style.color = 'white'; }; button.onmouseleave = () => { isHovering = false; button.style.color = '#999999'; }; updateButton(); return button; } function createSeparator() { return createElement('div', { height: '2px', background: 'linear-gradient(to right, transparent, #666666, transparent)', margin: '8px 5px' }); } function toggleSetting(settingName) { settings[settingName] = !settings[settingName]; window.dispatchEvent(new CustomEvent(`${settingName}Toggle`, { detail: { enabled: settings[settingName] } })); } function showMenu() { menuVisible = true; menu.style.display = 'block'; } function hideMenu() { menuVisible = false; menu.style.display = 'none'; } function toggleMenu() { menuVisible ? hideMenu() : showMenu(); } let currentZoom = null; let targetZoom = null; let hasUserScrolled = false; const minZoom = 0.00005; const maxZoom = 800; const zoomSpeed = 0.3; function init() { const gameCanvas = document.getElementById("main_canvas"); if (gameCanvas) { c = document.createElement("canvas"); c.style.position = "absolute"; c.style.top = "0"; c.style.left = "0"; c.style.pointerEvents = "none"; c.style.zIndex = "9999"; c.width = gameCanvas.width; c.height = gameCanvas.height; ctx = c.getContext("2d"); if (window.game && window.game.visibility) { window.game.visibility.render = function() {}; } if (ctx) { gameCanvas.parentNode.insertBefore(c, gameCanvas.nextSibling); menu.appendChild(createElement('div', { fontSize: '18px', fontWeight: 'bold', marginBottom: '20px' }, 'Cowz+')); ['Item Filter', 'Item Highlight', 'Dark Mode'].forEach(buttonText => { const settingKey = buttonText === 'Dark Mode' ? 'darkMode' : buttonText === 'Item Filter' ? 'filter' : buttonText === 'Item Highlight' ? 'highlight' : buttonText.toLowerCase().replace(' ', ''); menu.appendChild(createButton(buttonText, () => toggleSetting(settingKey))); menu.appendChild(createSeparator()); }); menu.appendChild(createButton('Close', hideMenu)); document.body.appendChild(menu); menu.addEventListener('click', (event) => { event.stopPropagation(); }); menu.addEventListener('mousedown', (event) => { event.stopPropagation(); }); menu.addEventListener('mouseup', (event) => { event.stopPropagation(); }); document.addEventListener('keydown', (event) => { if (event.key.toLowerCase() === 'd' && !event.ctrlKey && !event.altKey && !event.shiftKey) { const activeElement = document.activeElement; const isTyping = activeElement && ( activeElement.tagName === 'INPUT' || activeElement.tagName === 'TEXTAREA' || activeElement.contentEditable === 'true' ); if (!isTyping) { event.preventDefault(); toggleMenu(); } } else if (event.key === 'Escape' && menuVisible) { hideMenu(); } }); window.addEventListener('darkModeToggle', (e) => { toggleDarkOverlay(e.detail.enabled); }); window.addEventListener('filterToggle', (e) => { toggleFilter(e.detail.enabled); }); window.addEventListener('highlightToggle', (e) => { toggleHighlight(e.detail.enabled); }); if (window.game && window.game.update) { const game = window.game; const originalUpdate = game.update; if (game.camera) { Object.defineProperty(game.camera, 'z', { get: function() { return hasUserScrolled ? (currentZoom || 1) : this._z || 1; }, set: function(value) { if (hasUserScrolled) { return; } this._z = value; if (currentZoom === null) { currentZoom = value; targetZoom = value; } } }); game.camera._z = game.camera.z; window.zoomOverrideCount = 0; } game.update = function(deltaTime) { originalUpdate.call(this, deltaTime); run(); }; interceptLmbCommand(); } else { setTimeout(init, 100); return; } } else { setTimeout(init, 100); } } else { setTimeout(init, 100); } } function handleWheel(event) { event.preventDefault(); if (!hasUserScrolled) { hasUserScrolled = true; } if (event.deltaY > 0) { targetZoom = Math.min(maxZoom, targetZoom + zoomSpeed); } else { targetZoom = Math.max(minZoom, targetZoom - zoomSpeed); } } document.addEventListener('wheel', handleWheel, { passive: false }); function renderItem(item, renderData) { if (renderData.hidden) { setHidden(item); return; } setVisible(item); if (renderData.highlighted) { const camera = window.game.camera; const worldX = item.pos.x; const worldY = item.pos.y; const screenX = 0.5 * window.innerWidth - (camera.pos.x - worldX) / camera.z * camera.ppu; const screenY = 0.5 * window.innerHeight + (camera.pos.y - worldY) / camera.z * camera.ppu; ctx.globalAlpha = 0.5; const itemScale = 0.75 / camera.z; const highlightSize = itemScale * 120; ctx.fillStyle = renderData.highlightColor; ctx.fillRect(screenX - highlightSize/2, screenY - highlightSize/2, highlightSize, highlightSize); } } function setHidden(item) { if (item.container.visible) { item.container.visible = false; } if (item.nameText.visible) { item.nameText.visible = false; } if (item.itemEmitter) { if (item.itemEmitter.enabled) { item.itemEmitter.enabled = false; } } } function setVisible(item) { if (!item.container.visible) { item.container.visible = true; } if (!item.nameText.visible) { item.nameText.visible = true; } if (item.itemEmitter) { if (!item.itemEmitter.enabled) { item.itemEmitter.enabled = true; } } } let filterEnabled = true; let highlightEnabled = true; function computeRenderData(item) { const itemData = item.item; const baseType = itemData.baseType; const type = itemData.type; const rarity = itemData.rarity; const lvlReq = itemData.lvlReq; const flags = itemData.flags; let renderData = { hidden: false, highlighted: false, highlightColor: null, id: itemData.itemId, idOld: itemData.itemIdOld }; if (!highlightEnabled && !filterEnabled) { return renderData; } else { if (baseType.startsWith("brand")) { let brandLevel = Number(baseType.match(/\d+$/)); if (brandLevel >= 13) { if (highlightEnabled) { renderData.highlighted = true; renderData.highlightColor = brandColors[brandLevel]; } } else if (filterEnabled && !(brandLevel === 5 || brandLevel === 6 || brandLevel === 8 || brandLevel === 9)) { renderData.hidden = true; } } else if (baseType.startsWith("jewel")) { if (rarity >= 3) { if (highlightEnabled) { renderData.highlighted = true; renderData.highlightColor = "hsl(11 100% 47.1%)"; } } else if (filterEnabled && rarity <= 1) { renderData.hidden = true; } } else if (baseType.endsWith("ring") || baseType.endsWith("amulet")) { if (rarity >= 3) { if (highlightEnabled) { renderData.highlighted = true; renderData.highlightColor = "hsl(21 100% 47.1%)"; } } else if (filterEnabled && rarity <= 1) { renderData.hidden = true; } } else if (baseType === "aburite") { if (highlightEnabled) { renderData.highlighted = true; renderData.highlightColor = "hsl(185 100% 61.5%)"; } } else if (baseType === "steak_cow_03") { if (highlightEnabled) { renderData.highlighted = true; renderData.highlightColor = "hsl(31 83.5% 47.9%)"; } } else if (baseType === "amber") { if (highlightEnabled) { renderData.highlighted = true; renderData.highlightColor = "orange"; } } else if (baseType === "bezoar") { if (highlightEnabled) { renderData.highlighted = true; renderData.highlightColor = "hsl(46 67% 41%)"; } } else if (type.startsWith("fat_king")) { if (highlightEnabled) { renderData.highlighted = true; renderData.highlightColor = "hsl(299 54.2% 51%)"; } } else if (baseType.startsWith("map")) { if (highlightEnabled) { if (Number(item.item.baseType.slice(-1)) >= 4) { renderData.highlighted = true; renderData.highlightColor = "hsl(275 43.5% 50%)"; } } } else if (type === "unq_tome_portal" || type === "unq_shepherd_codex" || type === "unq_skeleton_key") { if (highlightEnabled) { renderData.highlighted = true; renderData.highlightColor = "hsl(119 100% 51%)"; } } else if (baseType === "skill_orb_passive") { if (filterEnabled && lvlReq !== 17) { renderData.hidden = true; } } else if (baseType === "scroll_seven_hands") { if (highlightEnabled) { renderData.highlighted = true; renderData.highlightColor = "hsl(40 63.2% 47.8%)"; } } else if (baseType.endsWith("_03")) { if (rarity >= 3) { if (highlightEnabled) { renderData.highlighted = true; renderData.highlightColor = "red"; } } else if (rarity === 0) { if (flags >= 2) { if (highlightEnabled) { renderData.highlighted = true; renderData.highlightColor = "white"; } } } else if (filterEnabled) { renderData.hidden = true; } } else if (filterEnabled && rarity <= 2 && !(baseType === "scroll_focus" || baseType === "pearl" || baseType === "marrow")) { renderData.hidden = true; } } return renderData; } function renderItems() { ctx.clearRect(0, 0, c.width, c.height); ctx.globalAlpha = 0.5; let items = window.game.itemBarn.items.filter(item => item.entityActive); items.forEach(item => { if (!item._renderData || item.item.itemId !== item._renderData.id || item.item.itemIdOld !== item._renderData.idOld) { item._renderData = computeRenderData(item); } renderItem(item, item._renderData); }); ctx.globalAlpha = 1; } let darkOverlay = null; function createDarkOverlay() { if (!window.game || !window.game.renderer || !window.game.renderer.gameContainer) { return; } if (!darkOverlay) { let Graphics = null; if (window.game.map && window.game.map.groundGfx) { Graphics = window.game.map.groundGfx.constructor; } if (Graphics) { darkOverlay = new Graphics(); darkOverlay.beginFill(0x000000, 0.7); darkOverlay.drawRect(-10000, -10000, 20000, 20000); darkOverlay.endFill(); darkOverlay.zIndex = 0.5; darkOverlay.visible = false; window.game.renderer.gameContainer.addChildAt(darkOverlay, 0); } } } function toggleDarkOverlay(enabled) { if (darkOverlay) { darkOverlay.visible = enabled; } } function toggleFilter(enabled) { filterEnabled = enabled; if (window.game && window.game.itemBarn && window.game.itemBarn.items) { window.game.itemBarn.items.forEach(item => { if (item.entityActive) { item._renderData = computeRenderData(item); } }); } } function toggleHighlight(enabled) { highlightEnabled = enabled; if (window.game && window.game.itemBarn && window.game.itemBarn.items) { window.game.itemBarn.items.forEach(item => { if (item.entityActive) { item._renderData = computeRenderData(item); } }); } } function interceptLmbCommand() { if (!window.game || !window.game.selection) return; const originalGetGameLmbCommand = window.game.selection.getGameLmbCommand; window.game.selection.getGameLmbCommand = function(game) { const command = originalGetGameLmbCommand.call(this, game); if (command.targetEntityId && game.itemBarn && game.itemBarn.items) { const targetItem = game.itemBarn.items.find(item => item.entityId === command.targetEntityId && item.entityActive ); if (targetItem && targetItem._renderData && targetItem._renderData.hidden) { return { cmd: 1, targetPos: command.targetPos || {x: 0, y: 0}, lmbPressed: command.lmbPressed, setTarget: command.setTarget }; } } return command; }; } function run() { if (!window.game || !window.game.itemBarn || !window.game.itemBarn.items || !window.game.camera) { return; } createDarkOverlay(); if (currentZoom === null) { currentZoom = window.game.camera.z; targetZoom = window.game.camera.z; } if (hasUserScrolled) { const zoomDiff = targetZoom - currentZoom; if (Math.abs(zoomDiff) > 0.01) { currentZoom += zoomDiff * 0.1; } } else { currentZoom = window.game.camera.z; targetZoom = window.game.camera.z; } if (hasUserScrolled && currentZoom !== null) { window.game.camera._z = currentZoom; } if (window.game.selection.setTarget) { } renderItems(); } init();