From a83181f6a855b80f4a2f4c9967b545227dc0a20c Mon Sep 17 00:00:00 2001 From: averagenative Date: Tue, 1 Sep 2026 13:02:22 -0400 Subject: [PATCH] Let the urchin's spikes reach the merge that exists for them The wrap fix in the last commit got the urchin's colours matching, and the lane still reported zero hazards with one sitting on it. The colour was only half of it. merge() is there because "a single sprite often breaks into a few blobs (the urchin's spikes especially)". But the hazard pass screened the raw blobs on size FIRST, at 30*px*px, so the spikes were thrown away before merge ever saw them -- leaving a merge that could only reassemble a sprite intact enough not to need it. Measured live over the DevTools protocol, one frame, one pixel buffer: an urchin at 17% of the lane put 150 pixels through the colour test and shattered into fragments whose LARGEST was 7px. Every one under the 30*px*px = 15.7 floor, so the pipeline emptied before the merge. Running the real pipeline over that same buffer at a range of pre-merge floors: floor 15.7 (shipped) no hazards matches the live probe floor 8 umbrella only floor 5 umbrella only floor 3 umbrella + urchin at 85px So the floor comes off entirely. blobs() already refuses anything under 3px, the 110*px*px screen still runs after the merge, and the urchin rebuilds to 85px against it. That leaves the beach umbrella, which is red and white, merges to 67px of its own and clears the same post-merge floor. The padded search box does cut it off today -- its centre sits at -0.07 of the lane against a box reaching -0.05 -- but two hundredths of a lane is a coincidence, not a margin, so hazards now get the lane-start screen the species pass has had all along for the sand mound at the same end. --- idleon-fishing.user.js | 25 ++++++++++++++++++++++--- idleon-suite.user.js | 25 ++++++++++++++++++++++--- 2 files changed, 44 insertions(+), 6 deletions(-) diff --git a/idleon-fishing.user.js b/idleon-fishing.user.js index a21b044..cb62e03 100644 --- a/idleon-fishing.user.js +++ b/idleon-fishing.user.js @@ -1,7 +1,7 @@ // ==UserScript== // @name IdleOn Fishing Helper // @namespace nativerobot -// @version 2.2 +// @version 2.3 // @downloadURL https://raw.githubusercontent.com/averagenative/idleon-userscripts/main/idleon-fishing.user.js // @updateURL https://raw.githubusercontent.com/averagenative/idleon-userscripts/main/idleon-fishing.user.js // @description Draws where your cast will land, plus fish and hazard markers, for the IdleOn fishing minigame @@ -761,8 +761,27 @@ landed = bobs2.sort((a, b) => b.n - a.n)[0] || null; // The bobber is red too, so it lands in the hazard mask. Drop clusters // that coincide with it, and require the rest to be urchin-sized. - haz = merge(raw(isHazard, 30 * px * px), clump) - .filter(o => o.n >= 110 * px * px) + // + // Nothing is screened on size BEFORE the merge, and that is the point. + // merge() exists because "a single sprite often breaks into a few blobs + // (the urchin's spikes especially)" — but a 30px floor ran first and threw + // the spikes away before merge could put them back, so the merge could + // only ever reassemble a sprite that did not need reassembling. Measured + // live: an urchin holding 150 matching pixels shattered into fragments + // whose LARGEST was 7px, every one of them under the floor, and the lane + // reported zero hazards with an urchin sitting on it. Handing merge the + // raw blobs instead rebuilds it at 85px, clear of the 110*px*px screen + // that still runs after. blobs() already refuses anything under 3px, and + // that is the only pre-merge screen worth having. + // + // The trailing lane-start screen is the hazard pass's version of the + // species pass's startX: the beach umbrella at the left end is red and + // white, merges to 67px of its own, and clears the same 110*px*px floor. + // Today the padded search box happens to cut it off — its centre sits at + // -0.07 of the lane against a box reaching -0.05 — but two hundredths of + // a lane is not a margin, it is a coincidence. + haz = merge(raw(isHazard, 3), clump) + .filter(o => o.n >= 110 * px * px && o.x > laneX0) .filter(o => !landed || Math.abs(o.x - landed.x) > W * 0.02); } if (cfg.marks) { diff --git a/idleon-suite.user.js b/idleon-suite.user.js index 5b1ee9c..f0c2fcc 100644 --- a/idleon-suite.user.js +++ b/idleon-suite.user.js @@ -1,7 +1,7 @@ // ==UserScript== // @name IdleOn Helper Suite // @namespace nativerobot -// @version 1.5 +// @version 1.6 // @downloadURL https://raw.githubusercontent.com/averagenative/idleon-userscripts/main/idleon-suite.user.js // @updateURL https://raw.githubusercontent.com/averagenative/idleon-userscripts/main/idleon-suite.user.js // @description All-in-one: autoclicker + Hoops, Fishing and Darts minigame helpers for Legends of IdleOn, each one individually switchable @@ -1994,8 +1994,27 @@ landed = bobs2.sort((a, b) => b.n - a.n)[0] || null; // The bobber is red too, so it lands in the hazard mask. Drop clusters // that coincide with it, and require the rest to be urchin-sized. - haz = merge(raw(isHazard, 30 * px * px), clump) - .filter(o => o.n >= 110 * px * px) + // + // Nothing is screened on size BEFORE the merge, and that is the point. + // merge() exists because "a single sprite often breaks into a few blobs + // (the urchin's spikes especially)" — but a 30px floor ran first and threw + // the spikes away before merge could put them back, so the merge could + // only ever reassemble a sprite that did not need reassembling. Measured + // live: an urchin holding 150 matching pixels shattered into fragments + // whose LARGEST was 7px, every one of them under the floor, and the lane + // reported zero hazards with an urchin sitting on it. Handing merge the + // raw blobs instead rebuilds it at 85px, clear of the 110*px*px screen + // that still runs after. blobs() already refuses anything under 3px, and + // that is the only pre-merge screen worth having. + // + // The trailing lane-start screen is the hazard pass's version of the + // species pass's startX: the beach umbrella at the left end is red and + // white, merges to 67px of its own, and clears the same 110*px*px floor. + // Today the padded search box happens to cut it off — its centre sits at + // -0.07 of the lane against a box reaching -0.05 — but two hundredths of + // a lane is not a margin, it is a coincidence. + haz = merge(raw(isHazard, 3), clump) + .filter(o => o.n >= 110 * px * px && o.x > laneX0) .filter(o => !landed || Math.abs(o.x - landed.x) > W * 0.02); } if (cfg.marks) {