On this page
  1. Related
  2. Games
  3. References
  4. Sources

An alert phase is a state the whole level enters when enemies spot the player. In Metal Gear Solid the alert lasts as long as some guard’s alert level holds the commander’s value up, and then a 300-frame evasion phase must run out before the level returns to infiltration1. The radar shows a status panel instead of the map in both phases2.

  • Alert then evasionMetal Gear Solid (1998). Alert while any guard's alert level holds the commander's value up, then evasion for 300 frames, then infiltration again.1,2

Games

GameYearHowNote
Metal Gear Solid1998Alert then evasionalert while any guard's alert level holds the commander's value up, then evasion for 300 frames, then infiltration again
Every claim about this mechanic, by game (2)
Metal Gear Solid 1998In Metal Gear Solid Integral (SLPM-86247), the enemy commander keeps one alert value and a mode: 0 (TOP_COMM_TRAVEL), 1 (TOP_COMM_ALERT), and 2, which sets GM_AlertMode to ALERT_EVASION; the atlas reads 0 as infiltration. Each update, s00a_command_800CF6A0 sets the value to the highest alert_level among its active guards, or lowers it by 4 when it is more than 4 above that, and raises it to TOPCOMMAND.alert, which the security camera and searchlight code set to 255 (ENE_SetTopCommAL). A patrolling guard (think1 0, think2 0) whose alert_level passes 2, after three frames of full sight from 0 (computed), goes to a reaction state: on its first frame it puts a mark over its head (ENE_PutMark, mark 0), and after 20 updates it switches to its alert routines (think1 1) and sets alert_level to 255. In mode 0, a value of 255 calls GM_AlertModeSet(3) (ALERT_ACTIVE), which plays SE_ALERT_SIREN when the mode was ALERT_OFF, and enters mode 1; it adds 1 to GM_EnemyWatchCount unless COM_GameStatus bit 2 is set. Once the commander leaves mode 0, every guard still in its patrol routines switches to its alert routines. Mode 1 has no timer: it lasts until the value falls to 0, which starts mode 2 with a counter of 300 that drops by 1 each update. A value of 255 during mode 2 returns to mode 1; when the counter runs out, the commander returns to mode 0 and ALERT_OFF. The game waits DG_FrameRate = 2 vertical blanks per frame, 30 frames a second on a 60 Hz display, so the evasion phase lasts 10 seconds (computed). The stage script's l option sets COM_EYE_LENGTH separately for modes 0, 1, and 2, 4,000 in each by default.Code
In Metal Gear Solid Integral (SLPM-86247), the radar (draw_radar) draws the map only in ALERT_OFF. In ALERT_ACTIVE and ALERT_EVASION, and in ALERT_OFF while GM_GameStatus has STATE_CHAFF or STATE_JAMMING set (shown as ALERT_JAMMING), it draws a status panel (menu_radar_draw_state) in its place, playing SE_RADAR_JAMMED when jamming begins from ALERT_OFF; for alert and evasion the panel draws GM_AlertLevel as a gauge. When the panel ends, the map returns behind a sweep while a counter set to 93 falls by 2 per frame, about 47 frames (computed), with SE_RADAR_CHIME, which the decompilers' comment says plays when evasion or jamming ends. In ALERT_OFF, with no override function set, the radar isn't drawn in a duct (PLAYER_INTRUDE) or with the radar turned off in the options. On the map, each guard's cone comes from its sight: its facing, vision.length, and twice vision.angle as the width (s00a_command_800C9878).Code

