Decompile 3 functions in Source/Contents/Effects/EffectPrimitiveMotion.cpp, Source/Contents/Effects/EffectParticle.h, ...

Batch #1869 by ragnarok-clanker: 3 byte-identical, 0 confirmed by peer review.

- fn_19971 EffectParticle::PrimWaterFall: byte-identical
- fn_21090 CGameActor::ProcessBodyState: byte-identical
- fn_12629 UIShortCutWnd::Slot03: byte-identical (already on main)

Merged automatically: every function is byte-identical to the original.
This commit is contained in:
ragnarok-clanker 2026-10-28 23:05:45 +00:00
commit 81e812ea39
11 changed files with 218 additions and 17 deletions

View file

@ -6,6 +6,16 @@
#include <cstddef> #include <cstddef>
enum {
BODYSTATE_NORMAL,
BODYSTATE_STONECURSE,
BODYSTATE_FREEZING,
BODYSTATE_STUN,
BODYSTATE_SLEEP,
BODYSTATE_UNDEAD,
BODYSTATE_STONECURSE_ING,
};
class CGameActor : public CRenderObject { class CGameActor : public CRenderObject {
public: public:
~CGameActor() override; ~CGameActor() override;

View file

@ -115,7 +115,7 @@ void CRenderObject::SetAnimation(unsigned animation, int, int repeat) {
this->render.previousAnimation = animation; this->render.previousAnimation = animation;
this->render.curMotion = 0; this->render.curMotion = 0;
this->render.unknown_006C = repeat; this->render.unknown_006C = repeat;
this->render.unknown_009C[1] = 0; this->render.isMotionFinished = 0;
this->render.unknown_0060 = 1.0f; this->render.unknown_0060 = 1.0f;
this->render.unknown_0064 = 1.0f; this->render.unknown_0064 = 1.0f;
this->render.unknown_00C8 = 0; this->render.unknown_00C8 = 0;
@ -423,9 +423,9 @@ void CRenderObject::JitterBounds(float* output, const int* input, float offset,
// FUNCTION: fn_21090 // FUNCTION: fn_21090
void CGameActor::ProcessBodyState() { void CGameActor::ProcessBodyState() {
switch (this->bodyState) { switch (this->bodyState) {
case 1: case BODYSTATE_FREEZING:
case 2: case BODYSTATE_STONECURSE:
this->render.unknown_009C[2] = 1; this->render.isMotionFreezed = true;
break; break;
} }
} }

View file

@ -46,13 +46,13 @@ void RenderObjectState::Reset(ResourceMgr& resources, JobNames& names) {
this->color = 0xFFFFFFFFu; this->color = 0xFFFFFFFFu;
this->unknown_00A2 = 0; this->unknown_00A2 = 0;
this->unknown_00A4 = 0; this->unknown_00A4 = 0;
this->unknown_009C[1] = 0; this->isMotionFinished = 0;
this->unknown_009C[2] = 0; this->isMotionFreezed = 0;
this->unknown_0078 = 0; this->unknown_0078 = 0;
this->unknown_007C = 0; this->unknown_007C = 0;
this->started = timeGetTime(); this->started = timeGetTime();
this->unknown_009C[3] = 0; this->isSingleColor = 0;
this->unknown_009C[0] = 0; this->isLieOnGround = 0;
this->unknown_00A3 = 0; this->unknown_00A3 = 0;
this->overrideColor = 0xFFFF0000u; this->overrideColor = 0xFFFF0000u;
this->unknown_0080 = 0; this->unknown_0080 = 0;

View file

@ -47,7 +47,10 @@ struct RenderObjectState {
/* 0090 */ std::uint32_t unknown_0090; /* 0090 */ std::uint32_t unknown_0090;
/* 0094 */ std::uint32_t unknown_0094; /* 0094 */ std::uint32_t unknown_0094;
/* 0098 */ std::uint32_t color; /* 0098 */ std::uint32_t color;
/* 009C */ unsigned char unknown_009C[4]; /* 009C */ bool isLieOnGround;
/* 009D */ bool isMotionFinished;
/* 009E */ bool isMotionFreezed;
/* 009F */ bool isSingleColor;
/* 00A0 */ unsigned char visible; /* 00A0 */ unsigned char visible;
/* 00A1 */ unsigned char enabled; /* 00A1 */ unsigned char enabled;
/* 00A2 */ unsigned char unknown_00A2; /* 00A2 */ unsigned char unknown_00A2;

View file

@ -38,6 +38,10 @@ struct EffectParticle : CRenderObject {
void PrimSMA(); void PrimSMA();
void PrimShieldBoomerang3(); void PrimShieldBoomerang3();
bool PrimSuperAngel(); bool PrimSuperAngel();
void PrimThrowItem();
bool PrimPeong();
void PrimGI3();
void PrimWaterFall();
bool AdvanceFrame(); bool AdvanceFrame();
void UpdateRecords(); void UpdateRecords();

View file

@ -1488,6 +1488,7 @@ void EffectParticle::PrimSMA() {
} }
// OFFSET: 0x00BC2A60 // OFFSET: 0x00BC2A60
// FUNCTION: fn_19835
void EffectParticle::PrimShieldBoomerang3() { void EffectParticle::PrimShieldBoomerang3() {
EffectPrimitiveSlot* slots = this->state.slots; EffectPrimitiveSlot* slots = this->state.slots;
FaceCamera(slots); FaceCamera(slots);
@ -1552,6 +1553,7 @@ void EffectParticle::PrimShieldBoomerang3() {
} }
// OFFSET: 0x00BC3C70 // OFFSET: 0x00BC3C70
// FUNCTION: fn_19840
bool EffectParticle::PrimSuperAngel() { bool EffectParticle::PrimSuperAngel() {
const AttachedEffect* master = this->state.master; const AttachedEffect* master = this->state.master;
this->render.position[0] = master->render.position[0]; this->render.position[0] = master->render.position[0];
@ -1699,6 +1701,182 @@ bool EffectParticle::PrimSuperAngel() {
return true; return true;
} }
// OFFSET: 0x00BC4730
void EffectParticle::PrimThrowItem() {
EffectPrimitiveSlot* slots = this->state.slots;
FaceCamera(slots);
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 % 2 == 1) {
if (slot.process > 3) {
FollowTrail(slots[3], slots[2], 25);
}
if (slot.process > 2) {
FollowTrail(slots[2], slots[1], 25);
}
if (slot.process > 1) {
FollowTrail(slots[1], slot, 150);
}
}
if (slot.flag1[2] == 15) {
slot.fullDisplayAngle += 45;
} else {
slot.fullDisplayAngle += 10;
}
if (slot.fullDisplayAngle >= 360) {
slot.fullDisplayAngle -= 360;
}
if (slot.process == 1) {
const float x = this->state.offset.x - slot.vecBNow.x;
const float z = this->state.offset.z - slot.vecBNow.z;
CalculateVectorAngle(x, z, &slot.rotStart);
}
float progress = static_cast<float>(slot.process);
progress /= static_cast<float>(slot.flag1[1]);
if (progress > 1.05f) {
slot.alphaB -= 20;
if (slot.alphaB < 0) {
slot.alphaB = 0;
}
return;
}
if (progress > 1.0f) {
progress = 1.0f;
}
const int arc = static_cast<int>(180.0f * progress);
slot.vecBPre.y += slot.height[2];
if (slot.flag1[2] == 0) {
slot.vecBNow.y = slot.vecBPre.y - g_sinTable[arc] * 10.0f;
} else if (slot.flag1[2] == 15) {
slot.vecBNow.y = slot.vecBPre.y - g_sinTable[arc];
} else {
slot.vecBNow.y = slot.vecBPre.y - g_sinTable[arc] * 30.0f;
}
slot.vecBNow.x += slot.height[1] * g_cosTable[slot.rotStart];
slot.vecBNow.z += slot.height[1] * g_sinTable[slot.rotStart];
}
// OFFSET: 0x00BC06B0
bool EffectParticle::PrimPeong() {
FaceCamera(this->state.slots);
for (int index = 0; index < 4; ++index) {
EffectPrimitiveSlot& slot = this->state.slots[index];
if (slot.life != 1) {
continue;
}
++slot.process;
if (slot.process <= 0) {
continue;
}
if (slot.process <= 90) {
const float cosine = g_cosTable[slot.riseAngle];
float sine = g_sinTable[slot.riseAngle];
slot.vecBPre.x += cosine * slot.maxHeight;
slot.vecBPre.z += sine * slot.maxHeight;
int angle = slot.process * 2;
if (angle >= 360) {
angle -= 360;
}
sine = g_sinTable[angle];
slot.vecBPre.y = slot.vecBNow.y - sine * slot.maxHeight * 50.0f;
}
if (slot.process <= 25) {
slot.alphaB += 2;
}
if (slot.process > 70) {
--slot.alphaB;
}
if (slot.alphaB < 0) {
slot.alphaB = 0;
}
}
return true;
}
// OFFSET: 0x00BBDE10
void EffectParticle::PrimGI3() {
for (int index = 0; index < 4; ++index) {
EffectPrimitiveSlot& slot = this->state.slots[index];
if (slot.life != 1) {
continue;
}
slot.process += 1;
slot.distance -= 0.01f;
if (slot.process >= 10) {
slot.alphaB -= 1;
if (slot.alphaB <= 0) {
slot.alphaB = 0;
if (slot.process > 30) {
slot.life = 0;
}
slot.distance = 20.0f;
slot.riseAngle = 81 + 9;
}
} else {
slot.alphaB += 10;
}
for (int sample = 0; sample < 21; ++sample) {
slot.height[sample] = slot.maxHeight * g_sinTable[slot.process];
}
}
}
// OFFSET: 0x00BEBC40
// FUNCTION: fn_19971
void EffectParticle::PrimWaterFall() {
for (int index = 0; index < 4; ++index) {
EffectPrimitiveSlot& slot = this->state.slots[index];
if (slot.life > 0) {
++slot.process;
}
}
}
// OFFSET: 0x00BB6F30 // OFFSET: 0x00BB6F30
// FUNCTION: fn_19779 // FUNCTION: fn_19779
bool EffectParticle::UpdateHit6() { bool EffectParticle::UpdateHit6() {

View file

@ -387,3 +387,8 @@ bool ItemInfo::IsElementalStone() const {
bool ItemInfo::IsAboveItemId600() const { bool ItemInfo::IsAboveItemId600() const {
return std::atoi(this->itemId.c_str()) > 500 && std::atoi(this->itemId.c_str()) > 600; return std::atoi(this->itemId.c_str()) > 500 && std::atoi(this->itemId.c_str()) > 600;
} }
// OFFSET: 0x005FCCF0
int ItemInfo::GetItemId() const {
return std::atoi(this->itemId.c_str());
}

View file

@ -65,6 +65,7 @@ struct alignas(8) ItemInfo {
bool operator<(const ItemInfo& other) const; bool operator<(const ItemInfo& other) const;
bool SetName(const char* name); bool SetName(const char* name);
void SetItemId(int value); void SetItemId(int value);
int GetItemId() const;
bool HasSpecialCard() const; bool HasSpecialCard() const;
bool IsApprenticeItem() const; bool IsApprenticeItem() const;
bool IsForgeMaterial() const; bool IsForgeMaterial() const;

View file

@ -203,7 +203,7 @@ void CBlurPC::SendObjectMessage(
this->unknown_04F8 = *reinterpret_cast<const float*>(&b); this->unknown_04F8 = *reinterpret_cast<const float*>(&b);
break; break;
case 3: case 3:
this->render.unknown_009C[2] = 1; this->render.isMotionFreezed = 1;
break; break;
default: default:
CPc::SendObjectMessage(sender, message, a, b, c, d, e, f, g, h, i, 0, 0, 0, 0); CPc::SendObjectMessage(sender, message, a, b, c, d, e, f, g, h, i, 0, 0, 0, 0);
@ -242,7 +242,7 @@ void CHalluNPC::SendObjectMessage(
this->unknown_0440 = *reinterpret_cast<const float*>(&b); this->unknown_0440 = *reinterpret_cast<const float*>(&b);
break; break;
case 3: case 3:
this->render.unknown_009C[2] = 1; this->render.isMotionFreezed = 1;
break; break;
default: default:
CNpc::SendObjectMessage(sender, message, a, b, c, d, e, f, g, h, i, 0, 0, 0, 0); CNpc::SendObjectMessage(sender, message, a, b, c, d, e, f, g, h, i, 0, 0, 0, 0);
@ -273,7 +273,7 @@ void CHalluPC2::SendObjectMessage(
this->unknown_04F8 = *reinterpret_cast<const float*>(&b); this->unknown_04F8 = *reinterpret_cast<const float*>(&b);
break; break;
case 3: case 3:
this->render.unknown_009C[2] = 1; this->render.isMotionFreezed = 1;
break; break;
default: default:
CPc::SendObjectMessage(sender, message, a, b, c, d, e, f, g, h, i, 0, 0, 0, 0); CPc::SendObjectMessage(sender, message, a, b, c, d, e, f, g, h, i, 0, 0, 0, 0);
@ -304,7 +304,7 @@ void CHalluPC::SendObjectMessage(
this->unknown_04F8 = *reinterpret_cast<const float*>(&b); this->unknown_04F8 = *reinterpret_cast<const float*>(&b);
break; break;
case 3: case 3:
this->render.unknown_009C[2] = 1; this->render.isMotionFreezed = 1;
break; break;
default: default:
CPc::SendObjectMessage(sender, message, a, b, c, d, e, f, g, h, i, 0, 0, 0, 0); CPc::SendObjectMessage(sender, message, a, b, c, d, e, f, g, h, i, 0, 0, 0, 0);
@ -330,7 +330,7 @@ void CHalluPlant::SendObjectMessage(
this->render.color &= (b << 24) + 0xFFFFFF; this->render.color &= (b << 24) + 0xFFFFFF;
break; break;
case 3: case 3:
this->render.unknown_009C[2] = 1; this->render.isMotionFreezed = 1;
break; break;
default: default:
CNpc::SendObjectMessage(sender, message, a, b, c, d, e, f, g, h, i, 0, 0, 0, 0); CNpc::SendObjectMessage(sender, message, a, b, c, d, e, f, g, h, i, 0, 0, 0, 0);

View file

@ -127,7 +127,7 @@ void ShortcutDrop::Drop(UIWindow& window, ShortcutGrid& grid, int x, int y, cons
const int column = grid.HitTest(x, y, this->itemSlotActive, this->currentRow); const int column = grid.HitTest(x, y, this->itemSlotActive, this->currentRow);
if (column != -1 && 9 * grid.rows <= 9 * this->currentRow + column) { if (column != -1 && 9 * grid.rows <= 9 * this->currentRow + column) {
if (this->itemSlotActive) { if (this->itemSlotActive) {
this->bindings.AssignItem(static_cast<std::uint32_t>(std::atoi(item.itemId.c_str())), column); this->bindings.AssignItem(static_cast<std::uint32_t>(item.GetItemId()), column);
Refresh(window); Refresh(window);
} }
@ -145,7 +145,7 @@ void ShortcutDrop::Drop(UIWindow& window, ShortcutGrid& grid, int x, int y, cons
const int column = grid.HitTest(x, y, this->itemSlotActive, this->currentRow); const int column = grid.HitTest(x, y, this->itemSlotActive, this->currentRow);
if (column != -1 && grid.rows > this->currentRow) { if (column != -1 && grid.rows > this->currentRow) {
const int index = 9 * this->currentRow + column; const int index = 9 * this->currentRow + column;
this->bindings.Assign(0, static_cast<std::uint32_t>(std::atoi(item.itemId.c_str())), 0, index, bank, this->currentRow, this->script, *this->mode); this->bindings.Assign(0, static_cast<std::uint32_t>(item.GetItemId()), 0, index, bank, this->currentRow, this->script, *this->mode);
if (value.slot != index) { if (value.slot != index) {
RemoveFirst(this->bindings.cooldowns, index); RemoveFirst(this->bindings.cooldowns, index);
} }

View file

@ -318,7 +318,7 @@ inline void ShortcutUse::Use(const NormalItemSlot& slot) {
case 0: case 0:
case 1: case 1:
case 2: case 2:
if (std::atoi(item.itemId.c_str()) != 12802 || this->dialogs.Confirm(this->naming.Message(2373), 2, 0, 0, "Message", 280, 120) != 188) { if (item.GetItemId() != 12802 || this->dialogs.Confirm(this->naming.Message(2373), 2, 0, 0, "Message", 280, 120) != 188) {
use(); use();
} }