// ==UserScript== // @name Sun:Raise - zombs.io // @namespace http://tampermonkey.net/ // @version 0.5 // @description weeb strikes again // @author rdm // @match *://zombs.io/ // @icon https://media.discordapp.net/attachments/854376044522242059/1067302959765016656/latest.png // @grant none // @license GNU GPLv3 // @noframes // @downloadURL none // ==/UserScript== /* @Credit * i have to give credit where credit is due, * most of the images used in this mod, including: * + intro background (#hud-intro::before), * + theme-character (.hud-intro-character) * is taken from Arcaea, this mod is themed to look * like Arcaea's UI. * * visit Arcaea at https://arcaea.lowiro.com/ and * check out the game on Google's Play store and * Apple's App Store. */ // day 1 (0.1) : intro styles done // day 2 (0.2) : menu styles done // day 3 (0.3) : ahrc, rb, autoup done + polishing // day 4 (0.4) : entering unfamiliar territory with scanner // day 5 (0.41): polishing // day ? (0.42): beta release // v0.5 : added resizeable wall blocks const fontAwesome = document.createElement("script"); fontAwesome.type = "text/javascript"; fontAwesome.src = "https://kit.fontawesome.com/1c239b2e80.js"; document.head.appendChild(fontAwesome); document.querySelectorAll('.ad-unit, #hud-intro > div.hud-intro-wrapper > h1, #hud-intro > div.hud-intro-footer > a:nth-child(2), #hud-intro > div.hud-intro-footer > a:nth-child(4), #hud-menu-shop > div.hud-shop-grid > a:nth-child(10), #hud-intro > div.hud-intro-wrapper > h2, .hud-intro-left, .hud-intro-guide, .hud-intro > .hud-intro-stone, .hud-intro >.hud-intro-tree, .hud-intro-youtuber, .hud-intro-more-games, .hud-intro-social, .hud-respawn-corner-bottom-left, .hud-respawn-twitter-btn, .hud-respawn-facebook-btn').forEach(el => el.remove()); const css = ` /* @Root */ :root { --menu-background: hsl(29deg 69% 34% / 40%); --normal-btn: hsl(44deg 58% 60%); --light-hover-btn: hsl(44deg 88% 70%); } ::-webkit-scrollbar { width: 12px; height: 0px; border-radius: 10px; background-color: rgba(0, 0, 0, 0); } ::-webkit-scrollbar-thumb { border-radius: 10px; background-image: url(https://cdn.discordapp.com/attachments/854376044522242059/924927754326142976/whiteslider.png); } /* @Keyframes */ @keyframes parallax-bg { 0%, 100% { background-position: top left; } 50% { background-position: bottom right; } } @keyframes bounce { 50% { background-position-y: -10px; } 100% { background-position-y: 0px; } } @keyframes slide-in-left { 0% { left: -100%; } 100% { left: 0px; } } @keyframes fade-in { 0% { opacity: 0; } 100% { opacity: 1; } } /* @ButtonStyles */ .no-bg { display: inline-block; height: 40px; line-height: 40px; padding: 0 20px; color: #eee; background: none; box-shadow: none; border: none; cursor: pointer; } .underline-red { border-bottom: 3px solid red; } .hud-settings-options .underline-red { border-bottom: 3px solid red; } /* @IntroStyles */ .hud-intro::before { background-image: url('https://media.discordapp.net/attachments/854376044522242059/1067303856893071481/1000.png'); background-size: 200%; background-position: top; filter: blur(10px); animation-name: parallax-bg; animation-duration: 400s; animation-timing-function: linear; animation-iteration-count: infinite; } .hud-intro::after { background: rgba(0, 0, 0, 0.2); } #hud-intro > div.hud-intro-corner-top-left { top: 0px; left: 0px; /* display: none; */ } .hud-intro-stick { display: block; position: relative; width: 30vw; background: #eee; height: 30px; box-shadow: 0px 5px 10px 2px rgb(0 0 0 / 70%); font-weight: 700; padding: 4px; } .hud-intro-stick::before { display: block; position: absolute; content: ""; right: -12px; top: 3px; height: 22.5px; width: 22.5px; transform: rotate(45deg); background: #eee; } .hud-intro-stick::after { display: block; position: absolute; content: ""; right: -11px; top: 4px; height: 18px; width: 18px; transform: rotate(45deg); background: black; border: 2px double #eee; } .hud-intro-scan-data { width: 100%; height: fit-content; background: rgba(0, 0, 0, 0.4); border-bottom-right-radius: 4px; padding: 10px; zoom: 90%; max-width: fit-content; min-width: 100%; color: #eee; max-height: 400px; overflow: scroll; } .hud-intro-scan-data .hud-intro-scan-data-player { position: relative; display: block; margin: 0 0 8px; padding: 0 90px 0 40px; height: 20px; line-height: 20px; font-size: 13px; font-family: 'Open Sans', sans-serif; } .hud-intro-scan-data .hud-intro-scan-data-player:last-child { margin-bottom: 0; } .hud-intro-scan-data .hud-intro-scan-data-player.is-header * { color: rgba(255, 255, 255, 0.6) !important; } .hud-intro-scan-data .hud-intro-scan-data-player .player-rank { position: absolute; top: 0; bottom: 0; left: 0; color: rgba(255, 255, 255, 0.6); } .hud-intro-scan-data .hud-intro-scan-data-player .player-name { display: block; height: 20px; line-height: 20px; } .hud-intro-scan-data .hud-intro-scan-data-player .player-score { position: absolute; top: 0; bottom: 0; right: 50px; color: rgba(255, 255, 255, 1); } .hud-intro-scan-data .hud-intro-scan-data-player .player-wave { position: absolute; top: 0; bottom: 0; right: 0; color: rgba(255, 255, 255, 0.7); } .hud-intro-scan-data hr { border: 1px dashed #eee; margin: 20px 0; } #hud-intro > div.hud-intro-corner-top-right { background: rgba(0, 0, 0, 0.3); padding: 15px; top: 0px; right: 0px; border-bottom-left-radius: 4px; } #hud-intro > div.hud-intro-corner-top-right::before { display: block; position: absolute; content: ""; width: 100%; height: 2px; background: linear-gradient(to right, transparent 5%, rgba(255, 255, 255, 0.9)); right: 10px; bottom: 0px; } #hud-intro > div.hud-intro-corner-top-right::after { display: block; position: absolute; content: ""; width: 15px; height: 15px; transform: rotate(45deg); margin: 10px; border: 4px solid white; background: black; right: 0px; bottom: -20px; box-shadow: none; border-style: double; } .hud-intro .hud-intro-footer { left: 20px; right: unset; text-shadow: 0 1px 3px rgb(0 0 0 / 50%); z-index: 20 !important; } #hud-intro > div.hud-intro-wrapper > div { z-index: 31; margin: 50px 30vw 0 0; } #hud-intro > div.hud-intro-wrapper > div > div { display: flex; flex-direction: row; flex-wrap: wrap; width: 380px; padding-bottom: 0px; padding-top: 37.5px; } .hud-intro-server-container { display: flex; flex-direction: row; justify-content: space-around; margin-bottom: 10px; } .hud-intro-server-decorator { width: 0px; content: ""; height: 0px; border-bottom: 50px solid #eee; border-right: 50px solid transparent; position: relative; bottom: 0px; } #hud-intro > div.hud-intro-wrapper > div > div > div > div > select { border-bottom-right-radius: 0px; border-top-right-radius: 0px; } .hud-intro-name-container { display: flex; flex-direction: row; justify-content: space-around; margin-bottom: 5px; } .hud-intro-name-decorator { width: 0px; content: ""; height: 0px; border-top: 50px solid #eee; border-right: 50px solid transparent; position: relative; bottom: 0px; } .hud-intro-name-decorator::after { content: ""; position: absolute; bottom: 54px; left: -200px; width: 120px; border-bottom: 3px dashed #eee; } #hud-intro > div.hud-intro-wrapper > div > div > div > div > input { border-bottom-right-radius: 0px; border-top-right-radius: 0px; padding: 8px 30px 8px 14px; } #saved-names { position: absolute; top: -34px; left: -20px; box-shadow: none; border: none; background: none; width: 20px; } #scan-btn { cursor: pointer; width: 120px; position: relative; right: -160px; top: -20px; height: 120px; margin: -60px; filter: drop-shadow(7.5px 2.5px 0px rgba(0, 0, 0, 0.5)); } .hud-intro .hud-intro-form .hud-intro-play { width: 150px; height: 150px; transform: rotate(45deg); border: 5px solid white; margin-bottom: -20px; margin-left: -7.5px; margin-right: -150px; margin-top: -17.5px; background-image: url(https://cdn.discordapp.com/attachments/854376044522242059/976742118661980160/Story_crimsonsolace.webp); background-size: 150%; padding: 0 0 0 0; background-position-y: center; background-position-x: center; transition: all 0.15s ease-in-out; z-index: 21 !important; position: relative; filter: drop-shadow(10px -5px 0px rgba(0, 0, 0, 0.4)); } .hud-intro .hud-intro-form .hud-intro-play:hover { filter: drop-shadow(10px -5px 0px rgba(0, 0, 0, 0.4)) saturate(200%); box-shadow: inset 0 0 20px 3px rgb(0 0 0 / 45%); } #playspan { position: relative; font-weight: 900; z-index: 22; font-size: xx-large; text-shadow: 1px 1px 3px black; cursor: pointer; font-family: 'Open Sans'; pointer-events: none; top: -75px; left: 65px; margin: -20px -30px; } .hud-intro .hud-intro-form .hud-intro-play::after { display: block; content: ""; position: absolute; top: -15px; left: -15px; width: 40px; height: 40px; border-top: 5px solid white; border-left: 5px solid white; border-top-left-radius: 5px; pointer-events: none; } #hud-intro > div.hud-intro-wrapper > div > div > label { margin: -30px 0 0 0; } .hud-intro .hud-intro-decoration { display: flex; position: absolute; bottom: 0px; width: 100%; pointer-events: none; } .hud-intro .hud-intro-decoration > * { pointer-events: none; } .hud-intro-decoration .hud-intro-left-triangle { height: 300px; width: 600px; } .hud-intro-decoration .hud-intro-left-triangle::before { width: 100%; height: 100%; transform: rotate(30deg); content: ''; display: block; position: absolute; left: -40%; bottom: -50%; background-image: linear-gradient( 45deg, rgba(60, 50, 93, 0.8) 25%, rgba(60, 50, 93, 0.7) 25%, rgba(60, 50, 93, 0.7) 50%, rgba(60, 50, 93, 0.8) 50%, rgba(60, 50, 93, 0.8) 75%, rgba(60, 50, 93, 0.7) 75%, rgba(60, 50, 93, 0.7) ); background-size: 10px 10px; } .hud-intro-decoration .hud-intro-right-triangle { height: 700px; width: 700px; } .hud-intro-decoration .hud-intro-right-triangle::before { width: 100%; height: 100%; transform: rotate(-45deg); content: ''; display: block; position: absolute; right: -50%; bottom: -50%; color: white; background-image: linear-gradient(rgba(255, 255, 255, 0.9), rgba(255, 255, 255, 0.9)), url(https://cdn.discordapp.com/attachments/854376044522242059/925743376505118720/light2.webp); background-position-x: 130px; filter: drop-shadow(4px 2px 6px black); } .hud-intro-decoration .hud-intro-character { display: block; position: absolute; height: 70vh; width: 70vh; bottom: 7.5vh; right: calc(20vw - 35vh); cursor: default; z-index: 30; filter: drop-shadow(15px 15px 0px rgba(0, 0, 0, 0.3)); background-size: cover; background-image: url(https://media.discordapp.net/attachments/854376044522242059/1067321580906086450/1000.png); background-repeat: no-repeat; animation-name: bounce; animation-duration: 10s; animation-iteration-count: infinite; } .hud-intro-credits { position: fixed; display: block; bottom: 40px; left: 20px; color: rgba(255, 255, 255, 0.4); } /* @UIBuildingOverlay */ .hud-building-overlay { background: var(--menu-background); border: 3px solid white; padding: 12px; width: 370px; } .hud-building-overlay::after { border-top: 6px solid white; top: 101%; } .hud-building-overlay .hud-tooltip-health .hud-tooltip-health-bar { background: #bf6509; } /* @UIChatStyles */ .hud-chat { resize: vertical; max-height: 380px; min-height: 75px; overflow-y: auto; border-radius: 4px 4px 4px 0; } .hud-chat .hud-chat-message { display: block; position: relative; width: 90%; white-space: unset; word-break: break-all; overflow: visible; } .hud-chat .hud-chat-message strong { display: inline-block; } .hud-chat .hud-chat-message > small { position: absolute; right: -12%; font-weight: bold; opacity: 0.4; } /* @UIZoomStyles */ .interaction-wheel { display: none; height: 250px; width: 250px; border: 80px solid rgba(0, 0, 0, 0.4); border-radius: 125px; position: fixed; top: calc(50vh - 125px); left: calc(50vw - 125px); } .tag-is-disabled { opacity: 0.4; pointer-events: none; cursor: no-drop; } #next-wheel { background: rgba(0, 0, 0, 0.4); color: white; right: -120px; position: absolute; top: -80px; height: 60px; width: 60px; border-radius: 50%; border: none; cursor: pointer; } #next-wheel::after { content: ' '; position: absolute; width: 100%; height: 100%; background-image: url(https://cdn.discordapp.com/attachments/854376044522242059/947717701839757392/Friends_Mutual.webp); background-size: 90%; top: 5%; left: 5%; } #zoom-mode { background: rgba(0, 0, 0, 0.4); color: white; left: -120px; position: absolute; bottom: -80px; height: 60px; width: 60px; border-radius: 50%; border: none; text-align: center; padding: 20px 0; font-family: 'Hammersmith One'; } #zoom-controls { background: rgba(0, 0, 0, 0.2); color: white; right: calc(50% - 65px); position: fixed; top: 10px; height: 60px; width: 130px; border-radius: 4px; border: none; text-align: start; padding: 10px; font-family: 'Hammersmith One'; } .hud-zoom-item { width: 48px; height: 48px; color: white; position: absolute; transition: all 0.15s ease-in-out; } .zoom-reset { top: -60px; left: calc(50% - 15px); } .zoom-up { left: -60px; top: calc(50% - 15px); } .zoom-down { top: calc(50% - 15px); right: -80px; } .zoom-prop { font-size: 20px; bottom: -80px; left: 25%; } /* @UIMisc. */ #joinWithPsk { display: none; background-color: rgba(0, 0, 0, 0.4); padding: 4px 5px; border-radius: 8px; color: rgb(255, 255, 255); width: 30vw; height: 40px; position: fixed; left: 35vw; top: 60vh; } /* @UIMenuShopStyles */ #hud-menu-shop { top: calc(50vh - 250px); left: calc(50vw - 345px); width: 690px; height: 500px; background: var(--menu-background); border: 4px solid white; margin: 0 0 0 0; padding: 20px 20px 20px 20px; z-index: 20; } .hud-menu-shop .hud-shop-grid { height: 360px; } .hud-shop-grid::after { font-size: 200px; position: absolute; top: -30px; right: -70px; width: 40%; height: 40%; z-index: -69; font-family: "Font Awesome 5 Free"; font-weight: 10; content: "\\f185"; opacity: 0.1; color: white; } .hud-menu-shop .hud-shop-grid .hud-shop-item .hud-shop-item-actions .hud-shop-actions-equip { background: var(--normal-btn); } .hud-menu-shop .hud-shop-grid .hud-shop-item .hud-shop-item-actions .hud-shop-actions-equip:hover, .hud-menu-shop .hud-shop-grid .hud-shop-item .hud-shop-item-actions .hud-shop-actions-equip:active { background: var(--light-hover-btn); } .hud-menu-shop .hud-shop-grid .hud-shop-item .hud-shop-item-actions .hud-shop-actions-equip.is-disabled { background: none; } .hud-menu-shop .hud-shop-grid .hud-shop-item[data-item=HatComingSoon] .hud-shop-item-coming-soon { background: none; } /* @UIMenuPartyStyles */ #hud-menu-party { top: calc(50vh - 240px); left: calc(50vw - 305px); margin: 0; width: 610px; height: 480px; background-color: var(--menu-background); border: 4px solid white; z-index: 20; } .hud-party-members::after { font-size: 200px; position: absolute; bottom: 30px; left: -10px; width: 40%; height: 40%; z-index: -69; font-family: "Font Awesome 5 Free"; font-weight: 10; content: "\\f185"; opacity: 0.1; color: white; } .hud-menu-party .hud-party-members .hud-member-link::before { display: block; position: absolute; content: " "; left: 0px; bottom: 0px; height: 3px; width: 30%; } #hud-menu-party > div.hud-party-members > div:nth-child(1)::before { background: #8473d4; } #hud-menu-party > div.hud-party-members > div:nth-child(2)::before { background: #d6ab35; } #hud-menu-party > div.hud-party-members > div:nth-child(3)::before { background: #76bd2f; } #hud-menu-party > div.hud-party-members > div:nth-child(4)::before { background: #d67820; } .hud-party-grid::after { font-size: 200px; position: absolute; bottom: 30px; left: -10px; width: 40%; height: 40%; z-index: -69; font-family: "Font Awesome 5 Free"; font-weight: 10; content: "\\f185"; opacity: 0.1; color: white; } .hud-menu-party .hud-party-grid .hud-party-link.is-active { background: var(--normal-btn) !important; } .hud-menu-party .hud-party-visibility { width: 275.5px; margin: 10px 3px 0 0; background: var(--normal-btn); } .hud-menu-party .hud-party-share { width: 395px; margin: 0 0 0 5px; } /* @UIMenuSettingsStyles */ #hud-menu-settings { background-color: var(--menu-background); border: 4px solid white; margin: 0px; top: calc(50vh - 275px); left: calc(50vw - 360px); width: 720px; height: 550px; overflow: hidden; } .hud-menu-settings::before { font-size: 200px; position: absolute; top: -90px; left: calc(50% - 100px); width: 40%; height: 40%; z-index: -69; font-family: "Font Awesome 5 Free"; font-weight: 10; content: "\\f185"; opacity: 0.1; color: white; } #hud-menu-settings::after { display: block; position: absolute; content: ""; width: 25px; height: 25px; transform: rotate(45deg); margin: 10px; background: white; right: -25px; top: 73px; box-shadow: none; } .hud-menu-settings .hud-settings-grid { height: 390px; margin: 90px 0 0; overflow: hidden; padding: unset; } .hud-settings-page { width: 100%; height: 100%; } .hud-settings-page > span { position: relative; margin: auto; font-size: 17px; opacity: 0.7; } .hud-settings-page .coming-soon { } .hud-settings-options { display: inline-block; position: relative; width: 50%; height: 100%; background: rgba(0, 0, 0, 0.2); padding: 15px; overflow: auto; } .hud-settings-options > div { opacity: 0.8; display: block; position: relative; height: 100px; border-bottom: 2px dashed white; margin-bottom: 15px; } .hud-settings-options h2 { font-family: "Open Sans"; margin: 5px 0 10px 0; font-size: 1.4em; } .hud-settings-options span { display: block; position: absolute; opacity: 0.7; width: 60%; -webkit-font-smoothing: antialiased; } .hud-settings-options button { position: absolute; top: calc(50% - 20px); right: 35px; height: 40px; width: 25%; background: unset; border: none; border-bottom: 3px solid white; color: white; font-size: 18px; cursor: pointer; transition: all 0.15s ease-in-out; } .hud-settings-options a { position: absolute; top: calc(50% - 10px); right: -5px; height: 20px; width: 20px; background: unset; opacity: 0.4; transition: all 0.15s ease-in-out; } .hud-settings-options a::before { font-family: "Font Awesome 5 Free"; content: "\\f054"; font-size: 20px; height: 100%; width: 100%; display: block; font-weight: 900; } .hud-settings-options a:hover { opacity: 1; } .hud-settings-more { position: relative; display: inline-block; width: 50%; height: 100%; padding: 15px; overflow: auto; } .hud-settings-more input { height: 40px; width: 100%; background: rgba(0, 0, 0, 0.2); border: 2px dashed rgba(255, 255, 255, 0.7); border-radius: 4px; padding: 5px; color: #eee; margin: 10px 0; } .hud-settings-more span { display: block; opacity: 0.5; } .hint-controls { position: absolute; display: flex; flex-direction: column; zoom: 83%; width: fit-content; height: 84px; top: 55px; left: 30px; overflow: scroll; } .hint-controls > li { opacity: 0.5; -webkit-font-smoothing: antialiased; margin: 0 5px 0 0; } #select-page { display: flex; justify-content: space-evenly; position: absolute; top: 75px; right: 0px; background-image: linear-gradient(to left, rgba(0, 0, 0, 0.4), transparent); box-shadow: 10px 0 rgb(0 0 0 / 40%); width: 200px; border: 2px solid; border-image: linear-gradient(to right, transparent 5%, rgb(163 163 43) 35%, rgb(206 120 55) 95%); border-image-slice: 1; border-left: none; border-right: none; border-top: none; padding-left: 20px; } #page-name { display: inline-block; -webkit-font-smoothing: antialiased; position: relative; transform: translate(0px, 9px); } `; const styles = document.createElement("style"); styles.type = "text/css"; styles.appendChild(document.createTextNode(css)); document.head.appendChild(styles); function getClass(DOMClass) { return document.getElementsByClassName(DOMClass); }; function getId(DOMId) { return document.getElementById(DOMId); }; /* @Intro */ getId("hud-intro").insertAdjacentHTML("beforeend", `
Sun:Raise
`); getClass("hud-intro-corner-top-left")[0].insertAdjacentHTML("afterbegin", ` Scanner
Scanned data will be shown here once done.
`); getClass("hud-intro-form")[0].insertAdjacentHTML("afterbegin", `
`); getClass("hud-intro-name-container")[0].insertAdjacentElement("afterbegin", document.querySelector("#hud-intro > div.hud-intro-wrapper > div > div > input")); getClass("hud-intro-server-container")[0].insertAdjacentElement("afterbegin", document.querySelector("#hud-intro > div.hud-intro-wrapper > div > div > select")); getClass("hud-intro-play")[0].innerText = ""; document.querySelector("#hud-intro > div.hud-intro-wrapper > div > div > div:nth-child(2)").insertAdjacentElement("afterbegin", document.querySelector("#hud-intro > div.hud-intro-wrapper > div > div > button")); document.querySelector("#hud-intro > div.hud-intro-wrapper > div > div > div:nth-child(2)").insertAdjacentHTML("beforeend", ` Play `); const oldSubmit = game.ui.components.Intro.submitElem; const newSubmit = oldSubmit.cloneNode(true); oldSubmit.parentNode.replaceChild(newSubmit, oldSubmit); game.ui.components.Intro.submitElem = newSubmit; game.ui.components.Intro.onSubmitClick = function (_0x56b3b8) { const realNicknameLength = new Blob([this.nameInputElem.value]).size; if (realNicknameLength > 29) return void game.ui.components.Intro.onConnectionError('Your nickname length is too long. Please shorten it/use less special characters.'); const server = this.ui.getOption(`servers`)[this.serverElem.value]; localStorage.setItem(`name`, this.nameInputElem.value.trim()); this.connecting || ( this.connecting = true, getId("playspan").style && (getId("playspan").innerText = "    "), this.connectionTimer = setTimeout(function () { this.connecting = false; game.network.disconnect(); getId("playspan").style && (getId("playspan").innerText = "Play"); this.serverElem?.classList.add('has-error'); this.errorElem.style.display = 'block'; this.errorElem.innerText = `We failed to join the game - this is a known issue with anti-virus software. Please try disabling any web filtering features.`; }, 15000), this.submitElem.innerHTML = '', this.errorElem.style.display = `none`, this.ui.setOption(`nickname`,this.nameInputElem.value.trim()), this.ui.setOption(`serverId`, this.serverElem.value), game.network.connect(server) ); } newSubmit.onclick = game.ui.components.Intro.onSubmitClick.bind(game.ui.components.Intro); game.ui.components.Intro.checkForPartyInvitation = function () { if (document.location.hash && !(document.location.hash.length < 2)) { var subString = document.location.hash.substring(2).split('/'), serverId = subString[0], partyShareKey = subString[1]; if (serverId && partyShareKey) { this.serverElem.setAttribute(`disabled`, `true`); document.querySelector("#hud-intro > div.hud-intro-wrapper > div > div > div:nth-child(1) > div.hud-intro-server-container > a").style.opacity = '0.4'; this.serverElem.querySelector('option[value=\x22' + serverId + '\x22]').setAttribute(`selected`, 'true'); this.partyShareKey = partyShareKey; /* Game.currentGame.network.addEnterWorldHandler(function (e) { if (e.allowed && !this.reconnectKey) { var packet = { 'name': `JoinPartyByShareKey`, 'partyShareKey': this.partyShareKey }; Game.currentGame.network.sendRpc(packet); } }); */ }; } }; game.ui.components.Intro.checkForPartyInvitation(); (function() { if (!localStorage.savedNames) return; let id = 0; const selectElem = getId("saved-names"), names = [], items = JSON.parse(localStorage.savedNames).map(nameUnfiltered => { const name = window.filterXSS(nameUnfiltered); names.push(nameUnfiltered); return ``; }).join('\n'); selectElem.innerHTML = items; })(); getId("saved-names").addEventListener('change', (e) => { getClass("hud-intro-name")[0].value = e.target.selectedOptions[0].innerText; }); game.network.addEnterWorldHandler((e) => { if (!e.allowed) { try { getId("playspan").innerText = "Play"; game.ui.components.Intro.submitElem.innerText = ''; } catch {}; }; console.log(e); !localStorage.savedNames && (localStorage.savedNames = JSON.stringify([])); const willBeSaved = e.effectiveDisplayName, storage = JSON.parse(localStorage.savedNames); if (storage.find(i => i == willBeSaved) === undefined) { storage.push(willBeSaved); localStorage.savedNames = JSON.stringify(storage); } }); document.getElementsByClassName('hud-party-tag')[0].setAttribute('maxlength', 49); document.getElementsByClassName('hud-intro-name')[0].setAttribute('maxlength', 29); window.sscs = (selected = getClass("hud-intro-server")[0].value) => { const server = game.options.servers[selected]; const hostname = server.hostname; const url = `wss://${hostname}:443/`; let hasSentData = false; document.querySelector("#hud-intro > div.hud-intro-corner-top-left > div").innerHTML = ` This may take 10-20 seconds. `; const iframe = document.createElement('iframe'); iframe.src = `https://zombs.io/`; iframe.style.display = 'none'; document.body.append(iframe); game.network.connectionOptions = { ipAddress: server.ipAddress }; game.network.connected = true; iframe.addEventListener("load", () => { const _game = iframe.contentWindow.game; _game.network.connectionOptions = { ipAddress: server.ipAddress }; _game.network.connected = true; const ws = new WebSocket(url); ws.binaryType = "arraybuffer"; ws.isclosed = false; const loadLbPacket = () => { for (let i = 0; i < 30; i++) ws.send(new Uint8Array([3, 17, 123, 34, 117, 112, 34, 58, 49, 44, 34, 100, 111, 119, 110, 34, 58, 48, 125])); // move packet ws.send(new Uint8Array([7, 0])); // ping ws.send( new Uint8Array( [9,6,0,0,0,126,8,0,0,108,27,0,0,146,23,0,0,82,23,0,0,8,91,11,0,8,91,11,0,0,0,0,0,32,78,0,0,76,79,0,0,172,38,0,0,120,155,0,0, 166,39,0,0,140,35,0,0,36,44,0,0,213,37,0,0,100,0,0,0,120,55,0,0,0,0,0,0,0,0,0,0,100,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,134,6,0,0] ) ); // metrics }; ws.onopen = (data) => { ws.network = new game.networkType(); ws.send(new Uint8Array([7, 0])); ws.sendPacket = (e, t) => { let enc; if (e == 6) { enc = _game.network.codec.encode(e, t); } else { enc = ws.network.codec.encode(e, t); } !ws.isclosed && ws.send(enc); }; ws.onRpc = (data) => { if(data.name === "SetPartyList") { ws.parties = data.response; }; if(data.name === "Leaderboard") { if (ws.b4) { window.appSsrs({ population: ws.pop, leaderboard: data, parties: ws.parties, server: server }); hasSentData = true; ws.close(); return; }; loadLbPacket(); ws.b4 = true; }; }; ws.onmessage = msg => { const dataArray = new Uint8Array(msg.data); let data; if (dataArray[0] == 5) { ws.network.codec.decodePreEnterWorldResponse = buffer => buffer; const _data = ws.network.codec.decode(msg.data); data = _game.network.codec.decodePreEnterWorldResponse(_data); data = {opcode: 5, ...data}; } else data = ws.network.codec.decode(msg.data); switch(data.opcode) { case 5: ws.sendPacket(4, { displayName: `${new Date().toLocaleString()}`, extra: data.extra }); break; case 4: if (!data.allowed) { const lbData = {name: "Leaderboard", response: [{name: "Server full.", uid: 727, rank: 0, score: 0, wave: 0}], opcode: 9}; window.appSsrs({ population: 32, leaderboard: lbData, parties: [], server: server }); hasSentData = true; } else { ws.sendPacket(6, {}); ws.sendPacket(3, { left: 1, up: 1 }); ws.sendPacket(3, {mouseMovedWhileDown: 0}); ws.sendPacket(3, {space: 0}); ws.sendPacket(3, {space: 1}); ws.pop = data.players; } break; case 9: ws.onRpc(data); break; }; }; ws.onclose = () => { ws.isclosed = true; if (!hasSentData) { const lbData = {name: "Leaderboard", response: [{name: "Unable to access.", uid: 727, rank: 0, score: 0, wave: 0}], opcode: 9}; window.appSsrs({ population: null, leaderboard: lbData, parties: [], server: server }); hasSentData = true; } iframe.remove(); } }; }); }; window.appSsrs = res => { console.log(res); if (res.population !== null) { getClass("hud-intro-server")[0].value = res.server.id; getClass("hud-intro-server")[0].selectedOptions[0].innerText = `${res.server.name} [${res.population}/32]`; } const leaderboard = res.leaderboard.response; const ssrs = getClass("hud-intro-scan-data")[0]; ssrs.innerHTML = `

