StatForge

Live ratio panel for Torn gym stats with rep-counter automation and per-stat gym switching. Inspired by ClasixTV's original Torn ratio helper. TornPDA users should set injection time to END.

Đây là phiên bản của script này, nơi mã nguồn đã được cập nhật. Hiện tất cả các phiên bản.

  • 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