Files
mod-playerbots/src/Ai/Base/Actions/TradeAction.cpp
bashermens 13fff46fa0 Improper singletons migration to clean Meyer's singletons (cherry-pick) (#2082)
# Pull Request

- Applies the clean and corrected singletons, Meyer pattern. (cherry
picked from @SmashingQuasar )

Testing by just playing the game in various ways. Been tested by myself
@Celandriel and @SmashingQuasar
---

## Complexity & Impact

- Does this change add new decision branches?
    - [x] No
    - [ ] Yes (**explain below**)

- Does this change increase per-bot or per-tick processing?
    - [x] No
    - [ ] Yes (**describe and justify impact**)

- Could this logic scale poorly under load?
    - [x] No
    - [ ] Yes (**explain why**)

---

## Defaults & Configuration

- Does this change modify default bot behavior?
    - [x] No
    - [ ] Yes (**explain why**)

---

## AI Assistance

- Was AI assistance (e.g. ChatGPT or similar tools) used while working
on this change?
    - [x] No
    - [ ] Yes (**explain below**)
---

## Final Checklist

- [x] Stability is not compromised
- [x] Performance impact is understood, tested, and acceptable
- [x] Added logic complexity is justified and explained
- [x] Documentation updated if needed

---

## Notes for Reviewers

Anything that significantly improves realism at the cost of stability or
performance should be carefully discussed
before merging.

---------

Co-authored-by: Nicolas Lebacq <nicolas.cordier@outlook.com>
Co-authored-by: Keleborn <22352763+Celandriel@users.noreply.github.com>
2026-01-30 21:49:37 +01:00

125 lines
3.5 KiB
C++

/*
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU AGPL v3 license, you may redistribute it
* and/or modify it under version 3 of the License, or (at your option), any later version.
*/
#include "TradeAction.h"
#include "ChatHelper.h"
#include "Event.h"
#include "ItemCountValue.h"
#include "ItemVisitors.h"
#include "Playerbots.h"
bool TradeAction::Execute(Event event)
{
std::string const text = event.getParam();
// If text starts with any excluded prefix, don't process it further.
for (auto const& prefix : sPlayerbotAIConfig.tradeActionExcludedPrefixes)
{
if (text.find(prefix) == 0)
return false;
}
if (!bot->GetTrader())
{
GuidVector guids = chat->parseGameobjects(text);
Player* player = nullptr;
for (auto& guid : guids)
if (guid.IsPlayer())
player = ObjectAccessor::FindPlayer(guid);
if (!player && botAI->GetMaster())
player = botAI->GetMaster();
if (!player)
return false;
if (!player->GetTrader())
{
WorldPacket packet(CMSG_INITIATE_TRADE);
packet << player->GetGUID();
bot->GetSession()->HandleInitiateTradeOpcode(packet);
return true;
}
else if (player->GetTrader() != bot)
return false;
}
uint32 copper = chat->parseMoney(text);
if (copper > 0)
{
WorldPacket packet(CMSG_SET_TRADE_GOLD, 4);
packet << copper;
bot->GetSession()->HandleSetTradeGoldOpcode(packet);
}
size_t pos = text.rfind(" ");
int count = pos != std::string::npos ? atoi(text.substr(pos + 1).c_str()) : 1;
std::vector<Item*> found = parseItems(text);
if (found.empty())
return false;
uint32 traded = 0;
for (Item* item : found)
{
if (!bot->GetTrader() || item->IsInTrade())
continue;
int8 slot = item->CanBeTraded() ? -1 : TRADE_SLOT_NONTRADED;
if (TradeItem(item, slot) && slot != TRADE_SLOT_NONTRADED && ++traded >= count)
break;
}
return true;
}
bool TradeAction::TradeItem(Item const* item, int8 slot)
{
int8 tradeSlot = -1;
Item* itemPtr = const_cast<Item*>(item);
TradeData* pTrade = bot->GetTradeData();
if ((slot >= 0 && slot < TRADE_SLOT_COUNT) && pTrade->GetItem(TradeSlots(slot)) == nullptr)
tradeSlot = slot;
if (slot == TRADE_SLOT_NONTRADED)
pTrade->SetItem(TRADE_SLOT_NONTRADED, itemPtr);
else
{
for (uint8 i = 0; i < TRADE_SLOT_TRADED_COUNT && tradeSlot == -1; i++)
{
if (pTrade->GetItem(TradeSlots(i)) == itemPtr)
{
tradeSlot = i;
WorldPacket packet(CMSG_CLEAR_TRADE_ITEM, 1);
packet << (uint8)tradeSlot;
bot->GetSession()->HandleClearTradeItemOpcode(packet);
pTrade->SetItem(TradeSlots(i), nullptr);
return true;
}
}
for (uint8 i = 0; i < TRADE_SLOT_TRADED_COUNT && tradeSlot == -1; i++)
{
if (pTrade->GetItem(TradeSlots(i)) == nullptr)
{
tradeSlot = i;
}
}
}
if (tradeSlot == -1)
return false;
WorldPacket packet(CMSG_SET_TRADE_ITEM, 3);
packet << (uint8)tradeSlot;
packet << (uint8)item->GetBagSlot();
packet << (uint8)item->GetSlot();
bot->GetSession()->HandleSetTradeItemOpcode(packet);
return true;
}