diff --git a/L2BotCore/Domain/Entities/BaseItem.h b/L2BotCore/Domain/Entities/BaseItem.h index 665e809..83b8d60 100644 --- a/L2BotCore/Domain/Entities/BaseItem.h +++ b/L2BotCore/Domain/Entities/BaseItem.h @@ -14,6 +14,10 @@ namespace L2Bot::Domain::Entities { return m_ObjectId; } + const uint32_t GetItemId() const + { + return m_ItemId; + } virtual void Update(const EntityInterface* other) override { const BaseItem* casted = static_cast(other); diff --git a/L2BotCore/Domain/Entities/EtcItem.h b/L2BotCore/Domain/Entities/EtcItem.h index bf0967f..c85319d 100644 --- a/L2BotCore/Domain/Entities/EtcItem.h +++ b/L2BotCore/Domain/Entities/EtcItem.h @@ -9,6 +9,11 @@ namespace L2Bot::Domain::Entities class EtcItem : public BaseItem { public: + void Autouse(bool enabled) + { + m_IsAutoused = enabled; + } + void Update(const EntityInterface* other) override { const EtcItem* casted = static_cast(other); @@ -17,6 +22,7 @@ namespace L2Bot::Domain::Entities m_Amount = casted->m_Amount; m_IsQuest = casted->m_IsQuest; + m_IsAutoused = casted->m_IsAutoused; } void SaveState() override { @@ -24,6 +30,7 @@ namespace L2Bot::Domain::Entities m_PrevState = { m_Amount, + m_IsAutoused, false }; } @@ -32,7 +39,8 @@ namespace L2Bot::Domain::Entities const EtcItem* casted = static_cast(other); return BaseItem::IsEqual(other) && m_IsQuest == casted->m_IsQuest && - m_Amount == casted->m_Amount; + m_Amount == casted->m_Amount && + m_IsAutoused == casted->m_IsAutoused; } const std::vector BuildSerializationNodes() const override @@ -48,6 +56,10 @@ namespace L2Bot::Domain::Entities { result.push_back({ "amount", std::to_string(m_Amount) }); } + if (m_PrevState.isNewState || m_IsAutoused != m_PrevState.isAutoused) + { + result.push_back({ "isAutoused", std::to_string(m_IsAutoused) }); + } return result; } @@ -82,7 +94,7 @@ namespace L2Bot::Domain::Entities EtcItem(const EtcItem* other) : BaseItem(other), m_Amount(other->m_Amount), - m_IsQuest(other->m_IsQuest) + m_IsAutoused(other->m_IsAutoused) { } @@ -93,6 +105,7 @@ namespace L2Bot::Domain::Entities struct GetState { uint32_t amount = 0; + bool isAutoused = false; bool isNewState = true; }; @@ -100,6 +113,7 @@ namespace L2Bot::Domain::Entities private: uint32_t m_Amount = 0; bool m_IsQuest = false; + bool m_IsAutoused = false; GetState m_PrevState = GetState(); }; } diff --git a/L2BotDll/Events/ItemAutousedEvent.h b/L2BotDll/Events/ItemAutousedEvent.h new file mode 100644 index 0000000..ad044f9 --- /dev/null +++ b/L2BotDll/Events/ItemAutousedEvent.h @@ -0,0 +1,33 @@ +#pragma once + +#include +#include +#include "Event.h" + +class ItemAutousedEvent : public Event +{ +public: + static constexpr const char* name = "itemAutoused"; + + const std::string GetName() const + { + return std::string(name); + } + + const std::vector& GetAutouseInfo() const + { + return m_AutouseInfo; + } + + ItemAutousedEvent(const std::vector autouseInfo) : + m_AutouseInfo(autouseInfo) + { + + } + + ItemAutousedEvent() = delete; + virtual ~ItemAutousedEvent() = default; + +private: + const std::vector m_AutouseInfo; +}; \ No newline at end of file diff --git a/L2BotDll/L2BotDll.vcxproj b/L2BotDll/L2BotDll.vcxproj index 88ef23b..521853c 100644 --- a/L2BotDll/L2BotDll.vcxproj +++ b/L2BotDll/L2BotDll.vcxproj @@ -170,6 +170,7 @@ + diff --git a/L2BotDll/L2BotDll.vcxproj.filters b/L2BotDll/L2BotDll.vcxproj.filters index e236d77..6b37801 100644 --- a/L2BotDll/L2BotDll.vcxproj.filters +++ b/L2BotDll/L2BotDll.vcxproj.filters @@ -171,6 +171,9 @@ Header Files + + Header Files + diff --git a/L2BotDll/Versions/Interlude/GameStructs/GameEngineWrapper.cpp b/L2BotDll/Versions/Interlude/GameStructs/GameEngineWrapper.cpp index df666cd..3e582a5 100644 --- a/L2BotDll/Versions/Interlude/GameStructs/GameEngineWrapper.cpp +++ b/L2BotDll/Versions/Interlude/GameStructs/GameEngineWrapper.cpp @@ -10,6 +10,7 @@ #include "../../../Events/ItemCreatedEvent.h" #include "../../../Events/ItemUpdatedEvent.h" #include "../../../Events/ItemDeletedEvent.h" +#include "../../../Events/ItemAutousedEvent.h" #include "../../../DTO/ItemData.h" namespace Interlude @@ -24,6 +25,7 @@ namespace Interlude void(__thiscall* GameEngineWrapper::__AddAbnormalStatus)(GameEngine*, L2ParamStack&) = 0; void(__thiscall* GameEngineWrapper::__AddInventoryItem)(GameEngine*, ItemInfo&) = 0; void(__thiscall* GameEngineWrapper::__OnReceiveUpdateItemList)(GameEngine*, UpdateItemListActionType, ItemInfo&) = 0; + void(__thiscall* GameEngineWrapper::__OnExAutoSoulShot)(GameEngine*, L2ParamStack&) = 0; void GameEngineWrapper::Init(HMODULE hModule) @@ -50,6 +52,9 @@ namespace Interlude (FARPROC&)__OnReceiveUpdateItemList = (FARPROC)splice( GetProcAddress(hModule, "?OnReceiveUpdateItemList@UGameEngine@@UAEXHAAUItemInfo@@@Z"), __OnReceiveUpdateItemList_hook ); + (FARPROC&)__OnExAutoSoulShot = (FARPROC)splice( + GetProcAddress(hModule, "?OnExAutoSoulShot@UGameEngine@@UAEXAAVL2ParamStack@@@Z"), __OnExAutoSoulShot_hook + ); } void GameEngineWrapper::Restore() @@ -61,6 +66,7 @@ namespace Interlude restore((void*&)__AddAbnormalStatus); restore((void*&)__AddInventoryItem); restore((void*&)__OnReceiveUpdateItemList); + restore((void*&)__OnExAutoSoulShot); } void __fastcall GameEngineWrapper::__Init_hook(GameEngine* This, uint32_t /*edx*/, float_t unk) @@ -147,4 +153,10 @@ namespace Interlude } (*__OnReceiveUpdateItemList)(This, actionType, itemInfo); } + + void __fastcall GameEngineWrapper::__OnExAutoSoulShot_hook(GameEngine* This, int, L2ParamStack& stack) + { + EventDispatcher::GetInstance().Dispatch(ItemAutousedEvent{ stack.GetBufferAsVector() }); + (*__OnExAutoSoulShot)(This, stack); + } } \ No newline at end of file diff --git a/L2BotDll/Versions/Interlude/GameStructs/GameEngineWrapper.h b/L2BotDll/Versions/Interlude/GameStructs/GameEngineWrapper.h index 63d0774..dce82da 100644 --- a/L2BotDll/Versions/Interlude/GameStructs/GameEngineWrapper.h +++ b/L2BotDll/Versions/Interlude/GameStructs/GameEngineWrapper.h @@ -26,6 +26,7 @@ namespace Interlude static void(__thiscall* __AddAbnormalStatus)(GameEngine*, L2ParamStack&); static void(__thiscall* __AddInventoryItem)(GameEngine*, ItemInfo&); static void(__thiscall* __OnReceiveUpdateItemList)(GameEngine*, UpdateItemListActionType, ItemInfo&); + static void(__thiscall* __OnExAutoSoulShot)(GameEngine*, L2ParamStack&); static void __fastcall __Init_hook(GameEngine* This, uint32_t /*edx*/, float_t unk); static void __fastcall __OnSkillListPacket_hook(GameEngine* This, uint32_t /*edx*/, L2ParamStack& stack); @@ -34,6 +35,7 @@ namespace Interlude static void __fastcall __AddAbnormalStatus_hook(GameEngine* This, uint32_t /*edx*/, L2ParamStack& stack); static void __fastcall __AddInventoryItem_hook(GameEngine* This, int /*edx*/, ItemInfo& itemInfo); static void __fastcall __OnReceiveUpdateItemList_hook(GameEngine* This, int /*edx*/, UpdateItemListActionType actionType, ItemInfo& itemInfo); + static void __fastcall __OnExAutoSoulShot_hook(GameEngine* This, int /*edx*/, L2ParamStack& stack); private: static void* originalInitAddress; diff --git a/L2BotDll/Versions/Interlude/Repositories/ItemRepository.h b/L2BotDll/Versions/Interlude/Repositories/ItemRepository.h index f840f80..652a5bd 100644 --- a/L2BotDll/Versions/Interlude/Repositories/ItemRepository.h +++ b/L2BotDll/Versions/Interlude/Repositories/ItemRepository.h @@ -11,6 +11,7 @@ #include "../../../Events/ItemUpdatedEvent.h" #include "../../../Events/ItemDeletedEvent.h" #include "../../../Events/HeroDeletedEvent.h" +#include "../../../Events/ItemAutousedEvent.h" #include "../../../Events/EventDispatcher.h" using namespace L2Bot::Domain; @@ -61,6 +62,9 @@ namespace Interlude EventDispatcher::GetInstance().Subscribe(HeroDeletedEvent::name, [this](const Event& evt) { OnHeroDeleted(evt); }); + EventDispatcher::GetInstance().Subscribe(ItemAutousedEvent::name, [this](const Event& evt) { + OnItemAutoused(evt); + }); } void OnHeroDeleted(const Event& evt) @@ -71,6 +75,31 @@ namespace Interlude Reset(); } } + + void OnItemAutoused(const Event& evt) + { + std::shared_lock(m_Mutex); + if (evt.GetName() == ItemAutousedEvent::name) + { + const auto casted = static_cast(evt); + const auto& data = casted.GetAutouseInfo(); + + const auto itemId = data[0]; + const bool isEnabled = data[1] > 0; + + for (const auto& item : m_Items) + { + if (item.second->GetItemId() == itemId) + { + auto ptr = dynamic_cast(item.second.get()); + if (ptr) + { + ptr->Autouse(isEnabled); + } + } + } + } + } //todo need to delete items if they are not exists in create "queue" void OnItemCreated(const Event& evt)