- // ==UserScript==
- // @name MooMoo.io Custom Store
- // @description Customize store
- // @author KOOKY WARRIOR
- // @match *://*.moomoo.io/*
- // @icon https://moomoo.io/img/favicon.png?v=1
- // @require https://cdnjs.cloudflare.com/ajax/libs/Sortable/1.10.2/Sortable.min.js
- // @require https://cdnjs.cloudflare.com/ajax/libs/msgpack-lite/0.1.26/msgpack.min.js
- // @run-at document-start
- // @grant unsafeWindow
- // @license MIT
- // @version 0.6.2
- // @namespace https://greasyfork.org/users/999838
- // ==/UserScript==
-
- /*
- - Right-click the Store Button to access the editing options
- - Press "B" to toggle store menu
- - To change the order of your hats and accessories, simply drag and drop them to the desired position
- - Add a blank space to give your collection some extra style
- - Don't need a particular hat or accessory? Delete it with just a click
- - Export your changes or import customizations
- */
-
- ;(async () => {
- unsafeWindow.customStore = true
- const elementID = (id) => {
- return document.getElementById(id)
- }
- var inGame = false
- var alliances = []
- var alliancePlayers = []
- var allianceTotalScroll = 1
- var allianceScroll = 1
- unsafeWindow.allianceScroll = allianceScroll
- let init = false
- await new Promise(async (resolve) => {
- let { send } = WebSocket.prototype
-
- WebSocket.prototype.send = function (...x) {
- send.apply(this, x)
- this.send = send
- if (!init) {
- init = true
- this.addEventListener("message", (e) => {
- if (!e.origin.includes("moomoo.io")) return
- const [packet, data] = msgpack.decode(new Uint8Array(e.data))
- switch (packet) {
- case "us":
- if (elementID("storeMenu").style.display == "block") {
- generateStoreList()
- }
- break
- case "1":
- myPlayer.sid = data[0]
- inGame = true
- break
- case "11":
- inGame = false
- break
- case "ac":
- alliances.push(data[0])
- if (myPlayer.playerObject?.team) {
- allianceTotalScroll = alliances.length > 5 ? (alliances.length - (alliances.length % 5)) / 5 + (alliances.length % 5 === 0 ? 0 : 1) : 1
- } else {
- allianceTotalScroll =
- alliancePlayers.length > 5 ? (alliancePlayers.length - (alliancePlayers.length % 5)) / 5 + (alliancePlayers.length % 5 === 0 ? 0 : 1) : 1
- }
- allianceScroll = Math.min(allianceTotalScroll, allianceScroll)
- if (elementID("allianceMenu").style.display == "block") {
- showAllianceMenu()
- }
- break
- case "st":
- allianceScroll = 1
- if (myPlayer.playerObject?.team) {
- allianceTotalScroll = alliances.length > 5 ? (alliances.length - (alliances.length % 5)) / 5 + (alliances.length % 5 === 0 ? 0 : 1) : 1
- } else {
- allianceTotalScroll =
- alliancePlayers.length > 5 ? (alliancePlayers.length - (alliancePlayers.length % 5)) / 5 + (alliancePlayers.length % 5 === 0 ? 0 : 1) : 1
- }
- allianceScroll = Math.min(allianceTotalScroll, allianceScroll)
- if (elementID("allianceMenu").style.display == "block") {
- showAllianceMenu()
- }
- break
- case "sa":
- alliancePlayers = data[0]
- if (myPlayer.playerObject?.team) {
- allianceTotalScroll = alliances.length > 5 ? (alliances.length - (alliances.length % 5)) / 5 + (alliances.length % 5 === 0 ? 0 : 1) : 1
- } else {
- allianceTotalScroll =
- alliancePlayers.length > 5 ? (alliancePlayers.length - (alliancePlayers.length % 5)) / 5 + (alliancePlayers.length % 5 === 0 ? 0 : 1) : 1
- }
- allianceScroll = Math.min(allianceTotalScroll, allianceScroll)
- if (elementID("allianceMenu").style.display == "block") {
- showAllianceMenu()
- }
- break
- case "ad":
- for (var i = alliances.length - 1; i >= 0; i--) {
- if (alliances[i].sid == data[0]) {
- alliances.splice(i, 1)
- }
- }
- if (myPlayer.playerObject?.team) {
- allianceTotalScroll = alliances.length > 5 ? (alliances.length - (alliances.length % 5)) / 5 + (alliances.length % 5 === 0 ? 0 : 1) : 1
- } else {
- allianceTotalScroll =
- alliancePlayers.length > 5 ? (alliancePlayers.length - (alliancePlayers.length % 5)) / 5 + (alliancePlayers.length % 5 === 0 ? 0 : 1) : 1
- }
- allianceScroll = Math.min(allianceTotalScroll, allianceScroll)
- if (elementID("allianceMenu").style.display == "block") {
- showAllianceMenu()
- }
- break
- case "id":
- alliances = data[0].teams
- allianceTotalScroll = alliances.length > 5 ? (alliances.length - (alliances.length % 5)) / 5 + (alliances.length % 5 === 0 ? 0 : 1) : 1
- break
- }
- })
- }
- resolve(this)
- }
- })
-
- const myPlayer = {
- sid: null,
- playerObject: null
- }
-
- const symbol = Symbol("lockDir")
- Object.defineProperty(Object.prototype, "lockDir", {
- get() {
- return this[symbol]
- },
- set(value) {
- this[symbol] = value
- if (this.isPlayer === true && this.sid === myPlayer.sid) {
- myPlayer.playerObject = this
- }
- },
- configurable: true
- })
-
- function waitForElm(selector) {
- return new Promise((resolve) => {
- if (document.querySelector(selector)) {
- return resolve(document.querySelector(selector))
- }
-
- const observer = new MutationObserver((mutations) => {
- if (document.querySelector(selector)) {
- resolve(document.querySelector(selector))
- observer.disconnect()
- }
- })
-
- observer.observe(document.body, {
- childList: true,
- subtree: true
- })
- })
- }
-
- const customStoreHolder = document.createElement("div")
- customStoreHolder.id = "customStoreHolder"
- waitForElm("#storeHolder").then((storeHolder) => {
- const style = document.createElement("style")
- style.innerHTML = `
- #customStoreHolder {
- pointer-events: all;
- width: 400px;
- display: inline-block;
- background-color: rgba(0, 0, 0, 0.25);
- -webkit-border-radius: 4px;
- -moz-border-radius: 4px;
- border-radius: 4px;
- color: #fff;
- padding: 10px;
- height: 200px;
- max-height: calc(100vh - 200px);
- overflow-y: scroll;
- -webkit-overflow-scrolling: touch;
- }
- `
- document.head.appendChild(style)
- storeHolder.parentNode.insertBefore(customStoreHolder, storeHolder.nextSibling)
- storeHolder.style.display = "none"
- })
-
- var currentStoreIndex = 0
- var store = {
- hats: [
- {
- id: 51,
- name: "Moo Cap",
- price: 0,
- scale: 120,
- desc: "coolest mooer around"
- },
- {
- id: 50,
- name: "Apple Cap",
- price: 0,
- scale: 120,
- desc: "apple farms remembers"
- },
- {
- id: 28,
- name: "Moo Head",
- price: 0,
- scale: 120,
- desc: "no effect"
- },
- {
- id: 29,
- name: "Pig Head",
- price: 0,
- scale: 120,
- desc: "no effect"
- },
- {
- id: 30,
- name: "Fluff Head",
- price: 0,
- scale: 120,
- desc: "no effect"
- },
- {
- id: 36,
- name: "Pandou Head",
- price: 0,
- scale: 120,
- desc: "no effect"
- },
- {
- id: 37,
- name: "Bear Head",
- price: 0,
- scale: 120,
- desc: "no effect"
- },
- {
- id: 38,
- name: "Monkey Head",
- price: 0,
- scale: 120,
- desc: "no effect"
- },
- {
- id: 44,
- name: "Polar Head",
- price: 0,
- scale: 120,
- desc: "no effect"
- },
- {
- id: 35,
- name: "Fez Hat",
- price: 0,
- scale: 120,
- desc: "no effect"
- },
- {
- id: 42,
- name: "Enigma Hat",
- price: 0,
- scale: 120,
- desc: "join the enigma army"
- },
- {
- id: 43,
- name: "Blitz Hat",
- price: 0,
- scale: 120,
- desc: "hey everybody i'm blitz"
- },
- {
- id: 49,
- name: "Bob XIII Hat",
- price: 0,
- scale: 120,
- desc: "like and subscribe"
- },
- {
- id: 57,
- name: "Pumpkin",
- price: 50,
- scale: 120,
- desc: "Spooooky"
- },
- {
- id: 8,
- name: "Bummle Hat",
- price: 100,
- scale: 120,
- desc: "no effect"
- },
- {
- id: 2,
- name: "Straw Hat",
- price: 500,
- scale: 120,
- desc: "no effect"
- },
- {
- id: 15,
- name: "Winter Cap",
- price: 600,
- scale: 120,
- desc: "allows you to move at normal speed in snow",
- coldM: 1
- },
- {
- id: 5,
- name: "Cowboy Hat",
- price: 1000,
- scale: 120,
- desc: "no effect"
- },
- {
- id: 4,
- name: "Ranger Hat",
- price: 2000,
- scale: 120,
- desc: "no effect"
- },
- {
- id: 18,
- name: "Explorer Hat",
- price: 2000,
- scale: 120,
- desc: "no effect"
- },
- {
- id: 31,
- name: "Flipper Hat",
- price: 2500,
- scale: 120,
- desc: "have more control while in water",
- watrImm: true
- },
- {
- id: 1,
- name: "Marksman Cap",
- price: 3000,
- scale: 120,
- desc: "increases arrow speed and range",
- aMlt: 1.3
- },
- {
- id: 10,
- name: "Bush Gear",
- price: 3000,
- scale: 160,
- desc: "allows you to disguise yourself as a bush"
- },
- {
- id: 48,
- name: "Halo",
- price: 3000,
- scale: 120,
- desc: "no effect"
- },
- {
- id: 6,
- name: "Soldier Helmet",
- price: 4000,
- scale: 120,
- desc: "reduces damage taken but slows movement",
- spdMult: 0.94,
- dmgMult: 0.75
- },
- {
- id: 23,
- name: "Anti Venom Gear",
- price: 4000,
- scale: 120,
- desc: "makes you immune to poison",
- poisonRes: 1
- },
- {
- id: 13,
- name: "Medic Gear",
- price: 5000,
- scale: 110,
- desc: "slowly regenerates health over time",
- healthRegen: 3
- },
- {
- id: 9,
- name: "Miners Helmet",
- price: 5000,
- scale: 120,
- desc: "earn 1 extra gold per resource",
- extraGold: 1
- },
- {
- id: 32,
- name: "Musketeer Hat",
- price: 5000,
- scale: 120,
- desc: "reduces cost of projectiles",
- projCost: 0.5
- },
- {
- id: 7,
- name: "Bull Helmet",
- price: 6000,
- scale: 120,
- desc: "increases damage done but drains health",
- healthRegen: -5,
- dmgMultO: 1.5,
- spdMult: 0.96
- },
- {
- id: 22,
- name: "Emp Helmet",
- price: 6000,
- scale: 120,
- desc: "turrets won't attack but you move slower",
- antiTurret: 1,
- spdMult: 0.7
- },
- {
- id: 12,
- name: "Booster Hat",
- price: 6000,
- scale: 120,
- desc: "increases your movement speed",
- spdMult: 1.16
- },
- {
- id: 26,
- name: "Barbarian Armor",
- price: 8000,
- scale: 120,
- desc: "knocks back enemies that attack you",
- dmgK: 0.6
- },
- {
- id: 21,
- name: "Plague Mask",
- price: 10000,
- scale: 120,
- desc: "melee attacks deal poison damage",
- poisonDmg: 5,
- poisonTime: 6
- },
- {
- id: 46,
- name: "Bull Mask",
- price: 10000,
- scale: 120,
- desc: "bulls won't target you unless you attack them",
- bullRepel: 1
- },
- {
- id: 14,
- name: "Windmill Hat",
- topSprite: true,
- price: 10000,
- scale: 120,
- desc: "generates points while worn",
- pps: 1.5
- },
- {
- id: 11,
- name: "Spike Gear",
- topSprite: true,
- price: 10000,
- scale: 120,
- desc: "deal damage to players that damage you",
- dmg: 0.45
- },
- {
- id: 53,
- name: "Turret Gear",
- topSprite: true,
- price: 10000,
- scale: 120,
- desc: "you become a walking turret",
- turret: {
- proj: 1,
- range: 700,
- rate: 2500
- },
- spdMult: 0.7
- },
- {
- id: 20,
- name: "Samurai Armor",
- price: 12000,
- scale: 120,
- desc: "increased attack speed and fire rate",
- atkSpd: 0.78
- },
- {
- id: 58,
- name: "Dark Knight",
- price: 12000,
- scale: 120,
- desc: "restores health when you deal damage",
- healD: 0.4
- },
- {
- id: 27,
- name: "Scavenger Gear",
- price: 15000,
- scale: 120,
- desc: "earn double points for each kill",
- kScrM: 2
- },
- {
- id: 40,
- name: "Tank Gear",
- price: 15000,
- scale: 120,
- desc: "increased damage to buildings but slower movement",
- spdMult: 0.3,
- bDmg: 3.3
- },
- {
- id: 52,
- name: "Thief Gear",
- price: 15000,
- scale: 120,
- desc: "steal half of a players gold when you kill them",
- goldSteal: 0.5
- },
- {
- id: 55,
- name: "Bloodthirster",
- price: 20000,
- scale: 120,
- desc: "Restore Health when dealing damage. And increased damage",
- healD: 0.25,
- dmgMultO: 1.2
- },
- {
- id: 56,
- name: "Assassin Gear",
- price: 20000,
- scale: 120,
- desc: "Go invisible when not moving. Can't eat. Increased speed",
- noEat: true,
- spdMult: 1.1,
- invisTimer: 1000
- }
- ],
- accessories: [
- {
- id: 12,
- name: "Snowball",
- price: 1000,
- scale: 105,
- xOff: 18,
- desc: "no effect"
- },
- {
- id: 9,
- name: "Tree Cape",
- price: 1000,
- scale: 90,
- desc: "no effect"
- },
- {
- id: 10,
- name: "Stone Cape",
- price: 1000,
- scale: 90,
- desc: "no effect"
- },
- {
- id: 3,
- name: "Cookie Cape",
- price: 1500,
- scale: 90,
- desc: "no effect"
- },
- {
- id: 8,
- name: "Cow Cape",
- price: 2000,
- scale: 90,
- desc: "no effect"
- },
- {
- id: 11,
- name: "Monkey Tail",
- price: 2000,
- scale: 97,
- xOff: 25,
- desc: "Super speed but reduced damage",
- spdMult: 1.35,
- dmgMultO: 0.2
- },
- {
- id: 17,
- name: "Apple Basket",
- price: 3000,
- scale: 80,
- xOff: 12,
- desc: "slowly regenerates health over time",
- healthRegen: 1
- },
- {
- id: 6,
- name: "Winter Cape",
- price: 3000,
- scale: 90,
- desc: "no effect"
- },
- {
- id: 4,
- name: "Skull Cape",
- price: 4000,
- scale: 90,
- desc: "no effect"
- },
- {
- id: 5,
- name: "Dash Cape",
- price: 5000,
- scale: 90,
- desc: "no effect"
- },
- {
- id: 2,
- name: "Dragon Cape",
- price: 6000,
- scale: 90,
- desc: "no effect"
- },
- {
- id: 1,
- name: "Super Cape",
- price: 8000,
- scale: 90,
- desc: "no effect"
- },
- {
- id: 7,
- name: "Troll Cape",
- price: 8000,
- scale: 90,
- desc: "no effect"
- },
- {
- id: 14,
- name: "Thorns",
- price: 10000,
- scale: 115,
- xOff: 20,
- desc: "no effect"
- },
- {
- id: 15,
- name: "Blockades",
- price: 10000,
- scale: 95,
- xOff: 15,
- desc: "no effect"
- },
- {
- id: 20,
- name: "Devils Tail",
- price: 10000,
- scale: 95,
- xOff: 20,
- desc: "no effect"
- },
- {
- id: 16,
- name: "Sawblade",
- price: 12000,
- scale: 90,
- spin: true,
- xOff: 0,
- desc: "deal damage to players that damage you",
- dmg: 0.15
- },
- {
- id: 13,
- name: "Angel Wings",
- price: 15000,
- scale: 138,
- xOff: 22,
- desc: "slowly regenerates health over time",
- healthRegen: 3
- },
- {
- id: 19,
- name: "Shadow Wings",
- price: 15000,
- scale: 138,
- xOff: 22,
- desc: "increased movement speed",
- spdMult: 1.1
- },
- {
- id: 18,
- name: "Blood Wings",
- price: 20000,
- scale: 178,
- xOff: 26,
- desc: "restores health when you deal damage",
- healD: 0.2
- },
- {
- id: 21,
- name: "Corrupt X Wings",
- price: 20000,
- scale: 178,
- xOff: 26,
- desc: "deal damage to players that damage you",
- dmg: 0.25
- }
- ]
- }
- var checkRealStore = JSON.parse(localStorage.getItem("realStore"))
- if (checkRealStore == null) {
- localStorage.setItem("realStore", JSON.stringify(store))
- }
- var customStore = JSON.parse(localStorage.getItem("customStore"))
- if (customStore == null) {
- customStore = store
- localStorage.setItem("customStore", JSON.stringify(store))
- }
-
- var totalScroll =
- customStore.hats.length > 4 ? (customStore.hats.length - (customStore.hats.length % 4)) / 4 + (customStore.hats.length % 4 === 0 ? 0 : 1) : 1
- var currentScroll = 1
- function updateScroll() {
- if (customStoreButton.style.background == "red") return
- const elements = document.querySelectorAll("#customStoreHolder > .storeItem")
- for (let i = 0; i < elements.length; i++) {
- elements[i].style.display = i >= (currentScroll - 1) * 4 && i < currentScroll * 4 ? null : "none"
- }
- }
- customStoreHolder.addEventListener("wheel", (event) => {
- if (event.wheelDelta > 0) {
- // scroll up
- currentScroll = Math.max(1, currentScroll - 1)
- } else {
- // scroll down
- currentScroll = Math.min(totalScroll, currentScroll + 1)
- }
- updateScroll()
- })
-
- var sortable = null
- function generateStoreList() {
- if (inGame) {
- while (customStoreHolder.hasChildNodes()) {
- customStoreHolder.removeChild(customStoreHolder.lastChild)
- }
- var index = currentStoreIndex
- var tmpArray = index ? customStore.accessories : customStore.hats
- totalScroll = tmpArray.length > 4 ? (tmpArray.length - (tmpArray.length % 4)) / 4 + (tmpArray.length % 4 === 0 ? 0 : 1) : 1
- addEdit.style.display = customStoreButton.style.background == "red" ? null : "none"
- reloadEdit.style.display = customStoreButton.style.background == "red" ? null : "none"
- importBut.style.display = customStoreButton.style.background == "red" ? null : "none"
- exportBut.style.display = customStoreButton.style.background == "red" ? null : "none"
- customStoreHolder.style.overflowY = customStoreButton.style.background == "red" ? null : "hidden"
- Array.from(tmpArray).forEach((ele) => {
- let tmp = document.createElement("div")
- tmp.id = "storeDisplay" + ele.id
- tmp.className = "storeItem"
- customStoreHolder.appendChild(tmp)
-
- let childtmp
- if (!ele.blank) {
- tmp.onmouseout = () => {
- unsafeWindow.showItemInfo()
- }
- tmp.onmouseover = () => {
- unsafeWindow.showItemInfo(ele, false, true)
- }
-
- childtmp = document.createElement("img")
- childtmp.className = "hatPreview"
- childtmp.src = "../img/" + (index ? "accessories/access_" : "hats/hat_") + ele.id + (ele.topSprite ? "_p" : "") + ".png"
- tmp.appendChild(childtmp)
-
- childtmp = document.createElement("span")
- childtmp.textContent = ele.name
- tmp.appendChild(childtmp)
- } else {
- childtmp = document.createElement("div")
- childtmp.className = "hatPreview"
- tmp.appendChild(childtmp)
- }
-
- if (customStoreButton.style.background == "red") {
- childtmp = document.createElement("div")
- childtmp.className = "joinAlBtn"
- childtmp.style = "margin-top: 5px"
- childtmp.textContent = "Delete"
- tmp.appendChild(childtmp)
- childtmp.onclick = () => {
- let arr = index ? customStore.accessories : customStore.hats
- const objWithIdIndex = arr.findIndex((obj) => obj.id === ele.id)
- if (objWithIdIndex > -1) {
- arr.splice(objWithIdIndex, 1)
- }
- localStorage.setItem("customStore", JSON.stringify(customStore))
- generateStoreList()
- }
- } else if (!ele.blank) {
- if (index ? !myPlayer.playerObject.tails[ele.id] : !myPlayer.playerObject.skins[ele.id]) {
- childtmp = document.createElement("div")
- childtmp.className = "joinAlBtn"
- childtmp.style = "margin-top: 5px"
- childtmp.textContent = "Buy"
- childtmp.onclick = () => {
- unsafeWindow.storeBuy(ele.id, index)
- }
- tmp.appendChild(childtmp)
-
- childtmp = document.createElement("span")
- childtmp.className = "itemPrice"
- childtmp.textContent = ele.price
- tmp.appendChild(childtmp)
- } else if ((index ? myPlayer.playerObject.tailIndex : myPlayer.playerObject.skinIndex) == ele.id) {
- childtmp = document.createElement("div")
- childtmp.className = "joinAlBtn"
- childtmp.style = "margin-top: 5px"
- childtmp.textContent = "Unequip"
- childtmp.onclick = () => {
- unsafeWindow.storeEquip(0, index)
- }
- tmp.appendChild(childtmp)
- } else {
- childtmp = document.createElement("div")
- childtmp.className = "joinAlBtn"
- childtmp.style = "margin-top: 5px"
- childtmp.textContent = "Equip"
- childtmp.onclick = () => {
- unsafeWindow.storeEquip(ele.id, index)
- }
- tmp.appendChild(childtmp)
- }
- }
- })
- updateScroll()
- if (customStoreButton.style.background == "red") {
- if (sortable != null) {
- sortable.destroy()
- }
- sortable = new Sortable.create(customStoreHolder, {
- animation: 150,
- onUpdate: (event) => {
- let arr = index ? customStore.accessories : customStore.hats
- if (event.newIndex >= arr.length) {
- var k = event.newIndex - arr.length + 1
- while (k--) {
- arr.push(undefined)
- }
- }
- arr.splice(event.newIndex, 0, arr.splice(event.oldIndex, 1)[0])
- localStorage.setItem("customStore", JSON.stringify(customStore))
- }
- })
- } else {
- if (sortable != null) {
- sortable.destroy()
- sortable = null
- }
- }
- }
- }
-
- const customStoreButton = document.createElement("div")
- customStoreButton.id = "customStoreButton"
- customStoreButton.className = "uiElement gameButton"
- customStoreButton.innerHTML = `<i class="material-icons" style="font-size:40px; vertical-align:middle"></i>`
- customStoreButton.onclick = () => {
- if (elementID("storeMenu").style.display != "block") {
- elementID("storeMenu").style.display = "block"
- elementID("allianceMenu").style.display = "none"
- elementID("chatBox").value = ""
- elementID("chatHolder").style.display = "none"
- generateStoreList()
- } else {
- elementID("storeMenu").style.display = "none"
- customStoreButton.style.background = null
- }
- }
- customStoreButton.oncontextmenu = (event) => {
- event.preventDefault()
- if (elementID("storeMenu").style.display != "block") {
- elementID("storeMenu").style.display = "block"
- elementID("allianceMenu").style.display = "none"
- elementID("chatBox").value = ""
- elementID("chatHolder").style.display = "none"
- if (customStoreButton.style.background != "red") {
- customStoreButton.style.background = "red"
- }
- generateStoreList()
- } else {
- elementID("storeMenu").style.display = "none"
- customStoreButton.style.background = null
- }
- }
-
- waitForElm("#storeButton").then((storeButton) => {
- const style = document.createElement("style")
- style.innerHTML = `
- #customStoreButton {
- right: 330px;
- }
- @media only screen and (max-width: 896px) {
- #customStoreButton {
- top: inherit;
- right: 60px;
- }
- }
- `
- document.head.appendChild(style)
- storeButton.parentNode.insertBefore(customStoreButton, storeButton.nextSibling)
- storeButton.hidden = true
- })
-
- waitForElm("#storeMenu > div:nth-child(1) > div:nth-child(1)").then((storeTab1) => {
- storeTab1.addEventListener("click", () => {
- currentStoreIndex = 0
- currentScroll = 1
- generateStoreList()
- })
- })
- const addEdit = document.createElement("div")
- addEdit.className = "storeTab"
- addEdit.textContent = "Add Blank"
- addEdit.style.display = "none"
- addEdit.style.marginLeft = "10px"
- const reloadEdit = document.createElement("div")
- reloadEdit.className = "storeTab"
- reloadEdit.textContent = "Reload"
- reloadEdit.style.display = "none"
- reloadEdit.style.marginLeft = "10px"
- const importBut = document.createElement("div")
- importBut.className = "storeTab"
- importBut.textContent = "Import"
- importBut.style.marginLeft = "10px"
- const exportBut = document.createElement("div")
- exportBut.className = "storeTab"
- exportBut.textContent = "Export"
- exportBut.style.marginLeft = "10px"
- waitForElm("#storeMenu > div:nth-child(1) > div:nth-child(2)").then((storeTab2) => {
- storeTab2.addEventListener("click", () => {
- currentStoreIndex = 1
- currentScroll = 1
- generateStoreList()
- })
-
- storeTab2.parentNode.appendChild(addEdit)
- addEdit.onclick = () => {
- let arr = currentStoreIndex ? customStore.accessories : customStore.hats
- let id = Math.max(...arr.map((el) => el.id)) + 1001
-
- let min = customStoreHolder.getBoundingClientRect().top + 10
- let top,
- index = 0
- let childrens = customStoreHolder.childNodes
- for (var i = 0; i < childrens.length; i++) {
- top = Math.abs(childrens[i].getBoundingClientRect().top)
- if (top <= min) {
- index = i + 1
- }
- }
- arr.splice(index, 0, { id: id, blank: true })
- localStorage.setItem("customStore", JSON.stringify(customStore))
- generateStoreList()
- }
-
- storeTab2.parentNode.appendChild(reloadEdit)
- reloadEdit.onclick = () => {
- let realStore = JSON.parse(localStorage.getItem("realStore"))
- currentStoreIndex ? (customStore.accessories = realStore.accessories) : (customStore.hats = realStore.hats)
- localStorage.setItem("customStore", JSON.stringify(customStore))
- currentScroll = 1
- generateStoreList()
- }
-
- storeTab2.parentNode.appendChild(importBut)
- importBut.onclick = () => {
- const tmpEle = document.createElement("input")
- tmpEle.type = "file"
- tmpEle.style.display = "none"
- document.body.appendChild(tmpEle)
- tmpEle.addEventListener("change", async () => {
- let data = await new Response(tmpEle.files[0]).json()
- customStore = data
- localStorage.setItem("customStore", JSON.stringify(data))
- tmpEle.remove()
- currentScroll = 1
- generateStoreList()
- })
- tmpEle.click()
- }
-
- storeTab2.parentNode.appendChild(exportBut)
- exportBut.onclick = () => {
- let dataStr = JSON.stringify(customStore)
- let dataUri = "data:application/jsoncharset=utf-8," + encodeURIComponent(dataStr)
-
- let exportFileDefaultName = `customStore_${Date.now()}.json`
-
- let linkElement = document.createElement("a")
- linkElement.setAttribute("href", dataUri)
- linkElement.setAttribute("download", exportFileDefaultName)
- linkElement.click()
- }
- })
-
- unsafeWindow.addEventListener("keydown", (event) => {
- if (event.code == "Escape") {
- customStoreButton.style.background = null
- } else if (event.code == "KeyB" && document.activeElement.tagName != "INPUT" && inGame) {
- if (elementID("storeMenu").style.display != "block") {
- elementID("storeMenu").style.display = "block"
- elementID("allianceMenu").style.display = "none"
- elementID("chatBox").value = ""
- elementID("chatHolder").style.display = "none"
- generateStoreList()
- } else {
- elementID("storeMenu").style.display = "none"
- customStoreButton.style.background = null
- }
- }
- })
-
- const customAllianceHolder = document.createElement("div")
- customAllianceHolder.id = "customAllianceHolder"
- waitForElm("#allianceHolder").then((allianceHolder) => {
- const style = document.createElement("style")
- style.innerHTML = `
- #customAllianceHolder {
- pointer-events: all;
- height: 200px;
- max-height: calc(100vh - 260px);
- overflow-y: hidden;
- -webkit-overflow-scrolling: touch;
- width: 350px;
- display: inline-block;
- text-align: left;
- padding: 10px;
- background-color: rgba(0, 0, 0, 0.25);
- -webkit-border-radius: 4px;
- -moz-border-radius: 4px;
- border-radius: 4px;
- }
- `
- document.head.appendChild(style)
- allianceHolder.parentNode.insertBefore(customAllianceHolder, allianceHolder.nextSibling)
- allianceHolder.style.display = "none"
- })
-
- customAllianceHolder.addEventListener("wheel", (event) => {
- if (event.wheelDelta > 0) {
- // scroll up
- allianceScroll = Math.max(1, allianceScroll - 1)
- } else {
- // scroll down
- allianceScroll = Math.min(allianceTotalScroll, allianceScroll + 1)
- }
- updateAllianceScroll()
- })
- function updateAllianceScroll() {
- const elements = document.querySelectorAll("#customAllianceHolder > .allianceItem")
- for (let i = 0; i < elements.length; i++) {
- elements[i].style.display = i >= (allianceScroll - 1) * 5 && i < allianceScroll * 5 ? null : "none"
- }
- }
-
- waitForElm("#allianceButton").then((ele) => {
- ele.addEventListener("click", () => {
- showAllianceMenu()
- })
- })
-
- function showAllianceMenu() {
- if (inGame) {
- while (customAllianceHolder.hasChildNodes()) {
- customAllianceHolder.removeChild(customAllianceHolder.lastChild)
- }
- if (myPlayer.playerObject?.team) {
- for (let i = 0; i < alliancePlayers.length; i += 2) {
- let tmp = document.createElement("div")
- tmp.className = "allianceItem"
- tmp.style = "color:" + (alliancePlayers[i] == myPlayer.playerObject.sid ? "#fff" : "rgba(255,255,255,0.6)")
- tmp.textContent = alliancePlayers[i + 1]
- customAllianceHolder.appendChild(tmp)
-
- if (myPlayer.playerObject.isOwner && alliancePlayers[i] != myPlayer.playerObject.sid) {
- let alliancePlayersArray = alliancePlayers
- let childtmp = document.createElement("div")
- childtmp.className = "joinAlBtn"
- childtmp.textContent = "Kick"
- childtmp.onclick = function () {
- unsafeWindow.kickFromClan(alliancePlayersArray[i])
- }
- tmp.appendChild(childtmp)
- }
- }
- } else {
- if (alliances.length) {
- for (let i = 0; i < alliances.length; ++i) {
- let tmp = document.createElement("div")
- tmp.className = "allianceItem"
- tmp.style = "color:" + (alliances[i].sid == myPlayer.playerObject?.team ? "#fff" : "rgba(255,255,255,0.6)")
- tmp.textContent = alliances[i].sid
- customAllianceHolder.appendChild(tmp)
-
- let childtmp = document.createElement("div")
- childtmp.className = "joinAlBtn"
- childtmp.textContent = "Join"
- childtmp.onclick = function () {
- unsafeWindow.sendJoin(i)
- }
- tmp.appendChild(childtmp)
- }
- } else {
- let tmp = document.createElement("div")
- tmp.className = "allianceItem"
- tmp.textContent = "No Tribes Yet"
- customAllianceHolder.appendChild(tmp)
- }
- }
- updateAllianceScroll()
- }
- }
- })()