From ff30729baa0d1c284fba2132cf38e8eeea440643 Mon Sep 17 00:00:00 2001 From: ragnarok-clanker Date: Fri, 30 Oct 2026 02:29:36 +0000 Subject: [PATCH] Decompile 8 functions in Source/Contents/Effects/EffectPoint.h, Source/Contents/Effects/HealSpEffect.cpp, ... Batch #4130 by youko: 0 byte-identical, 8 confirmed by peer review. - fn_18910 CLevel150Effect::AddBubbleRing: logic confirmed by peer review - fn_18915 CLevel150Effect::Slot03: logic confirmed by peer review - fn_18916 CLevel150Effect::Slot04: logic confirmed by peer review - fn_18921 CLevel150SubEffect::Init: logic confirmed by peer review - fn_18925 CLevel150SubEffect::Slot03: logic confirmed by peer review - fn_18929 CMagicFloorEffect::AddFloors: logic confirmed by peer review - fn_18930 CMagicFloorEffect::AddClouds: logic confirmed by peer review - fn_18935 CMagicFloorEffect::Slot03: logic confirmed by peer review Peer-reviewed-by: eAthena, alisonrag, OrangeCat Accepted without human review: peers confirmed the logic ("same" ahead by at least 3, with 70% of the votes). --- Source/Contents/Effects/Level150Effect.cpp | 260 +++++++++++++++++++ Source/Contents/Effects/MagicFloorEffect.cpp | 184 +++++++++++++ 2 files changed, 444 insertions(+) diff --git a/Source/Contents/Effects/Level150Effect.cpp b/Source/Contents/Effects/Level150Effect.cpp index 2fc54bf9..57132f5d 100644 --- a/Source/Contents/Effects/Level150Effect.cpp +++ b/Source/Contents/Effects/Level150Effect.cpp @@ -47,6 +47,87 @@ void CLevel150Effect::Slot08(int red, int green, int blue) { } // OFFSET: 0x00B46680 +// FUNCTION: fn_18910 +void CLevel150Effect::AddBubbleRing(int alphaOffset) { + const int effectId = this->id; + for (int ring = 0; ring < 4; ++ring) { + for (int segment = 0; segment <= 21; ++segment) { + CParticle* particle = CreateParticle(reinterpret_cast(this->position), 13); + if (!particle) { + continue; + } + + particle->SetTexture(FormatOwnedString("effect\\W_bubble%02d.tga", segment + 1).c_str()); + particle->unknown_0004 = this->id; + particle->unknown_0010 = ring; + particle->unknown_000C = segment; + particle->unknown_0008 = 4; + particle->alpha = alphaOffset + (3 - ring) * 45; + + if (effectId == 978) { + particle->SetColor(100, 100, 255); + } else if (effectId == 1022) { + particle->SetColor(255, 255, 100); + } else if (effectId == 1226) { + particle->SetColor(255, 155, 155); + } else if (effectId == 2275) { + particle->SetColor(255, 155, 0); + } + + *reinterpret_cast(&particle->unknown_00C4) = static_cast((ring + 2) * 90 % 360); + particle->unknown_0050 = 360; + particle->unknown_00C0 = 30.0f - static_cast(ring); + particle->scale = 3.5f; + particle->unknown_004C = 80; + particle->unknown_0054 = 0.0f; + particle->unknown_00E8 = 0; + + const int index = particle->unknown_000C; + const float radius = particle->unknown_00C0 * g_sinTable[index * 9] * 0.15f + particle->unknown_00C0; + const int direction = + static_cast(static_cast(static_cast(static_cast(particle->unknown_0050) / 20.0f) * index) + + *reinterpret_cast(&particle->unknown_00C4)) % + 360; + const int tilt = particle->unknown_004C; + const float spread = radius * g_cosTable[tilt]; + const float height = radius * g_sinTable[tilt]; + const float cosine = g_cosTable[direction]; + const float sine = g_sinTable[direction]; + + EffectPoint points[2]; + points[0].x = cosine * particle->scale; + points[0].y = 5.0f; + points[0].z = sine * particle->scale; + points[1].x = points[0].x + spread * cosine; + points[1].y = 5.0f - height; + points[1].z = points[0].z + spread * sine; + + particle->vertices[3].x = points[0].x; + particle->vertices[3].y = points[0].y; + particle->vertices[3].z = points[0].z; + particle->vertices[1].x = points[1].x; + particle->vertices[1].y = points[1].y; + particle->vertices[1].z = points[1].z; + + if (index != 0) { + particle->vertices[0].x = this->lastPoints[1].x; + particle->vertices[0].y = this->lastPoints[1].y; + particle->vertices[0].z = this->lastPoints[1].z; + particle->vertices[2].x = this->lastPoints[0].x; + particle->vertices[2].y = this->lastPoints[0].y; + particle->vertices[2].z = this->lastPoints[0].z; + } + + this->lastPoints[0].x = points[0].x; + this->lastPoints[0].y = points[0].y; + this->lastPoints[0].z = points[0].z; + this->lastPoints[1].x = points[1].x; + this->lastPoints[1].y = points[1].y; + this->lastPoints[1].z = points[1].z; + this->bubbles.push_back(particle); + } + } +} // OFFSET: 0x00B469F0 // FUNCTION: fn_18911 @@ -131,8 +212,104 @@ bool CLevel150Effect::Slot06() { } // OFFSET: 0x00B46F00 +// FUNCTION: fn_18915 +void CLevel150Effect::Slot03() { + for (std::vector::iterator it = this->bubbles.begin(); it != this->bubbles.end(); ++it) { + CParticle* particle = *it; + particle->position.x = this->position[0]; + particle->position.y = this->position[1]; + particle->position.z = this->position[2]; + + if (particle) { + int tilt = particle->unknown_004C - 1; + float scale = particle->scale + 0.07f; + int alpha = particle->alpha; + if (tilt < 10) { + tilt = 10; + alpha = 0; + } + + if (scale < 3.5f) { + alpha += 10; + } else { + alpha -= 3; + if (alpha <= 0) { + alpha = 0; + tilt = 74; + scale = 2.87f; + } + } + + particle->alpha = alpha; + particle->scale = scale; + particle->unknown_004C = tilt; + + const float radius = particle->unknown_00C0; + const int segment = particle->unknown_000C; + matrix transform; + std::memcpy(transform.values, g_identityMatrix, sizeof(transform.values)); + transform.SetScale(scale * 0.5f, radius * g_sinTable[tilt] / (radius * g_sinTable[segment * 9] * 0.15f + radius), scale * 0.5f); + particle->transform = transform; + } + + ++particle->unknown_00E8; + } + + for (std::vector::iterator it = this->shocks.begin(); it != this->shocks.end(); ++it) { + CParticle* particle = *it; + particle->position.x = this->position[0]; + particle->position.y = this->position[1]; + particle->position.z = this->position[2]; + + if (particle) { + int tilt = particle->unknown_004C + 3; + if (tilt >= 360) { + tilt -= 360; + } + particle->unknown_004C = tilt; + + const float size = *reinterpret_cast(particle->unknown_0058); + const float scale = size * 0.1f * g_sinTable[tilt] + 1.0f + size * 0.8f; + const int segment = particle->unknown_000C; + CGameMode* mode = static_cast(g_modeMgr.GetGameMode()); + const int yaw = static_cast(mode->camera->camera.yaw); + + matrix rotation; + std::memcpy(rotation.values, g_identityMatrix, sizeof(rotation.values)); + rotation.MakeXRotation(90.0f / 180.0f * 3.141592f); + rotation.AppendYRotation(static_cast(segment * 23) / 180.0f * 3.141592f - 160.0f / 180.0f * 3.141592f - + static_cast(yaw) / 180.0f * 3.141592f); + matrix scaling; + std::memcpy(scaling.values, g_identityMatrix, sizeof(scaling.values)); + scaling.SetScale(scale, scale, 1.0f); + matrix result; + result.Compose(scaling, rotation); + particle->transform = result; + } + + ++particle->unknown_00E8; + } +} // OFFSET: 0x00B474C0 +// FUNCTION: fn_18916 +void CLevel150Effect::Slot04() { + for (std::vector::iterator it = this->bubbles.begin(); it != this->bubbles.end(); ++it) { + CParticle* particle = *it; + if (!particle || particle->unknown_000C <= 0) { + continue; + } + + const int segment = particle->unknown_000C; + const ParticleQuad quad = {false, 0.0f, 1.0f, static_cast(segment) / 21.0f, static_cast(segment + 1) / 21.0f, false, true}; + particle->SetTexture(FormatOwnedString("effect\\W_bubble%02d.tga", particle->unknown_00E8 % 27 + 1).c_str()); + particle->Render(quad); + } + + for (std::vector::iterator it = this->shocks.begin(); it != this->shocks.end(); ++it) { + (*it)->Render(false, 0.0f, 1.0f, 0.0f, 1.0f, false, true); + } +} // OFFSET: 0x00B47670 // FUNCTION: fn_18917 @@ -158,6 +335,43 @@ void CLevel150SubEffect::Slot08(int red, int green, int blue) { } // OFFSET: 0x00B47850 +// FUNCTION: fn_18921 +void CLevel150SubEffect::Init() { + const int blue[4][3] = {{105, 105, 255}, {5, 5, 255}, {55, 55, 255}, {155, 155, 255}}; + const int yellow[4][3] = {{255, 255, 105}, {255, 255, 5}, {255, 255, 55}, {255, 255, 155}}; + const int red[4][3] = {{255, 105, 105}, {255, 5, 5}, {255, 55, 55}, {255, 155, 155}}; + const int effectId = this->id; + for (int ring = 0; ring < 4; ++ring) { + for (int index = 0; index < 2; ++index) { + CParticle* particle = CreateParticle(reinterpret_cast(this->position), 13); + if (!particle) { + continue; + } + + particle->SetTexture("effect\\emp shock.tga"); + *reinterpret_cast(&particle->unknown_00C4) = static_cast(std::max(rand() % 360, 0)); + particle->alpha = 200; + particle->unknown_0054 = 10.0f; + *reinterpret_cast(particle->unknown_0058) = 10.0f; + particle->unknown_0004 = this->id; + particle->unknown_000C = index; + particle->unknown_0010 = ring; + particle->unknown_0008 = 1; + particle->unknown_00E8 = -20 * ring; + this->particles.push_back(particle); + + if (effectId == 979) { + particle->SetColor(blue[ring][0], blue[ring][1], blue[ring][2]); + } else if (effectId == 1023) { + particle->SetColor(yellow[ring][0], yellow[ring][1], yellow[ring][2]); + } else if (effectId == 1227) { + particle->SetColor(red[ring][0], red[ring][1], red[ring][2]); + } else if (effectId == 2276) { + particle->SetColor(255, 155, 0); + } + } + } +} // OFFSET: 0x00B47A90 // FUNCTION: fn_18922 @@ -182,6 +396,52 @@ bool CLevel150SubEffect::Slot06() { } // OFFSET: 0x00B47AF0 +// FUNCTION: fn_18925 +void CLevel150SubEffect::Slot03() { + for (std::vector::iterator it = this->particles.begin(); it != this->particles.end(); ++it) { + CParticle* particle = *it; + particle->position.x = this->position[0]; + particle->position.y = this->position[1]; + particle->position.z = this->position[2]; + + if (particle && particle->unknown_00E8 > 0) { + float size = particle->unknown_0054 * 1.02; + if (size > 20.0f) { + int alpha = particle->alpha - 3; + if (alpha <= 0) { + size = 10.0f; + *reinterpret_cast(&particle->unknown_00C4) = static_cast(std::max(rand() % 360, 0)); + alpha = 200; + } + particle->alpha = alpha; + } + particle->unknown_0054 = size; + + const int angle = static_cast(*reinterpret_cast(&particle->unknown_00C4)); + CGameMode* mode = static_cast(g_modeMgr.GetGameMode()); + const int yaw = static_cast(mode->camera->camera.yaw); + const float scale = particle->unknown_0054; + const float height = *reinterpret_cast(particle->unknown_0058); + + matrix rotation; + std::memcpy(rotation.values, g_identityMatrix, sizeof(rotation.values)); + rotation.MakeYRotation(static_cast(angle) / 180.0f * 3.141592f - static_cast(yaw) / 180.0f * 3.141592f); + matrix scaling; + std::memcpy(scaling.values, g_identityMatrix, sizeof(scaling.values)); + scaling.SetScale(scale * 0.5f, scale * 0.5f, 1.0f); + matrix translate; + std::memcpy(translate.values, g_identityMatrix, sizeof(translate.values)); + translate.MakeTranslate(0.0f, -height, 0.0f); + matrix first; + first.Compose(scaling, rotation); + matrix result; + result.Compose(first, translate); + particle->transform = result; + } + + ++particle->unknown_00E8; + } +} // OFFSET: 0x00B47FD0 // FUNCTION: fn_18926 diff --git a/Source/Contents/Effects/MagicFloorEffect.cpp b/Source/Contents/Effects/MagicFloorEffect.cpp index 84d00ff3..24a9e61f 100644 --- a/Source/Contents/Effects/MagicFloorEffect.cpp +++ b/Source/Contents/Effects/MagicFloorEffect.cpp @@ -15,8 +15,73 @@ CMagicFloorEffect::CMagicFloorEffect() : CEffect(0x401) { } // OFFSET: 0x00B48400 +// FUNCTION: fn_18929 +void CMagicFloorEffect::AddFloors() { + std::string textures[6] = { + "effect\\hero_011.tga", + "effect\\hero_001.tga", + "effect\\hero_021.tga", + "effect\\hero_002.tga", + "effect\\hero_031.tga", + "effect\\hero_003.tga", + }; + + for (int index = 0; index < 6; ++index) { + CParticle* particle = CreateParticle(reinterpret_cast(this->position), 5); + if (!particle) { + continue; + } + + particle->SetTexture(textures[index]); + particle->unknown_0004 = this->id; + particle->unknown_000C = index; + particle->unknown_0010 = 0; + particle->unknown_0008 = 1; + particle->alpha = 255; + *reinterpret_cast(&particle->unknown_00C4) = 0.0f; + particle->unknown_004C = 0; + particle->scale = 30.0f; + InitParticleQuad(particle->vertices); + this->floors.push_back(particle); + } +} // OFFSET: 0x00B48880 +// FUNCTION: fn_18930 +void CMagicFloorEffect::AddClouds(int layer) { + for (int ring = 0; ring < 4; ++ring) { + const int angle = std::max(rand() % 360, 0); + for (int segment = 0; segment < 21; ++segment) { + CParticle* particle = CreateParticle(reinterpret_cast(this->position), 5); + if (!particle) { + continue; + } + + particle->SetTexture("effect\\cloud11.tga"); + particle->unknown_0004 = this->id; + particle->unknown_000C = segment; + particle->unknown_0010 = ring; + particle->unknown_0008 = 1; + particle->alpha = 200; + particle->unknown_0050 = 30; + *reinterpret_cast(&particle->unknown_00C4) = static_cast(angle); + particle->unknown_004C = std::max(rand() % 21, 0) + 80; + particle->unknown_0054 = 1.0f; + particle->SetColor(255, 100, 100); + + if (layer == 0) { + particle->unknown_00C0 = 48.0f - static_cast(ring) * 5.0f; + particle->scale = 11.0f; + } else if (layer == 1) { + particle->unknown_00C0 = 28.0f - static_cast(ring) * 5.0f; + particle->scale = 22.0f; + } + + InitParticleQuad(particle->vertices); + this->particles.push_back(particle); + } + } +} // OFFSET: 0x00B48D50 // FUNCTION: fn_18931 @@ -69,6 +134,125 @@ bool CMagicFloorEffect::Slot06() { } // OFFSET: 0x00B48F30 +// FUNCTION: fn_18935 +void CMagicFloorEffect::Slot03() { + for (std::vector::iterator it = this->floors.begin(); it != this->floors.end(); ++it) { + CParticle* particle = *it; + particle->position.x = this->position[0]; + particle->position.y = this->position[1]; + particle->position.z = this->position[2]; + + if (particle) { + const float current = *reinterpret_cast(&particle->unknown_00C4); + int angle = 0; + switch (particle->unknown_000C) { + case 0: + case 1: + angle = static_cast(current + 1.0f); + break; + case 2: + case 3: + angle = static_cast(current + 2.0f); + break; + case 4: + case 5: + angle = static_cast(current - 1.0f); + break; + } + + if (angle >= 360) { + angle -= 360; + } else if (angle < 0) { + angle += 360; + } + + *reinterpret_cast(&particle->unknown_00C4) = static_cast(angle); + matrix rotation; + std::memcpy(rotation.values, g_identityMatrix, sizeof(rotation.values)); + rotation.MakeZRotation(static_cast(angle) / 180.0f * 3.141592f); + rotation.AppendXRotation(90.0f / 180.0f * 3.141592f); + matrix scaling; + std::memcpy(scaling.values, g_identityMatrix, sizeof(scaling.values)); + scaling.SetScale(particle->scale, particle->scale, 1.0f); + matrix result; + result.Compose(scaling, rotation); + particle->transform = result; + } + + ++particle->unknown_00E8; + } + + for (std::vector::iterator it = this->particles.begin(); it != this->particles.end(); ++it) { + CParticle* particle = *it; + particle->position.x = this->position[0]; + particle->position.y = this->position[1]; + particle->position.z = this->position[2]; + + if (particle) { + const int direction = static_cast(*reinterpret_cast(&particle->unknown_00C4) + 5.0f) % 360; + const int sweep = std::min(particle->unknown_0050 + 3, 180); + particle->unknown_0050 = sweep; + int alpha = particle->alpha; + const int phase = particle->unknown_00E8 % 300; + *reinterpret_cast(&particle->unknown_00C4) = static_cast(direction); + if (phase == 0) { + alpha = 50; + } else if (phase > 100) { + alpha = std::max(alpha - 1, 0); + } + if (phase < 12) { + ++alpha; + } + particle->alpha = alpha; + + const int segment = particle->unknown_000C; + const float radius = particle->unknown_0054; + const int angle = + static_cast(static_cast(static_cast(static_cast(sweep) / 20.0f) * segment) + + *reinterpret_cast(&particle->unknown_00C4)) % + 360; + const int tilt = particle->unknown_004C; + const float spread = radius * g_cosTable[tilt]; + const float height = radius * g_sinTable[tilt]; + const float cosine = g_cosTable[angle]; + const float sine = g_sinTable[angle]; + const float floorRadius = *reinterpret_cast(&this->unknown_0048); + + EffectPoint points[4]; + points[0].x = floorRadius * cosine; + points[0].y = -particle->unknown_00C0; + points[0].z = floorRadius * sine; + points[1].x = points[0].x + cosine * spread; + points[1].y = points[0].y - height; + points[1].z = points[0].z + sine * spread; + + particle->vertices[3].x = points[0].x; + particle->vertices[3].y = points[0].y; + particle->vertices[3].z = points[0].z; + particle->vertices[1].x = points[1].x; + particle->vertices[1].y = points[1].y; + particle->vertices[1].z = points[1].z; + + if (segment != 0) { + particle->vertices[0].x = this->lastPoints[1].x; + particle->vertices[0].y = this->lastPoints[1].y; + particle->vertices[0].z = this->lastPoints[1].z; + particle->vertices[2].x = this->lastPoints[0].x; + particle->vertices[2].y = this->lastPoints[0].y; + particle->vertices[2].z = this->lastPoints[0].z; + } + + this->lastPoints[0].x = points[0].x; + this->lastPoints[0].y = points[0].y; + this->lastPoints[0].z = points[0].z; + this->lastPoints[1].x = points[1].x; + this->lastPoints[1].y = points[1].y; + this->lastPoints[1].z = points[1].z; + } + + ++particle->unknown_00E8; + } +} // OFFSET: 0x00B49760 // FUNCTION: fn_18936