// ==UserScript==
// @name florr.io | Petal farming progress counter
// @namespace Furaken
// @version 1.2.7
// @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==
// @require https://unpkg.com/string-similarity@4.0.4/umd/string-similarity.min.js
var obj =
{
rarity: 0,
id: 1,
aim: 5,
basicId: 605463,
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.2",
versionHash: versionHash,
autoFind: true,
multipleCounting: {
enable: false,
petal: {
"Common Basic": 5,
"Common Light": 5
},
key: "Minus"
}
},
petal = "Common Basic",
rarityArr = [
"Common",
"Unusual",
"Rare",
"Epic",
"Legendary",
"Mythic",
"Ultra",
"Super",
"Unique"
],
rarityColors = [
"#7EEF6D",
"#FFE65D",
"#4D52E3",
"#861FDE",
"#DE1F1F",
"#1FDBDE",
"#FF2B75",
"#2BFFA3",
"#444444"
],
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",
"Amulet",
"Compass",
"Disc",
"Shovel",
"Coin",
"Chip",
"Card",
"Moon",
"Privet",
"Glass",
"Corruption",
"Mana Orb",
"Blueberries",
"Magic Cotton",
"Magic Stinger",
"Magic Leaf",
"Magic Cactus",
"Magic Eye",
"Magic Missile",
"Magic Stick"
]
function getNewPetal(petalName) {
var tempObj = {
id : 1,
rarity: 0,
petal: ""
}
if (petalName.split(" ").length <= 0) return
if (petalName.split(" ").length == 1) {
if (petalName.startsWith("un") || petalName.startsWith("n")) tempObj.rarity = "Unusual"
else if (petalName.startsWith("r")) tempObj.rarity = "Rare"
else if (petalName.startsWith("e")) tempObj.rarity = "Epic"
else if (petalName.startsWith("l")) tempObj.rarity = "Legendary"
else if (petalName.startsWith("m")) tempObj.rarity = "Mythic"
else if (petalName.startsWith("u")) tempObj.rarity = "Ultra"
else if (petalName.startsWith("s")) tempObj.rarity = "Super"
else if (petalName.startsWith("q")) tempObj.rarity = "Unique"
else tempObj.rarity = "Common"
tempObj.id = stringSimilarity.findBestMatch(petalName.slice(1), petalArr)
petalName = tempObj.rarity + " " + tempObj.id.bestMatch.target
tempObj.rarity = rarityArr.indexOf(tempObj.rarity)
} else {
tempObj.rarity = stringSimilarity.findBestMatch(petalName.split(" ").shift(), rarityArr)
tempObj.id = stringSimilarity.findBestMatch(petalName.split(" ").splice(1).join(" "), petalArr)
petalName = tempObj.rarity.bestMatch.target + " " + tempObj.id.bestMatch.target
tempObj.rarity = tempObj.rarity.bestMatchIndex
}
tempObj.id = tempObj.id.bestMatchIndex + 1
tempObj.petal = petalName
return tempObj
}
var thisNewPetal = getNewPetal(petal)
obj.id = thisNewPetal.id
obj.rarity = thisNewPetal.rarity
petal = thisNewPetal.petal
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
}
}
// https://stackoverflow.com/questions/47011055/smooth-vertical-scrolling-on-mouse-wheel-in-vanilla-javascript
function SmoothScroll(target, speed, smooth) {
if (target === document) target = (document.scrollingElement || document.documentElement || document.body.parentNode || document.body)
var moving = false
var pos = target.scrollTop
var frame = target === document.body && document.documentElement ? document.documentElement : target
target.addEventListener('mousewheel', scrolled, { passive: false })
target.addEventListener('DOMMouseScroll', scrolled, { passive: false })
function scrolled(e) {
e.preventDefault()
var delta = normalizeWheelDelta(e)
pos += -delta * speed
pos = Math.max(0, Math.min(pos, target.scrollHeight - frame.clientHeight))
if (!moving) update()
}
function normalizeWheelDelta(e) {
if(e.detail) {
if(e.wheelDelta) return e.wheelDelta/e.detail/40 * (e.detail>0 ? 1 : -1)
else return -e.detail / 3
} else return e.wheelDelta / 120
}
function update() {
moving = true
var delta = (pos - target.scrollTop) / smooth
target.scrollTop += delta
if (Math.abs(delta) > 0.5) requestFrame(update)
else moving = false
}
var requestFrame = function() {
return (window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || function(func) {window.setTimeout(func, 1000 / 50)})
}();
}
if (localStorage.getItem('petalFarmingCounter') == null) {
localStorage.setItem('petalFarmingCounter', JSON.stringify(obj))
setTimeout(() => {
toggleCon()
conCon.scrollTo(0, 110)
}, 5000)
}
else {
var thisObj = JSON.parse(localStorage.getItem('petalFarmingCounter'))
if (thisObj.version != obj.version) {
thisObj.version = obj.version
setTimeout(() => {
toggleCon()
conCon.scrollTo(0, 110)
}, 5000)
}
if (thisObj.versionHash != versionHash) {
thisObj.versionHash = versionHash
if (thisObj.autoFind) {
setInterval(() => {
thisObj.basicId = findSequence(thisObj.find.value, unsafeWindow.Module.HEAPU32) - ((stringSimilarity.findBestMatch(thisObj.find.petal, petalArr).bestMatchIndex + 1) * 8) + 8
document.getElementById("Capply").innerHTML = `Basic ID: ${coloringValue(thisObj.basicId)}`
var thisObj_ = JSON.parse(localStorage.getItem('petalFarmingCounter'))
thisObj_.basicId = thisObj.basicId
localStorage.setItem('petalFarmingCounter', JSON.stringify(thisObj_))
}, 10000)
}
}
if (Object.keys(thisObj.multipleCounting.petal).length < 2) thisObj.multipleCounting.petal = obj.multipleCounting.petal
Object.keys(obj).forEach(k => {
if (!Object.keys(thisObj).includes(k)) thisObj[k] = obj[k]
})
obj = thisObj
localStorage.setItem('petalFarmingCounter', JSON.stringify(thisObj))
}
var thisPetalObj = {}
for (const [index, [key, value]] of Object.entries(Object.entries(obj.multipleCounting.petal))) {
thisPetalObj[index] = {
id: getNewPetal(key).id,
rarity: getNewPetal(key).rarity,
aim: value,
}
}
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 = "300px"
container.style.width = "400px"
conCon.style.overflow = "hidden scroll"
container.style.borderRadius = "5px"
barProgress.style.maxHeight = "300px"
barProgress.style.maxWidth = "400px"
barProgress.style.height = "300px"
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()
updateMultiProgress()
}
}
document.querySelector('body').appendChild(container)
var conCon = document.createElement("div")
conCon.style = `
overflow: hidden;
height: 300px;
`
container.appendChild(conCon)
new SmoothScroll(conCon, 90, 7)
containerPos()
petal = rarityArr[obj.rarity] + " " + petalArr[obj.id - 1]
thisNewPetal = getNewPetal(petal)
obj.id = thisNewPetal.id
obj.rarity = thisNewPetal.rarity
petal = thisNewPetal.petal
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}`
}
function coloringFunction(value) {
return `${value}`
}
obj.aim = Math.abs(Math.floor(obj.aim))
obj.aim = obj.aim == 0 ? 1 : obj.aim
function updateMultiProgress() {
var multiProgressInnerHTML = "",
thisMultiProgressValue
if (obj.multipleCounting.enable) {
for (const [index, [key, value]] of Object.entries(Object.entries(obj.multipleCounting.petal))) {
thisMultiProgressValue = unsafeWindow.Module.HEAPU32[obj.basicId + (getNewPetal(key).id * 8) - (8 - getNewPetal(key).rarity)]
multiProgressInnerHTML += `