// ==UserScript== // @name florr.io | Petal farming progress counter // @namespace Furaken // @version 1.1.0.1 // @description Petal farming progress counter // @author Furaken // @match https://florr.io/* // @grant unsafeWindow // @grant GM_addStyle // @license MIT // @require https://unpkg.com/string-similarity@4.0.4/umd/string-similarity.min.js // @downloadURL none // ==/UserScript== var obj = { rarity: 0, id: 1, aim: 5, basicId: 942239, find: { petal: "Basic", value: [5, 0, 0, 0, 0, 0, 0, 0] }, config: { top: false, left: false, x: "-20px", y: "-20px", scale: 1, key: "Equal" }, version: "1.1" }, petal = "Common Basic", rarityArr = [ "Common", "Unusual", "Rare", "Epic", "Legendary", "Mythic", "Ultra", "Super" ], petalArr = [ "Basic", "Light", "Rock", "Square", "Rose", "Stinger", "Iris", "Wing", "Missile", "Grapes", "Cactus", "Faster", "Bubble", "Pollen", "Dandelion", "Beetle Egg", "Antennae", "Heavy", "Yin Yang", "Web", "Honey", "Leaf", "Salt", "Rice", "Corn", "Sand", "Pincer", "Yucca", "Magnet", "Yggdrasil", "Starfish", "Pearl", "Lightning", "Jelly", "Claw", "Shell", "Cutter", "Dahlia", "Uranium", "Sponge", "Soil", "Fangs", "Third Eye", "Peas", "Stick", "Clover", "Powder", "Air", "Basil", "Orange", "Ant Egg", "Poo", "Relic", "Lotus", "Bulb", "Cotton", "Carrot", "Bone", "Plank", "Tomato", "Mark", "Rubber", "Blood Stinger", "Bur", "Root", "Ankh", "Dice", "Talisman", "Battery" ] function getNewPetal() { if (petal.split(" ").length <= 0) return if (petal.split(" ").length == 1) { if (petal.startsWith("un")) obj.rarity = "Unusual" else if (petal.startsWith("r")) obj.rarity = "Rare" else if (petal.startsWith("e")) obj.rarity = "Epic" else if (petal.startsWith("l")) obj.rarity = "Legendary" else if (petal.startsWith("m")) obj.rarity = "Mythic" else if (petal.startsWith("u")) obj.rarity = "Ultra" else if (petal.startsWith("s")) obj.rarity = "Super" else obj.rarity = "Common" obj.id = stringSimilarity.findBestMatch(petal.slice(1), petalArr) petal = obj.rarity + " " + obj.id.bestMatch.target obj.rarity = rarityArr.indexOf(obj.rarity) } else { obj.rarity = stringSimilarity.findBestMatch(petal.split(" ").shift(), rarityArr) obj.id = stringSimilarity.findBestMatch(petal.split(" ").splice(1).join(" "), petalArr) petal = obj.rarity.bestMatch.target + " " + obj.id.bestMatch.target obj.rarity = obj.rarity.bestMatchIndex } obj.id = obj.id.bestMatchIndex + 1 } getNewPetal() function findSequence(seq, mem) { let match = 0 for (let addr = 0; addr < mem.length; addr++) { if (mem[addr] === seq[match]) match++ else if (mem[addr] === seq[0]) match = 1 else match = 0 if (match === seq.length) return addr - match + 1 } } if (localStorage.getItem('petalFarmingCounter') == null) { localStorage.setItem('petalFarmingCounter', JSON.stringify(obj)) setTimeout(() => { toggleCon() }, 5000) } else { var thisObj = JSON.parse(localStorage.getItem('petalFarmingCounter')) if (thisObj.version != obj.version) { setTimeout(() => { toggleCon() }, 5000) } Object.keys(obj).forEach(k => { if (!Object.keys(thisObj).includes(k)) thisObj[k] = obj[k] }) obj = thisObj localStorage.setItem('petalFarmingCounter', JSON.stringify(thisObj)) } var container = document.createElement("div") container.id = "container" container.style = ` padding: 5px; height: 24px; width: 350px; position: absolute; transform: translate(${obj.config.x}, ${obj.config.y}) scale(${obj.config.scale}); background: #333333; border-radius: 24px; transition: all 1s ease-in-out; opacity: 1; box-shadow: 5px 5px rgba(0, 0, 0, 0.3); pointer-events: all; cursor: pointer; overflow: hidden; ` container.onclick = function() { toggleCon() } function toggleCon() { if (conCon.style.overflow == "hidden") { container.style.height = "150px" container.style.width = "400px" conCon.style.overflow = "hidden scroll" container.style.borderRadius = "5px" barProgress.style.maxHeight = "150px" barProgress.style.maxWidth = "400px" barProgress.style.height = "150px" barProgress.style.width = "400px" barProgress.style.borderRadius = "0px" barProgress.style.opacity = 0 barProgress.style.background = "#1FDBDE" barProgress.style.pointerEvents = "none" barText.style.opacity = 0 settings.style.pointerEvents = "all" settings.style.opacity = 1 changelog.style.pointerEvents = "all" changelog.style.opacity = 1 } else { container.style.height = "24px" container.style.width = "350px" conCon.style.overflow = "hidden" container.style.borderRadius = "24px" barProgress.style.maxHeight = "24px" barProgress.style.maxWidth = "350px" barProgress.style.height = "24px" barProgress.style.width = "350px" barProgress.style.borderRadius = "24px" barProgress.style.opacity = 1 barProgress.style.background = "#F5FF65" barProgress.style.pointerEvents = "all" barText.style.opacity = 1 settings.style.pointerEvents = "none" settings.style.opacity = 0 changelog.style.pointerEvents = "none" changelog.style.opacity = 0 updateProgress() } } document.querySelector('body').appendChild(container) var conCon = document.createElement("div") conCon.style = ` overflow: hidden; height: 150px; ` container.appendChild(conCon) containerPos() petal = rarityArr[obj.rarity] + " " + petalArr[obj.id - 1] getNewPetal() function convertNumber(value) { return Math.abs(Number(value)) >= 1.0e+9 ? (Math.abs(Number(value)) / 1.0e+9).toFixed(2) + "B" : Math.abs(Number(value)) >= 1.0e+6 ? (Math.abs(Number(value)) / 1.0e+6).toFixed(2) + "M" : Math.abs(Number(value)) >= 1.0e+3 ? (Math.abs(Number(value)) / 1.0e+3).toFixed(2) + "K" : Math.abs(Number(value)) } function containerPos() { if (obj.config.top) { container.style.top = "0" container.style.bottom = "unset" } else { container.style.top = "unset" container.style.bottom = "0" } if (obj.config.left) { container.style.left = "0" container.style.right = "unset" } else { container.style.left = "unset" container.style.right = "0" } container.style.transform = `translate(${obj.config.x}, ${obj.config.y}) scale(${obj.config.scale})` } function coloringBool(bool) { if (bool) return `${bool}` else return `${bool}` } function coloringValue(value) { return `${value}` } obj.aim = Math.abs(Math.floor(obj.aim)) obj.aim = obj.aim == 0 ? 1 : obj.aim var settings = document.createElement("div") settings.style = ` padding: 10px; color: white; font-family: 'Ubuntu'; z-index: 1; font-size: 12px; line-height: 15px; opacity: 0; transition: all 1s ease-in-out; pointer-events: none; text-shadow: rgb(0 0 0) 2px 0px 0px, rgb(0 0 0) 1.75517px 0.958851px 0px, rgb(0 0 0) 1.0806px 1.68294px 0px, rgb(0 0 0) 0.141474px 1.99499px 0px, rgb(0 0 0) -0.832294px 1.81859px 0px, rgb(0 0 0) -1.60229px 1.19694px 0px, rgb(0 0 0) -1.97998px 0.28224px 0px, rgb(0 0 0) -1.87291px -0.701566px 0px, rgb(0 0 0) -1.30729px -1.5136px 0px, rgb(0 0 0) -0.421592px -1.95506px 0px, rgb(0 0 0) 0.567324px -1.91785px 0px, rgb(0 0 0) 1.41734px -1.41108px 0px, rgb(0 0 0) 1.92034px -0.558831px 0px; ` conCon.appendChild(settings) var settings_transform = document.createElement("div") settings_transform.innerHTML = `
Settings
Progress Counter
Petal: ${coloringValue(petal)}
Aim: ${coloringValue(obj.aim)}
Transform & Hotkeys
top: ${coloringBool(obj.config.top)}
left: ${coloringBool(obj.config.left)}
x: ${coloringValue(obj.config.x)}
y: ${coloringValue(obj.config.y)}
scale: ${coloringValue(obj.config.scale)}
key: ${coloringValue(obj.config.key)}
Find & Apply Basic ID
Find & Apply
Basic ID: ${coloringValue(obj.basicId)}
` settings.appendChild(settings_transform); ["sProgress", "sTransform", "sFindId"].forEach(x => { document.getElementById(x).onclick = function(e) { e.stopPropagation() var kTransform = document.getElementById("k"+ this.id.slice(1)) if (kTransform.style.opacity != 1) { kTransform.style.opacity = 1 kTransform.style.height = "auto" kTransform.style.pointerEvents = "all" } else { kTransform.style.opacity = 0 kTransform.style.height = "0px" kTransform.style.pointerEvents = "none" } }; }); ["Cpetal", "Caim", "Ctop", "Cleft", "CposX", "CposY", "Cscale", "CkeyToggle", "Cfind", "Capply"].forEach(x => { document.getElementById(x).onclick = function(e) { e.stopPropagation() var value = "", value2 = [] if (["Cpetal", "Caim"].includes(this.id)) { if (["Cpetal"].includes(this.id)) { value = prompt('Petal name?', petal) if (petal == null) return petal = value getNewPetal() this.innerHTML = `Petal: ${coloringValue(petal)}` barText.innerHTML = `${petal}: ${convertNumber(thisPetal)} / ${convertNumber(obj.aim)} (${(thisPetal * 100 / obj.aim).toFixed(2)}%)` } else if (["Caim"].includes(this.id)) { value = prompt('Aim?', obj.aim) if (value == null) return if (isNaN(value)) return obj.aim = Number(value) obj.aim = Math.abs(Math.floor(obj.aim)) obj.aim = obj.aim == 0 ? 1 : obj.aim this.innerHTML = `Aim: ${coloringValue(obj.aim)}` } } else if (["Ctop", "Cleft", "CposX", "CposY", "Cscale", "CkeyToggle"].includes(this.id)) { if (["Ctop", "Cleft"].includes(this.id)) { value = !obj.config[x.slice(1)] this.innerHTML = `${x.slice(1)}: ${coloringBool(value)}` obj.config[x.slice(1)] = value } else if (["CposX", "CposY"].includes(this.id)) { value = prompt(x.slice(1), obj.config[x[x.length - 1].toLowerCase()].slice(0, -2)) if (value == null) return if (isNaN(value)) return value = Number(value) this.innerHTML = `${x[x.length - 1].toLowerCase()}: ${coloringValue(value + "px")}` obj.config[x[x.length - 1].toLowerCase()] = value + "px" } else if (["Cscale"].includes(this.id)) { value = prompt(x.slice(1), obj.config[x.slice(1)]) if (value == null) return if (isNaN(value)) return value = Number(value) if (value == 0) return this.innerHTML = `${x.slice(1)}: ${coloringValue(value)}` obj.config[x.slice(1)] = value } else if (["CkeyToggle"].includes(this.id)) { var endTime = Date.now() + 5 * 1000 this.innerHTML = `key: Press a key!` var keysPressed = [] var keyInterval = setInterval(() => { keysPressed.unshift(lastKey) if (keysPressed.length > 2) keysPressed.splice(2) if (keysPressed[keysPressed.length - 1] != keysPressed[0]) { obj.config.key = keysPressed[0] this.innerHTML = `key: ${coloringValue(keysPressed[0])}` clearInterval(keyInterval) } if (Date.now() > endTime) { this.innerHTML = `key: ${coloringValue(obj.config.key)}` clearInterval(keyInterval) return } }); } containerPos() } else if (["Cfind", "Capply"].includes(this.id)) { if (["Cfind"].includes(this.id)) { var thisPetalName = "" value = prompt("Petal?", obj.find.petal) value = stringSimilarity.findBestMatch(value, petalArr) thisPetalName = value.bestMatch.target value = value.bestMatchIndex + 1 rarityArr.forEach((x, i) => { var temporaryValue = prompt(`Amount of ${x} ${thisPetalName}`, obj.find.value[i]) if (temporaryValue == null) temporaryValue = 0 if (isNaN(temporaryValue)) temporaryValue = 0 value2.push(Number(temporaryValue)) }) obj.find.petal = thisPetalName obj.find.value = value2 obj.basicId = findSequence(value2, unsafeWindow.Module.HEAPU32) - (value * 8) + 8 document.getElementById("Capply").innerHTML = `Basic ID: ${coloringValue(obj.basicId)}` } else if (["Capply"].includes(this.id)) { value = prompt('Basic ID?', obj.basicId) if (value == null) return if (isNaN(value)) return obj.basicId = Number(value) this.innerHTML = `Basic ID: ${coloringValue(obj.basicId)}` } } localStorage.setItem('petalFarmingCounter', JSON.stringify(obj)) } }) var changelog = document.createElement("div") changelog.style = ` padding: 10px; color: white; font-family: 'Ubuntu'; z-index: 1; font-size: 12px; line-height: 15px; opacity: 0; transition: all 1s ease-in-out; pointer-events: none; text-shadow: rgb(0 0 0) 2px 0px 0px, rgb(0 0 0) 1.75517px 0.958851px 0px, rgb(0 0 0) 1.0806px 1.68294px 0px, rgb(0 0 0) 0.141474px 1.99499px 0px, rgb(0 0 0) -0.832294px 1.81859px 0px, rgb(0 0 0) -1.60229px 1.19694px 0px, rgb(0 0 0) -1.97998px 0.28224px 0px, rgb(0 0 0) -1.87291px -0.701566px 0px, rgb(0 0 0) -1.30729px -1.5136px 0px, rgb(0 0 0) -0.421592px -1.95506px 0px, rgb(0 0 0) 0.567324px -1.91785px 0px, rgb(0 0 0) 1.41734px -1.41108px 0px, rgb(0 0 0) 1.92034px -0.558831px 0px; ` changelog.innerHTML = `
Changelog
December 24th 2023 - v1.1
- Added 3 new petals.
- Added a manual way to find Basic ID (Credit to Max Nest).
- The container is now moveable and scalable.
- Press = key to show/hide the container, this is also available in earlier versions. You can custom it in settings now.
` conCon.appendChild(changelog) var barText = document.createElement("div") barText.style = ` top: 50%; left: 50%; transform: translate(-50%, -50%); position: absolute; width: 100%; color: white; font-family: 'Ubuntu'; text-align: center; transition: all 1s ease-in-out; text-wrap: nowrap; z-index: 1; pointer-events: none; font-size: 14px; text-shadow: rgb(0 0 0) 2px 0px 0px, rgb(0 0 0) 1.75517px 0.958851px 0px, rgb(0 0 0) 1.0806px 1.68294px 0px, rgb(0 0 0) 0.141474px 1.99499px 0px, rgb(0 0 0) -0.832294px 1.81859px 0px, rgb(0 0 0) -1.60229px 1.19694px 0px, rgb(0 0 0) -1.97998px 0.28224px 0px, rgb(0 0 0) -1.87291px -0.701566px 0px, rgb(0 0 0) -1.30729px -1.5136px 0px, rgb(0 0 0) -0.421592px -1.95506px 0px, rgb(0 0 0) 0.567324px -1.91785px 0px, rgb(0 0 0) 1.41734px -1.41108px 0px, rgb(0 0 0) 1.92034px -0.558831px 0px; ` container.appendChild(barText) var barProgress = document.createElement("div") barProgress.style = ` background: #F5FF65; border-radius: 24px; width: 0px; max-width: 350px; max-height: 24px; transition: all 1s ease-in-out; opacity: 0; height: 0px; top: 50%; position: absolute; transform: translate(0px, -50%); ` container.appendChild(barProgress) barText.innerHTML = `${petal}: 0 / ${convertNumber(obj.aim)} (0.00%)` var thisPetal, thisWidth function updateProgress() { thisPetal = unsafeWindow.Module.HEAPU32[obj.basicId + (obj.id * 8) - (8 - obj.rarity)] thisWidth = container.style.width.slice(0, -2) * thisPetal / obj.aim barProgress.style.height = thisWidth + "px" barProgress.style.width = thisWidth + "px" barProgress.style.opacity = thisPetal / (obj.aim * 0.08) barText.innerHTML = `${petal}: ${convertNumber(thisPetal)} / ${convertNumber(obj.aim)} (${(thisPetal * 100 / obj.aim).toFixed(2)}%)` } setInterval(() => { if (conCon.style.overflow != "hidden") return updateProgress() }, 10000) var lastKey document.documentElement.addEventListener("keydown", function (e) { lastKey = e.code if (event.code == obj.config.key) { if (container.style.opacity == "0") { container.style.opacity = 1 container.style.pointerEvents = "all" settings.style.pointerEvents = "all" changelog.style.pointerEvents = "all" } else { container.style.opacity = 0 container.style.pointerEvents = "none" settings.style.pointerEvents = "none" changelog.style.pointerEvents = "none" } } }) document.querySelector('canvas').onclick = function () { container.style.height = "24px" container.style.width = "350px" conCon.style.overflow = "hidden" container.style.borderRadius = "24px" barProgress.style.maxHeight = "24px" barProgress.style.maxWidth = "350px" barProgress.style.height = "24px" barProgress.style.width = "350px" barProgress.style.borderRadius = "24px" barProgress.style.opacity = 1 barProgress.style.background = "#F5FF65" barProgress.style.pointerEvents = "all" barText.style.opacity = 1 settings.style.pointerEvents = "none" settings.style.opacity = 0 changelog.style.pointerEvents = "none" changelog.style.opacity = 0 updateProgress() } GM_addStyle(` @keyframes blink { 0% {color: #DBD74B} 50% {color: #1FDBDE} 100% {color: #DBD74B} } .blink { animation-name: blink; animation-duration: 1.5s; animation-iteration-count: infinite; } ::-webkit-scrollbar { width: 5px; } ::-webkit-scrollbar-track { background: #00000000; } ::-webkit-scrollbar-thumb { background: #444; border-radius: 5px; } ::-webkit-scrollbar-thumb:hover { background: #444; } `)