// ==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();