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.

هذه إصدارات لهذا البرنامج النصي حيث تم تحديث الكود. عرض كل الإصدارات.

  • 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