References

  1. ^ abIn Metal Gear Solid Integral (SLPM-86247), the enemy commander keeps one alert value and a mode: 0 (TOP_COMM_TRAVEL), 1 (TOP_COMM_ALERT), and 2, which sets GM_AlertMode to ALERT_EVASION; the atlas reads 0 as infiltration. Each update, s00a_command_800CF6A0 sets the value to the highest alert_level among its active guards, or lowers it by 4 when it is more than 4 above that, and raises it to TOPCOMMAND.alert, which the security camera and searchlight code set to 255 (ENE_SetTopCommAL). A patrolling guard (think1 0, think2 0) whose alert_level passes 2, after three frames of full sight from 0 (computed), goes to a reaction state: on its first frame it puts a mark over its head (ENE_PutMark, mark 0), and after 20 updates it switches to its alert routines (think1 1) and sets alert_level to 255. In mode 0, a value of 255 calls GM_AlertModeSet(3) (ALERT_ACTIVE), which plays SE_ALERT_SIREN when the mode was ALERT_OFF, and enters mode 1; it adds 1 to GM_EnemyWatchCount unless COM_GameStatus bit 2 is set. Once the commander leaves mode 0, every guard still in its patrol routines switches to its alert routines. Mode 1 has no timer: it lasts until the value falls to 0, which starts mode 2 with a counter of 300 that drops by 1 each update. A value of 255 during mode 2 returns to mode 1; when the counter runs out, the commander returns to mode 0 and ALERT_OFF. The game waits DG_FrameRate = 2 vertical blanks per frame, 30 frames a second on a 60 Hz display, so the evasion phase lasts 10 seconds (computed). The stage script's l option sets COM_EYE_LENGTH separately for modes 0, 1, and 2, 4,000 in each by default.CodeFoxdieTeam/mgs_reversing
    How we know
    598void s00a_command_800CF6A0( int val, ENEMY_COMMAND* command )
    ⋮
    600    if ( command->alert - val > 4 )
    ⋮
    602        command->alert -= 4;
    ⋮
    604    else
    ⋮
    606        command->alert = val;
    ⋮
    609    if ( command->alert < TOPCOMMAND.alert )
    ⋮
    611        command->alert = TOPCOMMAND.alert;
    ⋮
    614    ENE_SetTopCommAL( 0 );
    
    source/enemy/command.c lines 598–615 at bf9189e · upstream ↗
    617void s00a_command_800CF704( ENEMY_COMMAND *command )
    ⋮
    621    switch ( command->mode )
    ⋮
    626        case 0:
    627            COM_EYE_LENGTH = EnemyCommand.field_0x88.vx;
    628            COM_SHOOTRANGE = EnemyCommand.field_0x88.vx + 500;
    629            if ( command->alert >= 255 )
    ⋮
    631                command->alert = 255;
    632                GM_AlertModeSet(3);
    633                command->mode = 1;
    634                EnemyCommand.reset_enemy_num = 0;
    635                COM_GameStatus |= 0x1;
    ⋮
    637                if ( !( COM_GameStatus & 2 ) )
    ⋮
    
    source/enemy/command.c lines 617–694 at bf9189e · upstream ↗
    760    alert = 0;
    ⋮
    766    for ( i = 0; i < EnemyCommand.field_0x08; i++ )
    ⋮
    768        if ( EnemyCommand.field_0xC8[ i ].field_04 == 2 )
    ⋮
    770            watcher = EnemyCommand.field_0xC8[ i ].watcher;
    771            alert =  s00a_command_800CF688( alert, watcher->alert_level );
    ⋮
    785    s00a_command_800CF6A0( alert, &EnemyCommand );
    786    s00a_command_800CF704( &EnemyCommand );
    
    source/enemy/command.c lines 760–786 at bf9189e · upstream ↗
    588int s00a_command_800CF688( int a0, int a1 )
    ⋮
    590    if ( a0 < a1 )
    ⋮
    592        a0 = a1;
    ⋮
    595    return a0;
    
    source/enemy/command.c lines 588–596 at bf9189e · upstream ↗
    536#define TOP_COMM_TRAVEL 0
    537#define TOP_COMM_ALERT  1
    
    source/enemy/enemy.h lines 536–537 at bf9189e · upstream ↗
    177enum {
    178    ALERT_OFF = 0,
    179    ALERT_JAMMING = 1,
    180    ALERT_EVASION = 2,
    181    ALERT_ACTIVE = 3
    
    source/game/g_define.h lines 177–182 at bf9189e · upstream ↗
    260    if (field_1EC == 35)
    ⋮
    262        ENE_SetTopCommAL(255);
    
    source/enemy/camera.c lines 260–262 at bf9189e · upstream ↗
    448    if (s01a_searchli_800D73D8(work))
    ⋮
    450        ENE_SetTopCommAL(255);
    
    source/enemy/searchli.c lines 448–450 at bf9189e · upstream ↗
    1955    else if ( work->alert_level > 2 )
    ⋮
    1957        ENE_SetGopointLast();
    1958        s00a_command_800CB240( work );
    
    source/enemy/think.c lines 1955–1959 at bf9189e · upstream ↗
    385void s00a_command_800CB240( WatcherWork* work )
    ⋮
    387    work->think2 = 7;
    388    work->think3 = 14;
    389    work->count3 = 0;
    
    source/enemy/think.c lines 385–390 at bf9189e · upstream ↗
    2324void s00a_command_800CDD80( WatcherWork *work )
    ⋮
    2326    switch( work->think3 )
    ⋮
    2328        case 14:
    2329        if ( s00a_command_800CBDFC( work ) )
    ⋮
    2331            s00a_command_800CB2C8( work );
    ⋮
    2340            work->alert_level = 255;
    
    source/enemy/think.c lines 2324–2343 at bf9189e · upstream ↗
    929int s00a_command_800CBDFC( WatcherWork* work )
    ⋮
    935    if ( count == 0 )
    ⋮
    937        ENE_PutMark( work, 0 );
    ⋮
    942    if ( count < 20 )
    ⋮
    944        work->pad.press |= 0x20;
    945        work->count3++;
    946        return 0;
    ⋮
    949    return 1;
    
    source/enemy/think.c lines 929–951 at bf9189e · upstream ↗
    411void s00a_command_800CB2C8( WatcherWork *work )
    ⋮
    414    work->think1 = 1;
    415    work->think2 = 9;
    
    source/enemy/think.c lines 411–418 at bf9189e · upstream ↗
    2688void s00a_command_800CE634( WatcherWork *work )
    ⋮
    2690    switch( work->think2 )
    ⋮
    2694        break;
    2695        case 0:
    2696        s00a_command_800CD210( work );
    2697        break;
    ⋮
    2701        break;
    ⋮
    2705        break;
    ⋮
    2709        break;
    ⋮
    2713        break;
    ⋮
    2717        break;
    ⋮
    2721        break;
    ⋮
    
    source/enemy/think.c lines 2688–2736 at bf9189e · upstream ↗
    2832    switch ( work->think1 )
    ⋮
    2834    case 0:
    2835        work->unknown.field_1E = 1;
    2836        s00a_command_800CE634( work );
    2837        break;
    2838    case 1:
    2839        work->unknown.field_1E = 1;
    2840        s00a_command_800CE778( work );
    
    source/enemy/think.c lines 2832–2840 at bf9189e · upstream ↗
    193    if ( new_alert_mode >= 0 && new_alert_mode != GM_AlertMode )
    ⋮
    195        if ( song_status == 0 )
    ⋮
    197            switch ( new_alert_mode )
    ⋮
    199            case ALERT_ACTIVE:
    200                if ( GM_AlertMode == ALERT_OFF )
    ⋮
    202                    GM_SeSet2( 0, 0x3F, SE_ALERT_SIREN );
    
    source/game/alert.c lines 193–204 at bf9189e · upstream ↗
    1039    s00a_command_800D018C( work );
    ⋮
    1043    s00a_command_800CFA94( work );
    ⋮
    1046    EnemyCommand.field_0x0C++;
    
    source/enemy/command.c lines 1039–1046 at bf9189e · upstream ↗
    24int DG_FrameRate = 2;
    
    source/libdg/dgd.c line 24 at bf9189e · upstream ↗
    77    else
    ⋮
    79        mts_wait_vbl( DG_FrameRate );
    
    source/libdg/dgd.c lines 77–79 at bf9189e · upstream ↗

    Checked against the evidence by its author, an AI model, 2026-10-22.

    Checked by a second AI model, 2026-10-22.

    In the claim ledger

  2. ^ abIn Metal Gear Solid Integral (SLPM-86247), the radar (draw_radar) draws the map only in ALERT_OFF. In ALERT_ACTIVE and ALERT_EVASION, and in ALERT_OFF while GM_GameStatus has STATE_CHAFF or STATE_JAMMING set (shown as ALERT_JAMMING), it draws a status panel (menu_radar_draw_state) in its place, playing SE_RADAR_JAMMED when jamming begins from ALERT_OFF; for alert and evasion the panel draws GM_AlertLevel as a gauge. When the panel ends, the map returns behind a sweep while a counter set to 93 falls by 2 per frame, about 47 frames (computed), with SE_RADAR_CHIME, which the decompilers' comment says plays when evasion or jamming ends. In ALERT_OFF, with no override function set, the radar isn't drawn in a duct (PLAYER_INTRUDE) or with the radar turned off in the options. On the map, each guard's cone comes from its sight: its facing, vision.length, and twice vision.angle as the width (s00a_command_800C9878).CodeFoxdieTeam/mgs_reversing
    How we know
    1038void draw_radar(MenuWork *work, u_long *ot)
    ⋮
    1046    alertLevel = GM_AlertLevel;
    1047    alertMode = GM_AlertMode;
    ⋮
    1054    if (alertMode == ALERT_OFF && gFn_radar_800AB48C == NULL)
    ⋮
    1056        if (GM_PlayerStatus & PLAYER_INTRUDE)
    ⋮
    1058            return;
    ⋮
    1061        if (GM_Configuration & GM_CONFIG_RADAR_OFF)
    ⋮
    1063            return;
    ⋮
    1074    else
    ⋮
    1076        if (alertMode == ALERT_OFF)
    ⋮
    1078            if (GM_GameStatus & (STATE_CHAFF | STATE_JAMMING))
    ⋮
    1080                alertMode = ALERT_JAMMING;
    ⋮
    
    source/menu/radar.c lines 1038–1170 at bf9189e · upstream ↗
    921void menu_radar_draw_state(MenuWork *work, u_long *ot, int radarMode, int alertLevel)
    ⋮
    930    switch (radarMode)
    ⋮
    932    case ALERT_JAMMING:
    ⋮
    943    default:
    944        draw_seg(work->prim, alertLevel, 3 - radarMode);
    
    source/menu/radar.c lines 921–946 at bf9189e · upstream ↗
    24void s00a_command_800C9878( WatcherWork* work )
    ⋮
    26    VISION     *vision = &work->vision;
    27    RADAR_SIGHT_PARAM *r_param   = &work->control.radar_param;
    ⋮
    29    r_param->dir = vision->facedir;
    30    r_param->dis = vision->length;
    31    r_param->range = vision->angle * 2;
    
    source/enemy/enemy.c lines 24–32 at bf9189e · upstream ↗

    Checked against the evidence by its author, an AI model, 2026-10-22.

    Checked by a second AI model, 2026-10-22.

    In the claim ledger

Sources

Code