Decompile 8 functions in Source/Contents/Effects/EffectPrimitiveMotion.cpp, Source/Contents/Effects/EffectPrimitiveState.cpp, ...

Batch #1765 by ragnarok-clanker: 0 byte-identical, 8 confirmed by peer review.

- fn_19791 EffectParticle::PrimBottom: logic confirmed by peer review
- fn_19765 EffectPrimitiveState::GetColorOverride: logic confirmed by peer review
- fn_19779 EffectParticle::UpdateHit6: logic confirmed by peer review
- fn_19785 MoveEffectPrimitive: logic confirmed by peer review
- fn_19849 EffectPrimitiveState::UpdateColor: logic confirmed by peer review
- fn_20076 CreateEffectParticle: logic confirmed by peer review
- fn_19866 RenderEffectPrimitive15: logic confirmed by peer review
- fn_20088 UpdatePartyEffect: logic confirmed by peer review

Reviewed-by: ragnarok-clanker
This commit is contained in:
ragnarok-clanker 2026-10-28 22:09:53 +00:00
commit 25dd065dbd
10 changed files with 284 additions and 195 deletions

View file

@ -27,7 +27,7 @@ inline RagEffectState::RagEffectState()
// INLINED // INLINED
inline RagEffectState::~RagEffectState() { inline RagEffectState::~RagEffectState() {
for (EffectPrimitiveState* particle : this->related) { for (EffectPrimitiveState* particle : this->related) {
particle->parent = nullptr; particle->master = nullptr;
} }
this->related.clear(); this->related.clear();

View file

@ -1,5 +1,5 @@
#include "Contents/Effects/EffectParticle.h" #include "Contents/Effects/EffectParticle.h"
#include "Contents/Effects/RagEffectState.h" #include "Contents/Effects/AttachedEffect.h"
// OFFSET: 0x00BAD940 // OFFSET: 0x00BAD940
// FUNCTION: fn_19761 // FUNCTION: fn_19761
@ -9,13 +9,13 @@ EffectParticle::EffectParticle(ResourceMgr& resources, JobNames& names) : CRende
// OFFSET: 0x00C1DE70 // OFFSET: 0x00C1DE70
// FUNCTION: fn_20076 // FUNCTION: fn_20076
EffectParticle* CreateEffectParticle( EffectParticle* CreateEffectParticle(
RagEffectState& parent, const RenderObjectState& parentRender, int type, float x, float y, float z, ResourceMgr& resources, JobNames& names, AttachedEffect& master, const RenderObjectState& masterRender, int type, float x, float y, float z, ResourceMgr& resources, JobNames& names,
std::list<CRenderObject*>& worldObjects std::list<CRenderObject*>& worldObjects
) { ) {
auto* particle = new EffectParticle(resources, names); auto* particle = new EffectParticle(resources, names);
particle->state.Initialize(particle->render, parent, parentRender, type, x, y, z); particle->state.Initialize(particle->render, master, masterRender, type, x, y, z);
parent.related.push_back(&particle->state); master.state.related.push_back(&particle->state);
worldObjects.push_back(particle); worldObjects.push_back(particle);
return particle; return particle;

View file

@ -8,7 +8,7 @@
struct JobNames; struct JobNames;
class ResourceMgr; class ResourceMgr;
struct RagEffectState; struct AttachedEffect;
struct EffectParticle : CRenderObject { struct EffectParticle : CRenderObject {
EffectParticle(ResourceMgr& resources, JobNames& names); EffectParticle(ResourceMgr& resources, JobNames& names);
@ -22,6 +22,7 @@ struct EffectParticle : CRenderObject {
bool UpdateExit(); bool UpdateExit();
bool UpdateWarp(); bool UpdateWarp();
void PrimBottom2(); void PrimBottom2();
void PrimBottom();
bool AdvanceFrame(); bool AdvanceFrame();
void UpdateRecords(); void UpdateRecords();
@ -30,7 +31,7 @@ struct EffectParticle : CRenderObject {
}; };
EffectParticle* CreateEffectParticle( EffectParticle* CreateEffectParticle(
RagEffectState& parent, const RenderObjectState& parentRender, int type, float x, float y, float z, ResourceMgr& resources, JobNames& names, AttachedEffect& master, const RenderObjectState& masterRender, int type, float x, float y, float z, ResourceMgr& resources, JobNames& names,
std::list<CRenderObject*>& worldObjects std::list<CRenderObject*>& worldObjects
); );

View file

@ -1,5 +1,5 @@
#include "Contents/Effects/EffectPrimitiveState.h" #include "Contents/Effects/EffectPrimitiveState.h"
#include "Contents/Effects/RagEffectState.h" #include "Contents/Effects/AttachedEffect.h"
#include "Utility/Math/ScalarConversion.h" #include "Utility/Math/ScalarConversion.h"
// OFFSET: 0x00BC5E00 // OFFSET: 0x00BC5E00
@ -45,7 +45,7 @@ void EffectPrimitiveState::UpdateColor() {
} }
if (this->unknown_015C == 0) { if (this->unknown_015C == 0) {
const int parentRemaining = this->parent->lifetime - this->parent->unknown_0178; const int parentRemaining = this->master->state.lifetime - this->master->state.unknown_0178;
const int remaining = this->lifetime - current; const int remaining = this->lifetime - current;
if (remaining > parentRemaining + 1) { if (remaining > parentRemaining + 1) {

View file

@ -6,6 +6,7 @@
#include "Resource/Sprites/ActionResource.h" #include "Resource/Sprites/ActionResource.h"
#include "Contents/Effects/EffectParticle.h" #include "Contents/Effects/EffectParticle.h"
#include "Contents/Effects/EffectPrimitiveState.h" #include "Contents/Effects/EffectPrimitiveState.h"
#include "Contents/Effects/AttachedEffect.h"
#include "Contents/Effects/RagEffectState.h" #include "Contents/Effects/RagEffectState.h"
#include "Contents/Sound/SoundMgr.h" #include "Contents/Sound/SoundMgr.h"
#include "Resource/World/TerrainResource.h" #include "Resource/World/TerrainResource.h"
@ -136,8 +137,8 @@ bool MoveEffectPrimitive(EffectPrimitiveState& particle, RenderObjectState& rend
} }
if ((particle.flags & 0x400u) != 0) { if ((particle.flags & 0x400u) != 0) {
const float x = particle.parent->offset[0] - render.position[0]; const float x = particle.master->state.offset[0] - render.position[0];
const float z = particle.parent->offset[2] - render.position[2]; const float z = particle.master->state.offset[2] - render.position[2];
const float distance = std::sqrt(z * z + x * x); const float distance = std::sqrt(z * z + x * x);
if (3.0f >= distance) { if (3.0f >= distance) {
@ -188,16 +189,16 @@ bool MoveEffectPrimitive(EffectPrimitiveState& particle, RenderObjectState& rend
} }
if ((particle.flags & 0x10u) != 0) { if ((particle.flags & 0x10u) != 0) {
particle.parent->offset[0] = particle.velocity.x + particle.offset.x; particle.master->state.offset[0] = particle.velocity.x + particle.offset.x;
particle.parent->offset[1] = particle.offset.y + particle.velocity.y; particle.master->state.offset[1] = particle.offset.y + particle.velocity.y;
particle.parent->offset[2] = particle.offset.z + particle.velocity.z; particle.master->state.offset[2] = particle.offset.z + particle.velocity.z;
} }
if ((particle.flags & 4u) != 0 && render.position[1] > context.ground.Height(render.position[0], render.position[2])) { if ((particle.flags & 4u) != 0 && render.position[1] > context.ground.Height(render.position[0], render.position[2])) {
particle.flags &= ~4u; particle.flags &= ~4u;
particle.unknown_01E0 = particle.lifetime - 25; particle.unknown_01E0 = particle.lifetime - 25;
particle.unknown_02BC = 0; particle.unknown_02BC = 0;
particle.parent->unknown_0170 = 1; particle.master->state.unknown_0170 = 1;
} }
const int frame = particle.unknown_01E0; const int frame = particle.unknown_01E0;
@ -257,7 +258,7 @@ bool MoveEffectPrimitive(EffectPrimitiveState& particle, RenderObjectState& rend
// OFFSET: 0x00BAE7D0 // OFFSET: 0x00BAE7D0
// FUNCTION: fn_19769 // FUNCTION: fn_19769
bool UpdateEffectPrimitive15(EffectPrimitiveState& particle, RenderObjectState& render, EffectMotionContext& context, int updateTick) { bool UpdateEffectPrimitive15(EffectPrimitiveState& particle, RenderObjectState& render, EffectMotionContext& context, int updateTick) {
if (!particle.parent) { if (!particle.master) {
return false; return false;
} }
@ -280,39 +281,39 @@ bool ShrinkEffectPrimitiveSlots(EffectPrimitiveState& particle, RenderObjectStat
for (int index = 0; index < 4; ++index) { for (int index = 0; index < 4; ++index) {
EffectPrimitiveSlot& slot = particle.slots[index]; EffectPrimitiveSlot& slot = particle.slots[index];
if (slot.active != 1) { if (slot.life != 1) {
continue; continue;
} }
float height = slot.unknown_0080 - 0.05f; float height = slot.distance - 0.05f;
++slot.frame; ++slot.process;
slot.unknown_0080 = height; slot.distance = height;
if (height <= 0.0f) { if (height <= 0.0f) {
slot.unknown_0080 = 10.0f; slot.distance = 10.0f;
slot.unknown_0002 = 0; slot.alphaB = 0;
height = 10.0f; height = 10.0f;
} }
slot.unknown_0008 = height; slot.maxHeight = height;
slot.unknown_007E = static_cast<std::int16_t>(static_cast<int>(90.0f - height * 9.0f)); slot.riseAngle = static_cast<std::int16_t>(static_cast<int>(90.0f - height * 9.0f));
if (slot.frame >= particle.lifetime - 40) { if (slot.process >= particle.lifetime - 40) {
slot.unknown_0002 -= 3; slot.alphaB -= 3;
if (slot.unknown_0002 < 0) { if (slot.alphaB < 0) {
slot.unknown_0002 = 0; slot.alphaB = 0;
} }
} else if (slot.unknown_0002 < 70) { } else if (slot.alphaB < 70) {
++slot.unknown_0002; ++slot.alphaB;
} }
for (int value = 0; value < 21; ++value) { for (int value = 0; value < 21; ++value) {
if (slot.finished[value] == 0) { if (slot.flag1[value] == 0) {
slot.values[value] = slot.unknown_0008; slot.height[value] = slot.maxHeight;
if (slot.values[value] < 0.0f) { if (slot.height[value] < 0.0f) {
slot.values[value] = 0; slot.height[value] = 0;
} }
} }
} }
@ -331,21 +332,21 @@ bool PulseEffectPrimitiveSlots(EffectPrimitiveState& particle, RenderObjectState
for (int index = 0; index < 4; ++index) { for (int index = 0; index < 4; ++index) {
EffectPrimitiveSlot& slot = particle.slots[index]; EffectPrimitiveSlot& slot = particle.slots[index];
if (slot.active != 1) { if (slot.life != 1) {
continue; continue;
} }
float phase = slot.unknown_0080 + 0.1f; float phase = slot.distance + 0.1f;
const int frame = ++slot.frame; const int frame = ++slot.process;
slot.unknown_0080 = phase; slot.distance = phase;
if (phase >= 13.0f) { if (phase >= 13.0f) {
slot.unknown_0080 = 3.0f; slot.distance = 3.0f;
slot.unknown_0002 = 0; slot.alphaB = 0;
phase = 3.0f; phase = 3.0f;
if (frame > 50) { if (frame > 50) {
slot.active = 0; slot.life = 0;
} }
} }
@ -355,23 +356,23 @@ bool PulseEffectPrimitiveSlots(EffectPrimitiveState& particle, RenderObjectState
if (phase > 5.0f) { if (phase > 5.0f) {
height = 10.0f - phase; height = 10.0f - phase;
if (slot.unknown_0002 > 0) { if (slot.alphaB > 0) {
slot.unknown_0002 -= 2; slot.alphaB -= 2;
} }
} else { } else {
slot.unknown_0002 += 2; slot.alphaB += 2;
height = phase; height = phase;
} }
slot.unknown_0008 = height * 2.0f; slot.maxHeight = height * 2.0f;
slot.unknown_007E = static_cast<std::int16_t>(static_cast<int>(90.0f - phase * 5.0f)); slot.riseAngle = static_cast<std::int16_t>(static_cast<int>(90.0f - phase * 5.0f));
for (int value = 0; value < 21; ++value) { for (int value = 0; value < 21; ++value) {
if (slot.finished[value] == 0) { if (slot.flag1[value] == 0) {
slot.values[value] = slot.unknown_0008; slot.height[value] = slot.maxHeight;
if (slot.values[value] < 0.0f) { if (slot.height[value] < 0.0f) {
slot.values[value] = 0; slot.height[value] = 0;
} }
} }
} }
@ -559,10 +560,10 @@ bool EffectParticle::AdvanceFrame() {
// OFFSET: 0x00BB5E80 // OFFSET: 0x00BB5E80
// FUNCTION: fn_19772 // FUNCTION: fn_19772
bool EffectParticle::UpdateFireWall() { bool EffectParticle::UpdateFireWall() {
const RagEffectState* parent = this->state.parent; const AttachedEffect* master = this->state.master;
this->render.position[0] = std::bit_cast<float>(parent->unknown_013C[3]); this->render.position[0] = master->render.position[0];
this->render.position[1] = std::bit_cast<float>(parent->unknown_013C[4]); this->render.position[1] = master->render.position[1];
this->render.position[2] = std::bit_cast<float>(parent->unknown_013C[5]); this->render.position[2] = master->render.position[2];
for (int index = 0; index < 4; ++index) { for (int index = 0; index < 4; ++index) {
if (this->state.scale == 3.0f && index < 3) { if (this->state.scale == 3.0f && index < 3) {
@ -571,38 +572,38 @@ bool EffectParticle::UpdateFireWall() {
EffectPrimitiveSlot& slot = this->state.slots[index]; EffectPrimitiveSlot& slot = this->state.slots[index];
if (slot.active != 1) { if (slot.life != 1) {
continue; continue;
} }
++slot.frame; ++slot.process;
if (index < 3) { if (index < 3) {
slot.angle = static_cast<std::int16_t>(slot.angle + index + 3); slot.rotStart = static_cast<std::int16_t>(slot.rotStart + index + 3);
} }
if (slot.angle >= 360) { if (slot.rotStart >= 360) {
slot.angle = static_cast<std::int16_t>(slot.angle - 360); slot.rotStart = static_cast<std::int16_t>(slot.rotStart - 360);
} }
const int limit = this->state.lifetime - 40; const int limit = this->state.lifetime - 40;
bool grown = false; bool grown = false;
if (slot.frame < limit) { if (slot.process < limit) {
if (slot.frame < 20) { if (slot.process < 20) {
if (index == 3) { if (index == 3) {
this->state.slots[3].unknown_0002 = static_cast<std::int16_t>(this->state.slots[3].unknown_0002 + 8); this->state.slots[3].alphaB = static_cast<std::int16_t>(this->state.slots[3].alphaB + 8);
if (this->state.slots[3].unknown_0002 > 100) { if (this->state.slots[3].alphaB > 100) {
this->state.slots[3].unknown_0002 = 100; this->state.slots[3].alphaB = 100;
} }
grown = true; grown = true;
} else { } else {
slot.unknown_0002 = static_cast<std::int16_t>(slot.unknown_0002 + 10); slot.alphaB = static_cast<std::int16_t>(slot.alphaB + 10);
if (slot.unknown_0002 > 180) { if (slot.alphaB > 180) {
slot.unknown_0002 = 180; slot.alphaB = 180;
} }
} }
} }
@ -612,16 +613,16 @@ bool EffectParticle::UpdateFireWall() {
} }
} else { } else {
if (index < 3) { if (index < 3) {
slot.unknown_0002 = static_cast<std::int16_t>(slot.unknown_0002 - 5); slot.alphaB = static_cast<std::int16_t>(slot.alphaB - 5);
if (slot.unknown_0002 < 0) { if (slot.alphaB < 0) {
slot.unknown_0002 = 0; slot.alphaB = 0;
} }
} else { } else {
slot.unknown_0002 = static_cast<std::int16_t>(slot.unknown_0002 - 3); slot.alphaB = static_cast<std::int16_t>(slot.alphaB - 3);
if (slot.unknown_0002 < 0) { if (slot.alphaB < 0) {
slot.unknown_0002 = 0; slot.alphaB = 0;
} }
grown = true; grown = true;
@ -630,46 +631,46 @@ bool EffectParticle::UpdateFireWall() {
if (!grown) { if (!grown) {
for (int sample = 0; sample < 21; ++sample) { for (int sample = 0; sample < 21; ++sample) {
if (slot.finished[sample] == 0) { if (slot.flag1[sample] == 0) {
if (slot.frame <= 90) { if (slot.process <= 90) {
slot.values[sample] = slot.unknown_0008 * ClientSine(sample * 9) * ClientSine(slot.frame); slot.height[sample] = slot.maxHeight * ClientSine(sample * 9) * ClientSine(slot.process);
} }
const float maximum = slot.unknown_0008 * ClientSine(sample * 9); const float maximum = slot.maxHeight * ClientSine(sample * 9);
if (slot.values[sample] > maximum) { if (slot.height[sample] > maximum) {
slot.values[sample] = maximum; slot.height[sample] = maximum;
slot.finished[sample] = 1; slot.flag1[sample] = 1;
} }
if (slot.values[sample] < 0.0f) { if (slot.height[sample] < 0.0f) {
slot.values[sample] = 0.0f; slot.height[sample] = 0.0f;
} }
} }
} }
} else { } else {
for (int sample = 0; sample < 21; ++sample) { for (int sample = 0; sample < 21; ++sample) {
if (slot.finished[sample] != 0) { if (slot.flag1[sample] != 0) {
const float base = slot.unknown_0008 * ClientSine(sample * 9) * 0.55f; const float base = slot.maxHeight * ClientSine(sample * 9) * 0.55f;
slot.values[sample] = base; slot.height[sample] = base;
slot.values[sample] = slot.unknown_0008 * ClientSine(sample * 9) * 0.45f * ClientSine(slot.frame % 360) + base; slot.height[sample] = slot.maxHeight * ClientSine(sample * 9) * 0.45f * ClientSine(slot.process % 360) + base;
} else { } else {
float value; float value;
if (slot.frame > 90) { if (slot.process > 90) {
slot.finished[sample] = 1; slot.flag1[sample] = 1;
value = slot.values[sample]; value = slot.height[sample];
} else { } else {
value = slot.unknown_0008 * ClientSine(sample * 9) * ClientSine(slot.frame); value = slot.maxHeight * ClientSine(sample * 9) * ClientSine(slot.process);
slot.values[sample] = value; slot.height[sample] = value;
} }
if (value > slot.unknown_0008 * ClientSine(sample * 9)) { if (value > slot.maxHeight * ClientSine(sample * 9)) {
slot.finished[sample] = 1; slot.flag1[sample] = 1;
} }
if (slot.values[sample] < 0.0f) { if (slot.height[sample] < 0.0f) {
slot.values[sample] = 0.0f; slot.height[sample] = 0.0f;
} }
} }
} }
@ -682,10 +683,10 @@ bool EffectParticle::UpdateFireWall() {
// OFFSET: 0x00BB63C0 // OFFSET: 0x00BB63C0
// FUNCTION: fn_19775 // FUNCTION: fn_19775
bool EffectParticle::UpdateStoneCurse() { bool EffectParticle::UpdateStoneCurse() {
const RagEffectState* parent = this->state.parent; const AttachedEffect* master = this->state.master;
this->render.position[0] = std::bit_cast<float>(parent->unknown_013C[3]); this->render.position[0] = master->render.position[0];
this->render.position[1] = std::bit_cast<float>(parent->unknown_013C[4]); this->render.position[1] = master->render.position[1];
this->render.position[2] = std::bit_cast<float>(parent->unknown_013C[5]); this->render.position[2] = master->render.position[2];
for (int index = 0; index < 4; ++index) { for (int index = 0; index < 4; ++index) {
if (this->state.scale == 3.0f && index < 3) { if (this->state.scale == 3.0f && index < 3) {
@ -694,59 +695,59 @@ bool EffectParticle::UpdateStoneCurse() {
EffectPrimitiveSlot& slot = this->state.slots[index]; EffectPrimitiveSlot& slot = this->state.slots[index];
if (slot.active != 1) { if (slot.life != 1) {
continue; continue;
} }
++slot.frame; ++slot.process;
if (index < 3) { if (index < 3) {
slot.angle = static_cast<std::int16_t>(slot.angle + index + 3); slot.rotStart = static_cast<std::int16_t>(slot.rotStart + index + 3);
} }
if (slot.angle >= 360) { if (slot.rotStart >= 360) {
slot.angle = static_cast<std::int16_t>(slot.angle - 360); slot.rotStart = static_cast<std::int16_t>(slot.rotStart - 360);
} }
if (slot.frame < this->state.lifetime - 40) { if (slot.process < this->state.lifetime - 40) {
if (slot.frame < 20 && slot.unknown_0004 != 1) { if (slot.process < 20 && slot.alphaT != 1) {
if (index == 3) { if (index == 3) {
this->state.slots[3].unknown_0002 = static_cast<std::int16_t>(this->state.slots[3].unknown_0002 + 8); this->state.slots[3].alphaB = static_cast<std::int16_t>(this->state.slots[3].alphaB + 8);
if (this->state.slots[3].unknown_0002 > 60) { if (this->state.slots[3].alphaB > 60) {
this->state.slots[3].unknown_0002 = 60; this->state.slots[3].alphaB = 60;
} }
} else { } else {
slot.unknown_0002 = static_cast<std::int16_t>(slot.unknown_0002 + 10); slot.alphaB = static_cast<std::int16_t>(slot.alphaB + 10);
if (slot.unknown_0002 > 180) { if (slot.alphaB > 180) {
slot.unknown_0002 = 180; slot.alphaB = 180;
} }
} }
} }
} else { } else {
slot.unknown_0002 = static_cast<std::int16_t>(slot.unknown_0002 - (index >= 3 ? 2 : 5)); slot.alphaB = static_cast<std::int16_t>(slot.alphaB - (index >= 3 ? 2 : 5));
if (slot.unknown_0002 < 0) { if (slot.alphaB < 0) {
slot.unknown_0002 = 0; slot.alphaB = 0;
} }
} }
for (int sample = 0; sample < 21; ++sample) { for (int sample = 0; sample < 21; ++sample) {
if (slot.finished[sample] == 0) { if (slot.flag1[sample] == 0) {
if (slot.frame <= 90) { if (slot.process <= 90) {
slot.values[sample] = slot.unknown_0008 * ClientSine(sample * 9) * ClientSine(slot.frame); slot.height[sample] = slot.maxHeight * ClientSine(sample * 9) * ClientSine(slot.process);
} }
const float maximum = slot.unknown_0008 * ClientSine(sample * 9); const float maximum = slot.maxHeight * ClientSine(sample * 9);
if (slot.values[sample] > maximum) { if (slot.height[sample] > maximum) {
slot.values[sample] = maximum; slot.height[sample] = maximum;
slot.finished[sample] = 1; slot.flag1[sample] = 1;
} }
if (slot.values[sample] < 0.0f) { if (slot.height[sample] < 0.0f) {
slot.values[sample] = 0.0f; slot.height[sample] = 0.0f;
} }
} }
} }
@ -758,10 +759,10 @@ bool EffectParticle::UpdateStoneCurse() {
// OFFSET: 0x00BB65C0 // OFFSET: 0x00BB65C0
// FUNCTION: fn_19776 // FUNCTION: fn_19776
void EffectParticle::UpdateBeginSpell() { void EffectParticle::UpdateBeginSpell() {
const RagEffectState* parent = this->state.parent; const AttachedEffect* master = this->state.master;
this->state.origin.x = std::bit_cast<float>(parent->unknown_013C[3]) + this->state.velocity.x; this->state.origin.x = master->render.position[0] + this->state.velocity.x;
this->state.origin.y = std::bit_cast<float>(parent->unknown_013C[4]) + this->state.velocity.y; this->state.origin.y = master->render.position[1] + this->state.velocity.y;
this->state.origin.z = std::bit_cast<float>(parent->unknown_013C[5]) + this->state.velocity.z; this->state.origin.z = master->render.position[2] + this->state.velocity.z;
float base; float base;
@ -815,41 +816,117 @@ void EffectParticle::UpdateBeginSpell() {
// OFFSET: 0x00BBAB10 // OFFSET: 0x00BBAB10
// FUNCTION: fn_19790 // FUNCTION: fn_19790
void EffectParticle::PrimBottom2() { void EffectParticle::PrimBottom2() {
const RagEffectState* parent = this->state.parent; const AttachedEffect* master = this->state.master;
this->render.position[0] = std::bit_cast<float>(parent->unknown_013C[3]); this->render.position[0] = master->render.position[0];
this->render.position[1] = std::bit_cast<float>(parent->unknown_013C[4]); this->render.position[1] = master->render.position[1];
this->render.position[2] = std::bit_cast<float>(parent->unknown_013C[5]); this->render.position[2] = master->render.position[2];
for (int index = 0; index < 4; ++index) { for (int index = 0; index < 4; ++index) {
EffectPrimitiveSlot& slot = this->state.slots[index]; EffectPrimitiveSlot& slot = this->state.slots[index];
if (slot.active != 1) { if (slot.life != 1) {
continue; continue;
} }
++slot.frame; ++slot.process;
if (slot.values[0] == 1.0f) { if (slot.height[0] == 1.0f) {
slot.displayAngle += 4; slot.fullDisplayAngle += 4;
} else { } else {
slot.displayAngle += 2; slot.fullDisplayAngle += 2;
} }
if (slot.displayAngle >= 360) { if (slot.fullDisplayAngle >= 360) {
slot.displayAngle -= 360; slot.fullDisplayAngle -= 360;
} }
slot.unknown_0008 = 20.0f + 10.0f * ClientSine(slot.displayAngle); slot.maxHeight = 20.0f + 10.0f * ClientSine(slot.fullDisplayAngle);
}
}
// OFFSET: 0x00BBABC0
// FUNCTION: fn_19791
void EffectParticle::PrimBottom() {
const CView* view = static_cast<CGameMode*>(g_world.ActiveGameMode())->camera;
EffectPrimitiveSlot* slots = this->state.slots;
slots[0].alphaT = static_cast<std::int16_t>(360 - static_cast<int>(view->camera.yaw));
slots[1].alphaT = static_cast<std::int16_t>(360 - static_cast<int>(view->camera.pitch) + 90);
if (slots[1].alphaT >= 360) {
slots[1].alphaT -= 360;
}
const AttachedEffect* master = this->state.master;
this->render.position[0] = master->render.position[0];
this->render.position[1] = master->render.position[1];
this->render.position[2] = master->render.position[2];
EffectPrimitiveSlot& slot = slots[0];
if (slot.life != 1) {
return;
}
++slot.process;
if (slot.process % 6 == 0) {
for (int index = 3; index > 0; --index) {
EffectPrimitiveSlot& trail = slots[index];
const EffectPrimitiveSlot& previous = slots[index - 1];
if (trail.life > 0) {
trail.fullDisplayAngle = previous.fullDisplayAngle;
trail.distance = previous.distance + 0.5f;
trail.height[8] = previous.height[8];
trail.alphaB = previous.alphaB - 50;
if (trail.alphaB < 0) {
trail.alphaB = 0;
}
trail.vecBNow = previous.vecBNow;
trail.fullDisplayAngle = previous.fullDisplayAngle;
trail.flag1[0] = previous.flag1[0];
trail.flag1[2] = 2;
trail.height[7] = 0;
}
}
}
slot.height[8] += 5.0f;
if (slot.height[8] >= 360.0f) {
slot.height[8] -= 360.0f;
}
++slot.rotStart;
if (slot.rotStart >= 360) {
slot.rotStart -= 360;
}
slot.vecBNow.x = this->render.position[0];
slot.vecBNow.z = this->render.position[2];
slot.vecBPre.y = this->render.position[1] - 6.0f;
slot.vecBNow.y = slot.vecBPre.y + 3.0f * ClientSine(slot.rotStart);
if (slot.flag1[2] == 7) {
slot.fullDisplayAngle += 10;
if (slot.fullDisplayAngle >= 360) {
slot.fullDisplayAngle -= 360;
}
} }
} }
// OFFSET: 0x00BB6F30 // OFFSET: 0x00BB6F30
// FUNCTION: fn_19779 // FUNCTION: fn_19779
bool EffectParticle::UpdateHit6() { bool EffectParticle::UpdateHit6() {
const RagEffectState* parent = this->state.parent; const AttachedEffect* master = this->state.master;
this->state.origin.x = std::bit_cast<float>(parent->unknown_013C[3]) + this->state.velocity.x; this->state.origin.x = master->render.position[0] + this->state.velocity.x;
this->state.origin.y = std::bit_cast<float>(parent->unknown_013C[4]) + this->state.velocity.y; this->state.origin.y = master->render.position[1] + this->state.velocity.y;
this->state.origin.z = std::bit_cast<float>(parent->unknown_013C[5]) + this->state.velocity.z; this->state.origin.z = master->render.position[2] + this->state.velocity.z;
const int frame = this->state.unknown_01E0; const int frame = this->state.unknown_01E0;
@ -930,7 +1007,7 @@ bool EffectParticle::UpdateHit6() {
this->render.position[2] = this->state.offset.z + this->state.origin.z; this->render.position[2] = this->state.offset.z + this->state.origin.z;
if ((this->state.flags & 0x100u) != 0) { if ((this->state.flags & 0x100u) != 0) {
if (3.0f >= this->HorizontalDistance(this->state.parent->offset[0], this->state.parent->offset[2])) { if (3.0f >= this->HorizontalDistance(this->state.master->state.offset[0], this->state.master->state.offset[2])) {
return false; return false;
} }
} }
@ -948,10 +1025,10 @@ bool EffectParticle::UpdateHit6() {
// FUNCTION: fn_19780 // FUNCTION: fn_19780
bool EffectParticle::UpdateCoin() { bool EffectParticle::UpdateCoin() {
CGameMode* mode = static_cast<CGameMode*>(g_world.ActiveGameMode()); CGameMode* mode = static_cast<CGameMode*>(g_world.ActiveGameMode());
const RagEffectState* parent = this->state.parent; const AttachedEffect* master = this->state.master;
this->state.origin.z = std::bit_cast<float>(parent->unknown_013C[5]) + this->state.velocity.z; this->state.origin.z = master->render.position[2] + this->state.velocity.z;
this->state.origin.y = std::bit_cast<float>(parent->unknown_013C[4]) + this->state.velocity.y; this->state.origin.y = master->render.position[1] + this->state.velocity.y;
this->state.origin.x = std::bit_cast<float>(parent->unknown_013C[3]) + this->state.velocity.x; this->state.origin.x = master->render.position[0] + this->state.velocity.x;
this->state.unknown_02EC = this->state.unknown_02F0 + this->state.unknown_02EC; this->state.unknown_02EC = this->state.unknown_02F0 + this->state.unknown_02EC;
const float speed = this->state.unknown_02C0 + this->state.unknown_02BC; const float speed = this->state.unknown_02C0 + this->state.unknown_02BC;
@ -1082,8 +1159,8 @@ bool EffectParticle::UpdateDetoxication() {
// OFFSET: 0x00BB7EC0 // OFFSET: 0x00BB7EC0
// FUNCTION: fn_19782 // FUNCTION: fn_19782
bool EffectParticle::UpdateExit() { bool EffectParticle::UpdateExit() {
const RagEffectState* parent = this->state.parent; const AttachedEffect* master = this->state.master;
this->state.origin = {std::bit_cast<float>(parent->unknown_013C[3]), std::bit_cast<float>(parent->unknown_013C[4]), std::bit_cast<float>(parent->unknown_013C[5])}; this->state.origin = {master->render.position[0], master->render.position[1], master->render.position[2]};
const float lateral = this->state.unknown_033C + this->state.unknown_0330; const float lateral = this->state.unknown_033C + this->state.unknown_0330;
float vertical = this->state.unknown_02EC + this->state.unknown_02F0; float vertical = this->state.unknown_02EC + this->state.unknown_02F0;
@ -1146,10 +1223,10 @@ bool EffectParticle::UpdateExit() {
// OFFSET: 0x00BB8180 // OFFSET: 0x00BB8180
// FUNCTION: fn_19783 // FUNCTION: fn_19783
bool EffectParticle::UpdateWarp() { bool EffectParticle::UpdateWarp() {
const RagEffectState* parent = this->state.parent; const AttachedEffect* master = this->state.master;
this->state.origin = { this->state.origin = {
std::bit_cast<float>(parent->unknown_013C[3]) + this->state.velocity.x, std::bit_cast<float>(parent->unknown_013C[4]) + this->state.velocity.y, master->render.position[0] + this->state.velocity.x, master->render.position[1] + this->state.velocity.y,
std::bit_cast<float>(parent->unknown_013C[5]) + this->state.velocity.z master->render.position[2] + this->state.velocity.z
}; };
const int angle = static_cast<int>(this->state.unknown_0314); const int angle = static_cast<int>(this->state.unknown_0314);

View file

@ -1,4 +1,5 @@
#include "Contents/Effects/EffectPrimitiveRendering.h" #include "Contents/Effects/EffectPrimitiveRendering.h"
#include "Contents/Effects/AttachedEffect.h"
#include "Contents/Effects/EffectPrimitiveState.h" #include "Contents/Effects/EffectPrimitiveState.h"
#include "Contents/Effects/EffectVisibility.h" #include "Contents/Effects/EffectVisibility.h"
#include "Contents/Actors/RenderObjectState.h" #include "Contents/Actors/RenderObjectState.h"
@ -86,7 +87,7 @@ void DrawEffectPrimitive15(EffectPrimitiveState& particle, const RenderObjectSta
void RenderEffectPrimitive15( void RenderEffectPrimitive15(
EffectPrimitiveState& particle, const RenderObjectState& render, EffectPrimitiveRenderContext& context, const EffectVisibilityContext& visibility EffectPrimitiveState& particle, const RenderObjectState& render, EffectPrimitiveRenderContext& context, const EffectVisibilityContext& visibility
) { ) {
if (particle.parent && PartyEffectVisible(*particle.parent, visibility)) { if (particle.master && PartyEffectVisible(particle.master->state, visibility)) {
DrawEffectPrimitive15(particle, render, context); DrawEffectPrimitive15(particle, render, context);
} }
} }

View file

@ -1,5 +1,5 @@
#include "Contents/Effects/EffectPrimitiveState.h" #include "Contents/Effects/EffectPrimitiveState.h"
#include "Contents/Effects/RagEffectState.h" #include "Contents/Effects/AttachedEffect.h"
#include "Contents/Actors/RenderObjectState.h" #include "Contents/Actors/RenderObjectState.h"
#include "Utility/Math/AffineMatrix.h" #include "Utility/Math/AffineMatrix.h"
@ -10,7 +10,7 @@
// FUNCTION: fn_19762 // FUNCTION: fn_19762
EffectPrimitiveSlot::EffectPrimitiveSlot() { EffectPrimitiveSlot::EffectPrimitiveSlot() {
for (int i = 0; i < 4; ++i) { for (int i = 0; i < 4; ++i) {
this->unknown_0084[i] = {0.0f, 0.0f, 0.0f}; this->vectors[i] = {0.0f, 0.0f, 0.0f};
} }
} }
@ -29,7 +29,7 @@ EffectPrimitiveState::EffectPrimitiveState(RenderObjectState& render) {
this->unknown_0158 = 0; this->unknown_0158 = 0;
this->unknown_015C = 0; this->unknown_015C = 0;
this->unknown_0138 = 0; this->unknown_0138 = 0;
this->parent = nullptr; this->master = nullptr;
this->unknown_01D4 = 0; this->unknown_01D4 = 0;
this->unknown_01D8 = 0; this->unknown_01D8 = 0;
this->unknown_01E0 = 0; this->unknown_01E0 = 0;
@ -146,8 +146,8 @@ EffectPrimitiveState::EffectPrimitiveState(RenderObjectState& render) {
// INLINED // INLINED
EffectPrimitiveState::~EffectPrimitiveState() { EffectPrimitiveState::~EffectPrimitiveState() {
if (this->parent) { if (this->master) {
auto& related = this->parent->related; auto& related = this->master->state.related;
for (auto entry = related.begin(); entry != related.end(); ++entry) { for (auto entry = related.begin(); entry != related.end(); ++entry) {
if (*entry == this) { if (*entry == this) {
@ -165,16 +165,16 @@ EffectPrimitiveState::~EffectPrimitiveState() {
// OFFSET: 0x00BAE460 // OFFSET: 0x00BAE460
// FUNCTION: fn_19765 // FUNCTION: fn_19765
void EffectPrimitiveState::GetColorOverride(unsigned char* red, unsigned char* green, unsigned char* blue) { void EffectPrimitiveState::GetColorOverride(unsigned char* red, unsigned char* green, unsigned char* blue) {
if (this->parent->unknown_11C88[0] != -1) { if (this->master->state.unknown_11C88[0] != -1) {
*red = static_cast<unsigned char>(this->parent->unknown_11C88[0]); *red = static_cast<unsigned char>(this->master->state.unknown_11C88[0]);
} }
if (this->parent->unknown_11C88[1] != -1) { if (this->master->state.unknown_11C88[1] != -1) {
*green = static_cast<unsigned char>(this->parent->unknown_11C88[1]); *green = static_cast<unsigned char>(this->master->state.unknown_11C88[1]);
} }
if (this->parent->unknown_11C88[2] != -1) { if (this->master->state.unknown_11C88[2] != -1) {
*blue = static_cast<unsigned char>(this->parent->unknown_11C88[2]); *blue = static_cast<unsigned char>(this->master->state.unknown_11C88[2]);
} }
} }
@ -198,15 +198,15 @@ void __stdcall CalculateVectorAngle(float x, float y, std::int16_t* angle) {
// OFFSET: 0x00BAE5D0 // OFFSET: 0x00BAE5D0
// FUNCTION: fn_19767 // FUNCTION: fn_19767
void EffectPrimitiveState::Initialize( void EffectPrimitiveState::Initialize(
RenderObjectState& render, RagEffectState& parent, const RenderObjectState& parentRender, int type, float x, float y, float z RenderObjectState& render, AttachedEffect& master, const RenderObjectState& masterRender, int type, float x, float y, float z
) { ) {
const float first = x + this->offset.x; const float first = x + this->offset.x;
this->parent = &parent; this->master = &master;
this->type = type; this->type = type;
this->offset.x = first; this->offset.x = first;
this->offset.y = y + this->offset.y; this->offset.y = y + this->offset.y;
this->offset.z = z + this->offset.z; this->offset.z = z + this->offset.z;
this->origin = {parentRender.position[0], parentRender.position[1], parentRender.position[2]}; this->origin = {masterRender.position[0], masterRender.position[1], masterRender.position[2]};
render.position[0] = this->origin.x; render.position[0] = this->origin.x;
render.position[1] = this->origin.y; render.position[1] = this->origin.y;
render.position[2] = this->origin.z; render.position[2] = this->origin.z;

View file

@ -8,7 +8,7 @@
#include <vector> #include <vector>
#include "Contents/Actors/RenderObjectState.h" #include "Contents/Actors/RenderObjectState.h"
struct RagEffectState; struct AttachedEffect;
class CTexture; class CTexture;
struct EffectVector3 { struct EffectVector3 {
@ -33,34 +33,42 @@ struct EffectPrimitiveRecord {
struct EffectPrimitiveSlot { struct EffectPrimitiveSlot {
EffectPrimitiveSlot(); EffectPrimitiveSlot();
/* 0000 */ unsigned char active; /* 0000 */ unsigned char life;
/* 0001 */ unsigned char unknown_0001; /* 0001 */ unsigned char unknown_0001;
/* 0002 */ std::int16_t unknown_0002; /* 0002 */ std::int16_t alphaB;
/* 0004 */ std::int16_t unknown_0004; /* 0004 */ std::int16_t alphaT;
/* 0006 */ std::int16_t displayAngle; /* 0006 */ std::int16_t fullDisplayAngle;
/* 0008 */ float unknown_0008; /* 0008 */ float maxHeight;
/* 000C */ int frame; /* 000C */ int process;
/* 0010 */ std::int16_t angle; /* 0010 */ std::int16_t rotStart;
/* 0012 */ unsigned char unknown_0012[2]; /* 0012 */ unsigned char unknown_0012[2];
/* 0014 */ float values[21]; /* 0014 */ float height[21];
/* 0068 */ unsigned char finished[21]; /* 0068 */ unsigned char flag1[21];
/* 007D */ unsigned char unknown_007D; /* 007D */ unsigned char unknown_007D;
/* 007E */ std::int16_t unknown_007E; /* 007E */ std::int16_t riseAngle;
/* 0080 */ float unknown_0080; /* 0080 */ float distance;
/* 0084 */ EffectVector3 unknown_0084[4]; union {
/* 0084 */ EffectVector3 vectors[4];
struct {
/* 0084 */ EffectVector3 vecBNow;
/* 0090 */ EffectVector3 vecTNow;
/* 009C */ EffectVector3 vecBPre;
/* 00A8 */ EffectVector3 vecTPre;
};
};
}; };
struct EffectPrimitiveState { struct EffectPrimitiveState {
explicit EffectPrimitiveState(RenderObjectState& render); explicit EffectPrimitiveState(RenderObjectState& render);
~EffectPrimitiveState(); ~EffectPrimitiveState();
void Initialize(RenderObjectState& render, RagEffectState& parent, const RenderObjectState& parentRender, int type, float x, float y, float z); void Initialize(RenderObjectState& render, AttachedEffect& master, const RenderObjectState& masterRender, int type, float x, float y, float z);
void UpdateColor(); void UpdateColor();
void InitializeRecords(const RenderObjectState& render); void InitializeRecords(const RenderObjectState& render);
void GetColorOverride(unsigned char* red, unsigned char* green, unsigned char* blue); void GetColorOverride(unsigned char* red, unsigned char* green, unsigned char* blue);
/* 0138 */ std::uint32_t unknown_0138; /* 0138 */ std::uint32_t unknown_0138;
/* 013C */ std::uint32_t unknown_013C; /* 013C */ std::uint32_t unknown_013C;
/* 0140 */ RagEffectState* parent; /* 0140 */ AttachedEffect* master;
/* 0144 */ CTexture** textures; /* 0144 */ CTexture** textures;
/* 0148 */ std::uint32_t unknown_0148; /* 0148 */ std::uint32_t unknown_0148;
/* 014C */ EffectVector3 unknown_014C; /* 014C */ EffectVector3 unknown_014C;
@ -185,9 +193,9 @@ static_assert(offsetof(EffectVector3, z) == 0x8);
static_assert(offsetof(EffectPrimitiveRecord, corners) == 0xC); static_assert(offsetof(EffectPrimitiveRecord, corners) == 0xC);
static_assert(offsetof(EffectPrimitiveRecord, matrix) == 0x48); static_assert(offsetof(EffectPrimitiveRecord, matrix) == 0x48);
static_assert(offsetof(EffectPrimitiveRecord, color) == 0x88); static_assert(offsetof(EffectPrimitiveRecord, color) == 0x88);
static_assert(offsetof(EffectPrimitiveSlot, values) == 0x14); static_assert(offsetof(EffectPrimitiveSlot, height) == 0x14);
static_assert(offsetof(EffectPrimitiveSlot, finished) == 0x68); static_assert(offsetof(EffectPrimitiveSlot, flag1) == 0x68);
static_assert(offsetof(EffectPrimitiveSlot, unknown_0084) == 0x84); static_assert(offsetof(EffectPrimitiveSlot, vecBNow) == 0x84);
static_assert(sizeof(EffectPrimitiveState) == 0xF8E0); static_assert(sizeof(EffectPrimitiveState) == 0xF8E0);
#endif #endif

View file

@ -1,7 +1,7 @@
#include "Contents/Effects/AttachedEffect.h"
#include "Contents/Effects/EffectActor.h" #include "Contents/Effects/EffectActor.h"
#include "Contents/Effects/EffectParticle.h" #include "Contents/Effects/EffectParticle.h"
#include "Contents/Effects/PartyEffect.h" #include "Contents/Effects/PartyEffect.h"
#include "Contents/Effects/RagEffectState.h"
#include "Contents/Ground/TerrainHeight.h" #include "Contents/Ground/TerrainHeight.h"
#include "Render/Textures/TextureCache.h" #include "Render/Textures/TextureCache.h"
@ -10,9 +10,12 @@
// OFFSET: 0x00C2CF20 // OFFSET: 0x00C2CF20
// FUNCTION: fn_20088 // FUNCTION: fn_20088
bool UpdatePartyEffect( bool UpdatePartyEffect(
RagEffectState& effect, RenderObjectState& render, ResourceMgr& resources, JobNames& names, std::list<CRenderObject*>& worldObjects, TextureCache& textures, AttachedEffect& self, ResourceMgr& resources, JobNames& names, std::list<CRenderObject*>& worldObjects, TextureCache& textures, const TerrainHeight& ground,
const TerrainHeight& ground, int updateTick int updateTick
) { ) {
RagEffectState& effect = self.state;
RenderObjectState& render = self.render;
if (!effect.parent) { if (!effect.parent) {
return false; return false;
} }
@ -36,7 +39,7 @@ bool UpdatePartyEffect(
} }
if (effect.unknown_0178 == 0) { if (effect.unknown_0178 == 0) {
EffectParticle* particle = CreateEffectParticle(effect, render, 15, 0, 0, 0, resources, names, worldObjects); EffectParticle* particle = CreateEffectParticle(self, render, 15, 0, 0, 0, resources, names, worldObjects);
effect.unknown_11C84 = &particle->state; effect.unknown_11C84 = &particle->state;
EffectPrimitiveState& state = *effect.unknown_11C84; EffectPrimitiveState& state = *effect.unknown_11C84;
state.lifetime = 9999; state.lifetime = 9999;

View file

@ -3,8 +3,7 @@
#include <list> #include <list>
struct RagEffectState; struct AttachedEffect;
struct RenderObjectState;
struct EffectParticle; struct EffectParticle;
struct JobNames; struct JobNames;
struct TerrainHeight; struct TerrainHeight;
@ -13,8 +12,8 @@ class TextureCache;
class CRenderObject; class CRenderObject;
bool UpdatePartyEffect( bool UpdatePartyEffect(
RagEffectState& effect, RenderObjectState& render, ResourceMgr& resources, JobNames& names, std::list<CRenderObject*>& worldObjects, TextureCache& textures, AttachedEffect& self, ResourceMgr& resources, JobNames& names, std::list<CRenderObject*>& worldObjects, TextureCache& textures, const TerrainHeight& ground,
const TerrainHeight& ground, int updateTick int updateTick
); );
#endif #endif