mod-playerbots/src/Ai/World/Rpg/NewRpgInfo.cpp
Keleborn 53a607e147
Enable bots to do Outdoor pvp (#2217)
## Pull Request Description
Bots will now engage with outdoor pvp targets when in an area with them.
I carved this out of the guildrpg system Im working on since it should
work just fine as a standalone. Note this requires a core update
https://github.com/azerothcore/azerothcore-wotlk/pull/25103

## Feature Evaluation

Its not expensive. the status checks are fairly light and simple. Should
be on par with current rpg system actions

## How to Test the Changes

You can try to use selfbot to enable this while in EPL, or set the
probability of all other rpg actions to 0.


## Impact Assessment
<!-- As a generic test, before and after measure of pmon (playerbot pmon
tick) can help you here. -->
- Does this change increase per-bot/per-tick processing or risk scaling
poorly with thousands of bots?
    - [ ] No, not at all
    - [x] Minimal impact (**explain below**)
    - [ ] Moderate impact (**explain below**)

There is some impact, but should be minimal overall. 

- Does this change modify default bot behavior?
    - [ ] No
    - [x] Yes (**explain why**)
It will activate automatically based on default config. 


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

## AI Assistance
Was AI assistance used while working on this change?
- [ ] No
- [x] Yes (**explain below**)
<!--
If yes, please specify:
- Purpose of usage (e.g. brainstorming, refactoring, documentation, code
generation).
- Which parts of the change were influenced or generated, and whether it
was thoroughly reviewed.
-->
Nothing beyond search functionality and autocomplete. 


## 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 (Conf comments, WiKi commands).

## Notes for Reviewers
<!-- Anything else that's helpful to review or test your pull request.
-->

---------

Co-authored-by: bash <hermensb@gmail.com>
Co-authored-by: Revision <tkn963@gmail.com>
Co-authored-by: kadeshar <kadeshar@gmail.com>
2026-04-10 22:16:58 -07:00

178 lines
5.1 KiB
C++

#include "NewRpgInfo.h"
#include <cmath>
#include "Timer.h"
void NewRpgInfo::ChangeToGoGrind(WorldPosition pos)
{
startT = getMSTime();
data = GoGrind{pos};
}
void NewRpgInfo::ChangeToGoCamp(WorldPosition pos)
{
startT = getMSTime();
data = GoCamp{pos};
}
void NewRpgInfo::ChangeToWanderNpc()
{
startT = getMSTime();
data = WanderNpc{};
}
void NewRpgInfo::ChangeToWanderRandom()
{
startT = getMSTime();
data = WanderRandom{};
}
void NewRpgInfo::ChangeToDoQuest(uint32 questId, const Quest* quest)
{
startT = getMSTime();
DoQuest do_quest;
do_quest.questId = questId;
do_quest.quest = quest;
data = do_quest;
}
void NewRpgInfo::ChangeToTravelFlight(ObjectGuid fromFlightMaster, std::vector<uint32> path)
{
startT = getMSTime();
TravelFlight flight;
flight.fromFlightMaster = fromFlightMaster;
flight.path = std::move(path);
flight.inFlight = false;
data = flight;
}
void NewRpgInfo::ChangeToOutdoorPvp(ObjectGuid::LowType capturePointSpawnId)
{
startT = getMSTime();
OutdoorPvP pvp;
pvp.capturePointSpawnId = capturePointSpawnId;
data = pvp;
}
void NewRpgInfo::ChangeToRest()
{
startT = getMSTime();
data = Rest{};
}
void NewRpgInfo::ChangeToIdle()
{
startT = getMSTime();
data = Idle{};
}
bool NewRpgInfo::CanChangeTo(NewRpgStatus)
{
return true;
}
void NewRpgInfo::Reset()
{
data = Idle{};
startT = getMSTime();
}
void NewRpgInfo::SetMoveFarTo(WorldPosition pos)
{
nearestMoveFarDis = FLT_MAX;
stuckTs = 0;
stuckAttempts = 0;
moveFarPos = pos;
}
NewRpgStatus NewRpgInfo::GetStatus()
{
return std::visit([](auto&& arg) -> NewRpgStatus {
using T = std::decay_t<decltype(arg)>;
if constexpr (std::is_same_v<T, Idle>) return RPG_IDLE;
if constexpr (std::is_same_v<T, GoGrind>) return RPG_GO_GRIND;
if constexpr (std::is_same_v<T, GoCamp>) return RPG_GO_CAMP;
if constexpr (std::is_same_v<T, WanderNpc>) return RPG_WANDER_NPC;
if constexpr (std::is_same_v<T, WanderRandom>) return RPG_WANDER_RANDOM;
if constexpr (std::is_same_v<T, Rest>) return RPG_REST;
if constexpr (std::is_same_v<T, DoQuest>) return RPG_DO_QUEST;
if constexpr (std::is_same_v<T, TravelFlight>) return RPG_TRAVEL_FLIGHT;
if constexpr (std::is_same_v<T, OutdoorPvP>) return RPG_OUTDOOR_PVP;
return RPG_IDLE;
}, data);
}
std::string NewRpgInfo::ToString()
{
std::stringstream out;
out << "Status: ";
std::visit([&out, this](auto&& arg)
{
using T = std::decay_t<decltype(arg)>;
if constexpr (std::is_same_v<T, GoGrind>)
{
out << "GO_GRIND";
out << "\nGrindPos: " << arg.pos.GetMapId() << " " << arg.pos.GetPositionX() << " "
<< arg.pos.GetPositionY() << " " << arg.pos.GetPositionZ();
out << "\nlastGoGrind: " << startT;
}
else if constexpr (std::is_same_v<T, GoCamp>)
{
out << "GO_CAMP";
out << "\nCampPos: " << arg.pos.GetMapId() << " " << arg.pos.GetPositionX() << " "
<< arg.pos.GetPositionY() << " " << arg.pos.GetPositionZ();
out << "\nlastGoCamp: " << startT;
}
else if constexpr (std::is_same_v<T, WanderNpc>)
{
out << "WANDER_NPC";
out << "\nnpcOrGoEntry: " << arg.npcOrGo.GetCounter();
out << "\nlastWanderNpc: " << startT;
out << "\nlastReachNpcOrGo: " << arg.lastReach;
}
else if constexpr (std::is_same_v<T, WanderRandom>)
{
out << "WANDER_RANDOM";
out << "\nlastWanderRandom: " << startT;
}
else if constexpr (std::is_same_v<T, Idle>)
{
out << "IDLE";
}
else if constexpr (std::is_same_v<T, Rest>)
{
out << "REST";
out << "\nlastRest: " << startT;
}
else if constexpr (std::is_same_v<T, DoQuest>)
{
out << "DO_QUEST";
out << "\nquestId: " << arg.questId;
out << "\nobjectiveIdx: " << arg.objectiveIdx;
out << "\npoiPos: " << arg.pos.GetMapId() << " " << arg.pos.GetPositionX() << " "
<< arg.pos.GetPositionY() << " " << arg.pos.GetPositionZ();
out << "\nlastReachPOI: " << (arg.lastReachPOI ? GetMSTimeDiffToNow(arg.lastReachPOI) : 0);
}
else if constexpr (std::is_same_v<T, TravelFlight>)
{
out << "TRAVEL_FLIGHT";
out << "\nfromFlightMaster: " << arg.fromFlightMaster.GetEntry();
out << "\nfromNode: " << arg.path[0];
out << "\ntoNode: " << arg.path[arg.path.size() - 1];
out << "\ninFlight: " << arg.inFlight;
}
else if constexpr (std::is_same_v<T, OutdoorPvP>)
{
out << "OUTDOOR_PVP";
if (!arg.capturePointSpawnId)
out << "\nNo capture point assigned.";
else
out << "\ncapturePointSpawnId: " << arg.capturePointSpawnId;
}
else
out << "UNKNOWN";
}, data);
return out.str();
}