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

493
build/achievements_src.py Normal file
View file

@ -0,0 +1,493 @@
# -*- coding: utf-8 -*-
"""Hand-written guide content for the 51 MGS2 Master Collection achievements.
Keyed by Steam apiname so official icons/names can be merged automatically."""
ACH = {
# ---------------------------------------------------------------- STORY (14)
"ach_002_001": dict(cat="story", guide="""
<p><b>Unmissable.</b> Defeat Olga Gurlukovich on the Navigational Deck, Wing at the end of the Tanker chapter.</p>
<ul class="tight">
<li>Shoot the <b>spotlight</b> and the <b>bottom corners of the tarp</b> as soon as the fight starts.</li>
<li>She fires at your <i>last known position</i> roll to a blind side after every shot.</li>
<li>Taking damage here is fine: your health is refilled after the fight.</li>
</ul>"""),
"ach_002_002": dict(cat="story", guide="""
<p><b>Unmissable.</b> Pops during the Tanker story when Revolver Ocelot makes his entrance. Nothing to do.</p>"""),
"ach_002_003": dict(cat="story", guide="""
<p><b>Unmissable.</b> Pops when Peter Stillman teaches you how to defuse C4 in the Strut E Heliport at the start of the Plant chapter.</p>
<div class="infobox">Pay attention here the coolant/sensor mechanics you learn are the same ones you need for <b>Party's Over</b> and the whole bomb-defusal section.</div>"""),
"ach_002_004": dict(cat="story", guide="""
<p><b>Unmissable.</b> You do not have to beat Fortune you only have to <b>survive</b> her attack sequence. It ends on its own.</p>
<ul class="tight">
<li>Her rail gun tracks a fixed pattern; stay behind cover and keep moving.</li>
<li>If you are doing the Big Boss run, see the Fortune strategy in the <b>Big Boss Run</b> tab (walk left/right in a cardboard box at the bottom of the arena).</li>
</ul>"""),
"ach_002_005": dict(cat="story", guide="""
<p><b>Unmissable.</b> Defeat Fatman on the Big Shell helipad.</p>
<ul class="tight">
<li>Equip the <b>Sensor A</b> coolant and prioritise <b>freezing the bombs he plants</b> do not wait for all of them to be planted.</li>
<li>Melee him as he skates past to knock him down, then shoot him in the head with the <b>M9</b> while he is getting up.</li>
<li>From range, shoot him with the SOCOM to knock him down, then M9 to the head.</li>
</ul>"""),
"ach_002_006": dict(cat="story", guide="""
<p><b>Unmissable.</b> Pops after you interrogate Ames in the Shell 1 Core hostage room and learn where the President is.</p>"""),
"ach_002_007": dict(cat="story", guide="""
<p><b>Unmissable.</b> Destroy the AV-88 Harrier II.</p>
<ul class="tight">
<li>Pick up the <b>Stinger</b> the moment the fight starts and fire as fast as you can.</li>
<li>When it flies straight out, follow the contrails <b>wait for the flash</b>, then fire and take cover.</li>
<li>When it hovers above you, spam the Stinger at the middle of the jet; you do not need a lock-on.</li>
<li>Rockets: run to the far left up the stairs, then cartwheel right as it fires. Get behind the big grey container when it closes in.</li>
</ul>"""),
"ach_002_008": dict(cat="story", guide="""
<p><b>Unmissable.</b> Pops when you meet President James Johnson in the Shell 1 Core.</p>"""),
"ach_002_009": dict(cat="story", guide="""
<p><b>Unmissable.</b> Defeat Vamp.</p>
<ul class="tight">
<li>M9 to the head, then when he dives into the water shoot the <b>water</b> with the Stinger to drain his O₂.</li>
<li>Classic cheese: step off the platform so Raiden hangs from the edge, let Vamp walk over, then pull up as he attacks. Punch twice, back off, repeat.</li>
</ul>"""),
"ach_002_010": dict(cat="story", guide="""
<p><b>Unmissable.</b> Pops when you find Emma Emmerich in the Shell 2 Core filtration chamber.</p>"""),
"ach_002_011": dict(cat="story", guide="""
<p><b>Unmissable.</b> Pops during the Arsenal Gear sequence when Olga turns on Solidus and helps you.</p>"""),
"ach_002_012": dict(cat="story", guide="""
<p><b>Unmissable.</b> Defeat Metal Gear RAY.</p>
<ul class="tight">
<li>You fight roughly <b>20 RAYs</b>. Be quick with shots and listen for missile barrages from RAYs outside the arena.</li>
<li>Dodge machine-gun fire and single missiles by running left/right and cartwheeling as they get close.</li>
<li><b>Big Boss note:</b> each RAY destruction counts as mech damage see the Big Boss tab.</li>
</ul>"""),
"ach_002_013": dict(cat="story", guide="""
<p><b>Unmissable.</b> Defeat Solidus Snake on the rooftop. See the Big Boss tab for the block-and-punish strategy.</p>
<div class="warnbox"><b>Do NOT skip the cutscene that follows.</b> You need it for <b>Vamp Eyer</b>.</div>"""),
"ach_002_014": dict(cat="story", guide="""
<p><b>Unmissable.</b> Pops when you finish both chapters on any difficulty. See the <b>Roadmap</b> tab.</p>"""),
# ------------------------------------------------- MISC / MISSABLE (window)
"ach_002_015": dict(cat="misc", miss=True,
where="Tanker — Deck-A, crew's quarters (lockers)", window="Any time in the Tanker/Plant",
guide="""
<p>Put an enemy inside a locker. Easiest in the <b>Tanker, Deck-A Crew's Quarters</b>.</p>
<ol class="tight">
<li>Tranquillise or kill the guard patrolling the hallway.</li>
<li>Drag him (grab button) into the room with the lockers.</li>
<li>Open a locker, then drag him into it Snake automatically stuffs him in and shuts the door.</li>
</ol>
<p class="muted">Works as both Snake and Raiden, so this is one of the easiest to pick up in the first 5 minutes of the run.</p>"""),
"ach_002_016": dict(cat="misc", miss=True,
where="Plant — Strut F warehouse (Book), place in a guard's path", window="After Fatman for the safest Book route",
guide="""
<p>Lure a guard with the <b>Book</b> (the girlie magazine).</p>
<ol class="tight">
<li>Get the <b>Book</b> in <b>Strut F</b>: on the top floor, lean on the railing, flip over it, shimmy right until you are above the stack of crates, drop down and pick it up. (Also found in the Shell 1 Core 1F south lockers and in Emma's locker in Shell 2 Core B1.)</li>
<li>Equip the Book and drop it in a guard's patrol path.</li>
<li>When he stops to stare, the achievement pops.</li>
</ol>"""),
"ach_002_017": dict(cat="coll", miss=True,
where="Any chapter — hold up any guard or boss", window="First opportunist moment",
guide="""
<p>Collect a single dog tag. This is the first of the collectible chain and pops almost immediately.</p>
<p><b>How to hold up a guard:</b></p>
<ol class="tight">
<li>Approach from <b>behind</b>, equip the M9/SOCOM, hold the aim button while pressing the fire button so the gun is pressed into their back Snake shouts <i>"Freeze!"</i>.</li>
<li>Keep the gun raised and <b>run around to their front</b> while still aiming.</li>
<li>Aim at their <b>face</b>; they shake and drop the tag.</li>
<li>If they refuse, shoot their <b>hand or foot with a lethal weapon</b> to scare them, then tranquillise them.</li>
</ol>
<div class="infobox">The full 394-tag checklist with guard names, areas and conditional-spawn notes is in the <b>Dog Tags</b> tab.</div>"""),
"ach_002_018": dict(cat="misc", miss=True, cum=True,
where="Anywhere — cameras in story, Snake Tales and VR", window="Cumulative",
guide="""
<p>Destroy <b>5 wall-mounted cameras</b> (cumulative across story, Snake Tales and VR missions).</p>
<ul class="tight">
<li>You must use a <b>lethal</b> weapon tranquiliser shots do not break cameras.</li>
<li><b>Cyphers do NOT count</b> only the cameras mounted on walls.</li>
<li>The Tanker has several easy ones (Deck-C, Deck-D) and the Plant has them all over the Shell cores.</li>
</ul>
<div class="warnbox">If you are going for <b>Big Boss</b>, remember every camera you destroy counts toward your mech-damage limit. Do this achievement on a non-Big-Boss run.</div>"""),
"ach_002_019": dict(cat="misc", miss=True,
where="Tanker — Deck-D, crew's quarters (fire extinguisher)", window="Tanker, before the Holds",
guide="""
<p>Disorient a guard with a fire extinguisher cloud.</p>
<ol class="tight">
<li>Go to <b>Deck-D Crew's Quarters</b>, near the kitchen/food storeroom and the laser trap hallway.</li>
<li>Stand across from the laser trap and wait for the patrolling guard to stop next to the fire extinguisher.</li>
<li>Shoot the <b>extinguisher</b> (non-lethal works) so the cloud engulfs him.</li>
</ol>"""),
"ach_002_020": dict(cat="misc", miss=True, cum=True,
where="Anywhere — shoot the radio on a guard's back", window="Cumulative",
guide="""
<p>Shoot an enemy's radio.</p>
<ul class="tight">
<li>Stand behind a guard and aim at the <b>radio on their lower back</b>. You will see sparks when you hit it.</li>
<li>Non-lethal weapons work, so you can do this while farming dog tags.</li>
</ul>"""),
"ach_002_021": dict(cat="misc", miss=True,
where="Tanker — pipe-lined hallways", window="Tanker",
guide="""
<p>Down an enemy with steam from a burst pipe.</p>
<ol class="tight">
<li>Hold up (or drag) a guard next to a wall pipe, then shoot the pipe. Steam jets out.</li>
<li>Keep shooting the pipe until the guard dies you can tell it is working because he waves a hand in front of his face.</li>
<li>Alternatively, during the <b>Tanker ambush hallway</b> (narrow corridor lined with pipes) just shoot the pipes next to the soldiers.</li>
</ol>
<div class="warnbox"><b>Caution: Hot requires a kill.</b> If you are attempting Pacifist Run or Big Boss in the same session, do not trigger this on that file.</div>"""),
"ach_002_022": dict(cat="misc", miss=True,
where="Tanker — Deck-A, crew's quarters (poster locker)", window="Tanker",
guide="""
<p>Kiss the poster inside a locker.</p>
<ol class="tight">
<li>In <b>Deck-A Crew's Quarters</b>, open lockers until you find the one with a <b>pin-up poster</b> on the inside of the door.</li>
<li>Get inside the locker. The door closes behind you and the poster is right in your face.</li>
<li>Hold the aim/first-person button until you hear a <b>kissing noise</b>.</li>
</ol>
<p class="muted">Do this back-to-back with <b>Snake Beater</b>.</p>"""),
"ach_002_023": dict(cat="misc", miss=True,
where="Tanker — same locker as Kissing Booth", window="Tanker, right after Kissing Booth",
guide="""
<p>Get caught by Otacon while "stimulating yourself".</p>
<ol class="tight">
<li>After <b>Kissing Booth</b>, get out of the locker and press the first-person button to stare at the poster again you must be <b>right up against it</b>.</li>
<li>While still in first-person staring at the poster, open the <b>codec</b> and call <b>Otacon</b>.</li>
<li>The achievement pops on the call.</li>
</ol>"""),
"ach_002_024": dict(cat="misc", miss=True,
where="Tanker — Hold No. 2 (projector screens)", window="Tanker Holds — one-shot area",
guide="""
<p>Photograph the ghost image in Hold No. 2.</p>
<ol class="tight">
<li>Late in the Tanker you sneak through the marine holds. In <b>Hold No. 2</b> there are two projector screens the marines flip between.</li>
<li>Use the <b>camera Otacon gave you</b> (not the Digital Camera special item) and photograph the <b>right-hand screen</b>.</li>
<li>If the ghost image is not up, interact with the <b>projector</b> to switch to it.</li>
</ol>
<div class="warnbox">The Holds are a one-way trip grab this and <b>Sexting</b> before you leave.</div>"""),
"ach_002_025": dict(cat="misc", miss=True,
where="Tanker — Hold No. 3 (computer, bottom-right)", window="Tanker Holds — before photographing RAY",
guide="""
<p>Send Otacon a picture of the pantsless marine.</p>
<ol class="tight">
<li>In the holds, find the marine in the crowd with <b>no trousers</b> and photograph him with <b>Otacon's camera</b> — the Digital Camera special item does <b>not</b> work.</li>
<li>Continue to <b>Hold No. 3</b> (where RAY is) and use the <b>computer in the bottom-right corner</b> to send the photo.</li>
</ol>
<div class="warnbox">Send it <b>before</b> you take the RAY photographs, or you will have to replay the Tanker.</div>"""),
"ach_002_026": dict(cat="misc", miss=True,
where="Plant — Strut A (lie near the sea lice)", window="Start of the Plant chapter",
guide="""
<p>Get sea lice all over your rations.</p>
<ol class="tight">
<li>At the very start of the Plant, pick up a <b>ration</b>.</li>
<li>Lie down on the ground near the little bugs (Strut A area) and wait a louse crawls onto your rations in your inventory.</li>
</ol>
<p class="muted">To get rid of it afterwards, hold your inventory open and cycle the ration up and down quickly.</p>"""),
"ach_002_027": dict(cat="misc", miss=True,
where="Plant — Shell 1 Core (Ames) and the oil fence", window="Two separate story moments",
guide="""
<p>Hear Johnny's bowel noises in <b>two</b> locations, both in the Plant chapter, using the <b>Directional Mic</b>.</p>
<ol class="tight">
<li><b>Location 1 Ames' hostage room.</b> During the scene Ames tells you to mic Ocelot and Solidus. Aim the Directional Mic <b>slightly left</b> of that conversation until you pick up Johnny talking to himself in the bathroom. Keep it on him until he finishes.</li>
<li><b>Location 2 the oil fence.</b> While covering Emma, when she ducks behind the <b>second platform</b>, aim the mic at that platform. You will hear Emma bump into Johnny. Keep the mic on them until he leaves.</li>
</ol>
<div class="warnbox">Community reports say the two listens must happen <b>in the same game session</b> do not quit to the menu between them. Some players needed to load a save made just before the sniper section and re-listen.</div>"""),
"ach_002_028": dict(cat="misc", miss=True,
where="End of the game — rooftop epilogue cutscene", window="Final cutscene — DO NOT SKIP",
guide="""
<p>Catch a glimpse of Vamp standing in the streets of New York during the end cinematic.</p>
<ol class="tight">
<li><b>Do not skip the final cutscene.</b> This is the single most commonly missed achievement in the game.</li>
<li>When Snake asks Raiden <i>"By the way, what is that?"</i> and Raiden answers <i>"No, never heard the name before"</i>, immediately hold the <b>zoom button</b> (R2/L2 on PS, RT on Xbox) and look around with the stick.</li>
<li>Vamp is standing in the background. Zoom in on him and the achievement pops.</li>
</ol>"""),
"ach_002_029": dict(cat="misc",
where="Main Menu → Special → Casting Theater (after beating the game)", window="After completing the game",
guide="""
<p>Watch Rose kill Raiden on a rooftop using the Casting Theater.</p>
<ol class="tight">
<li>Beat the game once to unlock Casting Theater.</li>
<li>Go to <b>Main Menu Special Casting Theater</b>.</li>
<li>Select <b>Demo 8</b>.</li>
<li>Replace <b>Raiden with Rose</b> and <b>Solidus with Raiden</b>.</li>
<li>Watch the scene this pops <b>Love Hurts</b> and <b>Casting Theater</b> together.</li>
</ol>"""),
# --------------------------------------------------------- CUMULATIVE
"ach_002_030": dict(cat="misc", cum=True,
where="Anywhere — hold up enemies", window="Cumulative, carries across runs",
guide="""
<p>Hold up <b>30 enemies</b> (cumulative).</p>
<p>This comes for free while hunting dog tags you will hold up well over 30 guards across the Tanker and Plant tag runs.
The counter persists across playthroughs, so it is effectively impossible to miss.</p>"""),
"ach_002_031": dict(cat="misc", cum=True,
where="Anywhere — M9 / PSG1-T", window="Cumulative, carries across runs",
guide="""
<p>Tranquilise <b>100 enemies</b> (cumulative).</p>
<ul class="tight">
<li>Use the <b>M9</b> or <b>PSG1-T</b>. A tranquilised enemy shows <b>"Z"s</b> floating above them.</li>
<li>You should finish this naturally during the dog-tag runs always tranquillise after taking a tag.</li>
<li>Bodies wake up eventually; tranq the same guard again after he gets up if you need volume.</li>
</ul>"""),
"ach_002_032": dict(cat="misc", cum=True,
where="Anywhere — grab from behind, tap the grab button", window="Cumulative, carries across runs",
guide="""
<p>Break the neck of <b>30 enemies</b> (cumulative).</p>
<ol class="tight">
<li>Get behind an enemy and grab them.</li>
<li>Keep tapping the grab button until the neck snaps.</li>
</ol>
<div class="warnbox">Neck breaks are <b>kills</b> they void <b>Pacifist Run</b> and <b>Big Boss</b>. Farm this on a normal tag run.</div>"""),
"ach_002_033": dict(cat="misc", cum=True,
where="Anywhere — melee combos / groin punch / HF Blade stun side", window="Cumulative, carries across runs",
guide="""
<p>Knock <b>30 enemies unconscious</b> (cumulative). An unconscious enemy has <b>stars</b> above their head.</p>
<ul class="tight">
<li>Land repeated melee hits until they pass out.</li>
<li>Fastest method: hold a guard up, aim at his <b>groin</b> and punch a clean hit knocks him out in one blow.</li>
<li>Late in the game you get the <b>HF Blade</b>. Open the inventory on it and press the swap button to flip it to the <b>non-lethal side</b> (the icon turns <b>blue</b>) that side knocks enemies out instead of killing.</li>
</ul>"""),
"ach_002_034": dict(cat="misc", cum=True,
where="Tanker — Engine Room · Plant — Strut D or FA Connecting Bridge", window="Cumulative, carries across runs",
guide="""
<p>Attain <b>grip level 3</b> (the maximum). You need <b>two</b> grip levels, and each level is
<b>100 pull-ups</b> <i>or</i> <b>10 drop-and-catches</b> so the full job is <b>200 pull-ups</b> or <b>20 catches</b>.</p>
<h3>Where to do it</h3>
<ul class="tight">
<li><b>Tanker Engine Room</b> (the guide-recommended spot): two railings sit stacked directly one above the other.
Hang on the upper one, drop, and immediately mash the grab button to catch the lower one.</li>
<li><b>Plant Strut D, Sediment Pool:</b> hang off the railing, drop to the level below, and the stairs back up are right
beside you, so the loop is quick.</li>
<li><b>Plant FA Connecting Bridge:</b> also has a railing directly below the one you hang from.</li>
</ul>
<h3>The two methods</h3>
<ul class="tight">
<li><b>Drop and catch (fast):</b> flip over the railing, press <b>drop</b>, then mash the <b>grab/hang</b> button to catch the
railing below. One catch = <b>10 pull-ups</b>, so <b>20 catches</b> finishes it. If you miss, you fall and die.</li>
<li><b>Pull-ups (safe):</b> hang from any railing and hold <b>both shoulder buttons</b> to do a pull-up; repeat 200 times,
climbing back up when your grip meter runs low. Slower, but you cannot fall.</li>
</ul>
<div class="warnbox"><b>Progress resets if you die</b> without leaving the room, so step out and back in every few drops to bank
it. In the <b>Tanker Engine Room</b> specifically, take the two one-shot guard tags (<i>Jeff A Saylor Jr</i>,
<i>Kazuki Tokunaga</i>) <b>first</b> they despawn the moment you leave the room.</div>
<div class="okbox">Do this in the Tanker so it is finished <b>before the Holds</b> the hidden marine tags in Hold No. 1 and
No. 3 need long ledge shimmies that drain grip and health, and grip level 3 makes that far safer.</div>
<div class="warnbox"><b>Never</b> grind this on a Big Boss run: one missed catch is a death, and that voids the codename.</div>"""),
# --------------------------------------------------------- COLLECTIBLE
"ach_002_035": dict(cat="coll", miss=True,
where="Plant — Strut E conveyor (Box 5) or end of game", window="Plant chapter",
guide="""
<p>Acquire the digital camera. Three routes:</p>
<ul class="tight">
<li><b>Beat the game</b> you are given it automatically. Simplest.</li>
<li><b>Box 5 conveyor ride:</b> get Cardboard Box 5 in Strut E, equip it and stand on the conveyor belt. The belt stops, then carries you down into a room containing the camera.</li>
<li><b>After escorting Emma:</b> head for Snake, climb the ladder into Strut E, and immediately look for the <b>Level 5 door</b> at the top of the small area before the conveyor section. The camera is inside.</li>
</ul>"""),
"ach_002_036": dict(cat="coll", miss=True,
where="Tanker — 6 weapon types", window="Tanker chapter",
guide="""
<p>Collect all <b>6</b> weapon types on the Tanker:</p>
<table>
<tr><th>Weapon</th><th>How / where</th></tr>
<tr><td class="n">M9</td><td>Default starting weapon.</td></tr>
<tr><td class="n">USP</td><td>Automatic given to you after beating Olga.</td></tr>
<tr><td class="n">Chaff Grenades</td><td>Deck-C, crew's quarters — in the locker left of the stairs after the first camera.</td></tr>
<tr><td class="n">Stun Grenades</td><td>Deck-A crew's lounge — at the bottom of the stairs leading to the Engine Room, starboard. You pass them during the story.</td></tr>
<tr><td class="n">Hand Grenades</td><td>Engine Room bottom level, bottom-left corner near the exit at the foot of the stairs.</td></tr>
<tr><td class="n">Magazine</td><td>Automatic you get it the first time you reload a weapon.</td></tr>
</table>
<div class="warnbox">Must be done in a single Tanker playthrough; the game only checks the weapon types you have held at once.</div>"""),
"ach_002_037": dict(cat="coll", miss=True,
where="Plant — every weapon type (~18 items)", window="Plant chapter",
guide="""
<p>Collect every weapon <b>type</b> in the Plant. You only need one of each grenade type. Listed in the order they become available:</p>
<table>
<tr><th>Weapon</th><th>Where</th></tr>
<tr><td class="n">Chaff Grenades</td><td>Strut A Roof · FA connecting bridge · Strut F · Shell 1 Core 1F · Strut L Perimeter · KL connecting bridge</td></tr>
<tr><td class="n">M9</td><td>Strut F top floor, room on the right after entering from the FA top-floor bridge (also near the start on Very Easy).</td></tr>
<tr><td class="n">Magazine</td><td>Automatic when you reload a weapon.</td></tr>
<tr><td class="n">Coolant</td><td>Given by Stillman during the story.</td></tr>
<tr><td class="n">Book</td><td>Strut F hang over the top-floor railing and drop onto the crates. Also Shell 1 Core 1F south lockers, and Emma's locker in Shell 2 Core B1 Filtration Chamber 2.</td></tr>
<tr><td class="n">Stun Grenades</td><td>Strut F bottom floor · Strut E · DE connecting bridge · Shell 1 Core B1 lockers.</td></tr>
<tr><td class="n">Claymore Mines</td><td>EF connecting bridge (crawl across to collect) · Strut E Heliport · Strut A Roof after the Fortune fight · Shell 1 Core 1F south lockers.</td></tr>
<tr><td class="n">AKS-74u</td><td>Strut F bottom floor, after the Fatman fight.</td></tr>
<tr><td class="n">M4</td><td>Strut F top floor, middle-left room, after the Fatman fight.</td></tr>
<tr><td class="n">C-4</td><td>Strut F top floor top-right room (locker) · Shell 1 Core 1F south lockers · Emma's locker in Shell 2 Core B1.</td></tr>
<tr><td class="n">Directional Mic</td><td>Shell 1 Core B2 Computer Room story-required item.</td></tr>
<tr><td class="n">RGB6</td><td>Strut F, after meeting Ames top floor, <b>top-left</b> room.</td></tr>
<tr><td class="n">PSG-1</td><td>Strut F, after meeting Ames top floor, <b>middle-right</b> room.</td></tr>
<tr><td class="n">PSG-1T</td><td>Same room as the PSG-1 crawl into the vent.</td></tr>
<tr><td class="n">Grenades</td><td>Strut F, after meeting Ames top floor, <b>bottom-left</b> room.</td></tr>
<tr><td class="n">Stinger</td><td>Automatic during the Harrier fight.</td></tr>
<tr><td class="n">Nikita</td><td>Shell 2 Core B1 story-required; swim underwater to find it.</td></tr>
<tr><td class="n">HF Blade</td><td>Automatic given by Snake after you escape the torture room.</td></tr>
</table>
<div class="infobox">Most Strut F weapon rooms only open up <b>after the Fatman fight</b> and again <b>after meeting Ames</b> do a full sweep of Strut F at each of those points.</div>"""),
"ach_002_038": dict(cat="coll", miss=True,
where="Tanker (2 boxes) + Plant (5 boxes)", window="Both chapters",
guide="""
<p>Collect all <b>7</b> cardboard boxes.</p>
<h3>Tanker</h3>
<ul class="tight">
<li><b>Box 1 </b> Deck-D, crew's quarters, inside the food storage room (right of the stairs you come up).</li>
<li><b>Wet Box </b> after the Olga fight, on the Navigational Deck, Wing. As you turn the corner a guard comes out of a door; the box is up by the spotlight near where he goes.</li>
</ul>
<h3>Plant</h3>
<ul class="tight">
<li><b>Box 1 Strut A:</b> after getting the Lv. 1 Card, take the small stairs in the bottom-left of the pipe room, crawl under the pipes on your first right and climb over the box below. Needs Lv. 1 Card.</li>
<li><b>Box 2 Strut F:</b> bottom floor, in the bottom-left room with the Radar Node. Needs Lv. 1 Card.</li>
<li><b>Box 5 Strut E:</b> on the conveyor belt near the Radar Node.</li>
<li><b>Box 3 Strut E Rooftop Helipad:</b> bottom-left corner of the rooftop.</li>
<li><b>Box 4 Shell 1 Core B2:</b> across from the Radar Node, near the Directional Mic and the parrot.</li>
</ul>"""),
"ach_002_044": dict(cat="coll", miss=True,
where="Tanker — 50 tags", window="End of a completed chapter",
guide="""
<p>Get the <b>Bandana</b> (infinite ammo) requires <b>50 Tanker dog tags</b>.</p>
<p>All Very Easy (24) + all Easy (26) = exactly 50. Finish the chapter and save a <b>completed</b> file so the item carries over.</p>"""),
"ach_002_045": dict(cat="coll", miss=True,
where="Tanker — 76 tags", window="End of a completed chapter",
guide="""
<p>Get the <b>Tanker stealth suit</b> requires <b>76 Tanker dog tags</b>.</p>
<p>Very Easy (24) + Easy (26) + Normal (33) = 83, so 76 arrives partway through the Normal tag sweep. Finish the chapter and save a completed file.</p>"""),
"ach_002_046": dict(cat="coll", miss=True,
where="Plant — 80 tags", window="End of a completed chapter",
guide="""
<p>Get the <b>Brown Wig</b> (infinite ammo) requires <b>80 Plant dog tags</b>.</p>
<p>Very Easy (43) + Easy (44) = 87, so this lands during the Easy sweep. Finish the chapter and save a completed file.</p>"""),
"ach_002_047": dict(cat="coll", miss=True,
where="Plant — 120 tags", window="End of a completed chapter",
guide="""
<p>Get the <b>Plant stealth suit</b> requires <b>120 Plant dog tags</b>.</p>
<p>Very Easy (43) + Easy (44) + Normal (49) = 136, so 120 arrives partway through the Normal sweep. This is the item that makes Pacifist Run and Complete Stealth trivial, so do it before those runs.</p>"""),
# --------------------------------------------------------- CHALLENGE
"ach_002_048": dict(cat="chal", miss=True,
where="Any completed playthrough", window="Whole run",
guide="""
<p>Clear the game without killing anyone.</p>
<ul class="tight">
<li>Only use <b>non-lethal</b> weapons M9, PSG1-T, stun grenades, the HF Blade's <b>blue</b> side.</li>
<li>This includes bosses that have a <b>stamina bar</b>: Olga, Fatman, Vamp, Harrier, Solidus. Damage their stamina, not their health.</li>
<li>For <b>Solidus</b>, open the inventory on the HF Blade and swap it to the <b>non-lethal side</b>.</li>
</ul>
<div class="infobox"><b>Easiest route:</b> do this on <b>Very Easy with the Bandana equipped</b> (infinite tranq ammo) after you have unlocked it. Community reports also confirm you can earn it with a <b>Tanker-only</b> run if you started one.</div>
<div class="warnbox">Do not press the neck-break prompt, do not shoot explosive barrels into enemies, and do not let the steam pipe kill anyone on this file.</div>"""),
"ach_002_049": dict(cat="chal", miss=True,
where="Any completed playthrough", window="Whole run",
guide="""
<p>Clear the game without entering <b>Alert</b> mode (mandatory alert events excluded).</p>
<ul class="tight">
<li>You are fine while the HUD says <b>CAUTION</b>. You fail the moment it turns red <b>ALERT</b>.</li>
<li>Being spotted is OK <i>if</i> you stop the guard before he finishes his radio call you have a short window.</li>
<li><b>Easiest method:</b> equip the <b>Stealth Camo</b> and walk through the whole game invisible. Enemies and cameras cannot see you.</li>
</ul>
<div class="warnbox"><b>The one exception:</b> the <b>Shell 1 Core elevator</b> requires you to wear the disguise and equip the AK-47. The camera will spot you even with stealth equipped if you try it any other way do it properly and you stay safe.</div>
<p>The following forced alert sequences <b>do not</b> void the achievement:</p>
<ul class="tight">
<li>Boss fights</li>
<li>The soldiers hallway fight in the Tanker</li>
<li>After speaking with Ames in the hostage room</li>
<li>The Tengu soldier fight alongside Snake</li>
</ul>
<p class="muted">Save often and reload if the HUD goes red. Pair this with Pacifist Run on the same playthrough both are trivial with stealth + bandana on Very Easy.</p>"""),
"ach_002_050": dict(cat="chal", miss=True,
where="Extreme difficulty, Tanker → Plant", window="Whole run",
guide="""
<p>Earn the title of <b>Big Boss</b>. This is the hardest achievement in the game see the dedicated
<b>Big Boss Run</b> tab for full criteria, boss strategies, save points and time checkpoints.</p>
<p>Complete the game on <b>Extreme</b>, TankerPlant, with:</p>
<ul class="tight">
<li>Time under <b>3:00:00</b></li>
<li><b>0</b> continues, <b>0</b> rations used, <b>0</b> kills</li>
<li><b>3 or fewer</b> alerts</li>
<li><b>700 or fewer</b> shots fired</li>
<li>Mech damage under <b>60</b> (cameras, Cyphers, RAYs you must destroy ~20 RAYs, so keep everything else under ~40)</li>
<li>Damage received: <b>10 health bars or less</b></li>
<li><b>No special items</b>, <b>no radar</b></li>
</ul>"""),
# --------------------------------------------------------- MODES / EXTRA
"ach_002_039": dict(cat="mode",
where="Main Menu → Special → Casting Theater", window="After completing the game",
guide="""
<p>Watch anything in the Casting Theater. Pops automatically while earning <b>Love Hurts</b>.</p>
<p>Main Menu Special Casting Theater pick any demo and let it play.</p>"""),
"ach_002_040": dict(cat="mode",
where="Main Menu → Boss Survival", window="Unlocked after beating the game",
guide="""
<p>Complete <b>Boss Survival</b> all bosses from both chapters back to back:</p>
<p class="muted">Olga Tanker ambush soldiers Fatman Harrier Vamp Tengu soldiers Metal Gear RAYs Solidus</p>
<div class="okbox"><b>Pick Raiden on Easy.</b> Raiden has the <b>HF Blade</b> for the Solidus fight; Snake only gets a melee attack, which makes the last fight far harder. You can also change the difficulty of Boss Survival independently.</div>"""),
"ach_002_041": dict(cat="mode",
where="Main Menu → Snake Tales", window="Any time",
guide="""
<p>Complete at least <b>one</b> of the five Snake Tales: <i>A Wrongdoing</i>, <i>Big Shell Evil</i>, <i>Confidential Legacy</i>,
<i>Dead Man</i>, <i>External Gazer</i>.</p>
<p>The Master Collection only requires one (the 2011 HD release required all five). Pick whichever you like <b>A Wrongdoing</b> is the shortest.</p>"""),
"ach_002_042": dict(cat="mode",
where="Main Menu → VR Missions / Alternative Missions", window="Any time",
guide="""
<p>Complete any single VR or Alternative mission. One and done pick the shortest Sneaking mission you can find.</p>"""),
"ach_002_043": dict(cat="mode",
where="Main Menu → VR Missions / Alternative Missions", window="Any time",
guide="""
<p>Place <b>first</b> in 50 different VR/Alternative missions (beat the target time).</p>
<ul class="tight">
<li>There are 500+ missions, so this is only ~10% of them.</li>
<li>Short <b>Sneaking</b> and <b>Weapon</b> missions are the fastest first places.</li>
<li>The Master Collection does <b>not</b> require clearing every mission <i>Virtually Impossible</i> was removed.</li>
</ul>"""),
"ach_002_051": dict(cat="extra",
where="Master Collection launcher → MGS2 Screenplay Book", window="Any time",
guide="""
<p>Read all pages in the <b>Screenplay Book</b>.</p>
<ol class="tight">
<li>From the Master Collection launcher, open the MGS2 <b>Screenplay</b>.</li>
<li>Tab/page all the way to the <b>end</b> the achievement pops when you reach the last page.</li>
</ol>
<div class="okbox">Free achievement do it from the main menu before you even start playing.</div>"""),
}