rodecomp/Source/Contents/Effects/StormKickEffect.cpp
ragnarok-clanker 6d44b5dea6 Decompile 22 functions in Source/Contents/Effects/SpriteEffect.cpp, Source/Contents/Effects/SpriteEffect.h, ...
Batch #4423 by youko: 7 byte-identical, 15 confirmed by peer review.

- fn_19201 CSpriteEffect::Slot04: byte-identical
- fn_19203 CStarEffect::Close: logic confirmed by peer review
- fn_19204 CStarEffect::Slot01: logic confirmed by peer review
- fn_19205 CStarEffect::SetupParticle: logic confirmed by peer review
- fn_19206 CStarEffect::Slot06: byte-identical
- fn_19207 CStarEffect::Slot03: byte-identical
- fn_19208 CStarEffect::UpdateParticle: logic confirmed by peer review
- fn_19209 CStarEffect::Slot04: byte-identical
- fn_19211 CStormGustEffect::Close: logic confirmed by peer review
- fn_19212 CStormGustEffect::Slot01: logic confirmed by peer review
- fn_19213 CStormGustEffect::Slot06: byte-identical
- fn_19214 CStormGustEffect::Slot03: logic confirmed by peer review
- fn_19215 CStormGustEffect::Slot04: byte-identical
- fn_19216 CStormKickEffect::CStormKickEffect: logic confirmed by peer review
- fn_19218 CStormKickEffect::CreateStorms: logic confirmed by peer review
- fn_19219 CStormKickEffect::CreateClouds: logic confirmed by peer review
- fn_19220 CStormKickEffect::UpdateStorm: logic confirmed by peer review
- fn_19221 CStormKickEffect::Close: logic confirmed by peer review
- fn_19222 CStormKickEffect::Slot01: logic confirmed by peer review
- fn_19223 CStormKickEffect::Slot12: logic confirmed by peer review
- fn_19224 CStormKickEffect::Slot06: byte-identical
- fn_19225 CStormKickEffect::Slot03: logic confirmed by peer review

Peer-reviewed-by: eAthena, KWDev
Reviewed-by: ragnarok-clanker
Adds to the build: Source/Contents/Effects/StarEffect.cpp, Source/Contents/Effects/StormGustEffect.cpp, Source/Contents/Effects/StormKickEffect.cpp
2026-10-30 03:42:30 +00:00

375 lines
11 KiB
C++

