If you’ve ever tried to max out character stats in Final Fantasy VIII, you know the pain. It’s not a boss fight or a puzzle — it’s hours of navigating the same menus, buying the same items, refining the same materials, and pressing confirm hundreds of times. It’s a grind designed for patience I don’t have.
So I wrote a script to do it for me.
The Problem
In FF8, stats like Strength, Vitality, and Magic cap at 255. HP caps at 9,999. To push a character’s stats to those ceilings, you need stat-boosting items — things like Str Up, Vit Up, Mag Up, and HP Up. You can’t just buy them outright. Instead, you have to:
Farm gil — the game’s currency — by buying Tents and Cottages, refining them into Mega Potions through a GF ability, and selling the Mega Potions at a profit. Each cycle nets you 352,500 gil. To fill up your wallet (99,999,999 gil), you might need to repeat this loop hundreds of times.
Farm stat-up items — take that gil to the Esthar Pet Shop, buy materials like Power Wrists or Hypno Crowns, refine them through two layers of GF abilities (GFAbl Med-RF, then Forbid Med-RF), and finally get your stat-up items. Each item costs 1,500,000 gil worth of materials. For a single stat like Strength, you need up to 255 of them.
Use the items — navigate to the Item menu, select each stat-up item, choose a character, and confirm. Every. Single. Time.
One full pass through this workflow yields about 60 stat-ups for Strength, Vitality, or Magic (or 100 HP Ups). To max a single stat from zero, you’d need to repeat the entire cycle several times. Multiply that by four stats and six characters, and you’re staring down thousands of repetitive menu inputs.
I did this by hand for about ten minutes before deciding there had to be a better way.
The Solution: Keyboard Automation
I wrote a Python script that automates the entire pipeline. It doesn’t hack the game, read memory, or modify any files. It simply simulates keyboard presses — the same ones you’d be mashing yourself — and sends them to the game in the exact sequence needed to navigate every menu.
The script chains together three distinct phases in a loop:
- Gil Farm — Automates the buy/refine/sell profit loop until you hit 99,999,999 gil
- Stat Farm — Buys shop items and refines them through two GF ability tiers into stat-up items
- Item Use — Applies all the stat-up items to your chosen character
Then it loops back to step 1 and repeats until the stat is maxed. You select a character, pick a stat, enter your current numbers, and walk away.
Demo (54 secs): Here’s the script running end-to-end (gil farm → stat farm → item use), with live terminal ETA updates.
How It Actually Works (Under the Hood)
The script is built on a library called pydirectinput, which sends low-level keyboard input that DirectX games (like FF8 on Steam) can actually receive. Normal keyboard simulation libraries often get ignored by games — pydirectinput bypasses that by talking to the Windows input pipeline directly.
The core of the automation is straightforward: every menu action in FF8 is deterministic. If you’re on a specific menu item and press Down three times, then Enter, you will always land on the same option. The game has no randomness in its menu navigation. That predictability is what makes this kind of blind automation possible.
Here’s the catch — it really is blind. The script has no idea what’s actually on screen. It doesn’t use image recognition or read pixel data. It assumes you’ve set up the game state exactly as expected (cursor on the right item, correct shop open, empty first page in your item inventory). If anything is off by even one menu position, the entire sequence desyncs and you’ll be buying the wrong items or navigating into the wrong menus.
That fragility is a tradeoff I accepted. Adding screen reading or OCR would make it far more complex and introduce dependencies on resolution, UI scaling, and frame timing. The deterministic approach keeps the script under 1,100 lines with zero external dependencies beyond the input library.
The Execution Plan
One thing I’m particularly happy with is the planning system. Before the script presses a single key, it builds a complete execution plan. It calculates:
- Exactly how many stat-up items are needed based on your current base stat and the maximum
- How many buy/refine cycles and runs that translates to (including partial runs to avoid waste)
- The exact gil cost of each iteration
- Time estimates for every phase — gil farming, stat farming, navigation, and item usage
These estimates aren’t guesses. I calibrated them from actual timed runs. For example, each gil farm cycle takes about 13.15 seconds, each stat farm buy/refine cycle takes about 9.35 seconds, and each GF ability refinement step takes about 2.2 seconds. The script uses these constants to project how long the entire process will take before it starts.
As it runs, it tracks actual elapsed time against the plan and adjusts its ETA. If the first iteration ran 5% slower than estimated (maybe due to slightly longer loading screens), it scales the remaining time projection accordingly. It’s a simple linear correction, but it keeps the ETA honest rather than drifting further off as the run progresses.
What the Output Looks Like
When you run the script, you get a configuration summary, a full execution plan with per-phase breakdowns, and then real-time progress logging:
==========================================
Configuration Summary
------------------------------------------
Character: Squall (position 1)
Stat: Str Up
Current base stat: 130
Target stat: 255
Str Ups needed: 125
Total iterations: 3
Current gil: 99,999,999
Starting phase: Stat Farm
Max gil when done: No
==========================================
Execution Plan
------------------------------------------
Iteration 1/3: ~9m 55s
Stat Farm (6 runs): ~9m 35s
Nav + Items (60x): ~20s
------------------------------------------
Iteration 2/3: ~1h 6m
Gil Farm (256 cycles): ~56m 6s
Stat Farm (6 runs): ~9m 35s
Nav + Items (60x): ~23s
------------------------------------------
Iteration 3/3: ~57m
Gil Farm (256 cycles): ~56m 6s
Stat Farm (1 run, 5 cycles): ~46s
Nav + Items (5x): ~7s
------------------------------------------
Total estimated: ~2h 13m
==========================================
Each cycle logs its own runtime and the cumulative elapsed time, so you can glance at the terminal and know exactly where things stand.
Flexible Input Parsing
A small quality-of-life detail: the gil input parser accepts human-friendly formats. You can type 210k, 0.21m, 99m, 15000000, or even max. It sounds trivial, but when you’re entering values repeatedly while testing, not having to count zeros matters.
The Numbers
To put it in perspective, here’s what maxing Strength on a single character from a base of 130 looks like:
| Metric | Value |
|---|---|
| Str Up items needed | 125 |
| Gil Farm Cycles (assuming you start at max gil) | 512 |
| Automated execution time | ~2h 13m |
| Manual execution time | ~6-8hrs |
The bulk of that time is gil farming — two of the three iterations need a full 256-cycle gil farm run at ~56 minutes each. The stat farming and menu navigation are comparatively quick, but a human would still need to perform every buy, every menu navigation, and every item use manually at a much slower pace. The script’s precision with frame-level timing lets it work roughly 3x faster than a human could.
Doing this by hand, you’re looking at around 6–7 hours for a single character and a single stat. Now multiply that across four stats and six characters. The script turns what would be a multi-week manual grind into something you can run in the background while you do literally anything else.
Why I Built It This Way
As someone who works in data engineering, my instinct when I see a repetitive, rule-based process is to automate it. The same principles that apply to building reliable data pipelines apply here:
- Deterministic inputs produce deterministic outputs — FF8’s menu system is essentially a state machine with known transitions. Model those transitions as a sequence of inputs, and you have a pipeline.
- Calculate before you execute — the script builds the full plan upfront, just like how a query optimizer plans execution before touching data. No wasted cycles, no over-purchasing.
- Observe and correct — real-time ETA adjustment is the same idea as monitoring pipeline SLAs and adjusting expectations based on actual throughput.
Limitations and Caveats
This is a tool for a specific audience. You need:
- The PC or Remastered version of FF8 on Steam
- Windows 10 or 11
- Python installed on your machine
- The game set to Borderless Windowed mode (fullscreen can block simulated input)
- Enough comfort with a terminal to run
pip install pydirectinputandpython max_stat_farm.py
The script is also inherently fragile by design. Any unexpected dialog box, a loading screen that takes slightly too long, or an accidental mouse click can throw it off. You should keep an eye on it while it runs and be ready to hit Ctrl+C if something looks wrong.
Try It Yourself
The full source code is on GitHub. It’s a small repo — just four scripts, no frameworks, no complex setup. If you’re an FF8 fan who’s been putting off the stat maxing grind, this might save you a few evenings.
And if you’re not a Python person but found this interesting — the takeaway is that any repetitive, deterministic process is a candidate for automation. You just need to map out the states, define the transitions, and let the machine handle the tedium.
