diff --git a/src/mod_autofish.cpp b/src/mod_autofish.cpp index 700173a..37ea6a2 100644 --- a/src/mod_autofish.cpp +++ b/src/mod_autofish.cpp @@ -1,86 +1,101 @@ #include "ScriptMgr.h" #include "Player.h" #include "GameObject.h" -#include "WorldSession.h" #include "ObjectAccessor.h" -#include "CellImpl.h" -#include "GridNotifiers.h" -#include "GridNotifiersImpl.h" +#include "Config.h" #include "LootMgr.h" -class mod_autofish_PlayerScript : public PlayerScript +namespace { -public: - mod_autofish_PlayerScript() : PlayerScript("mod_autofish_PlayerScript") {} + bool sEnabled = true; + uint32 sTickMs = 200; + float sScanRange = 30.0f; + std::vector sBobberEntries; - void OnUpdate(Player* player, uint32) override + std::vector ParseEntryList(std::string const& csv) { - if (!player->IsAlive() || player->IsInCombat() || player->GetMap()->IsBattlegroundOrArena()) - return; - - Acore::GameObjectInRangeCheck check(player, player, 10.0f); - Acore::GameObjectSearcher searcher(player, foundBobber, check); - player->VisitNearbyGridObject(10.0f, searcher); - - if (!foundBobber) - return; - - GameObject* go = foundBobber; - if (go->GetOwnerGUID() != player->GetGUID()) + std::vector out; + std::stringstream ss(csv); + std::string item; + while (std::getline(ss, item, ',')) { - foundBobber = nullptr; - return; + item.erase(0, item.find_first_not_of(" \t\r\n")); + item.erase(item.find_last_not_of(" \t\r\n") + 1); + if (!item.empty()) + out.push_back(uint32(std::stoul(item))); } - - if (go->GetGoState() != GO_STATE_READY) - { - foundBobber = nullptr; - return; - } - - player->SendLoot(go->GetGUID(), LOOT_FISHING); - Loot* loot = &go->loot; - for (uint32 i = 0; i < loot->items.size(); ++i) - player->StoreLootItem(i, loot); - player->SendLootRelease(go->GetGUID()); - - foundBobber = nullptr; + return out; } -private: - static GameObject* foundBobber; -}; - -GameObject* mod_autofish_PlayerScript::foundBobber = nullptr; - -class mod_autofish_WorldScript : public WorldScript -{ -public: - mod_autofish_WorldScript() : WorldScript("mod_autofish_WorldScript") {} - - void OnGameObjectCreate(GameObject* go) override + void TryAutoFish(Player* plr) { - if (go->GetGoType() == GAMEOBJECT_TYPE_FISHINGNODE) - lastBobber = go; + if (!plr || !plr->IsInWorld()) + return; + + std::list nearList; + for (auto entry : sBobberEntries) + plr->GetGameObjectListWithEntryInGrid(nearList, entry, sScanRange); + + for (GameObject* go : nearList) + { + if (!go || go->GetOwnerGUID() != plr->GetGUID()) + continue; + + if (go->getLootState() == GO_READY) + { + plr->SendLoot(go->GetGUID(), LOOT_FISHING); + + Loot* loot = &go->loot; + for (uint32 i = 0; i < loot->items.size(); ++i) + { + if (LootItem* li = loot->LootItemInSlot(i, plr)) + plr->AutoStoreLootItem(i, loot); + } + + plr->SendLootRelease(go->GetGUID()); + go->SetLootState(GO_JUST_DEACTIVATED); + return; + } + } } - - static GameObject* GetLastBobber() { return lastBobber; } - -private: - static GameObject* lastBobber; -}; - -GameObject* mod_autofish_WorldScript::lastBobber = nullptr; - -class mod_autofish_GridNotifier : public Acore::GameObjectSearcher -{ -public: - mod_autofish_GridNotifier(Player* p, GameObject*& result, Acore::GameObjectInRangeCheck const& check) - : Acore::GameObjectSearcher(p, result, check) {} -}; - -void Addmod_autofishScripts() -{ - new mod_autofish_PlayerScript(); - new mod_autofish_WorldScript(); +} + +class AutoFish_WorldScript : public WorldScript +{ +public: + AutoFish_WorldScript() : WorldScript("AutoFish_WorldScript") {} + + void OnAfterConfigLoad(bool) override + { + sEnabled = sConfigMgr->GetOption("AutoFish.Enabled", true); + sTickMs = sConfigMgr->GetOption("AutoFish.TickMs", 200u); + sScanRange = sConfigMgr->GetOption("AutoFish.ScanRange", 30.0f); + sBobberEntries = ParseEntryList(sConfigMgr->GetOption("AutoFish.BobberEntries", "35591")); + } + + void OnUpdate(uint32 diff) override + { + if (!sEnabled) + return; + + static uint32 acc = 0; + acc += diff; + if (acc < sTickMs) + return; + acc = 0; + + auto const& players = ObjectAccessor::GetPlayers(); + for (auto const& kv : players) + { + Player* plr = kv.second; + if (!plr || !plr->IsInWorld() || plr->IsGameMaster()) + continue; + TryAutoFish(plr); + } + } +}; + +void AddSC_autofish_world() +{ + new AutoFish_WorldScript(); }