From c6cc9dc69e7f043465c8fa61307352d5951b3e1f Mon Sep 17 00:00:00 2001 From: ragnarok-clanker Date: Tue, 27 Oct 2026 21:09:20 +0000 Subject: [PATCH] Decompile 6 functions in Source/Contents/Effects/EffectPrimitiveState.cpp, Source/Contents/Effects/EffectPrimitiveState.h, ... Batch #1199 by eAthena: 0 byte-identical, 6 confirmed by peer review. - fn_19765 EffectPrimitiveState::GetColorOverride: logic confirmed by peer review - fn_19773 ShrinkEffectPrimitiveSlots: logic confirmed by peer review - fn_19774 PulseEffectPrimitiveSlots: logic confirmed by peer review - fn_19777 SpinEffectPrimitive: logic confirmed by peer review - fn_19778 RollEffectPrimitive: logic confirmed by peer review - fn_19784 AdvanceEffectPrimitive: logic confirmed by peer review Reviewed-by: ragnarok-clanker --- .../Effects/EffectPrimitiveMotion.cpp | 267 ++++++++++++++++++ .../Contents/Effects/EffectPrimitiveMotion.h | 5 + .../Contents/Effects/EffectPrimitiveState.cpp | 18 +- .../Contents/Effects/EffectPrimitiveState.h | 37 ++- 4 files changed, 319 insertions(+), 8 deletions(-) diff --git a/Source/Contents/Effects/EffectPrimitiveMotion.cpp b/Source/Contents/Effects/EffectPrimitiveMotion.cpp index 6da70b46..d40e838b 100644 --- a/Source/Contents/Effects/EffectPrimitiveMotion.cpp +++ b/Source/Contents/Effects/EffectPrimitiveMotion.cpp @@ -19,6 +19,16 @@ namespace { ((matrix[5] * point.y + matrix[2] * point.x) + point.z * matrix[8]) + matrix[11] }; } + + // INLINED + EffectVector3 Upward(float distance, const float* matrix) { + const EffectVector3 point{0.0f, -distance, 0.0f}; + return { + ((matrix[3] * point.y + matrix[0] * point.x) + point.z * matrix[6]) + matrix[9], + ((matrix[4] * point.y + matrix[1] * point.x) + point.z * matrix[7]) + matrix[10], + ((matrix[5] * point.y + matrix[2] * point.x) + point.z * matrix[8]) + matrix[11] + }; + } } // OFFSET: 0x00BB8C50 @@ -239,3 +249,260 @@ bool UpdateEffectPrimitive15(EffectPrimitiveState& particle, RenderObjectState& ++particle.unknown_01E0; return particle.unknown_01E0 <= particle.lifetime; } + +// OFFSET: 0x00BB6180 +// FUNCTION: fn_19773 +bool ShrinkEffectPrimitiveSlots(EffectPrimitiveState& particle, RenderObjectState& render, EffectMotionContext& context) { + render.position[0] = context.parentRender.position[0]; + render.position[1] = context.parentRender.position[1]; + render.position[2] = context.parentRender.position[2]; + + for (int index = 0; index < 4; ++index) { + EffectPrimitiveSlot& slot = particle.slots[index]; + + if (slot.active != 1) { + continue; + } + + float height = slot.unknown_0080 - 0.05f; + ++slot.frame; + slot.unknown_0080 = height; + + if (height <= 0.0f) { + slot.unknown_0080 = 10.0f; + slot.unknown_0002 = 0; + height = 10.0f; + } + + slot.unknown_0008 = height; + slot.unknown_007E = static_cast(static_cast(90.0f - height * 9.0f)); + + if (slot.frame >= particle.lifetime - 40) { + slot.unknown_0002 -= 3; + + if (slot.unknown_0002 < 0) { + slot.unknown_0002 = 0; + } + } else if (slot.unknown_0002 < 70) { + ++slot.unknown_0002; + } + + for (int value = 0; value < 21; ++value) { + if (slot.finished[value] == 0) { + slot.values[value] = slot.unknown_0008; + + if (slot.values[value] < 0.0f) { + slot.values[value] = 0; + } + } + } + } + + return true; +} + +// OFFSET: 0x00BB62A0 +// FUNCTION: fn_19774 +bool PulseEffectPrimitiveSlots(EffectPrimitiveState& particle, RenderObjectState& render, EffectMotionContext& context) { + render.position[0] = context.parentRender.position[0]; + render.position[1] = context.parentRender.position[1]; + render.position[2] = context.parentRender.position[2]; + + for (int index = 0; index < 4; ++index) { + EffectPrimitiveSlot& slot = particle.slots[index]; + + if (slot.active != 1) { + continue; + } + + float phase = slot.unknown_0080 + 0.1f; + const int frame = ++slot.frame; + slot.unknown_0080 = phase; + + if (phase >= 13.0f) { + slot.unknown_0080 = 3.0f; + slot.unknown_0002 = 0; + phase = 3.0f; + + if (frame > 50) { + slot.active = 0; + } + } + + phase -= 3.0f; + float height; + + if (phase > 5.0f) { + height = 10.0f - phase; + + if (slot.unknown_0002 > 0) { + slot.unknown_0002 -= 2; + } + } else { + slot.unknown_0002 += 2; + height = phase; + } + + slot.unknown_0008 = height * 2.0f; + slot.unknown_007E = static_cast(static_cast(90.0f - phase * 5.0f)); + + for (int value = 0; value < 21; ++value) { + if (slot.finished[value] == 0) { + slot.values[value] = slot.unknown_0008; + + if (slot.values[value] < 0.0f) { + slot.values[value] = 0; + } + } + } + } + + return true; +} + +// OFFSET: 0x00BB6820 +// FUNCTION: fn_19777 +bool SpinEffectPrimitive(EffectPrimitiveState& particle, RenderObjectState& render, EffectMotionContext& context) { + particle.origin = { + context.parentRender.position[0] + particle.velocity.x, context.parentRender.position[1] + particle.velocity.y, + context.parentRender.position[2] + particle.velocity.z + }; + + particle.unknown_02BC = particle.unknown_02C0 + particle.unknown_02BC; + particle.unknown_0334 = particle.unknown_0340 + particle.unknown_0334; + particle.unknown_0364 = particle.unknown_0368 + particle.unknown_0364; + particle.unknown_0310 = particle.unknown_0334 + particle.unknown_0310; + particle.unknown_0300 = particle.unknown_0308 + particle.unknown_0300; + particle.unknown_02FC = particle.unknown_0304 + particle.unknown_02FC; + particle.unknown_0330 = particle.unknown_033C + particle.unknown_0330; + particle.unknown_030C = particle.unknown_0330 + particle.unknown_030C; + + AffineMatrix& matrix = *reinterpret_cast(particle.matrix1); + matrix.SetXRotation(ClientRadians(static_cast(particle.unknown_0310))); + matrix.RotateY(ClientRadians(static_cast(particle.unknown_030C))); + + particle.unknown_0370 = Upward(particle.unknown_02BC, particle.matrix1); + particle.offset.y = particle.unknown_0370.y + particle.offset.y; + particle.offset.x = particle.unknown_0370.x + particle.offset.x; + particle.offset.z = particle.unknown_0370.z + particle.offset.z; + particle.unknown_030C = particle.unknown_0330 + particle.unknown_030C; + particle.unknown_02F4 += particle.unknown_02FC; + render.position[0] = particle.offset.x + particle.origin.x; + render.position[1] = particle.offset.y + particle.origin.y; + render.position[2] = particle.offset.z + particle.origin.z; + particle.unknown_02F8 += particle.unknown_0300; + particle.unknown_0360 = particle.unknown_0364 + particle.unknown_0360; + + if (particle.unknown_0360 > particle.unknown_036C) { + particle.unknown_0360 = particle.unknown_036C; + } + + if ((particle.flags & 1u) != 0 && particle.unknown_01E0 == particle.unknown_01F0) { + particle.unknown_0300 = -(particle.unknown_02F8 / static_cast(particle.lifetime - particle.unknown_01E0 + 1)); + } + + particle.UpdateColor(); + + if (particle.unknown_01E0 % particle.unknown_01E8 == 0) { + const auto next = render.unknown_003C + 1u; + render.unknown_003C = next; + + if (particle.unknown_0254 != 0) { + render.unknown_003C = static_cast(next) % static_cast(particle.textureCount); + } else if (next == particle.textureCount) { + return false; + } + } + + return true; +} + +// OFFSET: 0x00BB6B30 +// FUNCTION: fn_19778 +bool RollEffectPrimitive(EffectPrimitiveState& particle, RenderObjectState& render, EffectMotionContext& context) { + particle.origin = { + context.parentRender.position[0] + particle.velocity.x, context.parentRender.position[1] + particle.velocity.y, + context.parentRender.position[2] + particle.velocity.z + }; + + particle.unknown_02BC = particle.unknown_02C0 + particle.unknown_02BC; + particle.unknown_0300 = particle.unknown_0308 + particle.unknown_0300; + particle.unknown_02FC = particle.unknown_0304 + particle.unknown_02FC; + particle.unknown_0364 = particle.unknown_0368 + particle.unknown_0364; + + AffineMatrix& matrix = *reinterpret_cast(particle.matrix1); + matrix.SetXRotation(ClientRadians(static_cast(particle.unknown_0310))); + matrix.RotateY(ClientRadians(static_cast(particle.unknown_030C))); + + particle.unknown_0370 = Upward(particle.unknown_02BC, particle.matrix1); + particle.offset.x = particle.unknown_0370.x + particle.offset.x; + particle.offset.y = particle.unknown_0370.y + particle.offset.y; + particle.offset.z = particle.unknown_0370.z + particle.offset.z; + render.position[0] = particle.offset.x + particle.origin.x; + render.position[1] = particle.offset.y + particle.origin.y; + render.position[2] = particle.offset.z + particle.origin.z; + particle.unknown_030C = particle.unknown_0330 + particle.unknown_030C; + particle.unknown_02F8 = particle.unknown_0300 + particle.unknown_02F8; + particle.unknown_02F4 = particle.unknown_02FC + particle.unknown_02F4; + particle.unknown_0360 += particle.unknown_0364; + + if (particle.unknown_0360 > particle.unknown_036C) { + particle.unknown_0360 = particle.unknown_036C; + } + + if ((particle.flags & 1u) != 0 && particle.unknown_01E0 == particle.unknown_01F0) { + particle.unknown_0300 = -(particle.unknown_02F8 / static_cast(particle.lifetime - particle.unknown_01E0 + 1)); + } + + particle.UpdateColor(); + + if (particle.unknown_01E0 % particle.unknown_01E8 == 0) { + const auto next = render.unknown_003C + 1u; + render.unknown_003C = next; + + if (particle.unknown_0254 != 0) { + render.unknown_003C = static_cast(next) % static_cast(particle.textureCount); + } else if (next == particle.textureCount) { + return false; + } + } + + return true; +} + +// OFFSET: 0x00BB8610 +// FUNCTION: fn_19784 +void AdvanceEffectPrimitive(EffectPrimitiveState& particle, RenderObjectState& render, EffectMotionContext& context) { + particle.origin = { + context.parentRender.position[0] + particle.velocity.x, context.parentRender.position[1] + particle.velocity.y, + context.parentRender.position[2] + particle.velocity.z + }; + + if (particle.unknown_01E0 == particle.unknown_0200) { + particle.unknown_02BC = particle.unknown_029C; + particle.unknown_02C0 = particle.unknown_02A0; + } + + particle.unknown_02BC = particle.unknown_02C0 + particle.unknown_02BC; + particle.unknown_0370 = Forward(particle.unknown_02BC, particle.matrix1); + particle.offset.x = particle.unknown_0370.x + particle.offset.x; + particle.offset.y = particle.unknown_0370.y + particle.offset.y; + particle.offset.z = particle.unknown_0370.z + particle.offset.z; + render.position[0] = particle.offset.x + particle.origin.x; + render.position[1] = particle.offset.y + particle.origin.y; + render.position[2] = particle.offset.z + particle.origin.z; + + if ((particle.flags & 1u) != 0 && particle.unknown_01E0 == static_cast(particle.unknown_01D4)) { + particle.unknown_02C0 = 0; + particle.unknown_02BC = 0; + } + + if ((particle.flags & 2u) != 0) { + if (particle.unknown_01E0 == particle.lifetime - 30) { + particle.unknown_02BC = particle.unknown_02A4.y; + particle.unknown_02C0 = particle.unknown_02B0.y; + } + } else { + particle.UpdateColor(); + } +} diff --git a/Source/Contents/Effects/EffectPrimitiveMotion.h b/Source/Contents/Effects/EffectPrimitiveMotion.h index c91af7ee..9f644914 100644 --- a/Source/Contents/Effects/EffectPrimitiveMotion.h +++ b/Source/Contents/Effects/EffectPrimitiveMotion.h @@ -14,6 +14,11 @@ struct EffectMotionContext { }; bool MoveEffectPrimitive(EffectPrimitiveState& particle, RenderObjectState& render, EffectMotionContext& context); +bool ShrinkEffectPrimitiveSlots(EffectPrimitiveState& particle, RenderObjectState& render, EffectMotionContext& context); +bool PulseEffectPrimitiveSlots(EffectPrimitiveState& particle, RenderObjectState& render, EffectMotionContext& context); +bool SpinEffectPrimitive(EffectPrimitiveState& particle, RenderObjectState& render, EffectMotionContext& context); +bool RollEffectPrimitive(EffectPrimitiveState& particle, RenderObjectState& render, EffectMotionContext& context); +void AdvanceEffectPrimitive(EffectPrimitiveState& particle, RenderObjectState& render, EffectMotionContext& context); bool UpdateEffectPrimitive15(EffectPrimitiveState& particle, RenderObjectState& render, EffectMotionContext& context, int updateTick); #endif diff --git a/Source/Contents/Effects/EffectPrimitiveState.cpp b/Source/Contents/Effects/EffectPrimitiveState.cpp index 2f9849ff..09d4c0dd 100644 --- a/Source/Contents/Effects/EffectPrimitiveState.cpp +++ b/Source/Contents/Effects/EffectPrimitiveState.cpp @@ -133,7 +133,7 @@ EffectPrimitiveState::EffectPrimitiveState(RenderObjectState& render) { std::memcpy(this->matrix1, g_identityMatrix, sizeof(g_identityMatrix)); std::memcpy(this->matrix2, g_identityMatrix, sizeof(g_identityMatrix)); - std::memset(this->unknown_03E8, 0, sizeof(this->unknown_03E8)); + std::memset(this->slots, 0, sizeof(this->slots)); } // INLINED @@ -169,3 +169,19 @@ void EffectPrimitiveState::Initialize( render.position[2] = this->origin.z; this->unknown_013C = 0; } + +// OFFSET: 0x00BAE460 +// FUNCTION: fn_19765 +void EffectPrimitiveState::GetColorOverride(unsigned char* red, unsigned char* green, unsigned char* blue) { + if (this->parent->unknown_11C88[0] != -1) { + *red = static_cast(this->parent->unknown_11C88[0]); + } + + if (this->parent->unknown_11C88[1] != -1) { + *green = static_cast(this->parent->unknown_11C88[1]); + } + + if (this->parent->unknown_11C88[2] != -1) { + *blue = static_cast(this->parent->unknown_11C88[2]); + } +} diff --git a/Source/Contents/Effects/EffectPrimitiveState.h b/Source/Contents/Effects/EffectPrimitiveState.h index e5cc4e8c..f398f8e0 100644 --- a/Source/Contents/Effects/EffectPrimitiveState.h +++ b/Source/Contents/Effects/EffectPrimitiveState.h @@ -31,12 +31,31 @@ struct EffectPrimitiveRecord { /* 0088 */ std::uint32_t color; }; +struct EffectPrimitiveSlot { + /* 0000 */ unsigned char active; + /* 0001 */ unsigned char unknown_0001; + /* 0002 */ std::int16_t unknown_0002; + /* 0004 */ std::int16_t unknown_0004; + /* 0006 */ unsigned char unknown_0006[2]; + /* 0008 */ float unknown_0008; + /* 000C */ int frame; + /* 0010 */ std::int16_t angle; + /* 0012 */ unsigned char unknown_0012[2]; + /* 0014 */ float values[21]; + /* 0068 */ unsigned char finished[21]; + /* 007D */ unsigned char unknown_007D; + /* 007E */ std::int16_t unknown_007E; + /* 0080 */ float unknown_0080; + /* 0084 */ EffectVector3 unknown_0084[4]; +}; + struct EffectPrimitiveState { explicit EffectPrimitiveState(RenderObjectState& render); ~EffectPrimitiveState(); void Initialize(RenderObjectState& render, RagEffectState& parent, const RenderObjectState& parentRender, int type, float x, float y, float z); void UpdateColor(); void InitializeRecords(const RenderObjectState& render); + void GetColorOverride(unsigned char* red, unsigned char* green, unsigned char* blue); /* 0138 */ std::uint32_t unknown_0138; /* 013C */ std::uint32_t unknown_013C; @@ -100,12 +119,12 @@ struct EffectPrimitiveState { /* 02E8 */ float unknown_02E8; /* 02EC */ std::uint32_t unknown_02EC; /* 02F0 */ std::uint32_t unknown_02F0; - /* 02F4 */ std::uint32_t unknown_02F4; - /* 02F8 */ std::uint32_t unknown_02F8; - /* 02FC */ std::uint32_t unknown_02FC; - /* 0300 */ std::uint32_t unknown_0300; - /* 0304 */ std::uint32_t unknown_0304; - /* 0308 */ std::uint32_t unknown_0308; + /* 02F4 */ float unknown_02F4; + /* 02F8 */ float unknown_02F8; + /* 02FC */ float unknown_02FC; + /* 0300 */ float unknown_0300; + /* 0304 */ float unknown_0304; + /* 0308 */ float unknown_0308; /* 030C */ float unknown_030C; /* 0310 */ float unknown_0310; /* 0314 */ float unknown_0314; @@ -138,7 +157,7 @@ struct EffectPrimitiveState { /* 03A0 */ EffectVector3 unknown_03A0; /* 03AC */ EffectVector3 unknown_03AC; /* 03B8 */ EffectVector3 corners[4]; - /* 03E8 */ unsigned char unknown_03E8[720]; + /* 03E8 */ EffectPrimitiveSlot slots[4]; /* 06B8 */ EffectPrimitiveRecord records[50]; /* 2210 */ RenderTriangle triangles[512]; /* FA10 */ std::uint32_t unknown_FA10; @@ -147,11 +166,15 @@ struct EffectPrimitiveState { static_assert(sizeof(EffectVector3) == 12); static_assert(sizeof(EffectPrimitiveRecord) == 140); +static_assert(sizeof(EffectPrimitiveSlot) == 0xB4); #if defined(_WIN32) && !defined(_WIN64) static_assert(offsetof(EffectVector3, z) == 0x8); static_assert(offsetof(EffectPrimitiveRecord, corners) == 0xC); static_assert(offsetof(EffectPrimitiveRecord, matrix) == 0x48); static_assert(offsetof(EffectPrimitiveRecord, color) == 0x88); +static_assert(offsetof(EffectPrimitiveSlot, values) == 0x14); +static_assert(offsetof(EffectPrimitiveSlot, finished) == 0x68); +static_assert(offsetof(EffectPrimitiveSlot, unknown_0084) == 0x84); static_assert(sizeof(EffectPrimitiveState) == 0xF8E0); #endif