From ff4d63ef39486c72c1810af470fb219aeece0b44 Mon Sep 17 00:00:00 2001 From: Flerp Date: Tue, 18 Nov 2025 16:02:37 -0800 Subject: [PATCH] Added catches for quest and money loot --- src/mod_autofish.cpp | 226 +++++++++++++++++++++++++------------------ 1 file changed, 130 insertions(+), 96 deletions(-) diff --git a/src/mod_autofish.cpp b/src/mod_autofish.cpp index 6384801..3b3f5e2 100644 --- a/src/mod_autofish.cpp +++ b/src/mod_autofish.cpp @@ -25,14 +25,20 @@ namespace uint32 sRequiredEquipId = 0; std::vector sBobberEntries; - struct GuidHash { std::size_t operator()(ObjectGuid const& g) const noexcept { return std::hash()(g.GetRawValue()); } }; + struct GuidHash + { + std::size_t operator()(ObjectGuid const &g) const noexcept { return std::hash()(g.GetRawValue()); } + }; std::unordered_map sRecastTimers; - struct PendingLoot { uint32 timer; }; + struct PendingLoot + { + uint32 timer; + }; std::unordered_map sLootTimers; - std::vector ParseEntryList(std::string const& csv) + std::vector ParseEntryList(std::string const &csv) { std::vector out; std::stringstream ss(csv); @@ -47,21 +53,23 @@ namespace return out; } - bool HasEquippedItem(Player* plr, uint32 entry) + bool HasEquippedItem(Player *plr, uint32 entry) { - if (!entry) return true; + if (!entry) + return true; for (uint8 slot = EQUIPMENT_SLOT_START; slot < EQUIPMENT_SLOT_END; ++slot) { - if (Item* it = plr->GetItemByPos(INVENTORY_SLOT_BAG_0, slot)) + if (Item *it = plr->GetItemByPos(INVENTORY_SLOT_BAG_0, slot)) if (it->GetEntry() == entry) return true; } return false; } - bool RequirementMet(Player* plr) + bool RequirementMet(Player *plr) { - if (!plr) return false; + if (!plr) + return false; if (sRequiredItemId && !plr->HasItemCount(sRequiredItemId, 1, false)) return false; if (sRequiredEquipId && !HasEquippedItem(plr, sRequiredEquipId)) @@ -69,18 +77,18 @@ namespace return true; } - void ScheduleRecast(Player* plr) + void ScheduleRecast(Player *plr) { if (!sAutoRecast || !plr || !plr->IsInWorld()) return; sRecastTimers[plr->GetGUID()] = sRecastDelayMs; } - void ScheduleAutoLoot(Player* plr) + void ScheduleAutoLoot(Player *plr) { if (!sServerAutoLoot || !plr) return; - sLootTimers[plr->GetGUID()] = PendingLoot{ sAutoLootDelayMs }; + sLootTimers[plr->GetGUID()] = PendingLoot{sAutoLootDelayMs}; } void TickRecast(uint32 diff) @@ -94,7 +102,7 @@ namespace } else { - Player* plr = ObjectAccessor::FindPlayer(it->first); + Player *plr = ObjectAccessor::FindPlayer(it->first); if (plr && plr->IsInWorld() && plr->IsAlive() && !plr->IsInCombat() && RequirementMet(plr)) plr->CastSpell(plr, sRecastSpell, true); it = sRecastTimers.erase(it); @@ -113,105 +121,131 @@ namespace continue; } - Player* plr = ObjectAccessor::FindPlayer(it->first); + Player *plr = ObjectAccessor::FindPlayer(it->first); if (plr && plr->IsInWorld() && RequirementMet(plr)) { ObjectGuid lootGuid = plr->GetLootGUID(); if (lootGuid.IsGameObject()) { - if (GameObject* lootGo = ObjectAccessor::GetGameObject(*plr, lootGuid)) + if (GameObject *lootGo = ObjectAccessor::GetGameObject(*plr, lootGuid)) { - Loot* loot = &lootGo->loot; - for (uint32 i = 0; i < loot->items.size(); ++i) + Loot *loot = &lootGo->loot; + + // 1) Normal items + for (uint32 slot = 0; slot < loot->items.size(); ++slot) { - if (loot->items[i].is_looted) + LootItem &li = loot->items[slot]; + if (li.is_looted) continue; + InventoryResult msg = EQUIP_ERR_OK; - plr->StoreLootItem(uint8(i), loot, msg); + plr->StoreLootItem(uint8(slot), loot, msg); + + if (!loot->quest_items.empty()) + { + uint32 baseSlot = loot->items.size(); + for (uint32 q = 0; q < loot->quest_items.size(); ++q) + { + QuestItem &qi = loot->quest_items[q]; + if (qi.is_looted) + continue; + + uint8 slot = uint8(baseSlot + q); + InventoryResult msg = EQUIP_ERR_OK; + plr->StoreLootItem(slot, loot, msg); + } + } + + if (loot->gold > 0) + { + plr->ModifyMoney(loot->gold); + loot->gold = 0; + } + + plr->SendLootRelease(lootGuid); + + if (lootGo->GetGoType() == GAMEOBJECT_TYPE_FISHINGNODE) + lootGo->SetLootState(GO_JUST_DEACTIVATED); } - plr->SendLootRelease(lootGuid); - if (lootGo->GetGoType() == GAMEOBJECT_TYPE_FISHINGNODE) - lootGo->SetLootState(GO_JUST_DEACTIVATED); } } + + it = sLootTimers.erase(it); + } + } + + void TryAutoFish(Player * plr) + { + if (!plr || !plr->IsInWorld() || !RequirementMet(plr)) + 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 && go->GetGoType() == GAMEOBJECT_TYPE_FISHINGNODE) + { + go->Use(plr); + if (sServerAutoLoot) + ScheduleAutoLoot(plr); + ScheduleRecast(plr); + return; + } + } + } + } + + class AutoFish_WorldScript : public WorldScript + { + public: + AutoFish_WorldScript() : WorldScript("AutoFish_WorldScript") {} + + void OnAfterConfigLoad(bool) override + { + sEnabled = sConfigMgr->GetOption("AutoFish.Enabled", true); + sServerAutoLoot = sConfigMgr->GetOption("AutoFish.ServerAutoLoot", true); + sAutoRecast = sConfigMgr->GetOption("AutoFish.AutoRecast", true); + sTickMs = sConfigMgr->GetOption("AutoFish.TickMs", 200u); + sScanRange = sConfigMgr->GetOption("AutoFish.ScanRange", 30.0f); + sRecastDelayMs = sConfigMgr->GetOption("AutoFish.RecastDelayMs", 500u); + sRecastSpell = sConfigMgr->GetOption("AutoFish.RecastSpell", 18248u); + sAutoLootDelayMs = sConfigMgr->GetOption("AutoFish.AutoLootDelayMs", 120u); + sRequiredItemId = sConfigMgr->GetOption("AutoFish.RequiredItemId", 0u); + sRequiredEquipId = sConfigMgr->GetOption("AutoFish.RequiredEquipId", 0u); + sBobberEntries = ParseEntryList(sConfigMgr->GetOption("AutoFish.BobberEntries", "35591")); + } + + void OnUpdate(uint32 diff) override + { + if (!sEnabled) + return; + + static uint32 acc = 0; + acc += diff; + if (acc >= sTickMs) + { + 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); + } } - it = sLootTimers.erase(it); + TickAutoLoot(diff); + TickRecast(diff); } - } + }; - void TryAutoFish(Player* plr) + void AddSC_autofish_world() { - if (!plr || !plr->IsInWorld() || !RequirementMet(plr)) - 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 && go->GetGoType() == GAMEOBJECT_TYPE_FISHINGNODE) - { - go->Use(plr); - if (sServerAutoLoot) - ScheduleAutoLoot(plr); - ScheduleRecast(plr); - return; - } - } + new AutoFish_WorldScript(); } -} - -class AutoFish_WorldScript : public WorldScript -{ -public: - AutoFish_WorldScript() : WorldScript("AutoFish_WorldScript") {} - - void OnAfterConfigLoad(bool) override - { - sEnabled = sConfigMgr->GetOption("AutoFish.Enabled", true); - sServerAutoLoot = sConfigMgr->GetOption("AutoFish.ServerAutoLoot", true); - sAutoRecast = sConfigMgr->GetOption("AutoFish.AutoRecast", true); - sTickMs = sConfigMgr->GetOption("AutoFish.TickMs", 200u); - sScanRange = sConfigMgr->GetOption("AutoFish.ScanRange", 30.0f); - sRecastDelayMs = sConfigMgr->GetOption("AutoFish.RecastDelayMs", 500u); - sRecastSpell = sConfigMgr->GetOption("AutoFish.RecastSpell", 18248u); - sAutoLootDelayMs = sConfigMgr->GetOption("AutoFish.AutoLootDelayMs", 120u); - sRequiredItemId = sConfigMgr->GetOption("AutoFish.RequiredItemId", 0u); - sRequiredEquipId = sConfigMgr->GetOption("AutoFish.RequiredEquipId", 0u); - sBobberEntries = ParseEntryList(sConfigMgr->GetOption("AutoFish.BobberEntries", "35591")); - } - - void OnUpdate(uint32 diff) override - { - if (!sEnabled) - return; - - static uint32 acc = 0; - acc += diff; - if (acc >= sTickMs) - { - 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); - } - } - - TickAutoLoot(diff); - TickRecast(diff); - } -}; - -void AddSC_autofish_world() -{ - new AutoFish_WorldScript(); -}