#include "Contents/Effects/StormKickEffect.h"
#include "Client/Mode/ModeMgr.h"
#include "Contents/Actors/RenderObject.h"
#include "Contents/Effects/EffectMemoryMgr.h"
#include "Contents/Effects/Particle.h"
#include "Contents/World/World.h"
#include "Utility/Math/AffineMatrix.h"
#include <algorithm>
#include <cstdlib>
#include <cstring>
// OFFSET: 0x00B7B340
// FUNCTION: fn_19216
CStormKickEffect::CStormKickEffect() : CEffect(-1) {
}
// OFFSET: 0x00B7B4F0
// FUNCTION: fn_19218
void CStormKickEffect::CreateStorms(int layer) {
for (int index = 0; index < 10; ++index) {
CParticle* particle = CreateParticle(reinterpret_cast<const vector3d*>(this->position), 5);
if (!particle) {
continue;
}
particle->SetTexture("effect\\storm2.tga");
particle->unknown_0004 = this->id;
particle->unknown_000C = index;
particle->unknown_0010 = 0;
particle->unknown_0008 = 1;
particle->unknown_00C0 = 40.0f;
particle->alpha = 0;
*reinterpret_cast<float*>(&particle->unknown_00C4) = static_cast<float>(std::max(rand() % 360, 0));
particle->scale = 2.0f;
particle->unknown_0054 = 50.0f;
float* motion = reinterpret_cast<float*>(particle->unknown_0058);
motion[0] = 5.0f;
motion[1] = static_cast<float>(layer);
switch (this->id) {
case 435:
particle->SetColor(50, 50, 255);
break;
case 459:
particle->SetColor(164, 136, 55);
break;
case 460:
particle->SetColor(255, 255, 255);
break;
case 461:
particle->SetColor(130, 130, 255);
break;
case 464:
if (motion[1] == 0.0f) {
particle->SetColor(255, 255, 255);
} else if (motion[1] == 1.0f) {
particle->SetColor(255, 55, 55);
}
break;
case 465:
particle->SetColor(155, 255, 155);
break;
case 1223:
particle->SetColor(255, 255, 50);
break;
}
InitParticleQuad(particle->vertices);
this->storms.push_back(particle);
this->UpdateStorm(particle);
}
}
// OFFSET: 0x00B7B6C0
// FUNCTION: fn_19219
void CStormKickEffect::CreateClouds(int layer) {
int ring = 0;
for (int angle = 0; angle < 360; angle += 90) {
for (int segment = 0; segment < 21; ++segment) {
CParticle* particle = CreateParticle(reinterpret_cast<const vector3d*>(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 = 0;
particle->unknown_0050 = 30;
*reinterpret_cast<float*>(&particle->unknown_00C4) = static_cast<float>(angle);
particle->unknown_004C = std::max(rand() % 21, 0) + 80;
particle->unknown_0054 = 1.0f;
if (this->id == 1223) {
if (layer == 0) {
particle->unknown_00C0 = 28.0f - ring * 5.0f;
particle->scale = 10.0f - ring * 2.0f;
} else if (layer == 1) {
particle->unknown_00C0 = 18.0f - ring * 5.0f;
particle->scale = 5.0f - ring;
}
} else if (layer == 0) {
particle->unknown_00C0 = 48.0f - ring * 5.0f;
particle->scale = 14.0f - ring * 2.0f;
} else if (layer == 1) {
particle->unknown_00C0 = 28.0f - ring * 5.0f;
particle->scale = 6.0f - ring;
}
InitParticleQuad(particle->vertices);
this->clouds.push_back(particle);
}
++ring;
}
}
// OFFSET: 0x00B7B8D0
// FUNCTION: fn_19220
void CStormKickEffect::UpdateStorm(CParticle* particle) {
if (!particle) {
return;
}
const float* motion = reinterpret_cast<const float*>(particle->unknown_0058);
const int segment = particle->unknown_000C;
float radius = particle->unknown_00C0;
const float height = -particle->unknown_0054 + segment * motion[0];
int angle = static_cast<int>(static_cast<float>(segment * 45) + *reinterpret_cast<const float*>(&particle->unknown_00C4)) % 360;
for (int step = 1; step <= segment; ++step) {
radius -= (2.2f - step * 0.2f) * particle->scale;
}
EffectPoint corners[4];
angle = (angle + 90) % 360;
corners[0].x = radius * g_cosTable[angle];
corners[0].y = height - 1.0f;
corners[0].z = radius * g_sinTable[angle];
angle = (angle + 90) % 360;
corners[1].x = radius * g_cosTable[angle];
corners[1].y = height - 1.0f;
corners[1].z = radius * g_sinTable[angle];
angle = (angle + 90) % 360;
corners[2].x = radius * g_cosTable[angle];
corners[2].y = height - 1.0f;
corners[2].z = radius * g_sinTable[angle];
angle = (angle + 90) % 360;
corners[3].x = radius * g_cosTable[angle];
corners[3].y = height - 1.0f;
corners[3].z = radius * g_sinTable[angle];
particle->vertices[0].x = corners[2].x;
particle->vertices[0].y = corners[2].y;
particle->vertices[0].z = corners[2].z;
particle->vertices[1].x = corners[1].x;
particle->vertices[1].y = corners[1].y;
particle->vertices[1].z = corners[1].z;
particle->vertices[2].x = corners[3].x;
particle->vertices[2].y = corners[3].y;
particle->vertices[2].z = corners[3].z;
particle->vertices[3].x = corners[0].x;
particle->vertices[3].y = corners[0].y;
particle->vertices[3].z = corners[0].z;
}
// OFFSET: 0x00B7BC20
// FUNCTION: fn_19221
void CStormKickEffect::Close() {
for (CParticle* particle : this->storms) {
FreeParticle(particle);
}
this->storms.clear();
for (CParticle* particle : this->clouds) {
FreeParticle(particle);
}
this->clouds.clear();
}
// OFFSET: 0x00B7BC90
// FUNCTION: fn_19222
void CStormKickEffect::Slot01() {
g_modeMgr.GetGameMode();
switch (this->id) {
case 435:
case 459:
case 460:
case 461:
case 465:
this->CreateStorms(0);
this->CreateClouds(0);
this->CreateClouds(1);
break;
case 464:
this->CreateStorms(0);
this->CreateStorms(1);
this->CreateClouds(0);
this->CreateClouds(1);
break;
case 1223:
this->CreateClouds(0);
this->CreateClouds(1);
break;
}
switch (this->id) {
case 435:
case 459:
case 460:
case 461:
case 464:
this->unknown_002C = 100;
break;
case 465:
this->unknown_002C = 1000;
break;
case 1223:
this->unknown_002C = 60;
break;
}
}
// OFFSET: 0x00B7BDD0
// FUNCTION: fn_19223
void CStormKickEffect::Slot12() {
switch (this->id) {
case 435:
this->AddEvent(0, "effect\\T_회오리차기.wav", 5, 0);
break;
case 460:
this->AddEvent(0, "ice_titan_attack.wav", 5, 0);
break;
case 464:
this->AddEvent(0, "effect\\REVERBERATION.wav", 0, 0);
break;
}
}
// OFFSET: 0x00B7BF60
// FUNCTION: fn_19224
bool CStormKickEffect::Slot06() {
return !this->IsFinished();
}
// OFFSET: 0x00B7BF70
// FUNCTION: fn_19225
void CStormKickEffect::Slot03() {
for (auto it = this->storms.begin(); it != this->storms.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 alpha = particle->alpha;
if (particle->unknown_00E8 > 60 && this->id != 465) {
alpha = std::max(alpha - 1, 0);
}
if (particle->unknown_00E8 <= 40) {
++alpha;
}
particle->alpha = alpha;
float& rotation = *reinterpret_cast<float*>(&particle->unknown_00C4);
rotation = static_cast<float>(static_cast<int>(rotation - static_cast<float>(std::max(rand() % 3, 0) + 3)) % 360);
matrix transform;
std::memcpy(transform.values, g_identityMatrix, sizeof(transform.values));
transform.MakeYRotation(rotation / 180.0f * 3.141592f);
particle->transform = transform;
}
++particle->unknown_00E8;
}
for (auto it = this->clouds.begin(); it != this->clouds.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) {
float& rotation = *reinterpret_cast<float*>(&particle->unknown_00C4);
const float nextRotation = static_cast<float>(static_cast<int>(rotation + 5.0f) % 360);
const int spread = std::min(particle->unknown_0050 + 3, 180);
particle->unknown_0050 = spread;
const int frame = particle->unknown_00E8;
int alpha = particle->alpha;
rotation = nextRotation;
if (this->id == 1223) {
if (frame > 30) {
alpha = std::max(alpha - 3, 0);
} else {
alpha += 3;
}
} else if (frame > 50) {
alpha = std::max(alpha - 1, 0);
} else if (frame < 12) {
++alpha;
}
particle->alpha = alpha;
if (frame > 12) {
particle->scale += 0.1f;
}
const int segment = particle->unknown_000C;
const float radius = particle->unknown_0054;
const int angle = static_cast<int>(static_cast<float>(static_cast<int>(static_cast<float>(spread) / 20.0f) * segment) + nextRotation) % 360;
const int tilt = particle->unknown_004C;
const float horizontal = radius * g_cosTable[tilt];
const float vertical = radius * g_sinTable[tilt];
EffectPoint corners[4];
corners[3].x = g_cosTable[angle] * particle->scale;
corners[3].y = -particle->unknown_00C0;
corners[3].z = g_sinTable[angle] * particle->scale;
corners[1].x = corners[3].x + g_cosTable[angle] * horizontal;
corners[1].y = corners[3].y - vertical;
corners[1].z = corners[3].z + g_sinTable[angle] * horizontal;
particle->vertices[3].x = corners[3].x;
particle->vertices[3].y = corners[3].y;
particle->vertices[3].z = corners[3].z;
particle->vertices[1].x = corners[1].x;
particle->vertices[1].y = corners[1].y;
particle->vertices[1].z = corners[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] = corners[3];
this->lastPoints[1] = corners[1];
}
++particle->unknown_00E8;
}
CRenderObject* actor = FindRenderObject(this->actor);
if (!actor) {
return;
}
float angle;
switch (this->id) {
case 435:
case 1223:
if (this->frame > 47) {
return;
}
angle = actor->render.angle + 30.0f;
break;
case 459:
if (this->frame > 50) {
return;
}
angle = actor->render.angle + 14.0f;
break;
default:
return;
}
actor->render.angle = angle;
if (angle > 360.0f) {
actor->render.angle = angle - 360.0f;
}
}