Claim set · data/claims/silent-hill.yaml

Silent Hill (shdecompilations' silent-hill-decomp, US build)

Game: Silent Hill.

In the US build (SLUS-00707), Game_NpcUpdate picks the enemies the pocket radio reacts to by distance alone, with no line-of-sight test. An enemy (a character id up to Chara_MonsterCybil, the code's last common enemy) counts while its health is above 0, its CharaFlag_NoRadioStatic flag is clear (Split Head's init sets it; other setters weren't read), and its squared distance from Harry on the ground plane, x and z with height ignored, is under 32² world units (a unit is Q12 1.0). In maps flagged MapFlag_Interior with one or two active chunks, which the code calls low-visibility interiors, the enemy must also share Harry's 40-unit chunk cell on both axes. The code keeps the three nearest, and the radio's two static channels (g_RadioNoise[2]) each follow one of the nearest two, only while ItemToggleFlag_RadioOn is set. Each channel is panned toward its enemy, and its volume falls with distance: the attenuation is the distance converted by Q12_TO_Q4 (sixteenths of a unit, by the decompilers' reading, which their comment "TODO: Is it Q4 here?" doubts), halved outside low-visibility interiors, capped at 255, and Sd_SfxAttributesUpdate takes that share out of 255 from the volume. Computed under that reading, the static falls silent at about 16 units in a low-visibility interior and about 32 units elsewhere. silent-hill/radio-static

About: Silent Hill Proximity warning

Value
{
 "rangeUnits": 32,
 "channels": 2,
 "chunkCell": 40,
 "silentInteriorUnits": 16,
 "silentElsewhereUnits": 32,
 "attenuationMax": 255
}
Codesilent-hill-decomp: a matching decompilation of Silent Hill for the PlayStation (shdecompilations/silent-hill-decomp) · src/bodyprog/events/npc_main.c#L218-L229posXShift6 = Q12_TO_Q6(g_SysWork.playerWork.player.position.vx); posZShift6 = Q12_TO_Q6(g_SysWork.playerWork.player.position.vz); … closestNpcInfos[j].distanceToNpc = SQUARE(32);silent-hill-decomp: a matching decompilation of Silent Hill for the PlayStation (shdecompilations/silent-hill-decomp) · src/bodyprog/events/npc_main.c#L243-L287// Only process enemy NPC for radio interference. if (curNpc->model.charaId <= CHARA_LAST_ENEMY_ID) { // Compute square integer distance from player to NPC. curDistToNpc = Q12_SQUARE_PRECISE(Q12_TO_Q6(curNpc->position.vx) - posXShift6) + Q12_SQUARE_PRECISE(Q12_TO_Q6(curNpc->position.vz) - posZShift6); // Check if map is low-visibility interior. isLowVisInterior = false; if (g_MapOverlayHdr.mapInfo->flags & MapFlag_Interior) { isLowVisInterior = (g_MapOverlayHdr.mapInfo->flags & (MapFlag_OneActiveChunk | MapFlag_TwoActiveChunks)) > 0; …silent-hill-decomp: a matching decompilation of Silent Hill for the PlayStation (shdecompilations/silent-hill-decomp) · include/bodyprog/map/terrain.h#L7#define CHUNK_SIZE 40.0fsilent-hill-decomp: a matching decompilation of Silent Hill for the PlayStation (shdecompilations/silent-hill-decomp) · include/bodyprog/chara/chara.h#L15#define CHARA_LAST_ENEMY_ID Chara_MonsterCybilsilent-hill-decomp: a matching decompilation of Silent Hill for the PlayStation (shdecompilations/silent-hill-decomp) · src/maps/characters/split_head.c#L62splitHead->flags |= CharaFlag_NoRadioStatic | CharaFlag_Hit;silent-hill-decomp: a matching decompilation of Silent Hill for the PlayStation (shdecompilations/silent-hill-decomp) · src/bodyprog/events/npc_main.c#L155s_CloseNpcInfo closestNpcInfos[3];silent-hill-decomp: a matching decompilation of Silent Hill for the PlayStation (shdecompilations/silent-hill-decomp) · src/bodyprog/events/npc_main.c#L181-L201s32 func_800382B0(s32 bitIdx) … for (i = 0; i < (ARRAY_SIZE(closestNpcInfos) - 1); i++) … static s32 func_800382EC() … for (i = 0; i < (ARRAY_SIZE(closestNpcInfos) - 1); i++)silent-hill-decomp: a matching decompilation of Silent Hill for the PlayStation (shdecompilations/silent-hill-decomp) · src/bodyprog/events/game_sys_states.c#L68s_RadioNoise g_RadioNoise[2];silent-hill-decomp: a matching decompilation of Silent Hill for the PlayStation (shdecompilations/silent-hill-decomp) · src/bodyprog/events/npc_main.c#L362-L365if (!(g_SavegamePtr->itemToggleFlags & ItemToggleFlag_RadioOn)) { return; }silent-hill-decomp: a matching decompilation of Silent Hill for the PlayStation (shdecompilations/silent-hill-decomp) · src/bodyprog/events/npc_main.c#L423-L445isExterior = false; if (!(g_MapOverlayHdr.mapInfo->flags & MapFlag_Interior) || !(g_MapOverlayHdr.mapInfo->flags & (MapFlag_OneActiveChunk | MapFlag_TwoActiveChunks))) { isExterior = true; } … balance = Vc_StereoBalanceGet(&closeNpcInfo->position); // Compute volume from distance. distToNpc = Q12_TO_Q4(SquareRoot12(Q12(closeNpcInfo->distanceToNpc))); if (isExterior) { …silent-hill-decomp: a matching decompilation of Silent Hill for the PlayStation (shdecompilations/silent-hill-decomp) · src/bodyprog/sound/sd_call.c#L560-L561convertedVol = vol; convertedVol = g_Sd_VabPlayingInfo.volumeLeft - ((g_Sd_VabPlayingInfo.volumeLeft * (convertedVol)) / 255);Checked by claude-agent, 2026-10-22 — read Game_NpcUpdate's distance, filter, and sound blocks, the two nested slot finders, and Sd_SfxAttributesUpdate's volume line; worked the Q6/Q12 squares and the Q4 attenuation by hand

The squared distance is integer world units: positions are Q12, shifted to Q6 and squared with a Q12 shift. The attenuation reads that integer square root back as Q4, so 255 is reached at 255/16 ≈ 15.9 units, or 255/8 ≈ 31.9 units once halved. The decompilers' own comment on the volume line ("TODO: Is it Q4 here?") marks the scale as their open question, not the code's. g_RadioPitchState is set to the number of filled slots (0 to 3) in the same function; its reader isn't identified.

Cited by: Proximity warning, Silent Hill

In the US build, the flashlight swaps which environment preset's flags are live, and enemy code reads those flags. Gfx_EffectsUpdate moves flashlightIntensity toward 1 while the flashlight is on and toward 0 while it's off, by 4 × g_DeltaTime per update, and func_8003F838 copies the live flags (field_154) from the flashlight-off preset (field_1C[0]) while the intensity is under 0.5 and from the flashlight-on preset (field_1C[1]) from 0.5 up. WorldEnv_MapPresetSet gives a map whose header's unnamed field_16 is 2 the preset pair 6 and 3, or 7 and 4 in low-visibility interiors (off, then on). Presets 6 and 7 set SpecialEnvEventFlags_DarkEnvironment and SpecialEnvEventFlags_FlashlightAllowed; presets 3 and 4 set FlashlightAllowed without DarkEnvironment. A map whose field_16 is 1 gets preset 1 or 2 for both, which set neither flag, and Gfx_MapEnvStepUpdate marks the flashlight unavailable whenever the two presets are the same. So in those dark maps, the flags read as dark with the flashlight off and as lit with it on; map events can load other pairs. silent-hill/flashlight-presets

About: Silent Hill Light detection

Value
{
 "switchAt": 0.5,
 "rampPerDelta": 4,
 "darkMapOffPresets": [
  6,
  7
 ],
 "darkMapOnPresets": [
  3,
  4
 ],
 "fogMapPresets": [
  1,
  2
 ]
}
Codesilent-hill-decomp: a matching decompilation of Silent Hill for the PlayStation (shdecompilations/silent-hill-decomp) · src/bodyprog/world/world_effects.c#L393-L403if (g_SysWork.field_2388.isFlashlightOn) { g_SysWork.field_2388.flashlightIntensity += Q12_MULT_FLOAT_PRECISE(g_DeltaTime, 4.0f); } else { g_SysWork.field_2388.flashlightIntensity -= Q12_MULT_FLOAT_PRECISE(g_DeltaTime, 4.0f); } g_SysWork.field_2388.flashlightIntensity = CLAMP(g_SysWork.field_2388.flashlightIntensity, Q12(0.0f), Q12(1.0f));silent-hill-decomp: a matching decompilation of Silent Hill for the PlayStation (shdecompilations/silent-hill-decomp) · src/bodyprog/world/world_effects.c#L412-L415if (ptr->primitiveType == PrimitiveType_None) { ptr->field_1C[0] = ptr->field_84[0]; ptr->field_1C[1] = ptr->field_84[1];silent-hill-decomp: a matching decompilation of Silent Hill for the PlayStation (shdecompilations/silent-hill-decomp) · src/bodyprog/world/world_effects.c#L430func_8003F838(&ptr->field_154, &ptr->field_1C[0], &ptr->field_1C[1], ptr->flashlightIntensity);silent-hill-decomp: a matching decompilation of Silent Hill for the PlayStation (shdecompilations/silent-hill-decomp) · src/bodyprog/world/world_effects.c#L636-L657static void func_8003F838(s_StructUnk3* target, s_StructUnk3* envSettings0, s_StructUnk3* envSettings1, q19_12 weight) // 0x8003F838 … // Copy enviroment flags. if (weight < Q12(0.5f)) { target->effectsInfo.flags.field_00[0] = envSettings0->effectsInfo.flags.field_00[0]; } else { target->effectsInfo.flags.field_00[0] = envSettings1->effectsInfo.flags.field_00[0]; }silent-hill-decomp: a matching decompilation of Silent Hill for the PlayStation (shdecompilations/silent-hill-decomp) · src/bodyprog/world/world_effects.c#L316-L337if (preset0 == preset1) { g_SysWork.field_2388.isFlashlightUnavailable = true; } … Gfx_FogParametersSet(&g_SysWork.field_2388.field_84[0], preset0); Gfx_FogParametersSet(&g_SysWork.field_2388.field_84[1], preset1);silent-hill-decomp: a matching decompilation of Silent Hill for the PlayStation (shdecompilations/silent-hill-decomp) · src/bodyprog/world/world_effects.c#L22-L25static s_MapEnvPresetIdxs D_800A9F80 = { 1, 1 }; static s_MapEnvPresetIdxs D_800A9F84 = { 2, 2 }; static s_MapEnvPresetIdxs D_800A9F88 = { 6, 3 }; static s_MapEnvPresetIdxs D_800A9F8C = { 7, 4 };silent-hill-decomp: a matching decompilation of Silent Hill for the PlayStation (shdecompilations/silent-hill-decomp) · src/bodyprog/world/world_effects.c#L210-L232switch (mapHdr->field_16) { case 1: if (hasActiveChunk) { presetIdxPtr = &D_800A9F84; } else { presetIdxPtr = &D_800A9F80; } break; …silent-hill-decomp: a matching decompilation of Silent Hill for the PlayStation (shdecompilations/silent-hill-decomp) · src/bodyprog/sys/map_info.c#L5-L119s_MapEffectsInfo MAP_EFFECTS_INFOS[21] = { … .flags = { .field_00 = { SpecialEnvEventFlags_None, 0xFF, UnkGfxEnum_0, 0 }}, … .flags = { .field_00 = { SpecialEnvEventFlags_None, 0xFF, UnkGfxEnum_2, 0 }}, … .flags = { .field_00 = { (SpecialEnvEventFlags_FlashlightAllowed | SpecialEnvEventFlags_EnableBrightness | SpecialEnvEventFlags_EnableLensflare), 0xFF, UnkGfxEnum_1, 0 }}, … .flags = { .field_00 = { (SpecialEnvEventFlags_FlashlightAllowed | SpecialEnvEventFlags_EnableBrightness | SpecialEnvEventFlags_EnableLensflare), 0xFF, UnkGfxEnum_1, 0 }}, … .flags = { .field_00 = { (SpecialEnvEventFlags_DarkEnvironment | SpecialEnvEventFlags_FlashlightAllowed | SpecialEnvEventFlags_EnableBrightness), 0xFF, UnkGfxEnum_0, 0 }}, … …Checked by claude-agent, 2026-10-22 — read the intensity ramp and blend call in Gfx_EffectsUpdate, func_8003F838's flag copy, Gfx_MapEnvStepUpdate, WorldEnv_MapPresetSet and its index pairs, and the flags of presets 1 to 7 in MAP_EFFECTS_INFOS

The table's entries are at lines 6 (preset 0), 22 (1), 38 (2), 54 (3), 70 (4), 86 (5), 102 (6), and 118 (7); the quote's fragments are presets 1, 2, 3, 4, 6, and 7 in order. The decompilers' comment on DarkEnvironment reads "Double check". Whether a map's field_16 of 2 means the Otherworld or nighttime, the atlas hasn't checked.

Cited by: Light detection, Silent Hill

In the US build, LarvalStalker_ControlUpdate sets the larval stalker's target position to Harry's whenever his distance on the ground plane is under 2 × base + step, with base and step picked by the live light flags (silent-hill/flashlight-presets): 2.5 and 8 when neither DarkEnvironment nor FlashlightAllowed is set, 3.5 and 10 when only FlashlightAllowed is, and 0.5 and 1.5 otherwise. Computed, that's 13 world units in fog presets; in the dark map presets, 17 units with the flashlight on and 2.5 with it off. This check reads no facing and no line of sight. silent-hill/larval-stalker-light

About: Silent Hill Light detection

Value
{
 "fogUnits": 13,
 "lightOnUnits": 17,
 "lightOffUnits": 2.5
}
Codesilent-hill-decomp: a matching decompilation of Silent Hill for the PlayStation (shdecompilations/silent-hill-decomp) · src/maps/characters/larval_stalker.c#L84void LarvalStalker_ControlUpdate(s_SubCharacter* larvalStalker)silent-hill-decomp: a matching decompilation of Silent Hill for the PlayStation (shdecompilations/silent-hill-decomp) · src/maps/characters/larval_stalker.c#L111-L133idxInfo = g_SysWork.field_2388.field_154.effectsInfo.flags.field_0 & (SpecialEnvEventFlags_DarkEnvironment | SpecialEnvEventFlags_FlashlightAllowed); if (idxInfo == 0) { baseDistMax = Q12(2.5f); distStep = Q12(8.0f); } else if (idxInfo == 2) { baseDistMax = Q12(3.5f); distStep = Q12(10.0f); } else …silent-hill-decomp: a matching decompilation of Silent Hill for the PlayStation (shdecompilations/silent-hill-decomp) · include/game.h#L298-L299SpecialEnvEventFlags_DarkEnvironment = 1 << 0, // Double check. SpecialEnvEventFlags_FlashlightAllowed = 1 << 1,Checked by claude-agent, 2026-10-22 — read the flag switch and the distance test in LarvalStalker_ControlUpdate; computed 2 × base + step for each branch

Cited by: Light detection, Silent Hill

In the US build, a walking creeper (Creeper_ControlWalkForward) retargets Harry's position when func_8006FD90 passes, with arguments picked by the live light flags (silent-hill/flashlight-presets). func_8006FD90 scales a range by how directly the creeper faces Harry, f = 1 − |angle off its heading|/180° (1 straight ahead, 0 behind), raised to the power count + 1; it fails beyond base + step × that, and otherwise a ray test toward Harry (Ray_CharaTraceQuery) decides. With only FlashlightAllowed set, the creeper calls it with count 0, base 12, and step 8: 12 units behind to 20 ahead. With FlashlightAllowed and DarkEnvironment, count 2, base 0.8, step 0.4: 0.8 to 1.2 units. With neither flag, count 1, base 4, step 12: 4 to 16 units (all computed). A separate check (func_80070360 with 0.5) or an alert flag also retargets it. silent-hill/creeper-light

About: Silent Hill Light detection

Value
{
 "lightOn": {
  "count": 0,
  "base": 12,
  "step": 8
 },
 "darkLightOff": {
  "count": 2,
  "base": 0.8,
  "step": 0.4
 },
 "neither": {
  "count": 1,
  "base": 4,
  "step": 12
 }
}
Codesilent-hill-decomp: a matching decompilation of Silent Hill for the PlayStation (shdecompilations/silent-hill-decomp) · src/maps/characters/creeper.c#L372-L392void Creeper_ControlWalkForward(s_SubCharacter* creeper) … if (((g_SysWork.field_2388.field_154.effectsInfo.flags.field_0 & (SpecialEnvEventFlags_DarkEnvironment | SpecialEnvEventFlags_FlashlightAllowed)) == SpecialEnvEventFlags_FlashlightAllowed && func_8006FD90(creeper, 0, Q12(12.0f), Q12(8.0f))) || ((g_SysWork.field_2388.field_154.effectsInfo.flags.field_00[0] & SpecialEnvEventFlags_FlashlightAllowed) && (g_SysWork.field_2388.field_154.effectsInfo.flags.field_00[0] & SpecialEnvEventFlags_DarkEnvironment) && func_8006FD90(creeper, 2, Q12(0.8f), Q12(0.4f))) || (!(g_SysWork.field_2388.field_154.effectsInfo.flags.field_0 & (SpecialEnvEventFlags_DarkEnvironment | SpecialEnvEventFlags_FlashlightAllowed)) && func_8006FD90(creeper, 1, Q12(4.0f), Q12(12.0f))) || (func_80070360(creeper, 0, Q12(0.5f)) || creeperProps.flags & CreeperFlag_Alerted)) { creeperProps.targetPositionX = playerChara.position.vx; creeperProps.targetPositionZ = playerChara.position.vz;silent-hill-decomp: a matching decompilation of Silent Hill for the PlayStation (shdecompilations/silent-hill-decomp) · src/bodyprog/collision/los.c#L137-L171bool func_8006FD90(s_SubCharacter* chara, s32 count, q19_12 baseDistMax, q19_12 distStep) // 0x8006FD90 … distMult = (Math_AngleNormalizeSigned(ratan2(g_SysWork.playerWork.player.position.vx - chara->position.vx, g_SysWork.playerWork.player.position.vz - chara->position.vz) - chara->rotation.vy) * 2) + Q12_ANGLE(360.0f); … distMult = (Q12_ANGLE(180.0f) - Math_AngleNormalizeSigned((ratan2(g_SysWork.playerWork.player.position.vx - chara->position.vx, g_SysWork.playerWork.player.position.vz - chara->position.vz) - chara->rotation.vy))) * 2; … for (i = distMult; count > 0; count--) { …silent-hill-decomp: a matching decompilation of Silent Hill for the PlayStation (shdecompilations/silent-hill-decomp) · src/bodyprog/collision/los.c#L172-L195return false; … return !Ray_CharaTraceQuery(&sp10, &pos, &offset, chara) || sp20.vx != Q12(0.0f);Checked by claude-agent, 2026-10-22 — read Creeper_ControlWalkForward's three-way flag test and func_8006FD90's facing factor, power loop, range test, and ray test; computed the ranges at f = 0 and f = 1

Q12_ANGLE(360) is Q12 1.0, so the facing factor runs from 1.0 straight ahead to 0 directly behind. The ray's start height also depends on the flags (los.c lines 182-192), and the decompilers' TODO above the return says the ray's output struct may be mistyped, so the claim doesn't say what the ray tests beyond its call. The idle creeper (Creeper_ControlIdle) uses the same three flag cases with count 2 in each, and other enemies (stalker, groaner, romper, hanged scratcher, puppet nurse) also branch on these flags; they aren't read here.

Cited by: Light detection, Silent Hill

In the US build, using a healing item from the inventory (Inventory_PlayerItemScroll) adds 40 health for a Health Drink, 80 for a First Aid Kit, and 100 for an Ampoule, then clamps Harry's health to 0–100 and spends one item. An Ampoule also sets healthSaturation to 300 (a set, not an add). Player_LogicUpdate lowers healthSaturation by g_DeltaTime on each update and, while any remains, raises Harry's health by the same amount, capped at 100. So an Ampoule fills health and then keeps restoring it, up to 300 more in all (computed), with the store draining even while health is full. silent-hill/healing-items

About: Silent Hill Healing item

Value
{
 "healthMax": 100,
 "healthDrink": 40,
 "firstAidKit": 80,
 "ampoule": 100,
 "ampouleStore": 300
}
Codesilent-hill-decomp: a matching decompilation of Silent Hill for the PlayStation (shdecompilations/silent-hill-decomp) · src/bodyprog/items/item_screens_3.c#L1995void Inventory_PlayerItemScroll(u32* selectedItemId) // 0x800523D8silent-hill-decomp: a matching decompilation of Silent Hill for the PlayStation (shdecompilations/silent-hill-decomp) · src/bodyprog/items/item_screens_3.c#L2516-L2539switch (g_SavegamePtr->items[g_SysWork.invItemSelectedIdx].id) … case InvItemId_FirstAidKit: g_SysWork.playerWork.player.health += Q12(80.0f); break; case InvItemId_HealthDrink: g_SysWork.playerWork.player.health += Q12(40.0f); break; case InvItemId_Ampoule: g_SysWork.playerWork.player.health += Q12(100.0f); g_SavegamePtr->healthSaturation = Q12(300.0f); break; …silent-hill-decomp: a matching decompilation of Silent Hill for the PlayStation (shdecompilations/silent-hill-decomp) · src/bodyprog/player_control.c#L1230void Player_LogicUpdate(s_SubCharacter* player, s_PlayerExtra* extra, GsCOORDINATE2* coords) // 0x80071CE8silent-hill-decomp: a matching decompilation of Silent Hill for the PlayStation (shdecompilations/silent-hill-decomp) · src/bodyprog/player_control.c#L1289-L1296g_SavegamePtr->healthSaturation -= g_DeltaTime; g_SavegamePtr->healthSaturation = CLAMP(g_SavegamePtr->healthSaturation, Q12(0.0f), Q12(300.0f)); if (g_SavegamePtr->healthSaturation != Q12(0.0f)) { playerChara.health += g_DeltaTime; playerChara.health = CLAMP(playerChara.health, Q12(0.0f), Q12(100.0f)); }Checked by claude-agent, 2026-10-22 — read the apply-health case in Inventory_PlayerItemScroll and the healthSaturation lines in Player_LogicUpdate

The header comment on healthSaturation (savegame.h line 60) reads "Ampoules give extra stored health. If the player loses health, it will be slowly restored." How fast that is in seconds depends on g_DeltaTime's unit, which the atlas hasn't pinned down. Enemy damage to Harry isn't read here.

Cited by: Healing item, Silent Hill

In the US build, Event_CommonItemTake gives 15 handgun bullets, 6 shotgun shells, or 6 rifle shells per ammunition pickup, times a multiplier of extraBulletAdjust + 1, which is at least 2 on Easy; healing pickups always give one item. Normal and Hard don't change the count. extraBulletAdjust is an Extra Options setting: the options screen allows 1 plus one step for each of the five low bits set in extraOptionsEnabled, so ×1 to ×6. silent-hill/ammo-pickups

About: Silent Hill Ammunition

Value
{
 "handgun": 15,
 "shotgun": 6,
 "rifle": 6,
 "easyMinMultiplier": 2,
 "maxMultiplier": 6
}
Codesilent-hill-decomp: a matching decompilation of Silent Hill for the PlayStation (shdecompilations/silent-hill-decomp) · include/bodyprog/items.h#L7-L10#define DEFAULT_PICKUP_ITEM_COUNT 1 #define HANDGUN_AMMO_PICKUP_ITEM_COUNT 15 #define SHOTGUN_AMMO_PICKUP_ITEM_COUNT 6 #define RIFLE_AMMO_PICKUP_ITEM_COUNT 6silent-hill-decomp: a matching decompilation of Silent Hill for the PlayStation (shdecompilations/silent-hill-decomp) · src/bodyprog/events/events_util.c#L1104-L1142void Event_CommonItemTake(u32 pickupType, e_EventFlag eventFlagIdx) // 0x800879FC { #define EASY_DIFFICULTY_AMMO_COUNT_MULT_MIN 2 … ammoCountMult = g_GameWork.config.extraBulletAdjust + 1; if (g_SavegamePtr->gameDifficulty == GameDifficulty_Easy) { ammoCountMult = CLAMP(ammoCountMult, EASY_DIFFICULTY_AMMO_COUNT_MULT_MIN, ammoCountMult); } … Event_ItemTake(InvItemId_FirstAidKit, DEFAULT_PICKUP_ITEM_COUNT, eventFlagIdx, MapMsgIdx_FirstAidSelect); … …silent-hill-decomp: a matching decompilation of Silent Hill for the PlayStation (shdecompilations/silent-hill-decomp) · src/screens/options/options.c#L136-L146g_ExtraOptionsMenu_BulletMultMax = 1; unlockedOptFlags = g_GameWork.config.extraOptionsEnabled; // Set available bullet multiplier. for (i = 0; i < 5; i++) { if (unlockedOptFlags & (1 << i)) { g_ExtraOptionsMenu_BulletMultMax++; } }silent-hill-decomp: a matching decompilation of Silent Hill for the PlayStation (shdecompilations/silent-hill-decomp) · src/screens/options/options.c#L460-L462g_GameWork.config.extraBulletAdjust = g_GameWork.config.extraBulletAdjust + (g_ExtraOptionsMenu_BulletMultMax - 1); … g_GameWork.config.extraBulletAdjust = g_GameWork.config.extraBulletAdjust % g_ExtraOptionsMenu_BulletMultMax;Checked by claude-agent, 2026-10-22 — read Event_CommonItemTake, the pickup-count defines, and the options screen's bullet-multiplier cap

Which achievements set the five extraOptionsEnabled bits isn't read here. Weapons that map scripts hand over (the handgun in map0_s01, the shotgun in map1_s02 and map2_s04, the hunting rifle in map4_s03) come with the define's count and no multiplier.

Cited by: Silent Hill