mirror of
https://github.com/liyunfan1223/mod-playerbots.git
synced 2026-02-20 10:00:02 +01:00
# Pull Request
This is the first in a series of PRs intended to eliminate warnings in
the module. The design intent is to eliminate the calling event when not
needed in the body of the function. Based off of SmashingQuasars work.
---
## How to Test the Changes
- Step-by-step instructions to test the change
- Any required setup (e.g. multiple players, bots, specific
configuration)
- Expected behavior and how to verify it
## 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**)
If this introduces more advanced or AI-heavy logic:
- [ ] Lightweight mode remains the default
- [ ] More complex behavior is optional and thereby configurable
---
## 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: bashermens <31279994+hermensbas@users.noreply.github.com>
185 lines
5.1 KiB
C++
185 lines
5.1 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 "StatsAction.h"
|
|
|
|
#include "ChatHelper.h"
|
|
#include "Event.h"
|
|
#include "PlayerbotAI.h"
|
|
|
|
bool StatsAction::Execute(Event /*event*/)
|
|
{
|
|
std::ostringstream out;
|
|
|
|
ListGold(out);
|
|
|
|
out << ", ";
|
|
ListBagSlots(out);
|
|
|
|
out << ", ";
|
|
ListRepairCost(out);
|
|
|
|
if (bot->GetUInt32Value(PLAYER_NEXT_LEVEL_XP))
|
|
{
|
|
out << ", ";
|
|
ListXP(out);
|
|
}
|
|
|
|
botAI->TellMaster(out);
|
|
return true;
|
|
}
|
|
|
|
void StatsAction::ListGold(std::ostringstream& out) { out << chat->formatMoney(bot->GetMoney()); }
|
|
|
|
void StatsAction::ListBagSlots(std::ostringstream& out)
|
|
{
|
|
uint32 totalused = 0, total = 16;
|
|
|
|
// list out items in main backpack
|
|
for (uint8 slot = INVENTORY_SLOT_ITEM_START; slot < INVENTORY_SLOT_ITEM_END; slot++)
|
|
{
|
|
if (bot->GetItemByPos(INVENTORY_SLOT_BAG_0, slot))
|
|
{
|
|
++totalused;
|
|
}
|
|
}
|
|
|
|
uint32 totalfree = 16 - totalused;
|
|
|
|
// list out items in other removable backpacks
|
|
for (uint8 bag = INVENTORY_SLOT_BAG_START; bag < INVENTORY_SLOT_BAG_END; ++bag)
|
|
{
|
|
if (Bag const* pBag = (Bag*)bot->GetItemByPos(INVENTORY_SLOT_BAG_0, bag))
|
|
{
|
|
ItemTemplate const* pBagProto = pBag->GetTemplate();
|
|
if (pBagProto->Class == ITEM_CLASS_CONTAINER && pBagProto->SubClass == ITEM_SUBCLASS_CONTAINER)
|
|
{
|
|
total += pBag->GetBagSize();
|
|
totalfree += pBag->GetFreeSlots();
|
|
}
|
|
}
|
|
}
|
|
|
|
std::string color = "ff00ff00";
|
|
if (totalfree < total / 2)
|
|
color = "ffffff00";
|
|
|
|
if (totalfree < total / 4)
|
|
color = "ffff0000";
|
|
|
|
out << "|h|c" << color << totalfree << "/" << total << "|h|cffffffff Bag";
|
|
}
|
|
|
|
void StatsAction::ListXP(std::ostringstream& out)
|
|
{
|
|
uint32 curXP = bot->GetUInt32Value(PLAYER_XP);
|
|
uint32 nextLevelXP = bot->GetUInt32Value(PLAYER_NEXT_LEVEL_XP);
|
|
uint32 restXP = bot->GetUInt32Value(PLAYER_REST_STATE_EXPERIENCE);
|
|
uint32 xpPercent = 0;
|
|
|
|
if (nextLevelXP)
|
|
xpPercent = 100 * curXP / nextLevelXP;
|
|
|
|
uint32 restPercent = 0;
|
|
if (restXP && nextLevelXP)
|
|
restPercent = 2 * (100 * restXP / nextLevelXP);
|
|
|
|
out << "|cff00ff00" << xpPercent << "|cffffd333/|cff00ff00" << restPercent << "%|cffffffff XP";
|
|
}
|
|
|
|
void StatsAction::ListRepairCost(std::ostringstream& out)
|
|
{
|
|
uint32 totalCost = 0;
|
|
double repairPercent = 0;
|
|
double repairCount = 0;
|
|
|
|
for (uint32 i = EQUIPMENT_SLOT_START; i < INVENTORY_SLOT_ITEM_END; ++i)
|
|
{
|
|
uint16 pos = ((INVENTORY_SLOT_BAG_0 << 8) | i);
|
|
totalCost += EstRepair(pos);
|
|
double repair = RepairPercent(pos);
|
|
if (repair < 100)
|
|
{
|
|
repairPercent += repair;
|
|
++repairCount;
|
|
}
|
|
}
|
|
|
|
repairPercent /= repairCount;
|
|
|
|
std::string color = "ff00ff00";
|
|
if (repairPercent < 50)
|
|
color = "ffffff00";
|
|
|
|
if (repairPercent < 25)
|
|
color = "ffff0000";
|
|
|
|
out << "|c" << color << (uint32)ceil(repairPercent) << "% (" << chat->formatMoney(totalCost) << ")|cffffffff Dur";
|
|
}
|
|
|
|
uint32 StatsAction::EstRepair(uint16 pos)
|
|
{
|
|
Item* item = bot->GetItemByPos(pos);
|
|
|
|
uint32 TotalCost = 0;
|
|
if (!item)
|
|
return TotalCost;
|
|
|
|
uint32 maxDurability = item->GetUInt32Value(ITEM_FIELD_MAXDURABILITY);
|
|
if (!maxDurability)
|
|
return TotalCost;
|
|
|
|
uint32 curDurability = item->GetUInt32Value(ITEM_FIELD_DURABILITY);
|
|
|
|
uint32 LostDurability = maxDurability - curDurability;
|
|
if (LostDurability > 0)
|
|
{
|
|
ItemTemplate const* ditemProto = item->GetTemplate();
|
|
|
|
DurabilityCostsEntry const* dcost = sDurabilityCostsStore.LookupEntry(ditemProto->ItemLevel);
|
|
if (!dcost)
|
|
{
|
|
LOG_ERROR("playerbots", "RepairDurability: Wrong item lvl {}", ditemProto->ItemLevel);
|
|
return TotalCost;
|
|
}
|
|
|
|
uint32 dQualitymodEntryId = (ditemProto->Quality + 1) * 2;
|
|
DurabilityQualityEntry const* dQualitymodEntry = sDurabilityQualityStore.LookupEntry(dQualitymodEntryId);
|
|
if (!dQualitymodEntry)
|
|
{
|
|
LOG_ERROR("playerbots", "RepairDurability: Wrong dQualityModEntry {}", dQualitymodEntryId);
|
|
return TotalCost;
|
|
}
|
|
|
|
uint32 dmultiplier =
|
|
dcost->multiplier[ItemSubClassToDurabilityMultiplierId(ditemProto->Class, ditemProto->SubClass)];
|
|
uint32 costs = uint32(LostDurability * dmultiplier * double(dQualitymodEntry->quality_mod));
|
|
|
|
if (!costs) // fix for ITEM_QUALITY_ARTIFACT
|
|
costs = 1;
|
|
|
|
TotalCost = costs;
|
|
}
|
|
|
|
return TotalCost;
|
|
}
|
|
|
|
double StatsAction::RepairPercent(uint16 pos)
|
|
{
|
|
Item* item = bot->GetItemByPos(pos);
|
|
if (!item)
|
|
return 100;
|
|
|
|
uint32 maxDurability = item->GetUInt32Value(ITEM_FIELD_MAXDURABILITY);
|
|
if (!maxDurability)
|
|
return 100;
|
|
|
|
uint32 curDurability = item->GetUInt32Value(ITEM_FIELD_DURABILITY);
|
|
if (!curDurability)
|
|
return 0;
|
|
|
|
return curDurability * 100.0 / maxDurability;
|
|
}
|