mirror of
https://github.com/Ninjdai1/pokeemerald.git
synced 2025-02-20 19:23:38 +01:00
Merge pull request #1803 from abaresk/thunder
Add more documentation to thunder weather effect
This commit is contained in:
commit
fad92ec906
@ -77,12 +77,12 @@ struct Weather
|
||||
u8 snowflakeSpriteCount;
|
||||
u8 targetSnowflakeSpriteCount;
|
||||
// Thunderstorm
|
||||
u16 thunderDelay;
|
||||
u16 thunderCounter;
|
||||
u16 thunderTimer; // general-purpose timer for state transitions
|
||||
u16 thunderSETimer; // timer for thunder sound effect
|
||||
bool8 thunderAllowEnd;
|
||||
bool8 thunderSkipShort;
|
||||
u8 thunderShortRetries;
|
||||
bool8 thunderTriggered;
|
||||
bool8 thunderLongBolt; // true if this cycle will end in a long lightning bolt
|
||||
u8 thunderShortBolts; // the number of short bolts this cycle
|
||||
bool8 thunderEnqueued;
|
||||
// Horizontal fog
|
||||
u16 fogHScrollPosX;
|
||||
u16 fogHScrollCounter;
|
||||
|
@ -1014,29 +1014,29 @@ static void UpdateSnowflakeSprite(struct Sprite *sprite)
|
||||
enum {
|
||||
// This block of states is run only once
|
||||
// when first setting up the thunderstorm
|
||||
TSTORM_STATE_LOAD_RAIN,
|
||||
TSTORM_STATE_CREATE_RAIN,
|
||||
TSTORM_STATE_INIT_RAIN,
|
||||
TSTORM_STATE_WAIT_CHANGE,
|
||||
THUNDER_STATE_LOAD_RAIN,
|
||||
THUNDER_STATE_CREATE_RAIN,
|
||||
THUNDER_STATE_INIT_RAIN,
|
||||
THUNDER_STATE_WAIT_CHANGE,
|
||||
|
||||
// The thunderstorm loops through these states,
|
||||
// not necessarily in order.
|
||||
TSTORM_STATE_LOOP_START,
|
||||
TSTORM_STATE_LOOP_WAIT,
|
||||
TSTORM_STATE_INIT_THUNDER_SHORT_1,
|
||||
TSTORM_STATE_INIT_THUNDER_SHORT_2,
|
||||
TSTORM_STATE_TRY_THUNDER_SHORT,
|
||||
TSTORM_STATE_TRY_NEW_THUNDER,
|
||||
TSTORM_STATE_WAIT_THUNDER_SHORT,
|
||||
TSTORM_STATE_INIT_THUNDER_LONG,
|
||||
TSTORM_STATE_WAIT_THUNDER_LONG,
|
||||
TSTORM_STATE_FADE_THUNDER_LONG,
|
||||
TSTORM_STATE_END_THUNDER_LONG,
|
||||
THUNDER_STATE_NEW_CYCLE,
|
||||
THUNDER_STATE_NEW_CYCLE_WAIT,
|
||||
THUNDER_STATE_INIT_CYCLE_1,
|
||||
THUNDER_STATE_INIT_CYCLE_2,
|
||||
THUNDER_STATE_SHORT_BOLT,
|
||||
THUNDER_STATE_TRY_NEW_BOLT,
|
||||
THUNDER_STATE_WAIT_BOLT_SHORT,
|
||||
THUNDER_STATE_INIT_BOLT_LONG,
|
||||
THUNDER_STATE_WAIT_BOLT_LONG,
|
||||
THUNDER_STATE_FADE_BOLT_LONG,
|
||||
THUNDER_STATE_END_BOLT_LONG,
|
||||
};
|
||||
|
||||
void Thunderstorm_InitVars(void)
|
||||
{
|
||||
gWeatherPtr->initStep = TSTORM_STATE_LOAD_RAIN;
|
||||
gWeatherPtr->initStep = THUNDER_STATE_LOAD_RAIN;
|
||||
gWeatherPtr->weatherGfxLoaded = FALSE;
|
||||
gWeatherPtr->rainSpriteVisibleCounter = 0;
|
||||
gWeatherPtr->rainSpriteVisibleDelay = 4;
|
||||
@ -1045,7 +1045,7 @@ void Thunderstorm_InitVars(void)
|
||||
gWeatherPtr->targetColorMapIndex = 3;
|
||||
gWeatherPtr->colorMapStepDelay = 20;
|
||||
gWeatherPtr->weatherGfxLoaded = FALSE; // duplicate assignment
|
||||
gWeatherPtr->thunderTriggered = FALSE;
|
||||
gWeatherPtr->thunderEnqueued = FALSE;
|
||||
SetRainStrengthFromSoundEffect(SE_THUNDERSTORM);
|
||||
}
|
||||
|
||||
@ -1061,11 +1061,11 @@ void Thunderstorm_InitAll(void)
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
static void UpdateThunderSound(void);
|
||||
static void SetThunderCounter(u16);
|
||||
static void EnqueueThunder(u16);
|
||||
|
||||
void Downpour_InitVars(void)
|
||||
{
|
||||
gWeatherPtr->initStep = TSTORM_STATE_LOAD_RAIN;
|
||||
gWeatherPtr->initStep = THUNDER_STATE_LOAD_RAIN;
|
||||
gWeatherPtr->weatherGfxLoaded = FALSE;
|
||||
gWeatherPtr->rainSpriteVisibleCounter = 0;
|
||||
gWeatherPtr->rainSpriteVisibleDelay = 4;
|
||||
@ -1084,110 +1084,119 @@ void Downpour_InitAll(void)
|
||||
Thunderstorm_Main();
|
||||
}
|
||||
|
||||
// In a given cycle, there will be some shorter bolts of lightning, potentially
|
||||
// followed by a longer bolt. As a "regex", the pattern is:
|
||||
// (SHORT_BOLT){1,2}(LONG_BOLT)?
|
||||
//
|
||||
// Thunder only plays on the final bolt of the cycle.
|
||||
void Thunderstorm_Main(void)
|
||||
{
|
||||
UpdateThunderSound();
|
||||
switch (gWeatherPtr->initStep)
|
||||
{
|
||||
case TSTORM_STATE_LOAD_RAIN:
|
||||
case THUNDER_STATE_LOAD_RAIN:
|
||||
LoadRainSpriteSheet();
|
||||
gWeatherPtr->initStep++;
|
||||
break;
|
||||
case TSTORM_STATE_CREATE_RAIN:
|
||||
case THUNDER_STATE_CREATE_RAIN:
|
||||
if (!CreateRainSprite())
|
||||
gWeatherPtr->initStep++;
|
||||
break;
|
||||
case TSTORM_STATE_INIT_RAIN:
|
||||
case THUNDER_STATE_INIT_RAIN:
|
||||
if (!UpdateVisibleRainSprites())
|
||||
{
|
||||
gWeatherPtr->weatherGfxLoaded = TRUE;
|
||||
gWeatherPtr->initStep++;
|
||||
}
|
||||
break;
|
||||
case TSTORM_STATE_WAIT_CHANGE:
|
||||
case THUNDER_STATE_WAIT_CHANGE:
|
||||
if (gWeatherPtr->palProcessingState != WEATHER_PAL_STATE_CHANGING_WEATHER)
|
||||
gWeatherPtr->initStep = TSTORM_STATE_INIT_THUNDER_SHORT_1;
|
||||
gWeatherPtr->initStep = THUNDER_STATE_INIT_CYCLE_1;
|
||||
break;
|
||||
case TSTORM_STATE_LOOP_START:
|
||||
case THUNDER_STATE_NEW_CYCLE:
|
||||
gWeatherPtr->thunderAllowEnd = TRUE;
|
||||
gWeatherPtr->thunderDelay = (Random() % 360) + 360;
|
||||
gWeatherPtr->thunderTimer = (Random() % 360) + 360;
|
||||
gWeatherPtr->initStep++;
|
||||
// fall through
|
||||
case TSTORM_STATE_LOOP_WAIT:
|
||||
// Wait between 360-720 frames before trying thunder again
|
||||
if (--gWeatherPtr->thunderDelay == 0)
|
||||
case THUNDER_STATE_NEW_CYCLE_WAIT:
|
||||
// Wait between 360-720 frames before starting a new cycle.
|
||||
if (--gWeatherPtr->thunderTimer == 0)
|
||||
gWeatherPtr->initStep++;
|
||||
break;
|
||||
case TSTORM_STATE_INIT_THUNDER_SHORT_1:
|
||||
case THUNDER_STATE_INIT_CYCLE_1:
|
||||
gWeatherPtr->thunderAllowEnd = TRUE;
|
||||
gWeatherPtr->thunderSkipShort = Random() % 2;
|
||||
gWeatherPtr->thunderLongBolt = Random() % 2;
|
||||
gWeatherPtr->initStep++;
|
||||
break;
|
||||
case TSTORM_STATE_INIT_THUNDER_SHORT_2:
|
||||
gWeatherPtr->thunderShortRetries = (Random() & 1) + 1;
|
||||
case THUNDER_STATE_INIT_CYCLE_2:
|
||||
gWeatherPtr->thunderShortBolts = (Random() & 1) + 1;
|
||||
gWeatherPtr->initStep++;
|
||||
// fall through
|
||||
case TSTORM_STATE_TRY_THUNDER_SHORT:
|
||||
case THUNDER_STATE_SHORT_BOLT:
|
||||
// Short bolt of lightning strikes.
|
||||
ApplyWeatherColorMapIfIdle(19);
|
||||
if (!gWeatherPtr->thunderSkipShort && gWeatherPtr->thunderShortRetries == 1)
|
||||
SetThunderCounter(20); // Do short thunder
|
||||
// If final lightning bolt, enqueue thunder.
|
||||
if (!gWeatherPtr->thunderLongBolt && gWeatherPtr->thunderShortBolts == 1)
|
||||
EnqueueThunder(20);
|
||||
|
||||
gWeatherPtr->thunderDelay = (Random() % 3) + 6;
|
||||
gWeatherPtr->thunderTimer = (Random() % 3) + 6;
|
||||
gWeatherPtr->initStep++;
|
||||
break;
|
||||
case TSTORM_STATE_TRY_NEW_THUNDER:
|
||||
if (--gWeatherPtr->thunderDelay == 0)
|
||||
case THUNDER_STATE_TRY_NEW_BOLT:
|
||||
if (--gWeatherPtr->thunderTimer == 0)
|
||||
{
|
||||
// Short bolt of lightning ends.
|
||||
ApplyWeatherColorMapIfIdle(3);
|
||||
gWeatherPtr->thunderAllowEnd = TRUE;
|
||||
if (--gWeatherPtr->thunderShortRetries != 0)
|
||||
if (--gWeatherPtr->thunderShortBolts != 0)
|
||||
{
|
||||
// Try a short thunder again
|
||||
gWeatherPtr->thunderDelay = (Random() % 16) + 60;
|
||||
gWeatherPtr->initStep = TSTORM_STATE_WAIT_THUNDER_SHORT;
|
||||
// Wait a little, then do another short bolt.
|
||||
gWeatherPtr->thunderTimer = (Random() % 16) + 60;
|
||||
gWeatherPtr->initStep = THUNDER_STATE_WAIT_BOLT_SHORT;
|
||||
}
|
||||
else if (!gWeatherPtr->thunderSkipShort)
|
||||
else if (!gWeatherPtr->thunderLongBolt)
|
||||
{
|
||||
// No more thunder, restart loop
|
||||
gWeatherPtr->initStep = TSTORM_STATE_LOOP_START;
|
||||
// No more bolts, restart loop.
|
||||
gWeatherPtr->initStep = THUNDER_STATE_NEW_CYCLE;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Set up long thunder
|
||||
gWeatherPtr->initStep = TSTORM_STATE_INIT_THUNDER_LONG;
|
||||
// Set up long bolt.
|
||||
gWeatherPtr->initStep = THUNDER_STATE_INIT_BOLT_LONG;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case TSTORM_STATE_WAIT_THUNDER_SHORT:
|
||||
if (--gWeatherPtr->thunderDelay == 0)
|
||||
gWeatherPtr->initStep = TSTORM_STATE_TRY_THUNDER_SHORT;
|
||||
case THUNDER_STATE_WAIT_BOLT_SHORT:
|
||||
if (--gWeatherPtr->thunderTimer == 0)
|
||||
gWeatherPtr->initStep = THUNDER_STATE_SHORT_BOLT;
|
||||
break;
|
||||
case TSTORM_STATE_INIT_THUNDER_LONG:
|
||||
gWeatherPtr->thunderDelay = (Random() % 16) + 60;
|
||||
case THUNDER_STATE_INIT_BOLT_LONG:
|
||||
gWeatherPtr->thunderTimer = (Random() % 16) + 60;
|
||||
gWeatherPtr->initStep++;
|
||||
break;
|
||||
case TSTORM_STATE_WAIT_THUNDER_LONG:
|
||||
if (--gWeatherPtr->thunderDelay == 0)
|
||||
case THUNDER_STATE_WAIT_BOLT_LONG:
|
||||
if (--gWeatherPtr->thunderTimer == 0)
|
||||
{
|
||||
// Do long thunder
|
||||
SetThunderCounter(100);
|
||||
// Do long bolt. Enqueue thunder with a potentially longer delay.
|
||||
EnqueueThunder(100);
|
||||
ApplyWeatherColorMapIfIdle(19);
|
||||
gWeatherPtr->thunderDelay = (Random() & 0xF) + 30;
|
||||
gWeatherPtr->thunderTimer = (Random() & 0xF) + 30;
|
||||
gWeatherPtr->initStep++;
|
||||
}
|
||||
break;
|
||||
case TSTORM_STATE_FADE_THUNDER_LONG:
|
||||
if (--gWeatherPtr->thunderDelay == 0)
|
||||
case THUNDER_STATE_FADE_BOLT_LONG:
|
||||
if (--gWeatherPtr->thunderTimer == 0)
|
||||
{
|
||||
// Fade long bolt out over time.
|
||||
ApplyWeatherColorMapIfIdle_Gradual(19, 3, 5);
|
||||
gWeatherPtr->initStep++;
|
||||
}
|
||||
break;
|
||||
case TSTORM_STATE_END_THUNDER_LONG:
|
||||
case THUNDER_STATE_END_BOLT_LONG:
|
||||
if (gWeatherPtr->palProcessingState == WEATHER_PAL_STATE_IDLE)
|
||||
{
|
||||
gWeatherPtr->thunderAllowEnd = TRUE;
|
||||
gWeatherPtr->initStep = TSTORM_STATE_LOOP_START;
|
||||
gWeatherPtr->initStep = THUNDER_STATE_NEW_CYCLE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -1218,7 +1227,7 @@ bool8 Thunderstorm_Finish(void)
|
||||
if (!UpdateVisibleRainSprites())
|
||||
{
|
||||
DestroyRainSprites();
|
||||
gWeatherPtr->thunderTriggered = 0;
|
||||
gWeatherPtr->thunderEnqueued = FALSE;
|
||||
gWeatherPtr->finishStep++;
|
||||
return FALSE;
|
||||
}
|
||||
@ -1229,20 +1238,21 @@ bool8 Thunderstorm_Finish(void)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void SetThunderCounter(u16 max)
|
||||
// Enqueue a thunder sound effect for at most `waitFrames` frames from now.
|
||||
static void EnqueueThunder(u16 waitFrames)
|
||||
{
|
||||
if (!gWeatherPtr->thunderTriggered)
|
||||
if (!gWeatherPtr->thunderEnqueued)
|
||||
{
|
||||
gWeatherPtr->thunderCounter = Random() % max;
|
||||
gWeatherPtr->thunderTriggered = TRUE;
|
||||
gWeatherPtr->thunderSETimer = Random() % waitFrames;
|
||||
gWeatherPtr->thunderEnqueued = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
static void UpdateThunderSound(void)
|
||||
{
|
||||
if (gWeatherPtr->thunderTriggered == TRUE)
|
||||
if (gWeatherPtr->thunderEnqueued == TRUE)
|
||||
{
|
||||
if (gWeatherPtr->thunderCounter == 0)
|
||||
if (gWeatherPtr->thunderSETimer == 0)
|
||||
{
|
||||
if (IsSEPlaying())
|
||||
return;
|
||||
@ -1252,11 +1262,11 @@ static void UpdateThunderSound(void)
|
||||
else
|
||||
PlaySE(SE_THUNDER2);
|
||||
|
||||
gWeatherPtr->thunderTriggered = FALSE;
|
||||
gWeatherPtr->thunderEnqueued = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
gWeatherPtr->thunderCounter--;
|
||||
gWeatherPtr->thunderSETimer--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user