From 4f1abe4e7ba8ef03411d8feb0c027b14031d6e0b Mon Sep 17 00:00:00 2001 From: ragnarok-clanker Date: Sat, 31 Oct 2026 07:13:06 +0000 Subject: [PATCH] Decompile fn_22252 (CItem::SendMsg) Batch #7367 by gordaoprogramas: 0 byte-identical, 1 confirmed by peer review. - fn_22252 CItem::SendMsg: logic confirmed by peer review Peer-reviewed-by: eAthena, aDw Accepted without human review: peers confirmed the logic ("same" ahead by at least 3, with 70% of the votes). --- Source/Contents/Actors/Item.cpp | 120 ++++++++++++++++++++++++++++++++ Source/Contents/Actors/Item.h | 12 ++-- 2 files changed, 127 insertions(+), 5 deletions(-) diff --git a/Source/Contents/Actors/Item.cpp b/Source/Contents/Actors/Item.cpp index 783044dd..5c8b2124 100644 --- a/Source/Contents/Actors/Item.cpp +++ b/Source/Contents/Actors/Item.cpp @@ -1,13 +1,42 @@ #include "Contents/Actors/Item.h" #include "Client/Mode/CGameMode.h" +#include "Client/Input/InputCharset.h" #include "Client/Mode/ModeMgr.h" +#include "Contents/Configuration/ServiceConfiguration.h" +#include "Contents/Effects/EffectLists.h" +#include "Contents/Effects/RagEffect.h" +#include "Contents/Items/ItemDescription.h" +#include "Contents/Items/ItemInfo.h" +#include "Contents/Items/ItemInfoMgr.h" +#include "Contents/Items/ItemNaming.h" +#include "Contents/Items/ItemResources.h" +#include "Contents/MessageTable.h" +#include "Contents/PlayerNameDictionary.h" #include "Contents/World/World.h" +#include "Resource/ResourceMgr.h" #include "Resource/World/TerrainResource.h" +#include "Utility/Text/FormatString.h" +#include #include #include +struct ItemFallEntry { + /* 0000 */ char itemId[0x20]; + /* 0020 */ std::uint32_t aid; + /* 0024 */ int column; + /* 0028 */ int row; + /* 002C */ int subColumn; + /* 0030 */ int subRow; + /* 0034 */ int falling; + /* 0038 */ int count; + /* 003C */ unsigned char identified; + /* 003E */ std::uint16_t unknown_003E; + /* 0040 */ unsigned char showEffect; + /* 0042 */ std::uint16_t grade; +}; + // OFFSET: 0x00D8B5A0 // FUNCTION: fn_22248 void CItem::SubD8B5A0() { @@ -48,3 +77,94 @@ void CItem::Render(int argument) { this->DrawSprite(argument, false, 0.0f); } } + +// OFFSET: 0x00D8B720 +// FUNCTION: fn_22252 +void CItem::SendMsg(CGameObject* sender, int message, int a, int b, int c, int d, int e, int f, int g, int h, int i, int, int, int, int) { + CGameMode* mode = static_cast(g_modeMgr.GetGameMode()); + if (message != 4 || a != 0) { + this->EffectActor::SendMsg(sender, message, a, b, c, d, e, f, g, h, i, 0, 0, 0, 0); + return; + } + + const ItemFallEntry* entry = reinterpret_cast(b); + this->itemAid = entry->aid; + this->name = entry->itemId; + std::string itemName = this->name; + mode->SubcellPosition(entry->column, entry->row, entry->subColumn, entry->subRow, this->render.position.x, this->render.position.z); + this->render.position.y = mode->scene->terrain->Grid().Height(this->render.position.x, this->render.position.z); + if (entry->falling) { + this->fallVelocity = -0.6f; + this->render.position.y -= 15.0f; + this->isFalling = 1; + } else { + this->isFalling = 0; + } + this->fallOrigin = this->render.position.y; + + ItemDescriptions descriptions{g_itemDescriptions}; + std::string spriteName = ItemDragResource(descriptions, this->name.c_str(), entry->identified); + spriteName += ".spr"; + std::string actionName = ItemDragResource(descriptions, this->name.c_str(), entry->identified); + actionName += ".act"; + this->SetSpriteName(ResourceMgr::Instance(), spriteName.c_str()); + this->SetActionName(ResourceMgr::Instance(), actionName.c_str()); + + ITEM_INFO item; + this->itemIndex = std::atoi(entry->itemId); + this->unknown_018C = entry->unknown_003E; + this->itemId = static_cast(std::atoi(entry->itemId)); + this->identified = entry->identified; + item.itemId = itemName; + item.identified = entry->identified; + item.unknown_0060 = 0; + bool languagePrefix = false; + WORD language = g_serverLanguage->language; + ItemNaming naming{descriptions, g_itemCardNames, *g_playerNameDictionary, languagePrefix, g_serviceType, language}; + this->name = static_cast(FormatOwnedString(LookupMessage(183), naming.DisplayName(item, 0).c_str(), entry->count)); + this->GetActRes(); + this->render.unknown_008C = timeGetTime(); + + if (entry->showEffect == 1) { + const float x = this->render.position.x; + const float z = this->render.position.z; + const float height = mode->scene->terrain->Grid().Height(x, z); + const int effectId = g_itemInfoMgr->GetEffectId(this->itemIndex); + if (effectId >= 0 && !g_effectMgr->Spawn(entry->aid, effectId, x, height, z, 0, -1, 0, 0)) { + if (CRagEffect* effect = this->LaunchEffect(effectId, vector3d{0.0f, 0.0f, 0.0f}, 0.0f)) { + effect->render.position.x = x; + effect->render.position.y = height; + effect->render.position.z = z; + } + } + + if (static_cast(entry->grade - 1) <= 4) { + int gradeEffectId = 2485; + switch (entry->grade) { + case 1: + gradeEffectId = 1869; + break; + case 2: + gradeEffectId = 1189; + break; + case 3: + gradeEffectId = 1190; + break; + case 4: + gradeEffectId = 1870; + break; + case 5: + gradeEffectId = 1871; + break; + } + + if (!g_effectMgr->Spawn(entry->aid, gradeEffectId, x, height, z, 0, -1, 0, 0)) { + if (CRagEffect* effect = this->LaunchEffect(gradeEffectId, vector3d{0.0f, 0.0f, 0.0f}, 0.0f)) { + effect->render.position.x = x; + effect->render.position.y = height; + effect->render.position.z = z; + } + } + } + } +} diff --git a/Source/Contents/Actors/Item.h b/Source/Contents/Actors/Item.h index 7a508c18..af48bb10 100644 --- a/Source/Contents/Actors/Item.h +++ b/Source/Contents/Actors/Item.h @@ -1,27 +1,29 @@ #ifndef RAGNAROK_SOURCE_CONTENTS_ACTORS_ITEM_H #define RAGNAROK_SOURCE_CONTENTS_ACTORS_ITEM_H -#include "Contents/Actors/RenderObject.h" +#include "Contents/Effects/EffectActor.h" #include #include #include -class CItem : public CRenderObject { +class CItem : public EffectActor { public: void SubD8B5A0(); void SubD8B5B0(); bool OnProcess() override; + void SendMsg(CGameObject* sender, int message, int a, int b, int c, int d, int e, int f, int g, int h, int i, int j, int k, int l, int m) override; void Render(int argument) override; - /* 0138 */ unsigned char unknown_0138[0x20]; /* 0158 */ std::string name; - /* 0170 */ unsigned char unknown_0170[0x0C]; + /* 0170 */ std::uint32_t itemId; + /* 0174 */ unsigned char identified; + /* 0178 */ int itemIndex; /* 017C */ std::uint32_t itemAid; /* 0180 */ std::uint32_t isFalling; /* 0184 */ float fallVelocity; /* 0188 */ float fallOrigin; - /* 018C */ std::uint32_t unknown_018C; + /* 018C */ std::uint16_t unknown_018C; }; #if defined(_WIN32) && !defined(_WIN64)