diff --git a/cheat-base/src/cheat-base/util.cpp b/cheat-base/src/cheat-base/util.cpp index b22244d..892b94b 100644 --- a/cheat-base/src/cheat-base/util.cpp +++ b/cheat-base/src/cheat-base/util.cpp @@ -172,6 +172,30 @@ namespace util return tokens; } + std::string SplitWords(const std::string& value) + { + std::stringstream outStream; + std::stringstream inStream(value); + + char ch; + inStream >> ch; + outStream << ch; + while (inStream >> ch) + { + if (isupper(ch)) + outStream << " "; + outStream << ch; + } + return outStream.str(); + } + + std::string MakeCapital(std::string value) + { + if (islower(value[0])) + value[0] = toupper(value[0]); + return value; + } + static const std::string base64_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "abcdefghijklmnopqrstuvwxyz" diff --git a/cheat-base/src/cheat-base/util.h b/cheat-base/src/cheat-base/util.h index 6be91ae..dd9c0a6 100644 --- a/cheat-base/src/cheat-base/util.h +++ b/cheat-base/src/cheat-base/util.h @@ -37,6 +37,8 @@ namespace util int64_t GetCurrentTimeMillisec(); std::vector StringSplit(const std::string& delimiter, const std::string& content); + std::string SplitWords(const std::string& value); + std::string MakeCapital(std::string value); std::string to_hex_string(uint8_t* barray, int length); bool IsLittleEndian(); diff --git a/cheat-library/src/user/cheat/esp/ESP.cpp b/cheat-library/src/user/cheat/esp/ESP.cpp index b6f9d94..2165fed 100644 --- a/cheat-library/src/user/cheat/esp/ESP.cpp +++ b/cheat-library/src/user/cheat/esp/ESP.cpp @@ -409,31 +409,7 @@ namespace cheat::feature return; } - std::string SplitWords(const std::string& value) - { - std::stringstream outStream; - std::stringstream inStream(value); - - char ch; - inStream >> ch; - outStream << ch; - while (inStream >> ch) - { - if (isupper(ch)) - outStream << " "; - outStream << ch; - } - return outStream.str(); - } - - std::string MakeCapital(std::string value) - { - if (islower(value[0])) - value[0] = toupper(value[0]); - return value; - } - -#define ADD_FILTER_FIELD(section, name) AddFilter(MakeCapital(#section), SplitWords(#name), &game::filters::##section##::##name##) +#define ADD_FILTER_FIELD(section, name) AddFilter(util::MakeCapital(#section), util::SplitWords(#name), &game::filters::##section##::##name##) void ESP::InstallFilters() { ADD_FILTER_FIELD(collection, Book); diff --git a/cheat-library/src/user/cheat/game/filters.cpp b/cheat-library/src/user/cheat/game/filters.cpp index 70f87df..d3e54d0 100644 --- a/cheat-library/src/user/cheat/game/filters.cpp +++ b/cheat-library/src/user/cheat/game/filters.cpp @@ -29,6 +29,16 @@ namespace cheat::game::filters ChestFilter STrap = ChestFilter(game::Chest::ChestState::Trap); } + namespace equipment + { + SimpleFilter Artifacts = { app::EntityType__Enum_1::DropItem, "_Relic" }; + SimpleFilter Bow = { app::EntityType__Enum_1::DropItem, "_Bow" }; + SimpleFilter Claymore = { app::EntityType__Enum_1::DropItem, "_Claymore" }; + SimpleFilter Catalyst = { app::EntityType__Enum_1::DropItem, "_Catalyst" }; + SimpleFilter Pole = { app::EntityType__Enum_1::DropItem, "_Pole" }; + SimpleFilter Sword = { app::EntityType__Enum_1::DropItem, "_Sword" }; + } + namespace featured { SimpleFilter Anemoculus = { app::EntityType__Enum_1::GatherObject, "WindCrystalShell" }; @@ -93,12 +103,13 @@ namespace cheat::game::filters SimpleFilter WeaselThief = { app::EntityType__Enum_1::Monster, "Thoarder_Weasel" }; SimpleFilter Kitsune = { app::EntityType__Enum_1::EnvAnimal, "Vulpes" }; SimpleFilter BakeDanuki = { app::EntityType__Enum_1::Monster, "Inu_Tanuki" }; + SimpleFilter Meat = { app::EntityType__Enum_1::GatherObject , std::vector { "_Food_BirdMeat", "_Food_Meat", "_Fishmeat" }}; } namespace mineral { SimpleFilter AmethystLump = { app::EntityType__Enum_1::GatherObject, "_Thundercrystal" }; - SimpleFilter ArchaicStone = { app::EntityType__Enum_1::GatherObject, "AncientOre" }; + SimpleFilter ArchaicStone = { app::EntityType__Enum_1::GatherObject, "_AncientOre" }; SimpleFilter CorLapis = { app::EntityType__Enum_1::GatherObject, "_ElementRock" }; SimpleFilter CrystalChunk = { app::EntityType__Enum_1::GatherObject, std::vector { "_OreCrystal", "_ShiningCrystalOre" } }; @@ -112,6 +123,16 @@ namespace cheat::game::filters SimpleFilter Starsilver = { app::EntityType__Enum_1::GatherObject, "_OreMoonMeteor" }; SimpleFilter WhiteIronChunk = { app::EntityType__Enum_1::GatherObject, "_OreMetal" }; SimpleFilter DunlinsTooth = { app::EntityType__Enum_1::GatherObject, "_DunlinsTooth" }; + + SimpleFilter AmethystLumpDrop = { app::EntityType__Enum_1::GatherObject, "_Thundercrystaldrop" }; + SimpleFilter CrystalChunkDrop = { app::EntityType__Enum_1::GatherObject,"_Drop_Crystal"}; + SimpleFilter ElectroCrystalDrop = { app::EntityType__Enum_1::GatherObject, "_Drop_Ore_ElectricRock" }; + SimpleFilter IronChunkDrop = { app::EntityType__Enum_1::GatherObject, "_Drop_Stone" }; + SimpleFilter NoctilucousJadeDrop = { app::EntityType__Enum_1::GatherObject,"_NightBerth" }; + SimpleFilter MagicalCrystalChunkDrop = { app::EntityType__Enum_1::GatherObject, "_DropMagicCrystal" }; + SimpleFilter ScarletQuartzDrop = { app::EntityType__Enum_1::GatherObject, "_DropDulinsBlood" }; + SimpleFilter StarsilverDrop = { app::EntityType__Enum_1::GatherObject, "_DropMoonMeteor" }; + SimpleFilter WhiteIronChunkDrop = { app::EntityType__Enum_1::GatherObject, "_Drop_Metal" }; } namespace monster @@ -193,6 +214,7 @@ namespace cheat::game::filters SimpleFilter BambooShoot = { app::EntityType__Enum_1::GatherObject, "_Bambooshoot" }; SimpleFilter Berry = { app::EntityType__Enum_1::GatherObject, "_Raspberry" }; SimpleFilter CallaLily = { app::EntityType__Enum_1::GatherObject, "_Plant_Callas" }; + SimpleFilter Cabbage = { app::EntityType__Enum_1::GatherObject, "_Plant_Cabbage" }; SimpleFilter Carrot = { app::EntityType__Enum_1::GatherObject, "_Plant_Carrot" }; SimpleFilter Cecilia = { app::EntityType__Enum_1::GatherObject, "_Cecilia" }; SimpleFilter DandelionSeed = { app::EntityType__Enum_1::GatherObject, "_Plant_Dandelion" }; @@ -211,6 +233,7 @@ namespace cheat::game::filters SimpleFilter NakuWeed = { app::EntityType__Enum_1::GatherObject, "_Howlgrass" }; SimpleFilter PhilanemoMushroom = { app::EntityType__Enum_1::GatherObject, "_WindmilHunter" }; SimpleFilter Pinecone = { app::EntityType__Enum_1::GatherObject, "_Drop_Plant_Pine" }; + SimpleFilter Potato = { app::EntityType__Enum_1::GatherObject, "_Plant_Potato" }; SimpleFilter Qingxin = { app::EntityType__Enum_1::GatherObject, "_QingXin" }; SimpleFilter Radish = { app::EntityType__Enum_1::GatherObject, "_Plant_Radish" }; SimpleFilter SakuraBloom = { app::EntityType__Enum_1::GatherObject, "_Cherrypetals" }; @@ -224,6 +247,7 @@ namespace cheat::game::filters SimpleFilter SweetFlower = { app::EntityType__Enum_1::GatherObject, "_Plant_Whiteballet" }; SimpleFilter Valberry = { app::EntityType__Enum_1::GatherObject, "_DropingBerry_Gather" }; SimpleFilter Violetgrass = { app::EntityType__Enum_1::GatherObject, "_GlazedGrass" }; + SimpleFilter Wheat = { app::EntityType__Enum_1::GatherObject, "_Plant_Wheat" }; SimpleFilter WindwheelAster = { app::EntityType__Enum_1::GatherObject, "_WindmilDaisy" }; SimpleFilter Wolfhook = { app::EntityType__Enum_1::GatherObject, "_GogoFruit" }; } diff --git a/cheat-library/src/user/cheat/game/filters.h b/cheat-library/src/user/cheat/game/filters.h index aafe47e..20617bf 100644 --- a/cheat-library/src/user/cheat/game/filters.h +++ b/cheat-library/src/user/cheat/game/filters.h @@ -32,6 +32,16 @@ namespace cheat::game::filters extern ChestFilter STrap; } + namespace equipment + { + extern SimpleFilter Artifacts; + extern SimpleFilter Bow; + extern SimpleFilter Claymore; + extern SimpleFilter Catalyst; + extern SimpleFilter Pole; + extern SimpleFilter Sword; + } + namespace featured { extern SimpleFilter Anemoculus; @@ -94,6 +104,7 @@ namespace cheat::game::filters extern SimpleFilter Weasel; extern SimpleFilter Kitsune; extern SimpleFilter BakeDanuki; + extern SimpleFilter Meat; } namespace mineral @@ -111,6 +122,16 @@ namespace cheat::game::filters extern SimpleFilter Starsilver; extern SimpleFilter WhiteIronChunk; extern SimpleFilter DunlinsTooth; + + extern SimpleFilter AmethystLumpDrop; + extern SimpleFilter CrystalChunkDrop; + extern SimpleFilter ElectroCrystalDrop; + extern SimpleFilter IronChunkDrop; + extern SimpleFilter NoctilucousJadeDrop; + extern SimpleFilter MagicalCrystalChunkDrop; + extern SimpleFilter ScarletQuartzDrop; + extern SimpleFilter StarsilverDrop; + extern SimpleFilter WhiteIronChunkDrop; } namespace monster @@ -189,6 +210,7 @@ namespace cheat::game::filters extern SimpleFilter Apple; extern SimpleFilter BambooShoot; extern SimpleFilter Berry; + extern SimpleFilter Cabbage; extern SimpleFilter CallaLily; extern SimpleFilter Carrot; extern SimpleFilter Cecilia; @@ -208,6 +230,7 @@ namespace cheat::game::filters extern SimpleFilter NakuWeed; extern SimpleFilter PhilanemoMushroom; extern SimpleFilter Pinecone; + extern SimpleFilter Potato; extern SimpleFilter Qingxin; extern SimpleFilter Radish; extern SimpleFilter SakuraBloom; @@ -221,6 +244,7 @@ namespace cheat::game::filters extern SimpleFilter SweetFlower; extern SimpleFilter Valberry; extern SimpleFilter Violetgrass; + extern SimpleFilter Wheat; extern SimpleFilter WindwheelAster; extern SimpleFilter Wolfhook; } diff --git a/cheat-library/src/user/cheat/world/VacuumLoot.cpp b/cheat-library/src/user/cheat/world/VacuumLoot.cpp index 5cdd182..851bc39 100644 --- a/cheat-library/src/user/cheat/world/VacuumLoot.cpp +++ b/cheat-library/src/user/cheat/world/VacuumLoot.cpp @@ -9,20 +9,44 @@ namespace cheat::feature { VacuumLoot::VacuumLoot() : Feature(), - NF(f_Enabled, "Vacuum Loot", "VacuumLoot", false) - { - events::GameUpdateEvent += MY_METHOD_HANDLER(VacuumLoot::OnGameUpdate); - } + NF(f_Enabled, "Vacuum Loot", "VacuumLoot", false), + NF(f_DelayTime, "Delay time (in ms)", "VacuumLoot", 1000), + NF(f_Distance, "Distance", "VacuumLoot", 1.5f), + NF(f_Radius, "Radius", "VacuumLoot", 20.0f), + nextTime(0) + { + InstallFilters(); + events::GameUpdateEvent += MY_METHOD_HANDLER(VacuumLoot::OnGameUpdate); + } + const FeatureGUIInfo& VacuumLoot::GetGUIInfo() const { static const FeatureGUIInfo info{ "", "World", true }; return info; } - void VacuumLoot::DrawMain() - { - ConfigWidget("Vacuum Loot", f_Enabled, "Vacuum Loot drops"); - } + void VacuumLoot::DrawMain() + { + if (ImGui::BeginGroupPanel("Vacuum Loot", false)) + { + ConfigWidget("Enabled", f_Enabled, "Vacuum Loot drops"); ImGui::SameLine(); ImGui::SetNextItemWidth(100.0f); + ConfigWidget("Delay Time (ms)", f_DelayTime, 1, 0, 1000, "Delay (in ms) between loot vacuum."); + ConfigWidget("Radius (m)", f_Radius, 0.1f, 5.0f, 100.0f, "Radius of loot vacuum."); + ConfigWidget("Distance (m)", f_Distance, 0.1f, 1.0f, 10.0f, "Distance between the player and the loot.\n" + "Values under 1.5 may be too intruding."); + if (ImGui::TreeNode(this, "Loot Types")) + { + for (auto& [section, filters] : m_Sections) + { + ImGui::PushID(section.c_str()); + DrawSection(section, filters); + ImGui::PopID(); + } + ImGui::TreePop(); + } + } + ImGui::EndGroupPanel(); + } bool VacuumLoot::NeedStatusDraw() const { @@ -31,7 +55,7 @@ namespace cheat::feature void VacuumLoot::DrawStatus() { - ImGui::Text ("VacuumLoot"); + ImGui::Text("VacuumLoot"); } VacuumLoot& VacuumLoot::GetInstance() @@ -42,62 +66,151 @@ namespace cheat::feature bool VacuumLoot::IsEntityForVac(game::Entity* entity) { + // Go through all sections. For each section, go through all filters. + // If a filter matches the given entity and that filter is enabled, return true. + bool entityValid = std::any_of(m_Sections.begin(), m_Sections.end(), + [entity](std::pair const& section) { + return std::any_of(section.second.begin(), section.second.end(), [entity](const FilterInfo& filterInfo) { + return filterInfo.second->IsValid(entity) && filterInfo.first; }); + }); + + if (!entityValid)return false; + auto& manager = game::EntityManager::instance(); auto distance = manager.avatar()->distance(entity); - float radius = 100.0f; - // TODO: Add more on the filter list in the future - static std::vector dropList - { - "SceneObj_DropItem", - "SceneObj_Ore_Drop", - "_DropMagicCrystal", - "_Thundercrystaldrop", - "_Ore_ElectricRock", - "_DropMoonMeteor_", - "_DropMagicCrystal", - "_Potato", - "_Radish02_Clear", - "_Cabbage", - "_Carrot02_Clear", - "_Wheat", - "Wisp", - "Meat", - "Fishmeat", - "Equip_Sword", - "Equip_Pole", - "Equip_Bow", - "Equip_Catalyst", - "Equip_Claymore", - "Eff_Animal" - }; - - for (auto& dropListNames : dropList) - if (entity->name().find(dropListNames) != std::string::npos) - return distance <= radius; - - return false; + return distance <= f_Radius; } - void VacuumLoot::OnGameUpdate() - { - if (!f_Enabled) - return; + void VacuumLoot::OnGameUpdate() + { + if (!f_Enabled) + return; auto currentTime = util::GetCurrentTimeMillisec(); if (currentTime < nextTime) return; - auto& manager = game::EntityManager::instance(); + auto& manager = game::EntityManager::instance(); auto avatarEntity = manager.avatar(); - for (const auto& entity : manager.entities()) - { - if (!IsEntityForVac(entity)) - continue; - entity->setRelativePosition(avatarEntity->relativePosition()); - } - nextTime = currentTime + 1000; - } - + for (const auto& entity : manager.entities()) + { + if (!IsEntityForVac(entity)) + continue; + + entity->setRelativePosition(avatarEntity->relativePosition() + avatarEntity->forward() * f_Distance); + } + nextTime = currentTime + f_DelayTime.value(); + } + + void VacuumLoot::DrawSection(const std::string& section, const Filters& filters) + { + bool checked = std::all_of(filters.begin(), filters.end(), [](const FilterInfo& filter) { return filter.first; }); + bool changed = false; + + if (ImGui::BeginSelectableGroupPanel(section.c_str(), checked, changed, true)) + { + // TODO : Get Max Container Width and Calculate Max Item Width of Checkbox + Text / or specify same width for all columns + // then divide MaxWidth by ItemWidth/ColumnWidth and asign a floor result >= 1 to columns. + // Though this is also just fine IMO. + + int columns = 3; + + if (ImGui::BeginTable(section.c_str(), columns == 0 ? 1 : columns )) { + int i = 0; + for (std::pair, game::IEntityFilter*> filter : filters) { + + if (i % (columns == 0 ? 1 : columns) == 0) + { + ImGui::TableNextRow(); + ImGui::TableSetColumnIndex(0); + } + else + ImGui::TableNextColumn(); + + ImGui::PushID(&filter); + ConfigWidget(filter.first); + ImGui::PopID(); + i++; + } + ImGui::EndTable(); + } + } + ImGui::EndSelectableGroupPanel(); + + if (changed) + { + for (const auto& info : filters) + { + info.first.value() = checked; + info.first.FireChanged(); + } + } + } + + void VacuumLoot::AddFilter(const std::string& section, const std::string& name, game::IEntityFilter* filter) + { + if (m_Sections.count(section) == 0) + m_Sections[section] = {}; + + auto& filters = m_Sections[section]; + bool newItem(filter); + filters.push_back({ config::CreateField(name,name,fmt::format("VacuumLoot::Filters::{}", section),false, newItem) , filter }); + } + +#define ADD_FILTER_FIELD(section, name) AddFilter(util::MakeCapital(#section), util::SplitWords(#name), &game::filters::##section##::##name##) + void VacuumLoot::InstallFilters() + { + // Add more in the future + + ADD_FILTER_FIELD(featured, ItemDrops); + + // ADD_FILTER_FIELD(mineral, AmethystLump); + // ADD_FILTER_FIELD(mineral, ArchaicStone); + // ADD_FILTER_FIELD(mineral, CorLapis); + // ADD_FILTER_FIELD(mineral, CrystalChunk); + // ADD_FILTER_FIELD(mineral, CrystalMarrow); + // ADD_FILTER_FIELD(mineral, ElectroCrystal); + // ADD_FILTER_FIELD(mineral, IronChunk); + // ADD_FILTER_FIELD(mineral, NoctilucousJade); + // ADD_FILTER_FIELD(mineral, MagicalCrystalChunk); + // ADD_FILTER_FIELD(mineral, ScarletQuartz); + // ADD_FILTER_FIELD(mineral, Starsilver); + // ADD_FILTER_FIELD(mineral, WhiteIronChunk); + // ADD_FILTER_FIELD(mineral, DunlinsTooth); + + // Ores that drops as a loot when destroyed + ADD_FILTER_FIELD(mineral, AmethystLumpDrop); + ADD_FILTER_FIELD(mineral, CrystalChunkDrop); + ADD_FILTER_FIELD(mineral, ElectroCrystalDrop); + ADD_FILTER_FIELD(mineral, IronChunkDrop); + ADD_FILTER_FIELD(mineral, NoctilucousJadeDrop); + ADD_FILTER_FIELD(mineral, MagicalCrystalChunkDrop); + ADD_FILTER_FIELD(mineral, ScarletQuartzDrop); + ADD_FILTER_FIELD(mineral, StarsilverDrop); + ADD_FILTER_FIELD(mineral, WhiteIronChunkDrop); + + ADD_FILTER_FIELD(plant, Apple); + ADD_FILTER_FIELD(plant, Cabbage); + ADD_FILTER_FIELD(plant, Carrot); + ADD_FILTER_FIELD(plant, Potato); + ADD_FILTER_FIELD(plant, Radish); + ADD_FILTER_FIELD(plant, Sunsettia); + ADD_FILTER_FIELD(plant, Wheat); + + ADD_FILTER_FIELD(living, CrystalCore); + ADD_FILTER_FIELD(living, Meat); + ADD_FILTER_FIELD(living, Crab); + ADD_FILTER_FIELD(living, Eel); + ADD_FILTER_FIELD(living, LizardTail); + + ADD_FILTER_FIELD(equipment, Artifacts); + ADD_FILTER_FIELD(equipment, Bow); + ADD_FILTER_FIELD(equipment, Catalyst); + ADD_FILTER_FIELD(equipment, Claymore); + ADD_FILTER_FIELD(equipment, Sword); + ADD_FILTER_FIELD(equipment, Pole); + } +#undef ADD_FILTER_FIELD } diff --git a/cheat-library/src/user/cheat/world/VacuumLoot.h b/cheat-library/src/user/cheat/world/VacuumLoot.h index 72bff8b..007d4bb 100644 --- a/cheat-library/src/user/cheat/world/VacuumLoot.h +++ b/cheat-library/src/user/cheat/world/VacuumLoot.h @@ -5,14 +5,17 @@ #include #include #include +#include namespace cheat::feature { - class VacuumLoot : public Feature { public: config::Field> f_Enabled; + config::Field f_Distance; + config::Field f_Radius; + config::Field f_DelayTime; static VacuumLoot& GetInstance(); @@ -23,11 +26,19 @@ namespace cheat::feature void DrawStatus() override; void OnGameUpdate(); - private: - std::vector m_Filters; + private: + using FilterInfo = std::pair, game::IEntityFilter*>; + using Filters = std::vector; + using Sections = std::map; + + Sections m_Sections; + SafeValue nextTime; + VacuumLoot(); - int nextTime{}; + void DrawSection(const std::string& section, const Filters& filters); + void InstallFilters(); + void AddFilter(const std::string& section, const std::string& name, game::IEntityFilter* filter); bool IsEntityForVac(cheat::game::Entity* entity); }; }