Tempoross: permit-max rework (auto-equip, reward collection, instance-safe navigation) - #534
Conversation
PLUGIN_DEBUGGING_NOTES section 2 documented the two getWorldLocation() accessors the wrong way round. Rs2Player.getWorldLocation() translates via WorldPoint.fromLocalInstance, so it returns the OVERWORLD coordinate the instance was copied from; the raw client.getLocalPlayer() call does not translate and stays on the instance side. Measured in Tempoross: Rs2Player.getWorldLocation() = (3035, 2853) in region 12076 while NPCs reported (10556, 5892) in the same tick. The bullets above that code block were already correct - only the labels contradicted them - but the swapped labels plausibly produced the bugs now recorded in the new doc. Adds INSTANCE_COORDINATE_SPACES.md: the rule for which comparisons are safe inside an instance, the plugins currently mixing the two spaces (RoyalTitans danger-tile dodge, pestcontrol brawler proximity, mahoganyhomez object sorting), the plugins verified consistent so they are not "fixed" by mistake, and how to confirm at runtime before changing combat code. Plugin fixes are deliberately not included - the reference implementation is being proven in the Tempoross plugin first. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Live Tempoross runs showed only the cloud dodge was the space-mixing bug; the ammo-crate and fish-spot symptoms had different causes (NPC render distance, per-game chunk rotation). Record those alongside the walkFastLocal canvas-projection footgun so they are not conflated with the split again. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…9.1) Brings over ~30 fixes and the permit-max strategy developed and live-tested across many rounds in the sibling Microbot repo. Highlights: Coordinate/instance correctness - entity vs Rs2Player.getWorldLocation() coordinate-space mixing fixed throughout (cloud dodge, tether logging, fish-spot selection); see docs/INSTANCE_COORDINATE_SPACES.md - side containment via the two per-side exit NPCs (ship + totem anchors); cross-ship watchdog cancels fall-through clicks and walks - spirit pool selected by the spiritPoolPoint mark - both sides' pools tie at exactly 10 tiles from the exit NPC, so exit distance cannot pick Behaviour - permit-max strategy: 7/9-fish opening, cook-everything, 49% load cutoff (needs 4+ fish), stage at the pool mark at ~5% energy, harpoon to 97-98% - pool phase detected by energy, not pool-NPC visibility (render distance); poolPhaseActive flag stops idling at the mark after the final load - fires: douse en route (triangle-inequality detour cap), sidestep when out of water, douse when standing in one; walkable-tile checks on all dodges - repairs walk to the damaged mast/totem (10-tile cap), rope refetched from any state, harpoon fallback no longer rewrites user config - world hop to a configurable world (default 422) at script start Robustness - isInMinigame debounced (scene-reload LOADING blips reset the game state mid-round); work area stashed and restored after spurious resets; finishGame resets only after departure is confirmed - depleted fish spots released immediately; camera turns only when the target is off-screen; thresholds randomized per game Descriptor keeps the Hub's PluginConstants fields (isExternal/enabledByDefault). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…entVersion - docs/README.md for the hub listing: strategy, setup, config table, known limitations (including the intentional forfeit behaviour) - authors = See1Duck (original plugin author) - minClientVersion 2.0.13 -> 2.6.16: the rework uses tile-object cache queries, Rs2Tile.isWalkable(LocalPoint) and hopToWorld, none of which exist in 2.0.13; 2.6.16 is the version the build verifies against No icon/card assets yet, so iconUrl/cardUrl stay empty rather than pointing at files that do not exist. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…e is up THIRD_CATCH previously ran until the bag was full, so the third phase was one long catch followed by one long cook. The strategy is batches: catch 7, cook them, load, repeat - and only stay out to fill the bag while a double spot is available, since that is when catching is fast enough to be worth it. The predicate now short-circuits in order: bag full (or the solo essence target) -> done; solo -> unchanged; 49% energy load cutoff with 4+ fish -> done; otherwise 7 fish AND no double spot up. The existing cook interrupt in handleStateLoop already pulls us back out of THIRD_COOK when a double appears mid-cook, so the two rules together produce the alternating pattern. Also consolidates three slightly different "is a double available" checks into TemporossScript.hasDoubleSpot() - cloud-filtered, since a spot we cannot stand at is no reason to keep catching. The catch cutoff, the cook interrupt and the abandon-a-single rule now agree by construction. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Captured live from the agent server across three games: almost everything in the
arena is duplicated per side with DISTINCT ids, so the side is a lookup, not a
geometry problem. All four exit NPCs appear in one instance and pair fixedly:
A: Captain Dudi 10587 (west ship) + First Mate Deri 10593 (north totem)
spots 10565, mast 41352, totem 41354, crates 10576/10577
B: Captain Pudi 10585 (east ship) + First Mate Peri 10596 (south totem)
spots 10568, mast 41353, totem 41355, crates 10578/10579
Measured fishing clusters sat 40 tiles apart with no overlap. New TemporossSide
enum holds the table; the nearest exit NPC's id selects it at setup.
This removes two proven-unsafe distance rules:
- pairing our two exit NPCs by proximity: the west ship host measured 17 tiles
from its own totem host and 18 from the other side's, a one-tile margin
- selecting the totem object by radius: the other side's sat 19 tiles away,
inside the 30 query radius, rejected only by isOnOurSide's 18-tile test
Fishing spots, masts, totems, damaged variants and ammo crates are now selected
by our side's id alone. Still geometric, because both sides share the id: the
shrine, water pump, supply crates, spirit pool, and the double spot 10569 -
which the capture confirmed spawns on both sides.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The dodge has been firing early. Two candidate causes, both addressed: 1. inCloud(point, 0) computes (radius+1) tiles, so "radius 0" actually meant "within one tile" - it dodged while merely ADJACENT to a shadow. 2. 41007 (lightning_shadow_short) was never tracked at all. It may be the imminent-strike marker while 41006 is the earlier warning. Unproven. Now tiered: - IMMINENT (standing on a shadow, or on/beside a 41007): move regardless of what we are doing, including a pool harpoon - the hit is never worth it. - WARNING (adjacent to a 41006 only): still step out, but not worth abandoning a pool harpoon for. 41007 is tracked and logged rather than trusted. A throttled CLOUDS: line reports the 41006/41007 split, whether we are on-tile / adjacent / imminent, and current HP, so one game shows whether 41007 appears at all and whether damage follows it. If it never appears, tier 1 degrades to the on-tile test, which is the off-by-one fix on its own. Rollback is this commit alone; the side-lock work is separate. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Two fire gaps, both about not eating avoidable damage. 1. Douse the fire a strike leaves behind. In mass mode nothing covered this: handleFires() is solo-only, and fightFiresInPath only clears fires that lie on a route we happen to be walking, so a fresh fire beside us burned untouched. handleNearbyFire() douses anything within 3 tiles when we have water. Bounded tight so it can never turn into a trip, and it yields to a pool harpoon. 2. Never walk through a fire that is in the way. detourAroundFires used to run only when we had ZERO water, on the assumption that dousing covered the route otherwise. It does not: fightFiresInPath only clears as many fires as we have full buckets, so with one bucket and three fires on the line it doused one and walked through the other two. The sidestep now runs regardless, after dousing, on whatever is still burning. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Dousing means walking to the fire - there is no ranged douse - so fightFiresInPath targeting fires up to 10 tiles away with a 4 tile detour budget was a genuine trip. Cut to 5 and 2, so it only douses fires it is effectively passing. Fires are a hazard to avoid, not a points source: the permit route scores on fish. Anything too far to douse in passing is walked around by detourAroundFires instead, which costs nothing and already guarantees we never walk through one. handleNearbyFire (3 tiles) was already local and is unchanged. Solo mode's continuous fire-fighting is untouched - clearing fires aggressively is the point there. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Root cause of the observed run-off. Rs2Walker.walkFastLocal builds its menu click from Perspective.localToCanvas and does not null-check it: a tile beyond draw distance or off-screen is dispatched as (-1,-1) and the client resolves that to an arbitrary destination. Measured 2026-08-05 23:21: the pool-phase trigger fired while we were at the range, walkToSpiritPool aimed at the mark ~25 tiles away, and the resulting destination was (10512,8607) - 44 tiles from our exit NPC. The wrong-side watchdog caught and cancelled it, and the bot recovered to the pool 12s later, but the walk should never have been issued. walkLocalSafe() now guards every work-area walk: turn the camera to the target, and if it is still off-screen walk a fraction of the way along the same line to a tile that IS clickable and walkable. A far target still makes progress, one hop at a time. The bug is in the shared walker, which ships in the client jar and cannot be patched from the Hub, so it is avoided at the call site instead. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…walkTo fallback The run-off past the range was Rs2Walker.walkTo, not the canvas click. When LocalPoint.fromWorld returned null, walkToWorkAreaPoint fell back to the global pathfinder - but our points are raw instance coordinates and the shortest-path plugin reads them as real-world ones. Hence shortest-path-script:trigger-null in the log, ten seconds of running, and recovery only once the pool rendered and the watchdog cancelled the destination. Both unreachable paths now stage via the totem, the mid-side anchor: - target outside the loaded scene (was walkTo) - target loaded but with no canvas point (was a straight-line partway step) The totem is used rather than interpolating along the straight line because the direct line from the range to the dock can cross water; the totem never does. Everything on our side is reachable from there, and the real target usually renders on the way, so the second leg is issued before we arrive. Staging is suppressed when the totem is itself the target, so it cannot recurse. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Permits are varbit 11936 (verified live via the agent server - read 26 while standing in the lobby). In-game points are varbit 11897. Collection runs between games, in the lobby: - take a small fishing net (303) from the Spirit Angler, NPC 10605, "Take-net" - Big-search the reward pool, object 41300 in the menu / 41356 in the object cache (multiloc, so both ids are matched) Two config options, both driven by how the reward table actually works. Per the wiki: rewards are rolled from BASE Fishing level AT THE MOMENT OF COLLECTION - not when the permits were earned - boosts do not count, and up to 8000 rolls can be stored. So holding permits until a higher level is strictly better and there is no rush: - "Permits before collecting" (default 50) - "Min Fishing level to collect" (default 1 = collect regardless) Also logs points and permits gained when a game ends, and shows permits plus the current game's gain on the progression overlay. Known limit: collection stops with 3 free slots left rather than banking, so it will not strand the next game with a full inventory. Banking is deliberately not included - a blind deposit-all would bank the harpoon, hammer and rope. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…laim
I described the pool as a multiloc on the strength of the object cache returning
41356 while the in-game menu reported 41300. That characterisation was not
established - correction from the user.
What the game data does show: ten ids exist - base 41356 tempoross_rewardpool plus
41296-41304 tempoross_rewardpool_0.._8 - and the wiki states the pool's appearance
changes as more permits are stored. At 26 permits the menu reported 41300 (_4).
Whatever drives that, matching only {41300, 41356} was fragile: a different permit
count could present a different variant and the lookup would find nothing. All ten
are now matched, which is correct under either explanation and costs nothing.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The pool presents one of ten ids and the id tracks stored permits, but the thresholds are unverified - 26 permits presenting as 41300 (_4) is the only pairing actually measured. Logging the resolved id on every collection means the mapping accumulates from normal play instead of being argued about. No behaviour change: all ten ids are already matched, which is correct whatever the thresholds turn out to be. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
… not HP Banking. Collection used to stall at 3 free slots. It now opens the lobby bank chest (41315) and deposits everything except what the next game needs: the configured harpoon, buckets (empty and full), a rope and a hammer. The small net is deliberately NOT kept - the Spirit Angler hands out a fresh one each cycle. The cloud diagnostic was measuring the wrong thing. Tempoross fire deals no hitpoint damage at all: it destroys fish and supplies. HP therefore never moved, which is why last game's log showed a flat 48 throughout and proved nothing. The CLOUDS: line now reports fish (total and cooked), water, rope and hammer, so a loss event is visible and can be attributed to 41006 or 41007. That also raises the stakes on the dodge: destroyed cooked fish is lost points, and points are permits, which is the whole objective. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Banking the net would stockpile hundreds of them - the Spirit Angler hands out a fresh one every cycle - and carrying one into a game wastes an inventory slot that should be holding fish. The net is now kept across banking DURING a collection session, so mid-session banking does not force a trip back to the Angler, and dropped as soon as collecting stops (permits below threshold, or holding for a Fishing level). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…ing it Big-search is one continuous animation that drains permits until they hit zero or the bag fills - not a per-click action. Two bugs against that: 1. The permit threshold was re-checked every loop, so with a threshold of 50 the FIRST permit spent dropped us to 49, collection returned false, and the next loop boarded the boat mid-search. The threshold now gates starting only; a collectingRewards flag keeps it draining to zero once begun. 2. After clicking we waited for permits to tick down, which returned after the first one and led straight back into a re-click, restarting the interaction. Now we only wait for the animation to START - the existing isAnimating guard lets it run untouched from there. Collection ends when permits reach zero: flag cleared, net dropped. A bag that fills mid-search still breaks out to bank and resumes afterwards. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Reads the wiki's Tempoross/Strategies recommended equipment table into TemporossGear and equips the best owned tier per slot, once per start, from the lobby bank chest: head Spirit angler headband -> Angler hat (25592 -> 13258) body Spirit angler top -> Angler top (25594 -> 13259) legs Spirit angler waders -> Angler waders (25596 -> 13260) boots Spirit angler boots -> Angler boots (25598 -> 13261) off Imcando hammer (off-hand) (29775) Slots resolve independently because the wiki notes a Spirit Angler piece is interchangeable with an Angler one without the full set, so there is no reason to hold out for a matching set. This is on-objective rather than cosmetic: Angler pieces raise points, and points are permits. The harpoon defers to the configured type - that is the user's stated intent - and only falls back down the wiki tier list when they do not own it. A plain harpoon is left to the existing crate pickup, which already covers owning none at all. Worth recording from the wiki footnotes: the top weapon tier splits by goal - Crystal harpoon "if maximum fishing experience is desired", Infernal harpoon "if maximum reward permits are desired". Infernal is correct for this plugin, and is already the config default. Rings (Lightbearer, Elven/Celestial signet) and Ghommal's lucky penny are left out: all are conditional on special-attack usage or on being under the catch-rate level, and Ghommal's penny has no matching ItemID constant to bind to. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…g slot Ghommal's lucky penny is absent from RuneLite's ItemID and from the OSRS objtypes dump (searched lucky_penny and ghommal; only infernal defenders returned), so it most likely postdates that data. Ring ids recorded inline in case the conditional cases ever become worth handling. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…ammer An Imcando hammer (off-hand, 29775) repairs from the equipment slot, so carrying a normal hammer as well is a wasted inventory slot - and that slot holds a fish, which is points, which is permits. Overridden in all four places the hammer config reached: - areItemsMissing / fetchMissingItems: no longer treats a missing inventory hammer as missing when one is worn, so no pointless trip to the hammer crate - handleRepairs: gates on canRepair() (worn OR carried) rather than the inventory alone, so repairs still happen with only the off-hand equipped - bank keep-list: only keeps a hammer when one is actually needed The CLOUDS: diagnostic now reports canRepair rather than an inventory-only count, so it stays truthful for either source. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…deciding Two bugs, either sufficient to produce "does not seem to run": 1. Chicken-and-egg. The "anything to do?" check ran before the bank was opened, but bank contents were only visible while it was open (isOpen() ? hasItem : false). Gear in the bank was therefore invisible, the check concluded "Gear already optimal", marked itself done, and the bank never opened. The feature could only ever act on gear already in the inventory. 2. autoEquipDone was never reset in run(). The script bean is a singleton, so the flag survived plugin restarts and every later start skipped auto-equip with no log at all. Now reset alongside the other per-start flags (plus collectingRewards / loggedHoldingPermits, which had the same latent issue). Rewritten bank-first: equip anything already carried (inventory menus are not reachable while the bank is up), open the chest, then one banked upgrade per pass. On completion, displaced lower tiers are deposited so they do not ride into the game as dead slots - harpoons only when one is worn, since with none worn a carried harpoon is the fishing tool. A carried configured harpoon is now wielded too: worn instead of carried is one more fish slot. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…ange Auto-equip and reward banking both bailed with "Bank chest not in range" when the script started away from the dock. Both now route through openLobbyBank(): head for the tile in front of the chest (3156, 2836 - real overworld coordinates, the Unkah dock is not instanced so the global pathfinder is safe here) and interact once within 10 tiles. The distance gate also covers the chest being in scene but too far for a reliable canvas click. Gives up after five failed pathing attempts so an unreachable start (wrong area entirely) cannot wedge the loop; counter resets per script start. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Cache names settle what the two ids are: 41006 tempoross_lightning_shadow, 41007 tempoross_lightning_shadow_short, and NPC 10580 is the harmless hovering tempoross_lightning_cloud. The shadows are the strike telegraphs and "short" means less warning - but how many ticks each variant actually gives is the number the dodge policy needs, and nobody has measured it. Logs each shadow's spawn-to-despawn lifetime in game ticks (CLOUD-TELEGRAPH: <id> lived N ticks). Pure telemetry, no behaviour change; every test game now collects the data for free. Tracked from the unfiltered scene list so a shadow leaving the 30-tile radius is not mistaken for a despawn, and lifetimes >= 100 ticks are discarded as cross-game garbage. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
A plain harpoon (and bare hands) cannot go in the weapon slot, but the harpoon logic only excluded BAREHAND - with the config on a normal harpoon it offered item 311 for wielding every pass, the equip silently failed, and the retry loop never reached the bank. Two guards: - isWieldable(): only the four wiki weapon tiers (barb-tail/dragon/infernal/ crystal) are ever offered to the weapon slot. A non-wieldable configured harpoon is a deliberate choice - auto-equip leaves it to the normal carry/crate supply logic entirely. - equipRejected: any item whose equip attempt fails (stat requirements are invisible in item ids - dragon/infernal need 60 Attack, crystal 70) is blacklisted for the session instead of retried forever. Reset per script start. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…w loadout
Per-slot diffing equipped the Angler outfit but left the displaced graceful
set riding along in the inventory into the game as dead fish slots. Redesigned
to the flow the user described: deposit worn items, deposit the whole
inventory, then withdraw exactly what the game needs.
Step machine, one step per pass, each capped at 8 passes so nothing wedges:
0 strip (deposit worn items) 4 buckets - pre-filled water from the
1 deposit inventory bank first, empty for the remainder
2 best outfit piece per slot 5 rope (in-game rule: rope && !spirit
3 harpoon - wield wieldable, anglers; hints when the full set is on)
carry plain 6 hammer (skipped with Imcando off-hand)
A stat-gated wieldable harpoon (60/70 Attack) that fails to equip is carried
instead - it fishes fine from the inventory. Bank shortfalls fall through to
the in-game crates, same as before.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…session Observed: after spending all permits it boarded the next game with the full inventory of rewards still in the bag - the "all permits spent" exit never banked, and those slots would have ridden into the game as dead fish slots. Collection session reshaped to the described flow: - opens with a deposit (keep-list only stays) so the whole bag is free before taking the net - a full bag is always banked; in drain mode collection then resumes until permits hit zero - EVERY exit path banks remaining loot first: drained, one-load done, or bank unreachable (which now also latches the session shut instead of restarting into the same dead end every pass) New "Spend all permits" toggle (default on): off collects one inventory per lobby visit, banks it, and returns to the game; the latch clears when the next game starts. Keep-list extracted to rewardKeepList() and shared with the new hasLootToBank(), which replaces the free-slot heuristic for "anything worth banking". Bank shortfalls of buckets/rope/hammer remain non-fatal throughout - the in-game supply crates cover whatever the bank could not provide. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
… behaviour User call: bank-when-full-and-go-back-for-more was the whole ask, and that is what drain-to-zero already does, so the one-load mode was a config knob with no audience. The rewardSessionDone latch stays for its other job - stopping a collection whose bank went unreachable from restarting into the same dead end every pass until a new game clears it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…ions permits < threshold passes when both are zero, so every lobby loop pass opened a session that logged "Collecting 0 permits" and immediately "All permits spent". Harmless but noisy, forever. Starting now also requires permits > 0, which gives threshold 0 the sensible reading: collect whenever there is anything to collect. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…scipline Three changes built on the first live telemetry (five 41006 shadows, all exactly 16 ticks from spawn to strike): Clouds - dodge on a timer, not on sight. A 41006 shadow only counts as a threat inside its final 4 ticks, so standing on a fresh one keeps fishing instead of throwing away up to 9 seconds per cloud (the "dodges early" observation). 41007 stays flee-on-sight until measured; shadows first seen mid-life count as imminent. The tracker now runs BEFORE the wave gate in onGameTick so ages keep counting through waves. Strikes never land on the pool point (observed live), so a pool harpoon is never abandoned. CLOUDS diagnostic gains nextStrike=Nt. States - the fixed ~49% catch cutoff becomes adaptive: an EMA of the energy drain rate (sampled from widget changes, reset on any rise) projects ticks until the pool phase, and catching stops when that is only just enough to cook (~2t) and load (~1t) the raw fish held, plus walking overhead. Fast mass worlds cut earlier, slow ones keep fishing past 49%. Falls back to the old line until the rate is sampled. Camera - once per game: high pitch + wide zoom (whole side on screen), and walkLocalSafe now widens the view (pitch, then zoom steps) when a yaw turn was not what the off-screen target needed. Observed live: 22 seconds of "no on-screen approach" at game start with nothing ever changing the view. Fewer arrow-key turns also means fewer of the 3x-speed camera spins. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…ding Observed: attempt 1 fired while the welcome screen was still initializing (getLocalPlayer null), a guaranteed failure that consumed one of the three tries. Now waits for the player to exist before attempting, without counting the wait against the attempt budget. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
A strike can drop a fire ON the player's tile with roughly one tick to douse it before supplies burn. The script loop's 300ms cadence can eat most of that budget, so the on-top-of-us case now bypasses the loop entirely: an NpcSpawned subscriber recognises a Douse-action NPC within a tile of the player and sends the Douse click the same client frame it spawned (water permitting). One click per tick across a spawn batch; anything further away stays with the hazards-first loop from the previous commit. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Pre-review hardening: the client-thread snapshot fields were volatile, but the older cross-thread statics were not - state, workArea, isFilling, the entity lists (sortedFires/sortedClouds/fishSpots), and the per-tick fish counters plus cachedInMinigame are all written on the client thread and read on the script executor. All volatile now. The lists were already replaced whole rather than mutated in place, so reference visibility is the only thing that was missing. Also audited the new instant-douse path for client-thread safety: the click helper's walk branch only runs behind a latched cant-reach flag and the walker no-ops on the client thread; runOnClientThreadOptional executes directly when already there. Rs2Player.isMoving/isAnimating wrap runOnClientThreadOptional internally, so their remaining uses are sound. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Two live findings on 2.21.7: Red mark, no movement. A clicked fish spot with no walkable path (fresh double, path blocked) leaves the interaction set while the player stands still - and the interaction-based busy check read that as "busy" forever. Busy now requires PROGRESS: moving, or engaged with the fishing animation playing. A stuck stand falls through to the fire/detour logic and a fresh approach instead of waiting. Parked at an empty pool from 30%. The recharge tops out around 97 against an ATTACK completion threshold sampled at 98, so the phase could end with the latch still set: the redirect-to-fishing required the latch clear, and the clear required energy 92+, leaving the bot idling at the mark through the whole climb. A pool that stays gone for ~6 passes (~2s) with energy past the approach window now ends the phase on the spot. The pool query already required the Harpoon action, so ghost pool NPCs were not the cause. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Observed: a fire douse stopped the character, and the re-walk to the crate spammed "no on-screen approach" for 12+ seconds with the camera visibly not turning. The camera ladder was an else-if: when one rung silently did nothing (pitch smoothing no-op), it re-claimed its turn every pass and the yaw rung never ran. Two changes to walkLocalSafe: - all camera rungs fire together each pass (redundant adjustments are cheap, stalls are not) - a camera-independent last resort: a MINIMAP click needs no 3D projection. A bounded leg (11/8/5/3 tiles, first walkable and fire-free) along the line toward the target gets clicked on the minimap, repeating from closer next pass. Raw instance coordinates round-trip correctly because worldToMinimap converts back through LocalPoint. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Observed: dodged a cloud cleanly, then ran back through the fresh fires twice. Two holes: - the cloud-dodge escape predicate only avoided CLOUDS, so a dodge could legally land on or beside a fire; it now requires fire-free tiles too - every fire check ran at CLICK time, and most handlers return early while already moving, so a fire spawning on a committed path was run through. New handleFireOnPath in the hazards chain: while moving, the nearest live fire near the remaining path is doused once within ~6 tiles (the Douse click redirects the walk); with no water the walk is broken off so the detour logic can route around it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
User strategy call: the boss does not normally survive two pool phases, so essence at or under half after pool 1 means the next pool kills it, and energy under 30 means that pool is a minute or two out. Both together now trigger the emergency fill of everything held - raw and cooked - into the cannon (previously essence <=20 with energy <=48, which barely ever fired given essence only falls during pool phases). By arrival energy is lower still; fish not loaded when the boss dies score nothing. Both gates are named constants (ESSENCE_ENDGAME / ENERGY_ENDGAME) and expressly tuned by trial and error; the log line now prints both readings so rounds show how early the dump engages. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
User strategy (wiki-endorsed): after the opening load, everything caught and cooked before the FIRST pool phase stays in the bag, and the cannon trip happens after the phase ends. Every early catch is one fewer to catch in the short post-pool window - 170 kills of live data say the round is decided by the second pool, so the pre-pool-1 hold is free (pool 1 cannot end the round, essence starts full) and jump-starts the only load that matters. Saves a crate trip too. Mechanics: - poolPhasesSeen counts phases from the energy widget itself - energy only recharges during a pool phase, so a rise out of the low band IS one; no reliance on our own staging flags. Reset per game and per start. - while poolPhasesSeen == 0, the THIRD_COOK -> SECOND_FILL advance redirects back to catching, and the low-energy emergency fill is suppressed - a full cooked bag pre-pool stands by instead of clicking spots that cannot pay out Also corrected against the Reward pool wiki page: it drops NO outfit pieces (the Spirit Angler set there is just the navbox); the post-collection auto-equip re-run is kept for the pool's real equipable unique, the dragon harpoon. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Observed again: hop attempt 1 fired seconds after login and failed - the player EXISTING is not enough, the welcome banner keeps initialising for several seconds and the world switcher cannot open through it; attempt 2 then fired with zero cooldown. The hop now settles ~5s (8 ticks) after the player first appears before the first attempt, cools down ~6s (10 ticks) between attempts, and gets 4 tries instead of 3. The mid-hop LootTracker NPE in the log is the stock RuneLite plugin reacting to a chat message while the local player is null during the hop - client-side, cosmetic, not reachable from the Hub. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
User call: banking and reward collection are world-agnostic (lobby chest and pool exist everywhere, permits are an account varbit), only boarding wants the mass world. Hopping last means the client has settled long past the welcome-banner window that made login-time hops fail; the settle and cooldown guards remain for the nothing-to-bank case. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Observed: THIRD_CATCH left a live double to cook 4 fish. The adaptive/49% cutoff fired on ">=4 fish + energy at the floor" with no regard for the double - only the batch-of-7 rule respected it. With the endgame dump backstopping at ENERGY_ENDGAME, deferring is safe: a double dies within ~23s (measured) which re-arms the cutoff, and anything the schedule cannot cook is swept raw by the dump. - THIRD_CATCH cutoff (floor and adaptive both) suspended while a double is up; bag-full still ends the catch - the SECOND_COOK/THIRD_COOK double interrupts now yield down to the dump gate (30) instead of the load cutoff (48) - every tick above the dump with a double up belongs to the double Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
… sweep User flow, now the whole round shape: second cook -> opening load -> fish (and cook) while waiting for pool 1, holding everything -> after the pool, catch-and-cook batches continuously -> the emergency fill / endgame dump is the SINGLE cannon trip of the cycle, sweeping cooked and raw together. - the scheduled SECOND_FILL is never entered, in any cycle; loading happens via the opening INITIAL_FILL and EMERGENCY_FILL only - the load cutoff (49% floor + adaptive projection) is gone from THIRD_CATCH: below the old line the batch just shrinks to 4 so the backlog stays cooked for the sweep (cooked deposits 65 against 20 raw), which also kills the cook-per-fish thrash the cutoff would have caused under the new flow - a live double still suspends batching outright, bag-full still ends any catch, and the emergency/dump gates are unchanged (full bag under 49, or 6+ fish under 33, or essence <=50 with energy <=30) Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Root cause read out of Microbot.hopToWorld: it opens the world switcher and requests the hop in ONE client-thread pass, but the panel opens asynchronously, so the request is dropped before the switcher exists. That made attempt 1 fail every single time, with attempt 2 working only because attempt 1 had left the panel open. The welcome-banner and settle theories were incidental. The script now opens the switcher itself a few ticks before the first attempt, so the hop request lands on an existing panel. Also, the retry cooldown is armed AFTER the attempt returns - armed before it, the ~6s the call itself takes had already burned the window and retries fired back to back. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Observed on a slow round: cooking finished with a full bag at ~50% energy, and the bag-full sweep gate (<49) left the bot standing idle waiting for the threshold. A full, fully-cooked bag has nothing left to do at any energy - it now goes straight to the cannon (post-pool-1 as ever), freeing the bag for more catching in the remaining window. Full with raw still cooks first. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
The plugin is now at ver 2.24.2 the plugin is stable. Tested running for ~1-2 hrs after the last commit. The phases still need a bit of work but it's consistent permits. |
chsami
left a comment
There was a problem hiding this comment.
Thanks—the release version is now aligned at 2.24.2, the submitted CI is green, and a clean synthetic merge with current development (7a16229) passes ./gradlew build -PpluginList=TemporossPlugin. The 1–2 hour live run is also useful.
The threading migration on current head d375ea6 is still incomplete, though. The scheduled script executor continues to consume live client objects and perform client/world-view conversions outside GameTick, for example:
handleWrongSideClick()callsRs2Player.getInteracting(), then reads the returned NPC's world location, and callsWorldPoint.fromLocal(Microbot.getClient(), dest).handleFires(), theATTACK_TEMPOROSSstate, andhandleNearbyFire()callRs2Player.getInteracting()and then inspect the returned live actor/NPC on the executor.localToWorld()calls bothLocalPoint.fromWorld(Microbot.getClient(), ...)andWorldPoint.fromLocalInstance(Microbot.getClient(), ...); multiple executor paths also callLocalPoint.fromWorld(Microbot.getClient(), ...)directly. Those conversions consult the client's world view/plane and belong on the client thread or in the per-tick snapshot.
cachedInteractingIndex is captured correctly but currently used only for the fishing-spot check; the other interaction branches still retrieve live actors. Please finish the snapshot boundary by caching the plain interaction/location/coordinate data needed by the executor (or marshal each complete operation onto the client thread), rather than returning RuneLite objects and reading them later off-thread. After that, please rerun the focused multi-round live check. I am not changing this broad runtime rewrite from the maintainer side.
…thread Addresses the second threading review on PR chsami#534. The executor no longer touches any live RuneLite object or performs client conversions: - interaction snapshot extended to plain data (cachedInteractingId and cachedInteractingWorld alongside the index), captured on GameTick. All five executor interaction sites now use it: handleWrongSideClick (side check via the cached world point), handleFires and handleNearbyFire ("already dousing" by index), and the ATTACK_TEMPOROSS busy-with-pool check (id + cached location against the pool mark). Zero Rs2Player.getInteracting() calls remain in the plugin. - every LocalPoint.fromWorld / WorldPoint.fromLocal / WorldPoint.fromLocalInstance is marshalled through localFromWorld / worldFromLocal / templateFromLocal, each a complete operation on the client thread via getClientThread().invoke (which executes inline when already on it, so client-thread callers pay nothing). The three helper bodies are the only raw conversion sites left in the file. A fresh focused multi-round live check on this build follows. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
Snapshot boundary completed in 9bac075 (v2.24.3), covering every site named plus one more of the same class:
A fresh focused multi-round live check on this exact build is being run and will be reported here. 🤖 Addressed by Claude Code |
The 2.24.2 full-and-cooked arm sat behind the poolPhasesSeen gate, so during the pre-pool-1 hold a bag that filled after a few batches stood idle until the pool arrived. The hold means no SCHEDULED trips, not stranding a full bag: loading it and refilling beats idling in every cycle. The low-energy arms keep the pool-1 gate. (Report that surfaced this came from a stale 2.24.0 sideload, but the idle exists pre-pool on current head too - the fix stands on its own.) Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
Run for 1h. no issues within the minigame found. world hop now completes on the first try. roughly 4 permits per game with a basic harpoon and level ~70 fishing on mass worlds. could get more or less depending on the amount of players. threading migration should be complete now |
chsami
left a comment
There was a problem hiding this comment.
The interaction fields and scene conversions called out on the prior head are corrected, but the snapshot boundary on current head 2908490 is still incomplete.
The GameTick publisher replaces sortedFires, fishSpots, sortedClouds, and work-area references atomically, but those collections still contain live Rs2NpcModel, NPC, GameObject, and tile-object wrappers. The scheduled executor then dereferences them directly. Examples include fishSpots entries through getNpc().getLocalLocation() in the catch/fill paths, sortedFires entries through getNpc().getLocalLocation() in handleNearbyFire and fire-path handling, and sortedClouds GameObject locations in the dodge paths. The current model wrappers delegate those location reads to live actors/objects; replacing the list does not snapshot their fields.
Please publish the plain IDs/indices and LocalPoint/WorldPoint data needed by the executor from GameTick, or marshal each complete live-object operation to the client thread. Avoid retaining live RuneLite objects for later executor reads. Add focused automated coverage where practical and rerun the normal targeted build. The existing green CI and reported runtime results do not remove this client-thread race.
|
Addressed in c3ed416 (v2.24.5). The executor-facing boundary now contains only immutable plain-data snapshots:
Added Verification:
|
|
Follow-up on the failed build job: CI resolved Microbot Verification:
The Tempoross snapshot-boundary changes remain unchanged in |
chsami
left a comment
There was a problem hiding this comment.
Re-reviewed the synchronized head. The executor/client-thread boundary now publishes immutable plain snapshots, resolves live NPC/tile-object wrappers only inside client-thread operations, and keeps cross-thread signals volatile. The version is aligned at 2.24.5. A fresh synthetic-merge build produced the Tempoross and Farming Contracts JARs with all five added tests passing; updated-head CI is green.
What this is
A ground-up rework of the Tempoross plugin (v2.0.0 -> v2.20.1) built around one goal: maximum reward permits per game on mass worlds, using the "cook everything" strategy. Points, not XP.
Gameplay changes
Reliability fixes (all reproduced live before fixing)
Rs2Player.getWorldLocation()returns template space, entity locations return raw scene space - mixing them broke fish-spot choice, repairs, walking. All internal logic now stays in one space;docs/INSTANCE_COORDINATE_SPACES.mddocuments the trap for other pluginsTemporossSide): both arena halves are in the scene with distinct ids; side is resolved from the exit-NPC id, never from geometry (measured 1-tile margin made proximity rules flip sides)Reviewer notes
minClientVersionraised to 2.6.16 - the rework uses the newer cache/query APIs (Rs2TileObjectCache, NPC cache queries,hopToWorld)PluginConstants.INFUSEprefix constant (unused by this plugin, available for future ones)Co-authored with Claude (Anthropic) during live debugging sessions.
🤖 Generated with Claude Code