Population: ${res.population === null ? "Cannot fetch" : res.population}

${leaderboard.map(lb => { return `
#${lb.rank + 1} ${window.filterXSS(lb.name)} ${lb.score.toLocaleString("en")} ${lb.wave.toLocaleString("en")}
`; }).join("\n")}

${res.parties.map(p => { return `
${p.memberCount} ${window.filterXSS(p.partyName)} ${p.isOpen ? "Public" : "Private"} ${p.partyId}
`; }).join("\n")}
`; }; /* @UI */ // @Chat game.ui.components.Chat.chatResize = function() { this.messagesElem.style.height = (this.componentElem.offsetHeight - 40) + "px"; this.componentElem.scrollTop = this.messagesElem.scrollHeight; } game.ui.components.Chat.blockedNames = []; game.ui.components.Chat.emojiList = { // static emojis hmm: "https://cdn.discordapp.com/emojis/724365641963929611.png?size=48", pog: "https://cdn.discordapp.com/emojis/721070353337811026.png?size=48", pepehands: "https://cdn.discordapp.com/emojis/733406770139103293.png?size=48", pepeEyes: "https://cdn.discordapp.com/emojis/869573233794486323.gif?size=48", pepeHappy: "https://cdn.discordapp.com/emojis/801475958883614811.png?size=48", sadge: "https://cdn.discordapp.com/emojis/826530556974989344.png?size=48", ha: "https://cdn.discordapp.com/emojis/782756472886525953.png?size=48", kekw: "https://cdn.discordapp.com/emojis/748511358076846183.png?size=48", pogEyes: "https://cdn.discordapp.com/emojis/786979080406564885.png?size=48", appalled: "https://cdn.discordapp.com/emojis/830880294881853530.png?size=48", pogYou: "https://cdn.discordapp.com/emojis/790293794716516430.png?size=48", pogChag: "https://cdn.discordapp.com/emojis/831156303497134090.png?size=48", pogey: "https://cdn.discordapp.com/emojis/790293759861719050.png?size=48", weirdChamp: "https://cdn.discordapp.com/emojis/757553915389673502.png?size=48", monkaS: "https://cdn.discordapp.com/emojis/757179783573405766.png?size=48", yep: "https://cdn.discordapp.com/emojis/758356179477987339.png?size=48", // animated emojis / gif weirdButOkay: "https://cdn.discordapp.com/emojis/831156194247966782.gif?size=48", pogpogpogpog: "https://cdn.discordapp.com/emojis/869580566096379974.gif?size=48", wooyeah: "https://cdn.discordapp.com/emojis/791008461420888084.gif?size=48", idk: "https://cdn.discordapp.com/emojis/882513306164805642.gif?size=48", }; game.ui.components.Chat.blockPlayer = function(name) { game.ui.components.PopupOverlay.showConfirmation(`Are you sure you want to block ${window.filterXSS(name)}?`, 3500, () => { this.blockedNames.push(name); for (let msg of Array.from(document.getElementsByClassName("hud-chat-message"))) { if (msg.childNodes[1].innerText === ' ' + name) { let bl = msg.childNodes[0]; bl.innerHTML = "Unblock"; bl.style.color = "blue"; bl.onclick = () => this.unblockPlayer(name); }; }; }, () => {}); }; game.ui.components.Chat.unblockPlayer = function(name) { this.blockedNames.splice(this.blockedNames.indexOf(name), 1); for (let msg of Array.from(document.getElementsByClassName("hud-chat-message"))) { if (msg.childNodes[1].innerText === ' ' + name) { let bl = msg.childNodes[0]; bl.innerHTML = "Block"; bl.style.color = "red"; bl.onclick = () => this.blockPlayer(name); }; }; }; game.ui.components.Chat.onMessageReceived = function(e) { if (this.blockedNames.includes(e.displayName) || window.chatDisabled) return; let a = this, b = window.filterXSS(e.displayName), c = window.filterXSS(e.message) .replace(/(?:f|F)uck/gi, ``) .replace(/s[3e]x+/gi, ``) .replace(/n+[i1]+gg+[a@]+/i, ``); let arr = c.split(':'); for (let i = 1; i < arr.length; i += 2) { if (!this.emojiList[arr[i]]) arr = [c]; else arr[i] = ``; } let d = a.ui.createElement(`
Block ${b}: ${arr.join(" ")}${getClock()}
`); d.children[0].onclick = () => game.ui.components.Chat.blockPlayer(b); a.messagesElem.appendChild(d); a.messagesElem.scrollTop = a.messagesElem.scrollHeight; } new ResizeObserver(game.ui.components.Chat.chatResize.bind(game.ui.components.Chat)).observe(getId("hud-chat")); Game.currentGame.network.emitter.removeListener("PACKET_RPC", Game.currentGame.network.emitter._events.PACKET_RPC[1]); Game.currentGame.network.addRpcHandler("ReceiveChatMessage", game.ui.components.Chat.onMessageReceived.bind(game.ui.components.Chat)); // @Zoom getId('hud').insertAdjacentHTML('beforeend', `
1.0x Button N to zoom in
M to zoom out
`); game.zoom = { dimension: 1, zoomonscroll: false, upd: function() { getClass('zoom-prop')[0].innerText = `${this.dimension.toFixed(1)}x`; this.dimension = Math.max(0.1, this.dimension); const renderer = Game.currentGame.renderer; let canvasWidth = window.innerWidth * window.devicePixelRatio; let canvasHeight = window.innerHeight * window.devicePixelRatio; let ratio = canvasHeight / (1080 * this.dimension); renderer.scale = ratio; renderer.entities.setScale(ratio); renderer.ui.setScale(ratio); renderer.renderer.resize(canvasWidth, canvasHeight); renderer.viewport.width = renderer.renderer.width / renderer.scale + 2 * renderer.viewportPadding; renderer.viewport.height = renderer.renderer.height / renderer.scale + 2 * renderer.viewportPadding; }, onWindowResize: function(e) { if (this.zoomonscroll) { if (e.deltaY > 0) this.dimension += 0.02; else if (e.deltaY < 0) this.dimension -= 0.02; } this.upd(); }, zoom: function(val) { this.dimension = val; this.upd(); }, toggleZoomOnScroll: function() { this.dimension -= 0.02; this.zoomonscroll = !this.zoomonscroll; const zoomMode = document.querySelector("#zoom-mode"); const zoomBtns = [...document.getElementsByClassName('hud-zoom-item')]; if (!this.zoomonscroll) { this.resetZoom(); for (let i of zoomBtns) i.classList.remove('tag-is-disabled'); zoomMode.innerText = "Button"; } else { zoomMode.innerText = "Scroll"; for (let i of zoomBtns) i.classList.add('tag-is-disabled'); } }, zoomOut: function() { this.dimension += 1; this.zoom(this.dimension); }, zoomIn: function() { this.dimension -= 1; this.zoom(this.dimension); }, resetZoom: function() { this.dimension = 1; this.zoom(this.dimension); } }; game.zoom.onWindowResize(); window.onresize = game.zoom.onWindowResize.bind(game.zoom); window.onwheel = game.zoom.onWindowResize.bind(game.zoom); /* @Party */ game.ui.components.MenuParty.loaded = false; game.ui.components.MenuParty.serverPopulation = 0; game.ui.components.MenuParty.closedParties = null; game.ui.components.MenuParty.shareKeyLog = null; game.ui.components.MenuParty.partyMenu = getClass("hud-menu-party")[0]; game.ui.components.MenuParty.partyTabs = getClass("hud-party-tabs")[0]; game.ui.components.MenuParty.partyMembers = getClass("hud-party-members")[0]; game.ui.components.MenuParty.partyGrid = getClass("hud-party-grid")[0]; game.ui.components.MenuParty.init = function() { if (this.loaded) return; this.loaded = true; this.partyMembers.style.display = "block"; this.partyGrid.style.display = "none"; const privateTab2 = document.createElement("a"); privateTab2.className = "hud-party-tabs-link"; privateTab2.id = "privateTab2"; privateTab2.innerHTML = "Closed Parties"; this.closedParties = document.createElement("div"); this.closedParties.className = "hud-private hud-party-grid"; this.closedParties.id = "privateHud2"; this.closedParties.style.display = "none"; this.partyTabs.appendChild(privateTab2); this.partyMenu.insertBefore(this.closedParties, getClass("hud-party-actions")[0]); const privateTab = document.createElement("a"); privateTab.className = "hud-party-tabs-link"; privateTab.id = "privateTab"; privateTab.innerHTML = "Key Logs"; this.shareKeyLog = document.createElement("div"); this.shareKeyLog.className = "hud-private hud-party-grid"; this.shareKeyLog.id = "privateHud"; this.shareKeyLog.style.display = "none"; this.partyTabs.appendChild(privateTab); this.partyMenu.insertBefore(this.shareKeyLog, getClass("hud-party-actions")[0]); privateTab.addEventListener("click", e => { for (let menu of [this.partyMembers, this.partyGrid, this.closedParties, this.shareKeyLog]) { menu.style.display == "block" && (menu.style.display = "none"); } for (let i of getClass("hud-party-tabs-link")) i.className = "hud-party-tabs-link"; privateTab.className = "hud-party-tabs-link is-active"; this.shareKeyLog.style.display = "block"; }) privateTab2.addEventListener("click", e => { for (let menu of [this.partyMembers, this.partyGrid, this.closedParties, this.shareKeyLog]) { menu.style.display == "block" && (menu.style.display = "none"); } for (let i of getClass("hud-party-tabs-link")) i.className = "hud-party-tabs-link"; privateTab2.className = "hud-party-tabs-link is-active"; this.closedParties.style.display = "block"; }) getClass("hud-party-tabs-link")[0].addEventListener("click", e => { this.shareKeyLog.style.display = "none"; privateTab.className = "hud-party-tabs-link"; this.closedParties.style.display = "none"; privateTab2.className = "hud-party-tabs-link"; }) getClass("hud-party-tabs-link")[1].addEventListener("click", e => { this.shareKeyLog.style.display = "none"; privateTab.className = "hud-party-tabs-link"; this.closedParties.style.display = "none"; privateTab2.className = "hud-party-tabs-link"; }) } game.ui.components.MenuParty.onSetPartyList = function(parties) { this.serverPopulation = 0; for (let party of parties) this.serverPopulation += party.memberCount; document.getElementsByClassName("hud-party-server")[0].innerHTML = `${this.serverPopulation}/32`; } game.ui.components.MenuParty.onPartyShareKey = function(e) { const psk = e.partyShareKey, lnk = `https://zombs.io/#/${game.options.serverId}/${psk}/`; this.shareKeyLog.innerHTML += `
  • ${psk} - [Link]

  • `; } game.ui.components.MenuParty.update = function () { var parties = this.ui.getParties(); var playerIsLeader = this.ui.getPlayerPartyLeader(); var playerPartyData = parties[this.ui.getPlayerPartyId()]; var playerPartyMembers = this.ui.getPlayerPartyMembers(); var serverId = this.ui.getOption('serverId'); var staleElems = {}; var availableParties = 0; this.clonedPartyElems ||= {}; this.closedGridElem ||= getId("privateHud2"); for (var partyId in this.partyElems) { staleElems[partyId] = true; } for (var partyId in parties) { var partyData = parties[partyId]; var partyElem = this.partyElems[partyId]; var partyNameSanitized = window.filterXSS(partyData.partyName); delete staleElems[partyId]; if (!this.partyElems[partyId]) { partyElem = this.ui.createElement("
    "); this.clonedPartyElems[partyId] = this.ui.createElement("
    "); this.partyElems[partyId] = partyElem; this.gridElem.appendChild(partyElem); this.closedGridElem.appendChild(this.clonedPartyElems[partyId]); partyElem.addEventListener('click', this.onPartyJoinRequestHandler(partyData.partyId).bind(this)); } if (partyData.isOpen) { partyElem.style.display = 'block'; this.clonedPartyElems[partyId].style.display = "none"; availableParties++; } else { partyElem.style.display = 'none'; this.clonedPartyElems[partyId].style.display = "block"; } if (this.ui.getPlayerPartyId() === partyData.partyId) { partyElem.classList.add('is-active'); partyElem.classList.remove('is-disabled'); this.clonedPartyElems[partyId].classList.add('is-active'); this.clonedPartyElems[partyId].classList.remove('is-disabled'); } else if (partyData.memberCount === this.maxPartySize) { partyElem.classList.remove('is-active'); partyElem.classList.add('is-disabled'); this.clonedPartyElems[partyId].classList.remove('is-active'); this.clonedPartyElems[partyId].classList.add('is-disabled'); } else { partyElem.classList.remove('is-active'); partyElem.classList.remove('is-disabled'); this.clonedPartyElems[partyId].classList.remove('is-active'); this.clonedPartyElems[partyId].classList.remove('is-disabled'); } partyElem.innerHTML = "" + partyNameSanitized + "id: " + partyData.partyId + " " + partyData.memberCount + "/" + this.maxPartySize + ""; this.clonedPartyElems[partyId].innerHTML = "" + partyNameSanitized + "id: " + partyData.partyId + " " + partyData.memberCount + "/" + this.maxPartySize + ""; } for (var partyId in staleElems) { if (!this.partyElems[partyId]) { continue; } this.partyElems[partyId].remove(); this.clonedPartyElems[partyId].remove(); delete this.partyElems[partyId]; delete this.clonedPartyElems[partyId]; } for (var i in this.memberElems) { this.memberElems[i].remove(); delete this.memberElems[i]; } for (var i in playerPartyMembers) { var playerName = window.filterXSS(playerPartyMembers[i].displayName); var memberElem = this.ui.createElement( "
    \n " + playerName + "\n " + (playerPartyMembers[i].isLeader === 1 ? 'Leader' : 'Member') + "\n \n
    " ); this.membersElem.appendChild(memberElem); this.memberElems[i] = memberElem; if (playerIsLeader && playerPartyMembers[i].isLeader === 0) { var kickElem = memberElem.querySelector('.hud-member-kick'); var canSellElem = memberElem.querySelector('.hud-member-can-sell'); kickElem.addEventListener('click', this.onPartyMemberKick(i).bind(this)); canSellElem.addEventListener('click', this.onPartyMemberCanSellToggle(i).bind(this)); } } if (availableParties > 0) { this.gridEmptyElem.style.display = 'none'; } else { this.gridEmptyElem.style.display = 'block'; } if (!playerPartyData) { this.tagInputElem.setAttribute('disabled', 'true'); this.tagInputElem.value = ''; this.shareInputElem.setAttribute('disabled', 'true'); this.shareInputElem.value = ''; this.visibilityElem.classList.add('is-disabled'); return; } if (document.activeElement !== this.tagInputElem) { this.tagInputElem.value = playerPartyData.partyName; } if (playerIsLeader) { this.tagInputElem.removeAttribute('disabled'); } else { this.tagInputElem.setAttribute('disabled', 'true'); } this.shareInputElem.removeAttribute('disabled'); this.shareInputElem.value = 'https://zombs.io/#/' + serverId + '/' + this.ui.getPlayerPartyShareKey(); if (playerIsLeader) { this.visibilityElem.classList.remove('is-disabled'); } else { this.visibilityElem.classList.add('is-disabled'); } if (playerPartyData.isOpen) { this.visibilityElem.classList.remove('is-private'); this.visibilityElem.innerText = 'Public'; } else { this.visibilityElem.classList.add('is-private'); this.visibilityElem.innerText = 'Private'; } } getClass("hud-party-actions")[0].insertAdjacentHTML("afterend", `
    `); game.ui.components.MenuParty.init(); game.network.addRpcHandler("PartyShareKey", (e) => game.ui.components.MenuParty.onPartyShareKey(e)); game.network.addRpcHandler("SetPartyList", (e) => game.ui.components.MenuParty.onSetPartyList(e)); /* @Settings @ModMenu */ getId('hud-menu-settings').innerHTML = `

    Advanced

    -
    `; getClass('hud-settings-grid')[0].innerHTML = `
    Coming soon...
    Coming soon...
    `; const hint_enum = { 0: `
  • Shift + 1 [!] toggles Wall Block.
  • Comma [,] toggles Rebuilder.
  • Period [.] toggles Auto Upgrade.
  • `, 1: `
  • C toggles quick join via PSK input.
  • G toggles zoom menu.
  • Dash [-] toggles local info indicators.
  • Equal [=] toggles Auto Bow.
  • `, 2: `
  • ? toggles Screenshot Mode.
  • ~ marks your position.
  • `, 3: ``, }; const pageName_enum = { 0: 'Build', 1: 'Player', 2: 'Visual', 3: 'Misc.', }; /* const optionElem_enum = { name: 'h2', description: 'span', } */ const menu = { page0: { AHRC: { name: `AHRC`, description: `Automatically harvests resources.`, more: null }, rebuild: { name: `Auto Rebuilder`, description: `Automatically rebuilds dead towers.`, more: null, onCallback: () => { game.rebuilder.saveTowers(); }, offCallback: () => { game.rebuilder.reset(); }, }, autoUpgrade: { name: `Auto Upgrader`, description: `Automatically upgrades towers.`, more: null }, wallBlock: { name: `Wall Block`, description: `Allows you to place mulitple walls at once.`, more: { html: ` Change the size of the block that will be placed. Default value is 5x5, maximum is 15x15 (cells).
    Width: Height:
    `, functions: () => {} }, } }, page1: { chatSpam: { name: `Chat Spammer`, description: `Annoys other players with messages.`, more: { html: ` Input the text that you want to spam. If no text is inputted, random messages with be sent. `, functions: () => { const spamInputElem = getId("chat-spam-input"); spamInputElem.oninput = game.spam.onchange.bind(game.spam); } }, onCallback: () => { game.spam.start(); }, offCallback: () => { game.spam.stop(); }, }, autoAim: { name: `Auto Aim`, description: "Aims at the nearest player.", more: null } }, /* page2: { }, page3: { } */ }; function refreshMore(page) { const container = document.querySelector("#" + page + " > div.hud-settings-more"); for (let children of container.children) { children.style.display = "none"; } } function refreshPage(pageState, page) { for (let i = 0; i < 4; i++) getId(`page${i}`).style.display = "none"; }; function setPage(page) { const pageState = page; switch(page) { case "forward": page = parseInt(getClass('hud-settings-grid')[0].getAttribute('page')) + 1; break; case "backwards": page = parseInt(getClass('hud-settings-grid')[0].getAttribute('page')) - 1; break; } refreshPage(pageState, page); if (page < 0) page = 3; if (page > 3) page = 0; getId(`page${page}`).style.display = "flex"; getId('page-name').innerText = pageName_enum[page]; getClass('hint-controls')[0].innerHTML = hint_enum[page]; getClass('hud-settings-grid')[0].setAttribute('page', page); }; setPage('0'); getId('back-page').addEventListener('click', () => setPage("backwards")); getId('forward-page').addEventListener('click', () => setPage("forward")); /* @Functions */ // @Options game.options.options = { autoBow: false, getRSS: false, AHRC: false, rebuild: false, autoUpgrade: false, heal: true, revive: true, frss: false, chatSpam: false, autoAim: false, wallBlock: false, } // @Marker game.markers = { currentIndex: 0, allMarkers: [], placeMarker: function({x, y, id, timeout, shouldIndicateIndex}) { id ||= Math.random(); shouldIndicateIndex && (this.currentIndex++); const markerLeft = parseInt(Math.round(x / game.world.getWidth() * 100)) - 4; const markerTop = parseInt(Math.round(y / game.world.getHeight() * 100)) - 14; const markerElem = document.createElement("div"); markerElem.style.left = `${markerLeft}%`; markerElem.style.top = `${markerTop}%`; markerElem.style.display = "block"; markerElem.style.color = "white"; markerElem.style.position = "absolute"; markerElem.classList.add("map-display"); markerElem.id = id; markerElem.innerHTML = `${shouldIndicateIndex ? this.currentIndex : ""}`; getId("hud-map").insertAdjacentElement("beforeend", markerElem); this.allMarkers.push({x, y}); timeout && setTimeout(() => { getId(`${id}`).remove(); }, 240000); } } // @RSSOverhead game.rssOverhead = { allowedRSS: true, assignOldTick: function(player, playerTick) { const [wood_1, stone_1, gold_1, token_1, px_1, py_1, info] = playerTick; player.targetTick.oldWood = wood_1; player.targetTick.oldStone = stone_1; player.targetTick.oldGold = gold_1; player.targetTick.oldToken = token_1; player.targetTick.oldPX = px_1; player.targetTick.oldPY = py_1; player.targetTick.info = info; player.targetTick.name = player.targetTick.info; }, onTick: function(entities) { const options = game.options.options; if (options.getRSS) !this.allowedRSS && (this.allowedRSS = true); if (options.getRSS || this.allowedRSS) { for (let uid in entities) { const player = game.world.entities[uid]; if (!!player?.fromTick?.name) { let wood_1 = counter(player.targetTick.wood); let stone_1 = counter(player.targetTick.stone); let gold_1 = counter(player.targetTick.gold); let token_1 = counter(player.targetTick.token); let px_1 = counter(player.targetTick.position.x); let py_1 = counter(player.targetTick.position.y); let timeout_1 = player.targetTick.isPaused ? "On Timeout" : ""; if (options.getRSS && !player.targetTick.oldName) { player.targetTick.oldName = player.targetTick.name; let info = ` ${window.filterXSS(player.targetTick.oldName)}; score: ${player.targetTick.score.toLocaleString()} UID: ${player.targetTick.uid} W: ${wood_1}, S: ${stone_1}, G: ${gold_1}, T: ${token_1} partyId: ${Math.round(player.targetTick.partyId)} timeDead: ${msToTime(player.targetTick.timeDead)} ${timeout_1} `; this.assignOldTick(player, [wood_1, stone_1, gold_1, token_1, px_1, py_1, info]); } if (!options.getRSS && player.targetTick.oldName) { player.targetTick.info = player.targetTick.oldName; player.targetTick.name = player.targetTick.info; player.targetTick.oldName = null; } if (options.getRSS) { if (player.targetTick.oldGold !== gold_1 || player.targetTick.oldWood !== wood_1 || player.targetTick.oldStone !== stone_1 || player.targetTick.oldToken !== token_1 || player.targetTick.oldPX !== px_1 || player.targetTick.oldPY !== py_1) { let info = ` ${window.filterXSS(player.targetTick.oldName)}; score: ${player.targetTick.score.toLocaleString()} UID: ${player.targetTick.uid} W: ${wood_1}, S: ${stone_1}, G: ${gold_1}, T: ${token_1} partyId: ${Math.round(player.targetTick.partyId)} timeDead: ${msToTime(player.targetTick.timeDead)} ${timeout_1} `; this.assignOldTick(player, [wood_1, stone_1, gold_1, token_1, px_1, py_1, info]); } } } } } if (!options.getRSS) this.allowedRSS = false; }, } // @AHRC game.ahrc = { checkedHarvesters: new Set(), workingHarvesters: new Set(), onTick: function() { const options = game.options.options; if (options.AHRC) { for (let uid in game.world.entities) { const entity = game.world.entities[uid]; if (entity.targetTick.model == "Harvester" && entity.targetTick.partyId == game.ui.playerPartyId && game.ui.playerTick.gold > 0.69) { if (this.checkedHarvesters.has(uid)) { if (entity.fromTick.stone !== entity.targetTick.stone || entity.fromTick.wood !== entity.targetTick.wood) { this.workingHarvesters.add(uid); }; } else { this.checkedHarvesters.add(uid); game.network.sendRpc({name: "AddDepositToHarvester", uid: parseInt(uid), deposit: 0.69}); }; }; if (this.workingHarvesters.has(uid)) { const amount = entity.fromTick.tier * 0.05 - 0.02; game.network.sendRpc({name: "AddDepositToHarvester", uid: parseInt(uid), deposit: amount}); game.network.sendRpc({name: "CollectHarvester", uid: parseInt(uid)}); }; }; } } } // @Rebuilder game.rebuilder = { savedTowers: new Map(), shouldBeReplaced: [], goldStash: null, reset: function() { this.savedTowers = new Map(); }, saveTowers: function() { for (let i in game.ui.buildings) { const {x, y, type} = game.ui.buildings[i]; this.savedTowers.set(parseInt(i), {x, y, type}); } }, onLocalBuilding: function(buildings) { const options = game.options.options; const allBuildings = Object.values(game.ui.buildings); this.goldStash = allBuildings.find(building => building.type == "GoldStash"); if (options.rebuild) { for (let i in buildings) { const {dead, uid, x, y, type} = buildings[i]; if (dead === 1) { if (this.savedTowers.get(uid) !== undefined) { this.shouldBeReplaced.push({x, y, type}); } } else { const replacedBuilding = getByValue(this.savedTowers, {x, y, type}); if (replacedBuilding) { this.savedTowers.set(parseInt(uid), {x, y, type}); this.shouldBeReplaced = this.shouldBeReplaced.filter(e => !equal(e, {x, y, type})); console.log(this.shouldBeReplaced); } } } } }, onTick: function(entities) { const options = game.options.options; if (options.rebuild && this.goldStash) { for (let i = this.shouldBeReplaced.length - 1; i >= 0; i--) { const deadTower = this.shouldBeReplaced[i]; const {x, y, type} = deadTower; game.network.sendRpc({name: "MakeBuilding", type, x, y, yaw: 0}); } } }, }; game.autoAim = { targets: [], onTick: function() { const options = game.options.options; if (options.autoAim) { this.targets = []; const entities = Object.values(game.world.entities); for (let entity of entities) { if (entity.fromTick.model == "GamePlayer" && entity.targetTick.partyId !== game.ui.playerPartyId && entity.fromTick.dead == 0) { this.targets.push(entity.fromTick); }; }; if (this.targets.length > 0) { const myPos = game.ui.playerTick.position; this.targets.sort((a, b) => { return measureDistance(myPos, a.position) - measureDistance(myPos, b.position); }); const target = this.targets[0]; let reversedAim = game.inputPacketCreator.screenToYaw((target.position.x - myPos.x) * 100, (target.position.y - myPos.y) * 100); game.inputPacketCreator.lastAnyYaw = reversedAim; game.network.sendPacket(3, {mouseMoved: reversedAim}); } }; } }; // @Buildings game.ui.components.BuildingOverlay.createResourceCostString = function (schema, schemaTier, amountOfBuildings) { void 0 === schemaTier && (schemaTier = 0x1); void 0 === amountOfBuildings && (amountOfBuildings = 0x1); var totalCost = [], resources = { 'wood': `wood`, 'stone': `stone`, 'gold': 'gold', 'token': 'tokens' }, playerTick = Game.currentGame.ui.getPlayerTick(); for (var resource in resources) { var resourceCost = resource + `Costs`; if (schema[resourceCost] && schema[resourceCost][schemaTier - 1]) { var currentTotalCost = schema[resourceCost][schemaTier - 1] * amountOfBuildings, canAfford = playerTick && playerTick[resource] >= currentTotalCost; canAfford ? totalCost.push('' + currentTotalCost.toLocaleString() + '\x20' + resources[resource] + ``) : totalCost.push(`` + currentTotalCost.toLocaleString() + '\x20' + resources[resource] + ``); } } return totalCost.length > 0 ? totalCost.join(',\x20') : `Free`; } game.ui.components.BuildingOverlay.createResourceRefundString = function (buildingType, buildingSchema, tier) { void 0 === tier && (tier = 1); var totalCost = [], buildingsByTier = {}, buildings = Object.values(game.ui.buildings).filter(e => e.type == buildingType), resources = { 'wood': `wood`, 'stone': `stone`, 'gold': `gold`, 'token': 'tokens' }; for (let building of buildings) { buildingsByTier[building.tier] ||= 0; buildingsByTier[building.tier]++; } for (var resource in resources) { var resourceCost = resource + `Costs`; if (buildingSchema[resourceCost]) { var totalTierCost = 0; if (this.shouldUpgradeAll) { for (let i = 1; i <= tier; i++) { totalTierCost = Math.floor( buildingSchema[resourceCost].slice(0, i) .reduce((prev, curr) => prev + curr, 0) / 2 ) * buildingsByTier[i]; } } else totalTierCost = Math.floor(buildingSchema[resourceCost].slice(0, tier).reduce((prev, curr) => prev + curr, 0) / 2); totalTierCost && totalCost.push('' + totalTierCost.toLocaleString() + '\x20' + resources[resource] + ``); } } return totalCost.length > 0 ? totalCost.join(',\x20') : `None`; } game.ui.components.BuildingOverlay.sellBuilding = function () { if (this.buildingUid) { if ('GoldStash' == this.buildingId) { game.ui.components.PopupOverlay.showConfirmation(`Are you sure you want to delete all buildings?`, 5000, function() { sellAll(); }); return this.stopWatching(); } if (this.shouldUpgradeAll) { const id = this.buildingId; game.ui.components.PopupOverlay.showConfirmation(`Are you sure you want to delete all buildings of this type?`, 5000, function() { sellAllByType(id); }); } else Game.currentGame.network.sendRpc({name: 'DeleteBuilding', uid: this.buildingUid}); } } game.ui.components.BuildingOverlay.startWatching = function(buildingId) { this.buildingUid && this.stopWatching(); let buildings = this.ui.getBuildings(), building = buildings[buildingId]; if (!building) return; this.buildingUid = buildingId; this.buildingId = building.type; this.buildingTier = building.tier; let schema = this.ui.getBuildingSchema(), buildingSchema = schema[this.buildingId]; if ('GoldStash' == this.buildingId) { var world = Game.currentGame.world, cellSize = world.entityGrid.getCellSize(); this.rangeIndicator = game.assetManager.loadModel('RangeIndicatorModel', { 'width': this.maxStashDistance * cellSize * 2, 'height': this.maxStashDistance * cellSize * 2 }); Game.currentGame.renderer.ground.addAttachment(this.rangeIndicator); } else { buildingSchema.rangeTiers && ( this.rangeIndicator = game.assetManager.loadModel('RangeIndicatorModel', { 'isCircular': true, 'radius': buildingSchema.rangeTiers[this.buildingTier - 1] * 0.57071 }), Game.currentGame.renderer.ground.addAttachment(this.rangeIndicator) ); }; this.componentElem.innerHTML = `

    ` + buildingSchema.name + `

    Tier ` + this.buildingTier + ` Building

    `; this.tierElem = this.componentElem.querySelector(`.hud-building-tier`); this.healthBarElem = this.componentElem.querySelector(`.hud-tooltip-health-bar`); this.statsElem = this.componentElem.querySelector(`.hud-building-stats`); this.actionsElem = this.componentElem.querySelector(`.hud-building-actions`); this.depositElem = this.componentElem.querySelector(`.hud-building-deposit`); this.dualBtnElem = this.componentElem.querySelector(`.hud-building-dual-btn`); this.collectElem = this.componentElem.querySelector(`.hud-building-collect`); this.upgradeElem = this.componentElem.querySelector('.hud-building-upgrade'); this.sellElem = this.componentElem.querySelector('.hud-building-sell'); `Harvester` !== this.buildingId && (this.dualBtnElem.style.display = `none`); this.depositElem.addEventListener(`click`, this.depositIntoBuilding.bind(this)); this.collectElem.addEventListener(`click`, this.collectFromBuilding.bind(this)); this.upgradeElem.addEventListener(`click`, this.upgradeBuilding.bind(this)); this.sellElem.addEventListener(`click`, this.sellBuilding.bind(this)); this.show(); this.update(); } game.ui.components.BuildingOverlay.update = function () { if (this.buildingUid) { const buildingEntity = Game.currentGame.world.getEntityByUid(this.buildingUid); if (!buildingEntity) return void this.stopWatching(); let renderer = Game.currentGame.renderer, buildingUiPosition = renderer.worldToScreen(buildingEntity.getPositionX(), buildingEntity.getPositionY()), buildingTick = buildingEntity.getTargetTick(), buildingsSchema = this.ui.getBuildingSchema(), buildings = this.ui.getBuildings(), buildingSchema = buildingsSchema[this.buildingId], building = buildings[this.buildingUid]; if (!building) return void this.stopWatching(); let buildingHeight = buildingSchema.gridHeight, buildingScale = (buildingSchema.gridWidth, buildingHeight / 2 * 48 * (renderer.getScale() / window.devicePixelRatio)), buildingTier = building.tier, buildingSchemaTier = 1, isBuildingMaxed = false, isBuildingAtMaxTier = false, currentStats = {}, nextTierStats = {}, sameBuildings = 1, buildingStats = { 'health': `Health`, 'damage': `Damage`, 'range': 'Range', 'gps': 'Gold/Sec', 'harvest': `Harvest/Sec`, 'harvestCapacity': `Capacity` }; if (buildingSchema.tiers) { const stashTier = this.getGoldStashTier(); building.tier < buildingSchema.tiers ? (buildingSchemaTier = building.tier + 1, isBuildingMaxed = false) : (buildingSchemaTier = building.tier, isBuildingMaxed = true); isBuildingAtMaxTier = !isBuildingMaxed && (building.tier < stashTier || `GoldStash` === this.buildingId); } for (let buildingStat in buildingStats) { let currentStat = ``, nextTierStat = ''; buildingSchema[buildingStat + `Tiers`] && ( currentStat = buildingSchema[buildingStat + `Tiers`][buildingTier - 1].toLocaleString(), isBuildingMaxed || ( nextTierStat = buildingSchema[buildingStat + 'Tiers'][buildingSchemaTier - 1].toLocaleString() ), currentStats[buildingStat] = '

    ' + buildingStats[buildingStat] + `: ` + currentStat + '

    ', nextTierStats[buildingStat] = `

    ` + buildingStats[buildingStat] + ':\x20' + nextTierStat + `

    ` ); } if (this.shouldUpgradeAll) { sameBuildings = 0; for (let buildingUid in buildings) { // parseInt(buildingUid); tf buildings[buildingUid].type === this.buildingId && buildings[buildingUid].tier === building.tier && sameBuildings++; } } let costString = this.createResourceCostString(buildingSchema, buildingSchemaTier, sameBuildings), refundString = this.createResourceRefundString(this.buildingId, buildingSchema, building.tier), buildingHealth = Math.round(buildingTick.health / buildingTick.maxHealth * 100); buildingTick.partyId !== this.ui.getPlayerPartyId() ? this.actionsElem.style.display = `none` : this.actionsElem.style.display = 'block'; this.tierElem.innerHTML = building.tier.toString(); this.buildingTier = building.tier; this.healthBarElem.style.width = buildingHealth + '%'; if (Object.keys(currentStats).length > 0) { let currentStatValues = '', nextTierStatValues = ''; for (let stat in currentStats) currentStatValues += currentStats[stat]; for (let stat in nextTierStats) nextTierStatValues += nextTierStats[stat]; this.statsElem.innerHTML = `
    ` + currentStatValues + `
    ` + nextTierStatValues + `
    `; } else this.statsElem.innerHTML = ''; if (`Harvester` === this.buildingId) { let depositAmount = Math.floor(buildingTick.depositMax / 10), isDepositPossible = buildingTick.depositMax - buildingTick.deposit < depositAmount; isDepositPossible ? this.depositElem.classList.add('is-disabled') : this.depositElem.classList.remove(`is-disabled`); this.shouldUpgradeAll ? this.depositElem.innerHTML = 'Refuel\x20All\x20(' + (depositAmount * sameBuildings).toLocaleString() + ` gold)` : this.depositElem.innerHTML = 'Refuel\x20(' + depositAmount.toLocaleString() + ` gold)`; } isBuildingAtMaxTier ? this.upgradeElem.classList.remove(`is-disabled`) : this.upgradeElem.classList.add('is-disabled'); this.shouldUpgradeAll ? ( this.upgradeElem.innerHTML = `Upgrade All (` + costString + ')', this.sellElem.innerHTML = `Sell All (` + refundString + ')' ) : ( this.upgradeElem.innerHTML = `Upgrade (` + costString + `)`, this.sellElem.innerHTML = `Sell (` + refundString + `)` ); `GoldStash` == this.buildingId ? ( this.sellElem.innerHTML = `Sell All Buildings`, this.sellElem.classList.remove(`is-disabled`), this.isSellingAll && this.sellElem.classList.add(`is-disabled`) ) : this.ui.getPlayerPartyCanSell() ? ( this.sellElem.classList.remove(`is-disabled`) ) : ( this.sellElem.classList.add(`is-disabled`), this.sellElem.innerHTML = `Need Permission to Sell` ); this.componentElem.style.left = buildingUiPosition.x - this.componentElem.offsetWidth / 0x2 + 'px'; this.componentElem.style.top = buildingUiPosition.y - buildingScale - this.componentElem.offsetHeight - 0x14 + 'px'; this.rangeIndicator && this.rangeIndicator.setPosition(buildingEntity.getPositionX(), buildingEntity.getPositionY()); } } // @Spammer game.spam = { literallyEveryUnicodeEver: null, randomSpamText: [ // `${garbageGenerator()} BIG RAID ${garbageGenerator()}`, `?verify`, "hi", "ez", "Super Idol的笑容都没你的甜八月正午的阳光都没你耀眼热爱 105 °C的你滴滴清纯的蒸馏水", "Zǎoshang hǎo zhōngguó xiànzài wǒ yǒu BING CHILLING 🥶🍦", "Wǒ hěn xǐhuān BING CHILLING 🥶🍦 Dànshì sùdù yǔ jīqíng 9 bǐ BING CHILLING 🥶🍦", ], spamInterval: null, spamText: '', fetchUnicode: async function() { if (!this.literallyEveryUnicodeEver) { this.literallyEveryUnicodeEver = await fetch('https://raw.githubusercontent.com/bits/UTF-8-Unicode-Test-Documents/master/UTF-8_sequence_unseparated/utf8_sequence_0-0xffff_assigned_printable_unseparated.txt') .then(response => response.text()) .then(data => { return data; }); this.randomSpamText.push(`${garbageGenerator()} BIG RAID ${garbageGenerator()}`); } }, onchange: function({target}) { this.spamText = target.value; }, start: function() { this.spamInterval = setInterval(() => { let text; if (this.spamText !== '') text = `${garbageGenerator()} ${this.spamText} ${garbageGenerator()}`; else text = getRandomItem(this.randomSpamText); game.network.sendRpc({ name: "SendChatMessage", channel: "Local", message: text }); }, 1050); }, stop: function() { clearInterval(this.spamInterval); } } function getRandomItem(array) { return array[Math.floor(Math.random() * array.length)]; }; function garbageGenerator(garbageLength = 25) { let garbageCharacters = game.spam.literallyEveryUnicodeEver; let garbage = ""; for (let i = 0; i < garbageLength; i++) garbage += garbageCharacters[Math.floor(Math.random() * garbageCharacters.length)]; return garbage; } function isEven(number) { return number % 2 === 0; }; function isEntityOccupied(x, y) { const cell = game.world.entityGrid.getCellIndexes(x, y, { width: 1, height: 1 }); const entity = game.world.entityGrid.getEntitiesInCell(cell); return Object.keys(entity).length > 0; }; function placeWallBlock(blockWidth, blockHeight, data) { for (let x = -((blockWidth - (isEven(blockWidth) ? 0 : 1)) / 2) * 48; x <= (blockWidth - (isEven(blockWidth) ? 0 : 1)) / 2 * 48; x += 48) { for (let y = -((blockHeight - (isEven(blockHeight) ? 0 : 1)) / 2) * 48; y <= (blockHeight - (isEven(blockHeight) ? 0 : 1)) / 2 * 48; y += 48) { const posX = data.x + x, posY = data.y + y, shouldPlace = !isEntityOccupied(posX, posY); shouldPlace && game.network.sendPacket(9, {name: "MakeBuilding", type: "Wall", x: posX, y: posY, yaw: 0}); }; }; }; function sellAllByType(type) { if (!game.ui.playerPartyCanSell) return; let lastSoldBuilding = null; let allBuildings = [Infinity, ...Object.values(game.ui.buildings).filter(e => e.type == type)]; let sellInterval = () => { if (!game.ui.buildings[lastSoldBuilding?.uid]) allBuildings.shift(); if (window.sellBreak || allBuildings.length == 0) return; const target = allBuildings[0]; if (target !== undefined && !game.ui.buildings[target]?.dead) { lastSoldBuilding = target; Game.currentGame.network.sendRpc({ name: "DeleteBuilding", uid: parseInt(target.uid) }); setTimeout(sellInterval, 50); }; }; sellInterval(); }; function sellAll() { game.ui.components.BuildingOverlay.isSellingAll = true; const sellInterval = () => { if (window.sellBreak) return; if (Object.keys(game.ui.buildings).length > 1 && game.ui.playerPartyCanSell) { Game.currentGame.network.sendRpc({ name: "DeleteBuilding", uid: parseInt(Object.keys(game.ui.buildings)[1]) }); setTimeout(() => { sellInterval(); }, 100); Object.keys(game.ui.buildings).length == 2 && (game.ui.components.BuildingOverlay.isSellingAll = false); } } sellInterval(); } const measureDistance = (obj1, obj2) => { if (!(obj1.x && obj1.y && obj2.x && obj2.y)) return Infinity; let xDif = obj2.x - obj1.x; let yDif = obj2.y - obj1.y; return Math.abs((Math.pow(xDif, 2)) + (Math.pow(yDif, 2))); }; function getByValue(map, searchValue) { for (let [key, value] of map.entries()) { if (equal(value, searchValue)) return key; } } function equal(a, b) { if (a === b) return true; if (a && b && typeof a == 'object' && typeof b == 'object') { if (a.constructor !== b.constructor) return false; var length, i, keys; if (a.valueOf !== Object.prototype.valueOf) return a.valueOf() === b.valueOf(); if (a.toString !== Object.prototype.toString) return a.toString() === b.toString(); keys = Object.keys(a); length = keys.length; if (length !== Object.keys(b).length) return false; for (i = length; i-- !== 0;) { if (!Object.prototype.hasOwnProperty.call(b, keys[i])) return false; } for (i = length; i-- !== 0;) { var key = keys[i]; if (!equal(a[key], b[key])) return false; } return true; } return a!==a && b!==b; }; const addFunctionToElem = ({ id, option, buttonText, colors, onCallback, offCallback }) => { const options = game.options.options; colors ||= 'btn-red?btn-theme'; getId(id).addEventListener('click', e => { let toggleColor = colors.split('?'); if (options[option] === false) { options[option] = true; toggleColor[1] && e.target.classList.remove(toggleColor[1]); e.target.classList.add(toggleColor[0]); buttonText === undefined || (e.target.innerText = `Disable ${buttonText}`); onCallback?.(); } else { options[option] = false; e.target.classList.remove(toggleColor[0]); toggleColor[1] && e.target.classList.add(toggleColor[1]); buttonText === undefined || (e.target.innerText = `Enable ${buttonText}`); offCallback?.(); } }); } function counter(e = 0) { if (e <= -0.99949999999999999e24) { return Math.round(e/-1e23)/-10 + "TT"; } if (e <= -0.99949999999999999e21) { return Math.round(e/-1e20)/-10 + "TB"; } if (e <= -0.99949999999999999e18) { return Math.round(e/-1e17)/-10 + "TM"; } if (e <= -0.99949999999999999e15) { return Math.round(e/-1e14)/-10 + "TK"; } if (e <= -0.99949999999999999e12) { return Math.round(e/-1e11)/-10 + "T"; } if (e <= -0.99949999999999999e9) { return Math.round(e/-1e8)/-10 + "B"; } if (e <= -0.99949999999999999e6) { return Math.round(e/-1e5)/-10 + "M"; } if (e <= -0.99949999999999999e3) { return Math.round(e/-1e2)/-10 + "K"; } if (e <= 0.99949999999999999e3) { return Math.round(e) + ""; } if (e <= 0.99949999999999999e6) { return Math.round(e/1e2)/10 + "K"; } if (e <= 0.99949999999999999e9) { return Math.round(e/1e5)/10 + "M"; } if (e <= 0.99949999999999999e12) { return Math.round(e/1e8)/10 + "B"; } if (e <= 0.99949999999999999e15) { return Math.round(e/1e11)/10 + "T"; } if (e <= 0.99949999999999999e18) { return Math.round(e/1e14)/10 + "TK"; } if (e <= 0.99949999999999999e21) { return Math.round(e/1e17)/10 + "TM"; } if (e <= 0.99949999999999999e24) { return Math.round(e/1e20)/10 + "TB"; } if (e <= 0.99949999999999999e27) { return Math.round(e/1e+23)/10 + "TT"; } if (e >= 0.99949999999999999e27) { return Math.round(e/1e+23)/10 + "TT"; } } const getClock = () => { let date = new Date(), d = date.getDate(), d1 = date.getDay(), h = date.getHours(), m = date.getMinutes(), s = date.getSeconds(), session = "PM"; if (h == 2){ h = 12; }; if (h < 13) { session = "AM" }; if (h > 12){ session = "PM"; h -= 12; }; h = (h < 10) ? "0" + h : h; m = (m < 10) ? "0" + m : m; s = (s < 10) ? "0" + s : s; return `${h}:${m} ${session}`; } function msToTime(s) { // Pad to 2 or 3 digits, default is 2 function pad(n, z) { z = z || 2; return ('00' + n).slice(-z); } var ms = s % 1000; s = (s - ms) / 1000; var secs = s % 60; s = (s - secs) / 60; var mins = s % 60; var hrs = (s - mins) / 60; return pad(hrs) + ':' + pad(mins) + ':' + pad(secs) + '.' + pad(ms, 3); } function ssMode() { const mba = document.querySelectorAll([".hud-bottom-right", ".hud-bottom-left", ".hud-bottom-center", ".hud-center-left", ".hud-center-right", ".hud-chat", ".hud-top-right"]); for (let mb of mba) mb.style.display = (mb.style.display === "none") ? "block" : "none"; document.querySelector(".hud-bottom-right").appendChild(document.querySelector("#hud-shield-bar")); document.querySelector(".hud-bottom-right").appendChild(document.querySelector("#hud-health-bar")); document.querySelector(".hud-bottom-right").insertAdjacentElement("afterbegin", document.querySelector("#hud-party-icons")); document.querySelector(".hud-bottom-left").insertAdjacentElement("afterbegin", document.querySelector("#hud-day-night-ticker")); }; // @TickUpdates game.tickUpdate = { playerTickUpdate: { resourceElem: game.ui.components.Resources, healPlayer: () => { for (let i of ["BuyItem", "EquipItem"]) Game.currentGame.network.sendRpc({name: i, itemName: "HealthPotion", tier: 1}); }, onTick: function(player) { const options = game.options.options; const playerHealth = (player.health / player.maxHealth) * 100; const healThreshold = getId?.("healThreshold")?.valueAsNumber || 15; if (options.heal && playerHealth <= healThreshold) this.healPlayer(); if (!options.frss) return; const resources = ["wood", "stone", "gold"]; for (let rs of resources) { this.resourceElem[`${rs}Elem`].innerHTML = Math.round(player[rs]).toLocaleString(); }; this.resourceElem.tokensElem.innerHTML = Math.round(player.token).toLocaleString(); }, }, petTickUpdate: { buyItem: (itemName, tier = 1) => Game.currentGame.network.sendRpc({name: "BuyItem", itemName, tier}), equipItem: (itemName, tier = 1) => Game.currentGame.network.sendRpc({name: "EquipItem", itemName, tier}), petLevelEnum: [8, 16, 24, 32, 48, 64, 96], petTokenEnum: [100, 100, 100, 100, 200, 200, 300, Infinity], onTick: function(pet) { const options = game.options.options; if (options.revive && pet.health <= 0) { this.buyItem("PetRevive"); this.equipItem("PetRevive"); } if (options.heal) { let petHealth = (pet.health / pet.maxHealth) * 100; const healThreshold = getId?.("healThreshold")?.valueAsNumber || 15; if (petHealth <= healThreshold) { this.buyItem('PetHealthPotion'); this.equipItem("PetHealthPotion"); } }; this.petLevelEnum.indexOf(game.ui.components.MenuShop.shopItems[pet.model].level) > -1 && ( game.ui.playerTick.token >= this.petTokenEnum[pet.tier - 1] && this.buyItem(pet.model, pet.tier + 1) ) }, }, } /* @Handlers + Bindings */ game.network.sendRpc = function(data) { if (data.name === "MakeBuilding" && data.type === "Wall" && game.options.options.wallBlock) { const blockWidth = document.querySelector('#blockX').valueAsNumber; const blockHeight = document.querySelector('#blockY').valueAsNumber; placeWallBlock(blockWidth, blockHeight, data); return; }; this.sendPacket(9, data); }; game.network.addEntityUpdateHandler((e) => { const {entities} = e; const options = game.options.options; if (options.autoBow) { game.network.sendInput({space: 0}); game.network.sendInput({space: 1}); } if (options.autoUpgrade) { for (let uid in game.world.entities) { const { fromTick } = game.world.entities[uid]; if (fromTick?.model == "GoldStash" || fromTick?.tier >= game.rebuilder.goldStash.tier || !(uid in game.ui.buildings)) continue; game.network.sendRpc({name: "UpgradeBuilding", uid: parseInt(uid)}); } } game.ahrc.onTick(); game.rssOverhead.onTick(entities); game.rebuilder.onTick(entities); game.autoAim.onTick(); }); game.spam.fetchUnicode(); game.network.addRpcHandler("LocalBuilding", game.rebuilder.onLocalBuilding.bind(game.rebuilder)); game.ui._events.playerPetTickUpdate.push(game.tickUpdate.petTickUpdate.onTick.bind(game.tickUpdate.petTickUpdate)); game.ui._events.playerTickUpdate.push(game.tickUpdate.playerTickUpdate.onTick.bind(game.tickUpdate.playerTickUpdate)); (function MapFunctionsToElem() { for (let page in menu) { const [optionsElem, moreElem] = document.querySelectorAll("#" + page + " > div"); for (let option in menu[page]) { const {name, description, more, onCallback, offCallback} = menu[page][option]; const hasMore = !!more; const itemElem = document.createElement("div"); itemElem.innerHTML = `

    ${name}

    ${description} ${hasMore ? `` : ""} `; optionsElem.appendChild(itemElem); if (hasMore) { const {html, functions} = more; const moreContainer = document.createElement("div"); moreContainer.innerHTML = html; moreContainer.style.display = "none"; moreElem.appendChild(moreContainer); functions?.(); const toggleElem = getId("more-" + option); toggleElem.onclick = () => { refreshMore(page); moreContainer.style.display = "block"; } } addFunctionToElem({id: 'toggle-' + option, option, buttonText: '', colors: "underline-red?", onCallback, offCallback}); } } })(); /* @Keybinds */ document.addEventListener('keydown', function(e) { if (document.activeElement.tagName.toLowerCase() !== "input" && document.activeElement.tagName.toLowerCase() !== "textarea") { if (e.key == "/") { game.network.sendRpc({name: "EquipItem", itemName: "PetCARL", tier: game.ui.inventory?.PetCARL?.tier || 1}); } if (e.key === "?") { ssMode(); }; } }); document.addEventListener('keyup', function(e) { if (document.activeElement.tagName.toLowerCase() !== "input" && document.activeElement.tagName.toLowerCase() !== "textarea") { if (e.key == "~") { game.markers.placeMarker({ x: game.ui.playerTick.position.x, y: game.ui.playerTick.position.y, timeout: false, shouldIndicateIndex: true, }); } if (e.key == '-') { game.options.options.getRSS = !game.options.options.getRSS; } if (e.key == "=") { game.world.inWorld && ( game.ui.playerTick.gold > 100 && ( game.ui.inventory.Bow || ( game.network.sendRpc({name: "BuyItem", itemName: "Bow", tier: 1}), game.ui.inventory.Bow = {itemName: 'Bow', tier: 1, stacks: 1} ) ), game.ui.inventory.Bow && ( game.options.options.autoBow = !game.options.options.autoBow, game.options.options.autoBow && game.network.sendRpc({name: "EquipItem", itemName: "Bow", tier: game.ui.inventory.Bow.tier}) ) ) } if (e.key == ",") { getId('toggle-rebuild').click(); } if (e.key == ".") { getId("toggle-autoUpgrade").click(); } if (e.key == ";") { game.ui.getPlayerPetUid() && Game.currentGame.network.sendRpc({name: "DeleteBuilding", uid: game.ui.getPlayerPetUid()}); } if (e.key == "'") { game.ui.getPlayerPetUid() && ( game.network.sendRpc({name: "BuyItem", itemName: "PetRevive", tier: 1}), game.network.sendRpc({name: "EquipItem", itemName: "PetRevive", tier: 1}) ); } if (e.code == 'KeyG') { const wheelDisplay = getClass('interaction-wheel')[0]; wheelDisplay.style.display = (wheelDisplay.style.display === 'block') ? 'none' : 'block'; } if (e.code == 'KeyC' && !e.ctrlKey) { setTimeout(() => { document.querySelector('#joinWithPsk').style.display = 'block'; document.querySelector('#joinWithPsk').focus(); document.querySelector('#joinWithPsk').value = ""; }, 100); } if (e.code == "KeyN") { game.zoom.zoomIn(); } if (e.code == "KeyM") { game.zoom.zoomOut(); } if (e.key == "Escape") { getClass('interaction-wheel')[0].style.display = 'none'; } if (e.key == "!") { getId("toggle-wallBlock").click(); } } }); document.querySelector('#joinWithPsk').addEventListener('keyup', (e) => { if (e.key == "Enter" || e.key == "Escape") { e.target.style.display = 'none'; (e.key == "Enter") && game.network.sendRpc({name: "JoinPartyByShareKey", partyShareKey: e.target.value}); } })