Mechanic · environment · action-adventure
Wind
A world force with a direction and a strength that pushes or drives what moves through it.
On this page
Wind gives a game’s world a direction to move with or against. In The Legend of Zelda: The Wind Waker, the Wind’s Requiem sets one of eight directions1, and each room’s wind level sets the strength the sail feels2.
- Player-setThe Legend of Zelda: The Wind Waker (2002). The Wind's Requiem picks one of eight directions, 45° apart, kept in the save; each room's wind level sets the strength.1,2
Games
| Game | Year | How | Note |
|---|---|---|---|
| The Legend of Zelda: The Wind Waker | 2002 | Player-set | the Wind's Requiem picks one of eight directions, 45° apart, kept in the save; each room's wind level sets the strength |
| Super Mario Bros.: The Lost Levels | 1986 | Area push | a steady push to the right in some outdoor stretches, on average a quarter of Mario's walking speed |
Every claim about this mechanic, by game (5)
References
- ^ abIn the USA build, the wind-direction picker dOperate_wind_c (which the atlas reads as the Wind's Requiem's, from its TAKT_WIND sounds; "takt" is the baton) sets mDeg on opening from the current wind vector's yaw and then, with the stick pushed to at least 0.9, sets mDeg to one of eight compass values, 0 to 315 in 45-degree steps. A confirms it: windSet passes dKyw_tact_wind_set a pitch of 0 and a yaw of 180° − mDeg (0 gives −0x8000, 90 gives 0x4000, 270 gives −0x4000). dKyw_tact_wind_set stores both angles for the environment and in the save (dComIfGs_setWindX, setWindY) and sets the tact-wind flag; dKyw_wind_set then builds the wind vector as (cos pitch × cos yaw, sin pitch, cos pitch × sin yaw). dKyw_wind_init reloads the saved angles unless both are −1. B cancels the picker.Codezeldaret/tww
How we know
372 if (stick->getValueStick() >= 0.89999998f && fabs(stick_value) - fabs(field_0x8b8) >= 0.0) { 373 int stick_control = dOw_stickControl(field_0x8d0, stick->getAngleStick()); ⋮ 377 switch (stick_control) { 378 case 8: 379 if (mDeg != 315) { 380 field_0x8ca = 7; 381 mDeg = 315; 382 mDoAud_seStart(JA_SE_TAKT_WIND_CURSOR);
src/d/d_operate_wind.cpp lines 370–384 at cb24f55 · upstream ↗ 462void dOperate_wind_c::windSet() { 463 switch (mDeg) { 464 case 315: 465 dKyw_tact_wind_set(0, -0x6000); 466 break; 467 case 0: 468 dKyw_tact_wind_set(0, -0x8000); 469 break; 470 case 45: 471 dKyw_tact_wind_set(0, 0x6000); 472 break; 473 case 90: ⋮
src/d/d_operate_wind.cpp lines 462–488 at cb24f55 · upstream ↗ 613 cXyz* wind_vec = dKyw_get_wind_vec(); 614 s16 temp_r3 = cM_atan2s(wind_vec->x, wind_vec->z) + 0x8000; 615 mDeg = dOw_angleRegular(((180.0f * temp_r3) / (f32)0x8000) - 90.0f); 616 arrowRotate(&field_0xec, mDeg);
src/d/d_operate_wind.cpp lines 613–616 at cb24f55 · upstream ↗ 661 if (CPad_CHECK_TRIG_A(0)) { 662 windSet(); 663 dComIfGp_setOperateWindChangeOff(); 664 } else if (CPad_CHECK_TRIG_B(0)) { 665 dComIfGp_setOperateWindCancelOff();
src/d/d_operate_wind.cpp lines 661–666 at cb24f55 · upstream ↗ 1328void dKyw_tact_wind_set(s16 i_windX, s16 i_windY) { ⋮ 1332 env_light.mWind.mTactWindAngleX = i_windX; 1333 env_light.mWind.mTactWindAngleY = i_windY; 1334 dComIfGs_setWindX(i_windX); 1335 dComIfGs_setWindY(i_windY); ⋮ 1338 env_light.mWind.mTactWindAngleFlags = 1;
src/d/d_kankyo_wether.cpp lines 1328–1338 at cb24f55 · upstream ↗ 1010 } else if (g_env_light.mWind.mTactWindAngleFlags != 0) { 1011 tact_wind_x = g_env_light.mWind.mTactWindAngleX; 1012 tact_wind_y = g_env_light.mWind.mTactWindAngleY; ⋮ 1018 wind_vec.x = cM_scos(tact_wind_x) * cM_scos(tact_wind_y); 1019 wind_vec.y = cM_ssin(tact_wind_x); 1020 wind_vec.z = cM_scos(tact_wind_x) * cM_ssin(tact_wind_y);
src/d/d_kankyo_wether.cpp lines 1010–1020 at cb24f55 · upstream ↗ 967 if (dComIfGs_getWindX() == -1 && dComIfGs_getWindY() == -1) { 968 g_env_light.mWind.mTactWindAngleFlags = 0; ⋮ 972 g_env_light.mWind.mTactWindAngleFlags = 1; 973 g_env_light.mWind.mTactWindAngleX = dComIfGs_getWindX(); 974 g_env_light.mWind.mTactWindAngleY = dComIfGs_getWindY();
src/d/d_kankyo_wether.cpp lines 967–974 at cb24f55 · upstream ↗ Checked against the evidence by its author, an AI model, 2026-10-22.
Checked by a second AI model, 2026-10-22.
- ^ abIn the USA build, dKyw_wind_set, when no actor has set a wind vector override (mpWindVecOverride), takes the wind's strength from the room's file list (dStage_FileList_dt_GlobalWindLevel): level 0 gives 0.3, level 1 gives 0.6, level 2 gives 0.9, any other level 0. A custom wind power above 0 replaces it, an event wind setting of 2 makes it 0, and it is capped at 1. While mInitAnimTimer is nonzero the wind vector and power jump to the new values; otherwise each call moves each vector component a tenth of the way (at most 2, at least 0.001) and the power a tenth of the way (at most 1, at least 0.005). Since the boat, in the decompilers' not-yet-matching C++ for d_a_ship (procSteerMove), divides the power by 0.5 and caps it at 1, a level-0 room tops out at 0.6 of the boat's 55, 33 units an update, and levels 1 and 2 at the full 55 (computed, once the power has settled).Codezeldaret/twwrevised
How we know
990 if (g_env_light.mWind.mpWindVecOverride != NULL) { 991 wind_vec = *g_env_light.mWind.mpWindVecOverride; 992 strength = g_env_light.mWind.mWindStrengthOverride; ⋮ 1022 if (fili_p != NULL) { 1023 wind_level = dStage_FileList_dt_GlobalWindLevel(fili_p); ⋮ 1026 switch (wind_level) { 1027 case 0: 1028 strength = 0.3f; 1029 break; 1030 case 1: 1031 strength = 0.6f; 1032 break; ⋮
src/d/d_kankyo_wether.cpp lines 990–1040 at cb24f55 · upstream ↗ 1062 if (g_env_light.mWind.mCustomWindPower > 0.0f) { 1063 strength = g_env_light.mWind.mCustomWindPower; ⋮ 1067 if (g_env_light.mWind.mEvtWindSet == 2) { 1068 strength = 0.0f; ⋮ 1071 if (strength > 1.0f) { 1072 strength = 1.0f; ⋮ 1075 if (g_env_light.mInitAnimTimer != 0) { 1076 g_env_light.mWind.mWindVec = wind_vec; 1077 g_env_light.mWind.mWindPower = strength; 1078 } else { 1079 f32 scale = 0.1f; 1080 cLib_addCalc(&g_env_light.mWind.mWindVec.x, wind_vec.x, scale, 2.0f, 0.001f); ⋮
src/d/d_kankyo_wether.cpp lines 1062–1084 at cb24f55 · upstream ↗ 1596 f32 targetSpeed = *dKyw_get_wind_power() / 0.5f;src/d/actor/d_a_ship.cpp line 1596 at cb24f55 · upstream ↗ Checked against the evidence by its author, an AI model, 2026-10-22.
Revised after a check by a second AI model, 2026-10-22.
Sources
Code
- zeldaret. 2026. “tww: a decompilation of The Legend of Zelda: The Wind Waker (zeldaret/tww).” Commit cb24f55. zeldaret/tww @ cb24f55 · licence, all uses