Files
mod-playerbots/src/TravelMgr.h
2022-09-22 16:03:27 -06:00

991 lines
32 KiB
C++

/*
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU GPL v2 license, you may redistribute it and/or modify it under version 2 of the License, or (at your option), any later version.
*/
#ifndef _PLAYERBOT_TRAVELMGR_H
#define _PLAYERBOT_TRAVELMGR_H
#include "AiObject.h"
#include "CreatureData.h"
#include "GameObject.h"
#include "GridDefines.h"
#include "PlayerbotAIConfig.h"
#include <boost/functional/hash.hpp>
#include <random>
class GuidPosition;
class ObjectGuid;
class Quest;
class Player;
class PlayerbotAI;
struct QuestStatusData;
namespace G3D
{
class Vector2;
class Vector3;
class Vector4;
}
//Constructor types for WorldPosition
enum WorldPositionConst
{
WP_RANDOM = 0,
WP_CENTROID = 1,
WP_MEAN_CENTROID = 2,
WP_CLOSEST = 3
};
enum TravelState
{
TRAVEL_STATE_IDLE = 0,
TRAVEL_STATE_TRAVEL_PICK_UP_QUEST = 1,
TRAVEL_STATE_WORK_PICK_UP_QUEST = 2,
TRAVEL_STATE_TRAVEL_DO_QUEST = 3,
TRAVEL_STATE_WORK_DO_QUEST = 4,
TRAVEL_STATE_TRAVEL_HAND_IN_QUEST = 5,
TRAVEL_STATE_WORK_HAND_IN_QUEST = 6,
TRAVEL_STATE_TRAVEL_RPG = 7,
TRAVEL_STATE_TRAVEL_EXPLORE = 8,
MAX_TRAVEL_STATE
};
enum TravelStatus
{
TRAVEL_STATUS_NONE = 0,
TRAVEL_STATUS_PREPARE = 1,
TRAVEL_STATUS_TRAVEL = 2,
TRAVEL_STATUS_WORK = 3,
TRAVEL_STATUS_COOLDOWN = 4,
TRAVEL_STATUS_EXPIRED = 5,
MAX_TRAVEL_STATUS
};
class QuestTravelDestination;
//A quest destination container for quick lookup of all destinations related to a quest.
struct QuestContainer
{
std::vector<QuestTravelDestination*> questGivers;
std::vector<QuestTravelDestination*> questTakers;
std::vector<QuestTravelDestination*> questObjectives;
};
typedef std::pair<int32, int32> mGridCoord;
//Extension of WorldLocation with distance functions.
class WorldPosition : public WorldLocation
{
public:
//Constructors
WorldPosition() : WorldLocation() { };
WorldPosition(WorldLocation const& loc) : WorldLocation(loc) { }
WorldPosition(WorldPosition const& pos) : WorldLocation(pos), visitors(pos.visitors) { }
WorldPosition(std::string const str);
WorldPosition(uint32 mapid, float x, float y, float z = 0.f, float orientation = 0.f) : WorldLocation(mapid, x, y, z, orientation) { }
WorldPosition(uint32 mapId, const Position& pos);
WorldPosition(WorldObject const* wo);
WorldPosition(std::vector<WorldPosition*> list, WorldPositionConst conType);
WorldPosition(std::vector<WorldPosition> list, WorldPositionConst conType);
WorldPosition(uint32 mapid, GridCoord grid);
WorldPosition(uint32 mapid, CellCoord cell);
WorldPosition(uint32 mapid, mGridCoord grid);
//Setters
void set(const WorldLocation& pos);
void setMapId(uint32 id);
void setX(float x);
void setY(float y);
void setZ(float z);
void setO(float o);
void addVisitor()
{
++visitors;
}
void remVisitor()
{
--visitors;
}
//Getters
operator bool() const;
bool operator==(WorldPosition const& p1);
bool operator!=(WorldPosition const& p1);
WorldPosition& operator+=(WorldPosition const& p1);
WorldPosition& operator-=(WorldPosition const& p1);
uint32 getMapId();
float getX();
float getY();
float getZ();
float getO();
G3D::Vector3 getVector3();
std::string const print();
std::string const to_string();
void printWKT(std::vector<WorldPosition> points, std::ostringstream& out, uint32 dim = 0, bool loop = false);
void printWKT(std::ostringstream& out) { printWKT({ *this }, out); }
uint32 getVisitors() { return visitors; }
bool isOverworld();
bool isInWater();
bool isUnderWater();
WorldPosition relPoint(WorldPosition* center);
WorldPosition offset(WorldPosition* center);
float size();
//Slow distance function using possible map transfers.
float distance(WorldPosition* center);
float distance(WorldPosition center)
{
return distance(&center);
}
float fDist(WorldPosition* center);
float fDist(WorldPosition center)
{
return fDist(&center);
}
template<class T>
std::pair<T, WorldPosition> closest(std::vector<std::pair<T, WorldPosition>> list)
{
return *std::min_element(list.begin(), list.end(), [this](std::pair<T, WorldPosition> i, std::pair<T, WorldPosition> j)
{
return this->distance(i.second) < this->distance(j.second);
});
}
template<class T>
std::pair<T, WorldPosition> closest(std::vector<T> list)
{
return closest(GetPosList(list));
}
//Returns the closest point from the list.
WorldPosition* closest(std::vector<WorldPosition*> list)
{
return *std::min_element(list.begin(), list.end(), [this](WorldPosition* i, WorldPosition* j) { return this->distance(i) < this->distance(j); });
}
WorldPosition closest(std::vector<WorldPosition> list)
{
return *std::min_element(list.begin(), list.end(), [this](WorldPosition i, WorldPosition j) { return this->distance(i) < this->distance(j); });
}
//Quick square distance in 2d plane.
float sqDistance2d(WorldPosition center)
{
return (getX() - center.getX()) * (getX() - center.getX()) + (getY() - center.getY()) * (getY() - center.getY());
}
//Quick square distance calculation without map check. Used for getting the minimum distant points.
float sqDistance(WorldPosition center)
{
return (getX() - center.getX()) * (getX() - center.getX()) + (getY() - center.getY()) *
(getY() - center.getY()) + (getZ() - center.getZ()) * (getZ() - center.getZ());
}
float sqDistance2d(WorldPosition* center)
{
return (getX() - center->getX()) * (getX() - center->getX()) + (getY() - center->getY()) * (getY() - center->getY());
}
float sqDistance(WorldPosition* center)
{
return (getX() - center->getX()) * (getX() - center->getX()) + (getY() - center->getY()) *
(getY() - center->getY()) + (getZ() - center->getZ()) * (getZ() - center->getZ());
}
//Returns the closest point of the list. Fast but only works for the same map.
WorldPosition* closestSq(std::vector<WorldPosition*> list)
{
return *std::min_element(list.begin(), list.end(), [this](WorldPosition* i, WorldPosition* j) { return this->sqDistance(i) < this->sqDistance(j); });
}
WorldPosition closestSq(std::vector<WorldPosition> list)
{
return *std::min_element(list.begin(), list.end(), [this](WorldPosition i, WorldPosition j) { return this->sqDistance(i) < this->sqDistance(j); });
}
float getAngleTo(WorldPosition endPos)
{
float ang = atan2(endPos.getY() - getY(), endPos.getX() - getX());
return (ang >= 0) ? ang : 2 * static_cast<float>(M_PI) + ang;
}
float getAngleBetween(WorldPosition dir1, WorldPosition dir2)
{
return abs(getAngleTo(dir1) - getAngleTo(dir2));
}
WorldPosition lastInRange(std::vector<WorldPosition> list, float minDist = -1.f, float maxDist = -1.f);
WorldPosition firstOutRange(std::vector<WorldPosition> list, float minDist = -1.f, float maxDist = -1.f);
float mSign(WorldPosition* p1, WorldPosition* p2)
{
return(getX() - p2->getX()) * (p1->getY() - p2->getY()) - (p1->getX() - p2->getX()) * (getY() - p2->getY());
}
bool isInside(WorldPosition* p1, WorldPosition* p2, WorldPosition* p3);
//Map functions. Player independent.
MapEntry const* getMapEntry();
uint32 getInstanceId();
Map* getMap();
float getHeight(); // remove const - whipowill
std::set<Transport*> getTransports(uint32 entry = 0);
GridCoord getGridCoord() { return Acore::ComputeGridCoord(getX(), getY()); };
std::vector<GridCoord> getGridCoord(WorldPosition secondPos);
std::vector<WorldPosition> fromGridCoord(GridCoord GridCoord);
CellCoord getCellCoord() { return Acore::ComputeCellCoord(getX(), getY()); }
std::vector<WorldPosition> fromCellCoord(CellCoord cellCoord);
std::vector<WorldPosition> gridFromCellCoord(CellCoord cellCoord);
mGridCoord getmGridCoord()
{
return std::make_pair((int32)(CENTER_GRID_ID - getX() / SIZE_OF_GRIDS), (int32)(CENTER_GRID_ID - getY() / SIZE_OF_GRIDS));
}
std::vector<mGridCoord> getmGridCoords(WorldPosition secondPos);
std::vector<WorldPosition> frommGridCoord(mGridCoord GridCoord);
void loadMapAndVMap(uint32 mapId, uint8 x, uint8 y);
void loadMapAndVMap()
{
loadMapAndVMap(getMapId(), getmGridCoord().first, getmGridCoord().second);
}
void loadMapAndVMaps(WorldPosition secondPos);
//Display functions
WorldPosition getDisplayLocation();
float getDisplayX()
{
return getDisplayLocation().getY() * -1.0;
}
float getDisplayY()
{
return getDisplayLocation().getX();
}
uint16 getAreaId();
AreaTableEntry const* getArea();
std::string const getAreaName(bool fullName = true, bool zoneName = false);
std::vector<WorldPosition> fromPointsArray(std::vector<G3D::Vector3> path);
//Pathfinding
std::vector<WorldPosition> getPathStepFrom(WorldPosition startPos, Unit* bot);
std::vector<WorldPosition> getPathFromPath(std::vector<WorldPosition> startPath, Unit* bot, uint8 maxAttempt = 40);
std::vector<WorldPosition> getPathFrom(WorldPosition startPos, Unit* bot)
{
return getPathFromPath({ startPos }, bot);
}
std::vector<WorldPosition> getPathTo(WorldPosition endPos, Unit* bot)
{
return endPos.getPathFrom(*this, bot);
}
bool isPathTo(std::vector<WorldPosition> path, float maxDistance = sPlayerbotAIConfig->targetPosRecalcDistance) { return !path.empty() && distance(path.back()) < maxDistance; };
bool cropPathTo(std::vector<WorldPosition>& path, float maxDistance = sPlayerbotAIConfig->targetPosRecalcDistance);
bool canPathTo(WorldPosition endPos, Unit* bot) { return endPos.isPathTo(getPathTo(endPos, bot)); }
float getPathLength(std::vector<WorldPosition> points)
{
float dist = 0.f;
for (auto& p : points)
{
if (&p == &points.front())
dist = 0.f;
else
dist += std::prev(&p, 1)->distance(p);
}
return dist;
}
bool GetReachableRandomPointOnGround(Player* bot, float radius, bool randomRange = true);
uint32 getUnitsAggro(GuidVector& units, Player* bot);
//Creatures
std::vector<CreatureData const*> getCreaturesNear(float radius = 0, uint32 entry = 0);
//GameObjects
std::vector<GameObjectData const*> getGameObjectsNear(float radius = 0, uint32 entry = 0);
private:
uint32 visitors = 0;
};
inline ByteBuffer& operator<<(ByteBuffer& b, WorldPosition& guidP)
{
b << guidP.getMapId();
b << guidP.getX();
b << guidP.getY();
b << guidP.getZ();
b << guidP.getO();
b << guidP.getVisitors();
return b;
}
inline ByteBuffer& operator>>(ByteBuffer& b, [[maybe_unused]] WorldPosition& g)
{
uint32 mapid;
float coord_x;
float coord_y;
float coord_z;
float orientation;
uint32 visitors = 0;
b >> mapid;
b >> coord_x;
b >> coord_y;
b >> coord_z;
b >> orientation;
b >> visitors;
return b;
}
//Generic creature finder
class FindPointCreatureData
{
public:
FindPointCreatureData(WorldPosition point1 = WorldPosition(), float radius1 = 0, uint32 entry1 = 0) { point = point1; radius = radius1; entry = entry1; }
void operator()(CreatureData const& dataPair);
std::vector<CreatureData const*> GetResult() const { return data; };
private:
WorldPosition point;
float radius;
uint32 entry;
std::vector<CreatureData const*> data;
};
//Generic gameObject finder
class FindPointGameObjectData
{
public:
FindPointGameObjectData(WorldPosition point1 = WorldPosition(), float radius1 = 0, uint32 entry1 = 0) { point = point1; radius = radius1; entry = entry1; }
void operator()(GameObjectData const& dataPair);
std::vector<GameObjectData const*> GetResult() const { return data; };
private:
WorldPosition point;
float radius;
uint32 entry;
std::vector<GameObjectData const*> data;
};
class GuidPosition : public ObjectGuid, public WorldPosition
{
public:
GuidPosition() : ObjectGuid(), WorldPosition(), loadedFromDB(false) { }
GuidPosition(WorldObject* wo);
GuidPosition(CreatureData const& creData);
GuidPosition(GameObjectData const& goData);
CreatureTemplate const* GetCreatureTemplate();
GameObjectTemplate const* GetGameObjectTemplate();
WorldObject* GetWorldObject();
Creature* GetCreature();
Unit* GetUnit();
GameObject* GetGameObject();
Player* GetPlayer();
bool HasNpcFlag(NPCFlags flag);
bool isDead(); //For loaded grids check if the unit/object is unloaded/dead.
operator bool() const { return !IsEmpty(); }
bool operator==(ObjectGuid const& guid) const { return GetRawValue() == guid.GetRawValue(); }
bool operator!=(ObjectGuid const& guid) const { return GetRawValue() != guid.GetRawValue(); }
bool operator<(ObjectGuid const& guid) const { return GetRawValue() < guid.GetRawValue(); }
private:
bool loadedFromDB;
};
template<class T>
std::vector<std::pair<T, WorldPosition>> GetPosList(std::vector<T> oList)
{
std::vector<std::pair<T, WorldPosition>> retList;
for (auto& obj : oList)
retList.push_back(std::make_pair(obj, WorldPosition(obj)));
return std::move(retList);
};
template<class T>
std::vector<std::pair<T, WorldPosition>> GetPosVector(std::vector<T> oList)
{
std::vector<std::pair<T, WorldPosition>> retList;
for (auto& obj : oList)
retList.push_back(make_pair(obj, WorldPosition(obj)));
return std::move(retList);
};
class mapTransfer
{
public:
mapTransfer(WorldPosition pointFrom1, WorldPosition pointTo1, float portalLength1 = 0.1f)
: pointFrom(pointFrom1), pointTo(pointTo1), portalLength(portalLength1) { }
bool isFrom(WorldPosition point)
{
return point.getMapId() == pointFrom.getMapId();
}
bool isTo(WorldPosition point)
{
return point.getMapId() == pointTo.getMapId();
}
WorldPosition* getPointFrom()
{
return &pointFrom;
}
WorldPosition* getPointTo()
{
return &pointTo;
}
bool isUseful(WorldPosition point)
{
return isFrom(point) || isTo(point);
}
float distance(WorldPosition point)
{
return isUseful(point) ? (isFrom(point) ? point.distance(pointFrom) : point.distance(pointTo)) : 200000;
}
bool isUseful(WorldPosition start, WorldPosition end)
{
return isFrom(start) && isTo(end);
}
float distance(WorldPosition start, WorldPosition end)
{
return (isUseful(start, end) ? (start.distance(pointFrom) + portalLength + pointTo.distance(end)) : 200000);
}
float fDist(WorldPosition start, WorldPosition end);
private:
WorldPosition pointFrom;
WorldPosition pointTo;
float portalLength = 0.1f;
};
//A destination for a bot to travel to and do something.
class TravelDestination
{
public:
TravelDestination() { }
TravelDestination(float radiusMin1, float radiusMax1)
{
radiusMin = radiusMin1; radiusMax = radiusMax1;
}
TravelDestination(std::vector<WorldPosition*> points1, float radiusMin1, float radiusMax1)
{
points = points1; radiusMin = radiusMin1; radiusMax = radiusMax1;
}
void addPoint(WorldPosition* pos)
{
points.push_back(pos);
}
void setExpireDelay(uint32 delay)
{
expireDelay = delay;
}
void setCooldownDelay(uint32 delay)
{
cooldownDelay = delay;
}
void setMaxVisitors(uint32 maxVisitors1 = 0, uint32 maxVisitorsPerPoint1 = 0)
{
maxVisitors = maxVisitors1;
maxVisitorsPerPoint = maxVisitorsPerPoint1;
}
std::vector<WorldPosition*> getPoints(bool ignoreFull = false);
uint32 getExpireDelay() { return expireDelay; }
uint32 getCooldownDelay() { return cooldownDelay; }
void addVisitor()
{
++visitors;
}
void remVisitor()
{
--visitors;
}
uint32 getVisitors()
{
return visitors;
}
virtual Quest const* GetQuestTemplate() { return nullptr; }
virtual bool isActive([[maybe_unused]] Player* bot) { return false; }
bool isFull(bool ignoreFull = false);
virtual std::string const getName() { return "TravelDestination"; }
virtual int32 getEntry() { return 0; }
virtual std::string const getTitle() { return "generic travel destination"; }
WorldPosition* nearestPoint(WorldPosition* pos);
float distanceTo(WorldPosition* pos) { return nearestPoint(pos)->distance(pos); }
bool onMap(WorldPosition* pos) { return nearestPoint(pos)->getMapId() == pos->getMapId(); }
virtual bool isIn(WorldPosition* pos, float radius = 0.f) { return onMap(pos) && distanceTo(pos) <= (radius? radius : radiusMin); }
virtual bool isOut(WorldPosition* pos, float radius = 0.f) { return !onMap(pos) || distanceTo(pos) > (radius? radius : radiusMax); }
float getRadiusMin() { return radiusMin; }
std::vector<WorldPosition*> touchingPoints(WorldPosition* pos);
std::vector<WorldPosition*> sortedPoints(WorldPosition* pos);
std::vector<WorldPosition*> nextPoint(WorldPosition* pos, bool ignoreFull = true);
protected:
std::vector<WorldPosition*> points;
float radiusMin = 0;
float radiusMax = 0;
uint32 visitors = 0;
uint32 maxVisitors = 0;
uint32 maxVisitorsPerPoint = 0;
uint32 expireDelay = 5 * 1000;
uint32 cooldownDelay = 60 * 1000;
};
//A travel target that is always inactive and jumps to cooldown.
class NullTravelDestination : public TravelDestination
{
public:
NullTravelDestination(uint32 cooldownDelay1 = 5 * 60 * 1000) : TravelDestination()
{
cooldownDelay = cooldownDelay1;
};
Quest const* GetQuestTemplate() override { return nullptr; }
bool isActive([[maybe_unused]] Player* bot) override { return false; }
std::string const getName() override { return "NullTravelDestination"; }
std::string const getTitle() override { return "no destination"; }
bool isIn([[maybe_unused]] WorldPosition* pos, [[maybe_unused]] float radius = 0.f) override { return true; }
bool isOut([[maybe_unused]] WorldPosition* pos, [[maybe_unused]] float radius = 0.f) override { return false; }
};
//A travel target specifically related to a quest.
class QuestTravelDestination : public TravelDestination
{
public:
QuestTravelDestination(uint32 questId1, float radiusMin1, float radiusMax1);
Quest const* GetQuestTemplate() override { return questTemplate; }
bool isActive(Player* bot) override;
std::string const getName() override { return "QuestTravelDestination"; }
int32 getEntry() override { return 0; }
std::string const getTitle() override;
protected:
uint32 questId;
Quest const* questTemplate;
};
//A quest giver or taker.
class QuestRelationTravelDestination : public QuestTravelDestination
{
public:
QuestRelationTravelDestination(uint32 quest_id1, uint32 entry1, uint32 relation1, float radiusMin1, float radiusMax1) :
QuestTravelDestination(quest_id1, radiusMin1, radiusMax1)
{
entry = entry1;
relation = relation1;
}
bool isActive(Player* bot) override;
std::string const getName() override { return "QuestRelationTravelDestination"; }
int32 getEntry() override { return entry; }
std::string const getTitle() override;
virtual uint32 getRelation() { return relation; }
private:
uint32 relation;
int32 entry;
};
//A quest objective (creature/gameobject to grind/loot)
class QuestObjectiveTravelDestination : public QuestTravelDestination
{
public:
QuestObjectiveTravelDestination(uint32 quest_id1, uint32 entry1, uint32 objective1, float radiusMin1, float radiusMax1, uint32 itemId1 = 0) :
QuestTravelDestination(quest_id1, radiusMin1, radiusMax1)
{
objective = objective1;
entry = entry1;
itemId = itemId1;
}
bool isCreature();
uint32 ReqCreature();
uint32 ReqGOId();
uint32 ReqCount();
bool isActive(Player* bot) override;
std::string const getName() override { return "QuestObjectiveTravelDestination"; }
int32 getEntry() override { return entry; }
std::string const getTitle() override;
private:
uint32 objective;
uint32 entry;
uint32 itemId = 0;
};
//A location with rpg target(s) based on race and level
class RpgTravelDestination : public TravelDestination
{
public:
RpgTravelDestination(uint32 entry1, float radiusMin1, float radiusMax1) : TravelDestination(radiusMin1, radiusMax1)
{
entry = entry1;
}
bool isActive(Player* bot) override;
virtual CreatureTemplate const* GetCreatureTemplate();
std::string const getName() override { return "RpgTravelDestination"; }
int32 getEntry() override { return 0; }
std::string const getTitle() override;
protected:
uint32 entry;
};
//A location with zone exploration target(s)
class ExploreTravelDestination : public TravelDestination
{
public:
ExploreTravelDestination(uint32 areaId1, float radiusMin1, float radiusMax1) : TravelDestination(radiusMin1, radiusMax1)
{
areaId = areaId1;
}
bool isActive(Player* bot) override;
std::string const getName() override { return "ExploreTravelDestination"; }
int32 getEntry() override { return 0; }
std::string const getTitle() override { return title; };
virtual void setTitle(std::string newTitle) { title = newTitle; }
virtual uint32 getAreaId() { return areaId; }
protected:
uint32 areaId;
std::string title = "";
};
//A location with zone exploration target(s)
class GrindTravelDestination : public TravelDestination
{
public:
GrindTravelDestination(int32 entry1, float radiusMin1, float radiusMax1) : TravelDestination(radiusMin1, radiusMax1)
{
entry = entry1;
}
bool isActive(Player* bot) override;
virtual CreatureTemplate const* GetCreatureTemplate();
std::string const getName() override { return "GrindTravelDestination"; }
int32 getEntry() override { return entry; }
std::string const getTitle() override;
protected:
int32 entry;
};
//A location with a boss
class BossTravelDestination : public TravelDestination
{
public:
BossTravelDestination(int32 entry1, float radiusMin1, float radiusMax1) : TravelDestination(radiusMin1, radiusMax1)
{
entry = entry1;
cooldownDelay = 1000;
}
bool isActive(Player* bot) override;
CreatureTemplate const* getCreatureTemplate();
std::string const getName() override { return "BossTravelDestination"; }
int32 getEntry() override { return entry; }
std::string const getTitle() override;
protected:
int32 entry;
};
//Current target and location for the bot to travel to.
//The flow is as follows:
//PREPARE (wait until no loot is near)
//TRAVEL (move towards target until close enough) (rpg and grind is disabled)
//WORK (grind/rpg until the target is no longer active) (rpg and grind is enabled on quest mobs)
//COOLDOWN (wait some time free to do what the bot wants)
//EXPIRE (if any of the above actions take too long pick a new target)
class TravelTarget : AiObject
{
public:
TravelTarget(PlayerbotAI* botAI) : AiObject(botAI), m_status(TRAVEL_STATUS_NONE), startTime(getMSTime()) { };
TravelTarget(PlayerbotAI* botAI, TravelDestination* tDestination1, WorldPosition* wPosition1) : AiObject(botAI), m_status(TRAVEL_STATUS_NONE), startTime(getMSTime())
{
setTarget(tDestination1, wPosition1);
}
~TravelTarget();
void setTarget(TravelDestination* tDestination1, WorldPosition* wPosition1, bool groupCopy1 = false);
void setStatus(TravelStatus status);
void setExpireIn(uint32 expireMs)
{
statusTime = getExpiredTime() + expireMs;
}
void incRetry(bool isMove)
{
if (isMove)
++moveRetryCount;
else
++extendRetryCount;
}
void setRetry(bool isMove, uint32 newCount = 0)
{
if (isMove)
moveRetryCount = newCount;
else
extendRetryCount = newCount;
}
void setForced(bool forced1)
{
forced = forced1;
}
void setRadius(float radius1)
{
radius = radius1;
}
void copyTarget(TravelTarget* target);
void addVisitors();
void releaseVisitors();
float distance(Player* bot);
WorldPosition* getPosition();
TravelDestination* getDestination();
uint32 getEntry()
{
if (!tDestination)
return 0;
return tDestination->getEntry();
}
PlayerbotAI* getAi()
{
return botAI;
}
uint32 getExpiredTime()
{
return getMSTime() - startTime;
}
uint32 getTimeLeft()
{
return statusTime - getExpiredTime();
}
uint32 getMaxTravelTime();
uint32 getRetryCount(bool isMove)
{
return isMove ? moveRetryCount: extendRetryCount;
}
bool isTraveling();
bool isActive();
bool isWorking();
bool isPreparing();
bool isMaxRetry(bool isMove)
{
return isMove ? (moveRetryCount > 5) : (extendRetryCount > 5);
}
TravelStatus getStatus()
{
return m_status;
}
TravelState getTravelState();
bool isGroupCopy()
{
return groupCopy;
}
bool isForced()
{
return forced;
}
protected:
TravelStatus m_status;
uint32 startTime;
uint32 statusTime = 0;
bool forced = false;
float radius = 0.f;
bool groupCopy = false;
bool visitor = true;
uint32 extendRetryCount = 0;
uint32 moveRetryCount = 0;
TravelDestination* tDestination = nullptr;
WorldPosition* wPosition = nullptr;
};
//General container for all travel destinations.
class TravelMgr
{
public:
TravelMgr() { };
static TravelMgr* instance()
{
static TravelMgr instance;
return &instance;
}
void Clear();
void LoadQuestTravelTable();
template <class D, class W, class URBG>
void weighted_shuffle(D first, D last, W first_weight, W last_weight, URBG&& g)
{
while (first != last && first_weight != last_weight)
{
std::discrete_distribution<int>dd(first_weight, last_weight);
auto i = dd(g);
if (i)
{
std::swap(*first, *std::next(first, i));
std::swap(*first_weight, *std::next(first_weight, i));
}
++first;
++first_weight;
}
}
std::vector<WorldPosition*> getNextPoint(WorldPosition* center, std::vector<WorldPosition*> points, uint32 amount = 1);
std::vector<WorldPosition> getNextPoint(WorldPosition center, std::vector<WorldPosition> points, uint32 amount = 1);
QuestStatusData* getQuestStatus(Player* bot, uint32 questId);
bool getObjectiveStatus(Player* bot, Quest const* pQuest, uint32 objective);
uint32 getDialogStatus(Player* pPlayer, int32 questgiver, Quest const* pQuest);
std::vector<TravelDestination*> getQuestTravelDestinations(Player* bot, int32 questId = -1, bool ignoreFull = false, bool ignoreInactive = false, float maxDistance = 5000, bool ignoreObjectives = false);
std::vector<TravelDestination*> getRpgTravelDestinations(Player* bot, bool ignoreFull = false, bool ignoreInactive = false, float maxDistance = 5000);
std::vector<TravelDestination*> getExploreTravelDestinations(Player* bot, bool ignoreFull = false, bool ignoreInactive = false);
std::vector<TravelDestination*> getGrindTravelDestinations(Player* bot, bool ignoreFull = false, bool ignoreInactive = false, float maxDistance = 5000);
std::vector<TravelDestination*> getBossTravelDestinations(Player* bot, bool ignoreFull = false, bool ignoreInactive = false, float maxDistance = 25000);
void setNullTravelTarget(Player* player);
void addMapTransfer(WorldPosition start, WorldPosition end, float portalDistance = 0.1f, bool makeShortcuts = true);
void loadMapTransfers();
float mapTransDistance(WorldPosition start, WorldPosition end);
float fastMapTransDistance(WorldPosition start, WorldPosition end);
NullTravelDestination* nullTravelDestination = new NullTravelDestination();
WorldPosition* nullWorldPosition = new WorldPosition();
void addBadVmap(uint32 mapId, uint8 x, uint8 y)
{
badVmap.push_back(std::make_tuple(mapId, x, y));
}
void addBadMmap(uint32 mapId, uint8 x, uint8 y)
{
badMmap.push_back(std::make_tuple(mapId, x, y));
}
bool isBadVmap(uint32 mapId, uint8 x, uint8 y)
{
return std::find(badVmap.begin(), badVmap.end(), std::make_tuple(mapId, x, y)) != badVmap.end();
}
bool isBadMmap(uint32 mapId, uint8 x, uint8 y)
{
return std::find(badMmap.begin(), badMmap.end(), std::make_tuple(mapId, x, y)) != badMmap.end();
}
void printGrid(uint32 mapId, int x, int y, std::string const type);
void printObj(WorldObject* obj, std::string const type);
//protected:
void logQuestError(uint32 errorNr, Quest* quest, uint32 objective = 0, uint32 unitId = 0, uint32 itemId = 0);
std::vector<uint32> avoidLoaded;
std::vector<QuestTravelDestination*> questGivers;
std::vector<RpgTravelDestination*> rpgNpcs;
std::vector<GrindTravelDestination*> grindMobs;
std::vector<BossTravelDestination*> bossMobs;
std::unordered_map<uint32, ExploreTravelDestination*> exploreLocs;
std::unordered_map<uint32, QuestContainer*> quests;
std::vector<std::tuple<uint32, uint8, uint8>> badVmap, badMmap;
std::unordered_map<std::pair<uint32, uint32>, std::vector<mapTransfer>, boost::hash<std::pair<uint32, uint32>>> mapTransfersMap;
};
#define sTravelMgr TravelMgr::instance()
#endif