您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Adds better Visuals to Sploop.io! Such Item effects, perfect hitbox, shadows, footsteps, weapon range, and more!
// ==UserScript== // @name Enhanced Visuals: improves your visuals making the experience better! // @version v-3.5 // @description Adds better Visuals to Sploop.io! Such Item effects, perfect hitbox, shadows, footsteps, weapon range, and more! // @namespace EHD // @license All Rights Reserved // @author Cubic Flex [CF] // @match *://sploop.io/ // @grant none // @icon https://cdn.glitch.global/499d2ba6-cd57-4e5f-8b56-5557baa5b3a0/EHD%20Visuals.png?v=1709777562902 // ==/UserScript== /*! * Enhanced Visuals [*Free Version] v3.5.1 * https://discord.gg/aZGuQmrm8z * * Auto save features * Mouse over for tooltips (feature description) * Hold click to settings menu * * More info at: * https://io-mods.glitch.me/ * * Made By: Cubic Flex [CF] | 10/11/2024 (mmddyy) */ //[=]=> Util functions class MouseManager { constructor() { this.x = 0; this.y = 0; this.resize(); } listeners() { window.addEventListener('mousemove', this.move.bind(this)); window.addEventListener('resize', this.resize.bind(this)); } resize() { this.width = window.innerWidth; this.height = window.innerHeight; this.update(); } move(e) { this.x = e.clientX; this.y = e.clientY; this.update(); } update() { this.angle = Math.atan2(this.y - this.height / 2, this.x - this.width / 2); } } class Img extends Image { constructor(src, width = 150, height = 150) { super(width, height); this.src = src; } } class Utils { static distance(player1, player2) { return Math.sqrt(Math.pow(player2.y - player1.y, 2) + Math.pow(player2.x - player1.x, 2)); } static lerp(start, end, amt) { return start + (end - start) * amt; } static try_parse(STRING) { try { return JSON.parse(STRING); } catch { return 'Failed to PARSE' } } static ls_get(key) { const got = localStorage[key]; return got ? this.try_parse(got) : false; } static ls_set(key, value) { localStorage[key] = typeof value === 'string' ? value : JSON.stringify(value); } } class Tooltip { static show(id, title) { const TIP = document.querySelector('#tooltip-menu'); const feature = All_features[id]; TIP.style.opacity = '1'; TIP.innerHTML = title || feature.info; TIP.style.left = Mouse.x + 'px'; TIP.style.top = Mouse.y + 'px'; } static hide() { const TIP = document.querySelector('#tooltip-menu'); TIP.style.opacity = '0'; } } //[=]=> Variables def. const server = { request_received: 17, entity_spawned: 32, items_upgrade: 2, items_count: 36, ping_update: 15, create_clan: 24, update_clan: 16, entity_chat: 30, leave_clan: 27, update_age: 8, item_hit: 29, upgrades: 14, spawned: 35, killed: 28, update: 20, died: 19 } const All_features = { colored_hp: { name: 'Colored HP', info: 'Colors your health bar', icon: 'palette-fill', enabled: true }, display_hp: { name: 'Display HP', info: 'Shows how many hp you have', icon: 'percent', enabled: true }, smooth_hp: { name: 'Smooth HP', info: 'Makes the health bar smoother', icon: 'water', enabled: true }, healing_effect: { name: 'Healing effect', info: 'Particles come out when heal', icon: 'apple', enabled: true }, weapon_range: { name: 'Weapon range', info: 'Shows weapon range', icon: 'opencollective', enabled: true }, hitbox: { name: 'Hitbox', info: 'Shows objects hitbox', icon: 'disc', enabled: false }, tornado_particles: { name: 'Tornado particles', info: 'Adds particles to tornadoes', icon: 'tornado', enabled: true }, footsteps: { name: 'Footsteps', info: 'Shows footsteps', icon: 'meta', enabled: true }, hide_ads: { name: 'Hide ads', info: 'Hide ads from the game menu', icon: 'eye-slash-fill', enabled: true }, night_mode: { name: 'Night mode', info: 'Night mode in sploop', icon: 'moon-stars-fill', enabled: false }, name_changer: { name: 'Name changer', info: 'Changes the mob names', icon: 'marker-tip', enabled: false } } const Features = Utils.ls_get('ehd_features') || { colored_hp: true, display_hp: true, smooth_hp: true, healing_effect: true, weapon_range: true, hitbox: false, tornado_particles: true, footsteps: true, hide_ads: true, night_mode: false, name_changer: false } const Settings = Utils.ls_get('ehd_settings') || { colored_hp: { mine_health: '#611a80', enemy_health: '#ae6999' }, weapon_range: { color: '#404040', cap: true }, hitbox: { color: '#50C878' }, footsteps: { land: false }, name_changers: { Wolf: 'Dog', Dragon: 'Boss', Duck: 'Quack' } } for (const key in All_features) { if (All_features.hasOwnProperty(key)) { if (!Features.hasOwnProperty(key)) { Features[key] = All_features[key].enabled; } } } const Vars = { loaded: false, entities: [], steps: [], heals: [], health: false, images: { cookie: new Img('https://sploop.io/img/entity/cookie.png'), apple: new Img('https://sploop.io/img/entity/apple.png') }, holds: {} } //[=]=> Menu functions class MenuManager { static parseID(id) { const value = id.children[1].innerHTML; return value.replace(/ /g, '_').toLowerCase(); } static parseSetting(element) { const value = element.parentElement.parentElement; const feature = value.parentElement.classList[1].replace(/settings\-/g, ''); return { feature, id: value.classList[2] } } static removeNC(element) { const name = element.parentElement.children[1].children[0]; const value = name.innerHTML; // Cleans the input values, adds it to the settings & close the "dropdown" delete Settings.name_changers[value]; // Then append the replacers again lm4o this.appendReplacer() } static addNC(element) { const inputs = element.parentElement.children[1].children; const name = inputs[0]; const replace = inputs[2]; if (name.value.trim().length < 1) return name.focus(); if (replace.value.trim().length < 1) return replace.focus(); // Cleans the input values, adds it to the settings & close the "dropdown" Settings.name_changers[name.value] = replace.value; document.querySelector('.button-plus').click() //MenuManager.toggleNewNC(this); name.value = ''; replace.value = ''; // Then append the replacers again lm4o this.appendReplacer() } static appendReplacer() { // Appends each name changer let string = ''; for (let name in Settings.name_changers) { const change = Settings.name_changers[name]; string += ` <div class="name-changer"> <i class="text bi bi-trash-fill" onclick="MenuManager.removeNC(this)"></i> <div class="name-changes"> <span>${name}</span> <i class="bi bi-arrow-left-right"></i> <span> ${change} </span> </div> </div> `; } document.querySelector('#name-changer-wrap').innerHTML = string; } static changeIcon(element, over, icon, remove) { setTimeout(() => { element.classList = `bi bi-${icon}` }, 1e3 / 60) } static toggleNewNC(element) { // Display / hide const edit = document.querySelectorAll('.edit'); const display = edit[0].style.display === 'flex' ? 'none' : 'flex'; const icon = edit[0].style.display === 'flex' ? 'bi bi-plus' : 'bi bi-dash'; edit.forEach(edit => { edit.style.display = display; }); // Focus the input const input = document.querySelector('.name-changes').children[0]; input.focus(); // Change this icon element.children[0].classList = icon; } static searchParent(element, parentClass) { function repeat(elem) { if (!elem || !elem.parentElement) { return null; } const contains = elem.parentElement.classList.contains(parentClass); if (contains) { return elem.parentElement; } else { return repeat(elem.parentElement); } } return repeat(element); } static enable(element, id, enabled, disabled) { const { feature } = this.parseSetting(element); const Setting = Settings[feature][id]; Settings[feature][id] = element.checked; if (!enabled) return; const parent = this.searchParent(element, 'switch') const icon = parent.querySelector('i'); icon.classList = `bi bi-${element.checked ? enabled : disabled}` } static changeColor(element) { // Remove all balls active class & add it to self const balls = element.parentElement.children; for (let ballID in balls) { const ball = balls[ballID]; if (ball.classList?.contains('color-ball')) { ball.classList.remove('active'); } } element.classList.add('active') // Now apply the color to the settings const { feature, id } = this.parseSetting(element); Settings[feature][id] = element.style.backgroundColor; } static colorPicker(element) { // First apply the color to the settings const { feature, id } = this.parseSetting(element); Settings[feature][id] = element.value; // Then change the color in the ball const balls = element.parentElement.parentElement.children[0].children; for (let ballID in balls) { const ball = balls[ballID]; if (ball.classList?.contains('picker-div')) { ball.style.backgroundColor = element.value ball.classList.add('active') } else if (ball.classList?.contains('color-ball')) { ball.classList.remove('active') } } // Make this element active } static ToggleToolTip(raw_id, hovering) { const id = this.parseID(raw_id); if (!hovering) { Tooltip.hide() return; } Tooltip.show(id); } static display(menu, toggle, trigger) { menu.style.display = toggle ? 'block' : 'none'; setTimeout(() => { trigger || this.s_opacity(menu, toggle, true); }, trigger ? 80 : 0); } static s_opacity(menu, toggle, trigger) { menu.style.opacity = toggle ? '1' : '0'; setTimeout(() => { trigger || this.display(menu, toggle, true); }, trigger ? 0 : 400); } static toggleSelector() { // frist change the text to select feture document.querySelector('.settings-icon').classList = `bi bi-sliders2 settings-icon`; document.querySelector('.settings-name').innerHTML = 'Select a feature'; // THEN open the selector andclose body document.querySelector('.settings-selector').style.display = 'flex'; document.querySelector('.settings-body').style.display = 'none'; } static toggleSettings(raw_id, toggle) { const id = toggle && this.parseID(raw_id); const menu = document.querySelector('#settings-menu'); toggle ? this.display(menu, toggle) : this.s_opacity(menu, toggle); if (!toggle) return; // ok if its opening then: append the name and info to the menu const { icon, name } = All_features[id]; document.querySelector('.settings-icon').classList = `bi bi-${icon} settings-icon`; document.querySelector('.settings-name').innerHTML = name; // First closes "all feature settings" div then open the settings div document.querySelector('.settings-selector').style.display = 'none'; document.querySelector('.settings-body').style.display = 'block'; // After open the div card, if it has a card then open the card if not open the error card kk const setting_divs = document.querySelectorAll('.setting'); const error = document.querySelector('.settings-undefined'); setting_divs.forEach(div => { div.style.display = 'none'; // also clsoes all the opened cards }) const setting = document.querySelector(`.settings-${id}`); (setting || error).style.display = 'block'; } static ToggleFeature(raw_id, holding) { if (holding) { Vars.holds[raw_id] = Date.now(); return; } // Handle MouseUp const date = Date.now() - Vars.holds[raw_id]; if (date > 200) { // Holding this.toggleSettings(raw_id, true) return; } const id = this.parseID(raw_id); Features[id] = !Features[id]; // Add the active class const setting = document.querySelector(`.setting-div-${id}`); const toggle = Features[id] ? 'add' : 'remove'; raw_id.classList[toggle]('active') setting.classList[toggle]('active') } static minimize(element) { const menu = document.querySelector('#ehd-menu'); const minimized = menu.style.width === '4.6vw'; element.style.rotate = !minimized ? '0deg' : '180deg'; // rotate the arrow menu.style.width = minimized ? '16vw' : '4.6vw'; // adjust width menu.classList[minimized ? 'remove' : 'add']('minimized'); // then just add / remove the minimized class } static opacity(element) { const checked = element.checked; const color = checked ? 'rgb(255 255 255 / .25)' : 'transparent'; document.querySelector('#ehd-menu').style.opacity = checked ? '.6' : '1'; document.querySelector('#transparency').parentElement.style.backgroundColor = color; } } //[=]=> Css ! const CSS = document.createElement('style'); CSS.innerHTML = ` @import url("https://cdn.jsdelivr.net/npm/[email protected]/font/bootstrap-icons.css"); :root { --main: #242527; --softer: #3a3b3d; --color: #dedee0; --gray: #a6a7a9; --light-gray: #3a3b3d; --text: url(img/ui/cursor-text.png) 16 0, text; --default: url(img/ui/cursor-default.png) 2 0, default; --pointer: url(img/ui/cursor-pointer.png) 6 0, pointer; --index: 100000000; } * { transition: all 0.4s ease; transition-duration: .4s /* lmao=? */ } @keyframes glow { 0% { box-shadow: 0 0 20px -1.1vw rgba(255, 255, 255, 0.9); } 50% { box-shadow: 0 0 40px -1.1vw rgba(255, 255, 255, 0.9); } 100% { box-shadow: 0 0 20px -1.1vw rgba(255, 255, 255, 0.9); } } @keyframes rotate { 0% { transform: scale(1) rotateY(0deg) } 50% { transform: scale(1.15) rotateY(180deg) } 100% { transform: scale(1) rotateY(0deg) } } @keyframes rotateDeg { 0% { rotate: 0deg } 50% { rotate: 360deg } 100% { rotate: 0deg } } .ehd_scrollBar::-webkit-scrollbar, .ehd_scrollBar *::-webkit-scrollbar { height: 7px; width: 7px; } .ehd_scrollBar::-webkit-scrollbar-track, .ehd_scrollBar *::-webkit-scrollbar-track { border-radius: 5px; background-color: transparent; } .ehd_scrollBar::-webkit-scrollbar-track:hover, .ehd_scrollBar *::-webkit-scrollbar-track:hover { background-color: #B8C0C2; } .ehd_scrollBar::-webkit-scrollbar-track:active, .ehd_scrollBar *::-webkit-scrollbar-track:active { background-color: #B8C0C2; } .ehd_scrollBar::-webkit-scrollbar-thumb, .ehd_scrollBar *::-webkit-scrollbar-thumb { border-radius: 5px; background-color: #5E5E5E; } .ehd_scrollBar::-webkit-scrollbar-thumb:hover, .ehd_scrollBar *::-webkit-scrollbar-thumb:hover { background-color: #474747; } .ehd_scrollBar::-webkit-scrollbar-thumb:active, .ehd_scrollBar *::-webkit-scrollbar-thumb:active { background-color: #7F7F7F; } #ehd-menu { overflow: hidden; background-color: var(--main); z-index: var(--index); position: fixed; left: 1.5vw; top: 1.5vw; width: 16vw; height: 32vw; border-radius: .7vw; display: flex; flex-direction: column; box-shadow: 0px 0px 6px 0px black } #ehd-menu.minimized .body { overflow: hidden /* idk, why can you scroll while minimized? no sense ig */ } #ehd-menu.minimized .checkbox, #ehd-menu.minimized span { font-size: 0vw; width: 0vw !important } #ehd-menu.minimized .menu-size { margin-left: 2.8vw } #ehd-menu div { width: 100%; } #ehd-menu .header { height: 16%; padding: 1vw; display: flex; flex-direction: row; justify-content: flex-start; align-items: center; } #ehd-menu .body { padding: 1vw; height: 60%; overflow: scroll; overflow-x: hidden } #ehd-menu .footer { border-top: 1px solid #47484a; padding: 1vw; height: max-content } .header img { width: 2.8vw; margin-right: .8vw; border-radius: 0.4vw } .header span { color: var(--color); } .header-holder { display: flex; flex-direction: column } .header-holder span { font-weight: 700; font-size: .9vw } .description { color: var(--gray) !important; font-size: .8vw !important } .menu-button { margin-bottom: .3vw; height: max-content; padding: 0.7vw; display: flex; flex-direction: row; align-items: center; text-align: left; color: var(--color); border-radius: 0.4vw; overflow: hidden } .menu-button:hover { background: rgb(255 255 255 / .05); } .menu-button.active { background: rgb(255 255 255 / .15); } .menu-button i, .menu-button span { margin-right: .7vw; font-weight: 600; font-size: 1.2vw } .menu-button span { font-size: 0.9vw } .menu-button, .menu-button * { cursor: var(--pointer); } .separator { display: flex; align-items: center; } .switch { display: flex; min-width: 2vw; justify-content: space-between; } .switch * { cursor: var(--pointer) } .switch input[type="checkbox"] { opacity: 0; position: fixed } .checkbox { display: block; width: 2.5vw !important; height: 1vw; border-radius: 20vw; background-color: white; } .switch .checkbox::before { content: ''; display: block; width: 0.8vw; height: 0.8vw; border-radius: 50%; margin: .1vw; background-color: var(--main); transition: margin-left 0.3s ease } .switch input[type="checkbox"]:checked + .checkbox::before { margin-left: 1.15vw } .menu-size { background-color: var(--light-gray); position: fixed; border-radius: 50%; width: 1.7vw !important; height: 1.7vw; margin-left: 14vw; display: flex; flex-direction: row; align-items: center; justify-content: center; font-weight: bolder; font-size: 1vw; cursor: var(--pointer); text-shadow: 0px 0px 1px white; box-shadow: 0px 0px 2px black; rotate: 180deg } .menu-size i { cursor: var(--pointer); color: white; } #tooltip-menu { position: fixed; top: 100px; left: 220px; pointer-events: none; background-color: #1d1e1f; color: white; font-family: 'Baloo Paaji'; font-weight: 300; z-index: calc(var(--index) + 10); border-radius: 0.4vw; height: 2.8vw; padding: 0.4vw 1vw; box-shadow: 0px 0px 6px var(--main); } #settings-menu, .night-card { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: radial-gradient(transparent, rgb(0 0 0 / .6)); pointer-events: none; z-index: calc(var(--index) - 1); } #settings-menu { display: none; opacity: 0; background: none; background-color: rgb(0 0 0 / .4); z-index: calc(var(--index) + 2); pointer-events: all } #settings-menu .container { display: flex; flex-direction: column; width: 30%; height: 60%; margin: 10% auto; background: var(--main); border-radius: .7vw; padding: 1.5vw; box-shadow: 0px 0px 6px 0px var(--main) } #main-content { width: max-content } .settings-header { display: flex; flex-direction: row; justify-content: space-between; margin-bottom: 0.5vw } .settings-header * { font-size: 2.7vw; font-weight: 700; color: var(--color); } .feature-container { display: flex; flex-direction: column; justify-content: center; } .feature-container * { font-size: 1.3vw; } .settings-button { cursor: var(--pointer) } .settings-button:hover { animation: rotateDeg 1.5s ease forwards } .actual-feature { /* Same as desc but diff font size */ color: var(--gray) !important; font-size: 1vw !important } .settings-body, .settings-selector { width: 100%; height: 100%; background: #1d1d1d; padding: 1vw; border-radius: 0.4vw; overflow: scroll; overflow-x: hidden } .settings-body *, .settings-selector * { color: var(--color); font-weight: 600; font-size: 1.175vw; } .settings-selector { flex-direction: row; flex-wrap: wrap; justify-content: center; align-content: flex-start; } .settings-item { width: 4vw; height: 4vw; background: rgb(255 255 255 / .025); display: grid; align-items: center; justify-content: center; border-radius: 1vw; cursor: var(--pointer); margin: 1vw; } .settings-item:hover { background: rgb(255 255 255 / .25); border-radius: .6vw; } .settings-item.active { background: rgb(255 255 255 / .15); } .settings-item * { cursor: var(--pointer); font-size: 2vw } .color-ball { width: 1.5vw; height: 1.5vw; border-radius: 50%; margin: 0vw 0.6vw; cursor: var(--pointer); } .color-ball:hover { filter: brightness(.7); border-radius: 30% } .color-ball.active::before { transition: all 0.4s ease; content: ''; display: flex; width: 109%; height: 110%; border: 0.15vw solid rgb(255 255 255 / 0.25); border-radius: 50%; margin: -.22vw; } .color-ball.active:hover::before { filter: brightness(.7); border-radius: 30% } .picker-holder input[type="color"] { opacity: 0; position: fixed } .picker-color { cursor: var(--pointer); font-size: 1.5vw; margin-left: 1vw } .picker-text { color: var(--gray) !important; font-size: 1vw !important; } .color-picker { display: flex; justify-content: space-between; } .settings-hr { margin: 1vw 0vw; border: .025vw solid var(--main); } .checkbox-wrapper { flex-direction: row; justify-content: space-between; align-items: center; } .checkbox-wrapper i { margin-right: 1.5vw; font-size: 2.3vw; } .info-holder { display: flex; flex-direction: column; } .info-holder * { font-size: 1vw } .dropdown-div { display: flex; justify-content: space-between } .dropdown-div i { margin-right: .6vw; font-size: 1vw !important; color: var(--gray) !important; } .button-plus { cursor: var(--pointer); background-color: rgb(255 255 255 / .25);); border-radius: 50%; display: flex; flex-direction: row; justify-content: center; align-items: center; width: 1.5vw; height: 1.5vw; } .button-plus:hover { filter: opacity(0.7) } .button-plus:active { filter: opacity(1.2) } .button-plus i { cursor: var(--pointer); margin: 0px !important; color: white !important; font-size: 1.3vw; } .name-changer { display: flex; flex-direction: row; justify-content: space-between; align-items: center; margin-bottom: 1vw } .name-changer .text { font-size: 2.1vw; color: var(--gray) !important; cursor: var(--pointer); margin-right: 1vw } .name-changes { justify-content: space-between; display: flex; width: 100%; background: #161616; padding: 0.6vw 1vw; border-radius: 0.4vw; flex-direction: row; justify-content: center; text-align: center; } .name-changes i { margin: 0vw 1vw } .name-changes > :first-child { width: 45%; } .name-changes > :nth-child(2) { width: 10%; } .name-changes > :nth-child(3) { width: 45%; } .name-edit { text-align: center; outline: none; user-select: none; background-color: inherit; border: 0px; cursor: var(--text); } .edit { margin-bottom: 1vw; display: none } .edit .name-changes { animation: glow 1s forwards; box-shadow: 0 0 20px -1.1vw rgb(255 255 255 / .9) } .edit span { font-size: 0.8vw; margin-bottom: 1vw } .risk { margin-right: .5vw; color: #E74C3C } .icon-change:hover { animation: rotate 1s infinite } .icon-change { animation: rotate 1s forwards } .name-changer i:hover { filter: opacity(.5) } `; //[=]=> Menu append & title const HUD = document.createElement('div'); HUD.id = 'ehd-menu'; HUD.classList = 'ehd_scrollBar'; HUD.innerHTML = ` <div class="header"> <img src="https://cdn.glitch.global/499d2ba6-cd57-4e5f-8b56-5557baa5b3a0/EHD%20Visuals.png" alt="EHD Mod Icon" draggable="false"> <div class="header-holder"> <span> EHD [Free Version] </span> <span class="description header-info"> Settings </span> </div> <div class="menu-size" onclick="MenuManager.minimize(this)"> <i class="bi bi-chevron-right"></i> </div> </div> <div class="body"></div> <div class="footer"> <div class="menu-button" role="button" onclick="window.open('https://discord.gg/aZGuQmrm8z', '_blank')" onmouseover="Tooltip.show(void 0, 'Join our Discord to share your feedback and discover more mods!')" onmouseout="Tooltip.hide()"> <i class="bi bi-discord"></i> <span> Discord </span> </div> <label class="menu-button switch"> <div class="separator" id="transparency"> <i class="bi bi-transparency"></i> <span> Transparency </span> </div> <input type="checkbox" onchange="MenuManager.opacity(this)"> <div class="checkbox"></div> </label> </div> `; const TIP = document.createElement('div'); TIP.id = 'tooltip-menu'; TIP.style = 'opacity: 0'; TIP.innerHTML = ` Enhanced Visuals ` const NIGHT = document.createElement('div'); NIGHT.classList = 'night-card'; NIGHT.style = 'opacity: 0'; const SETTINGS = document.createElement('div'); SETTINGS.id = 'settings-menu'; SETTINGS.innerHTML = ` <div class="container"> <div class="settings-header"> <div class="separator"> <!-- Separate the flex --> <i class="bi bi-sliders2 settings-icon" style="margin-right: 1vw"></i> <div class="feature-container"> <span> Settings </span> <span class="actual-feature settings-name"> Tornado particles </span> </div> </div> <div class="separator"> <i class="bi bi-arrow-90deg-left settings-button" style="font-size: 1.2vw; color: var(--gray)" onclick="MenuManager.toggleSelector()"></i> <i class="bi bi-x settings-button" onclick="MenuManager.toggleSettings('', false)"></i> </div> </div> <div class="settings-selector ehd_scrollBar"> </div> <div class="settings-body ehd_scrollBar"> <div class="setting settings-colored_hp"> Health bar color <div class="separator color-picker mine_health" style="margin-top: 0.6vw"> <div class="separator"> <div class="color-ball" style="background-color: #801a1a" onclick="MenuManager.changeColor(this)"></div> <div class="color-ball" style="background-color: #bacb29" onclick="MenuManager.changeColor(this)"></div> <div class="color-ball" style="background-color: #269a23" onclick="MenuManager.changeColor(this)"></div> <div class="color-ball" style="background-color: #23629a" onclick="MenuManager.changeColor(this)"></div> <div class="color-ball active picker-div" onclick="MenuManager.changeColor(this)" style="background-color: #611a80"></div> </div> <label class="picker-holder separator"> <input type="color" value="#611a80" onchange="MenuManager.colorPicker(this)"/> <span class="picker-text"> Color picker </span> <i class="bi bi-brush-fill picker-color"></i> </label> </div> <hr class="settings-hr"> Enemy bar color <div class="separator color-picker enemy_health" style="margin-top: 0.6vw"> <div class="separator"> <div class="color-ball" style="background-color: #801a1a" onclick="MenuManager.changeColor(this)"></div> <div class="color-ball" style="background-color: #bacb29" onclick="MenuManager.changeColor(this)"></div> <div class="color-ball" style="background-color: #269a23" onclick="MenuManager.changeColor(this)"></div> <div class="color-ball" style="background-color: #23629a" onclick="MenuManager.changeColor(this)"></div> <div class="color-ball active picker-div" onclick="MenuManager.changeColor(this)" style="background-color: #ae6999"></div> </div> <label class="picker-holder separator"> <input type="color" value="#ae6999" onchange="MenuManager.colorPicker(this)"/> <span class="picker-text"> Color picker </span> <i class="bi bi-brush-fill picker-color"></i> </label> </div> </div> <div class="setting settings-weapon_range"> <div class="switch separator checkbox-wrapper"> <div class="separator"> <i class="bi bi-slash-circle-fill"></i> <div class="info-holder"> <span> Round Cap </span> <span class="description"> Rounds the line cap to smooth </span> </div> </div> <label class="separator" style="width: 2.1vw"> <input type="checkbox" checked onchange="MenuManager.enable(this, 'cap', 'slash-circle-fill', 'slash-square-fill')"> <div class="checkbox"></div> </label> </div> <hr class="settings-hr"> Draw color <div class="separator color-picker color" style="margin-top: 0.6vw"> <div class="separator"> <div class="color-ball" style="background-color: #801a1a" onclick="MenuManager.changeColor(this)"></div> <div class="color-ball" style="background-color: #bacb29" onclick="MenuManager.changeColor(this)"></div> <div class="color-ball" style="background-color: #269a23" onclick="MenuManager.changeColor(this)"></div> <div class="color-ball" style="background-color: #23629a" onclick="MenuManager.changeColor(this)"></div> <div class="color-ball active picker-div" onclick="MenuManager.changeColor(this)" style="background-color: #404040"></div> </div> <label class="picker-holder separator"> <input type="color" value="#404040" onchange="MenuManager.colorPicker(this)"/> <span class="picker-text"> Color picker </span> <i class="bi bi-brush-fill picker-color"></i> </label> </div> </div> <div class="setting settings-hitbox"> Draw color <div class="separator color-picker color" style="margin-top: 0.6vw"> <div class="separator"> <div class="color-ball" style="background-color: #801a1a" onclick="MenuManager.changeColor(this)"></div> <div class="color-ball" style="background-color: #bacb29" onclick="MenuManager.changeColor(this)"></div> <div class="color-ball" style="background-color: #269a23" onclick="MenuManager.changeColor(this)"></div> <div class="color-ball" style="background-color: #23629a" onclick="MenuManager.changeColor(this)"></div> <div class="color-ball active picker-div" onclick="MenuManager.changeColor(this)" style="background-color: #50C878"></div> </div> <label class="picker-holder separator"> <input type="color" value="#50C878" onchange="MenuManager.colorPicker(this)"/> <span class="picker-text"> Color picker </span> <i class="bi bi-brush-fill picker-color"></i> </label> </div> </div> <div class="setting settings-footsteps"> <div class="switch separator checkbox-wrapper"> <div class="separator"> <i class="bi bi-meta"></i> <div class="info-holder"> <span> Land steps </span> <span class="description"> Draw steps when walking on land </span> </div> </div> <label class="separator" style="width: 2.1vw"> <input type="checkbox" checked onchange="MenuManager.enable(this, 'land')"> <div class="checkbox"></div> </label> </div> </div> <div class="setting settings-name_changer"> <div class="dropdown-div"> <div class="separator"> <i class="bi bi-pencil-fill"></i> <span> New Name Changer </span> </div> <div class="button-plus" onclick="MenuManager.toggleNewNC(this)"> <i class="bi bi-plus"></i> </div> </div> <hr class="settings-hr"> <div class="name-changer-holder"> <div class="name-changer edit"> <i class="bi bi-pencil-square text icon-change" onclick="MenuManager.addNC(this)" onmouseover="MenuManager.changeIcon(this, 1, 'bookmark-plus text icon-change')" onmouseout="MenuManager.changeIcon(this, 0, 'pencil-square text icon-change')"> </i> <div class="name-changes"> <input type="text" placeholder="Wolf" class="name-edit"/> <i class="bi bi-arrows"></i> <input type="text" placeholder="Dog" class="name-edit"/> </div> </div> <span class="edit"> <span class="risk">*</span> <span> NOTE: The name will be replaced ONCE entity is displayed on screen </span> </span> <div id="name-changer-wrap"></div> </div> </div> <div class="setting settings-undefined" style="display: none"> <span> No settings available for this feature. </span> </div> </div> </div> ` document.head.appendChild(CSS); document.body.appendChild(HUD); document.body.appendChild(TIP); document.body.appendChild(NIGHT); document.body.appendChild(SETTINGS); document.title = 'Sploop.io - EHD'; //[=]=> WebSocket overrider & functions class PlayerManager { constructor() { this.alive = false; this.clan = []; this.age = 0; this.old_weapon = 0; } update() { const velocity = !Vars.steps.length && Player.velocity > 18; if (velocity) { const land = Settings.footsteps.land; const platform = Vars.entities.find(entity => entity && entity.type === 9 && Utils.distance(Player, entity) <= 65); const bed = Vars.entities.find(entity => entity && entity.type === 15 && Utils.distance(Player, entity) <= 65); const { x, y } = Player; const color = bed ? '#474747' : platform ? '#69482a' : y < 2485 ? '#b9b5ad' : y < 7485 ? '#51603a' : y < 8000 ? '#beb387' : y < 9000 ? '#1e6774' : '#86613d' if (!land && y < 7485) return; Vars.steps.push({ x, y, color, size: 10 }); } } } class Packets { static init(ws) { const url = ws.url; ws.addEventListener('message', this.message.bind(this)); Object.assign(this, { ws, url }) } static message(event) { const message = event.data; const type = typeof message; const data = type === 'string' ? JSON.parse(message) : new Uint8Array(message); data.type = data[0]; if (data.type === server.items_upgrade) { if (data.byteLength > 1) { Player.items = []; for (let index = 1; index < data.byteLength; index++) { Player.items.push(data[index]) }; } } if (data.type === server.spawned) { const id = data[1], items = data[4], alive = true; Object.assign(Player, { id, items, alive }); } if (data.type === server.died) Player.alive = false; if (data.type === server.update) { Vars.enemy = null; for (let index = 1; index < data.length; index += 19) { const broke = data[index + 8]; const type = data[index + 0]; const sid = data[index + 1]; const id = data[index + 2] | data[index + 3] << 8; const x = data[index + 4] | data[index + 5] << 8; const y = data[index + 6] | data[index + 7] << 8; const dir = data[index + 9] / 255 * 6.283185307179586 - Math.PI; const weapon = data[index + 10]; const hat = data[index + 11]; const team = data[index + 12]; const health = data[index + 13] / 255 * 100; if (2 & broke) { Vars.entities[id] = null; } else { const entity = Vars.entities[id] || {}; Object.assign(entity, { type, sid, id, x, y, weapon, hat, health, team, dir }); Vars.entities[id] = entity; if (id === Player.id) { Player.velocity = Math.hypot(y - Player.y, x - Player.x); Player.update(); Object.assign(Player, entity); } const clan = (!Player.team || team != Player.team); if (type === 0 && Player.id !== id && clan) { const enemy = Vars.enemy; const newDist = Math.hypot(Player.y - y, Player.x - x); const oldDist = Vars.enemy ? Math.hypot(Player.y - enemy.y, Player.x - enemy.x) : null; if (enemy) { if (newDist < oldDist) { Vars.enemy = entity; } } else { Vars.enemy = entity; } } } } } } } WebSocket.prototype.send_ = WebSocket.prototype.send; WebSocket.prototype.send = function(data) { const url = Packets.ws?.url !== this.url; if (!Packets.ws || url) { Packets.init(this); } this.send_(data); }; //[=]=> Canvas drawing functions const particlesArray = [] class Functions { static footsteps(canvas, args) { Vars.steps.forEach((step, index) => { const { x, y, size, color } = step; canvas.save() canvas.beginPath() canvas.globalAlpha = Math.max(0, 1 - step.size / 30) canvas.fillStyle = color canvas.arc(x, y, size, 0, Math.PI * 2) canvas.fill() canvas.restore() step.size *= 1.05 if (step.size > 100) { Vars.steps.splice(index, 1); } }) } static heal_effect(canvas, args) { const [ x, y, hp ] = args; Vars.heals.forEach((healed, index) => { const { plus, type, dir, rot, x, y } = healed; const speed = .01; healed.alpha -= speed * 2; healed.plus += speed * rot; canvas.save(); canvas.translate(x, y); canvas.rotate(dir + plus); canvas.globalAlpha = healed.alpha; canvas.drawImage(type, 0, 0, 80, 80); canvas.restore(); if (healed.alpha < .06) { Vars.heals.splice(index, 1); } }) } static health_bar(canvas) { const colors = Settings.colored_hp; const color = canvas.fillStyle === '#a4cc4f' ? colors.mine_health : colors.enemy_health; canvas.fillStyle = color } static display_hp(canvas, args) { const [ x, y, hp ] = args const health = Math.round(hp + 5) const content = `${health}%` const { width } = canvas.measureText(content) const text = [content, x + 30 - (health > 99 ? 2 : 0), y + 30] canvas.font = '20px Baloo Paaji' canvas.fillStyle = 'white' canvas.strokeStyle = '#404040'; canvas.lineWidth = 6.5 canvas.strokeText(...text) canvas.fillText(...text) } static weaponRange(canvas, range) { const width = Math.min(4, canvas.lineWidth); canvas.save() canvas.beginPath() canvas.strokeStyle = Settings.weapon_range.color || '#404040' canvas.globalAlpha = .5 canvas.lineCap = Settings.weapon_range.cap ? 'round' : 'square'; canvas.rotate(-Math.PI / 2) // left canvas.arc(0, 0, range - width, 0, Math.PI) canvas.stroke() canvas.restore() } static hitbox(canvas, radius, object, x = 0, y = 0, width = 0, height = 0) { canvas.save() canvas.beginPath() canvas.strokeStyle = Settings.hitbox.color || '#50C878'; canvas.globalAlpha = object === 'trap' ? 1 : .6 canvas.arc(x + width / 2, y + height / 2, radius, 0, Math.PI * 2) canvas.stroke() canvas.restore() } static particles(canvas) { const particleCount = 20 const arcRadius = 5 if (particlesArray.length === 0) { for (let i = 0; i < particleCount; i++) { const x = Math.random() * 440 const y = Math.random() * 440 particlesArray.push({ x: -220 + x, y: -220 + y, alpha: 1, lifespan: Math.random() * 100 + 50 }) } } for (let i = particlesArray.length - 1; i >= 0; i--) { const particle = particlesArray[i] particle.alpha -= 1 / particle.lifespan if (particle.alpha <= 0) { particle.x = -220 + Math.random() * 400 particle.y = -220 + Math.random() * 400 particle.alpha = 1 particle.lifespan = Math.random() * 100 + 50 } // Draw particle canvas.beginPath() canvas.arc(particle.x, particle.y, arcRadius, 0, Math.PI * 2, false) canvas.fillStyle = `rgba(154, 113, 53, ${particle.alpha})` canvas.fill() canvas.closePath() } } } // [=]=> Ctx override function getWeaponRange(src) { let range = 0 weapons.forEach(weapon => { if (src.search(weapon) > 0) { const index = weapons.indexOf(weapon) range = ranges[index] } }) return range; } const weapons = [ 'hammer', 'sword', 'spear', 'axe', 'shield', 'stick', 'katana', 'naginata', 'bat', 'chillrend', 'dagger', 'staff', 'secret', 'scythe' ]; const ranges = [ 80, 135, 160, 90, 55, 100, 140, 165, 115, 140, 80, 140, 115, 160 ] const item_radius = { trap: 40, spike: 45, hard_spike: 45, big_spike: 42, boost: 40, wall: 45 } const drawImage = CanvasRenderingContext2D.prototype.drawImage; CanvasRenderingContext2D.prototype.drawImage = function (image, x, y, width, height) { const canvas = this; const check = image.src && image.src.search('inv') < 0; const isWeapon = check && weapons.some(item => image.src.search(item) > 0); if (isWeapon && Features.weapon_range) { const range = getWeaponRange(image.src); Functions.weaponRange(canvas, range); } if (!isWeapon && check && Features.hitbox) { const object = image.src.split('/')[5].split('.')[0] const radius = item_radius[object] const holding = image.src.includes('item'); const args = holding ? [x, y, width, height] : []; if (radius) Functions.hitbox(canvas, radius, object, ...args); } if (!isWeapon && check && image.src.search('tornado') > 0 && Features.tornado_particles) { Functions.particles(canvas) } return drawImage.apply(this, arguments) }; const strokeText = CanvasRenderingContext2D.prototype.strokeText; CanvasRenderingContext2D.prototype.strokeText = function (text, x, y, maxWidth) { // name changer const name = Settings.name_changers[text] if (Features.name_changer && name) { arguments[0] = name; } return strokeText.apply(this, arguments) } const fillText = CanvasRenderingContext2D.prototype.fillText; CanvasRenderingContext2D.prototype.fillText = function (text, x, y, maxWidth) { const canvas = this; // Healing effect! if (canvas.fillStyle === '#8ecc51' && Features.healing_effect) { const type = Player?.items?.includes(12) ? Vars.images.cookie : Vars.images.apple; const { x, y } = Player; const rot = Vars.rot || -1; Vars.rot ? delete Vars.rot : (Vars.rot = 1); const dir = Mouse.angle + (rot === -1 ? -.9 : 0); Vars.heals.push({ type, dir, rot, x, y, plus: 0, alpha: 1 }); } // Name changer const name = Settings.name_changers[text] if (Features.name_changer && name) { arguments[0] = name; } return fillText.apply(this, arguments) }; const fillRect = CanvasRenderingContext2D.prototype.fillRect; CanvasRenderingContext2D.prototype.fillRect = function (x, y, width, height) { const canvas = this; const isBar = ['#a4cc4f', '#cc5151'].includes(canvas.fillStyle); if (canvas.fillStyle === '#a4cc4f') { // Makes hp bar smoother if (Features.smooth_hp) { const old = Vars.health || width; const smooth = Utils.lerp(old, width, .1) width = smooth Vars.health = smooth } // Heal effect disp ck Features.healing_effect && Functions.heal_effect(canvas, arguments); // Footsteps disp Features.footsteps && Functions.footsteps(canvas, arguments); } if (isBar) { // Change bar colors Features.colored_hp && Functions.health_bar(canvas); fillRect.apply(canvas, arguments); // Then display HP Features.display_hp && Functions.display_hp(canvas, arguments); return; } return fillRect.apply(this, arguments) }; //[=]=> Apply window values window.Tooltip = Tooltip; window.MenuManager = MenuManager; window.Settings = Settings; const Player = new PlayerManager(); const Mouse = new MouseManager(); window.addEventListener('beforeunload', function () { Utils.ls_set('ehd_features', Features); Utils.ls_set('ehd_settings', Settings); }); window.addEventListener('click', function (event) { const { target } = event; if (target.id === 'settings-menu') MenuManager.toggleSettings('', false); }); //[=]=> Event listeners, dom load, etc (function load() { if (Vars.loaded) return; Vars.loaded = true; Mouse.listeners(); MenuManager.appendReplacer(); // Appends each button to the menu let string = ''; for (let featureID in Features) { const Feature = Features[featureID]; const { name, icon, info } = All_features[featureID] || {}; name && (string += ` <div class="menu-button ${ Feature ? 'active' : '' }" role="button" onmouseover="MenuManager.ToggleToolTip(this, 1)" onmouseout="MenuManager.ToggleToolTip(this, 0)" onmousedown="MenuManager.ToggleFeature(this, 1)" onmouseup="MenuManager.ToggleFeature(this, 0)"> <i class="bi bi-${icon}"></i> <span>${name}</span> </div> `); } document.querySelector('.body').innerHTML = string; // Appends features but to the setting selector string = ''; for (let featureID in Features) { const Feature = Features[featureID]; const { name, icon } = All_features[featureID] || {}; name && (string += ` <div class="settings-item setting-div-${featureID} ${Feature ? 'active' : ''}" onmouseover="MenuManager.ToggleToolTip(this, 1)" onmouseout="MenuManager.ToggleToolTip(this, 0)" onclick="MenuManager.toggleSettings(this, true)"> <i class="bi bi-${icon}"></i> <span style="display: none">${name}</span> </div> `); } document.querySelector('.settings-selector').innerHTML = string; function update() { // Hide ads, sry const rightAd = document.querySelector('#game-right-content-main'); const leftAd = document.querySelector('#game-left-content-main'); const downAd = document.querySelector('#game-bottom-content'); const display = Features.hide_ads ? 'none' : 'block'; rightAd.style.display = display; leftAd.style.display = display; downAd.style.display = display; // Night mode ! const condition = Features.night_mode && Player.alive; const night = document.querySelector('.night-card'); night.style.opacity = condition ? '1' : '0'; setTimeout(() => { requestAnimationFrame(update); }, 1e2); } requestAnimationFrame(update); })(); //yb! //sry for unsemantic html!
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址