Skip to content
Alex Demarest edited this page Aug 7, 2023 · 15 revisions

Fix Snow Weather

Credit to daniilS for the binary implementation this is based off of

In vanilla emerald (and Fire Red!) the WEATHER_SNOW is broken and will only emit a few snowflakes before stopping. Let's fix it!

For starters, open src/field_weather_effect.c

Increase the number of snowflakes (optional)

If you want to have the snow be heavier (or lighter), find Snow_InitVars and edit the line gWeatherPtr->targetSnowflakeSpriteCount = 16; to a value of your choosing.

Make the snowflakes generate as you walk around

Find the function UpdateSnowflakeSprite and delete the following chunk of code therein:

static void UpdateSnowflakeSprite(struct Sprite *sprite)
{
    s16 x;
    s16 y;

    sprite->tPosY += sprite->tDeltaY;
    sprite->y = sprite->tPosY >> 7;
    sprite->tWaveIndex += sprite->tWaveDelta;
    sprite->tWaveIndex &= 0xFF;
    sprite->x2 = gSineTable[sprite->tWaveIndex] / 64;

    x = (sprite->x + sprite->centerToCornerVecX + gSpriteCoordOffsetX) & 0x1FF;
    if (x & 0x100)
        x |= -0x100;

    if (x < -3)
        sprite->x = 242 - (gSpriteCoordOffsetX + sprite->centerToCornerVecX);
    else if (x > 242)
        sprite->x = -3 - (gSpriteCoordOffsetX + sprite->centerToCornerVecX);

-   y = (sprite->y + sprite->centerToCornerVecY + gSpriteCoordOffsetY) & 0xFF;
-   if (y > 163 && y < 171)
-   {
-       sprite->y = 250 - (gSpriteCoordOffsetY + sprite->centerToCornerVecY);
-       sprite->tPosY = sprite->y * 128;
-       sprite->tFallCounter = 0;
-       sprite->tFallDuration = 220;
-   }
-   else if (y > 242 && y < 250)
-   {
-       sprite->y = 163;
-       sprite->tPosY = sprite->y * 128;
-       sprite->tFallCounter = 0;
-       sprite->tFallDuration = 220;
-       sprite->invisible = TRUE;
-       sprite->callback = WaitSnowflakeSprite;
-   }
-   if (++sprite->tFallCounter == sprite->tFallDuration)
-   {
-       InitSnowflakeSpriteMovement(sprite);
-       sprite->y = 250;
-       sprite->invisible = TRUE;
-       sprite->callback = WaitSnowflakeSprite;
-   }
}

Stop the snow from disappearing

Find the function WaitSnowflakeSprite and alter it as follows:

 static void WaitSnowflakeSprite(struct Sprite *sprite)
 {
-    if (gWeatherPtr->snowflakeTimer > 18)
+    if (++gWeatherPtr->snowflakeTimer > 18)
     {
         sprite->invisible = FALSE;
         sprite->callback = UpdateSnowflakeSprite;
         sprite->pos1.y = 250 - (gSpriteCoordOffsetY + sprite->centerToCornerVecY);
         sprite->tPosY = sprite->pos1.y * 128;
         gWeatherPtr->snowflakeTimer = 0;
     }
 }

Fix snow spawning upon returning to the overworld

The snow is spawned based on gSpriteCoordOffsetX/Y, which is not updated until after the weather is initialized. To fix this, open src/field_weather.c.

  1. First, add #include "field_camera.h" to the top of the file somewhere.
  2. Next, add UpdateCameraPanning(); before sWeatherFuncs[gWeatherPtr->currWeather].initAll(); in Task_WeatherInit

Hail on Overworld

Credit to Samu, To allow hail on when snow is present, go to src/battle_util.c Search for switch (GetCurrentWeather()) (Around line 2504) and input these code below the WEATHER_DROUGHT code.

                case WEATHER_SNOW:
                    if (!(gBattleWeather & B_WEATHER_HAIL))
                    {
                        gBattleWeather = B_WEATHER_HAIL;
                        gBattleScripting.animArg1 = B_ANIM_HAIL_CONTINUES;
                        gBattleScripting.battler = battler;
                        effect++;
                    }
                    break;

The only thing left to do is to change the text string assigned to the snowy weather when it's casted in battle.

Head over to src/battle_message.c and search for const u16 gWeatherStartsStringIds.

Once there, make the following change:

const u16 gWeatherStartsStringIds[] =
{
    [WEATHER_NONE]               = STRINGID_ITISRAINING,
    [WEATHER_SUNNY_CLOUDS]       = STRINGID_ITISRAINING,
    [WEATHER_SUNNY]              = STRINGID_ITISRAINING,
    [WEATHER_RAIN]               = STRINGID_ITISRAINING,
-   [WEATHER_SNOW]               = STRINGID_ITISRAINING,
+   [WEATHER_SNOW]               = STRINGID_STARTEDHAIL,
    [WEATHER_RAIN_THUNDERSTORM]  = STRINGID_ITISRAINING,
    [WEATHER_FOG_HORIZONTAL]     = STRINGID_ITISRAINING,
    [WEATHER_VOLCANIC_ASH]       = STRINGID_ITISRAINING,
    [WEATHER_SANDSTORM]          = STRINGID_SANDSTORMISRAGING,
    [WEATHER_FOG_DIAGONAL]       = STRINGID_ITISRAINING,
    [WEATHER_UNDERWATER]         = STRINGID_ITISRAINING,
    [WEATHER_SHADE]              = STRINGID_ITISRAINING,
    [WEATHER_DROUGHT]            = STRINGID_SUNLIGHTSTRONG,
    [WEATHER_SNOW]               = STRINGID_STARTEDHAIL,
    [WEATHER_DOWNPOUR]           = STRINGID_ITISRAINING,
    [WEATHER_UNDERWATER_BUBBLES] = STRINGID_ITISRAINING,
    [WEATHER_ABNORMAL]           = STRINGID_ITISRAINING
};
Clone this wiki locally