Evades Helper (E-Helper)

Nothing interesting. Just helper for evades.io.

当前为 2023-03-19 提交的版本,查看 最新版本

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。

您需要先安装用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         Evades Helper (E-Helper)
// @name:ru      Evades Helper (E-Helper)
// @namespace    http://tampermonkey.net/
// @version      0.3.1
// @description  Nothing interesting. Just helper for evades.io.
// @description:ru  Ничего необычного. Обычный помощник для evades.io
// @author       TimiT#3626
// @match        https://evades.io/
// @run-at       document-start
// @grant        none
// ==/UserScript==

/*



Этот код сделал на коленке за пару вечеров чисто по фану :P



*/

const VERSION = "0.3"

window.storage = {
    get: (key,type="bool") => {
        let res = localStorage.getItem(key)
        if (type === "bool") return res === "true" ? true : false
        return res;
    },
    set: (key, value,type="bool") => {
        if (type === "bool" || type === "num") value = String(value)
        localStorage.setItem(key,value)
        return value
    }
}

const text = (t) => {
    let userlang = client.lang === "ru" ? 0 : 1

    return {
        cmd1: ["Выводит эту справку", "Displays this help"],
        cmd2: ["Включает следование за игроком. Укажите ник для включения, ничего не указывайте для отключения", "Enables following the player. Specify a nickname to enable, specify nothing to disable"],

        msg1: ["=== помимо команд ===", "=== apart from commands ==="],
        msg2: ["Включение света на картах", "Turning ON the lights on the maps"],
        msg3: ["Переключение камеры на клон Виолы (клавиша T)", "Switch camera to Viola's clone (key T)"],
        msg4: ["Спам кнопкой (нажмите обратный слэш и дальше по инструкции)", "Spam with a button (press the backslash and follow the instructions)"],
        msg5: ["Враги на миникарте. Отрисовка сетки", "Enemies on the minimap. Grid rendering"],
        msg6: ["Клавиша Del завершает игру и перезагружает вкладку", "The Del key ends the game and reloads the tab"],
        msg7: ["Автоприцел на некро (в движении может работать некорректно!!! рекомендую останавливаться, стрелять и двигаться дальше)", "Auto-aim on necro (may not work correctly while moving!!! I recommend to stop, shoot and move on)"],

        playerNotFound: ["Игрок не найден. Следование отключено.", "Player not found. Follow disabled."],
        followDisabled: ["Следование отключено", "Follow disabled."],
        followEnabledFor: ["Следование активировано за: ", "Follow activated for: "],

        unknownCommand: ["Неопознанная команда", "Unknown command"],

        pressButtonForSpam: ["Нажми клавишу для включения/отключения спама", "Press key to enable/disable spam"],

        light: ["Свет", "Light"],
        enemiesOnMinimap: ["Враги на миникарте", "Enemies on minimap"],
        gridRendering: ["Отрисовка сетки", "Grid rendering"],
        necroShoot: ["Автоприцел на некро [BETA]", "Auto-aim on necro [BETA]"],
        helpInChat: ["в чат для получения справки", "in chat for help"],
        ideas: ["предлагайте свои идеи", "offer your ideas"]
    }[t][userlang]
}

let counter = +new Date()

const hero = {
    necro: 4
}
const KEY = {
    k: 75
}

