StatForge

Live ratio panel for Torn gym stats with rep-counter automation and per-stat gym switching, plus a styled floating drug-cooldown alarm shown on all Torn pages via the Torn API (requires your own API key). Inspired by ClasixTV's original Torn ratio helper. TornPDA users should set injection time to END.

These are versions of this script where the code was updated. Show all versions.

  • v1.11.8 14. 06. 2026

    feat: alarm shows only in final 5 min, doubled size, blink on ready

    Hide the floating drug-cooldown pill until the cooldown has <=5 min left (DRUG_ALARM_SEC=300) or is ready; set-key/error states stay visible so it can still be configured. Double the pill size (font 13->26px, padding /dot/border doubled). Blink (sf-drug-blink) only in the ready state; the final-5-min countdown (sf-alarm) is steady. Bump to v1.11.8.

    Co-Authored-By: Claude Opus 4.8 (1M context) [email protected]

  • v1.11.6 14. 06. 2026

    feat: redesign drug cooldown alarm as styled floating pill

    Replace the sidebar status-icons indicator (which inherited Torn's icon styling and looked out of place) with a fully self-contained floating pill appended to document.body: own id #sf-drug-alarm, namespaced .sf-* classes, injected CSS with idle/countdown/ready(green+pulse)/error states. No Torn class is read or written, so nothing bleeds in. API polling, active-view gating, item.php click and bad-key auto-prompt are unchanged. Fixed bottom-left. Bump to v1.11.6.

    Co-Authored-By: Claude Opus 4.8 (1M context) [email protected]

  • v1.11.4 14. 06. 2026

    fix: neutralise inherited status-icon background on drug badge

    Torn styles every status-icons

  • as a fixed-size icon with a background sprite/colour, which bled through behind the drug-cooldown pill (a green sprite corner). Inject a #sf-drug-badge-scoped style that resets background, sizing, box-shadow and ::before/::after with !important. Bump to v1.11.4.

    Co-Authored-By: Claude Opus 4.8 (1M context) [email protected]

  • v1.11.3 14. 06. 2026

    feat: move drug cooldown to status-icons row + key UX

    Relocate the drug-cooldown indicator from the Energy bar to the first item of the sidebar status-icons row (li#sf-drug-badge inserted via insertBefore, hardened ul[class*="status-icons___"] selector, verified dump). Click with a working key opens item.php; no key / bad key opens the key prompt, and a code-2 'incorrect key' auto-prompts once. Bump to v1.11.3.

    Co-Authored-By: Claude Opus 4.8 (1M context) [email protected]

  • v1.11.1 14. 06. 2026

    feat: render drug cooldown inline in sidebar Energy bar

    Replace the floating fixed badge with an inline span inserted right after the Energy bar-value in Torn's left sidebar (verified DOM dump). Locate the Energy row via hash-safe [class*="bar-name_"] + /energy/i, insert after [class*="bar-value_"], and re-attach on sidebar re-render. Colored text instead of a pill: amber countdown, green "ready". Bump to v1.11.1.

    Co-Authored-By: Claude Opus 4.8 (1M context) [email protected]

  • v1.11.0 14. 06. 2026

    feat: drug cooldown badge on all Torn pages via API

    Widen @match to https://www.torn.com/* and add an all-pages drug cooldown badge driven by api.torn.com (selections=cooldowns). Polls every 60s only while the tab is actively viewed, shows a live local countdown, and turns green ("Drug ready") when the cooldown expires. API key entered via prompt() and stored locally. Gym ratio panel is still gated to gym.php via isGymPage(). Bump to v1.11.0.

    Co-Authored-By: Claude Opus 4.8 (1M context) [email protected]

  • v1.10.10 01. 06. 2026

    chore: remove internal TORN_DOM.md references from public comments

    The 5 comments referencing the private DOM-dump doc name leaked an internal artifact name into the public repo. Reworded to 'verified against gym.php DOM dump' — same meaning, nothing internal exposed.

    Co-Authored-By: Claude Opus 4.8 (1M context) [email protected]

  • v1.10.9 30. 05. 2026

    fix: abbreviate numbers in history table to fit mobile screen

    Co-Authored-By: Claude Sonnet 4.6 [email protected]

  • v1.10.8 13. 05. 2026

    feat: gate DOM-reading auto-paths on actively-viewed tab

    Adds isActivelyViewed() (visibilityState + hasFocus) and gates the four auto-paths that read the gym page: waitAndInject, backgroundStatWatch, syncEnergyBaseline, and the trainObserver callback. Adds visibilitychange

    • focus listeners to resume work and resync the energy baseline when the tab becomes actively viewed again.

    Bumps to v1.10.8. Aligns with Torn's 2026-05-13 scripting-rule clarification that scripts may only read from pages the user is actively viewing (foreground tab + focused window).

    Co-Authored-By: Claude Opus 4.7 (1M context) [email protected]

  • v1.10.7 30. 04. 2026

    chore: bump v1.10.7

  • v1.10.6 30. 04. 2026

    chore: drop dead initial assignment in clear-history confirm

    ESLint v9.13's no-useless-assignment caught let confirmed = false; — the value is never read because both try and catch branches assign before the next read. Cleanup; behavior unchanged.

    Bumps version to 1.10.6.

    Co-Authored-By: Claude Opus 4.7 (1M context) [email protected]

  • v1.10.5 29. 04. 2026

    fix(ratio): drop forcedDump from isStatDumped — multipliers drive skipping

    1.10.4 over-corrected by treating RATIOS[ratioKey].forcedDump as a "skip this stat" signal. That was wrong:

    • forcedDump is the recommended default for the user's dump-stat picker UI (so selecting Aec3 auto-picks DEX in the dump dropdown), not a directive to exclude the stat from training.
    • Aec3's DEX has multiplier 0.1351 (13.51%). The ratio's intent is to KEEP DEX at that ratio, not zero it. Treating forcedDump as a skip caused the planner to ignore DEX entirely — directly violating the ratio the user wants respected.

    Strip the forcedDump check from isStatDumped. The remaining rule is: the ratio's multiplier for whichever role this stat occupies must be exactly 0 to count as a dump.

    Concrete behaviour after this:

    • Hank: tert2 multiplier is 0 → that role's stat is skipped (unchanged from the original hardcoded check).
    • Aec3: DEX has multiplier 0.1351 → DEX is trained up to its 13.51% target like any other ratio stat.
    • Custom ratios with one or more 0 multipliers → those stats skipped. Two-stat or three-stat builds still work without code changes.

    Co-Authored-By: Claude Opus 4.7 (1M context) [email protected]

  • v1.10.4 29. 04. 2026

    fix(ratio): respect any ratio's dump intent, not just Hank's

    Six sites hardcoded the dump-stat check as ratioKey === 'hank' && roles.tert2 === key which meant the rep allocator and grade ignored every other ratio's dump declaration:

    • Aec3 declares forcedDump: 'dex' but the planner queued reps for DEX when it was below its 13.51% target.
    • Custom ratios with one or more 0-multiplier slots were trained anyway, since only tert2 was checked.
    • "Only train 2 stats" / "only train 3 stats" builds had no clean declarative way to be honoured.

    Replace all six sites with a single helper:

    isStatDumped(key, ratioKey, roles)

    That returns true when:

    1. RATIOS[ratioKey].forcedDump matches key (Aec3 → DEX), OR
    2. The ratio's multiplier for whichever role key occupies is 0 (Hank's tert2; or any Custom slot zeroed out — this is what makes 2/3-stat builds work without further code changes).

    Sites updated: computeRepPlan (rep allocator) overallGrade (overall ratio grade) getDriftWarnings (per-stat drift detection) buildExportText (export panel display) renderOverview x2 (recommended stat picker + per-stat status)

    Effect for Aec3 + DEX dump (the user's loadout): DEX is now skipped in the rep planner, the grade, drift warnings, recommended stat, status row, and exported text. Reps redistribute to STR/SPD/DEF based on whichever is most behind its ratio target. Hank behaviour is preserved (its tert2 multiplier of 0 still triggers the skip).

    Custom ratios automatically get the same treatment for any 0-multiplier slot — including 2-stat or 3-stat training plans without further code.

    Co-Authored-By: Claude Opus 4.7 (1M context) [email protected]

  • v1.10.3 29. 04. 2026

    feat: serialise train-button clicks behind Torn's UI-ready signal

    Spamming the train button could race Torn's mid-transition UI. Each click fired executeTrainStep synchronously, so a second click might land on a stale button reference, miss the freshly-rendered confirm button, or send the rep-counter to the wrong gym.

    Two changes:

    1. New sfWaitForCondition(predicate, maxMs) — same shape as TSA's qtWaitForCondition. Resolves true when the predicate becomes truthy under any DOM mutation, false on timeout.

    2. executeTrainStep → executeTrainStepAsync. After each click, await Torn reaching the expected next state:

      switch → wait for membership-confirm to appear OR active gym to match step.target (free switches don't show confirm). confirm → wait for membership-confirm to disappear. fill → wait for the input value to reflect the requested reps. train → wait for the train button to re-enable OR energy to drop.

    Each wait has a 3 s ceiling (500 ms for fill); on timeout the step resolves anyway so the user can manually retry.

    1. Click handler at #trh-train-now now sets a module-level trainStepInFlight flag while the async step runs. Spam clicks while the flag is set are silently dropped — once the previous step resolves, the next legitimate click is processed against the already-stable Torn UI.

    Net effect: clicking faster than Torn can render no longer breaks the flow; the script processes one click at a time, waiting for Torn's UI to settle between each.

    Co-Authored-By: Claude Opus 4.7 (1M context) [email protected]

  • v1.10.2 25. 04. 2026 Imported from URL
  • v1.10.1 22. 04. 2026

    Sync scripts from Claude repo

  • v1.10.0 22. 04. 2026

    Sync scripts from Claude repo

  • v1.9.10 22. 04. 2026

    Sync scripts from Claude repo

  • v1.9.9 22. 04. 2026

    Sync scripts from Claude repo

  • v1.9.8 22. 04. 2026

    Sync scripts from Claude repo

  • v1.9.7 22. 04. 2026 Imported from URL
  • v1.9.7 22. 04. 2026