From bb5241d838f982c0d3aea0bfca972d6b8095e364 Mon Sep 17 00:00:00 2001 From: mostlikely4r Date: Mon, 19 Dec 2022 11:48:22 +0100 Subject: [PATCH] -Internal: Gave WorldPosition and GuidPosition seperate files and removed unneeded includes. --- playerbot/FleeManager.h | 4 +- playerbot/GuidPosition.cpp | 162 +++ playerbot/GuidPosition.h | 76 ++ playerbot/PlayerbotAI.cpp | 1 + playerbot/PlayerbotFactory.cpp | 2 +- playerbot/TravelMgr.cpp | 970 +----------------- playerbot/TravelMgr.h | 368 +------ playerbot/TravelNode.cpp | 1 + playerbot/TravelNode.h | 2 +- playerbot/WorldPosition.cpp | 808 +++++++++++++++ playerbot/WorldPosition.h | 288 ++++++ .../strategy/actions/ChooseTargetActions.cpp | 1 + .../strategy/actions/ChooseTargetActions.h | 1 - .../actions/ChooseTravelTargetAction.cpp | 1 + .../actions/ChooseTravelTargetAction.h | 4 +- playerbot/strategy/actions/DebugAction.cpp | 1 + playerbot/strategy/actions/DebugAction.h | 1 - playerbot/strategy/actions/GoAction.cpp | 1 + playerbot/strategy/actions/GoAction.h | 2 + .../strategy/actions/GuildCreateActions.cpp | 44 + .../strategy/actions/GuildCreateActions.h | 46 +- .../actions/MoveToTravelTargetAction.cpp | 1 + .../actions/MoveToTravelTargetAction.h | 1 - .../actions/ReviveFromCorpseAction.cpp | 1 + playerbot/strategy/actions/RpgAction.cpp | 1 + playerbot/strategy/actions/RpgSubActions.cpp | 1 + playerbot/strategy/actions/TravelAction.cpp | 1 + playerbot/strategy/actions/TravelAction.h | 1 - playerbot/strategy/triggers/RpgTriggers.cpp | 6 + playerbot/strategy/triggers/RpgTriggers.h | 3 +- playerbot/strategy/triggers/StuckTriggers.h | 1 - playerbot/strategy/values/LastMovementValue.h | 1 - playerbot/strategy/values/PositionValue.h | 1 - playerbot/strategy/values/QuestValues.h | 1 - playerbot/strategy/values/RTSCValues.h | 1 - 35 files changed, 1413 insertions(+), 1392 deletions(-) create mode 100644 playerbot/GuidPosition.cpp create mode 100644 playerbot/GuidPosition.h create mode 100644 playerbot/WorldPosition.cpp create mode 100644 playerbot/WorldPosition.h diff --git a/playerbot/FleeManager.h b/playerbot/FleeManager.h index b6747efb1..e4f89a92a 100644 --- a/playerbot/FleeManager.h +++ b/playerbot/FleeManager.h @@ -1,6 +1,6 @@ #pragma once -#include "TravelMgr.h" +#include "WorldPosition.h" using namespace std; @@ -10,6 +10,8 @@ namespace ai { class Engine; + + class FleePoint { public: FleePoint(PlayerbotAI* ai, float x, float y, float z) : ai(ai), sumDistance(0.0f), minDistance(0.0f) { diff --git a/playerbot/GuidPosition.cpp b/playerbot/GuidPosition.cpp new file mode 100644 index 000000000..b3898002c --- /dev/null +++ b/playerbot/GuidPosition.cpp @@ -0,0 +1,162 @@ +#pragma once + +#include "GuidPosition.h" +#include +#include + +#include "GameEvents/GameEventMgr.h" + +using namespace ai; +using namespace MaNGOS; + +Creature* GuidPosition::GetCreature() const +{ + if (!*this) + return nullptr; + + return getMap()->GetAnyTypeCreature(*this); +} + +Unit* GuidPosition::GetUnit() const +{ + if (!*this) + return nullptr; + + if (IsPlayer()) + return sObjectAccessor.FindPlayer(*this); + + return GetCreature(); +} + +GameObject* GuidPosition::GetGameObject() +{ + if (!*this) + return nullptr; + + return getMap()->GetGameObject(*this); +} + +Player* GuidPosition::GetPlayer() const +{ + if (!*this) + return nullptr; + + if (IsPlayer()) + return sObjectAccessor.FindPlayer(*this); + + return nullptr; +} + +const FactionTemplateEntry* GuidPosition::GetFactionTemplateEntry() const +{ + if (IsPlayer() && GetPlayer()) + return GetPlayer()->GetFactionTemplateEntry(); + if (IsCreature() && IsCreature()) + return sFactionTemplateStore.LookupEntry(GetCreatureTemplate()->Faction); + + return nullptr; +} + +const ReputationRank GuidPosition::GetReactionTo(const GuidPosition& other) +{ + if(other.IsUnit() && other.GetUnit()) + if (other.GetUnit()->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PLAYER_CONTROLLED)) + { + if (const Player* unitPlayer = other.GetUnit()->GetControllingPlayer()) + { + if (unitPlayer->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_CONTESTED_PVP) && GetFactionTemplateEntry()->IsContestedGuardFaction()) + return REP_HOSTILE; + + if (const ReputationRank* rank = unitPlayer->GetReputationMgr().GetForcedRankIfAny(GetFactionTemplateEntry())) + return (*rank); + +#ifdef MANGOSBOT_ZERO + const FactionEntry* unitFactionEntry = sFactionStore.LookupEntry(GetFactionTemplateEntry()->faction); + return unitPlayer->GetReputationMgr().IsAtWar(unitFactionEntry) ? REP_HOSTILE : REP_FRIENDLY; +#else + if (!other.GetUnit()->HasFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_IGNORE_REPUTATION)) + { +#ifdef MANGOSBOT_TWO + const FactionEntry* thisFactionEntry = sFactionStore.LookupEntry(GetFactionTemplateEntry()->faction); +#else + const FactionEntry* thisFactionEntry = sFactionStore.LookupEntry(GetFactionTemplateEntry()->faction); +#endif + if (thisFactionEntry && thisFactionEntry->HasReputation()) + { + const ReputationMgr& reputationMgr = unitPlayer->GetReputationMgr(); + return reputationMgr.GetRank(thisFactionEntry); + } + } +#endif + } + } + + return PlayerbotAI::GetFactionReaction(GetFactionTemplateEntry(), other.GetFactionTemplateEntry()); +} + +bool GuidPosition::isDead() +{ + if (!getMap()) + return false; + + if (!getMap()->IsLoaded(getX(), getY())) + return false; + + if (IsUnit() && GetUnit() && GetUnit()->IsInWorld() && GetUnit()->IsAlive()) + return false; + + if (IsGameObject() && GetGameObject() && GetGameObject()->IsInWorld()) + return false; + + return true; +} + +uint16 GuidPosition::IsPartOfAPool() +{ + if (IsCreature()) + return sPoolMgr.IsPartOfAPool(GetCounter()); + if (IsGameObject()) + return sPoolMgr.IsPartOfAPool(GetCounter()); + + return 0; +} + +uint16 GuidPosition::GetGameEventId() +{ + if (uint16 pool_id = IsPartOfAPool()) + { + uint16 top_pool_id = sPoolMgr.IsPartOfTopPool(pool_id); + + if (int16 event_id = sGameEventMgr.GetGameEventId(top_pool_id)) + return event_id; + } + + if (IsCreature()) + return sGameEventMgr.GetGameEventId(GetCounter()); + if (IsGameObject()) + return sGameEventMgr.GetGameEventId(GetCounter()); + + return 0; +} + +bool GuidPosition::IsEventUnspawned() +{ + if (int16 event_id = GetGameEventId()) + if (!sGameEventMgr.IsActiveEvent(event_id)) + return true; + + return false; +} + +string GuidPosition::print() +{ + ostringstream out; + out << this; + out << mapid << std::fixed << std::setprecision(2); + out << ';' << coord_x; + out << ';' << coord_y; + out << ';' << coord_z; + out << ';' << orientation; + + return out.str(); +} \ No newline at end of file diff --git a/playerbot/GuidPosition.h b/playerbot/GuidPosition.h new file mode 100644 index 000000000..4e27298b7 --- /dev/null +++ b/playerbot/GuidPosition.h @@ -0,0 +1,76 @@ +#pragma once + +#include "WorldPosition.h" + +namespace ai +{ + class GuidPosition : public ObjectGuid, public WorldPosition + { + public: + GuidPosition() : ObjectGuid(), WorldPosition() {} + GuidPosition(ObjectGuid guid) { ObjectGuid::Set(guid); WorldPosition::set(guid); }; + GuidPosition(ObjectGuid guid, WorldPosition pos) : ObjectGuid(guid), WorldPosition(pos) {}; + GuidPosition(uint64 const& guid, WorldPosition const& pos) : ObjectGuid(guid), WorldPosition(pos) {}; + //template + //GuidPosition(ObjectGuid guid, T) : ObjectGuid(guid) {WorldPosition::set(WorldPosition(T))}; + GuidPosition(CreatureDataPair const* dataPair) : ObjectGuid(HIGHGUID_UNIT, dataPair->second.id, dataPair->first), WorldPosition(dataPair) {}; + GuidPosition(GameObjectDataPair const* dataPair) : ObjectGuid(HIGHGUID_GAMEOBJECT, dataPair->second.id, dataPair->first), WorldPosition(dataPair) {}; + GuidPosition(WorldObject* wo) : WorldPosition(wo) { ObjectGuid::Set(wo->GetObjectGuid()); }; + GuidPosition(HighGuid hi, uint32 entry, uint32 counter = 1, WorldPosition pos = WorldPosition()) : ObjectGuid(hi, entry, counter), WorldPosition(pos) {}; + //GuidPosition(const GuidPosition& guidp) {this->Set(guidp); this->setLocation(((WorldPosition)guidp).getLocation()); }; + + CreatureData* GetCreatureData() { return IsCreature() ? sObjectMgr.GetCreatureData(GetCounter()) : nullptr; } + CreatureInfo const* GetCreatureTemplate()const {return IsCreature() ? sObjectMgr.GetCreatureTemplate(GetEntry()) : nullptr; }; + + GameObjectInfo const* GetGameObjectInfo() { return IsGameObject() ? sObjectMgr.GetGameObjectInfo(GetEntry()) : nullptr; }; + + WorldObject* GetWorldObject() { return getMap() ? getMap()->GetWorldObject(*this) : nullptr;} + Creature* GetCreature() const; + Unit* GetUnit() const; + GameObject* GetGameObject(); + Player* GetPlayer() const; + + bool HasNpcFlag(NPCFlags flag) { return IsCreature() && GetCreatureTemplate()->NpcFlags & flag; } + bool isGoType(GameobjectTypes type) { return IsGameObject() && GetGameObjectInfo()->type == type; } + + const FactionTemplateEntry* GetFactionTemplateEntry() const; + const ReputationRank GetReactionTo(const GuidPosition& other); + bool IsFriendlyTo(const GuidPosition& other) { return (GetFactionTemplateEntry() && other.GetFactionTemplateEntry()) ? (GetReactionTo(other) > REP_NEUTRAL) : false; } + bool IsHostileTo(const GuidPosition& other) { return (GetFactionTemplateEntry() && other.GetFactionTemplateEntry()) ? (GetReactionTo(other) < REP_NEUTRAL) : false; } + + bool isDead(); //For loaded grids check if the unit/object is unloaded/dead. + + uint16 IsPartOfAPool(); + uint16 GetGameEventId(); + bool IsEventUnspawned(); + + virtual string print(); + + operator bool() const { return WorldPosition(*this) && !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(); } + }; + + inline ByteBuffer& operator<<(ByteBuffer& b, GuidPosition& guidP) + { + b << (ObjectGuid)guidP; + b << (WorldPosition)guidP; + + + return b; + } + + inline ByteBuffer& operator>>(ByteBuffer& b, GuidPosition& g) + { + ObjectGuid guid; + WorldPosition pos; + + b >> guid; + b >> pos; + + g = GuidPosition(guid, pos); + + return b; + } +} \ No newline at end of file diff --git a/playerbot/PlayerbotAI.cpp b/playerbot/PlayerbotAI.cpp index 1561d53ee..7bfe9e26e 100644 --- a/playerbot/PlayerbotAI.cpp +++ b/playerbot/PlayerbotAI.cpp @@ -29,6 +29,7 @@ #include "strategy/values/PositionValue.h" #include "ServerFacade.h" #include "TravelMgr.h" +#include "MoveSplineInitArgs.h" #include "ChatHelper.h" #include "strategy/values/BudgetValues.h" #include "Social/SocialMgr.h" diff --git a/playerbot/PlayerbotFactory.cpp b/playerbot/PlayerbotFactory.cpp index 0475dea8f..7cd36b626 100644 --- a/playerbot/PlayerbotFactory.cpp +++ b/playerbot/PlayerbotFactory.cpp @@ -14,7 +14,7 @@ #include "RandomPlayerbotFactory.h" #include "ServerFacade.h" #include "AiFactory.h" -#include "TravelMgr.h" + #ifndef MANGOSBOT_ZERO #ifdef CMANGOS #include "Arena/ArenaTeam.h" diff --git a/playerbot/TravelMgr.cpp b/playerbot/TravelMgr.cpp index 2ee651e7a..4dd65b6de 100644 --- a/playerbot/TravelMgr.cpp +++ b/playerbot/TravelMgr.cpp @@ -1,983 +1,17 @@ #pragma once -#include "TransportMgr.h" #include "TravelMgr.h" -#include "TravelNode.h" -#include "PlayerbotAI.h" - -#include "ByteBuffer.h" -#include "Creature.h" -#include "GameObject.h" -#include "Map.h" -#include "Object.h" -#include "ObjectMgr.h" -#include "ObjectGuid.h" -#include "Player.h" -#include "Unit.h" -#include "QuestDef.h" #include #include -#include "PathFinder.h" -#include "PlayerbotAI.h" -#include "vmap/VMapFactory.h" -#include "MoveMap.h" -#include "Transports.h" -#include "strategy/StrategyContext.h" - #include "strategy/values/SharedValueContext.h" - -#include "Grids/CellImpl.h" - -#include "GameEvents/GameEventMgr.h" - +#include "PathFinder.h" +#include "TravelNode.h" using namespace ai; using namespace MaNGOS; -WorldPosition::WorldPosition(const GuidPosition& guidP) -{ - if (guidP.mapid !=0 || guidP.coord_x != 0 || guidP.coord_y != 0 || guidP.coord_z !=0) { - set(WorldPosition(guidP.mapid, guidP.coord_x, guidP.coord_y, guidP.coord_z, guidP.orientation)); - return; - } - - set(ObjectGuid(guidP)); - } - -void WorldPosition::set(const ObjectGuid& guid) -{ - switch (guid.GetHigh()) - { - case HIGHGUID_PLAYER: - { - Player* player = sObjectAccessor.FindPlayer(guid); - if (player) - set(WorldLocation(player->GetMapId(), player->GetPositionX(), player->GetPositionY(), player->GetPositionZ(), player->GetOrientation())); - break; - } - case HIGHGUID_GAMEOBJECT: - { - GameObjectDataPair const* gpair = sObjectMgr.GetGODataPair(guid.GetCounter()); - if (gpair) - set(WorldLocation(gpair->second.mapid, gpair->second.posX, gpair->second.posY, gpair->second.posZ, gpair->second.orientation)); - break; - } - case HIGHGUID_UNIT: - { - CreatureDataPair const* cpair = sObjectMgr.GetCreatureDataPair(guid.GetCounter()); - if (cpair) - set(WorldLocation(cpair->second.mapid, cpair->second.posX, cpair->second.posY, cpair->second.posZ, cpair->second.orientation)); - break; - } - case HIGHGUID_TRANSPORT: - case HIGHGUID_MO_TRANSPORT: - case HIGHGUID_ITEM: - case HIGHGUID_PET: - case HIGHGUID_DYNAMICOBJECT: - case HIGHGUID_CORPSE: - return; - } - -} - -WorldPosition::WorldPosition(const vector& list, const WorldPositionConst conType) -{ - uint32 size = list.size(); - if (size == 0) - return; - else if (size == 1) - set(*list.front()); - else if (conType == WP_RANDOM) - set(*list[urand(0, size - 1)]); - else if (conType == WP_CENTROID) - set(std::accumulate(list.begin(), list.end(), WorldLocation(list[0]->getMapId(), 0, 0, 0, 0), [size](WorldLocation i, WorldPosition* j) {i.coord_x += j->getX() / size; i.coord_y += j->getY() / size; i.coord_z += j->getZ() / size; i.orientation += j->getO() / size; return i; })); - else if (conType == WP_MEAN_CENTROID) - { - WorldPosition pos = WorldPosition(list, WP_CENTROID); - set(*pos.closestSq(list)); - } -} - -WorldPosition::WorldPosition(const vector& list, const WorldPositionConst conType) -{ - uint32 size = list.size(); - if (size == 0) - return; - else if (size == 1) - set(list.front()); - else if (conType == WP_RANDOM) - set(list[urand(0, size - 1)]); - else if (conType == WP_CENTROID) - set(std::accumulate(list.begin(), list.end(), WorldLocation(list[0].getMapId(), 0, 0, 0, 0), [size](WorldLocation i, WorldPosition j) {i.coord_x += j.getX() / size; i.coord_y += j.getY() / size; i.coord_z += j.getZ() / size; i.orientation += j.getO() / size; return i; })); - else if (conType == WP_MEAN_CENTROID) - { - WorldPosition pos = WorldPosition(list, WP_CENTROID); - set(pos.closestSq(list)); - } -} - -float WorldPosition::distance(const WorldPosition& to) const -{ - if(mapid == to.getMapId()) - return relPoint(to).size(); - - //this -> mapTransfer | mapTransfer -> center - return sTravelMgr.mapTransDistance(*this, to); -}; - -float WorldPosition::fDist(const WorldPosition& to) const -{ - if (mapid == to.getMapId()) - return sqrt(sqDistance2d(to)); - - //this -> mapTransfer | mapTransfer -> center - return sTravelMgr.fastMapTransDistance(*this, to); -}; - -//When moving from this along list return last point that falls within range. -//Distance is move distance along path. -WorldPosition WorldPosition::lastInRange(const vector& list, const float minDist, const float maxDist) const -{ - WorldPosition rPoint; - - float startDist = 0.0f; - - //Enter the path at the closest point. - for (auto& p : list) - { - float curDist = distance(p); - if (startDist < curDist || p == list.front()) - startDist = curDist + 0.1f; - } - - float totalDist = 0.0f; - - //Follow the path from the last nearest point - //Return last point in range. - for (auto& p : list) - { - float curDist = distance(p); - - if (totalDist > 0) //We have started the path. Keep counting. - totalDist += p.distance(*std::prev(&p, 1)); - - if (curDist == startDist) //Start the path here. - totalDist = startDist; - - if (minDist > 0 && totalDist < minDist) - continue; - - if (maxDist > 0 && totalDist > maxDist) - continue; //We do not break here because the path may loop back and have a second startDist point. - - rPoint = p; - } - - return rPoint; -}; - -//Todo: remove or adjust to above standard. -WorldPosition WorldPosition::firstOutRange(const vector& list, const float minDist, const float maxDist) const -{ - WorldPosition rPoint; - - for (auto& p : list) - { - if (minDist > 0 && distance(p) < minDist) - return p; - - if (maxDist > 0 && distance(p) > maxDist) - return p; - - rPoint = p; - } - - return rPoint; -} - -//Returns true if (on the x-y plane) the position is inside the three points. -bool WorldPosition::isInside(const WorldPosition* p1, const WorldPosition* p2, const WorldPosition* p3) const -{ - if (getMapId() != p1->getMapId() != p2->getMapId() != p3->getMapId()) - return false; - - float d1, d2, d3; - bool has_neg, has_pos; - - d1 = mSign(p1, p2); - d2 = mSign(p2, p3); - d3 = mSign(p3, p1); - - has_neg = (d1 < 0) || (d2 < 0) || (d3 < 0); - has_pos = (d1 > 0) || (d2 > 0) || (d3 > 0); - - return !(has_neg && has_pos); -} - -void WorldPosition::distancePartition(const vector& distanceLimits, WorldPosition* to, vector>& partitions) const -{ - float dist = distance(*to); - - for (uint8 l = 0; l < distanceLimits.size(); l++) - if (dist <= distanceLimits[l]) - partitions[l].push_back(to); -} - -vector> WorldPosition::distancePartition(const vector& distanceLimits, vector points) const -{ - vector> partitions; - - for (auto lim : distanceLimits) - partitions.push_back({}); - - for (auto& point : points) - { - distancePartition(distanceLimits, point, partitions); - } - - return partitions; -} - -bool WorldPosition::canFly() const -{ -#ifdef MANGOSBOT_ZERO - return false; -#endif - if (!getTerrain()) - return false; - - uint32 zoneid, areaid; - getTerrain()->GetZoneAndAreaId(zoneid, areaid, getX(), getY(), getZ()); - -#ifdef MANGOSBOT_ONE - uint32 v_map = GetVirtualMapForMapAndZone(getMapId(), zoneid); - MapEntry const* mapEntry = sMapStore.LookupEntry(v_map); - if (!mapEntry || mapEntry->addon < 1 || !mapEntry->IsContinent()) - return false; -#endif -#ifdef MANGOSBOT_TWO - // Disallow mounting in wintergrasp when battle is in progress - if (OutdoorPvP* outdoorPvP = sOutdoorPvPMgr.GetScript(zoneid)) - { - if (outdoorPvP->IsBattlefield()) - return ((Battlefield*)outdoorPvP)->GetBattlefieldStatus() != BF_STATUS_IN_PROGRESS; - } - - // don't allow flying in Dalaran restricted areas - // (no other zones currently has areas with AREA_FLAG_CANNOT_FLY) - if (AreaTableEntry const* atEntry = GetAreaEntryByAreaID(areaid)) - return (!(atEntry->flags & AREA_FLAG_CANNOT_FLY)); -#endif - - return true; -} - -G3D::Vector3 WorldPosition::getVector3() const -{ - return G3D::Vector3(coord_x, coord_y, coord_z); -} - -string WorldPosition::print() const -{ - ostringstream out; - out << mapid << std::fixed << std::setprecision(2); - out << ';'<< coord_x; - out << ';' << coord_y; - out << ';' << coord_z; - out << ';' << orientation; - - return out.str(); -} - -void WorldPosition::printWKT(const vector& points, ostringstream& out, const uint32 dim, const bool loop) const -{ - switch (dim) { - case 0: - if(points.size() == 1) - out << "\"POINT("; - else - out << "\"MULTIPOINT("; - break; - case 1: - out << "\"LINESTRING("; - break; - case 2: - out << "\"POLYGON(("; - } - - for (auto& p : points) - out << p.getDisplayX() << " " << p.getDisplayY() << (!loop && &p == &points.back() ? "" : ","); - - if (loop) - out << points.front().getDisplayX() << " " << points.front().getDisplayY(); - - out << (dim == 2 ? "))\"," : ")\","); -} - -WorldPosition WorldPosition::getDisplayLocation() const -{ - WorldPosition mapOffset = sTravelNodeMap.getMapOffset(getMapId()); - return offset(mapOffset); -}; - -AreaTableEntry const* WorldPosition::getArea() const -{ - uint16 areaFlag = getAreaFlag(); - - //if(!areaFlag) - // return NULL; - - return GetAreaEntryByAreaFlagAndMap(areaFlag, getMapId()); -} - -string WorldPosition::getAreaName(const bool fullName, const bool zoneName) const -{ - if (!isOverworld()) - { - MapEntry const* map = sMapStore.LookupEntry(getMapId()); - if (map) - return map->name[0]; - } - - AreaTableEntry const* area = getArea(); - - if (!area) - return ""; - - string areaName = area->area_name[0]; - - if (fullName) - { - uint16 zoneId = area->zone; - - while (zoneId > 0) - { - AreaTableEntry const* parentArea = GetAreaEntryByAreaID(zoneId); - - if (!parentArea) - break; - - string subAreaName = parentArea->area_name[0]; - - if (zoneName) - areaName = subAreaName; - else - areaName = subAreaName + " " + areaName; - - zoneId = parentArea->zone; - } - } - - return areaName; -} - -int32 WorldPosition::getAreaLevel() const -{ - if(getArea()) - return sTravelMgr.getAreaLevel(getArea()->ID); - - return 0; -} - -std::set WorldPosition::getTransports(uint32 entry) -{ - /* - if(!entry) - return getMap()->m_transports; - else - { - */ - std::set transports; - /* - for (auto transport : getMap()->m_transports) - if(transport->GetEntry() == entry) - transports.insert(transport); - - return transports; - } - */ - return transports; -} - -std::vector WorldPosition::getGridPairs(const WorldPosition& secondPos) const -{ - std::vector retVec; - - int lx = std::min(getGridPair().x_coord, secondPos.getGridPair().x_coord); - int ly = std::min(getGridPair().y_coord, secondPos.getGridPair().y_coord); - int ux = std::max(getGridPair().x_coord, secondPos.getGridPair().x_coord); - int uy = std::max(getGridPair().y_coord, secondPos.getGridPair().y_coord); - int border = 1; - - lx = std::min(std::max(border, lx), MAX_NUMBER_OF_GRIDS - border); - ly = std::min(std::max(border, ly), MAX_NUMBER_OF_GRIDS - border); - ux = std::min(std::max(border, ux), MAX_NUMBER_OF_GRIDS - border); - uy = std::min(std::max(border, uy), MAX_NUMBER_OF_GRIDS - border); - - for (int x = lx - border; x <= ux + border; x++) - { - for (int y = ly - border; y <= uy + border; y++) - { - retVec.push_back(GridPair(x, y)); - } - } - - return retVec; -} - -vector WorldPosition::fromGridPair(const GridPair& gridPair) const -{ - vector retVec; - GridPair g; - - for (uint32 d = 0; d < 4; d++) - { - g = gridPair; - - if (d == 1 || d == 2) - g >> 1; - if (d == 2 || d == 3) - g += 1; - - retVec.push_back(WorldPosition(getMapId(), g)); - } - - return retVec; -} - -vector WorldPosition::fromCellPair(const CellPair& cellPair) const -{ - vector retVec; - CellPair p; - - for (uint32 d = 0; d < 4; d++) - { - p = cellPair; - - if (d == 1 || d == 2) - p >> 1; - if (d == 2 || d == 3) - p += 1; - - retVec.push_back(WorldPosition(getMapId(), p)); - } - return retVec; -} - -vector WorldPosition::gridFromCellPair(const CellPair& cellPair) const -{ - Cell c(cellPair); - - return fromGridPair(GridPair(c.GridX(), c.GridY())); -} - -vector> WorldPosition::getmGridPairs(const WorldPosition& secondPos) const -{ - std::vector retVec; - - int lx = std::min(getmGridPair().first, secondPos.getmGridPair().first); - int ly = std::min(getmGridPair().second, secondPos.getmGridPair().second); - int ux = std::max(getmGridPair().first, secondPos.getmGridPair().first); - int uy = std::max(getmGridPair().second, secondPos.getmGridPair().second); - int border = 1; - - //lx = std::min(std::max(border, lx), MAX_NUMBER_OF_GRIDS - border); - //ly = std::min(std::max(border, ly), MAX_NUMBER_OF_GRIDS - border); - //ux = std::min(std::max(border, ux), MAX_NUMBER_OF_GRIDS - border); - //uy = std::min(std::max(border, uy), MAX_NUMBER_OF_GRIDS - border); - - for (int x = lx - border; x <= ux + border; x++) - { - for (int y = ly - border; y <= uy + border; y++) - { - retVec.push_back(make_pair(x, y)); - } - } - - return retVec; -} - -vector WorldPosition::frommGridPair(const mGridPair& gridPair) const -{ - vector retVec; - mGridPair g; - - for (uint32 d = 0; d < 4; d++) - { - g = gridPair; - - if (d == 1 || d == 2) - g.second++; - if (d == 2 || d == 3) - g.first++; - - retVec.push_back(WorldPosition(getMapId(), g)); - } - - return retVec; -} - -void WorldPosition::loadMapAndVMap(uint32 mapId, uint32 instanceId, int x, int y) const -{ - string fileName = "load_map_grid.csv"; - - if (isOverworld() && false || false) - { -#ifdef MANGOSBOT_TWO - if (!MMAP::MMapFactory::createOrGetMMapManager()->IsMMapTileLoaded(mapId, instanceId, x, y)) -#else - if (!MMAP::MMapFactory::createOrGetMMapManager()->IsMMapIsLoaded(mapId, x, y)) -#endif - if (sPlayerbotAIConfig.hasLog(fileName)) - { - ostringstream out; - out << sPlayerbotAIConfig.GetTimestampStr(); - out << "+00,\"mmap\", " << x << "," << y << "," << (sTravelMgr.isBadMmap(mapId, x, y) ? "0" : "1") << ","; - printWKT(fromGridPair(GridPair(x, y)), out, 1, true); - sPlayerbotAIConfig.log(fileName, out.str().c_str()); - } - - int px = (float)(32 - x) * SIZE_OF_GRIDS; - int py = (float)(32 - y) * SIZE_OF_GRIDS; - -#ifdef MANGOSBOT_TWO - if (!MMAP::MMapFactory::createOrGetMMapManager()->IsMMapTileLoaded(mapId, instanceId, x, y)) -#else - if (!MMAP::MMapFactory::createOrGetMMapManager()->IsMMapIsLoaded(mapId, x, y)) -#endif - if(getTerrain()) - getTerrain()->GetTerrainType(px, py); - - } - else - { - - //This needs to be disabled or maps will not load. - //Needs more testing to check for impact on movement. - if (false) - if (!VMAP::VMapFactory::createOrGetVMapManager()->IsTileLoaded(mapId, x, y) && !sTravelMgr.isBadVmap(mapId, x, y)) - { - // load VMAPs for current map/grid... - const MapEntry* i_mapEntry = sMapStore.LookupEntry(mapId); - const char* mapName = i_mapEntry ? i_mapEntry->name[sWorld.GetDefaultDbcLocale()] : "UNNAMEDMAP\x0"; - - int vmapLoadResult = VMAP::VMapFactory::createOrGetVMapManager()->loadMap((sWorld.GetDataPath() + "vmaps").c_str(), mapId, x, y); - switch (vmapLoadResult) - { - case VMAP::VMAP_LOAD_RESULT_OK: - //sLog.outError("VMAP loaded name:%s, id:%d, x:%d, y:%d (vmap rep.: x:%d, y:%d)", mapName, mapId, x, y, x, y); - break; - case VMAP::VMAP_LOAD_RESULT_ERROR: - //sLog.outError("Could not load VMAP name:%s, id:%d, x:%d, y:%d (vmap rep.: x:%d, y:%d)", mapName, mapId, x, y, x, y); - sTravelMgr.addBadVmap(mapId, x, y); - break; - case VMAP::VMAP_LOAD_RESULT_IGNORED: - sTravelMgr.addBadVmap(mapId, x, y); - //sLog.outError("Ignored VMAP name:%s, id:%d, x:%d, y:%d (vmap rep.: x:%d, y:%d)", mapName, mapId, x, y, x, y); - break; - } - - if (sPlayerbotAIConfig.hasLog(fileName)) - { - ostringstream out; - out << sPlayerbotAIConfig.GetTimestampStr(); - out << "+00,\"vmap\", " << x << "," << y << ", " << (sTravelMgr.isBadVmap(mapId, x, y) ? "0" : "1") << ","; - printWKT(fromGridPair(GridPair(x, y)), out, 1, true); - sPlayerbotAIConfig.log(fileName, out.str().c_str()); - } - } - -#ifdef MANGOSBOT_TWO - if (!MMAP::MMapFactory::createOrGetMMapManager()->IsMMapTileLoaded(mapId, instanceId, x, y) && !sTravelMgr.isBadMmap(mapId, x, y)) -#else - if (!MMAP::MMapFactory::createOrGetMMapManager()->IsMMapIsLoaded(mapId, x, y) && !sTravelMgr.isBadMmap(mapId, x, y)) -#endif - { - // load navmesh -#ifdef MANGOSBOT_TWO - if (!MMAP::MMapFactory::createOrGetMMapManager()->loadMap(mapId, instanceId, x, y, 0)) -#else - if (!MMAP::MMapFactory::createOrGetMMapManager()->loadMap(mapId, x, y)) -#endif - sTravelMgr.addBadMmap(mapId, x, y); - - if (sPlayerbotAIConfig.hasLog(fileName)) - { - ostringstream out; - out << sPlayerbotAIConfig.GetTimestampStr(); - out << "+00,\"mmap\", " << x << "," << y << "," << (sTravelMgr.isBadMmap(mapId, x, y) ? "0" : "1") << ","; - printWKT(frommGridPair(mGridPair(x, y)), out, 1, true); - sPlayerbotAIConfig.log(fileName, out.str().c_str()); - } - } - } -} - -void WorldPosition::loadMapAndVMaps(const WorldPosition& secondPos, uint32 instanceId) const -{ - for (auto& grid : getmGridPairs(secondPos)) - { - loadMapAndVMap(getMapId(), instanceId, grid.first, grid.second); - } -} - -vector WorldPosition::fromPointsArray(const std::vector& path) const -{ - vector retVec; - for (auto p : path) - retVec.push_back(WorldPosition(getMapId(), p.x, p.y, p.z, getO())); - - return retVec; -} - -//A single pathfinding attempt from one position to another. Returns pathfinding status and path. -vector WorldPosition::getPathStepFrom(const WorldPosition& startPos, const Unit* bot) const -{ - std::hash hasher; - uint32 instanceId; - if (sTravelNodeMap.gethasToGen()) - instanceId = 0; - else if (!bot || sPlayerbotAIConfig.tweakValue || bot->GetMapId() != startPos.getMapId()) - instanceId = hasher(std::this_thread::get_id()); - else - instanceId = bot->GetInstanceId(); - //Load mmaps and vmaps between the two points. - - loadMapAndVMaps(startPos, instanceId); - - PointsArray points; - PathType type; - - if (bot && false) - { - PathFinder path(bot); - -#ifdef IKE_PATHFINDER - path.setAreaCost(NAV_AREA_WATER, 10.0f); //Water - path.setAreaCost(12, 5.0f); //Mob proximity - path.setAreaCost(13, 20.0f); //Mob agro -#endif - path.calculate(startPos.getVector3(), getVector3(), false); - - points = path.getPath(); - type = path.getPathType(); - - } - else -#ifdef IKE_PATHFINDER - { - PathFinder path(getMapId(), instanceId); - - path.setAreaCost(NAV_AREA_WATER, 10.0f); - path.setAreaCost(12, 5.0f); - path.setAreaCost(13, 20.0f); - - path.calculate(startPos.getVector3(), getVector3(), false); - - points = path.getPath(); - type = path.getPathType(); - } -#else - return PATHFIND_NOPATH; -#endif - - if (sPlayerbotAIConfig.hasLog("pathfind_attempt_point.csv")) - { - ostringstream out; - out << std::fixed << std::setprecision(1); - printWKT({ startPos, *this }, out); - sPlayerbotAIConfig.log("pathfind_attempt_point.csv", out.str().c_str()); - } - - if (sPlayerbotAIConfig.hasLog("pathfind_attempt.csv") && (type == PATHFIND_INCOMPLETE || type == PATHFIND_NORMAL)) - { - ostringstream out; - out << sPlayerbotAIConfig.GetTimestampStr() << "+00,"; - out << std::fixed << std::setprecision(1) << type << ","; - printWKT(fromPointsArray(points), out, 1); - sPlayerbotAIConfig.log("pathfind_attempt.csv", out.str().c_str()); - } - - if (type == PATHFIND_INCOMPLETE || type == PATHFIND_NORMAL) - return fromPointsArray(points); - else - return {}; - -} - -bool WorldPosition::cropPathTo(vector& path, const float maxDistance) const -{ - if (path.empty()) - return false; - - auto bestPos = std::min_element(path.begin(), path.end(), [this](WorldPosition i, WorldPosition j) {return this->sqDistance(i) < this->sqDistance(j); }); - - bool insRange = this->sqDistance(*bestPos) <= maxDistance * maxDistance; - - if (bestPos == path.end()) - return insRange; - - path.erase(std::next(bestPos), path.end()); - - return insRange; -} - -//A sequential series of pathfinding attempts. Returns the complete path and if the patfinder eventually found a way to the destination. -vector WorldPosition::getPathFromPath(const vector& startPath, const Unit* bot, uint8 maxAttempt) const -{ - //We start at the end of the last path. - WorldPosition currentPos = startPath.back(); - - //No pathfinding across maps. - if (getMapId() != currentPos.getMapId()) - return { }; - - vector subPath, fullPath = startPath; - - //Limit the pathfinding attempts - for (uint32 i = 0; i < maxAttempt; i++) - { - //Try to pathfind to this position. - subPath = getPathStepFrom(currentPos, bot); - - //If we could not find a path return what we have now. - if (subPath.empty() || currentPos.distance(subPath.back()) < sPlayerbotAIConfig.targetPosRecalcDistance) - break; - - //Append the path excluding the start (this should be the same as the end of the startPath) - fullPath.insert(fullPath.end(), std::next(subPath.begin(),1), subPath.end()); - - //Are we there yet? - if (isPathTo(subPath)) - break; - - //Continue pathfinding. - currentPos = subPath.back(); - } - - return fullPath; -} - -uint32 WorldPosition::getUnitsNear(const list& units, const float radius) const -{ - uint32 count = 0; - for (auto guid : units) - if (sqDistance(WorldPosition(guid)) <= radius * radius) - count++; - - return count; -}; - -uint32 WorldPosition::getUnitsAggro(const list& units, const Player* bot) const -{ - uint32 count = 0; - for (auto guid : units) - { - Unit* unit = GuidPosition(guid).GetUnit(); - - if (!unit) continue; - - if (this->sqDistance(WorldPosition(guid)) > unit->GetAttackDistance(bot) * unit->GetAttackDistance(bot)) - continue; - - count++; - } - - return count; -}; - - - -bool FindPointCreatureData::operator()(CreatureDataPair const& dataPair) -{ - if (!entry || dataPair.second.id == entry) - if ((!point || dataPair.second.mapid == point.getMapId()) && (!radius || point.sqDistance(WorldPosition(dataPair.second.mapid, dataPair.second.posX, dataPair.second.posY, dataPair.second.posZ)) < radius * radius)) - { - data.push_back(&dataPair); - } - - return false; -} - -bool FindPointGameObjectData::operator()(GameObjectDataPair const& dataPair) -{ - if (!entry || dataPair.second.id == entry) - if ((!point || dataPair.second.mapid == point.getMapId()) && (!radius || point.sqDistance(WorldPosition(dataPair.second.mapid, dataPair.second.posX, dataPair.second.posY, dataPair.second.posZ)) < radius * radius)) - { - data.push_back(&dataPair); - } - - return false; -} - -vector WorldPosition::getCreaturesNear(const float radius, const uint32 entry) const -{ - FindPointCreatureData worker(*this, radius, entry); - sObjectMgr.DoCreatureData(worker); - return worker.GetResult(); -} - -vector WorldPosition::getGameObjectsNear(const float radius, const uint32 entry) const -{ - FindPointGameObjectData worker(*this, radius, entry); - sObjectMgr.DoGOData(worker); - return worker.GetResult(); -} - -Creature* GuidPosition::GetCreature() const -{ - if (!*this) - return nullptr; - - return getMap()->GetAnyTypeCreature(*this); -} - -Unit* GuidPosition::GetUnit() const -{ - if (!*this) - return nullptr; - - if (IsPlayer()) - return sObjectAccessor.FindPlayer(*this); - - return GetCreature(); -} - -GameObject* GuidPosition::GetGameObject() -{ - if (!*this) - return nullptr; - - return getMap()->GetGameObject(*this); -} - -Player* GuidPosition::GetPlayer() const -{ - if (!*this) - return nullptr; - - if (IsPlayer()) - return sObjectAccessor.FindPlayer(*this); - - return nullptr; -} - -const FactionTemplateEntry* GuidPosition::GetFactionTemplateEntry() const -{ - if (IsPlayer() && GetPlayer()) - return GetPlayer()->GetFactionTemplateEntry(); - if (IsCreature() && IsCreature()) - return sFactionTemplateStore.LookupEntry(GetCreatureTemplate()->Faction); - - return nullptr; -} - -const ReputationRank GuidPosition::GetReactionTo(const GuidPosition& other) -{ - if(other.IsUnit() && other.GetUnit()) - if (other.GetUnit()->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PLAYER_CONTROLLED)) - { - if (const Player* unitPlayer = other.GetUnit()->GetControllingPlayer()) - { - if (unitPlayer->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_CONTESTED_PVP) && GetFactionTemplateEntry()->IsContestedGuardFaction()) - return REP_HOSTILE; - - if (const ReputationRank* rank = unitPlayer->GetReputationMgr().GetForcedRankIfAny(GetFactionTemplateEntry())) - return (*rank); - -#ifdef MANGOSBOT_ZERO - const FactionEntry* unitFactionEntry = sFactionStore.LookupEntry(GetFactionTemplateEntry()->faction); - return unitPlayer->GetReputationMgr().IsAtWar(unitFactionEntry) ? REP_HOSTILE : REP_FRIENDLY; -#else - if (!other.GetUnit()->HasFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_IGNORE_REPUTATION)) - { -#ifdef MANGOSBOT_TWO - const FactionEntry* thisFactionEntry = sFactionStore.LookupEntry(GetFactionTemplateEntry()->faction); -#else - const FactionEntry* thisFactionEntry = sFactionStore.LookupEntry(GetFactionTemplateEntry()->faction); -#endif - if (thisFactionEntry && thisFactionEntry->HasReputation()) - { - const ReputationMgr& reputationMgr = unitPlayer->GetReputationMgr(); - return reputationMgr.GetRank(thisFactionEntry); - } - } -#endif - } - } - - return PlayerbotAI::GetFactionReaction(GetFactionTemplateEntry(), other.GetFactionTemplateEntry()); -} - -bool GuidPosition::isDead() -{ - if (!getMap()) - return false; - - if (!getMap()->IsLoaded(getX(), getY())) - return false; - - if (IsUnit() && GetUnit() && GetUnit()->IsInWorld() && GetUnit()->IsAlive()) - return false; - - if (IsGameObject() && GetGameObject() && GetGameObject()->IsInWorld()) - return false; - - return true; -} - -uint16 GuidPosition::IsPartOfAPool() -{ - if (IsCreature()) - return sPoolMgr.IsPartOfAPool(GetCounter()); - if (IsGameObject()) - return sPoolMgr.IsPartOfAPool(GetCounter()); - - return 0; -} - -uint16 GuidPosition::GetGameEventId() -{ - if (uint16 pool_id = IsPartOfAPool()) - { - uint16 top_pool_id = sPoolMgr.IsPartOfTopPool(pool_id); - - if (int16 event_id = sGameEventMgr.GetGameEventId(top_pool_id)) - return event_id; - } - - if (IsCreature()) - return sGameEventMgr.GetGameEventId(GetCounter()); - if (IsGameObject()) - return sGameEventMgr.GetGameEventId(GetCounter()); - - return 0; -} - -bool GuidPosition::IsEventUnspawned() -{ - if (int16 event_id = GetGameEventId()) - if (!sGameEventMgr.IsActiveEvent(event_id)) - return true; - - return false; -} - -string GuidPosition::print() -{ - ostringstream out; - out << this; - out << mapid << std::fixed << std::setprecision(2); - out << ';' << coord_x; - out << ';' << coord_y; - out << ';' << coord_z; - out << ';' << orientation; - - return out.str(); -} - vector TravelDestination::getPoints(bool ignoreFull) { return points; diff --git a/playerbot/TravelMgr.h b/playerbot/TravelMgr.h index 7972ada6b..9cb7c59ba 100644 --- a/playerbot/TravelMgr.h +++ b/playerbot/TravelMgr.h @@ -1,376 +1,10 @@ #pragma once #include "strategy/AiObject.h" -#include "MoveSplineInitArgs.h" #include -#include "ObjectMgr.h" -#include "SpellMgr.h" -#include "PlayerbotAIConfig.h" -#include "GridDefines.h" -#include "SharedDefines.h" - -class ByteBuffer; - -namespace G3D -{ - class Vector2; - class Vector3; - class Vector4; -} namespace ai -{ - //Constructor types for WorldPosition - enum WorldPositionConst - { - WP_RANDOM = 0, - WP_CENTROID = 1, - WP_MEAN_CENTROID = 2, - WP_CLOSEST = 3 - }; - - class GuidPosition; - - typedef pair mGridPair; - - //Extension of WorldLocation with distance functions. - class WorldPosition : public WorldLocation - { - public: - //Constructors - WorldPosition() : WorldLocation() {}; - WorldPosition(const WorldLocation loc) : WorldLocation(loc) {} - WorldPosition(const WorldPosition& pos) : WorldLocation(pos) {} - WorldPosition(const string str) { stringstream out(str); out >> mapid; out >> coord_x; out >> coord_y; out >> coord_z; out >> orientation; } - WorldPosition(const uint32 mapid, const float x, const float y, const float z = 0, float orientation = 0) : WorldLocation(mapid, x, y, z, orientation) {} - WorldPosition(const uint32 mapId, const Position& pos) : WorldLocation(mapId, pos.GetPositionX(), pos.GetPositionY(),pos.GetPositionZ(), pos.GetPositionO()) {} - WorldPosition(const WorldObject* wo) { if (wo) { set(WorldLocation(wo->GetMapId(), wo->GetPositionX(), wo->GetPositionY(), wo->GetPositionZ(), wo->GetOrientation())); } } - WorldPosition(const CreatureDataPair* cdPair) { if (cdPair) { set(WorldLocation(cdPair->second.mapid, cdPair->second.posX, cdPair->second.posY, cdPair->second.posZ, cdPair->second.orientation)); } } - WorldPosition(const GameObjectDataPair* cdPair) { if (cdPair) { set(WorldLocation(cdPair->second.mapid, cdPair->second.posX, cdPair->second.posY, cdPair->second.posZ, cdPair->second.orientation)); } } - WorldPosition(const GuidPosition& guidP); - WorldPosition(const vector& list, const WorldPositionConst conType); - WorldPosition(const vector& list, const WorldPositionConst conType); - WorldPosition(const uint32 mapid, const GridPair grid) : WorldLocation(mapid, (int32(grid.x_coord) - CENTER_GRID_ID - 0.5)* SIZE_OF_GRIDS + CENTER_GRID_OFFSET, (int32(grid.y_coord) - CENTER_GRID_ID - 0.5)* SIZE_OF_GRIDS + CENTER_GRID_OFFSET, 0, 0) {} - WorldPosition(const uint32 mapid, const CellPair cell) : WorldLocation(mapid, (int32(cell.x_coord) - CENTER_GRID_CELL_ID - 0.5)* SIZE_OF_GRID_CELL + CENTER_GRID_CELL_OFFSET, (int32(cell.y_coord) - CENTER_GRID_CELL_ID - 0.5)* SIZE_OF_GRID_CELL + CENTER_GRID_CELL_OFFSET, 0, 0) {} - WorldPosition(const uint32 mapid, const mGridPair grid) : WorldLocation(mapid, (32 - grid.first)* SIZE_OF_GRIDS, (32 - grid.second)* SIZE_OF_GRIDS, 0, 0) {} - WorldPosition(const SpellTargetPosition* pos) : WorldLocation(pos->target_mapId, pos->target_X, pos->target_Y, pos->target_Z) {} - WorldPosition(const TaxiNodesEntry* pos) : WorldLocation(pos->map_id, pos->x, pos->y, pos->z) {} - - //Setters - void set(const WorldLocation& pos) { mapid = pos.mapid; coord_x = pos.coord_x; coord_y = pos.coord_y; coord_z = pos.coord_z; orientation = pos.orientation; } - void set(const WorldPosition& pos) { mapid = pos.mapid; coord_x = pos.coord_x; coord_y = pos.coord_y; coord_z = pos.coord_z; orientation = pos.orientation; } - void set(const ObjectGuid& guid); - void setMapId(const uint32 id) { mapid = id; } - void setX(const float x) { coord_x = x; } - void setY(const float y) { coord_y = y; } - void setZ(const float z) { coord_z = z; } - void setO(const float o) {orientation = o;} - - //Operators - operator bool() const { return coord_x != 0 || coord_y != 0 || coord_z != 0; } - bool operator==(const WorldPosition& p1) const { return mapid == p1.mapid && coord_x == p1.coord_x && coord_y == p1.coord_y && coord_z == p1.coord_z && orientation == p1.orientation; } - bool operator!=(const WorldPosition& p1) const { return mapid != p1.mapid || coord_x != p1.coord_x || coord_y != p1.coord_y || coord_z != p1.coord_z || orientation != p1.orientation; } - - WorldPosition& operator+=(const WorldPosition& p1) { coord_x += p1.coord_x; coord_y += p1.coord_y; coord_z += p1.coord_z; return *this; } - WorldPosition& operator-=(const WorldPosition& p1) { coord_x -= p1.coord_x; coord_y -= p1.coord_y; coord_z -= p1.coord_z; return *this; } - - WorldPosition& operator*=(const float s) { coord_x *= s; coord_y *= s; coord_z *= s; return *this; } - WorldPosition& operator/=(const float s) { coord_x /= s; coord_y /= s; coord_z /= s; return *this; } - - WorldPosition operator+(const WorldPosition& p1) const { WorldPosition p(*this); p += p1; return p; } - WorldPosition operator-(const WorldPosition& p1) const { WorldPosition p(*this); p -= p1; return p; } - - WorldPosition operator*(const float s) const { WorldPosition p(*this); p *= s; return p; } - WorldPosition operator/(const float s) const { WorldPosition p(*this); p /= s; return p; } - - float operator*(const WorldPosition& p1) const { return (coord_x * coord_x) + (coord_y * coord_y) + (coord_z * coord_z); } - - //Getters - uint32 getMapId() const { return mapid; } - float getX() const { return coord_x; } - float getY() const { return coord_y; } - float getZ() const { return coord_z; } - float getO() const { return orientation; } - G3D::Vector3 getVector3() const; - virtual string print() const; - string to_string() const {stringstream out; out << mapid; out << coord_x; out << coord_y; out << coord_z; out << orientation; return out.str();}; - - void printWKT(const vector& points, ostringstream& out, const uint32 dim = 0, const bool loop = false) const; - void printWKT(ostringstream& out) const { printWKT({ *this }, out); } - - bool isOverworld() const { return mapid == 0 || mapid == 1 || mapid == 530 || mapid == 571; } - bool isInWater() const { return getTerrain() ? getTerrain()->IsInWater(coord_x, coord_y, coord_z) : false; }; - bool isUnderWater() const { return getTerrain() ? getTerrain()->IsUnderWater(coord_x, coord_y, coord_z) : false; }; - - WorldPosition relPoint(const WorldPosition& center) const { return WorldPosition(mapid, coord_x - center.coord_x, coord_y - center.coord_y, coord_z - center.coord_z, orientation); } - WorldPosition offset(const WorldPosition& center) const { return WorldPosition(mapid, coord_x + center.coord_x, coord_y + center.coord_y, coord_z + center.coord_z, orientation); } - float size() const { return sqrt(pow(coord_x, 2.0) + pow(coord_y, 2.0) + pow(coord_z, 2.0)); } - - //Slow distance function using possible map transfers. - float distance(const WorldPosition& to) const; - - float fDist(const WorldPosition& to) const; - - //Returns the closest point from the list. - WorldPosition* closest(const vector& list) const { return *std::min_element(list.begin(), list.end(), [this](WorldPosition* i, WorldPosition* j) {return this->distance(*i) < this->distance(*j); }); } - WorldPosition closest(const vector& list) const { return *std::min_element(list.begin(), list.end(), [this](WorldPosition i, WorldPosition j) {return this->distance(i) < this->distance(j); }); } - - WorldPosition* furtest(const vector& list) const { return *std::max_element(list.begin(), list.end(), [this](WorldPosition* i, WorldPosition* j) {return this->distance(*i) < this->distance(*j); }); } - WorldPosition furtest(const vector& list) const { return *std::max_element(list.begin(), list.end(), [this](WorldPosition i, WorldPosition j) {return this->distance(i) < this->distance(j); }); } - - template - pair closest(const list>& list) const { return *std::min_element(list.begin(), list.end(), [this](pair i, pair j) {return this->distance(i.second) < this->distance(j.second); }); } - template - pair closest(const list& list) const { return closest(GetPosList(list)); } - - template - pair closest(const vector>& list) const { return *std::min_element(list.begin(), list.end(), [this](pair i, pair j) {return this->distance(i.second) < this->distance(j.second); }); } - template - pair closest(const vector& list) const { return closest(GetPosVector(list)); } - - - //Quick square distance in 2d plane. - float sqDistance2d(const WorldPosition& to) const { return (coord_x - to.coord_x) * (coord_x - to.coord_x) + (coord_y - to.coord_y) * (coord_y - to.coord_y); }; - - //Quick square distance calculation without map check. Used for getting the minimum distant points. - float sqDistance(const WorldPosition& to) const { return (coord_x - to.coord_x) * (coord_x - to.coord_x) + (coord_y - to.coord_y) * (coord_y - to.coord_y) + (coord_z - to.coord_z) * (coord_z - to.coord_z); }; - - //Returns the closest point of the list. Fast but only works for the same map. - WorldPosition* closestSq(const vector& list) const { return *std::min_element(list.begin(), list.end(), [this](WorldPosition* i, WorldPosition* j) {return sqDistance(*i) < sqDistance(*j); }); } - WorldPosition closestSq(const vector& list) const { return *std::min_element(list.begin(), list.end(), [this](WorldPosition i, WorldPosition j) {return sqDistance(i) < sqDistance(j); }); } - - float getAngleTo(const WorldPosition& endPos) const { float ang = atan2(endPos.coord_y - coord_y, endPos.coord_x - coord_x); return (ang >= 0) ? ang : 2 * M_PI_F + ang; }; - float getAngleBetween(const WorldPosition& dir1, const WorldPosition& dir2) const { return abs(getAngleTo(dir1) - getAngleTo(dir2)); }; - - WorldPosition limit(const WorldPosition& center, const float maxDistance) { WorldPosition pos(*this); pos -= center; float size = pos.size(); if (size > maxDistance) { pos /= pos.size(); pos *= maxDistance; pos += center; } return pos; } - - WorldPosition lastInRange(const vector& list, const float minDist = -1, const float maxDist = -1) const; - WorldPosition firstOutRange(const vector& list, const float minDist = -1, const float maxDist = -1) const; - - float mSign(const WorldPosition* p1, const WorldPosition* p2) const { return(coord_x - p2->coord_x) * (p1->coord_y - p2->coord_y) - (p1->coord_x - p2->coord_x) * (coord_y - p2->coord_y); } - bool isInside(const WorldPosition* p1, const WorldPosition* p2, const WorldPosition* p3) const; - - void distancePartition(const vector& distanceLimits, WorldPosition* to, vector>& partition) const; - vector> distancePartition(const vector& distanceLimits, vector points) const; - - //Map functions. Player independent. - const MapEntry* getMapEntry() const { return sMapStore.LookupEntry(mapid); } - uint32 getInstanceId() const { for (auto& map : sMapMgr.Maps()) { if (map.second->GetId() == getMapId()) return map.second->GetInstanceId(); }; return 0; } - Map* getMap() const { return sMapMgr.FindMap(mapid, getMapEntry()->Instanceable() ? getInstanceId() : 0); } - const TerrainInfo* getTerrain() const { return getMap() ? getMap()->GetTerrain() : NULL; } - -#if defined(MANGOSBOT_TWO) || MAX_EXPANSION == 2 - bool IsInLineOfSight(WorldPosition pos, float heightMod = 0.5f) const { return mapid == pos.mapid && getMap() && getMap()->IsInLineOfSight(coord_x, coord_y, coord_z + heightMod, pos.coord_x, pos.coord_y, pos.coord_z + heightMod, 0, true); } -#else - bool IsInLineOfSight(WorldPosition pos, float heightMod = 0.5f) const { return mapid == pos.mapid && getMap() && getMap()->IsInLineOfSight(coord_x, coord_y, coord_z + heightMod, pos.coord_x, pos.coord_y, pos.coord_z + heightMod, true); } -#endif - - bool isOutside() const { WorldPosition high(*this); high.setZ(coord_z + 500.0f); return IsInLineOfSight(high); } - bool canFly() const; - -#if defined(MANGOSBOT_TWO) || MAX_EXPANSION == 2 - const float getHeight() const { return getMap()->GetHeight(0, coord_x, coord_y, coord_z); } -#else - float getHeight() const { return getMap() ? getMap()->GetHeight(coord_x, coord_y, coord_z) : coord_z; } -#endif - - float currentHeight() const { return coord_z - getHeight(); } - - std::set getTransports(uint32 entry = 0); - - GridPair getGridPair() const { return MaNGOS::ComputeGridPair(coord_x, coord_y); }; - std::vector getGridPairs(const WorldPosition& secondPos) const; - vector fromGridPair(const GridPair& gridPair) const; - - CellPair getCellPair() const { return MaNGOS::ComputeCellPair(coord_x, coord_y); } - vector fromCellPair(const CellPair& cellPair) const; - vector gridFromCellPair(const CellPair& cellPair) const; - - mGridPair getmGridPair() const { - return make_pair((int)(32 - coord_x / SIZE_OF_GRIDS), (int)(32 - coord_y / SIZE_OF_GRIDS)); } - - vector getmGridPairs(const WorldPosition& secondPos) const; - vector frommGridPair(const mGridPair& gridPair) const; - - void loadMapAndVMap(uint32 mapId, uint32 instanceId, int x, int y) const; - void loadMapAndVMap(uint32 instanceId) const {loadMapAndVMap(getMapId(), instanceId, getmGridPair().first, getmGridPair().second); } - void loadMapAndVMaps(const WorldPosition& secondPos, uint32 instanceId) const; - - //Display functions - WorldPosition getDisplayLocation() const; - float getDisplayX() const { return getDisplayLocation().coord_y * -1.0; } - float getDisplayY() const { return getDisplayLocation().coord_x; } - - bool isValid() const { return MaNGOS::IsValidMapCoord(coord_x, coord_y, coord_z, orientation); }; - uint16 getAreaFlag() const { return isValid() ? sTerrainMgr.GetAreaFlag(getMapId(), coord_x, coord_y, coord_z) : 0; }; - AreaTableEntry const* getArea() const; - string getAreaName(const bool fullName = true, const bool zoneName = false) const; - int32 getAreaLevel() const; - - vector fromPointsArray(const std::vector& path) const; - - //Pathfinding - vector getPathStepFrom(const WorldPosition& startPos, const Unit* bot) const; - vector getPathFromPath(const vector& startPath, const Unit* bot, const uint8 maxAttempt = 40) const; - vector getPathFrom(const WorldPosition& startPos, const Unit* bot) { return getPathFromPath({ startPos }, bot); }; - vector getPathTo(WorldPosition endPos, const Unit* bot) const { return endPos.getPathFrom(*this, bot); } - bool isPathTo(const vector& path, float const maxDistance = sPlayerbotAIConfig.targetPosRecalcDistance) const { return !path.empty() && distance(path.back()) < maxDistance; }; - bool cropPathTo(vector& path, const float maxDistance = sPlayerbotAIConfig.targetPosRecalcDistance) const; - bool canPathTo(const WorldPosition& endPos, const Unit* bot) const { return endPos.isPathTo(getPathTo(endPos, bot)); } - - float getPathLength(const vector& points) const { float dist = 0.0f; for (auto& p : points) if (&p == &points.front()) dist = 0; else dist += std::prev(&p, 1)->distance(p); return dist; } - - bool GetReachableRandomPointOnGround(const Player* bot,const float radius, const bool randomRange = true) { -#ifndef MANGOSBOT_TWO - return getMap()->GetReachableRandomPointOnGround(coord_x, coord_y, coord_z, radius, randomRange); -#else - return getMap()->GetReachableRandomPointOnGround(bot->GetPhaseMask(), coord_x, coord_y, coord_z, radius, randomRange); -#endif - } - - uint32 getUnitsNear(const list& units, const float radius) const; - uint32 getUnitsAggro(const list& units, const Player* bot) const; - - //Creatures - vector getCreaturesNear(const float radius = 0, const uint32 entry = 0) const; - //GameObjects - vector getGameObjectsNear(const float radius = 0, const uint32 entry = 0) const; - }; - - inline ByteBuffer& operator<<(ByteBuffer& b, WorldPosition& guidP) - { - b << guidP.getMapId(); - b << guidP.coord_x; - b << guidP.coord_y; - b << guidP.coord_z; - b << guidP.orientation; - return b; - } - - inline ByteBuffer& operator>>(ByteBuffer& b, WorldPosition& g) - { - uint32 mapid; - float coord_x; - float coord_y; - float coord_z; - float orientation; - b >> mapid; - b >> coord_x; - b >> coord_y; - b >> coord_z; - b >> orientation; - - return b; - } - - //Generic creature finder - class FindPointCreatureData - { - public: - FindPointCreatureData(WorldPosition point1 = WorldPosition(), float radius1 = 0, uint32 entry1 = 0) { point = point1; radius = radius1; entry = entry1; } - - bool operator()(CreatureDataPair const& dataPair); - vector GetResult() const { return data; }; - private: - WorldPosition point; - float radius; - uint32 entry; - - vector data; - }; - - //Generic gameObject finder - class FindPointGameObjectData - { - public: - FindPointGameObjectData(WorldPosition point1 = WorldPosition(), float radius1 = 0, uint32 entry1 = 0) { point = point1; radius = radius1; entry = entry1; } - - bool operator()(GameObjectDataPair const& dataPair); - vector GetResult() const { return data; }; - private: - WorldPosition point; - float radius; - uint32 entry; - - vector data; - }; - - class GuidPosition : public ObjectGuid, public WorldPosition - { - public: - GuidPosition() : ObjectGuid(), WorldPosition() {} - GuidPosition(ObjectGuid guid) { ObjectGuid::Set(guid); WorldPosition::set(guid); }; - GuidPosition(ObjectGuid guid, WorldPosition pos) : ObjectGuid(guid), WorldPosition(pos) {}; - GuidPosition(uint64 const& guid, WorldPosition const& pos) : ObjectGuid(guid), WorldPosition(pos) {}; - //template - //GuidPosition(ObjectGuid guid, T) : ObjectGuid(guid) {WorldPosition::set(WorldPosition(T))}; - GuidPosition(CreatureDataPair const* dataPair) : ObjectGuid(HIGHGUID_UNIT, dataPair->second.id, dataPair->first), WorldPosition(dataPair) {}; - GuidPosition(GameObjectDataPair const* dataPair) : ObjectGuid(HIGHGUID_GAMEOBJECT, dataPair->second.id, dataPair->first), WorldPosition(dataPair) {}; - GuidPosition(WorldObject* wo) : WorldPosition(wo) { ObjectGuid::Set(wo->GetObjectGuid()); }; - GuidPosition(HighGuid hi, uint32 entry, uint32 counter = 1, WorldPosition pos = WorldPosition()) : ObjectGuid(hi, entry, counter), WorldPosition(pos) {}; - //GuidPosition(const GuidPosition& guidp) {this->Set(guidp); this->setLocation(((WorldPosition)guidp).getLocation()); }; - - CreatureData* GetCreatureData() { return IsCreature() ? sObjectMgr.GetCreatureData(GetCounter()) : nullptr; } - CreatureInfo const* GetCreatureTemplate()const {return IsCreature() ? sObjectMgr.GetCreatureTemplate(GetEntry()) : nullptr; }; - - GameObjectInfo const* GetGameObjectInfo() { return IsGameObject() ? sObjectMgr.GetGameObjectInfo(GetEntry()) : nullptr; }; - - WorldObject* GetWorldObject() { return getMap() ? getMap()->GetWorldObject(*this) : nullptr;} - Creature* GetCreature() const; - Unit* GetUnit() const; - GameObject* GetGameObject(); - Player* GetPlayer() const; - - bool HasNpcFlag(NPCFlags flag) { return IsCreature() && GetCreatureTemplate()->NpcFlags & flag; } - bool isGoType(GameobjectTypes type) { return IsGameObject() && GetGameObjectInfo()->type == type; } - - const FactionTemplateEntry* GetFactionTemplateEntry() const; - const ReputationRank GetReactionTo(const GuidPosition& other); - bool IsFriendlyTo(const GuidPosition& other) { return (GetFactionTemplateEntry() && other.GetFactionTemplateEntry()) ? (GetReactionTo(other) > REP_NEUTRAL) : false; } - bool IsHostileTo(const GuidPosition& other) { return (GetFactionTemplateEntry() && other.GetFactionTemplateEntry()) ? (GetReactionTo(other) < REP_NEUTRAL) : false; } - - bool isDead(); //For loaded grids check if the unit/object is unloaded/dead. - - uint16 IsPartOfAPool(); - uint16 GetGameEventId(); - bool IsEventUnspawned(); - - virtual string print(); - - operator bool() const { return WorldPosition(*this) && !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(); } - }; - - inline ByteBuffer& operator<<(ByteBuffer& b, GuidPosition& guidP) - { - b << (ObjectGuid)guidP; - b << (WorldPosition)guidP; - - - return b; - } - - inline ByteBuffer& operator>>(ByteBuffer& b, GuidPosition& g) - { - ObjectGuid guid; - WorldPosition pos; - - b >> guid; - b >> pos; - - g = GuidPosition(guid, pos); - - return b; - } - - template - list> GetPosList(list oList) { list> retList; for (auto& obj : oList) retList.push_back(make_pair(obj, WorldPosition(obj))); return retList; }; - - template - vector> GetPosVector(vector oList) { vector> retList; for (auto& obj : oList) retList.push_back(make_pair(obj, WorldPosition(obj))); return retList; }; - +{ class mapTransfer { public: diff --git a/playerbot/TravelNode.cpp b/playerbot/TravelNode.cpp index 08e52b2f1..a57a5f845 100644 --- a/playerbot/TravelNode.cpp +++ b/playerbot/TravelNode.cpp @@ -1,6 +1,7 @@ #pragma once #include "TravelNode.h" +#include "TravelMgr.h" #include #include diff --git a/playerbot/TravelNode.h b/playerbot/TravelNode.h index 37087e6d7..de589e69c 100644 --- a/playerbot/TravelNode.h +++ b/playerbot/TravelNode.h @@ -1,7 +1,7 @@ #pragma once #include -#include "TravelMgr.h" +#include "WorldPosition.h" //THEORY // diff --git a/playerbot/WorldPosition.cpp b/playerbot/WorldPosition.cpp new file mode 100644 index 000000000..f8d60eb43 --- /dev/null +++ b/playerbot/WorldPosition.cpp @@ -0,0 +1,808 @@ +#pragma once + +#include "WorldPosition.h" +#include "GuidPosition.h" +#include "TravelMgr.h" +#include "TravelNode.h" + +#include "Map.h" +#include "vmap/VMapFactory.h" +#include "MoveMap.h" +#include "PathFinder.h" +#include "Grids/CellImpl.h" + +#include +#include + +using namespace ai; +using namespace MaNGOS; + +WorldPosition::WorldPosition(const GuidPosition& guidP) +{ + if (guidP.mapid !=0 || guidP.coord_x != 0 || guidP.coord_y != 0 || guidP.coord_z !=0) { + set(WorldPosition(guidP.mapid, guidP.coord_x, guidP.coord_y, guidP.coord_z, guidP.orientation)); + return; + } + + set(ObjectGuid(guidP)); + } + +void WorldPosition::set(const ObjectGuid& guid) +{ + switch (guid.GetHigh()) + { + case HIGHGUID_PLAYER: + { + Player* player = sObjectAccessor.FindPlayer(guid); + if (player) + set(WorldLocation(player->GetMapId(), player->GetPositionX(), player->GetPositionY(), player->GetPositionZ(), player->GetOrientation())); + break; + } + case HIGHGUID_GAMEOBJECT: + { + GameObjectDataPair const* gpair = sObjectMgr.GetGODataPair(guid.GetCounter()); + if (gpair) + set(WorldLocation(gpair->second.mapid, gpair->second.posX, gpair->second.posY, gpair->second.posZ, gpair->second.orientation)); + break; + } + case HIGHGUID_UNIT: + { + CreatureDataPair const* cpair = sObjectMgr.GetCreatureDataPair(guid.GetCounter()); + if (cpair) + set(WorldLocation(cpair->second.mapid, cpair->second.posX, cpair->second.posY, cpair->second.posZ, cpair->second.orientation)); + break; + } + case HIGHGUID_TRANSPORT: + case HIGHGUID_MO_TRANSPORT: + case HIGHGUID_ITEM: + case HIGHGUID_PET: + case HIGHGUID_DYNAMICOBJECT: + case HIGHGUID_CORPSE: + return; + } + +} + +WorldPosition::WorldPosition(const vector& list, const WorldPositionConst conType) +{ + uint32 size = list.size(); + if (size == 0) + return; + else if (size == 1) + set(*list.front()); + else if (conType == WP_RANDOM) + set(*list[urand(0, size - 1)]); + else if (conType == WP_CENTROID) + set(std::accumulate(list.begin(), list.end(), WorldLocation(list[0]->getMapId(), 0, 0, 0, 0), [size](WorldLocation i, WorldPosition* j) {i.coord_x += j->getX() / size; i.coord_y += j->getY() / size; i.coord_z += j->getZ() / size; i.orientation += j->getO() / size; return i; })); + else if (conType == WP_MEAN_CENTROID) + { + WorldPosition pos = WorldPosition(list, WP_CENTROID); + set(*pos.closestSq(list)); + } +} + +WorldPosition::WorldPosition(const vector& list, const WorldPositionConst conType) +{ + uint32 size = list.size(); + if (size == 0) + return; + else if (size == 1) + set(list.front()); + else if (conType == WP_RANDOM) + set(list[urand(0, size - 1)]); + else if (conType == WP_CENTROID) + set(std::accumulate(list.begin(), list.end(), WorldLocation(list[0].getMapId(), 0, 0, 0, 0), [size](WorldLocation i, WorldPosition j) {i.coord_x += j.getX() / size; i.coord_y += j.getY() / size; i.coord_z += j.getZ() / size; i.orientation += j.getO() / size; return i; })); + else if (conType == WP_MEAN_CENTROID) + { + WorldPosition pos = WorldPosition(list, WP_CENTROID); + set(pos.closestSq(list)); + } +} + +float WorldPosition::distance(const WorldPosition& to) const +{ + if(mapid == to.getMapId()) + return relPoint(to).size(); + + //this -> mapTransfer | mapTransfer -> center + return sTravelMgr.mapTransDistance(*this, to); +}; + +float WorldPosition::fDist(const WorldPosition& to) const +{ + if (mapid == to.getMapId()) + return sqrt(sqDistance2d(to)); + + //this -> mapTransfer | mapTransfer -> center + return sTravelMgr.fastMapTransDistance(*this, to); +}; + +//When moving from this along list return last point that falls within range. +//Distance is move distance along path. +WorldPosition WorldPosition::lastInRange(const vector& list, const float minDist, const float maxDist) const +{ + WorldPosition rPoint; + + float startDist = 0.0f; + + //Enter the path at the closest point. + for (auto& p : list) + { + float curDist = distance(p); + if (startDist < curDist || p == list.front()) + startDist = curDist + 0.1f; + } + + float totalDist = 0.0f; + + //Follow the path from the last nearest point + //Return last point in range. + for (auto& p : list) + { + float curDist = distance(p); + + if (totalDist > 0) //We have started the path. Keep counting. + totalDist += p.distance(*std::prev(&p, 1)); + + if (curDist == startDist) //Start the path here. + totalDist = startDist; + + if (minDist > 0 && totalDist < minDist) + continue; + + if (maxDist > 0 && totalDist > maxDist) + continue; //We do not break here because the path may loop back and have a second startDist point. + + rPoint = p; + } + + return rPoint; +}; + +//Todo: remove or adjust to above standard. +WorldPosition WorldPosition::firstOutRange(const vector& list, const float minDist, const float maxDist) const +{ + WorldPosition rPoint; + + for (auto& p : list) + { + if (minDist > 0 && distance(p) < minDist) + return p; + + if (maxDist > 0 && distance(p) > maxDist) + return p; + + rPoint = p; + } + + return rPoint; +} + +//Returns true if (on the x-y plane) the position is inside the three points. +bool WorldPosition::isInside(const WorldPosition* p1, const WorldPosition* p2, const WorldPosition* p3) const +{ + if (getMapId() != p1->getMapId() != p2->getMapId() != p3->getMapId()) + return false; + + float d1, d2, d3; + bool has_neg, has_pos; + + d1 = mSign(p1, p2); + d2 = mSign(p2, p3); + d3 = mSign(p3, p1); + + has_neg = (d1 < 0) || (d2 < 0) || (d3 < 0); + has_pos = (d1 > 0) || (d2 > 0) || (d3 > 0); + + return !(has_neg && has_pos); +} + +void WorldPosition::distancePartition(const vector& distanceLimits, WorldPosition* to, vector>& partitions) const +{ + float dist = distance(*to); + + for (uint8 l = 0; l < distanceLimits.size(); l++) + if (dist <= distanceLimits[l]) + partitions[l].push_back(to); +} + +vector> WorldPosition::distancePartition(const vector& distanceLimits, vector points) const +{ + vector> partitions; + + for (auto lim : distanceLimits) + partitions.push_back({}); + + for (auto& point : points) + { + distancePartition(distanceLimits, point, partitions); + } + + return partitions; +} + +bool WorldPosition::canFly() const +{ +#ifdef MANGOSBOT_ZERO + return false; +#endif + if (!getTerrain()) + return false; + + uint32 zoneid, areaid; + getTerrain()->GetZoneAndAreaId(zoneid, areaid, getX(), getY(), getZ()); + +#ifdef MANGOSBOT_ONE + uint32 v_map = GetVirtualMapForMapAndZone(getMapId(), zoneid); + MapEntry const* mapEntry = sMapStore.LookupEntry(v_map); + if (!mapEntry || mapEntry->addon < 1 || !mapEntry->IsContinent()) + return false; +#endif +#ifdef MANGOSBOT_TWO + // Disallow mounting in wintergrasp when battle is in progress + if (OutdoorPvP* outdoorPvP = sOutdoorPvPMgr.GetScript(zoneid)) + { + if (outdoorPvP->IsBattlefield()) + return ((Battlefield*)outdoorPvP)->GetBattlefieldStatus() != BF_STATUS_IN_PROGRESS; + } + + // don't allow flying in Dalaran restricted areas + // (no other zones currently has areas with AREA_FLAG_CANNOT_FLY) + if (AreaTableEntry const* atEntry = GetAreaEntryByAreaID(areaid)) + return (!(atEntry->flags & AREA_FLAG_CANNOT_FLY)); +#endif + + return true; +} + +G3D::Vector3 WorldPosition::getVector3() const +{ + return G3D::Vector3(coord_x, coord_y, coord_z); +} + +string WorldPosition::print() const +{ + ostringstream out; + out << mapid << std::fixed << std::setprecision(2); + out << ';'<< coord_x; + out << ';' << coord_y; + out << ';' << coord_z; + out << ';' << orientation; + + return out.str(); +} + +void WorldPosition::printWKT(const vector& points, ostringstream& out, const uint32 dim, const bool loop) const +{ + switch (dim) { + case 0: + if(points.size() == 1) + out << "\"POINT("; + else + out << "\"MULTIPOINT("; + break; + case 1: + out << "\"LINESTRING("; + break; + case 2: + out << "\"POLYGON(("; + } + + for (auto& p : points) + out << p.getDisplayX() << " " << p.getDisplayY() << (!loop && &p == &points.back() ? "" : ","); + + if (loop) + out << points.front().getDisplayX() << " " << points.front().getDisplayY(); + + out << (dim == 2 ? "))\"," : ")\","); +} + +WorldPosition WorldPosition::getDisplayLocation() const +{ + WorldPosition mapOffset = sTravelNodeMap.getMapOffset(getMapId()); + return offset(mapOffset); +}; + +AreaTableEntry const* WorldPosition::getArea() const +{ + uint16 areaFlag = getAreaFlag(); + + //if(!areaFlag) + // return NULL; + + return GetAreaEntryByAreaFlagAndMap(areaFlag, getMapId()); +} + +string WorldPosition::getAreaName(const bool fullName, const bool zoneName) const +{ + if (!isOverworld()) + { + MapEntry const* map = sMapStore.LookupEntry(getMapId()); + if (map) + return map->name[0]; + } + + AreaTableEntry const* area = getArea(); + + if (!area) + return ""; + + string areaName = area->area_name[0]; + + if (fullName) + { + uint16 zoneId = area->zone; + + while (zoneId > 0) + { + AreaTableEntry const* parentArea = GetAreaEntryByAreaID(zoneId); + + if (!parentArea) + break; + + string subAreaName = parentArea->area_name[0]; + + if (zoneName) + areaName = subAreaName; + else + areaName = subAreaName + " " + areaName; + + zoneId = parentArea->zone; + } + } + + return areaName; +} + +int32 WorldPosition::getAreaLevel() const +{ + if(getArea()) + return sTravelMgr.getAreaLevel(getArea()->ID); + + return 0; +} + +std::set WorldPosition::getTransports(uint32 entry) +{ + /* + if(!entry) + return getMap()->m_transports; + else + { + */ + std::set transports; + /* + for (auto transport : getMap()->m_transports) + if(transport->GetEntry() == entry) + transports.insert(transport); + + return transports; + } + */ + return transports; +} + +std::vector WorldPosition::getGridPairs(const WorldPosition& secondPos) const +{ + std::vector retVec; + + int lx = std::min(getGridPair().x_coord, secondPos.getGridPair().x_coord); + int ly = std::min(getGridPair().y_coord, secondPos.getGridPair().y_coord); + int ux = std::max(getGridPair().x_coord, secondPos.getGridPair().x_coord); + int uy = std::max(getGridPair().y_coord, secondPos.getGridPair().y_coord); + int border = 1; + + lx = std::min(std::max(border, lx), MAX_NUMBER_OF_GRIDS - border); + ly = std::min(std::max(border, ly), MAX_NUMBER_OF_GRIDS - border); + ux = std::min(std::max(border, ux), MAX_NUMBER_OF_GRIDS - border); + uy = std::min(std::max(border, uy), MAX_NUMBER_OF_GRIDS - border); + + for (int x = lx - border; x <= ux + border; x++) + { + for (int y = ly - border; y <= uy + border; y++) + { + retVec.push_back(GridPair(x, y)); + } + } + + return retVec; +} + +vector WorldPosition::fromGridPair(const GridPair& gridPair) const +{ + vector retVec; + GridPair g; + + for (uint32 d = 0; d < 4; d++) + { + g = gridPair; + + if (d == 1 || d == 2) + g >> 1; + if (d == 2 || d == 3) + g += 1; + + retVec.push_back(WorldPosition(getMapId(), g)); + } + + return retVec; +} + +vector WorldPosition::fromCellPair(const CellPair& cellPair) const +{ + vector retVec; + CellPair p; + + for (uint32 d = 0; d < 4; d++) + { + p = cellPair; + + if (d == 1 || d == 2) + p >> 1; + if (d == 2 || d == 3) + p += 1; + + retVec.push_back(WorldPosition(getMapId(), p)); + } + return retVec; +} + +vector WorldPosition::gridFromCellPair(const CellPair& cellPair) const +{ + Cell c(cellPair); + + return fromGridPair(GridPair(c.GridX(), c.GridY())); +} + +vector> WorldPosition::getmGridPairs(const WorldPosition& secondPos) const +{ + std::vector retVec; + + int lx = std::min(getmGridPair().first, secondPos.getmGridPair().first); + int ly = std::min(getmGridPair().second, secondPos.getmGridPair().second); + int ux = std::max(getmGridPair().first, secondPos.getmGridPair().first); + int uy = std::max(getmGridPair().second, secondPos.getmGridPair().second); + int border = 1; + + //lx = std::min(std::max(border, lx), MAX_NUMBER_OF_GRIDS - border); + //ly = std::min(std::max(border, ly), MAX_NUMBER_OF_GRIDS - border); + //ux = std::min(std::max(border, ux), MAX_NUMBER_OF_GRIDS - border); + //uy = std::min(std::max(border, uy), MAX_NUMBER_OF_GRIDS - border); + + for (int x = lx - border; x <= ux + border; x++) + { + for (int y = ly - border; y <= uy + border; y++) + { + retVec.push_back(make_pair(x, y)); + } + } + + return retVec; +} + +vector WorldPosition::frommGridPair(const mGridPair& gridPair) const +{ + vector retVec; + mGridPair g; + + for (uint32 d = 0; d < 4; d++) + { + g = gridPair; + + if (d == 1 || d == 2) + g.second++; + if (d == 2 || d == 3) + g.first++; + + retVec.push_back(WorldPosition(getMapId(), g)); + } + + return retVec; +} + +void WorldPosition::loadMapAndVMap(uint32 mapId, uint32 instanceId, int x, int y) const +{ + string fileName = "load_map_grid.csv"; + + if (isOverworld() && false || false) + { +#ifdef MANGOSBOT_TWO + if (!MMAP::MMapFactory::createOrGetMMapManager()->IsMMapTileLoaded(mapId, instanceId, x, y)) +#else + if (!MMAP::MMapFactory::createOrGetMMapManager()->IsMMapIsLoaded(mapId, x, y)) +#endif + if (sPlayerbotAIConfig.hasLog(fileName)) + { + ostringstream out; + out << sPlayerbotAIConfig.GetTimestampStr(); + out << "+00,\"mmap\", " << x << "," << y << "," << (sTravelMgr.isBadMmap(mapId, x, y) ? "0" : "1") << ","; + printWKT(fromGridPair(GridPair(x, y)), out, 1, true); + sPlayerbotAIConfig.log(fileName, out.str().c_str()); + } + + int px = (float)(32 - x) * SIZE_OF_GRIDS; + int py = (float)(32 - y) * SIZE_OF_GRIDS; + +#ifdef MANGOSBOT_TWO + if (!MMAP::MMapFactory::createOrGetMMapManager()->IsMMapTileLoaded(mapId, instanceId, x, y)) +#else + if (!MMAP::MMapFactory::createOrGetMMapManager()->IsMMapIsLoaded(mapId, x, y)) +#endif + if(getTerrain()) + getTerrain()->GetTerrainType(px, py); + + } + else + { + + //This needs to be disabled or maps will not load. + //Needs more testing to check for impact on movement. + if (false) + if (!VMAP::VMapFactory::createOrGetVMapManager()->IsTileLoaded(mapId, x, y) && !sTravelMgr.isBadVmap(mapId, x, y)) + { + // load VMAPs for current map/grid... + const MapEntry* i_mapEntry = sMapStore.LookupEntry(mapId); + const char* mapName = i_mapEntry ? i_mapEntry->name[sWorld.GetDefaultDbcLocale()] : "UNNAMEDMAP\x0"; + + int vmapLoadResult = VMAP::VMapFactory::createOrGetVMapManager()->loadMap((sWorld.GetDataPath() + "vmaps").c_str(), mapId, x, y); + switch (vmapLoadResult) + { + case VMAP::VMAP_LOAD_RESULT_OK: + //sLog.outError("VMAP loaded name:%s, id:%d, x:%d, y:%d (vmap rep.: x:%d, y:%d)", mapName, mapId, x, y, x, y); + break; + case VMAP::VMAP_LOAD_RESULT_ERROR: + //sLog.outError("Could not load VMAP name:%s, id:%d, x:%d, y:%d (vmap rep.: x:%d, y:%d)", mapName, mapId, x, y, x, y); + sTravelMgr.addBadVmap(mapId, x, y); + break; + case VMAP::VMAP_LOAD_RESULT_IGNORED: + sTravelMgr.addBadVmap(mapId, x, y); + //sLog.outError("Ignored VMAP name:%s, id:%d, x:%d, y:%d (vmap rep.: x:%d, y:%d)", mapName, mapId, x, y, x, y); + break; + } + + if (sPlayerbotAIConfig.hasLog(fileName)) + { + ostringstream out; + out << sPlayerbotAIConfig.GetTimestampStr(); + out << "+00,\"vmap\", " << x << "," << y << ", " << (sTravelMgr.isBadVmap(mapId, x, y) ? "0" : "1") << ","; + printWKT(fromGridPair(GridPair(x, y)), out, 1, true); + sPlayerbotAIConfig.log(fileName, out.str().c_str()); + } + } + +#ifdef MANGOSBOT_TWO + if (!MMAP::MMapFactory::createOrGetMMapManager()->IsMMapTileLoaded(mapId, instanceId, x, y) && !sTravelMgr.isBadMmap(mapId, x, y)) +#else + if (!MMAP::MMapFactory::createOrGetMMapManager()->IsMMapIsLoaded(mapId, x, y) && !sTravelMgr.isBadMmap(mapId, x, y)) +#endif + { + // load navmesh +#ifdef MANGOSBOT_TWO + if (!MMAP::MMapFactory::createOrGetMMapManager()->loadMap(mapId, instanceId, x, y, 0)) +#else + if (!MMAP::MMapFactory::createOrGetMMapManager()->loadMap(mapId, x, y)) +#endif + sTravelMgr.addBadMmap(mapId, x, y); + + if (sPlayerbotAIConfig.hasLog(fileName)) + { + ostringstream out; + out << sPlayerbotAIConfig.GetTimestampStr(); + out << "+00,\"mmap\", " << x << "," << y << "," << (sTravelMgr.isBadMmap(mapId, x, y) ? "0" : "1") << ","; + printWKT(frommGridPair(mGridPair(x, y)), out, 1, true); + sPlayerbotAIConfig.log(fileName, out.str().c_str()); + } + } + } +} + +void WorldPosition::loadMapAndVMaps(const WorldPosition& secondPos, uint32 instanceId) const +{ + for (auto& grid : getmGridPairs(secondPos)) + { + loadMapAndVMap(getMapId(), instanceId, grid.first, grid.second); + } +} + +vector WorldPosition::fromPointsArray(const std::vector& path) const +{ + vector retVec; + for (auto p : path) + retVec.push_back(WorldPosition(getMapId(), p.x, p.y, p.z, getO())); + + return retVec; +} + +//A single pathfinding attempt from one position to another. Returns pathfinding status and path. +vector WorldPosition::getPathStepFrom(const WorldPosition& startPos, const Unit* bot) const +{ + std::hash hasher; + uint32 instanceId; + if (sTravelNodeMap.gethasToGen()) + instanceId = 0; + else if (!bot || sPlayerbotAIConfig.tweakValue || bot->GetMapId() != startPos.getMapId()) + instanceId = hasher(std::this_thread::get_id()); + else + instanceId = bot->GetInstanceId(); + //Load mmaps and vmaps between the two points. + + loadMapAndVMaps(startPos, instanceId); + + PointsArray points; + PathType type; + + if (bot && false) + { + PathFinder path(bot); + +#ifdef IKE_PATHFINDER + path.setAreaCost(NAV_AREA_WATER, 10.0f); //Water + path.setAreaCost(12, 5.0f); //Mob proximity + path.setAreaCost(13, 20.0f); //Mob agro +#endif + path.calculate(startPos.getVector3(), getVector3(), false); + + points = path.getPath(); + type = path.getPathType(); + + } + else +#ifdef IKE_PATHFINDER + { + PathFinder path(getMapId(), instanceId); + + path.setAreaCost(NAV_AREA_WATER, 10.0f); + path.setAreaCost(12, 5.0f); + path.setAreaCost(13, 20.0f); + + path.calculate(startPos.getVector3(), getVector3(), false); + + points = path.getPath(); + type = path.getPathType(); + } +#else + return PATHFIND_NOPATH; +#endif + + if (sPlayerbotAIConfig.hasLog("pathfind_attempt_point.csv")) + { + ostringstream out; + out << std::fixed << std::setprecision(1); + printWKT({ startPos, *this }, out); + sPlayerbotAIConfig.log("pathfind_attempt_point.csv", out.str().c_str()); + } + + if (sPlayerbotAIConfig.hasLog("pathfind_attempt.csv") && (type == PATHFIND_INCOMPLETE || type == PATHFIND_NORMAL)) + { + ostringstream out; + out << sPlayerbotAIConfig.GetTimestampStr() << "+00,"; + out << std::fixed << std::setprecision(1) << type << ","; + printWKT(fromPointsArray(points), out, 1); + sPlayerbotAIConfig.log("pathfind_attempt.csv", out.str().c_str()); + } + + if (type == PATHFIND_INCOMPLETE || type == PATHFIND_NORMAL) + return fromPointsArray(points); + else + return {}; + +} + +bool WorldPosition::cropPathTo(vector& path, const float maxDistance) const +{ + if (path.empty()) + return false; + + auto bestPos = std::min_element(path.begin(), path.end(), [this](WorldPosition i, WorldPosition j) {return this->sqDistance(i) < this->sqDistance(j); }); + + bool insRange = this->sqDistance(*bestPos) <= maxDistance * maxDistance; + + if (bestPos == path.end()) + return insRange; + + path.erase(std::next(bestPos), path.end()); + + return insRange; +} + +//A sequential series of pathfinding attempts. Returns the complete path and if the patfinder eventually found a way to the destination. +vector WorldPosition::getPathFromPath(const vector& startPath, const Unit* bot, uint8 maxAttempt) const +{ + //We start at the end of the last path. + WorldPosition currentPos = startPath.back(); + + //No pathfinding across maps. + if (getMapId() != currentPos.getMapId()) + return { }; + + vector subPath, fullPath = startPath; + + //Limit the pathfinding attempts + for (uint32 i = 0; i < maxAttempt; i++) + { + //Try to pathfind to this position. + subPath = getPathStepFrom(currentPos, bot); + + //If we could not find a path return what we have now. + if (subPath.empty() || currentPos.distance(subPath.back()) < sPlayerbotAIConfig.targetPosRecalcDistance) + break; + + //Append the path excluding the start (this should be the same as the end of the startPath) + fullPath.insert(fullPath.end(), std::next(subPath.begin(),1), subPath.end()); + + //Are we there yet? + if (isPathTo(subPath)) + break; + + //Continue pathfinding. + currentPos = subPath.back(); + } + + return fullPath; +} + +uint32 WorldPosition::getUnitsNear(const list& units, const float radius) const +{ + uint32 count = 0; + for (auto guid : units) + if (sqDistance(WorldPosition(guid)) <= radius * radius) + count++; + + return count; +}; + +uint32 WorldPosition::getUnitsAggro(const list& units, const Player* bot) const +{ + uint32 count = 0; + for (auto guid : units) + { + Unit* unit = GuidPosition(guid).GetUnit(); + + if (!unit) continue; + + if (this->sqDistance(WorldPosition(guid)) > unit->GetAttackDistance(bot) * unit->GetAttackDistance(bot)) + continue; + + count++; + } + + return count; +}; + + + +bool FindPointCreatureData::operator()(CreatureDataPair const& dataPair) +{ + if (!entry || dataPair.second.id == entry) + if ((!point || dataPair.second.mapid == point.getMapId()) && (!radius || point.sqDistance(WorldPosition(dataPair.second.mapid, dataPair.second.posX, dataPair.second.posY, dataPair.second.posZ)) < radius * radius)) + { + data.push_back(&dataPair); + } + + return false; +} + +bool FindPointGameObjectData::operator()(GameObjectDataPair const& dataPair) +{ + if (!entry || dataPair.second.id == entry) + if ((!point || dataPair.second.mapid == point.getMapId()) && (!radius || point.sqDistance(WorldPosition(dataPair.second.mapid, dataPair.second.posX, dataPair.second.posY, dataPair.second.posZ)) < radius * radius)) + { + data.push_back(&dataPair); + } + + return false; +} + +vector WorldPosition::getCreaturesNear(const float radius, const uint32 entry) const +{ + FindPointCreatureData worker(*this, radius, entry); + sObjectMgr.DoCreatureData(worker); + return worker.GetResult(); +} + +vector WorldPosition::getGameObjectsNear(const float radius, const uint32 entry) const +{ + FindPointGameObjectData worker(*this, radius, entry); + sObjectMgr.DoGOData(worker); + return worker.GetResult(); +} \ No newline at end of file diff --git a/playerbot/WorldPosition.h b/playerbot/WorldPosition.h new file mode 100644 index 000000000..656d2bcb2 --- /dev/null +++ b/playerbot/WorldPosition.h @@ -0,0 +1,288 @@ +#pragma once + +class ByteBuffer; + +namespace G3D +{ + class Vector2; + class Vector3; + class Vector4; +} + +namespace ai +{ + //Constructor types for WorldPosition + enum WorldPositionConst + { + WP_RANDOM = 0, + WP_CENTROID = 1, + WP_MEAN_CENTROID = 2, + WP_CLOSEST = 3 + }; + + class GuidPosition; + + typedef pair mGridPair; + + //Extension of WorldLocation with distance functions. + class WorldPosition : public WorldLocation + { + public: + //Constructors + WorldPosition() : WorldLocation() {}; + WorldPosition(const WorldLocation loc) : WorldLocation(loc) {} + WorldPosition(const WorldPosition& pos) : WorldLocation(pos) {} + WorldPosition(const string str) { stringstream out(str); out >> mapid; out >> coord_x; out >> coord_y; out >> coord_z; out >> orientation; } + WorldPosition(const uint32 mapid, const float x, const float y, const float z = 0, float orientation = 0) : WorldLocation(mapid, x, y, z, orientation) {} + WorldPosition(const uint32 mapId, const Position& pos) : WorldLocation(mapId, pos.GetPositionX(), pos.GetPositionY(),pos.GetPositionZ(), pos.GetPositionO()) {} + WorldPosition(const WorldObject* wo) { if (wo) { set(WorldLocation(wo->GetMapId(), wo->GetPositionX(), wo->GetPositionY(), wo->GetPositionZ(), wo->GetOrientation())); } } + WorldPosition(const CreatureDataPair* cdPair) { if (cdPair) { set(WorldLocation(cdPair->second.mapid, cdPair->second.posX, cdPair->second.posY, cdPair->second.posZ, cdPair->second.orientation)); } } + WorldPosition(const GameObjectDataPair* cdPair) { if (cdPair) { set(WorldLocation(cdPair->second.mapid, cdPair->second.posX, cdPair->second.posY, cdPair->second.posZ, cdPair->second.orientation)); } } + WorldPosition(const GuidPosition& guidP); + WorldPosition(const vector& list, const WorldPositionConst conType); + WorldPosition(const vector& list, const WorldPositionConst conType); + WorldPosition(const uint32 mapid, const GridPair grid) : WorldLocation(mapid, (int32(grid.x_coord) - CENTER_GRID_ID - 0.5)* SIZE_OF_GRIDS + CENTER_GRID_OFFSET, (int32(grid.y_coord) - CENTER_GRID_ID - 0.5)* SIZE_OF_GRIDS + CENTER_GRID_OFFSET, 0, 0) {} + WorldPosition(const uint32 mapid, const CellPair cell) : WorldLocation(mapid, (int32(cell.x_coord) - CENTER_GRID_CELL_ID - 0.5)* SIZE_OF_GRID_CELL + CENTER_GRID_CELL_OFFSET, (int32(cell.y_coord) - CENTER_GRID_CELL_ID - 0.5)* SIZE_OF_GRID_CELL + CENTER_GRID_CELL_OFFSET, 0, 0) {} + WorldPosition(const uint32 mapid, const mGridPair grid) : WorldLocation(mapid, (32 - grid.first)* SIZE_OF_GRIDS, (32 - grid.second)* SIZE_OF_GRIDS, 0, 0) {} + WorldPosition(const SpellTargetPosition* pos) : WorldLocation(pos->target_mapId, pos->target_X, pos->target_Y, pos->target_Z) {} + WorldPosition(const TaxiNodesEntry* pos) : WorldLocation(pos->map_id, pos->x, pos->y, pos->z) {} + + //Setters + void set(const WorldLocation& pos) { mapid = pos.mapid; coord_x = pos.coord_x; coord_y = pos.coord_y; coord_z = pos.coord_z; orientation = pos.orientation; } + void set(const WorldPosition& pos) { mapid = pos.mapid; coord_x = pos.coord_x; coord_y = pos.coord_y; coord_z = pos.coord_z; orientation = pos.orientation; } + void set(const ObjectGuid& guid); + void setMapId(const uint32 id) { mapid = id; } + void setX(const float x) { coord_x = x; } + void setY(const float y) { coord_y = y; } + void setZ(const float z) { coord_z = z; } + void setO(const float o) {orientation = o;} + + //Operators + operator bool() const { return coord_x != 0 || coord_y != 0 || coord_z != 0; } + bool operator==(const WorldPosition& p1) const { return mapid == p1.mapid && coord_x == p1.coord_x && coord_y == p1.coord_y && coord_z == p1.coord_z && orientation == p1.orientation; } + bool operator!=(const WorldPosition& p1) const { return mapid != p1.mapid || coord_x != p1.coord_x || coord_y != p1.coord_y || coord_z != p1.coord_z || orientation != p1.orientation; } + + WorldPosition& operator+=(const WorldPosition& p1) { coord_x += p1.coord_x; coord_y += p1.coord_y; coord_z += p1.coord_z; return *this; } + WorldPosition& operator-=(const WorldPosition& p1) { coord_x -= p1.coord_x; coord_y -= p1.coord_y; coord_z -= p1.coord_z; return *this; } + + WorldPosition& operator*=(const float s) { coord_x *= s; coord_y *= s; coord_z *= s; return *this; } + WorldPosition& operator/=(const float s) { coord_x /= s; coord_y /= s; coord_z /= s; return *this; } + + WorldPosition operator+(const WorldPosition& p1) const { WorldPosition p(*this); p += p1; return p; } + WorldPosition operator-(const WorldPosition& p1) const { WorldPosition p(*this); p -= p1; return p; } + + WorldPosition operator*(const float s) const { WorldPosition p(*this); p *= s; return p; } + WorldPosition operator/(const float s) const { WorldPosition p(*this); p /= s; return p; } + + float operator*(const WorldPosition& p1) const { return (coord_x * coord_x) + (coord_y * coord_y) + (coord_z * coord_z); } + + //Getters + uint32 getMapId() const { return mapid; } + float getX() const { return coord_x; } + float getY() const { return coord_y; } + float getZ() const { return coord_z; } + float getO() const { return orientation; } + G3D::Vector3 getVector3() const; + virtual string print() const; + string to_string() const {stringstream out; out << mapid; out << coord_x; out << coord_y; out << coord_z; out << orientation; return out.str();}; + + void printWKT(const vector& points, ostringstream& out, const uint32 dim = 0, const bool loop = false) const; + void printWKT(ostringstream& out) const { printWKT({ *this }, out); } + + bool isOverworld() const { return mapid == 0 || mapid == 1 || mapid == 530 || mapid == 571; } + bool isInWater() const { return getTerrain() ? getTerrain()->IsInWater(coord_x, coord_y, coord_z) : false; }; + bool isUnderWater() const { return getTerrain() ? getTerrain()->IsUnderWater(coord_x, coord_y, coord_z) : false; }; + + WorldPosition relPoint(const WorldPosition& center) const { return WorldPosition(mapid, coord_x - center.coord_x, coord_y - center.coord_y, coord_z - center.coord_z, orientation); } + WorldPosition offset(const WorldPosition& center) const { return WorldPosition(mapid, coord_x + center.coord_x, coord_y + center.coord_y, coord_z + center.coord_z, orientation); } + float size() const { return sqrt(pow(coord_x, 2.0) + pow(coord_y, 2.0) + pow(coord_z, 2.0)); } + + //Slow distance function using possible map transfers. + float distance(const WorldPosition& to) const; + + float fDist(const WorldPosition& to) const; + + //Returns the closest point from the list. + WorldPosition* closest(const vector& list) const { return *std::min_element(list.begin(), list.end(), [this](WorldPosition* i, WorldPosition* j) {return this->distance(*i) < this->distance(*j); }); } + WorldPosition closest(const vector& list) const { return *std::min_element(list.begin(), list.end(), [this](WorldPosition i, WorldPosition j) {return this->distance(i) < this->distance(j); }); } + + WorldPosition* furtest(const vector& list) const { return *std::max_element(list.begin(), list.end(), [this](WorldPosition* i, WorldPosition* j) {return this->distance(*i) < this->distance(*j); }); } + WorldPosition furtest(const vector& list) const { return *std::max_element(list.begin(), list.end(), [this](WorldPosition i, WorldPosition j) {return this->distance(i) < this->distance(j); }); } + + template + pair closest(const list>& list) const { return *std::min_element(list.begin(), list.end(), [this](pair i, pair j) {return this->distance(i.second) < this->distance(j.second); }); } + template + pair closest(const list& list) const { return closest(GetPosList(list)); } + + template + pair closest(const vector>& list) const { return *std::min_element(list.begin(), list.end(), [this](pair i, pair j) {return this->distance(i.second) < this->distance(j.second); }); } + template + pair closest(const vector& list) const { return closest(GetPosVector(list)); } + + + //Quick square distance in 2d plane. + float sqDistance2d(const WorldPosition& to) const { return (coord_x - to.coord_x) * (coord_x - to.coord_x) + (coord_y - to.coord_y) * (coord_y - to.coord_y); }; + + //Quick square distance calculation without map check. Used for getting the minimum distant points. + float sqDistance(const WorldPosition& to) const { return (coord_x - to.coord_x) * (coord_x - to.coord_x) + (coord_y - to.coord_y) * (coord_y - to.coord_y) + (coord_z - to.coord_z) * (coord_z - to.coord_z); }; + + //Returns the closest point of the list. Fast but only works for the same map. + WorldPosition* closestSq(const vector& list) const { return *std::min_element(list.begin(), list.end(), [this](WorldPosition* i, WorldPosition* j) {return sqDistance(*i) < sqDistance(*j); }); } + WorldPosition closestSq(const vector& list) const { return *std::min_element(list.begin(), list.end(), [this](WorldPosition i, WorldPosition j) {return sqDistance(i) < sqDistance(j); }); } + + float getAngleTo(const WorldPosition& endPos) const { float ang = atan2(endPos.coord_y - coord_y, endPos.coord_x - coord_x); return (ang >= 0) ? ang : 2 * M_PI_F + ang; }; + float getAngleBetween(const WorldPosition& dir1, const WorldPosition& dir2) const { return abs(getAngleTo(dir1) - getAngleTo(dir2)); }; + + WorldPosition limit(const WorldPosition& center, const float maxDistance) { WorldPosition pos(*this); pos -= center; float size = pos.size(); if (size > maxDistance) { pos /= pos.size(); pos *= maxDistance; pos += center; } return pos; } + + WorldPosition lastInRange(const vector& list, const float minDist = -1, const float maxDist = -1) const; + WorldPosition firstOutRange(const vector& list, const float minDist = -1, const float maxDist = -1) const; + + float mSign(const WorldPosition* p1, const WorldPosition* p2) const { return(coord_x - p2->coord_x) * (p1->coord_y - p2->coord_y) - (p1->coord_x - p2->coord_x) * (coord_y - p2->coord_y); } + bool isInside(const WorldPosition* p1, const WorldPosition* p2, const WorldPosition* p3) const; + + void distancePartition(const vector& distanceLimits, WorldPosition* to, vector>& partition) const; + vector> distancePartition(const vector& distanceLimits, vector points) const; + + //Map functions. Player independent. + const MapEntry* getMapEntry() const { return sMapStore.LookupEntry(mapid); } + uint32 getInstanceId() const { for (auto& map : sMapMgr.Maps()) { if (map.second->GetId() == getMapId()) return map.second->GetInstanceId(); }; return 0; } + Map* getMap() const { return sMapMgr.FindMap(mapid, getMapEntry()->Instanceable() ? getInstanceId() : 0); } + const TerrainInfo* getTerrain() const { return getMap() ? getMap()->GetTerrain() : NULL; } + +#if defined(MANGOSBOT_TWO) || MAX_EXPANSION == 2 + bool IsInLineOfSight(WorldPosition pos, float heightMod = 0.5f) const { return mapid == pos.mapid && getMap() && getMap()->IsInLineOfSight(coord_x, coord_y, coord_z + heightMod, pos.coord_x, pos.coord_y, pos.coord_z + heightMod, 0, true); } +#else + bool IsInLineOfSight(WorldPosition pos, float heightMod = 0.5f) const { return mapid == pos.mapid && getMap() && getMap()->IsInLineOfSight(coord_x, coord_y, coord_z + heightMod, pos.coord_x, pos.coord_y, pos.coord_z + heightMod, true); } +#endif + + bool isOutside() const { WorldPosition high(*this); high.setZ(coord_z + 500.0f); return IsInLineOfSight(high); } + bool canFly() const; + +#if defined(MANGOSBOT_TWO) || MAX_EXPANSION == 2 + const float getHeight() const { return getMap()->GetHeight(0, coord_x, coord_y, coord_z); } +#else + float getHeight() const { return getMap() ? getMap()->GetHeight(coord_x, coord_y, coord_z) : coord_z; } +#endif + + float currentHeight() const { return coord_z - getHeight(); } + + std::set getTransports(uint32 entry = 0); + + GridPair getGridPair() const { return MaNGOS::ComputeGridPair(coord_x, coord_y); }; + std::vector getGridPairs(const WorldPosition& secondPos) const; + vector fromGridPair(const GridPair& gridPair) const; + + CellPair getCellPair() const { return MaNGOS::ComputeCellPair(coord_x, coord_y); } + vector fromCellPair(const CellPair& cellPair) const; + vector gridFromCellPair(const CellPair& cellPair) const; + + mGridPair getmGridPair() const { + return make_pair((int)(32 - coord_x / SIZE_OF_GRIDS), (int)(32 - coord_y / SIZE_OF_GRIDS)); } + + vector getmGridPairs(const WorldPosition& secondPos) const; + vector frommGridPair(const mGridPair& gridPair) const; + + void loadMapAndVMap(uint32 mapId, uint32 instanceId, int x, int y) const; + void loadMapAndVMap(uint32 instanceId) const {loadMapAndVMap(getMapId(), instanceId, getmGridPair().first, getmGridPair().second); } + void loadMapAndVMaps(const WorldPosition& secondPos, uint32 instanceId) const; + + //Display functions + WorldPosition getDisplayLocation() const; + float getDisplayX() const { return getDisplayLocation().coord_y * -1.0; } + float getDisplayY() const { return getDisplayLocation().coord_x; } + + bool isValid() const { return MaNGOS::IsValidMapCoord(coord_x, coord_y, coord_z, orientation); }; + uint16 getAreaFlag() const { return isValid() ? sTerrainMgr.GetAreaFlag(getMapId(), coord_x, coord_y, coord_z) : 0; }; + AreaTableEntry const* getArea() const; + string getAreaName(const bool fullName = true, const bool zoneName = false) const; + int32 getAreaLevel() const; + + vector fromPointsArray(const std::vector& path) const; + + //Pathfinding + vector getPathStepFrom(const WorldPosition& startPos, const Unit* bot) const; + vector getPathFromPath(const vector& startPath, const Unit* bot, const uint8 maxAttempt = 40) const; + vector getPathFrom(const WorldPosition& startPos, const Unit* bot) { return getPathFromPath({ startPos }, bot); }; + vector getPathTo(WorldPosition endPos, const Unit* bot) const { return endPos.getPathFrom(*this, bot); } + bool isPathTo(const vector& path, float const maxDistance = sPlayerbotAIConfig.targetPosRecalcDistance) const { return !path.empty() && distance(path.back()) < maxDistance; }; + bool cropPathTo(vector& path, const float maxDistance = sPlayerbotAIConfig.targetPosRecalcDistance) const; + bool canPathTo(const WorldPosition& endPos, const Unit* bot) const { return endPos.isPathTo(getPathTo(endPos, bot)); } + + float getPathLength(const vector& points) const { float dist = 0.0f; for (auto& p : points) if (&p == &points.front()) dist = 0; else dist += std::prev(&p, 1)->distance(p); return dist; } + + bool GetReachableRandomPointOnGround(const Player* bot,const float radius, const bool randomRange = true) { +#ifndef MANGOSBOT_TWO + return getMap()->GetReachableRandomPointOnGround(coord_x, coord_y, coord_z, radius, randomRange); +#else + return getMap()->GetReachableRandomPointOnGround(bot->GetPhaseMask(), coord_x, coord_y, coord_z, radius, randomRange); +#endif + } + + uint32 getUnitsNear(const list& units, const float radius) const; + uint32 getUnitsAggro(const list& units, const Player* bot) const; + + //Creatures + vector getCreaturesNear(const float radius = 0, const uint32 entry = 0) const; + //GameObjects + vector getGameObjectsNear(const float radius = 0, const uint32 entry = 0) const; + }; + + inline ByteBuffer& operator<<(ByteBuffer& b, WorldPosition& guidP) + { + b << guidP.getMapId(); + b << guidP.coord_x; + b << guidP.coord_y; + b << guidP.coord_z; + b << guidP.orientation; + return b; + } + + inline ByteBuffer& operator>>(ByteBuffer& b, WorldPosition& g) + { + uint32 mapid; + float coord_x; + float coord_y; + float coord_z; + float orientation; + b >> mapid; + b >> coord_x; + b >> coord_y; + b >> coord_z; + b >> orientation; + + return b; + } + + //Generic creature finder + class FindPointCreatureData + { + public: + FindPointCreatureData(WorldPosition point1 = WorldPosition(), float radius1 = 0, uint32 entry1 = 0) { point = point1; radius = radius1; entry = entry1; } + + bool operator()(CreatureDataPair const& dataPair); + vector GetResult() const { return data; }; + private: + WorldPosition point; + float radius; + uint32 entry; + + vector data; + }; + + //Generic gameObject finder + class FindPointGameObjectData + { + public: + FindPointGameObjectData(WorldPosition point1 = WorldPosition(), float radius1 = 0, uint32 entry1 = 0) { point = point1; radius = radius1; entry = entry1; } + + bool operator()(GameObjectDataPair const& dataPair); + vector GetResult() const { return data; }; + private: + WorldPosition point; + float radius; + uint32 entry; + + vector data; + }; +} \ No newline at end of file diff --git a/playerbot/strategy/actions/ChooseTargetActions.cpp b/playerbot/strategy/actions/ChooseTargetActions.cpp index b6d8de1c0..8ff05f68e 100644 --- a/playerbot/strategy/actions/ChooseTargetActions.cpp +++ b/playerbot/strategy/actions/ChooseTargetActions.cpp @@ -4,6 +4,7 @@ #include "ChooseTargetActions.h" #include "MovementGenerator.h" #include "CreatureAI.h" +#include "../../TravelMgr.h" bool DpsAssistAction::isUseful() { diff --git a/playerbot/strategy/actions/ChooseTargetActions.h b/playerbot/strategy/actions/ChooseTargetActions.h index 8e64ba284..cfe2dc829 100644 --- a/playerbot/strategy/actions/ChooseTargetActions.h +++ b/playerbot/strategy/actions/ChooseTargetActions.h @@ -4,7 +4,6 @@ #include "AttackAction.h" #include "../../ServerFacade.h" #include "../../playerbot.h" -#include "../../TravelMgr.h" #include "../../LootObjectStack.h" #include "ChooseRpgTargetAction.h" diff --git a/playerbot/strategy/actions/ChooseTravelTargetAction.cpp b/playerbot/strategy/actions/ChooseTravelTargetAction.cpp index ce20b5580..3931fdf74 100644 --- a/playerbot/strategy/actions/ChooseTravelTargetAction.cpp +++ b/playerbot/strategy/actions/ChooseTravelTargetAction.cpp @@ -3,6 +3,7 @@ #include "../../LootObjectStack.h" #include "ChooseTravelTargetAction.h" #include "../../PlayerbotAIConfig.h" +#include "../../TravelMgr.h" #include using namespace ai; diff --git a/playerbot/strategy/actions/ChooseTravelTargetAction.h b/playerbot/strategy/actions/ChooseTravelTargetAction.h index 52bed3b11..50555fb67 100644 --- a/playerbot/strategy/actions/ChooseTravelTargetAction.h +++ b/playerbot/strategy/actions/ChooseTravelTargetAction.h @@ -2,10 +2,12 @@ #include "../Action.h" #include "MovementActions.h" -#include "../../TravelMgr.h" namespace ai { + class TravelTarget; + class TravelDestination; + class ChooseTravelTargetAction : public MovementAction { public: ChooseTravelTargetAction(PlayerbotAI* ai, string name = "choose travel target") : MovementAction(ai, name) {} diff --git a/playerbot/strategy/actions/DebugAction.cpp b/playerbot/strategy/actions/DebugAction.cpp index 29ab9c207..cd03b6f66 100644 --- a/playerbot/strategy/actions/DebugAction.cpp +++ b/playerbot/strategy/actions/DebugAction.cpp @@ -7,6 +7,7 @@ #include "strategy/values/SharedValueContext.h" #include "../../LootObjectStack.h" #include "../../../game/GameEvents/GameEventMgr.h" +#include "../../TravelMgr.h" using namespace ai; diff --git a/playerbot/strategy/actions/DebugAction.h b/playerbot/strategy/actions/DebugAction.h index c7bfe4b2c..6d1ba0601 100644 --- a/playerbot/strategy/actions/DebugAction.h +++ b/playerbot/strategy/actions/DebugAction.h @@ -1,5 +1,4 @@ #pragma once -#include "../../TravelMgr.h" #include "GenericActions.h" namespace ai diff --git a/playerbot/strategy/actions/GoAction.cpp b/playerbot/strategy/actions/GoAction.cpp index bd9401e4b..52e38846e 100644 --- a/playerbot/strategy/actions/GoAction.cpp +++ b/playerbot/strategy/actions/GoAction.cpp @@ -8,6 +8,7 @@ #include "TravelMgr.h" #include "MotionGenerators/PathFinder.h" #include "ChooseTravelTargetAction.h" +#include "../../TravelMgr.h" using namespace ai; diff --git a/playerbot/strategy/actions/GoAction.h b/playerbot/strategy/actions/GoAction.h index a131fc29e..2fab7f36c 100644 --- a/playerbot/strategy/actions/GoAction.h +++ b/playerbot/strategy/actions/GoAction.h @@ -3,6 +3,8 @@ namespace ai { + class TravelDestination; + class GoAction : public MovementAction { public: diff --git a/playerbot/strategy/actions/GuildCreateActions.cpp b/playerbot/strategy/actions/GuildCreateActions.cpp index f10266ada..5c93dbed3 100644 --- a/playerbot/strategy/actions/GuildCreateActions.cpp +++ b/playerbot/strategy/actions/GuildCreateActions.cpp @@ -11,6 +11,7 @@ #endif #endif #include "ServerFacade.h" +#include "TravelMgr.h" using namespace std; using namespace ai; @@ -275,6 +276,27 @@ bool PetitionTurnInAction::Execute(Event& event) return true; }; +bool PetitionTurnInAction::isUseful() +{ + if (!ai->HasStrategy("travel", BotState::BOT_STATE_NON_COMBAT)) + return false; + + if (!ChooseTravelTargetAction::isUseful()) + return false; + + bool inCity = false; + AreaTableEntry const* areaEntry = GetAreaEntryByAreaID(sServerFacade.GetAreaId(bot)); + if (areaEntry) + { + if (areaEntry->zone) + areaEntry = GetAreaEntryByAreaID(areaEntry->zone); + + if (areaEntry && areaEntry->flags & AREA_FLAG_CAPITAL) + inCity = true; + } + + return inCity && !bot->GetGuildId() && AI_VALUE2(uint32, "item count", chat->formatQItem(5863)) && AI_VALUE(uint8, "petition signs") >= sWorld.getConfig(CONFIG_UINT32_MIN_PETITION_SIGNS) && !context->GetValue("travel target")->Get()->isTraveling(); +}; bool BuyTabardAction::Execute(Event& event) { @@ -298,4 +320,26 @@ bool BuyTabardAction::Execute(Event& event) setNewTarget(&newTarget, oldTarget); return true; +}; + +bool BuyTabardAction::isUseful() +{ + if (!ai->HasStrategy("travel", BotState::BOT_STATE_NON_COMBAT)) + return false; + + if (!ChooseTravelTargetAction::isUseful()) + return false; + + bool inCity = false; + AreaTableEntry const* areaEntry = GetAreaEntryByAreaID(sServerFacade.GetAreaId(bot)); + if (areaEntry) + { + if (areaEntry->zone) + areaEntry = GetAreaEntryByAreaID(areaEntry->zone); + + if (areaEntry && areaEntry->flags & AREA_FLAG_CAPITAL) + inCity = true; + } + + return inCity && bot->GetGuildId() && !AI_VALUE2(uint32, "item count", chat->formatQItem(5976)) && AI_VALUE2(uint32, "free money for", uint32(NeedMoneyFor::guild)) >= 10000 && !context->GetValue("travel target")->Get()->isTraveling(); }; \ No newline at end of file diff --git a/playerbot/strategy/actions/GuildCreateActions.h b/playerbot/strategy/actions/GuildCreateActions.h index 7b6370d8b..0e126e7ff 100644 --- a/playerbot/strategy/actions/GuildCreateActions.h +++ b/playerbot/strategy/actions/GuildCreateActions.h @@ -5,6 +5,8 @@ namespace ai { + class TravelTarget; + class BuyPetitionAction : public Action { public: @@ -35,27 +37,7 @@ namespace ai public: PetitionTurnInAction(PlayerbotAI* ai) : ChooseTravelTargetAction(ai, "turn in petition") {} virtual bool Execute(Event& event); - virtual bool isUseful() - { - if (!ai->HasStrategy("travel", BotState::BOT_STATE_NON_COMBAT)) - return false; - - if (!ChooseTravelTargetAction::isUseful()) - return false; - - bool inCity = false; - AreaTableEntry const* areaEntry = GetAreaEntryByAreaID(sServerFacade.GetAreaId(bot)); - if (areaEntry) - { - if (areaEntry->zone) - areaEntry = GetAreaEntryByAreaID(areaEntry->zone); - - if (areaEntry && areaEntry->flags & AREA_FLAG_CAPITAL) - inCity = true; - } - - return inCity && !bot->GetGuildId() && AI_VALUE2(uint32, "item count", chat->formatQItem(5863)) && AI_VALUE(uint8, "petition signs") >= sWorld.getConfig(CONFIG_UINT32_MIN_PETITION_SIGNS) && !context->GetValue("travel target")->Get()->isTraveling(); - }; + virtual bool isUseful(); }; class BuyTabardAction : public ChooseTravelTargetAction @@ -63,26 +45,6 @@ namespace ai public: BuyTabardAction(PlayerbotAI* ai) : ChooseTravelTargetAction(ai, "buy tabard") {} virtual bool Execute(Event& event); - virtual bool isUseful() - { - if (!ai->HasStrategy("travel", BotState::BOT_STATE_NON_COMBAT)) - return false; - - if (!ChooseTravelTargetAction::isUseful()) - return false; - - bool inCity = false; - AreaTableEntry const* areaEntry = GetAreaEntryByAreaID(sServerFacade.GetAreaId(bot)); - if (areaEntry) - { - if (areaEntry->zone) - areaEntry = GetAreaEntryByAreaID(areaEntry->zone); - - if (areaEntry && areaEntry->flags & AREA_FLAG_CAPITAL) - inCity = true; - } - - return inCity && bot->GetGuildId() && !AI_VALUE2(uint32, "item count", chat->formatQItem(5976)) && AI_VALUE2(uint32, "free money for", uint32(NeedMoneyFor::guild)) >= 10000 && !context->GetValue("travel target")->Get()->isTraveling(); - }; + virtual bool isUseful(); }; } diff --git a/playerbot/strategy/actions/MoveToTravelTargetAction.cpp b/playerbot/strategy/actions/MoveToTravelTargetAction.cpp index 42323b6c9..0f8d39c14 100644 --- a/playerbot/strategy/actions/MoveToTravelTargetAction.cpp +++ b/playerbot/strategy/actions/MoveToTravelTargetAction.cpp @@ -6,6 +6,7 @@ #include "../../LootObjectStack.h" #include "MotionGenerators/PathFinder.h" #include "ChooseRpgTargetAction.h" +#include "../../TravelMgr.h" using namespace ai; diff --git a/playerbot/strategy/actions/MoveToTravelTargetAction.h b/playerbot/strategy/actions/MoveToTravelTargetAction.h index c53a51ab6..f6bfefc29 100644 --- a/playerbot/strategy/actions/MoveToTravelTargetAction.h +++ b/playerbot/strategy/actions/MoveToTravelTargetAction.h @@ -3,7 +3,6 @@ #include "../Action.h" #include "MovementActions.h" #include "../values/LastMovementValue.h" -#include "../../TravelMgr.h" namespace ai { diff --git a/playerbot/strategy/actions/ReviveFromCorpseAction.cpp b/playerbot/strategy/actions/ReviveFromCorpseAction.cpp index 97d62d960..f358bfecb 100644 --- a/playerbot/strategy/actions/ReviveFromCorpseAction.cpp +++ b/playerbot/strategy/actions/ReviveFromCorpseAction.cpp @@ -4,6 +4,7 @@ #include "../../PlayerbotFactory.h" #include "../../PlayerbotAIConfig.h" #include "../../FleeManager.h" +#include "../../TravelMgr.h" #include "ServerFacade.h" using namespace ai; diff --git a/playerbot/strategy/actions/RpgAction.cpp b/playerbot/strategy/actions/RpgAction.cpp index f6fa75ca2..9fcecd62d 100644 --- a/playerbot/strategy/actions/RpgAction.cpp +++ b/playerbot/strategy/actions/RpgAction.cpp @@ -5,6 +5,7 @@ #include "../values/Formations.h" #include "EmoteAction.h" #include "RpgSubActions.h" +#include "../../TravelMgr.h" using namespace ai; diff --git a/playerbot/strategy/actions/RpgSubActions.cpp b/playerbot/strategy/actions/RpgSubActions.cpp index ce14e332a..98402075c 100644 --- a/playerbot/strategy/actions/RpgSubActions.cpp +++ b/playerbot/strategy/actions/RpgSubActions.cpp @@ -9,6 +9,7 @@ #include "GossipDef.h" #include "GuildCreateActions.h" #include "SocialMgr.h" +#include "../../TravelMgr.h" using namespace ai; diff --git a/playerbot/strategy/actions/TravelAction.cpp b/playerbot/strategy/actions/TravelAction.cpp index 3954fd519..b16227c07 100644 --- a/playerbot/strategy/actions/TravelAction.cpp +++ b/playerbot/strategy/actions/TravelAction.cpp @@ -7,6 +7,7 @@ #include "GridNotifiersImpl.h" #include "CellImpl.h" #include "World/WorldState.h" +#include "../../TravelMgr.h" using namespace ai; diff --git a/playerbot/strategy/actions/TravelAction.h b/playerbot/strategy/actions/TravelAction.h index 8d6f5136c..f67eb7fa0 100644 --- a/playerbot/strategy/actions/TravelAction.h +++ b/playerbot/strategy/actions/TravelAction.h @@ -3,7 +3,6 @@ #include "../Action.h" #include "MovementActions.h" #include "../values/LastMovementValue.h" -#include "../../TravelMgr.h" namespace ai { diff --git a/playerbot/strategy/triggers/RpgTriggers.cpp b/playerbot/strategy/triggers/RpgTriggers.cpp index fe27f8252..518999db3 100644 --- a/playerbot/strategy/triggers/RpgTriggers.cpp +++ b/playerbot/strategy/triggers/RpgTriggers.cpp @@ -8,9 +8,15 @@ #include "SocialMgr.h" #include "../../ServerFacade.h" #include "../values/ItemUsageValue.h" +#include "../../TravelMgr.h" using namespace ai; +bool RpgTrigger::IsActive() +{ + return !ai->HasRealPlayerMaster() || (AI_VALUE(GuidPosition, "rpg target").GetEntry() && AI_VALUE(GuidPosition, "rpg target").GetEntry() == AI_VALUE(TravelTarget*, "travel target")->getEntry()); +}; + bool RpgTaxiTrigger::IsActive() { GuidPosition guidP(getGuidP()); diff --git a/playerbot/strategy/triggers/RpgTriggers.h b/playerbot/strategy/triggers/RpgTriggers.h index e517e3d13..e721921fd 100644 --- a/playerbot/strategy/triggers/RpgTriggers.h +++ b/playerbot/strategy/triggers/RpgTriggers.h @@ -1,6 +1,5 @@ #pragma once #include "../Trigger.h" -#include "../../TravelMgr.h" namespace ai { @@ -51,7 +50,7 @@ namespace ai GuidPosition getGuidP() { return AI_VALUE(GuidPosition, "rpg target"); } - virtual bool IsActive() { return !ai->HasRealPlayerMaster() || (AI_VALUE(GuidPosition, "rpg target").GetEntry() && AI_VALUE(GuidPosition, "rpg target").GetEntry() == AI_VALUE(TravelTarget*, "travel target")->getEntry()); }; + virtual bool IsActive(); virtual Event Check() { if (!NoRpgTargetTrigger::IsActive() && (AI_VALUE(string, "next rpg action") == "choose rpg target" || !FarFromRpgTargetTrigger::IsActive())) return Trigger::Check(); return Event(); }; }; diff --git a/playerbot/strategy/triggers/StuckTriggers.h b/playerbot/strategy/triggers/StuckTriggers.h index 97503c34f..cdbbcdf17 100644 --- a/playerbot/strategy/triggers/StuckTriggers.h +++ b/playerbot/strategy/triggers/StuckTriggers.h @@ -1,7 +1,6 @@ #pragma once #include "../Trigger.h" #include -#include "../../TravelMgr.h" namespace ai { diff --git a/playerbot/strategy/values/LastMovementValue.h b/playerbot/strategy/values/LastMovementValue.h index 1b8f4bc38..08256e509 100644 --- a/playerbot/strategy/values/LastMovementValue.h +++ b/playerbot/strategy/values/LastMovementValue.h @@ -1,7 +1,6 @@ #pragma once #include "../Value.h" #include "TravelNode.h" -#include "../../TravelMgr.h" namespace ai { diff --git a/playerbot/strategy/values/PositionValue.h b/playerbot/strategy/values/PositionValue.h index 92259d8eb..e927b8fd2 100644 --- a/playerbot/strategy/values/PositionValue.h +++ b/playerbot/strategy/values/PositionValue.h @@ -1,6 +1,5 @@ #pragma once #include "../Value.h" -#include "../../TravelMgr.h" namespace ai { diff --git a/playerbot/strategy/values/QuestValues.h b/playerbot/strategy/values/QuestValues.h index 3a0e6fc4b..543a9662e 100644 --- a/playerbot/strategy/values/QuestValues.h +++ b/playerbot/strategy/values/QuestValues.h @@ -1,7 +1,6 @@ #pragma once #include "../Value.h" #include "LootValues.h" -#include "../../TravelMgr.h" namespace ai { diff --git a/playerbot/strategy/values/RTSCValues.h b/playerbot/strategy/values/RTSCValues.h index 0bc728645..793213a5e 100644 --- a/playerbot/strategy/values/RTSCValues.h +++ b/playerbot/strategy/values/RTSCValues.h @@ -1,6 +1,5 @@ #pragma once #include "../Value.h" -#include "../../TravelMgr.h" namespace ai {