// ==UserScript==
// @name Sun:Raise - zombs.io
// @namespace http://tampermonkey.net/
// @version 0.72
// @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
// v0.6 : auto heal & ??????????????????
// v0.7 : unlimited slots base saver
// v0.71 : shop shortcuts
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-white {
border-bottom: 3px solid #eee;
}
.underline-red {
border-bottom: 3px solid red;
}
.hud-settings-options .underline-red {
border-bottom: 3px solid red;
}
.btn-important {
display: inline-block;
height: 40px;
line-height: 40px;
padding: 0 20px;
color: var(--normal-btn);
background: none;
border: none;
cursor: pointer;
transition: all 0.15s ease-in-out;
border-bottom: 3px solid var(--normal-btn);
box-shadow: inset 0 -7px 9px -7px var(--normal-btn);
}
.btn-important:hover {
filter: saturate(200%);
}
/* @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: 30vw;
min-width: 100%;
height: fit-content;
background: rgba(0, 0, 0, 0.4);
border-bottom-right-radius: 4px;
padding: 10px;
zoom: 90%;
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%;
}
/* @UIQuickBuy */
.hud-center-toolbar {
width: 30vw;
height: 68px;
z-index: 9999;
background: rgba(0, 0, 0, 0.4);
border-bottom-left-radius: 3px;
border-bottom-right-radius: 3px;
top: -20px;
position: relative;
overflow-x: auto;
padding: 10px;
display: flex;
flex-wrap: nowrap;
max-width: max-content;
}
.hud-center-toolbar .hud-center-toolbar-item {
position: relative;
flex: 0 0 auto;
display: inline-block;
width: 48px;
height: 48px;
line-height: 48px;
margin: 0 4px;
text-align: center;
text-decoration: none;
background: rgba(255, 255, 255, 0.1);
color: rgba(0, 0, 0, 0.8);
border-radius: 4px;
transition: all 0.15s ease-in-out;
}
.hud-center-toolbar .hud-center-toolbar-item::after {
content: ' ';
display: block;
width: 32px;
height: 32px;
margin: 8px auto;
background-size: contain;
background-position: center;
background-repeat: no-repeat;
opacity: 0.7;
transition: all 0.15s ease-in-out;
}
/* @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;
}
div > div > a.btn.btn-green.hud-confirmation-accept {
background: var(--normal-btn);
}
/* @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);
}
/* @UIMenuMoreCustomStyles */
.base-card {
position: relative;
display: block;
width: 100%;
height: 64px;
margin: 0 0 10px;
padding: 10px 10px 10px 10px;
text-decoration: none;
background: rgba(255, 255, 255, 0.1);
cursor: pointer;
color: #eee;
border-radius: 3px;
transition: all 0.15s ease-in-out;
text-align: left;
}
.base-card:hover {
background: rgba(255, 255, 255, 0.2);
}
#base-management {
position: absolute;
top: 0px;
width: 95%;
height: 75%;
margin: 0px;
padding-right: 10px;
overflow: scroll;
}
#base-management > h2 {
display: inline-block;
margin: 10px 0 10px;
font-weight: 600;
-webkit-font-smoothing: antialiased;
}
#base-management > hr {
width: 87%;
opacity: 0.4;
}
#save-config {
position: absolute;
top: 285px;
right: 15px;
}
`;
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.onConnectionError();
}.bind(this), 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.onConnectionError = function (errorText) {
errorText ||= `We were unable to connect to the gameserver. Please try another server.`;
this.connecting = false;
this.connectionTimer && (
clearInterval(this.connectionTimer),
delete this.connectionTimer
);
getId("playspan").style && (getId("playspan").innerText = "Play");
this.serverElem.classList.add('has-error');
this.errorElem.style.display = 'block';
this.errorElem.innerText = errorText;
}
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', `
`);
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();
game.ui.components.PlacementOverlay.onResize?.();
},
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 += `
`;
}
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.
Semi-colon [;] deletes your pet.
Back-tick ['] revives your pet.`, // anti tiến bịp,
2: ``,
3: ``,
4: `? toggles Screenshot Mode.
~ marks your position.`
};
const pageName_enum = {
0: 'Build',
1: 'Player',
2: 'Visual',
3: 'Clone',
4: '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: () => {},
},
},
baseSaver: {
name: "Base Saver",
description: `Manage all your saved bases here.`,
more: {
html: `
`,
functions: () => {
localStorage.totalSlots ||= 2;
getId("return-to-manager").onclick = () => document.querySelector("#more-baseSaver").click();
window.createBaseSlot = function() {
const oldTotalSlots = parseInt(localStorage.totalSlots);
const nextItem = oldTotalSlots + 1;
localStorage.totalSlots = nextItem;
localStorage[`baseslot${nextItem}`] = '|||';
document.querySelector("#more-baseSaver").click();
};
window.isSlotEmpty = function(index) {
const baseData = localStorage[`baseslot${index}`]?.split("|");
return !!baseData?.[0];
};
window.createBaseSlot = function() {
const oldTotalSlots = parseInt(localStorage.totalSlots);
const nextItem = oldTotalSlots + 1;
localStorage.totalSlots = nextItem;
localStorage[`baseslot${nextItem}`] = '|||';
document.querySelector("#more-baseSaver").click();
}
window.isSlotEmpty = function(index) {
const baseData = localStorage[`baseslot${index}`]?.split("|");
return !!baseData?.[0];
};
window.saveCurrentBaseConfig = function() {
const [design, title, description, date] = [...document.querySelectorAll("#target-base-design, #target-base-name, #target-base-description"), new Date().toLocaleDateString()];
const baseManagement = getId('base-management');
const currentBaseItem = baseManagement.getAttribute('current-item');
localStorage[`baseslot${currentBaseItem}`] = `${design.value}|${title.value}|${description.value}|${date}`;
return void game.ui.components.PopupOverlay.showHint('Current base configuration saved.');
};
},
bind: () => {
const baseContainer = getId('base-container');
const baseManagement = getId('base-management');
baseContainer.innerHTML = '';
baseManagement.style.display = "none";
for (let i = 1; i < parseInt(localStorage.totalSlots) + 1; i++) {
const baseItem = document.createElement('div');
const baseData = localStorage[`baseslot${i}`]?.split("|");
const baseId = genUUID();
baseData?.[1] && (baseData[1] = window.filterXSS(baseData[1]));
baseData?.[2] && (baseData[2] = window.filterXSS(baseData[2]));
baseItem.classList.add('base-card');
baseItem.id = `base-item-${i}`;
baseItem.setAttribute('item-base', i);
baseItem.innerHTML = `
`;
const [title, description, date] = baseItem.children;
title.innerText = baseData?.[1] || "Unoccupied";
description.innerText = baseData?.[2] || "-";
date.innerText = baseData?.[3] || "";
baseItem.onclick = function() {
const [designField, titleField, descriptionField] = [...document.querySelectorAll("#target-base-design, #target-base-name, #target-base-description")];
designField.value = baseData?.[0] || "";
titleField.value = baseData?.[1] || "";
descriptionField.value = baseData?.[2] || "";
getId("encode-target-design").onclick = game.builder.recordBase.bind(game.builder);
getId("view-target-design").onclick = () => game.ui.components.PlacementOverlay.showOverlay(designField.value, 10000);
baseManagement.setAttribute('current-item', i);
for (let otherItem = 1; otherItem < parseInt(localStorage.totalSlots) + 1; otherItem++) {
const item = getId(`base-item-${otherItem}`);
const isThisItem = item.getAttribute('item-base') == i;
if (isThisItem) continue;
item.style.display = "none";
};
baseItem.style.transform = 'translate(0px, 306px)';
getId('add-base-slot').style.display = "none";
baseManagement.style.display = "block";
getId("build-design").onclick = function() {
game.ui.components.PopupOverlay.showConfirmation("Are you sure you want to build base?", 5000, function() {
game.builder.buildBase(designField.value);
});
}
};
baseContainer.appendChild(baseItem);
}
const addItem = document.createElement('div');
addItem.classList.add('base-card');
addItem.id = "add-base-slot";
addItem.innerHTML = `
Add another base slot
`;
addItem.onclick = window.createBaseSlot;
baseContainer.appendChild(addItem);
},
},
},
},
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
},
autoHeal: {
name: "Auto Heal",
description: "Heals your player/pet automatically.",
more: {
html: `
Define the health percentage that the auto heal will kick in if below it.
Default value is 25%.
`,
functions: () => {},
}
},
frss: {
name: "Exact Resource Counter",
description: `"De-truncate" your resource counter.`,
more: null,
},
},
page2: {
ground: {
name: "Render Ground",
description: "Toggles rendering of the ground.",
more: null,
onCallback: () => { game.renderer.ground.setVisible(true); },
offCallback: () => { game.renderer.ground.setVisible(false); },
},
npcs: {
name: "Render NPCs",
description: "Toggles rendering of NPCs.",
more: null,
onCallback: () => { game.renderer.npcs.setVisible(true); },
offCallback: () => { game.renderer.npcs.setVisible(false); },
},
projectiles: {
name: "Render Projectiles",
description: "Toggles rendering of projectiles.",
more: null,
onCallback: () => { game.renderer.projectiles.setVisible(true); },
offCallback: () => { game.renderer.projectiles.setVisible(false); },
},
scenery: {
name: "Render Environment",
description: "Toggles rendering of the environment.",
more: null,
onCallback: () => { game.renderer.scenery.setVisible(true); },
offCallback: () => { game.renderer.scenery.setVisible(false); },
},
},
/*
page3: {},
page4: {} */
};
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 < 5; 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 = 4;
if (page > 4) 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"));
// @Misc.
const toolbar_enum = {
"Pickaxe": { index: 0, hasNextTier: true },
"Spear": { index: 1, hasNextTier: true },
"Bow": { index: 2, hasNextTier: true },
"Bomb": { index: 3, hasNextTier: true },
"HealthPotion": { index: 4, hasNextTier: false },
"PetHealthPotion": { index: 5, hasNextTier: false },
};
getClass('hud-top-center')[0].insertAdjacentHTML('afterbegin', `
`);
[...document.querySelector("#hud > div.hud-top-center > div").children].forEach(elem => {
const itemName = elem.getAttribute("data-item");
const itemTier = elem.getAttribute("data-tier");
const shouldBuyNextTier = toolbar_enum[itemName].hasNexTier;
elem.onclick = () => {
game.network.sendRpc({name: "BuyItem", itemName, tier: shouldBuyNextTier ? parseInt(itemTier) + 1 : parseInt(itemTier)});
};
});
game.network.addRpcHandler("SetItem", ({itemName, tier}) => {
if (Object.keys(toolbar_enum).indexOf(itemName) > -1) {
const { index, hasNextTier } = toolbar_enum[itemName];
if (!hasNextTier) return;
document.querySelector("#hud > div.hud-top-center > div").children[index].setAttribute("data-tier", tier + 1);
};
});
/* @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,
autoHeal: true,
ground: true,
npcs: true,
projectiles: true,
scenery: true,
}
// @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, tier} = buildings[i];
if (dead === 1) {
if (this.savedTowers.get(uid) !== undefined) {
this.shouldBeReplaced.push({x, y, type});
}
} else {
const oldBuilding = getByValue(this.savedTowers, {x, y, type});
if (oldBuilding) {
this.savedTowers.set(parseInt(uid), {x, y, type});
this.shouldBeReplaced = this.shouldBeReplaced.filter(e => !equal(e, {x, y, type}));
}
}
}
}
},
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});
}
}
},
};
// @Builder
game.builder = {
towerCodes: ["Wall", "Door", "SlowTrap", "ArrowTower", "CannonTower", "MeleeTower", "BombTower", "MagicTower", "GoldMine", "Harvester"],
buildBase: function(design) {
const goldStash = game.rebuilder.goldStash;
if (typeof design !== "string") throw new Error("Argument must be given as a string.");
if (goldStash === undefined) throw new Error("You must have a gold stash to be able to use this.");
const towers = design.split(";");
for (let towerStr of towers) {
const tower = towerStr.split(",");
if (tower[0] === "") continue;
if (tower.length < 4) throw new Error(`${JSON.stringify(tower)} contains an issue that must be fixed before this design can be replicated.`);
Game.currentGame.network.sendRpc({
name: "MakeBuilding",
type: this.towerCodes[parseInt(tower[0])],
x: goldStash.x - parseInt(tower[1]),
y: goldStash.y - parseInt(tower[2]),
yaw: parseInt(tower[3])
});
};
},
recordBase: function() {
const goldStash = game.rebuilder.goldStash;
let baseStr = "";
for (let i in game.ui.buildings) {
const building = game.ui.buildings[i];
if (this.towerCodes.indexOf(building.type) < 0) continue;
let yaw = 0;
if (["Harvester", "MeleeTower"].includes(building.type)) {
if (game.world.entities[building.uid] !== undefined) yaw = game.world.entities[building.uid].targetTick.yaw;
}
baseStr += `${this.towerCodes.indexOf(building.type)},${goldStash.x - building.x},${goldStash.y - building.y},${yaw};`;
}
getId('target-base-design').value = baseStr;
}
};
// @AutoAim
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.PlacementOverlay.showOverlay = function (design, timeout) {
this.buildingId && this.cancelPlacing();
const goldStash = game.rebuilder.goldStash;
if (typeof design !== "string") throw new Error("Argument must be given as a string.");
if (goldStash === null) throw new Error("You must have a gold stash to be able to use this.");
this.overlayEntities && (this.overlayEntities.length > 0 && this.overlayEntities.map(e => game.renderer.ui.removeAttachment(e)));
this.overlayEntities = [];
this.overlayDesign = design;
this.isShowingOverlay = true;
game.renderer.follow(game.world.entities[goldStash.uid]);
setTimeout(() => {
const towers = design.split(";"),
schema = this.ui.getBuildingSchema();
for (let towerStr of towers) {
const towerData = towerStr.split(",");
const [type, xWorld, yWorld, yaw] = towerData;
const towerLength = towerData.length
if (type === "") continue;
if (towerLength.length < 4) throw new Error(`${JSON.stringify(towerLength)} contains an issue that must be fixed before this design can be replicated.`);
const buildingType = schema[game.builder.towerCodes[parseInt(type)]],
placeholderEntity = Game.currentGame.assetManager.loadModel(buildingType.modelName, {}),
{ x, y } = game.renderer.worldToUi(goldStash.x - parseInt(xWorld), goldStash.y - parseInt(yWorld));
placeholderEntity.setAlpha(0.5);
placeholderEntity.setRotation(parseInt(yaw));
placeholderEntity.setPosition(x, y);
Game.currentGame.renderer.ui.addAttachment(placeholderEntity);
this.overlayEntities.push(placeholderEntity);
}
timeout && setTimeout(game.ui.components.PlacementOverlay.hideOverlay.bind(this), timeout);
}, 50);
}
game.ui.components.PlacementOverlay.hideOverlay = function() {
for (let entity of this.overlayEntities) game.renderer.ui.removeAttachment(entity);
game.renderer.follow(game.world.entities[game.world.myUid]);
this.isShowingOverlay = false;
this.overlayDesign = null;
}
game.ui.components.PlacementOverlay.onResize = function() {
this.isShowingOverlay && game.ui.components.PlacementOverlay.showOverlay(this.overlayDesign);
}
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 = ``;
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 genUUID() {
return ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(
/[018]/g, c => (
c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4
).toString(16)
);
};
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("auto-heal-threshold").valueAsNumber || 25;
if (options.autoHeal && 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.autoHeal) {
if (pet.health <= 0) {
this.buyItem("PetRevive");
this.equipItem("PetRevive");
}
let petHealth = (pet.health / pet.maxHealth) * 100;
const healThreshold = getId("auto-heal-threshold").valueAsNumber || 25;
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.ui.buildings) {
const building = game.ui.buildings[uid];
if (building?.type !== "GoldStash" && building?.tier >= game.rebuilder.goldStash.tier) continue;
if (building?.dead || !(uid in game.world.entities)) 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}
${game.options.options[option] === undefined ? "" : `
`}
${hasMore ? `` : ""}
`;
optionsElem.appendChild(itemElem);
if (hasMore) {
const {html, functions, bind} = 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);
bind?.();
moreContainer.style.display = "block";
}
}
game.options.options[option] === undefined || 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});
}
})