Among the special effects, the RO client supports few that can be classified as seasonal weather. These include snow, sakura blossom and autumn leaves. Until around 2004, the RO client had an additional special effect for rain, which has since been removed from the client. This article provides an overview over how this effect looked like and worked internally. Before you continue reading, read the disclaimer first. If you find a mistake or have a suggestion, you can contact me in Discord.
The rain special effect (EF_RAIN) has the ID 161 and is composed of two primitives. First primitive are white lines falling from height of 200 units above ground at the current position towards ground at random positions (+/-100, +/-50) while taking the 3D view into account (i.e. the effect follows changes camera). The second primitive is a texture named rain_gnd.tga which is fading-in and out on the ground and also displayed semi-transparent rushing in the Z direction. There is no sound effect associated.
Following is the code that was used to construct the effect, reconstructed from 2004-04-19aSakexe.exe assembly.
enum
{
PP_3DLINE = 0x14,
PP_3DTEXTURE_NOMASTER = 0x16,
};
void __stdcall CRagEffect::Rain() /* 0x55d9e0 */
{
struct vector_3d nullVector = { 0.0f, 0.0f, 0.0f };
CWorld* world;
world = g_modeMgr.GetGameMode()->m_world;
this->m_pos = world->m_player->m_pos;
if ( this->m_duration - this->m_stateCnt > 40 )
{
g_prim = this->LaunchEffectPrim(PP_3DLINE, nullVector);
g_prim->m_deltaPos2 = nullVector;
g_prim->m_duration = 40;
g_prim->m_type = PP_3DLINE;
g_prim->m_pos = this->m_master->m_pos;
g_prim->m_pos.y -= world->m_attr->GetHeight(this->m_pos.x, this->m_pos.z) + 200.0;
g_prim->m_pos.x += (float)( ( rand() % 200 ) - 100 );
g_prim->m_pos.z += (float)( ( rand() % 100 ) - 50 );
this->m_pos = g_prim->m_pos;
this->m_pos.y = world->m_attr->GetHeight(this->m_pos.x, this->m_pos.z);
g_prim = this->LaunchEffectPrim(PP_3DTEXTURE_NOMASTER, nullVector);
g_prim->m_duration = 40;
g_prim->m_roll = 90.0f;
g_prim->m_speed = 0.0f;
g_prim->m_accel = 0.0f;
g_prim->m_widthSize = 30.0f;
g_prim->m_heightSize = 70.0f;
g_prim->m_heightSpeed = 0.0f;
g_prim->m_widthSpeed = 0.0f;
g_prim->m_alpha = 0.0f;
g_prim->m_maxAlpha = 255.0f;
g_prim->m_alphaSpeed = g_prim->m_maxAlpha*0.025;
g_prim->m_texture = new CTexture*[g_prim->m_totalTexture];
g_prim->m_texture[0] = g_texMgr.GetTexture("effect\\rain_gnd.tga", 0);
this->m_pos = world->m_player->m_pos;
if ( this->m_duration - this->m_stateCnt > 300 )
{
g_prim = this->LaunchEffectPrim(PP_3DLINE, nullVector);
g_prim->m_deltaPos2 = nullVector;
g_prim->m_duration = 40;
g_prim->m_type = PP_3DLINE;
g_prim->m_pos = this->m_master->m_pos;
g_prim->m_pos.y -= world->m_attr->GetHeight(this->m_pos.x, this->m_pos.z) + 200.0;
g_prim->m_pos.x += (float)( ( rand() % 200 ) - 100 );
g_prim->m_pos.z += (float)( ( rand() % 100 ) - 50 );
this->m_pos = g_prim->m_pos;
this->m_pos.y = world->m_attr->GetHeight(this->m_pos.x, this->m_pos.z);
g_prim = this->LaunchEffectPrim(PP_3DTEXTURE_NOMASTER, nullVector);
g_prim->m_duration = 40;
g_prim->m_roll = 90.0f;
g_prim->m_speed = 5.0f;
g_prim->m_accel = 0.0f;
g_prim->m_widthSize = 30.0f;
g_prim->m_heightSize = 70.0f;
g_prim->m_heightSpeed = 0.0f;
g_prim->m_widthSpeed = 0.0f;
g_prim->m_alpha = 0.0f;
g_prim->m_maxAlpha = 255.0f;
g_prim->m_alphaSpeed = g_prim->m_maxAlpha*0.025;
g_prim->m_texture = new CTexture*[g_prim->m_totalTexture];
g_prim->m_texture[0] = g_texMgr.GetTexture("effect\\rain_gnd.tga", 0);
}
}
}
The texture rain_gnd.tga is longer available in the current game data and its visual is unknown to the author; it may have been a rain drop, vapor or water spray. As for reasons why the effect has been removed, the dense nature of the effect suggests, that it may have been removed for performance reasons, as then-current hardware was struggling with effect-dense scenes like WoE.
These videos illustrate how the effect shows in the 2004-04-19aSakexe.exe:
This document is supposed to serve for general educational purposes and is provided AS IS, without warranty of ANY KIND, either expressed or implied, including but not limited to the implied warranties of merchantability and/or fitness for a particular purpose. The author cannot be made liable for actions, that can arise from the direct or indirect use of this document, including but not limited to modifications of the RO client or running private RO servers. The author cannot be made liable for ANY KIND of damages on software or hardware, that may arise from, including but not limited to use of this document, the mentioned software or websites contents this document links to. The author is not affiliated, associated, authorized, maintained, sponsored, endorsed by, or in any way officially connected with Gravity Co., Ltd., or any of its subsidiaries or its affiliates. This is an independent project. The official Gravity Co., Ltd. website can be found at https://gravity.co.kr/.
Gravity Co., Ltd. & Lee Myoungjin.