rodecomp/Source/Contents/Effects/CloudKillEffect.cpp
ragnarok-clanker b946a09dbc Decompile fn_06930 (CCloudKillEffect::OnProcess)
Batch #15598 by Yommy: 0 byte-identical, 1 confirmed by peer review.

- fn_06930 CCloudKillEffect::OnProcess: logic confirmed by peer review

Peer-reviewed-by: ragnarok-clanker, eAthena
Accepted without human review: peers confirmed the logic ("same" ahead by at least 3, with 70% of the votes).
2026-11-10 10:29:07 +00:00

205 lines
8.5 KiB
C++

#include "Contents/Effects/CloudKillEffect.h"
#include "Contents/Effects/EffectMemoryMgr.h"
#include "Contents/Effects/Particle.h"
#include "Contents/Effects/SpriteParticle.h"
#include "Contents/MapSkyMgr.h"
#include "Utility/Math/AffineMatrix.h"
#include <algorithm>
#include <cstdlib>
namespace {
// INLINED
__forceinline bool IsParticleActive(const CSpriteParticle* particle) {
if (0.0f == particle->life) {
return true;
}
return particle->life * 60.0f > static_cast<float>(particle->elapsedFrames);
}
}
// OFFSET: 0x006FC410
// FUNCTION: fn_06923
CCloudKillEffect::CCloudKillEffect() : CEffect(1080) {
this->effectLifetime = 9999;
this->emitting = 1;
this->particleLifetimeFrames = 10;
this->spriteLifetimeFrames = 40;
}
// OFFSET: 0x006FC600
// FUNCTION: fn_06924
CCloudKillEffect::~CCloudKillEffect() {
}
// OFFSET: 0x006FC8F0
// FUNCTION: fn_06926
void CCloudKillEffect::AddSprites() {
for (int z = -10; z <= 10; z += 4) {
for (int x = -10; x <= 10; x += 4) {
CParticle* created = CreateSpriteParticle(reinterpret_cast<const vector3d*>(this->position), 1);
CSpriteParticle* particle = static_cast<CSpriteParticle*>(created);
matrix& rotation = *reinterpret_cast<matrix*>(particle->rotationStorage);
rotation.IsIdentity();
rotation.MakeYRotation(GetRadian(std::max(rand() % 360, 0)));
const float distance = static_cast<float>(std::max(rand() % 6, 0) + 2);
const float* values = rotation.values;
particle->originX = values[3] * 0.0f + values[0] * 0.0f + distance * values[6] + values[9] + static_cast<float>(x);
particle->originY = values[4] * 0.0f + values[1] * 0.0f + distance * values[7] + values[10] + 0.0f;
particle->originZ = values[5] * 0.0f + values[2] * 0.0f + distance * values[8] + values[11] + static_cast<float>(z);
rotation.MakeXRotation(GetRadian(90));
const float speed = static_cast<float>(std::max(rand() % 30, 0) + 30) / 100.0f;
const float acceleration = -(speed / 40.0f) * g_depthAverageHalf;
const int size = std::max(rand() % 50, 0);
particle->frameDelay = speed;
reinterpret_cast<float&>(particle->accelerationStorage) = acceleration;
particle->scale = static_cast<float>(size + 40) / 170.0f;
reinterpret_cast<float&>(particle->spinBits) = 3.0f;
particle->alpha = 0;
particle->animationParameter = 25.4f;
reinterpret_cast<float&>(particle->animationParameters) = 32.0f;
particle->SetSprite("이팩트\\particle3.spr");
particle->SetAction("이팩트\\particle3.act");
particle->life = static_cast<float>(this->spriteLifetimeFrames) / 60.0f;
this->sprites.push_back(created);
}
}
}
// OFFSET: 0x006FCBE0
// FUNCTION: fn_06927
void CCloudKillEffect::Close() {
for (auto it = this->particles.begin(); it != this->particles.end(); ++it) {
FreeParticle(*it);
}
this->particles.clear();
for (auto it = this->sprites.begin(); it != this->sprites.end(); ++it) {
FreeParticle(*it);
}
this->sprites.clear();
}
// OFFSET: 0x006FCCB0
// FUNCTION: fn_06928
void CCloudKillEffect::Open() {
}
// OFFSET: 0x006FCCC0
// FUNCTION: fn_06929
bool CCloudKillEffect::IsAlive() {
return !this->IsFinished();
}
// OFFSET: 0x006FCE60
// FUNCTION: fn_06930
void CCloudKillEffect::OnProcess() {
if (this->emitting && this->frame % 5 == 0) {
CParticle* created = CreateSpriteParticle(reinterpret_cast<const vector3d*>(this->position), 1);
CSpriteParticle* particle = static_cast<CSpriteParticle*>(created);
matrix& rotation = *reinterpret_cast<matrix*>(particle->rotationStorage);
rotation.IsIdentity();
rotation.MakeYRotation(GetRadian(std::max(rand() % 360, 0)));
rotation.MakeXRotation(GetRadian(90));
const float speed = static_cast<float>(std::max(rand() % 20, 0) + 20) / 80.0f;
particle->frameDelay = speed;
reinterpret_cast<float&>(particle->accelerationStorage) = -(speed / 10.0f) * g_depthAverageHalf;
particle->scale = 0.8f;
reinterpret_cast<float&>(particle->spinBits) = 3.0f;
particle->alpha = 70;
particle->animationParameter = 25.4f;
reinterpret_cast<float&>(particle->animationParameters) = 8.0f;
particle->SetSprite("이팩트\\particle3.spr");
particle->SetAction("이팩트\\particle3.act");
particle->life = static_cast<float>(this->particleLifetimeFrames) / 60.0f;
this->particles.push_back(created);
}
for (auto it = this->particles.begin(); it != this->particles.end();) {
CSpriteParticle* particle = static_cast<CSpriteParticle*>(*it);
if (IsParticleActive(particle) != true) {
FreeParticle(particle);
it = this->particles.erase(it);
} else {
const float* values = reinterpret_cast<matrix*>(particle->rotationStorage)->values;
float& angle = reinterpret_cast<float&>(particle->angleBits);
const float speed = reinterpret_cast<float&>(particle->accelerationStorage) + particle->frameDelay;
particle->frameDelay = speed;
particle->velocity.x = values[3] * 0.0f + values[0] * 0.0f + speed * values[6] + values[9] + particle->velocity.x;
particle->velocity.y = values[4] * 0.0f + values[1] * 0.0f + speed * values[7] + values[10] + particle->velocity.y;
particle->velocity.z = values[5] * 0.0f + values[2] * 0.0f + speed * values[8] + values[11] + particle->velocity.z;
angle = reinterpret_cast<float&>(particle->spinBits) + angle;
particle->position.z = particle->velocity.z + this->position[2];
particle->position.x = particle->velocity.x + this->position[0];
particle->position.y = particle->velocity.y + this->position[1];
const int age = particle->elapsedFrames;
float fade = particle->animationParameter;
if (age == static_cast<int>(reinterpret_cast<float&>(particle->animationParameters))) {
fade = -(static_cast<float>(particle->alpha) / static_cast<float>(this->particleLifetimeFrames - age));
}
particle->animationParameter = fade;
const float level = fade + static_cast<float>(particle->alpha);
const float positive = 0.0f <= level ? level : 0.0f;
particle->alpha = static_cast<int>(positive <= 254.0f ? positive : 254.0f);
particle->elapsedFrames = age + 1;
++it;
}
}
if (this->emitting && this->frame % 9 == 0) {
this->AddSprites();
}
for (auto it = this->sprites.begin(); it != this->sprites.end();) {
CSpriteParticle* particle = static_cast<CSpriteParticle*>(*it);
if (IsParticleActive(particle) != true) {
FreeParticle(particle);
it = this->sprites.erase(it);
} else {
const float* values = reinterpret_cast<matrix*>(particle->rotationStorage)->values;
float& angle = reinterpret_cast<float&>(particle->angleBits);
const float speed = reinterpret_cast<float&>(particle->accelerationStorage) + particle->frameDelay;
particle->frameDelay = speed;
particle->velocity.x = values[3] * 0.0f + values[0] * 0.0f + speed * values[6] + values[9] + particle->velocity.x;
particle->velocity.y = values[4] * 0.0f + values[1] * 0.0f + speed * values[7] + values[10] + particle->velocity.y;
particle->velocity.z = values[5] * 0.0f + values[2] * 0.0f + speed * values[8] + values[11] + particle->velocity.z;
particle->position.y = particle->originY + this->position[1] + particle->velocity.y;
particle->position.x = particle->originX + this->position[0] + particle->velocity.x;
particle->position.z = this->position[2] + particle->originZ + particle->velocity.z;
angle = reinterpret_cast<float&>(particle->spinBits) + angle;
const int age = particle->elapsedFrames;
float fade = particle->animationParameter;
if (age == static_cast<int>(reinterpret_cast<float&>(particle->animationParameters))) {
fade = -(static_cast<float>(particle->alpha) / static_cast<float>(this->spriteLifetimeFrames - age));
}
particle->animationParameter = fade;
const float level = fade + static_cast<float>(particle->alpha);
const float positive = 0.0f <= level ? level : 0.0f;
particle->alpha = static_cast<int>(positive <= 254.0f ? positive : 254.0f);
particle->elapsedFrames = age + 1;
++it;
}
}
if (!this->ActorExists()) {
this->emitting = 0;
this->effectLifetime = this->frame + 50;
}
}
// OFFSET: 0x006FD640
// FUNCTION: fn_06931
void CCloudKillEffect::Render() {
for (auto it = this->particles.begin(); it != this->particles.end(); ++it) {
if (*it) {
static_cast<CSpriteParticle*>(*it)->Draw(1);
}
}
for (auto it = this->sprites.begin(); it != this->sprites.end(); ++it) {
if (*it) {
static_cast<CSpriteParticle*>(*it)->Draw(1);
}
}
}