let _obs = new MutationObserver((ev) => {
    let elem = Array.from(document.querySelectorAll('script')).filter(a=>a.type === "module" && a.src.match(/\/index\.[0-9a-f]{8}\.js/))[0];
    if (!elem) return;
    let src = elem.src

    elem.remove()

    let req = new XMLHttpRequest()
    req.open("GET", src, false)
    req.send()
    let code = req.response
    let _tmp = 0
    code = code
        //.replace("b[p].render(this.context,this.camera)}", "b[p].render(this.context,this.camera)};window.customRender(this.context,this.camera);")
        // .replace("if(t.area.lighting<1)", "if(t.area.lighting<1 && !window.ignoreLighting)")
        // .replace("t.canvasScale=1/8,", "t.canvasScale=1/8,window.setRenderOptions(t),")
        // .replace("this.setState({leaderboardProps:this.initialLeaderboardProps()})", "this.setState({leaderboardProps:this.initialLeaderboardProps()});window.updateLeaderboard()")
        // .replace('e.beginPath(),e.arc(this.x+t.x,this.y+t.y,this.radius,0,2*Math.PI,!1)','this.color.length==7&&(this.color+="BD"),e.beginPath(),e.arc(this.x+t.x,this.y+t.y,this.radius,0,2*Math.PI,!1)')
        // .replace('this.isDeparted||','this.isDeparted&&(h="#0008"),')
        .replace("case\"focus\":case\"blur\":", "case\"focus\":case\"blur\":break;")


        .replace(/([a-zA-Z0-9\$]+)\=[a-zA-Z0-9\$]+\.FramePayload.decode\([a-zA-Z0-9]+\)/, (a,b) => {
            // console.log("Replace: ", a)
            return a + ",_=window._client.onMessage("+b+")"
        })
        .replace(/(ClientPayload\.encode\()([a-zA-Z0-9$]+)/, (a,b,c) => {
            return b + "window._client.input(" + c + ")"
        })
        .replace("this.sequence=0,","this.sequence=0,window._client.user=this,")
        .replace(/this\.camera\.centerOn\(([a-z])\.self\.entity\)\,/, (a,b) => {
            return "window.setCameraObject(this.camera),this.camera.centerOn(window.setCameraPosition(" + b + ")),"
        })
        .replace(/.=(.)\.sender,.=.\.style,.=.\.text[;,][a-z\, ]+(.)=null,(.)=null,.=null;.+"private-message"\),/, (a,b,c,d) => {
            // console.log("Replace: ", a, b, c, d)
            return a + "!" + c + " && ([" + c + "," + d + "]=window._client.checkSender(" + b + ".sender));"
        })
        .replace(/window\.tsmod&&\(window\.protobuf\=([a-zA-Z0-9$]+)\)/, (a,b) => {
            return "true&&(window.protobuf=" + b + ");window._client.decode = window.protobuf.FramePayload.decode;window._client.encode = window.protobuf.ClientPayload.encode;"
        })
        .replace(/([a-zA-Z0-9$]+)=new WebSocket\([a-z]\)/, (a,b) => {
            return a + ",window._client.ws = " + b
        })
        .replace(/this\.chatMessages\.pop\(\);/, (a) => {
            // console.log("replace", a)
            return a + "window._client.follow && ( this.mouseDown = window._client.processFollow() );"
        })
        .replace(/processServerMessage\(.\)\{/, (a) => {
            return a + "window._client.chat.add = this.updateChat;"
        })

        // IS DEPARTED
        .replace(/(rgba\(\$\{.\..\}, \$\{.\..\}, \$\{.\..\}, )0(\))/, (a,b,c) => {
            // console.log("Replaced", a)
            // console.log(b + "0.5" + c)
            return b + "0.5" + c
        })
        .replace(/if(.\.isDeparted)return;/, (a,b) => "").replace("this.bodyName||this.isDeparted", "this.bodyName").replaceAll("!this.isDeparted","true").replace("this.isDeparted||","false||")

        .replaceAll(/(.)(\.showOnMap)&&/g, (a,b,c) => {
            return "(" + b + c + " || (" + b + ".entityType !== 1 && " + b + ".brightness !== 0.281 && window._client.enemiesOnMinimap))&&"
        }).replace('fillStyle="rgba(80, 80, 80, 0.6)",', 'fillStyle = "rgba(0, 0, 0, 0.6)",')

        .replace(/window\.addEventListener\("keydown"\,(.)\)/, (a,b) => {
            // console.log("Replace: ", a)
            return `window.addEventListener("keydown", (_) => {
                window._client.onKeydown(_);${b}(_)
            })`
        })

        /* .replace(/this\.titleText=new ([a-zA-Z0-9$]+)/, (a,b) => {
            console.log("Replace", a)
            return a + ",this.notifyText = new " + b + ",window._client.text.notify.element = this.notifyText"
        }) */
        .replace(/(.)\.(fillText\(.,(.),40\),)([a-zA-Z0-9$]+\.get\(\)\.displayTimer)/, (a,b,c,d,e) => {
            // console.log("Replace",a,b,c,d)
            return b + "." + c + "window._client.text.notify && (" + b + ".font = " + b + ".font.replace('35', '22')) && (" +
                b + ".strokeText(window._client.text.notify," + d + ", 120) || " + b + ".fillText(window._client.text.notify," + d + ", 120))," + e
        })

        .replaceAll(".render(this.context,this.camera)",(a) => {
            if (++_tmp === 2) return ".render(this.context, this.camera);window._client.drawInfo(this)"
            return a
        })

        .replace(/drawImage\(([a-zA-Z0-9$]+tiles\.getImage\(\))/, (a,b) => {
            // console.log("Replace: ", a)
            return "drawImage(window._client.drawGrid ? " + b + " : window._client.tilesImg"
        })

    document.body.appendChild(panel)
    document.body.appendChild(openPanel)

    /* document.addEventListener("mousemove", (ev) => {
        window.mousePosition.x = ev.pageX
        window.mousePosition.y = ev.pageY
    })

    canvas = document.getElementById("canvas")
    canvas.addEventListener("wheel", (ev) => {
        window.scaleGame(ev.deltaY < 0)
    }) */

    setInterval(() => {
        if (client.antiAFK && client.ws){
            client.ws.send(client.encode({
                sequence: ++client.user.sequence
            }).finish())
        }
    }, 60000)

    let nScr = document.createElement("script")
    nScr.setAttribute("type", "module")
    nScr.innerHTML = code
    document.body.appendChild(nScr)

    console.log("Init")
    _obs.disconnect()

})
_obs.observe(document, {childList: true, subtree: true});

const onMessage = (msg) => {
    client.logMessages && console.log(msg)

    // LIGHT
    if (msg.area && client.ignoreLighting){
        msg.area.lighting = Math.max(msg.area.lighting, 0.5)
    }

    // VIOLA CLONE
    violaClone(msg)

    if (client.user.entities){
        let _ent = []
        for (let _e of msg.entities){
            // невидимки
            if (_e.hasOwnProperty("brightness")){
                if (_e.brightness < 0.2){
                    _e.brightness = 0.2
                }
            }

            // возвратные телепортеры
            let e = client.user.entities[_e.id]
            if (e && e.entityType === 55){
                if (e.x !== _e.x || e.y !== _e.y){
                    // console.log(e)
                    // client.user.entities[-_e.id] = Object.assign({}, e)
                    _ent.push({
                        id: -_e.id,
                        x: e.x,
                        y: e.y,
                        radius: e.radius,
                        entityType: e.entityType,
                        brightness: 0.281,
                    })
                }
            }
        }
        msg.entities = msg.entities.concat(_ent)
    }

    let _seq = client.seqQueue.find(q => q[0] === msg.sequence)
    if (_seq){
        client.ping = +new Date() - _seq[1]
        client.seqQueue = client.seqQueue.filter(q => q[0] > msg.sequence)
    }

    // CHAT

    // FOLLOW
    // if (client.follow) follow(msg, client.follow)

    // console.log(client.follow)
};

const necroCheck = (msg) => {
    if (client.ignoreNecroShoot || !msg.keys.find(k => k.keyType === 11 && k.keyEvent === 1) || !client.autoNecroShoot || !client.user.self.entity || client.user.self.entity.heroType !== hero.necro) return;
    let abil = client.user.heroInfoCard.abilityTwo
    if (abil.disabled || abil.cooldown !== 0 || abil.level === 0 || client.user.energy < 30) return

    let h = Object.values(client.user.globalEntities).find(e => {
        return e.deathTimer !== -1 && e.regionName === client.user.self.entity.regionName && e.areaName === client.user.self.entity.areaName
    })

    if (!h) return

    let vector = {
        x: Math.floor(h.x - client.user.self.entity.x),
        y: Math.floor(h.y - client.user.self.entity.y),
        updated: true
    }

    if (Math.sqrt(vector.x**2 + vector.y**2) > 1000) return;

    return vector;

    // window.dispatchEvent(new KeyboardEvent('keydown', {'keyCode': KEY.k}));

    // console.log("here", +new Date())
    // console.log("here", vector)
}

const processFollow = () => {
    let followTo = client.user.globalEntities[client.follow]
    let me = client.user.self.entity
    if (!followTo){
        chatMessage({text: text("playerNotFound")})
        client.follow = null
        return
    }
    let x = followTo.x - me.x
    let y = followTo.y - me.y
    let length = Math.sqrt(x**2+y**2);

    let count = (v) => {
        if (length >50){
            return v/length * 200
        }
        return v * 2
    }

    let mouseDown = {
        updated: true,
        x: Math.floor( count(x) ),
        y: Math.floor( count(y) )
    }

    // console.log(mouseDown)

    return mouseDown
    // client.user.mouseDown = mouseDown
    // console.log(client.user.mouseDown)
    // console.log("follow", client.user.sequence, msg.sequence)
}

const violaClone = (msg) => {
    let abil = client.user.heroInfoCard.abilityTwo
    /* if (abil.abilityType === 52){
        if (client.clone.id){
            if (client.clone.frame){
                client.clone.frame = false
            } else {
                if (abil.cooldown >= abil.totalCooldown - abil.totalCooldown / 14.5) client.clone.watch = !client.clone.watch
            }
        }
    } */

    let e = !client.clone.id && msg.entities && client.user && client.user.self.entity && msg.entities.find(ee => {
        return ee.name === client.user.name && ee.id !== client.user.self.id
    })
    if (e) client.clone.id = e.id

    if (msg.area){
        client.clone.id = undefined
        client.clone.watch = false;
    }
}

const input = (msg) => {
    // console.log(msg)

    // console.log("common", client.user.sequence, window.sequence)
    if (msg.message) localMessageHandler(msg);

    if (client.ignoreNecroShoot){
        client.ignoreNecroShoot = false
    } else {
        let necroShoot = necroCheck(msg)
        // console.log(necroShoot)

        if (necroShoot){
            /* msg.keys = msg.keys.filter(k => {
            return !([1,2,3,4].includes(k.keyType) && k.keyEvent === 1)
        }) */
            // msg.keys = [...msg.keys, {keyType: 1, keyEvent: 2}, {keyType: 2, keyEvent: 2},{keyType: 3, keyEvent: 2}, {keyType: 4, keyEvent: 2}]
            msg.mouseDown = necroShoot
            client._keys = msg.keys
            msg.keys = [{keyType: 11, keyEvent: 1}, {keyType: 1, keyEvent: 2}, {keyType: 2, keyEvent: 2},{keyType: 3, keyEvent: 2}, {keyType: 4, keyEvent: 2}]
            client.ignoreNecroShoot = true
            /* setTimeout(() => {
            // window.dispatchEvent(new KeyboardEvent('keydown', {'keyCode': KEY.k}));
            client.ws.send(client.encode({keys: [{keyType: 11, keyEvent: 2}], sequence: ++client.user.sequence}).finish())
        }, 60)
        setTimeout(() => {
            client.ignoreNecroShoot = false
        }, 2000)
        delete client.necroShoot */
        }
    }
    // console.log(msg)

    client.seqQueue.push([msg.sequence, +new Date()])
    return msg
}

const localMessageHandler = (msg) => {
    let txt = msg.message;
    if (!txt.startsWith("=")) return;

    delete msg.message;
    txt = txt.slice(1)

    txt = txt.split(/ +/g)
    let command = txt[0]
    let args = txt.slice(1)
    if (command === "help") {
            chatMessage({text: [
                ...(COMMANDS.map(c => PREFIX + c.name + " | " + c.description)),
                ...FUNCTIONS]})
    } else if (command === "follow"){
        let name = args.join(" ")
        if (!name){
            chatMessage({text: text("followDisabled")})
            client.follow = null
            return
        }
        let e = Object.values(client.user.globalEntities).find(ee => ee.name === name)
        client.follow = e ? e.id : null
        chatMessage({text: text("followEnabledFor") + name})
        client.user.mouseDown = processFollow()
    } else {
        chatMessage({text: text("unknownCommand")})
    }
}

const chatMessage = ({text, from, style}) => {
    Array.isArray(text) ? client.chat.add(client.user.globalEntities, {messages: text.map(t => {return{
        id: ++counter,
        text: t,
        style: 8,
        sender: ""
    }})}) : client.chat.add(client.user.globalEntities, {messages: [{
        id: ++counter,
        text,
        style: 8,
        sender: ""
    }]})
}

window.chatMessage = (msg) => {

}


window.setRenderOptions = (o) => {
    window.renderOptions = o
}
window.setCameraObject = (cam) => {
    if (!window.camera){
        window.camera = cam
    }
}

const checkSender = (sender, isConsole=false) => {
    if (DEVS.includes(sender)) return ["[E-H Dev]", "ehdev"];
    if (sender === "") return ["[E-H CONSOLE]", "ehconsole"]
    return [null,null];
}

window.setCameraPosition = (t) => {
    // console.log(t)
    let obj
//    if (window.focusCameraOn ?? window.focusCameraOn !== t.name){
//        let ent = Object.values(t.entities).find(e => e.showOnMap && e.name === window.focusCameraOn)
//        if (ent) obj = {x: ent.x, y: ent.y}
//    }
//    if (!obj){
        obj = {x: t.self.entity.x, y: t.self.entity.y}
        window.focusCameraOn = undefined
//    }

    if (client.clone.watch){
        let clone = t.entities[client.clone.id]
        if (!clone){
            client.clone.id = undefined
            client.clone.watch = false;
        } else {
            obj = {x: clone.x, y: clone.y}
        }
    }

    if (window.freeCameraMove){
        obj.x += (window.mousePosition.x - window.screen.width/2) * (window.startScale ? window.startScale[0] : 1)
        obj.y += (window.mousePosition.y - window.screen.height/2) * (window.startScale ? window.startScale[0] : 1)
    }
    return obj
}

addEventListener("keydown", (event) => {
    if (event.code === "End"){
        client.ws.send(client.encode({
            "sequence": ++client.user.sequence,
            "message": "/ff"
        }).finish())
        location.reload()
    }
});

const onKeydown = (e) => {
    const t = document.getElementById("chat-input");
    if (document.activeElement == t) return;

    if (client.listenKeyToSpam){
        let key = e.keyCode
        if (client.spam.includes(key)) client.spam = client.spam.filter(k => k !== key)
        else if (e.code !== "Backslash") client.spam.push(key)

        client.listenKeyToSpam = false
        client.text.notify = null

        // console.log(client.spam)
    } else if (e.code === "KeyT"){
        client.clone.watch = !client.clone.watch
    } else if (e.code === "Backslash"){
        client.listenKeyToSpam = true
        client.text.notify = text("pressButtonForSpam")
    } else if (e.code === "KeyV"){
        client.showInfo = !client.showInfo
    }

    // console.log(e)
}
const onKeyup = (e) => {}

const drawInfo = (r) => {
    if (!client.showInfo) return
    let x = 14, y = 230
    let text1 = "Ping: " + client.ping
    let text2 = client.ws.url.split("wss://")[1].slice(0,2).toUpperCase() + " " + (+client.ws.url.split("backend=")[1][0] + 1)
    let h = 16

    r.context.lineWidth = 3
    r.context.font = "bold 15px Tahoma, Verdana, Segoe, sans-serif"
    // r.context.globalAlpha = 0
    r.context.textAlign = "left"
    r.context.strokeStyle = "#000000"
    r.context.fillStyle = "#ffffff"
    r.context.strokeText(text1, x, y)
    r.context.strokeText(text2, x, y + h)
    r.context.fillText(text1, x, y)
    r.context.fillText(text2, x, y + h)

    r.context.lineWidth = 1
}

setInterval(() => {
    if (client.listenKeyToSpam) return

    for (let i of client.spam){
        window.dispatchEvent(new KeyboardEvent('keydown', {'keyCode': i}));
        setTimeout(() => {
            window.dispatchEvent(new KeyboardEvent('keyup', {'keyCode': i}));
        }, 30)
    }
}, 50)

const client = {
    user: null,
    ws: null,

    clone: {
        id: null,
        frame: true
    },
    chat: {
        add: null
    },
    follow: null,

    antiAFK: window.storage.get("antiAFK"),
    ignoreLighting: window.storage.get("ignoreLighting"),
    enemiesOnMinimap: window.storage.get("enemiesOnMinimap"),
    autoNecroShoot: window.storage.get("autoNecroShoot"),
    drawGrid: window.storage.get("drawGrid"),
    lang: window.storage.get("lang", "str") || window.storage.set("lang", "en", "str"),

    ignoreNecroShoot: false,

    processFollow,
    onMessage,
    checkSender,
    input,
    onKeydown, onKeyup,

    encode: null,
    decode: null,

    logMessages: 0,

    spam: [],
    listenKeyToSpam: false,

    text: {
        notify: null
    },

    drawInfo,
    showInfo: 1,
    seqQueue: [],
    ping: 0,
    fps: 0,

    tilesSrc: "https://drive.google.com/u/0/uc?id=1OBYGRSdma-KAv-Rr_FQP99Hm1StDOyTi",
    tilesImg: null
}
window._client = client

/*
window.scaleGame = (wh) => {
    if (!window.freeScale) return;
    if (!window.startScale) { window.startScale = [
        1,
        window.camera.viewportSize.width,
        window.camera.viewportSize.height,
        canvas.width,
        canvas.height
    ] }
    let change = 0.05
    wh ? window.startScale[0] -= change : window.startScale[0] += change
    let scale = window.startScale[0]

    window.camera.viewportSize.width = window.startScale[1] * scale
    window.camera.viewportSize.height = window.startScale[2] * scale

    canvas.width = window.startScale[3] * scale
    canvas.height = window.startScale[4] * scale

    window.dispatchEvent(new Event('resize'));

    document.getElementById("free_scale").innerHTML = "Free scale (x" + window.startScale[0].toFixed(2) + ")"
}*/

/*
window.updateLeaderboard = () => {
	for (let names of [...document.getElementsByClassName('leaderboard-name')]) {
		names.onclick = event => {
			// window.client.openUcard(getAttrInParents(event.target,"ariaLabel"), [20,event.y], window.client.userlog);
            window.focusCameraOn = event.target.innerHTML.split(" ")[0]
		};
		names.style.cursor = "pointer";
	}
}
*/

window.mousePosition = {x: 0, y: 0}
var canvas

window.updateLighting = (th) => {
    client.ignoreLighting = th.checked
    window.storage.set("ignoreLighting", client.ignoreLighting)
}
window.updateAntiAFK = (th) => {
    client.antiAFK = th.checked
    window.storage.set("antiAFK", client.antiAFK)
}
window.updateEnemiesOnMinimap = (th) => {
    client.enemiesOnMinimap = th.checked
    window.storage.set("enemiesOnMinimap", client.enemiesOnMinimap)
}
window.updateautoNecroShoot = (th) => {
    client.autoNecroShoot = th.checked
    window.storage.set("autoNecroShoot", client.autoNecroShoot)
}
window.updateDrawGrid = (th) => {
    client.drawGrid = th.checked
    window.storage.set("drawGrid", client.drawGrid)
}

window.changeLanguage = th => {
    let langs = ["ru", "en"]
    let lIndex = langs.findIndex(e => e === client.lang) + 1
    if (lIndex >= langs.length) lIndex =0
    let nLang = langs[lIndex]
    window.storage.set("lang", nLang, "str")
    let but = document.getElementById("_lang")
    but.innerHTML = "Language: " + nLang
    alert("Restart page for apply changes")
}


window.updateFreeCameraMove = (th) => {
    window.freeCameraMove = th.checked
}
window.updateFreeScale = (th) => {
    window.freeScale = th.checked
}


let panel = document.createElement("div")
panel.style.background = "rgba(200, 200, 200, 0.9)"
panel.style.width = "400px"
panel.align = "center"
panel.style.position = "fixed"
panel.style.top = "50px"
panel.style.left = "calc(50% - 200px)"
panel.style.borderRadius = "10px"
panel.style.visibility = "hidden"
panel.style.padding = "20px"

panel.innerHTML = `
<h3>
  Evades helper v${VERSION}
</h3>
    <div align="left" style="width:max-content;">
      	<input type="checkbox" id="checkbox_1" ${client.ignoreLighting ? "checked" : ""} onclick="window.updateLighting(this)"/>
        <label for="checkbox_1">${text("light")}</label>
        <br/>

      	<input type="checkbox" id="checkbox_2" ${client.antiAFK ? "checked" : ""} onclick="window.updateAntiAFK(this)"/>
        <label for="checkbox_2">AntiAFK</label>
        <br/>

      	<input type="checkbox" id="checkbox_3" ${client.enemiesOnMinimap ? "checked" : ""} onclick="window.updateEnemiesOnMinimap(this)"/>
        <label for="checkbox_3">${text("enemiesOnMinimap")}</label>
        <br/>

      	<input type="checkbox" id="checkbox_5" ${client.drawGrid ? "checked" : ""} onclick="window.updateDrawGrid(this)"/>
        <label for="checkbox_5">${text("gridRendering")}</label>
        <br/>

      	<input type="checkbox" id="checkbox_4" ${client.autoNecroShoot ? "checked" : ""} onclick="window.updateautoNecroShoot(this)"/>
        <label for="checkbox_4">${text("necroShoot")}</label>

    </div>
<p>=help ${text("helpInChat")}<br/>
[DISCORD]: <a id="developer" href="https://discordapp.com/users/998856554033987604">@TimiT#3626</a> (${text("ideas")})</p>

<button id="_lang" onclick="window.changeLanguage(this)">Language: ${client.lang}</button>

<style>
  #developer:link {
    color: black;
  }

  #developer:visited {
    color: black;
  }

  #developer:hover {
    color: #333333;
  }

  #developer:active {
    color: black;
  }
  .chat-message .ehdev {
    color: #ff4f00
  }
  .chat-message .ehconsole {
    color: #ff0800
  }
</style>
`

let openPanel = document.createElement("div")
openPanel.style.background = "rgba(100, 100, 100, 0.5)"
openPanel.style.borderRadius = "10px"
openPanel.style.bottom = "60px"
openPanel.style.right = "10px"
openPanel.style.position = "fixed"
openPanel.style.width = "40px"
openPanel.style.height = "40px"
openPanel.onclick = () => {
    panel.style.visibility = panel.style.visibility === "visible" ? "hidden" : "visible"
}

const tiles = new Image()
tiles.src = client.tilesSrc
tiles.onload = () => {
    client.tilesImg = tiles
}

const DEVS = ["TimiT"]
const PREFIX = "="
const COMMANDS = [{
    name: "help",
    description: text("cmd1")
}, {
    name: "follow",
    description: text("cmd2")
}]
const FUNCTIONS = [
    text("msg1"),
    text("msg2"),
    text("msg3"),
    text("msg4"),
    text("msg5"),
    text("msg6"),
    text("msg7")
]