Sync works on the deployed site; add reproducible build and deploy script

The Pages deployment is now the primary copy, so two things had to change:

- Hosted pages fall back to steam-sync.py on 127.0.0.1:8765 instead of
  refusing to sync. steam-sync.py now answers Chrome's Private Network
  Access preflight (Access-Control-Allow-Private-Network), which is what a
  public https page needs before it may call into localhost.
- The build sources lived in /tmp and would have been lost. They now live in
  build/, and build.py outputs to the repo root. deploy.sh rebuilds,
  commits and pushes in one step.

Editing index.html directly is no longer the workflow - edit build/ and run
./deploy.sh.
This commit is contained in:
Rain 2026-09-15 17:40:06 -04:00
parent 4d5545e6c5
commit a63606b5c8
17 changed files with 6120 additions and 18 deletions

411
build/roadmap_src.py Normal file
View file

@ -0,0 +1,411 @@
# -*- coding: utf-8 -*-
"""Ordered story walkthrough for the 'Everything Run' plus the later passes."""
ROADMAP = [
dict(phase="Phase 0 — Before you play", intro="""
<p>Do these first: they are free, and one of them changes how you do everything else.</p>""",
steps=[
dict(id="r0-1", title="Read the Screenplay Book to the end", area="Master Collection launcher → MGS2 Screenplay",
body="""<p>Free achievement (<b>Cover-to-Cover Solid 2</b>). Open the Screenplay from the launcher and page all the way to the last page.</p>"""),
dict(id="r0-2", title="Decide your run order and never break it", area="Planning",
body="""<p>You are going to play the game at least <b>five</b> times. Keep one save slot per run, and never overwrite a
<b>completed</b> file those are what carry the special items forward.</p>
<ul class="tight">
<li><b>Run 1</b> Very Easy, TankerPlant. Every misc/missable achievement + all 67 tags.</li>
<li><b>Run 2</b> Easy. All 70 tags.</li>
<li><b>Run 3</b> Normal. All 82 tags (you only need up to 76 Tanker / 120 Plant, but take them all).</li>
<li><b>Run 4</b> Very Easy with Stealth Camo + Bandana. Pacifist Run + Complete Stealth together.</li>
<li><b>Run 5</b> Extreme, no special items, no radar. Big Boss.</li>
</ul>
<p class="muted">Runs 13 are the same route the walkthrough below covers Run 1 in full and applies to all three.</p>"""),
dict(id="r0-3", title="Turn ON 'Hide done' if you want a clean screen", area="This page's header",
body="""<p>Use the header toggles. Export a backup of your progress before each playthrough so you can roll back a bad tap.</p>"""),
]),
dict(phase="Run 1 · Tanker (Very Easy)", intro="""
<p>Ordered by area. Everything here also applies to the Easy and Normal tag runs the only difference is
<b>which guards have tags</b>. Switch the <b>Dog Tags</b> tab to the matching difficulty as you go.</p>
<div class="infobox">Set the difficulty to <b>Very Easy</b> and start a <b>Tanker-Plant</b> game (not Tanker only)
the special-item achievements expect a completed Tanker-Plant file.</div>""",
steps=[
dict(id="r1-1", title="Aft Deck — arrival", area="Tanker · Aft Deck",
shots=["Silence is Golden"],
body="""<p>Nothing missable. Three guards carry tags here (<i>Josh Spires, Tomomi Nasu, Stephen M Driver</i> on Very Easy)
start practising your hold-ups.</p>
<p><b>Hold-up method:</b> approach from behind, jam the gun into their back (<code>Freeze!</code>), keep aiming and
run round to their front, then aim at the face.</p>
<p><b>Silence is Golden</b> comes free here: while you are behind a guard, aim at the <b>radio on his lower back</b>
and shoot it (non-lethal is fine) you can do it to every guard you hold up.</p>"""),
dict(id="r1-2", title="Deck-D, crew's quarters — Box 1 + the extinguisher", area="Tanker · Deck-D",
shots=["Down in Smoke","Moving Day"],
body="""<p>Three things here:</p>
<ul class="tight">
<li><b>Box 1 (Moving Day)</b> inside the food storage room, to the right of the stairs you come up.</li>
<li><b>Down in Smoke</b> stand across from the laser trap in the hallway; the patrolling guard stops next to a
<b>fire extinguisher</b>. Shoot the extinguisher when he is beside it.</li>
<li>Tags: <i>Miguel Luis Cunha</i> (moves after the Olga fight) and <i>Eiji Senke</i>, who only turns up while you are
inside the storeroom.</li>
</ul>"""),
dict(id="r1-3", title="Deck-A, crew's quarters — the locker room hat-trick", area="Tanker · Deck-A",
shots=["Hurt Locker","Kissing Booth","Bye Bye Big Brother"],
body="""<p><b>Do all three of these in one visit</b> — this is the most commonly botched spot in the game.</p>
<ol class="tight">
<li><b>Hurt Locker</b> tranquillise the hallway guard, drag him into the locker room, open a locker and drag him in.</li>
<li><b>Kissing Booth</b> find the locker with the <b>pin-up poster</b> inside the door, get in, and hold the
first-person button until you hear a kiss.</li>
<li><b>Snake Beater</b> get out, press first-person again and press <b>right up against the poster</b>, then open the
codec and call <b>Otacon</b>.</li>
</ol>
<p class="muted">There is also a wall camera nearby leave it alone if you care about Big Boss mech damage later, otherwise
shoot it for Bye Bye Big Brother.</p>"""),
dict(id="r1-4", title="Deck-A, crew's lounge — Stun Grenades", area="Tanker · Deck-A lounge",
body="""<p><b>Stun Grenades</b> sit at the bottom of the stairs that lead down to the Engine Room, starboard side — you
walk right past them during the story. Three tags here too.</p>"""),
dict(id="r1-5", title="Deck-B, crew's quarters", area="Tanker · Deck-B",
body="""<p>Two tags (<i>Yuki Hongoh</i> and one other on Very Easy). Nothing missable.</p>"""),
dict(id="r1-6", title="Deck-C, crew's quarters — Chaff Grenades + first camera", area="Tanker · Deck-C",
body="""<p><b>Chaff Grenades</b> are in the locker <b>left of the stairs after the first camera</b>. This is also your first
easy <b>Bye Bye Big Brother</b> camera remember cameras need a <b>lethal</b> shot.</p>"""),
dict(id="r1-7", title="Deck-2, port and starboard — the ambush", area="Tanker · Deck 2",
shots=["Caution: Hot"],
body="""<p>Three tags on Very Easy. Then the story triggers the <b>soldiers hallway ambush</b>.</p>
<div class="okbox">This ambush is a <b>forced alert</b> and does <b>not</b> void Complete Stealth.</div>
<p><b>Caution: Hot</b> is easiest right here: the ambush corridor is lined with pipes shoot the pipes next to a soldier
until he goes down.</p>"""),
dict(id="r1-8", title="Engine Room — Hand Grenades, one-time guards + Steel Grip", area="Tanker · Engine Room",
shots=["Steel Grip"],
body="""<p>Grab the <b>Hand Grenades</b> in the bottom-left corner of the bottom level, near the exit at the foot of the stairs.</p>
<div class="warnbox">Two guards here are <b>one-shot spawns</b>:
<i>Jeff A Saylor Jr</i> only appears the first time you enter the Engine Room, and <i>Kazuki Tokunaga</i> only appears in a
cutscene when you approach the IR sensors. <b>Both vanish if you leave the room.</b> Get their tags before you exit.</div>
<h4 style="margin-top:14px"> Do <b>Steel Grip</b> here this is the guide-recommended spot</h4>
<p>The Engine Room is called out as the best place for <b>Steel Grip</b> because it has <b>two railings stacked one above the
other</b>, which is exactly what the fast method needs. You need <b>two grip levels</b> to reach the maximum (level 3), and
each level is <b>100 pull-ups</b> <i>or</i> <b>10 drop-and-catches</b> so take the shortcut.</p>
<ol class="tight">
<li>Flip over the railing so you are hanging, with the lower railing visible directly below you.</li>
<li>Press the <b>drop</b> button, then immediately mash the <b>grab/hang</b> button to catch the lower railing.</li>
<li>Climb up and repeat. One clean catch = <b>10 pull-ups</b>, so <b>20 catches</b> finishes it.</li>
</ol>
<div class="warnbox"><b>Do the two one-shot guard tags first.</b> The count resets if you <b>die</b> without leaving the room,
and the usual advice is to step out and back in every few drops to bank your progress which is exactly what makes those
two guards despawn. Tags first, then hang.</div>
<div class="okbox"><b>Why here and not later:</b> the Tanker <b>Holds</b> come next, and the hidden marine tags in
Hold No. 1 and No. 3 need long <b>shimmies along ledges</b> that drain your grip and health. Getting grip level 3
<i>before</i> you reach the Holds makes that tag hunt far less lethal.</div>
<p class="muted">Plain pull-ups work too (hold both triggers, 200 of them) slower, but zero risk of falling.
Never grind this on a <b>Big Boss</b> run: a single missed catch is a death, and that voids the codename.</p>"""),
dict(id="r1-9", title="Navigational Deck, Wing — Olga + the Wet Box", area="Tanker · Deck-E bridge / Nav Deck",
body="""<p>Boss: <b>Olga Gurlukovich</b> → <b>Lights Out</b>. Shoot the spotlight and the tarp corners, and roll away from her
shots.</p>
<p>Immediately after the fight:</p>
<ul class="tight">
<li>Pick up and drop <b>Olga's body</b> for her dog tag.</li>
<li>Grab the <b>Wet Box</b> (Moving Day) on the Navigational Deck, Wing it is up by the <b>spotlight</b> near where the
guard emerges.</li>
<li><i>Brendan McLeod</i> spawns when you approach the starboard side.</li>
</ul>"""),
dict(id="r1-10", title="Holds 13 — marine tags, the ghost and the photo", area="Tanker · Holds",
shots=["Who Ya Gonna Call?","Sexting"],
body="""<p>The densest collectible section in the game, and a <b>one-way trip</b>. Save before you enter Hold No. 1.</p>
<ul class="tight">
<li><b>Who Ya Gonna Call?</b> in <b>Hold No. 2</b>, photograph the <b>right-hand projector screen</b> with Otacon's camera.
If the ghost is not up, interact with the projector to switch screens.</li>
<li><b>Sexting</b> photograph the <b>marine with no pants</b>, then send it from the <b>computer in the bottom-right of
Hold No. 3</b>. Do this <b>before</b> you photograph RAY.</li>
<li><b>Hidden marine tags:</b> after going down the first ladder, <b>shimmy</b> along the ledges there are guards tucked away
in Hold No. 1 and Hold No. 3. For the boxers marine in the middle of the crowd, tranquillise and drag the marines beside him.</li>
<li>Max out rations first shimmying drains health.</li>
</ul>
<p>Then photograph RAY and escape. <b>Lady Fortune</b> pops during the Fortune sequence on the way out.</p>"""),
dict(id="r1-11", title="Finish the Tanker → make a COMPLETED save", area="Tanker · Results screen",
body="""<p>Let the credits roll and save. Check <b>Special → Dog Tag Viewer</b> to confirm you have all <b>24</b> Very Easy tags
before moving on.</p>
<div class="infobox">Yorkie (50 tags) and Poodle (76 tags) will not pop until you finish a completed Tanker-Plant file that
contains those totals keep going into the Plant.</div>"""),
]),
dict(phase="Run 1 · Plant (Very Easy)", intro="""
<p>Same structure: work through the struts in order. The Plant is longer but its tags are more straightforward the
interesting ones are the <b>conditional spawns</b> (guards that only appear after Fatman, or after the Emma escort).</p>""",
steps=[
dict(id="r2-1", title="Strut A, Deep Sea Dock — sea lice + a boss", area="Plant · Strut A",
shots=["My Rations..."],
body="""<p>Do <b>My Rations…</b> right away: grab a ration, then <b>lie down near the bugs</b> and wait for a louse to crawl onto it.</p>
<p>Two tags here (<i>Brad I Lanning</i>, <i>Charles P Pinkerton</i>), and later the <b>Fortune</b> fight happens in this same
area <b>Lady Fortune</b>.</p>"""),
dict(id="r2-2", title="Strut A Roof + Pump Room", area="Plant · Strut A",
body="""<p>Tags on the roof (<i>Jason M Gillispie</i>) and two in the Pump Room. The <b>Box 1</b> cardboard box is in the Strut A
pipe room crawl under the pipes on your first right after the small stairs in the bottom-left, once you have the Lv. 1 Card.</p>"""),
dict(id="r2-3", title="A-B bridge → Strut B, Transformer Room", area="Plant · Strut B",
body="""<p>Two tags on the bridge, two in the transformer room. Grab the <b>Lv. 1 Card</b> along the way — it gates Box 1 and Box 2.</p>"""),
dict(id="r2-4", title="B-C bridge → Strut C, Dining Hall", area="Plant · Strut C",
body="""<p>One tag on the bridge, two in the dining hall. Simple area.</p>"""),
dict(id="r2-5", title="C-D bridge → Strut D, Sediment Pool", area="Plant · Strut D",
body="""<p>Two tags on the bridge and two to three in the sediment pool depending on difficulty.</p>
<p><b>Backup Steel Grip spot:</b> if you skipped the pull-ups in the Tanker Engine Room, Strut D's railings are the other
commonly recommended place you can drop onto the level below and the stairs to climb back up are right there, so the
loop is quick.</p>
<div class="warnbox">A soldier patrols Strut D and <b>regularly radios in</b>. If he goes down, a search party comes
looking so clear him quietly and tranquillise him again if he wakes up while you are grinding.</div>"""),
dict(id="r2-6", title="D-E bridge → Strut E, Parcel Room", area="Plant · Strut E",
body="""<p>Two tags on the bridge, two in the parcel room, and a <b>wall camera</b>.</p>"""),
dict(id="r2-7", title="Strut E Heliport — Stillman, then Fatman", area="Plant · Strut E Heliport",
body="""<p><b>Bomb Squad</b> pops during Stillman's C4 tutorial.</p>
<p>Then the bomb-defusal section around the Big Shell, then boss: <b>Fatman</b> <b>Party's Over</b>.</p>
<div class="warnbox">After the Fatman fight, <b>lift and drop Fatman's body</b> for the <i>Peter Stillman</i> dog tag — this is the
<b>last tag on every Plant difficulty list</b> and it is the one people miss.</div>
<div class="okbox">Beating Fatman <b>reopens weapon rooms in Strut F</b> (AKS-74u on the bottom floor, M4 in the top-floor
middle-left room). Go back for them.</div>"""),
dict(id="r2-8", title="Strut F warehouse — the Book, Box 2 and the weapon sweep", area="Plant · Strut F",
shots=["To Catch a Predator"],
body="""<p>Strut F is the game's collectible hub. Do a full sweep <b>now</b> and again after you meet Ames.</p>
<ul class="tight">
<li><b>To Catch a Predator</b> the <b>Book</b> is on the bottom floor on top of some crates. From the top floor, flip over
the railing, shimmy right until you are above the crates, drop and pick it up. Then drop it in a guard's path.</li>
<li><b>Box 2</b> bottom floor, bottom-left room with the Radar Node (needs Lv. 1 Card).</li>
<li><b>M9</b> top floor, room on the right after entering from the FA top-floor bridge.</li>
<li>Bottom floor after Fatman: <b>AKS-74u</b>. Top-floor middle-left: <b>M4</b>. Top-floor top-right locker: <b>C-4</b>.
Bottom floor: <b>Stun Grenades</b>.</li>
</ul>"""),
dict(id="r2-9", title="Strut E Heliport roof + Shell 1 Core 1F", area="Plant · Strut E / Shell 1",
body="""<p><b>Box 3</b> is in the bottom-left corner of the Strut E rooftop helipad. <b>Box 5</b> is on the conveyor belt in Strut E itself.</p>
<p>In <b>Shell 1 Core 1F</b>: several tags, the <b>south lockers</b> (Book / C-4 / Claymores / Stun Grenades), and cameras to shoot.</p>"""),
dict(id="r2-10", title="Shell 1 Core B2 — Box 4 + the Directional Mic", area="Plant · Shell 1 B2 Computer Room",
body="""<p><b>Box 4</b> sits across from the Radar Node on B2, near the <b>Directional Mic</b> and the parrot. The Directional Mic is
story-required here you will need it twice for <b>Johnny on the Spot</b>.</p>
<p>Four tags in the computer room.</p>"""),
dict(id="r2-11", title="Ames + Johnny (mic location 1)", area="Plant · Shell 1 Core hostage room",
shots=["Johnny on the Spot"],
body="""<p><b>Johnny on the Spot #1.</b> During the Ames scene you are told to mic Ocelot and Solidus. Aim the Directional Mic
<b>slightly left</b> of that conversation until you hear <b>Johnny</b> in the bathroom, and keep it on him until he finishes.</p>
<div class="warnbox">Do <b>not</b> quit to the menu after this do the second listen in the <b>same session</b>, or the achievement
may not register.</div>
<p>After the Ames scene, alert mode is forced it will not void Complete Stealth.</p>"""),
dict(id="r2-12", title="Shell 1 Core elevator — wear the disguise, carry the AK", area="Plant · Shell 1 Core",
body="""<p>The story requires you to use the <b>disguise + AK-47</b> here. Even with Stealth Camo equipped, the camera will
spot you if you try the elevator any other way.</p>
<p class="muted">This is the single exception to "stealth makes Complete Stealth free".</p>"""),
dict(id="r2-13", title="President Johnson → Vamp", area="Plant · Shell 1 Core",
body="""<p><b>Bohemian Candidate</b> pops when you meet the President. Then boss: <b>Vamp</b> → <b>Vampire Slayer</b>.</p>
<p>Vamp strategy: M9 to the head; when he dives in the water, shoot the water with the Stinger to drain his O₂. Then hang off
the platform edge to bait his attack and punch him twice when he comes close.</p>"""),
dict(id="r2-14", title="Shell 2 Core — Emma + the Nikita", area="Plant · Shell 2 Core B1",
body="""<p><b>I Think You Need a Hug, E</b> pops when you find Emma. Swim underwater for the story-required <b>Nikita</b>.</p>
<p>Emma's locker in the B1 Filtration Chamber 2 holds a <b>Book</b> and <b>C-4</b> — both count toward the weapon/box sweeps.</p>"""),
dict(id="r2-15", title="Emma escort + oil fence — Johnny (mic location 2) + the camera", area="Plant · oil fence",
shots=["Photo Finish","Johnny on the Spot"],
body="""<p><b>Johnny on the Spot #2.</b> While covering Emma, when she ducks behind the <b>second platform</b>, aim the Directional
Mic at that platform and listen to her run into Johnny. Keep the mic on them until he leaves. The achievement pops here if you
also did location 1.</p>
<p><b>Photo Finish</b> after the escort, when you climb the ladder into Strut E, look for the <b>Level 5 door</b> at the top of the
small area (before the conveyor section) for the Digital Camera.</p>"""),
dict(id="r2-16", title="Arsenal Gear — Snake's tag, Tengu, RAY", area="Arsenal Gear",
body="""<p>In the <b>Ascending Colon</b>, knock out the man you meet, pick him up and drop him for the first tag on every Plant
difficulty list (<i>Iroquois Pliskin / Solid Snake / Liquid Snake / Hideo Kojima</i>).</p>
<p>Then the <b>Tengu</b> fight (forced alert, safe) and boss: <b>Metal Gear RAY</b> <b>No Ray, José</b>. About 20 RAYs keep moving
and cartwheel through the missile barrages.</p>
<p>Then the <b>torture</b> room. Beating it gives you the <b>HF Blade</b> from Snake.</p>"""),
dict(id="r2-17", title="Solidus — and DO NOT SKIP THE CUTSCENE", area="Plant · rooftop",
shots=["Vamp Eyer"],
body="""<p>Boss: <b>Solidus Snake</b> → <b>Another Snake Bites the Dust</b>.</p>
<div class="warnbox"><b>Vamp Eyer:</b> let the ending cinematic play. When Snake asks <i>"By the way, what is that?"</i> and Raiden
answers <i>"No, never heard the name before"</i>, hold the zoom button and look around Vamp is standing in the street. Zoom in on him.</div>"""),
dict(id="r2-18", title="Save a completed Tanker-Plant file", area="Results screen",
body="""<p>Save after the credits. This single file is what proves your Tanker and Plant tag totals.</p>
<p>Check the totals: Tanker 24, Plant 43. Then open the <b>Dog Tags</b> tab and confirm the thresholds panel
<b>Bandana 50</b> and <b>Brown Wig 80</b> are already satisfied once you add the Easy-run tags; <b>Yorkie</b> will pop after
Run 2 and <b>Beagle</b> during Run 2 as well.</p>"""),
]),
dict(phase="Runs 2 & 3 — the dog-tag sweeps", intro="""
<p>The same route as Run 1, on <b>Easy</b> then <b>Normal</b>, picking up the tags you do not have. Nothing new is missable
you are only here for numbers.</p>""",
steps=[
dict(id="r3-1", title="Run 2 (Easy): sweep Tanker 26 + Plant 44", area="Easy difficulty",
body="""<p>When you save a completed file after this run you should cross <b>50 Tanker</b> (→ <b>Yorkie</b> / Bandana) and
<b>80 Plant</b> ( <b>Beagle</b> / Brown Wig).</p>
<p class="muted">The achievements pop when the chapter is completed with the totals present, not when the last tag is collected.</p>"""),
dict(id="r3-2", title="Run 3 (Normal): sweep Tanker 33 + Plant 49", area="Normal difficulty",
body="""<p>This run crosses <b>76 Tanker</b> (→ <b>Poodle</b> / Tanker stealth) and <b>120 Plant</b> (→ <b>Shiba Inu</b> / Plant stealth).</p>
<div class="okbox">After this run you have everything you need for the two challenge runs: <b>Stealth Camo</b> and the
<b>Bandana / Brown Wig</b> (infinite ammo). Start Run 4 from a file that loads this cleared data.</div>"""),
dict(id="r3-3", title="Optional: grab the last two wigs", area="Plant, all difficulties",
body="""<p>The <b>Orange Wig</b> (160 Plant tags) and <b>Blue Wig</b> (200 Plant tags) are <b>not</b> required for any achievement.
Only chase them if you want the Perfect/100% feel Hard (52) + Extreme (54) = 106 more tags.</p>"""),
]),
dict(phase="Run 4 — Pacifist Run + Complete Stealth together", intro="""
<p>Both of these are "whole playthrough" challenges, so do them at the same time. With the items from Run 3 this is the
easiest full playthrough you will ever do.</p>""",
steps=[
dict(id="r4-1", title="Start Very Easy with Stealth Camo + Bandana loaded", area="New game from cleared data",
body="""<p>Load the cleared save so the special items are in your inventory, then equip <b>Stealth Camo</b> permanently.</p>
<p>Equip the <b>Bandana</b> (or Brown Wig) for infinite non-lethal ammo.</p>"""),
dict(id="r4-2", title="Kill nothing, anywhere", area="Whole run",
body="""<p><b>Pacifist Run</b> requires zero kills — this includes:</p>
<ul class="tight">
<li>No neck breaks, no lethal weapons, no explosive barrels killing anyone.</li>
<li>No steam-pipe kills, no falling deaths you caused.</li>
<li>Bosses with a <b>stamina bar</b> (Olga, Fatman, Harrier, Vamp, Solidus) must be drained on stamina, not health.</li>
<li>For <b>Solidus</b>, flip the HF Blade to the <b>blue non-lethal side</b>.</li>
</ul>"""),
dict(id="r4-3", title="Do the Shell 1 elevator properly", area="Shell 1 Core",
body="""<p>Switch off stealth for this one moment and use the <b>disguise + AK-47</b> as the story demands.
Trying it in stealth gets you spotted and can void <b>Complete Stealth</b>.</p>"""),
dict(id="r4-4", title="Save-and-reload discipline for alerts", area="Whole run",
body="""<p>Save at the start of every new area. If the HUD ever turns red <b>ALERT</b>, reload immediately — the game only
checks the flag on the final results screen.</p>
<p class="muted">Forced alerts that are safe: boss fights, the Tanker hallway ambush, the post-Ames alert, the Tengu fight.</p>"""),
]),
dict(phase="Run 5 — Big Boss", intro="""
<p>The final boss of the achievement list. Everything you have learned so far gets used at once.
Full criteria, strategies and time checkpoints are in the <b>Big Boss Run</b> tab.</p>""",
steps=[
dict(id="r5-1", title="Practise the boss fights before you commit", area="Any difficulty",
body="""<p>Do a throwaway Extreme run just to learn Olga, Fatman, Harrier, Vamp and Solidus. The timer is unforgiving and
you cannot afford to learn a fight mid-run.</p>"""),
dict(id="r5-2", title="Start Extreme, Tanker→Plant, NO special items, NO radar", area="New game",
body="""<p>Do <b>not</b> load the cleared save — special items and the radar are banned and will void the codename.</p>"""),
dict(id="r5-3", title="Skip every cutscene and codec, ignore optional calls", area="Whole run",
body="""<p>Cutscenes and codec conversations all count toward your 3-hour limit. Mash the skip button the instant each one starts.</p>"""),
dict(id="r5-4", title="Hold the time checkpoints in the Big Boss tab", area="Whole run",
body="""<p>Fortune 00:45 · Fatman 00:49 · Harrier 01:10 · Vamp 01:25 · oil fence 01:40 · Tengu 01:56 · RAY 02:08 · Solidus 02:22.</p>
<p>If you are more than a couple of minutes behind at any of these, restart it is cheaper than finishing at 3:05.</p>"""),
]),
dict(phase="Off-story cleanup", intro="""
<p>Everything else is on the main menu and takes under an hour total.</p>""",
steps=[
dict(id="r6-1", title="Snake Tales — complete any one", area="Main Menu",
body="""<p><b>Tell Me a Tale.</b> A Wrongdoing is the shortest of the five.</p>"""),
dict(id="r6-2", title="Boss Survival — Raiden on Easy", area="Main Menu",
body="""<p><b>No Boss of Mine.</b> Raiden gets the HF Blade for Solidus; Snake does not.</p>"""),
dict(id="r6-3", title="VR missions — one clear, then 50 first places", area="Main Menu",
body="""<p><b>Piece of Cake</b> (any single mission) then <b>In It to Win It</b> (place 1st in 50). Pick the shortest
Sneaking missions and learn the target time.</p>"""),
dict(id="r6-4", title="Casting Theater — Demo 8 body swap", area="Main Menu → Special",
body="""<p><b>Casting Theater</b> + <b>Love Hurts</b>: Demo 8, Raiden→Rose, Solidus→Raiden, watch it play out.</p>"""),
dict(id="r6-5", title="Sweep the cumulative counters on any leftover run", area="Any playthrough",
body="""<p>Hold Up-aholic (30), Don't Taze Me Bro (100), Nothing Personal (30), Rent Money (30) and
Bye Bye Big Brother (5 cameras) all carry across playthroughs check the Achievements tab to see what is still outstanding and
farm it on a spare save.</p>
<p class="muted">Steel Grip is <b>not</b> on this list do that one on-site in the <b>Tanker Engine Room</b> (or Strut D)
where the stacked railings are, as covered in the Tanker walkthrough above.</p>"""),
]),
]
BIGBOSS = dict(
intro="""Three hours, no rations, no kills, no radar, no special items, on Extreme, with a mech-damage cap —
and you must destroy about 20 Metal Gear RAYs inside that cap. This is the one achievement that decides whether you get 100%.
Learn the route first, then execute it.""",
reqs=[
"Chapter: <b>Tanker-Plant</b> (a full run, both chapters)",
"Difficulty: <b>Extreme</b>",
"Time: <b>3:00:00 or less</b>",
"Continues: <b>0</b>",
"Rations used: <b>0</b>",
"Kills: <b>0</b>",
"Alert mode: <b>3 times or fewer</b>",
"Shots fired: <b>700 or less</b>",
"Mech damage: <b>under 60</b> — cameras, Cyphers and MG RAYs all count; you must destroy ~20 RAYs, so keep everything else under ~40",
"Damage received: <b>10 health bars or less</b>",
"<b>No special items</b> (no Bandana, no Stealth, no wigs)",
"<b>No radar</b>",
],
heals=[
"After the Olga boss fight",
"After the Fortune fight",
"After the Fatman boss fight",
"After the Vamp boss fight",
"After the first torture",
"After the Metal Gear RAYs boss fight",
],
times=[
["Fortune fight", "00:45:00"],
["Fatman fight", "00:49:00"],
["Harrier fight", "01:10:00"],
["Vamp fight", "01:25:00"],
["Cover Emma on the oil fence", "01:40:00"],
["Tengu soldiers", "01:56:00"],
["Metal Gear RAY fight", "02:08:00"],
["Solidus fight", "02:22:00"],
["Finish", "under 03:00:00"],
],
saves=[
"Before the Fortune fight",
"Before the Fatman fight",
"Before destroying the Semtex on the bridge ahead of the Harrier fight",
"Before the Vamp fight",
"Before covering Emma as she crosses the oil fence",
"Before the Tengu fight",
"Before the Metal Gear RAY fight",
"Before the Solidus fight",
],
tips=[
"<b>Cutscenes count toward the timer.</b> Skip every cutscene and codec immediately, including codec conversations.",
"<b>Do not answer optional codec calls.</b>",
"Save <b>immediately after entering a new area</b> — reloading restarts you at the start of the area you saved in.",
"If an elevator does not open right away, <b>press the button a second time</b>.",
"Use <b>Snake's roll</b> and <b>Raiden's cartwheel</b> constantly to move faster.",
"Do not hunt for ammo or items you do not need. You cannot kill or use rations, so almost everything is skippable.",
"Getting caught voids the codename anyway, so you will rarely need health outside boss fights.",
],
bosses=[
dict(name="Olga", body="""
<p>Shoot the <b>spotlight</b> and the <b>bottom corners of the tarp</b> immediately. She shoots at your last known position,
so roll to a blind side of her after each shot.</p>
<p>Taking damage here is fine your health refills after the fight.</p>"""),
dict(name="Fortune", body="""
<p>Pure timing. Equip a <b>cardboard box</b> and walk back and forth along the very bottom of the arena.</p>
<p>As soon as her <b>second shot</b> resolves, turn around and go the other way. If you were heading left, go right. Repeat
until the fight ends.</p>
<p>Watch for debris and exploding barrels. Her shots come fast expect a few attempts to get the rhythm.</p>"""),
dict(name="Fatman", body="""
<p><b>Stay close to Fatman</b> so you can freeze each bomb as it is planted rather than waiting for all of them.</p>
<ul class="tight">
<li>When he is planting, <b>melee</b> him to knock him down, then freeze the bomb while he is on the floor.</li>
<li>Melee him as he skates past, then M9 to the head while he gets up.</li>
<li>From range, shoot him with the <b>SOCOM</b> to knock him down (little health damage), then <b>M9 to the head</b>.</li>
<li>If you are fast, M9 him in the head the instant he falls and again on the way down.</li>
</ul>"""),
dict(name="Harrier", body="""
<ul class="tight">
<li>Pick up the <b>Stinger</b> immediately and fire as many shots as you can at the start.</li>
<li>While it circles the perimeter you can land a shot or two.</li>
<li>When it flies straight out, follow the contrails, <b>wait for the flash</b>, fire, then take cover fast.</li>
<li>When it hovers to burn you with thrusters, spam the Stinger at the <b>middle of the jet</b> no lock-on needed.</li>
<li>Bombs from above: drop to the bottom level.</li>
<li>Rockets: go far left up the stairs, then cartwheel right as it fires.</li>
<li>Close-range gun runs: get to the bottom floor behind the big grey box and move around it as the Harrier repositions.</li>
</ul>"""),
dict(name="Vamp", body="""
<p>This one can be cheesed.</p>
<ol class="tight">
<li>Open with an <b>M9 headshot</b>. When he dives into the water, shoot the <b>water</b> with the Stinger to drain his O₂.</li>
<li>Step slowly off the platform so Raiden <b>hangs from the edge</b> do not fall in. Vamp walks over.</li>
<li>Just before he crouches to attack, <b>pull yourself up</b> so the attack whiffs as you climb.</li>
<li>Hit him with two melee punches. When he crouches, run left or right but stay close enough to punish the slash, then
close in for two more punches. Repeat.</li>
<li>If he returns to the water, Stinger the water and restart the loop.</li>
</ol>"""),
dict(name="Tengu soldiers", body="""
<p>You have the sword now, but <b>stick to non-lethal weapons</b> running around with the blade will cost you too much health.</p>
<p>Snake will take damage. You can stand in front of him and hold the <b>sword block</b> to deflect bullets, which protects him
while he kills the enemies. You must stand still while blocking.</p>"""),
dict(name="Metal Gear RAY", body="""
<p>You fight about <b>20 RAYs</b>. Be quick with your shots and listen for missile barrages from RAYs outside the arena.</p>
<p>Machine-gun fire and the single-missile attack are dodged by running left or right and <b>cartwheeling</b> as the rounds
get close.</p>
<div class="warnbox">Every RAY you destroy counts toward your <b>mech damage</b> limit. Budget for ~20 and keep everything else
(cameras, Cyphers) near zero.</div>"""),
dict(name="Solidus", body="""
<p><b>Phase 1:</b> his melee and tentacle attacks can be blocked with the sword, and missiles can be cartwheeled or cut in half.
Bait the melee, block it, land your hits, then step back and run in again.</p>
<p><b>Phase 2:</b> hit him then run away far enough that he stops sliding point-to-point and comes straight at you. Hold
<b>block</b> to eat his elbow attack, deal damage, then disengage and repeat.</p>"""),
],
)