diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json
index ea659ebfe1..ed955ab619 100644
--- a/.devcontainer/devcontainer.json
+++ b/.devcontainer/devcontainer.json
@@ -33,7 +33,8 @@
"mhutchie.git-graph",
"github.vscode-pull-request-github",
"eamodio.gitlens",
- "cschlosser.doxdocgen"
+ "cschlosser.doxdocgen",
+ "sanaajani.taskrunnercode"
],
// Use 'forwardPorts' to make a list of ports inside the container available locally.
diff --git a/.dockerignore b/.dockerignore
index 44c4511bc4..ea6c901b71 100644
--- a/.dockerignore
+++ b/.dockerignore
@@ -1,13 +1,20 @@
/cmake-build-debug/*
/build*/
/var/*
+!/var/build/.gitkeep
+!/var/ccache/.gitkeep
/env/dist/*
+!/env/dist/.gitkeep
/env/user/*
-/env/docker/data/*
-/env/docker/logs/*
-/env/docker/etc/*
+/env/docker/*
+!/env/docker/bin/.gitkeep
+!/env/docker/data/.gitkeep
!/env/docker/etc/authserver.conf.dockerdist
!/env/docker/etc/worldserver.conf.dockerdist
+!/env/docker/logs/.gitkeep
/.env*
.idea
!.gitkeep
+
+# do not ignore the ccache folder (used by the ci)
+!/var/docker/ccache
diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md
index 89d0cd999c..11bd83499c 100644
--- a/.github/ISSUE_TEMPLATE/bug_report.md
+++ b/.github/ISSUE_TEMPLATE/bug_report.md
@@ -7,91 +7,40 @@ assignees: ''
---
-
+
-
+**CURRENT BEHAVIOUR:**
+
+**EXPECTED BLIZZLIKE BEHAVIOUR:**
+
-## CURRENT BEHAVIOUR:
-
+**SOURCE:**
+
-
-
-
-## EXPECTED BLIZZLIKE BEHAVIOUR:
-
-
-
-
-
-## SOURCE:
-
-
-
-
-
-## STEPS TO REPRODUCE THE PROBLEM:
-
+**STEPS TO REPRODUCE THE PROBLEM:**
+
1.
2.
3.
-## EXTRA NOTES:
-
+**EXTRA NOTES:**
+
+**AC HASH/COMMIT:**
+
+**OPERATING SYSTEM:**
+
+**MODULES:**
+
-## AC HASH/COMMIT:
-
-
-
-
-
-## OPERATING SYSTEM:
-
-
-
-
-
-## MODULES:
-
-
-
-
-
-## CUSTOMIZATIONS:
-
-
-
-
+**CUSTOMIZATIONS:**
+
-
+
## Changes Proposed:
-
-
-
## Issues Addressed:
+
- Closes
-
-
## SOURCE:
-
-
+
## Tests Performed:
-
+
-
-
## How to Test the Changes:
-
+
+1.
+2.
+3.
## Known Issues and TODO List:
-
+
+
+- [ ]
- [ ]
-- [ ]
-
-## Target Branch(es):
-- [x] Master
-
-
-
-
-
-
-
-
+
## How to Test AzerothCore PRs
When a PR is ready to be tested, it will be marked as **[WAITING TO BE TESTED]**.
diff --git a/src/cmake/compiler/clang/settings.cmake b/src/cmake/compiler/clang/settings.cmake
index fecfb2edc4..b3eb165f60 100644
--- a/src/cmake/compiler/clang/settings.cmake
+++ b/src/cmake/compiler/clang/settings.cmake
@@ -3,6 +3,12 @@
# Copyright (C) 2008-2019 TrinityCore
#
+if ((USE_COREPCH OR USE_SCRIPTPCH) AND (CMAKE_C_COMPILER_LAUNCHER STREQUAL "ccache" OR CMAKE_CXX_COMPILER_LAUNCHER STREQUAL "ccache"))
+ message(STATUS "Clang: disable pch timestamp when ccache and pch enabled")
+ # TODO: for ccache https://github.com/ccache/ccache/issues/539
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Xclang -fno-pch-timestamp")
+endif()
+
# Set build-directive (used in core to tell which buildtype we used)
target_compile_definitions(acore-compile-option-interface
INTERFACE
diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt
index d06edcaf3b..ebd34fe98f 100644
--- a/src/common/CMakeLists.txt
+++ b/src/common/CMakeLists.txt
@@ -49,8 +49,6 @@ target_include_directories(common
${CMAKE_CURRENT_BINARY_DIR})
target_link_libraries(common
- PRIVATE
- game-interface
PUBLIC
acore-core-interface
ace
diff --git a/src/common/Collision/DynamicTree.cpp b/src/common/Collision/DynamicTree.cpp
index c7f8c87d2e..2af4d36587 100644
--- a/src/common/Collision/DynamicTree.cpp
+++ b/src/common/Collision/DynamicTree.cpp
@@ -5,16 +5,12 @@
*/
#include "DynamicTree.h"
-//#include "QuadTree.h"
-//#include "RegularGrid.h"
#include "BoundingIntervalHierarchyWrapper.h"
-
#include "Log.h"
#include "RegularGrid.h"
#include "Timer.h"
#include "GameObjectModel.h"
#include "ModelInstance.h"
-
#include
#include
#include
@@ -23,10 +19,8 @@ using VMAP::ModelInstance;
namespace
{
-
int CHECK_TREE_PERIOD = 200;
-
-} // namespace
+}
template<> struct HashTrait< GameObjectModel>
{
@@ -44,15 +38,9 @@ template<> struct BoundsTrait< GameObjectModel>
static void getBounds2(const GameObjectModel* g, G3D::AABox& out) { out = g->getBounds();}
};
-/*
-static bool operator == (const GameObjectModel& mdl, const GameObjectModel& mdl2){
- return &mdl == &mdl2;
-}
-*/
-
typedef RegularGrid2D> ParentTree;
-struct DynTreeImpl : public ParentTree/*, public Intersectable*/
+struct DynTreeImpl : public ParentTree
{
typedef GameObjectModel Model;
typedef ParentTree base;
diff --git a/src/common/Collision/Management/IMMAPManager.h b/src/common/Collision/Management/IMMAPManager.h
index ec05fc0bdd..a558ab2c0b 100644
--- a/src/common/Collision/Management/IMMAPManager.h
+++ b/src/common/Collision/Management/IMMAPManager.h
@@ -35,4 +35,4 @@ namespace MMAP
};
}
-#endif
\ No newline at end of file
+#endif
diff --git a/src/common/Collision/Management/IVMapManager.h b/src/common/Collision/Management/IVMapManager.h
index aa5cd6037e..7d999c779b 100644
--- a/src/common/Collision/Management/IVMapManager.h
+++ b/src/common/Collision/Management/IVMapManager.h
@@ -18,7 +18,6 @@ This is the minimum interface to the VMapMamager.
namespace VMAP
{
-
enum VMAP_LOAD_RESULT
{
VMAP_LOAD_RESULT_ERROR,
@@ -83,6 +82,6 @@ namespace VMAP
virtual bool getAreaInfo(unsigned int pMapId, float x, float y, float& z, uint32& flags, int32& adtId, int32& rootId, int32& groupId) const = 0;
virtual bool GetLiquidLevel(uint32 pMapId, float x, float y, float z, uint8 ReqLiquidType, float& level, float& floor, uint32& type) const = 0;
};
-
}
+
#endif
diff --git a/src/common/Collision/Management/MMapFactory.cpp b/src/common/Collision/Management/MMapFactory.cpp
index b5ea34a506..78dd941f87 100644
--- a/src/common/Collision/Management/MMapFactory.cpp
+++ b/src/common/Collision/Management/MMapFactory.cpp
@@ -5,7 +5,6 @@
*/
#include "MMapFactory.h"
-#include "World.h"
#include
namespace MMAP
@@ -23,12 +22,6 @@ namespace MMAP
return g_MMapManager;
}
- bool MMapFactory::IsPathfindingEnabled(const Map* map)
- {
- if (!map) return false;
- return !forbiddenMaps[map->GetId()] && (sWorld->getBoolConfig(CONFIG_ENABLE_MMAPS) ? true : map->IsBattlegroundOrArena());
- }
-
void MMapFactory::InitializeDisabledMaps()
{
memset(&forbiddenMaps, 0, sizeof(forbiddenMaps));
@@ -46,4 +39,4 @@ namespace MMAP
g_MMapManager = nullptr;
}
}
-}
\ No newline at end of file
+}
diff --git a/src/common/Collision/Management/MMapFactory.h b/src/common/Collision/Management/MMapFactory.h
index 30d440870d..b25ccce698 100644
--- a/src/common/Collision/Management/MMapFactory.h
+++ b/src/common/Collision/Management/MMapFactory.h
@@ -10,8 +10,7 @@
#include "MMapManager.h"
#include "DetourAlloc.h"
#include "DetourNavMesh.h"
-#include "Navigation/DetourExtended.h"
-#include "Map.h"
+#include "DetourExtended.h"
#include
namespace MMAP
@@ -31,7 +30,6 @@ namespace MMAP
public:
static MMapManager* createOrGetMMapManager();
static void clear();
- static bool IsPathfindingEnabled(const Map* map);
static void InitializeDisabledMaps();
static bool forbiddenMaps[1000];
};
diff --git a/src/common/Collision/Management/MMapManager.cpp b/src/common/Collision/Management/MMapManager.cpp
index 1ccb133229..40fa342779 100644
--- a/src/common/Collision/Management/MMapManager.cpp
+++ b/src/common/Collision/Management/MMapManager.cpp
@@ -4,9 +4,10 @@
* Copyright (C) 2005-2009 MaNGOS
*/
-#include "Config.h"
-#include "MapManager.h"
#include "MMapManager.h"
+#include "Config.h"
+#include "Errors.h"
+#include "MapDefines.h"
#include "Log.h"
#include "StringFormat.h"
@@ -25,11 +26,41 @@ namespace MMAP
// if we had, tiles in MMapData->mmapLoadedTiles, their actual data is lost!
}
+ void MMapManager::InitializeThreadUnsafe(const std::vector& mapIds)
+ {
+ // the caller must pass the list of all mapIds that will be used in the VMapManager2 lifetime
+ for (const uint32& mapId : mapIds)
+ loadedMMaps.emplace(mapId, nullptr);
+
+ thread_safe_environment = false;
+ }
+
+ MMapDataSet::const_iterator MMapManager::GetMMapData(uint32 mapId) const
+ {
+ // return the iterator if found or end() if not found/NULL
+ MMapDataSet::const_iterator itr = loadedMMaps.find(mapId);
+ if (itr != loadedMMaps.cend() && !itr->second)
+ itr = loadedMMaps.cend();
+
+ return itr;
+ }
+
bool MMapManager::loadMapData(uint32 mapId)
{
// we already have this map loaded?
- if (loadedMMaps.find(mapId) != loadedMMaps.end())
- return true;
+ MMapDataSet::iterator itr = loadedMMaps.find(mapId);
+ if (itr != loadedMMaps.end())
+ {
+ if (itr->second)
+ return true;
+ }
+ else
+ {
+ if (thread_safe_environment)
+ itr = loadedMMaps.insert(MMapDataSet::value_type(mapId, nullptr)).first;
+ else
+ ASSERT(false, "Invalid mapId %u passed to MMapManager after startup in thread unsafe environment", mapId);
+ }
// load and init dtNavMesh - read parameters from file
std::string fileName = acore::StringFormat(MAP_FILE_NAME_FORMAT, sConfigMgr->GetOption("DataDir", ".").c_str(), mapId);
@@ -37,18 +68,16 @@ namespace MMAP
FILE* file = fopen(fileName.c_str(), "rb");
if (!file)
{
-#if defined(ENABLE_EXTRAS) && defined(ENABLE_EXTRA_LOGS)
LOG_DEBUG("maps", "MMAP:loadMapData: Error: Could not open mmap file '%s'", fileName.c_str());
-#endif
return false;
}
dtNavMeshParams params;
- int count = fread(¶ms, sizeof(dtNavMeshParams), 1, file);
+ uint32 count = uint32(fread(¶ms, sizeof(dtNavMeshParams), 1, file));
fclose(file);
if (count != 1)
{
- ;//TC_LOG_DEBUG(LOG_FILTER_MAPS, "MMAP:loadMapData: Error: Could not read params from file '%s'", fileName);
+ LOG_DEBUG("maps", "MMAP:loadMapData: Error: Could not read params from file '%s'", fileName.c_str());
return false;
}
@@ -61,15 +90,11 @@ namespace MMAP
return false;
}
-#if defined(ENABLE_EXTRAS) && defined(ENABLE_EXTRA_LOGS)
- LOG_DEBUG("server", "MMAP:loadMapData: Loaded %03i.mmap", mapId);
-#endif
+ LOG_DEBUG("maps", "MMAP:loadMapData: Loaded %03i.mmap", mapId);
// store inside our map list
MMapData* mmap_data = new MMapData(mesh);
- mmap_data->mmapLoadedTiles.clear();
-
- loadedMMaps.insert(std::pair(mapId, mmap_data));
+ itr->second = mmap_data;
return true;
}
@@ -78,22 +103,8 @@ namespace MMAP
return uint32(x << 16 | y);
}
- std::shared_mutex& MMapManager::GetMMapLock(uint32 mapId)
- {
- Map* map = sMapMgr->FindBaseMap(mapId);
- if (!map)
- {
- LOG_INFO("misc", "ZOMG! MoveMaps: BaseMap not found!");
- return this->MMapLock;
- }
-
- return map->GetMMapLock();
- }
-
bool MMapManager::loadMap(uint32 mapId, int32 x, int32 y)
{
- std::unique_lock guard(MMapManagerLock);
-
// make sure the mmap is loaded and ready to load tiles
if (!loadMapData(mapId))
return false;
@@ -104,7 +115,7 @@ namespace MMAP
// check if we already have this tile loaded
uint32 packedGridPos = packTileID(x, y);
- if (mmap->mmapLoadedTiles.find(packedGridPos) != mmap->mmapLoadedTiles.end())
+ if (mmap->loadedTileRefs.find(packedGridPos) != mmap->loadedTileRefs.end())
{
LOG_ERROR("server", "MMAP:loadMap: Asked to load already loaded navmesh tile. %03u%02i%02i.mmtile", mapId, x, y);
return false;
@@ -151,26 +162,18 @@ namespace MMAP
dtTileRef tileRef = 0;
- dtStatus stat;
- {
- std::unique_lock guard(GetMMapLock(mapId));
- stat = mmap->navMesh->addTile(data, fileHeader.size, DT_TILE_FREE_DATA, 0, &tileRef);
- }
-
// memory allocated for data is now managed by detour, and will be deallocated when the tile is removed
- if (stat == DT_SUCCESS)
+ if (dtStatusSucceed(mmap->navMesh->addTile(data, fileHeader.size, DT_TILE_FREE_DATA, 0, &tileRef)))
{
- mmap->mmapLoadedTiles.insert(std::pair(packedGridPos, tileRef));
+ mmap->loadedTileRefs.insert(std::pair(packedGridPos, tileRef));
++loadedTiles;
-#if defined(ENABLE_EXTRAS) && defined(ENABLE_EXTRA_LOGS)
dtMeshHeader* header = (dtMeshHeader*)data;
- LOG_DEBUG("server", "MMAP:loadMap: Loaded mmtile %03i[%02i,%02i] into %03i[%02i,%02i]", mapId, x, y, mapId, header->x, header->y);
-#endif
+ LOG_DEBUG("maps", "MMAP:loadMap: Loaded mmtile %03i[%02i,%02i] into %03i[%02i,%02i]", mapId, x, y, mapId, header->x, header->y);
return true;
}
else
{
- LOG_ERROR("server", "MMAP:loadMap: Could not load %03u%02i%02i.mmtile into navmesh", mapId, x, y);
+ LOG_ERROR("maps", "MMAP:loadMap: Could not load %03u%02i%02i.mmtile into navmesh", mapId, x, y);
dtFree(data);
return false;
}
@@ -180,10 +183,9 @@ namespace MMAP
bool MMapManager::unloadMap(uint32 mapId, int32 x, int32 y)
{
- std::unique_lock guard(MMapManagerLock);
-
// check if we have this map loaded
- if (loadedMMaps.find(mapId) == loadedMMaps.end())
+ MMapDataSet::const_iterator itr = GetMMapData(mapId);
+ if (itr == loadedMMaps.end())
{
// file may not exist, therefore not loaded
#if defined(ENABLE_EXTRAS) && defined(ENABLE_EXTRA_LOGS)
@@ -192,11 +194,11 @@ namespace MMAP
return false;
}
- MMapData* mmap = loadedMMaps[mapId];
+ MMapData* mmap = itr->second;
// check if we have this tile loaded
uint32 packedGridPos = packTileID(x, y);
- if (mmap->mmapLoadedTiles.find(packedGridPos) == mmap->mmapLoadedTiles.end())
+ if (mmap->loadedTileRefs.find(packedGridPos) == mmap->loadedTileRefs.end())
{
// file may not exist, therefore not loaded
#if defined(ENABLE_EXTRAS) && defined(ENABLE_EXTRA_LOGS)
@@ -205,16 +207,10 @@ namespace MMAP
return false;
}
- dtTileRef tileRef = mmap->mmapLoadedTiles[packedGridPos];
-
- dtStatus status;
- {
- std::unique_lock guard(GetMMapLock(mapId));
- status = mmap->navMesh->removeTile(tileRef, nullptr, nullptr);
- }
+ dtTileRef tileRef = mmap->loadedTileRefs[packedGridPos];
// unload, and mark as non loaded
- if (status != DT_SUCCESS)
+ if (dtStatusFailed(mmap->navMesh->removeTile(tileRef, nullptr, nullptr)))
{
// this is technically a memory leak
// if the grid is later reloaded, dtNavMesh::addTile will return error but no extra memory is used
@@ -224,11 +220,9 @@ namespace MMAP
}
else
{
- mmap->mmapLoadedTiles.erase(packedGridPos);
+ mmap->loadedTileRefs.erase(packedGridPos);
--loadedTiles;
-#if defined(ENABLE_EXTRAS) && defined(ENABLE_EXTRA_LOGS)
- LOG_DEBUG("server", "MMAP:unloadMap: Unloaded mmtile %03i[%02i,%02i] from %03i", mapId, x, y, mapId);
-#endif
+ LOG_DEBUG("maps", "MMAP:unloadMap: Unloaded mmtile %03i[%02i,%02i] from %03i", mapId, x, y, mapId);
return true;
}
@@ -237,70 +231,52 @@ namespace MMAP
bool MMapManager::unloadMap(uint32 mapId)
{
- std::unique_lock guard(MMapManagerLock);
-
- if (loadedMMaps.find(mapId) == loadedMMaps.end())
+ MMapDataSet::iterator itr = loadedMMaps.find(mapId);
+ if (itr == loadedMMaps.end() || !itr->second)
{
// file may not exist, therefore not loaded
-#if defined(ENABLE_EXTRAS) && defined(ENABLE_EXTRA_LOGS)
LOG_DEBUG("maps", "MMAP:unloadMap: Asked to unload not loaded navmesh map %03u", mapId);
-#endif
return false;
}
// unload all tiles from given map
- MMapData* mmap = loadedMMaps[mapId];
- for (MMapTileSet::iterator i = mmap->mmapLoadedTiles.begin(); i != mmap->mmapLoadedTiles.end(); ++i)
+ MMapData* mmap = itr->second;
+ for (auto i : mmap->loadedTileRefs)
{
- uint32 x = (i->first >> 16);
- uint32 y = (i->first & 0x0000FFFF);
+ uint32 x = (i.first >> 16);
+ uint32 y = (i.first & 0x0000FFFF);
- dtStatus status;
- {
- std::unique_lock guard(GetMMapLock(mapId));
- status = mmap->navMesh->removeTile(i->second, nullptr, nullptr);
- }
-
- if (status != DT_SUCCESS)
+ if (dtStatusFailed(mmap->navMesh->removeTile(i.second, nullptr, nullptr)))
LOG_ERROR("server", "MMAP:unloadMap: Could not unload %03u%02i%02i.mmtile from navmesh", mapId, x, y);
else
{
--loadedTiles;
-#if defined(ENABLE_EXTRAS) && defined(ENABLE_EXTRA_LOGS)
LOG_DEBUG("server", "MMAP:unloadMap: Unloaded mmtile %03i[%02i,%02i] from %03i", mapId, x, y, mapId);
-#endif
}
}
delete mmap;
- loadedMMaps.erase(mapId);
-#if defined(ENABLE_EXTRAS) && defined(ENABLE_EXTRA_LOGS)
- LOG_DEBUG("server", "MMAP:unloadMap: Unloaded %03i.mmap", mapId);
-#endif
+ itr->second = nullptr;
+ LOG_DEBUG("maps", "MMAP:unloadMap: Unloaded %03i.mmap", mapId);
return true;
}
bool MMapManager::unloadMapInstance(uint32 mapId, uint32 instanceId)
{
- std::unique_lock guard(MMapManagerLock);
-
// check if we have this map loaded
- if (loadedMMaps.find(mapId) == loadedMMaps.end())
+ MMapDataSet::const_iterator itr = GetMMapData(mapId);
+ if (itr == loadedMMaps.end())
{
// file may not exist, therefore not loaded
-#if defined(ENABLE_EXTRAS) && defined(ENABLE_EXTRA_LOGS)
LOG_DEBUG("maps", "MMAP:unloadMapInstance: Asked to unload not loaded navmesh map %03u", mapId);
-#endif
return false;
}
- MMapData* mmap = loadedMMaps[mapId];
+ MMapData* mmap = itr->second;
if (mmap->navMeshQueries.find(instanceId) == mmap->navMeshQueries.end())
{
-#if defined(ENABLE_EXTRAS) && defined(ENABLE_EXTRA_LOGS)
LOG_DEBUG("maps", "MMAP:unloadMapInstance: Asked to unload not loaded dtNavMeshQuery mapId %03u instanceId %u", mapId, instanceId);
-#endif
return false;
}
@@ -308,47 +284,44 @@ namespace MMAP
dtFreeNavMeshQuery(query);
mmap->navMeshQueries.erase(instanceId);
-#if defined(ENABLE_EXTRAS) && defined(ENABLE_EXTRA_LOGS)
- LOG_DEBUG("server", "MMAP:unloadMapInstance: Unloaded mapId %03u instanceId %u", mapId, instanceId);
-#endif
+ LOG_DEBUG("maps", "MMAP:unloadMapInstance: Unloaded mapId %03u instanceId %u", mapId, instanceId);
return true;
}
dtNavMesh const* MMapManager::GetNavMesh(uint32 mapId)
{
- if (loadedMMaps.find(mapId) == loadedMMaps.end())
+ MMapDataSet::const_iterator itr = GetMMapData(mapId);
+ if (itr == loadedMMaps.end())
return nullptr;
- return loadedMMaps[mapId]->navMesh;
+ return itr->second->navMesh;
}
dtNavMeshQuery const* MMapManager::GetNavMeshQuery(uint32 mapId, uint32 instanceId)
{
- if (loadedMMaps.find(mapId) == loadedMMaps.end())
+ MMapDataSet::const_iterator itr = GetMMapData(mapId);
+ if (itr == loadedMMaps.end())
return nullptr;
- MMapData* mmap = loadedMMaps[mapId];
+ MMapData* mmap = itr->second;
if (mmap->navMeshQueries.find(instanceId) == mmap->navMeshQueries.end())
{
- // pussywizard: different instances of the same map shouldn't access this simultaneously
- std::unique_lock guard(GetMMapLock(mapId));
// check again after acquiring mutex
if (mmap->navMeshQueries.find(instanceId) == mmap->navMeshQueries.end())
{
// allocate mesh query
dtNavMeshQuery* query = dtAllocNavMeshQuery();
ASSERT(query);
- if (DT_SUCCESS != query->init(mmap->navMesh, 1024))
+
+ if (dtStatusFailed(query->init(mmap->navMesh, 1024)))
{
dtFreeNavMeshQuery(query);
LOG_ERROR("server", "MMAP:GetNavMeshQuery: Failed to initialize dtNavMeshQuery for mapId %03u instanceId %u", mapId, instanceId);
return nullptr;
}
-#if defined(ENABLE_EXTRAS) && defined(ENABLE_EXTRA_LOGS)
- LOG_DEBUG("server", "MMAP:GetNavMeshQuery: created dtNavMeshQuery for mapId %03u instanceId %u", mapId, instanceId);
-#endif
+ LOG_DEBUG("maps", "MMAP:GetNavMeshQuery: created dtNavMeshQuery for mapId %03u instanceId %u", mapId, instanceId);
mmap->navMeshQueries.insert(std::pair(instanceId, query));
}
}
diff --git a/src/common/Collision/Management/MMapManager.h b/src/common/Collision/Management/MMapManager.h
index d71e35b18e..d2ebb3b0d8 100644
--- a/src/common/Collision/Management/MMapManager.h
+++ b/src/common/Collision/Management/MMapManager.h
@@ -34,7 +34,8 @@ namespace MMAP
// dummy struct to hold map's mmap data
struct MMapData
{
- MMapData(dtNavMesh* mesh) : navMesh(mesh) {}
+ MMapData(dtNavMesh* mesh) : navMesh(mesh) { }
+
~MMapData()
{
for (NavMeshQuerySet::iterator i = navMeshQueries.begin(); i != navMeshQueries.end(); ++i)
@@ -44,11 +45,10 @@ namespace MMAP
dtFreeNavMesh(navMesh);
}
- dtNavMesh* navMesh;
-
// we have to use single dtNavMeshQuery for every instance, since those are not thread safe
- NavMeshQuerySet navMeshQueries; // instanceId to query
- MMapTileSet mmapLoadedTiles; // maps [map grid coords] to [dtTile]
+ NavMeshQuerySet navMeshQueries; // instanceId to query
+ dtNavMesh* navMesh;
+ MMapTileSet loadedTileRefs; // maps [map grid coords] to [dtTile]
};
typedef std::unordered_map MMapDataSet;
@@ -58,9 +58,10 @@ namespace MMAP
class MMapManager
{
public:
- MMapManager() : loadedTiles(0) {}
+ MMapManager() : loadedTiles(0), thread_safe_environment(true) { }
~MMapManager();
+ void InitializeThreadUnsafe(const std::vector& mapIds);
bool loadMap(uint32 mapId, int32 x, int32 y);
bool unloadMap(uint32 mapId, int32 x, int32 y);
bool unloadMap(uint32 mapId);
@@ -73,18 +74,14 @@ namespace MMAP
uint32 getLoadedTilesCount() const { return loadedTiles; }
uint32 getLoadedMapsCount() const { return loadedMMaps.size(); }
- std::shared_mutex& GetMMapLock(uint32 mapId);
- std::shared_mutex& GetMMapGeneralLock() { return MMapLock; } // pussywizard: in case a per-map mutex can't be found, should never happen
- std::shared_mutex& GetManagerLock() { return MMapManagerLock; }
private:
bool loadMapData(uint32 mapId);
uint32 packTileID(int32 x, int32 y);
+ MMapDataSet::const_iterator GetMMapData(uint32 mapId) const;
MMapDataSet loadedMMaps;
uint32 loadedTiles;
-
- std::shared_mutex MMapManagerLock;
- std::shared_mutex MMapLock; // pussywizard: in case a per-map mutex can't be found, should never happen
+ bool thread_safe_environment;
};
}
diff --git a/src/common/Collision/Management/VMapFactory.cpp b/src/common/Collision/Management/VMapFactory.cpp
index 36d22ac5b5..5e9a65eda2 100644
--- a/src/common/Collision/Management/VMapFactory.cpp
+++ b/src/common/Collision/Management/VMapFactory.cpp
@@ -9,14 +9,15 @@
namespace VMAP
{
- IVMapManager* gVMapManager = nullptr;
+ VMapManager2* gVMapManager = nullptr;
//===============================================
// just return the instance
- IVMapManager* VMapFactory::createOrGetVMapManager()
+ VMapManager2* VMapFactory::createOrGetVMapManager()
{
- if (gVMapManager == 0)
- gVMapManager = new VMapManager2(); // should be taken from config ... Please change if you like :-)
+ if (!gVMapManager)
+ gVMapManager = new VMapManager2();
+
return gVMapManager;
}
diff --git a/src/common/Collision/Management/VMapFactory.h b/src/common/Collision/Management/VMapFactory.h
index d752ae50cc..03fe569766 100644
--- a/src/common/Collision/Management/VMapFactory.h
+++ b/src/common/Collision/Management/VMapFactory.h
@@ -9,20 +9,16 @@
#include "IVMapManager.h"
-/**
-This is the access point to the VMapManager.
-*/
-
+// This is the access point to the VMapManager.
namespace VMAP
{
- //===========================================================
+ class VMapManager2;
class VMapFactory
{
public:
- static IVMapManager* createOrGetVMapManager();
+ static VMapManager2* createOrGetVMapManager();
static void clear();
};
-
}
#endif
diff --git a/src/common/Collision/Management/VMapManager2.cpp b/src/common/Collision/Management/VMapManager2.cpp
index 7284762861..ff819e1336 100644
--- a/src/common/Collision/Management/VMapManager2.cpp
+++ b/src/common/Collision/Management/VMapManager2.cpp
@@ -15,21 +15,19 @@
* with this program. If not, see .
*/
-#include
-#include
-#include
-#include
#include "VMapManager2.h"
#include "MapTree.h"
#include "ModelInstance.h"
#include "WorldModel.h"
-#include
-#include
-#include "DisableMgr.h"
-#include "DBCStores.h"
+#include "MapDefines.h"
#include "Log.h"
#include "VMapDefinitions.h"
-#include "GridDefines.h"
+#include "Errors.h"
+#include
+#include
+#include
+#include
+#include
using G3D::Vector3;
@@ -38,20 +36,32 @@ namespace VMAP
VMapManager2::VMapManager2()
{
GetLiquidFlagsPtr = &GetLiquidFlagsDummy;
+ IsVMAPDisabledForPtr = &IsVMAPDisabledForDummy;
+ thread_safe_environment = true;
}
- VMapManager2::~VMapManager2(void)
+ VMapManager2::~VMapManager2()
{
for (InstanceTreeMap::iterator i = iInstanceMapTrees.begin(); i != iInstanceMapTrees.end(); ++i)
{
delete i->second;
}
+
for (ModelFileMap::iterator i = iLoadedModelFiles.begin(); i != iLoadedModelFiles.end(); ++i)
{
delete i->second.getModel();
}
}
+ void VMapManager2::InitializeThreadUnsafe(const std::vector& mapIds)
+ {
+ // the caller must pass the list of all mapIds that will be used in the VMapManager2 lifetime
+ for (const uint32& mapId : mapIds)
+ iInstanceMapTrees.emplace(mapId, nullptr);
+
+ thread_safe_environment = false;
+ }
+
Vector3 VMapManager2::convertPositionToInternalRep(float x, float y, float z) const
{
Vector3 pos;
@@ -63,6 +73,16 @@ namespace VMAP
return pos;
}
+ InstanceTreeMap::const_iterator VMapManager2::GetMapTree(uint32 mapId) const
+ {
+ // return the iterator if found or end() if not found/NULL
+ InstanceTreeMap::const_iterator itr = iInstanceMapTrees.find(mapId);
+ if (itr != iInstanceMapTrees.cend() && !itr->second)
+ itr = iInstanceMapTrees.cend();
+
+ return itr;
+ }
+
// move to MapTree too?
std::string VMapManager2::getMapFileName(unsigned int mapId)
{
@@ -92,6 +112,15 @@ namespace VMAP
{
InstanceTreeMap::iterator instanceTree = iInstanceMapTrees.find(mapId);
if (instanceTree == iInstanceMapTrees.end())
+ {
+ if (thread_safe_environment)
+ instanceTree = iInstanceMapTrees.insert(InstanceTreeMap::value_type(mapId, nullptr)).first;
+ else
+ ASSERT(false, "Invalid mapId %u tile [%u, %u] passed to VMapManager2 after startup in thread unsafe environment",
+ mapId, tileX, tileY);
+ }
+
+ if (!instanceTree->second)
{
std::string mapFileName = getMapFileName(mapId);
StaticMapTree* newTree = new StaticMapTree(mapId, basePath);
@@ -100,7 +129,7 @@ namespace VMAP
delete newTree;
return false;
}
- instanceTree = iInstanceMapTrees.insert(InstanceTreeMap::value_type(mapId, newTree)).first;
+ instanceTree->second = newTree;
}
return instanceTree->second->LoadMapTile(tileX, tileY, this);
@@ -109,13 +138,13 @@ namespace VMAP
void VMapManager2::unloadMap(unsigned int mapId)
{
InstanceTreeMap::iterator instanceTree = iInstanceMapTrees.find(mapId);
- if (instanceTree != iInstanceMapTrees.end())
+ if (instanceTree != iInstanceMapTrees.end() && instanceTree->second)
{
instanceTree->second->UnloadMap(this);
if (instanceTree->second->numLoadedTiles() == 0)
{
delete instanceTree->second;
- iInstanceMapTrees.erase(mapId);
+ instanceTree->second = nullptr;
}
}
}
@@ -123,25 +152,25 @@ namespace VMAP
void VMapManager2::unloadMap(unsigned int mapId, int x, int y)
{
InstanceTreeMap::iterator instanceTree = iInstanceMapTrees.find(mapId);
- if (instanceTree != iInstanceMapTrees.end())
+ if (instanceTree != iInstanceMapTrees.end() && instanceTree->second)
{
instanceTree->second->UnloadMapTile(x, y, this);
if (instanceTree->second->numLoadedTiles() == 0)
{
delete instanceTree->second;
- iInstanceMapTrees.erase(mapId);
+ instanceTree->second = nullptr;
}
}
}
bool VMapManager2::isInLineOfSight(unsigned int mapId, float x1, float y1, float z1, float x2, float y2, float z2)
{
-#if defined(ENABLE_EXTRAS) && defined(ENABLE_VMAP_CHECKS)
- if (!isLineOfSightCalcEnabled() || DisableMgr::IsDisabledFor(DISABLE_TYPE_VMAP, mapId, nullptr, VMAP_DISABLE_LOS))
+#if defined(ENABLE_VMAP_CHECKS)
+ if (!isLineOfSightCalcEnabled() || IsVMAPDisabledForPtr(mapId, VMAP_DISABLE_LOS))
return true;
#endif
- InstanceTreeMap::iterator instanceTree = iInstanceMapTrees.find(mapId);
+ InstanceTreeMap::const_iterator instanceTree = GetMapTree(mapId);
if (instanceTree != iInstanceMapTrees.end())
{
Vector3 pos1 = convertPositionToInternalRep(x1, y1, z1);
@@ -161,11 +190,11 @@ namespace VMAP
*/
bool VMapManager2::getObjectHitPos(unsigned int mapId, float x1, float y1, float z1, float x2, float y2, float z2, float& rx, float& ry, float& rz, float modifyDist)
{
-#if defined(ENABLE_EXTRAS) && defined(ENABLE_VMAP_CHECKS)
- if (isLineOfSightCalcEnabled() && !DisableMgr::IsDisabledFor(DISABLE_TYPE_VMAP, mapId, nullptr, VMAP_DISABLE_LOS))
+#if defined(ENABLE_VMAP_CHECKS)
+ if (isLineOfSightCalcEnabled() && !IsVMAPDisabledForPtr(mapId, VMAP_DISABLE_LOS))
#endif
{
- InstanceTreeMap::iterator instanceTree = iInstanceMapTrees.find(mapId);
+ InstanceTreeMap::const_iterator instanceTree = GetMapTree(mapId);
if (instanceTree != iInstanceMapTrees.end())
{
Vector3 pos1 = convertPositionToInternalRep(x1, y1, z1);
@@ -193,11 +222,11 @@ namespace VMAP
float VMapManager2::getHeight(unsigned int mapId, float x, float y, float z, float maxSearchDist)
{
-#if defined(ENABLE_EXTRAS) && defined(ENABLE_VMAP_CHECKS)
- if (isHeightCalcEnabled() && !DisableMgr::IsDisabledFor(DISABLE_TYPE_VMAP, mapId, nullptr, VMAP_DISABLE_HEIGHT))
+#if defined(ENABLE_VMAP_CHECKS)
+ if (isHeightCalcEnabled() && !IsVMAPDisabledForPtr(mapId, VMAP_DISABLE_HEIGHT))
#endif
{
- InstanceTreeMap::iterator instanceTree = iInstanceMapTrees.find(mapId);
+ InstanceTreeMap::const_iterator instanceTree = GetMapTree(mapId);
if (instanceTree != iInstanceMapTrees.end())
{
Vector3 pos = convertPositionToInternalRep(x, y, z);
@@ -214,11 +243,11 @@ namespace VMAP
bool VMapManager2::getAreaInfo(unsigned int mapId, float x, float y, float& z, uint32& flags, int32& adtId, int32& rootId, int32& groupId) const
{
-#if defined(ENABLE_EXTRAS) && defined(ENABLE_VMAP_CHECKS)
- if (!DisableMgr::IsDisabledFor(DISABLE_TYPE_VMAP, mapId, nullptr, VMAP_DISABLE_AREAFLAG))
+#if defined(ENABLE_VMAP_CHECKS)
+ if (!IsVMAPDisabledForPtr(mapId, VMAP_DISABLE_AREAFLAG))
#endif
{
- InstanceTreeMap::const_iterator instanceTree = iInstanceMapTrees.find(mapId);
+ InstanceTreeMap::const_iterator instanceTree = GetMapTree(mapId);
if (instanceTree != iInstanceMapTrees.end())
{
Vector3 pos = convertPositionToInternalRep(x, y, z);
@@ -234,11 +263,11 @@ namespace VMAP
bool VMapManager2::GetLiquidLevel(uint32 mapId, float x, float y, float z, uint8 reqLiquidType, float& level, float& floor, uint32& type) const
{
-#if defined(ENABLE_EXTRAS) && defined(ENABLE_VMAP_CHECKS)
- if (!DisableMgr::IsDisabledFor(DISABLE_TYPE_VMAP, mapId, nullptr, VMAP_DISABLE_LIQUIDSTATUS))
+#if defined(ENABLE_VMAP_CHECKS)
+ if (!IsVMAPDisabledForPtr(mapId, VMAP_DISABLE_LIQUIDSTATUS))
#endif
{
- InstanceTreeMap::const_iterator instanceTree = iInstanceMapTrees.find(mapId);
+ InstanceTreeMap::const_iterator instanceTree = GetMapTree(mapId);
if (instanceTree != iInstanceMapTrees.end())
{
LocationInfo info;
@@ -262,7 +291,7 @@ namespace VMAP
WorldModel* VMapManager2::acquireModelInstance(const std::string& basepath, const std::string& filename)
{
//! Critical section, thread safe access to iLoadedModelFiles
- std::lock_guard guard(LoadedModelFilesLock);
+ std::lock_guard lock(LoadedModelFilesLock);
ModelFileMap::iterator model = iLoadedModelFiles.find(filename);
if (model == iLoadedModelFiles.end())
@@ -274,20 +303,19 @@ namespace VMAP
delete worldmodel;
return nullptr;
}
-#if defined(ENABLE_EXTRAS) && defined(ENABLE_EXTRA_LOGS)
LOG_DEBUG("maps", "VMapManager2: loading file '%s%s'", basepath.c_str(), filename.c_str());
-#endif
model = iLoadedModelFiles.insert(std::pair(filename, ManagedModel())).first;
model->second.setModel(worldmodel);
}
- //model->second.incRefCount();
+
return model->second.getModel();
}
void VMapManager2::releaseModelInstance(const std::string& filename)
{
//! Critical section, thread safe access to iLoadedModelFiles
- std::lock_guard guard(LoadedModelFilesLock);
+ std::lock_guard lock(LoadedModelFilesLock);
+
ModelFileMap::iterator model = iLoadedModelFiles.find(filename);
if (model == iLoadedModelFiles.end())
{
@@ -296,9 +324,7 @@ namespace VMAP
}
if (model->second.decRefCount() == 0)
{
-#if defined(ENABLE_EXTRAS) && defined(ENABLE_EXTRA_LOGS)
LOG_DEBUG("maps", "VMapManager2: unloading file '%s'", filename.c_str());
-#endif
delete model->second.getModel();
iLoadedModelFiles.erase(model);
}
@@ -309,4 +335,9 @@ namespace VMAP
return StaticMapTree::CanLoadMap(std::string(basePath), mapId, x, y);
}
+ void VMapManager2::getInstanceMapTree(InstanceTreeMap& instanceMapTree)
+ {
+ instanceMapTree = iInstanceMapTrees;
+ }
+
} // namespace VMAP
diff --git a/src/common/Collision/Management/VMapManager2.h b/src/common/Collision/Management/VMapManager2.h
index 71fcbeaa33..514f03600c 100644
--- a/src/common/Collision/Management/VMapManager2.h
+++ b/src/common/Collision/Management/VMapManager2.h
@@ -19,9 +19,10 @@
#define _VMAPMANAGER2_H
#include "IVMapManager.h"
-#include "Define.h"
+#include "Common.h"
#include
#include
+#include
//===========================================================
@@ -65,12 +66,22 @@ namespace VMAP
typedef std::unordered_map InstanceTreeMap;
typedef std::unordered_map ModelFileMap;
+ enum DisableTypes
+ {
+ VMAP_DISABLE_AREAFLAG = 0x1,
+ VMAP_DISABLE_HEIGHT = 0x2,
+ VMAP_DISABLE_LOS = 0x4,
+ VMAP_DISABLE_LIQUIDSTATUS = 0x8
+ };
+
class VMapManager2 : public IVMapManager
{
protected:
// Tree to check collision
ModelFileMap iLoadedModelFiles;
InstanceTreeMap iInstanceMapTrees;
+ bool thread_safe_environment;
+
// Mutex for iLoadedModelFiles
std::mutex LoadedModelFilesLock;
@@ -78,6 +89,9 @@ namespace VMAP
/* void _unloadMap(uint32 pMapId, uint32 x, uint32 y); */
static uint32 GetLiquidFlagsDummy(uint32) { return 0; }
+ static bool IsVMAPDisabledForDummy(uint32 /*entry*/, uint8 /*flags*/) { return false; }
+
+ InstanceTreeMap::const_iterator GetMapTree(uint32 mapId) const;
public:
// public for debug
@@ -87,6 +101,8 @@ namespace VMAP
VMapManager2();
~VMapManager2() override;
+ void InitializeThreadUnsafe(const std::vector& mapIds);
+
int loadMap(const char* pBasePath, unsigned int mapId, int x, int y) override;
void unloadMap(unsigned int mapId, int x, int y) override;
@@ -113,12 +129,14 @@ namespace VMAP
return getMapFileName(mapId);
}
bool existsMap(const char* basePath, unsigned int mapId, int x, int y) override;
- public:
void getInstanceMapTree(InstanceTreeMap& instanceMapTree);
typedef uint32(*GetLiquidFlagsFn)(uint32 liquidType);
GetLiquidFlagsFn GetLiquidFlagsPtr;
+
+ typedef bool(*IsVMAPDisabledForFn)(uint32 entry, uint8 flags);
+ IsVMAPDisabledForFn IsVMAPDisabledForPtr;
};
}
-#endif
\ No newline at end of file
+#endif
diff --git a/src/common/Collision/Maps/MapDefines.h b/src/common/Collision/Maps/MapDefines.h
new file mode 100644
index 0000000000..e323dfcdea
--- /dev/null
+++ b/src/common/Collision/Maps/MapDefines.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2016+ AzerothCore , released under GNU AGPL v3 license: https://github.com/azerothcore/azerothcore-wotlk/blob/master/LICENSE-AGPL3
+ * Copyright (C) 2008+ TrinityCore
+ */
+
+#ifndef _MAPDEFINES_H
+#define _MAPDEFINES_H
+
+#include "Define.h"
+#include "DetourNavMesh.h"
+
+#define MAX_NUMBER_OF_GRIDS 64
+#define SIZE_OF_GRIDS 533.3333f
+
+#define MMAP_MAGIC 0x4d4d4150 // 'MMAP'
+#define MMAP_VERSION 11
+
+struct MmapTileHeader
+{
+ uint32 mmapMagic{MMAP_MAGIC};
+ uint32 dtVersion;
+ uint32 mmapVersion{MMAP_VERSION};
+ uint32 size{0};
+ char usesLiquids{true};
+ char padding[3]{};
+
+ MmapTileHeader() : dtVersion(DT_NAVMESH_VERSION) { }
+};
+
+// All padding fields must be handled and initialized to ensure mmaps_generator will produce binary-identical *.mmtile files
+static_assert(sizeof(MmapTileHeader) == 20, "MmapTileHeader size is not correct, adjust the padding field size");
+static_assert(sizeof(MmapTileHeader) == (sizeof(MmapTileHeader::mmapMagic) +
+ sizeof(MmapTileHeader::dtVersion) +
+ sizeof(MmapTileHeader::mmapVersion) +
+ sizeof(MmapTileHeader::size) +
+ sizeof(MmapTileHeader::usesLiquids) +
+ sizeof(MmapTileHeader::padding)), "MmapTileHeader has uninitialized padding fields");
+
+enum NavTerrain
+{
+ NAV_EMPTY = 0x00,
+ NAV_GROUND = 0x01,
+ NAV_MAGMA = 0x02,
+ NAV_SLIME = 0x04,
+ NAV_WATER = 0x08,
+ NAV_UNUSED1 = 0x10,
+ NAV_UNUSED2 = 0x20,
+ NAV_UNUSED3 = 0x40,
+ NAV_UNUSED4 = 0x80
+ // we only have 8 bits
+};
+
+#endif
diff --git a/src/common/Collision/Maps/MapTree.cpp b/src/common/Collision/Maps/MapTree.cpp
index 520ad8cc33..38e4f97d22 100644
--- a/src/common/Collision/Maps/MapTree.cpp
+++ b/src/common/Collision/Maps/MapTree.cpp
@@ -462,4 +462,10 @@ namespace VMAP
}
iLoadedTiles.erase(tile);
}
+
+ void StaticMapTree::getModelInstances(ModelInstance*& models, uint32& count)
+ {
+ models = iTreeValues;
+ count = iNTreeValues;
+ }
}
diff --git a/src/common/Collision/Maps/TileAssembler.cpp b/src/common/Collision/Maps/TileAssembler.cpp
index dd4f2621e0..c4fbed2019 100644
--- a/src/common/Collision/Maps/TileAssembler.cpp
+++ b/src/common/Collision/Maps/TileAssembler.cpp
@@ -8,7 +8,7 @@
#include "MapTree.h"
#include "BoundingIntervalHierarchy.h"
#include "VMapDefinitions.h"
-#include "SharedDefines.h"
+#include "MapDefines.h"
#include
#include
#include
diff --git a/src/common/Collision/Models/GameObjectModel.cpp b/src/common/Collision/Models/GameObjectModel.cpp
index 9a0e294a01..56b91c49d5 100644
--- a/src/common/Collision/Models/GameObjectModel.cpp
+++ b/src/common/Collision/Models/GameObjectModel.cpp
@@ -4,19 +4,13 @@
* Copyright (C) 2005-2009 MaNGOS
*/
+#include "GameObjectModel.h"
#include "VMapFactory.h"
#include "VMapManager2.h"
#include "VMapDefinitions.h"
#include "WorldModel.h"
-
-#include "GameObjectModel.h"
#include "Log.h"
-#include "GameObject.h"
-#include "Creature.h"
-#include "TemporarySummon.h"
-#include "Object.h"
-#include "DBCStores.h"
-#include "World.h"
+#include "Timer.h"
using G3D::Vector3;
using G3D::Ray;
@@ -35,16 +29,14 @@ struct GameobjectModelData
typedef std::unordered_map ModelList;
ModelList model_list;
-void LoadGameObjectModelList()
+void LoadGameObjectModelList(std::string const& dataPath)
{
- //#ifndef NO_CORE_FUNCS
uint32 oldMSTime = getMSTime();
- //#endif
- FILE* model_list_file = fopen((sWorld->GetDataPath() + "vmaps/" + VMAP::GAMEOBJECT_MODELS).c_str(), "rb");
+ FILE* model_list_file = fopen((dataPath + "vmaps/" + VMAP::GAMEOBJECT_MODELS).c_str(), "rb");
if (!model_list_file)
{
- LOG_ERROR("server", "Unable to open '%s' file.", VMAP::GAMEOBJECT_MODELS);
+ LOG_ERROR("maps", "Unable to open '%s' file.", VMAP::GAMEOBJECT_MODELS);
return;
}
@@ -72,7 +64,8 @@ void LoadGameObjectModelList()
|| fread(&v1, sizeof(Vector3), 1, model_list_file) != 1
|| fread(&v2, sizeof(Vector3), 1, model_list_file) != 1)
{
- LOG_ERROR("server", "File '%s' seems to be corrupted!", VMAP::GAMEOBJECT_MODELS);
+ LOG_ERROR("maps", "File '%s' seems to be corrupted!", VMAP::GAMEOBJECT_MODELS);
+ fclose(model_list_file);
break;
}
@@ -95,12 +88,12 @@ void LoadGameObjectModelList()
GameObjectModel::~GameObjectModel()
{
if (iModel)
- ((VMAP::VMapManager2*)VMAP::VMapFactory::createOrGetVMapManager())->releaseModelInstance(name);
+ VMAP::VMapFactory::createOrGetVMapManager()->releaseModelInstance(name);
}
-bool GameObjectModel::initialize(const GameObject& go, const GameObjectDisplayInfoEntry& info)
+bool GameObjectModel::initialize(std::unique_ptr modelOwner, std::string const& dataPath)
{
- ModelList::const_iterator it = model_list.find(info.Displayid);
+ ModelList::const_iterator it = model_list.find(modelOwner->GetDisplayId());
if (it == model_list.end())
return false;
@@ -112,24 +105,18 @@ bool GameObjectModel::initialize(const GameObject& go, const GameObjectDisplayIn
return false;
}
- iModel = ((VMAP::VMapManager2*)VMAP::VMapFactory::createOrGetVMapManager())->acquireModelInstance(sWorld->GetDataPath() + "vmaps/", it->second.name);
+ iModel = VMAP::VMapFactory::createOrGetVMapManager()->acquireModelInstance(dataPath + "vmaps/", it->second.name);
if (!iModel)
return false;
name = it->second.name;
- //flags = VMAP::MOD_M2;
- //adtId = 0;
- //ID = 0;
- iPos = Vector3(go.GetPositionX(), go.GetPositionY(), go.GetPositionZ());
-
- // pussywizard:
- phasemask = (go.GetGoState() == GO_STATE_READY || go.IsTransport()) ? go.GetPhaseMask() : 0;
-
- iScale = go.GetFloatValue(OBJECT_FIELD_SCALE_X);
+ iPos = modelOwner->GetPosition();
+ phasemask = modelOwner->GetPhaseMask();
+ iScale = modelOwner->GetScale();
iInvScale = 1.f / iScale;
- G3D::Matrix3 iRotation = G3D::Matrix3::fromEulerAnglesZYX(go.GetOrientation(), 0, 0);
+ G3D::Matrix3 iRotation = G3D::Matrix3::fromEulerAnglesZYX(modelOwner->GetOrientation(), 0, 0);
iInvRot = iRotation.inverse();
// transform bounding box:
mdl_box = AABox(mdl_box.low() * iScale, mdl_box.high() * iScale);
@@ -138,27 +125,24 @@ bool GameObjectModel::initialize(const GameObject& go, const GameObjectDisplayIn
rotated_bounds.merge(iRotation * mdl_box.corner(i));
iBound = rotated_bounds + iPos;
+
#ifdef SPAWN_CORNERS
// test:
for (int i = 0; i < 8; ++i)
{
Vector3 pos(iBound.corner(i));
- const_cast(go).SummonCreature(1, pos.x, pos.y, pos.z, 0, TEMPSUMMON_MANUAL_DESPAWN);
+ modelOwner->DebugVisualizeCorner(pos);
}
#endif
- owner = &go;
+ owner = std::move(modelOwner);
return true;
}
-GameObjectModel* GameObjectModel::Create(const GameObject& go)
+GameObjectModel* GameObjectModel::Create(std::unique_ptr modelOwner, std::string const& dataPath)
{
- const GameObjectDisplayInfoEntry* info = sGameObjectDisplayInfoStore.LookupEntry(go.GetDisplayId());
- if (!info)
- return nullptr;
-
GameObjectModel* mdl = new GameObjectModel();
- if (!mdl->initialize(go, *info))
+ if (!mdl->initialize(std::move(modelOwner), dataPath))
{
delete mdl;
return nullptr;
@@ -169,7 +153,7 @@ GameObjectModel* GameObjectModel::Create(const GameObject& go)
bool GameObjectModel::intersectRay(const G3D::Ray& ray, float& MaxDist, bool StopAtFirstHit, uint32 ph_mask) const
{
- if (!(phasemask & ph_mask) || !owner->isSpawned())
+ if (!(phasemask & ph_mask) || !owner->IsSpawned())
return false;
float time = ray.intersectionTime(iBound);
@@ -199,6 +183,7 @@ bool GameObjectModel::UpdatePosition()
return false;
G3D::AABox mdl_box(it->second.bound);
+
// ignore models with no bounds
if (mdl_box == G3D::AABox::zero())
{
@@ -206,12 +191,14 @@ bool GameObjectModel::UpdatePosition()
return false;
}
- iPos = Vector3(owner->GetPositionX(), owner->GetPositionY(), owner->GetPositionZ());
+ iPos = owner->GetPosition();
G3D::Matrix3 iRotation = G3D::Matrix3::fromEulerAnglesZYX(owner->GetOrientation(), 0, 0);
iInvRot = iRotation.inverse();
+
// transform bounding box:
mdl_box = AABox(mdl_box.low() * iScale, mdl_box.high() * iScale);
AABox rotated_bounds;
+
for (int i = 0; i < 8; ++i)
rotated_bounds.merge(iRotation * mdl_box.corner(i));
@@ -221,7 +208,7 @@ bool GameObjectModel::UpdatePosition()
for (int i = 0; i < 8; ++i)
{
Vector3 pos(iBound.corner(i));
- owner->SummonCreature(1, pos.x, pos.y, pos.z, 0.0f, TEMPSUMMON_TIMED_DESPAWN, 10000);
+ owner->DebugVisualizeCorner(pos);
}
#endif
diff --git a/src/common/Collision/Models/GameObjectModel.h b/src/common/Collision/Models/GameObjectModel.h
index 6e10df44a3..3051ba1605 100644
--- a/src/common/Collision/Models/GameObjectModel.h
+++ b/src/common/Collision/Models/GameObjectModel.h
@@ -7,13 +7,12 @@
#ifndef _GAMEOBJECT_MODEL_H
#define _GAMEOBJECT_MODEL_H
+#include "Define.h"
#include
#include
#include
#include
-#include "Define.h"
-
namespace VMAP
{
class WorldModel;
@@ -22,20 +21,23 @@ namespace VMAP
class GameObject;
struct GameObjectDisplayInfoEntry;
-class GameObjectModel /*, public Intersectable*/
+class GameObjectModelOwnerBase
{
- uint32 phasemask{0};
- G3D::AABox iBound;
- G3D::Matrix3 iInvRot;
- G3D::Vector3 iPos;
- //G3D::Vector3 iRot;
- float iInvScale{0};
- float iScale{0};
- VMAP::WorldModel* iModel;
- GameObject const* owner;
+public:
+ virtual ~GameObjectModelOwnerBase() = default;
- GameObjectModel() : iModel(nullptr), owner(nullptr) { }
- bool initialize(const GameObject& go, const GameObjectDisplayInfoEntry& info);
+ virtual bool IsSpawned() const = 0;
+ virtual uint32 GetDisplayId() const = 0;
+ virtual uint32 GetPhaseMask() const = 0;
+ virtual G3D::Vector3 GetPosition() const = 0;
+ virtual float GetOrientation() const = 0;
+ virtual float GetScale() const = 0;
+ virtual void DebugVisualizeCorner(G3D::Vector3 const& /*corner*/) const = 0;
+};
+
+class GameObjectModel
+{
+ GameObjectModel() : phasemask(0), iInvScale(0), iScale(0), iModel(nullptr) { }
public:
std::string name;
@@ -44,19 +46,33 @@ public:
~GameObjectModel();
- [[nodiscard]] const G3D::Vector3& getPosition() const { return iPos;}
+ [[nodiscard]] const G3D::Vector3& getPosition() const { return iPos; }
- /** Enables\disables collision. */
- void disable() { phasemask = 0;}
- void enable(uint32 ph_mask) { phasemask = ph_mask;}
+ /** Enables\disables collision. */
+ void disable() { phasemask = 0; }
+ void enable(uint32 ph_mask) { phasemask = ph_mask; }
- [[nodiscard]] bool isEnabled() const {return phasemask != 0;}
+ [[nodiscard]] bool isEnabled() const { return phasemask != 0; }
bool intersectRay(const G3D::Ray& Ray, float& MaxDist, bool StopAtFirstHit, uint32 ph_mask) const;
- static GameObjectModel* Create(const GameObject& go);
+ static GameObjectModel* Create(std::unique_ptr modelOwner, std::string const& dataPath);
bool UpdatePosition();
+
+private:
+ bool initialize(std::unique_ptr modelOwner, std::string const& dataPath);
+
+ uint32 phasemask;
+ G3D::AABox iBound;
+ G3D::Matrix3 iInvRot;
+ G3D::Vector3 iPos;
+ float iInvScale;
+ float iScale;
+ VMAP::WorldModel* iModel;
+ std::unique_ptr owner;
};
-#endif // _GAMEOBJECT_MODEL_H
\ No newline at end of file
+void LoadGameObjectModelList(std::string const& dataPath);
+
+#endif // _GAMEOBJECT_MODEL_H
diff --git a/src/common/Collision/Models/ModelInstance.h b/src/common/Collision/Models/ModelInstance.h
index 43d38566a8..1d9a11f726 100644
--- a/src/common/Collision/Models/ModelInstance.h
+++ b/src/common/Collision/Models/ModelInstance.h
@@ -7,13 +7,12 @@
#ifndef _MODELINSTANCE_H_
#define _MODELINSTANCE_H_
+#include "Define.h"
#include
#include
#include
#include
-#include "Define.h"
-
namespace VMAP
{
class WorldModel;
@@ -58,12 +57,11 @@ namespace VMAP
void intersectPoint(const G3D::Vector3& p, AreaInfo& info) const;
bool GetLocationInfo(const G3D::Vector3& p, LocationInfo& info) const;
bool GetLiquidLevel(const G3D::Vector3& p, LocationInfo& info, float& liqHeight) const;
+ WorldModel* getWorldModel() { return iModel; }
protected:
G3D::Matrix3 iInvRot;
float iInvScale{0.0f};
WorldModel* iModel{nullptr};
- public:
- WorldModel* getWorldModel();
};
} // namespace VMAP
diff --git a/src/common/Collision/Models/WorldModel.cpp b/src/common/Collision/Models/WorldModel.cpp
index e8333e0f6f..a65f305b7c 100644
--- a/src/common/Collision/Models/WorldModel.cpp
+++ b/src/common/Collision/Models/WorldModel.cpp
@@ -241,6 +241,13 @@ namespace VMAP
return result;
}
+ void WmoLiquid::getPosInfo(uint32& tilesX, uint32& tilesY, G3D::Vector3& corner) const
+ {
+ tilesX = iTilesX;
+ tilesY = iTilesY;
+ corner = iCorner;
+ }
+
// ===================== GroupModel ==================================
GroupModel::GroupModel(const GroupModel& other):
@@ -401,6 +408,13 @@ namespace VMAP
return 0;
}
+ void GroupModel::getMeshData(std::vector& outVertices, std::vector& outTriangles, WmoLiquid*& liquid)
+ {
+ outVertices = vertices;
+ outTriangles = triangles;
+ liquid = iLiquid;
+ }
+
// ===================== WorldModel ==================================
void WorldModel::setGroupModels(std::vector& models)
@@ -575,4 +589,9 @@ namespace VMAP
fclose(rf);
return result;
}
+
+ void WorldModel::getGroupModels(std::vector& outGroupModels)
+ {
+ outGroupModels = groupModels;
+ }
}
diff --git a/src/common/Collision/Models/WorldModel.h b/src/common/Collision/Models/WorldModel.h
index 88558a03e1..75a809c27b 100644
--- a/src/common/Collision/Models/WorldModel.h
+++ b/src/common/Collision/Models/WorldModel.h
@@ -7,13 +7,12 @@
#ifndef _WORLDMODEL_H
#define _WORLDMODEL_H
+#include "Define.h"
+#include "BoundingIntervalHierarchy.h"
#include
#include
#include
#include
-#include "BoundingIntervalHierarchy.h"
-
-#include "Define.h"
namespace VMAP
{
@@ -46,6 +45,7 @@ namespace VMAP
uint32 GetFileSize();
bool writeToFile(FILE* wf);
static bool readFromFile(FILE* rf, WmoLiquid*& liquid);
+ void getPosInfo(uint32& tilesX, uint32& tilesY, G3D::Vector3& corner) const;
private:
WmoLiquid() { }
uint32 iTilesX{0}; //!< number of tiles in x direction, each
@@ -54,8 +54,6 @@ namespace VMAP
uint32 iType{0}; //!< liquid type
float* iHeight{nullptr}; //!< (tilesX + 1)*(tilesY + 1) height values
uint8* iFlags{nullptr}; //!< info if liquid tile is used
- public:
- void getPosInfo(uint32& tilesX, uint32& tilesY, G3D::Vector3& corner) const;
};
/*! holding additional info for WMO group files */
@@ -80,6 +78,7 @@ namespace VMAP
[[nodiscard]] const G3D::AABox& GetBound() const { return iBound; }
[[nodiscard]] uint32 GetMogpFlags() const { return iMogpFlags; }
[[nodiscard]] uint32 GetWmoID() const { return iGroupWMOID; }
+ void getMeshData(std::vector& outVertices, std::vector& outTriangles, WmoLiquid*& liquid);
protected:
G3D::AABox iBound;
uint32 iMogpFlags{0};// 0x8 outdor; 0x2000 indoor
@@ -88,8 +87,6 @@ namespace VMAP
std::vector triangles;
BIH meshTree;
WmoLiquid* iLiquid{nullptr};
- public:
- void getMeshData(std::vector& vertices, std::vector& triangles, WmoLiquid*& liquid);
};
/*! Holds a model (converted M2 or WMO) in its original coordinate space */
class WorldModel
@@ -105,12 +102,11 @@ namespace VMAP
bool GetLocationInfo(const G3D::Vector3& p, const G3D::Vector3& down, float& dist, LocationInfo& info) const;
bool writeFile(const std::string& filename);
bool readFile(const std::string& filename);
+ void getGroupModels(std::vector& outGroupModels);
protected:
uint32 RootWMOID{0};
std::vector groupModels;
BIH groupTree;
- public:
- void getGroupModels(std::vector& groupModels);
};
} // namespace VMAP
diff --git a/src/common/Collision/VMapTools.h b/src/common/Collision/VMapTools.h
index d29c4c50e8..5826941268 100644
--- a/src/common/Collision/VMapTools.h
+++ b/src/common/Collision/VMapTools.h
@@ -7,11 +7,10 @@
#ifndef _VMAPTOOLS_H
#define _VMAPTOOLS_H
+#include "Define.h"
#include
#include
-#include "NodeValueAccess.h"
-
/**
The Class is mainly taken from G3D/AABSPTree.h but modified to be able to use our internal data structure.
This is an iterator that helps us analysing the BSP-Trees.
@@ -40,7 +39,6 @@ namespace VMAP
class MyCollisionDetection
{
- private:
public:
static bool collisionLocationForMovingPointFixedAABox(
const G3D::Vector3& origin,
diff --git a/src/common/Configuration/Config.cpp b/src/common/Configuration/Config.cpp
index c191f1be9c..777d59bedd 100644
--- a/src/common/Configuration/Config.cpp
+++ b/src/common/Configuration/Config.cpp
@@ -45,9 +45,11 @@ namespace
throw ConfigException(acore::StringFormat("Config::LoadFile: Failed open file '%s'", file.c_str()));
uint32 count = 0;
+ uint32 lineNumber = 0;
while (in.good())
{
+ lineNumber++;
std::string line;
std::getline(in, line);
@@ -67,7 +69,9 @@ namespace
auto const equal_pos = line.find('=');
if (equal_pos == std::string::npos || equal_pos == line.length())
- return;
+ {
+ ABORT_MSG("> Config::LoadFile: Failure to read line number %u. Don't use only whitespace lines", lineNumber);
+ }
auto entry = acore::String::Trim(line.substr(0, equal_pos), in.getloc());
auto value = acore::String::Trim(line.substr(equal_pos + 1), in.getloc());
diff --git a/src/common/PrecompiledHeaders/commonPCH.h b/src/common/PrecompiledHeaders/commonPCH.h
index d0c15b17f0..27707525f9 100644
--- a/src/common/PrecompiledHeaders/commonPCH.h
+++ b/src/common/PrecompiledHeaders/commonPCH.h
@@ -2,7 +2,5 @@
#include "Common.h"
#include "Log.h"
-#include "DatabaseWorker.h"
-#include "SQLOperation.h"
#include "Errors.h"
#include "TypeList.h"
diff --git a/src/common/Utilities/Util.cpp b/src/common/Utilities/Util.cpp
index 0aca756ec9..d69f8b6155 100644
--- a/src/common/Utilities/Util.cpp
+++ b/src/common/Utilities/Util.cpp
@@ -8,10 +8,9 @@
#include "Common.h"
#include "utf8.h"
#include "Log.h"
-#include "DatabaseWorker.h"
-#include "SQLOperation.h"
#include "Errors.h"
#include "TypeList.h"
+#include
#include "SFMT.h"
#include "Errors.h" // for ASSERT
#include
diff --git a/src/server/database/Database/Implementation/WorldDatabase.cpp b/src/server/database/Database/Implementation/WorldDatabase.cpp
index d5f015bbdc..398cd53f52 100644
--- a/src/server/database/Database/Implementation/WorldDatabase.cpp
+++ b/src/server/database/Database/Implementation/WorldDatabase.cpp
@@ -80,6 +80,7 @@ void WorldDatabaseConnection::DoPrepareStatements()
PrepareStatement(WORLD_DEL_DISABLES, "DELETE FROM disables WHERE entry = ? AND sourceType = ?", CONNECTION_ASYNC);
PrepareStatement(WORLD_UPD_CREATURE_ZONE_AREA_DATA, "UPDATE creature SET zoneId = ?, areaId = ? WHERE guid = ?", CONNECTION_ASYNC);
PrepareStatement(WORLD_UPD_GAMEOBJECT_ZONE_AREA_DATA, "UPDATE gameobject SET zoneId = ?, areaId = ? WHERE guid = ?", CONNECTION_ASYNC);
+ PrepareStatement(WORLD_INS_GAMEOBJECT_ADDON, "INSERT INTO gameobject_addon (guid, invisibilityType, invisibilityValue) VALUES (?, 0, 0)", CONNECTION_ASYNC);
// 0: uint8
PrepareStatement(WORLD_SEL_REQ_XP, "SELECT Experience FROM player_xp_for_level WHERE Level = ?", CONNECTION_SYNCH);
}
diff --git a/src/server/database/Database/Implementation/WorldDatabase.h b/src/server/database/Database/Implementation/WorldDatabase.h
index 7e3600f7dd..f00ef5b1c2 100644
--- a/src/server/database/Database/Implementation/WorldDatabase.h
+++ b/src/server/database/Database/Implementation/WorldDatabase.h
@@ -102,6 +102,7 @@ enum WorldDatabaseStatements
WORLD_UPD_CREATURE_ZONE_AREA_DATA,
WORLD_UPD_GAMEOBJECT_ZONE_AREA_DATA,
WORLD_SEL_REQ_XP,
+ WORLD_INS_GAMEOBJECT_ADDON,
MAX_WORLDDATABASE_STATEMENTS
};
diff --git a/src/server/game/AI/CoreAI/TotemAI.cpp b/src/server/game/AI/CoreAI/TotemAI.cpp
index 2fd9044642..a6e81dd920 100644
--- a/src/server/game/AI/CoreAI/TotemAI.cpp
+++ b/src/server/game/AI/CoreAI/TotemAI.cpp
@@ -76,6 +76,12 @@ void TotemAI::UpdateAI(uint32 /*diff*/)
me->VisitNearbyObject(max_range, checker);
}
+
+ if (!victim && me->GetCharmerOrOwnerOrSelf()->IsInCombat())
+ {
+ victim = me->GetCharmerOrOwnerOrSelf()->GetVictim();
+ }
+
// If have target
if (victim)
{
diff --git a/src/server/game/Battlefield/Battlefield.cpp b/src/server/game/Battlefield/Battlefield.cpp
index fe741f0026..f23a908207 100644
--- a/src/server/game/Battlefield/Battlefield.cpp
+++ b/src/server/game/Battlefield/Battlefield.cpp
@@ -787,7 +787,14 @@ Creature* Battlefield::SpawnCreature(uint32 entry, float x, float y, float z, fl
if (!map)
{
LOG_ERROR("server", "Battlefield::SpawnCreature: Can't create creature entry: %u map not found", entry);
- return 0;
+ return nullptr;
+ }
+
+ CreatureTemplate const* cinfo = sObjectMgr->GetCreatureTemplate(entry);
+ if (!cinfo)
+ {
+ LOG_ERROR("sql.sql", "Battlefield::SpawnCreature: entry %u does not exist.", entry);
+ return nullptr;
}
Creature* creature = new Creature(true);
@@ -801,12 +808,6 @@ Creature* Battlefield::SpawnCreature(uint32 entry, float x, float y, float z, fl
creature->setFaction(BattlefieldFactions[teamId]);
creature->SetHomePosition(x, y, z, o);
- CreatureTemplate const* cinfo = sObjectMgr->GetCreatureTemplate(entry);
- if (!cinfo)
- {
- LOG_ERROR("sql.sql", "Battlefield::SpawnCreature: entry %u does not exist.", entry);
- return nullptr;
- }
// force using DB speeds -- do we really need this?
creature->SetSpeed(MOVE_WALK, cinfo->speed_walk);
creature->SetSpeed(MOVE_RUN, cinfo->speed_run);
diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundWS.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundWS.cpp
index 3399feb48d..f7907b7350 100644
--- a/src/server/game/Battlegrounds/Zones/BattlegroundWS.cpp
+++ b/src/server/game/Battlegrounds/Zones/BattlegroundWS.cpp
@@ -142,6 +142,26 @@ void BattlegroundWS::RespawnFlagAfterDrop(TeamId teamId)
_bgEvents.CancelEvent(BG_WS_EVENT_BOTH_FLAGS_KEPT10);
_bgEvents.CancelEvent(BG_WS_EVENT_BOTH_FLAGS_KEPT15);
RemoveAssaultAuras();
+
+ CheckFlagKeeperInArea(teamId == TEAM_ALLIANCE ? TEAM_HORDE : TEAM_ALLIANCE);
+}
+
+void BattlegroundWS::CheckFlagKeeperInArea(TeamId teamId)
+{
+ if (GetStatus() != STATUS_IN_PROGRESS || GetFlagState(teamId) != BG_WS_FLAG_STATE_ON_PLAYER)
+ {
+ return;
+ }
+
+ uint32 triggerId = teamId == TEAM_ALLIANCE ? BG_WS_TRIGGER_HORDE_FLAG_SPAWN : BG_WS_TRIGGER_ALLIANCE_FLAG_SPAWN;
+ AreaTrigger const* areaTrigger = sObjectMgr->GetAreaTrigger(triggerId);
+ if (Player* player = ObjectAccessor::GetPlayer(FindBgMap(), GetFlagPickerGUID(teamId)))
+ {
+ if (areaTrigger && player->IsInAreaTriggerRadius(areaTrigger))
+ {
+ HandleAreaTrigger(player, triggerId);
+ }
+ }
}
void BattlegroundWS::EventPlayerCapturedFlag(Player* player)
@@ -287,6 +307,8 @@ void BattlegroundWS::EventPlayerClickedOnFlag(Player* player, GameObject* gameOb
_bgEvents.CancelEvent(BG_WS_EVENT_BOTH_FLAGS_KEPT10);
_bgEvents.CancelEvent(BG_WS_EVENT_BOTH_FLAGS_KEPT15);
RemoveAssaultAuras();
+
+ CheckFlagKeeperInArea(TEAM_HORDE);
return;
}
else
@@ -318,6 +340,8 @@ void BattlegroundWS::EventPlayerClickedOnFlag(Player* player, GameObject* gameOb
_bgEvents.CancelEvent(BG_WS_EVENT_BOTH_FLAGS_KEPT10);
_bgEvents.CancelEvent(BG_WS_EVENT_BOTH_FLAGS_KEPT15);
RemoveAssaultAuras();
+
+ CheckFlagKeeperInArea(TEAM_ALLIANCE);
return;
}
else
@@ -354,11 +378,11 @@ void BattlegroundWS::HandleAreaTrigger(Player* player, uint32 trigger)
switch (trigger)
{
- case 3646: // Alliance Flag spawn
+ case BG_WS_TRIGGER_ALLIANCE_FLAG_SPAWN: // Alliance Flag spawn
if (GetFlagState(TEAM_ALLIANCE) == BG_WS_FLAG_STATE_ON_BASE && GetFlagPickerGUID(TEAM_HORDE) == player->GetGUID())
EventPlayerCapturedFlag(player);
break;
- case 3647: // Horde Flag spawn
+ case BG_WS_TRIGGER_HORDE_FLAG_SPAWN: // Horde Flag spawn
if (GetFlagState(TEAM_HORDE) == BG_WS_FLAG_STATE_ON_BASE && GetFlagPickerGUID(TEAM_ALLIANCE) == player->GetGUID())
EventPlayerCapturedFlag(player);
break;
@@ -366,12 +390,12 @@ void BattlegroundWS::HandleAreaTrigger(Player* player, uint32 trigger)
case 3688: // Not used
case 4628: // Not used
case 4629: // Not used
- case 3686: // Alliance elixir of speed spawn
- case 3687: // Horde elixir of speed spawn
- case 3706: // Alliance elixir of regeneration spawn
- case 3708: // Horde elixir of regeneration spawn
- case 3707: // Alliance elixir of berserk spawn
- case 3709: // Horde elixir of berserk spawn
+ case BG_WS_TRIGGER_ALLIANCE_ELIXIR_SPEED_SPAWN: // Alliance elixir of speed spawn
+ case BG_WS_TRIGGER_HORDE_ELIXIR_SPEED_SPAWN: // Horde elixir of speed spawn
+ case BG_WS_TRIGGER_ALLIANCE_ELIXIR_REGEN_SPAWN: // Alliance elixir of regeneration spawn
+ case BG_WS_TRIGGER_HORDE_ELIXIR_REGEN_SPAWN: // Horde elixir of regeneration spawn
+ case BG_WS_TRIGGER_ALLIANCE_ELIXIR_BERSERK_SPAWN: // Alliance elixir of berserk spawn
+ case BG_WS_TRIGGER_HORDE_ELIXIR_BERSERK_SPAWN: // Horde elixir of berserk spawn
break;
}
}
diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundWS.h b/src/server/game/Battlegrounds/Zones/BattlegroundWS.h
index 31c55431c8..46f9d91dd5 100644
--- a/src/server/game/Battlegrounds/Zones/BattlegroundWS.h
+++ b/src/server/game/Battlegrounds/Zones/BattlegroundWS.h
@@ -135,6 +135,21 @@ enum BG_WS_Objectives
WS_EVENT_START_BATTLE = 8563
};
+enum BG_WS_Trigger
+{
+ BG_WS_TRIGGER_ALLIANCE_FLAG_SPAWN = 3646,
+ BG_WS_TRIGGER_HORDE_FLAG_SPAWN = 3647,
+
+ BG_WS_TRIGGER_ALLIANCE_ELIXIR_SPEED_SPAWN = 3686,
+ BG_WS_TRIGGER_HORDE_ELIXIR_SPEED_SPAWN = 3687,
+
+ BG_WS_TRIGGER_ALLIANCE_ELIXIR_REGEN_SPAWN = 3706,
+ BG_WS_TRIGGER_HORDE_ELIXIR_REGEN_SPAWN = 3708,
+
+ BG_WS_TRIGGER_ALLIANCE_ELIXIR_BERSERK_SPAWN = 3707,
+ BG_WS_TRIGGER_HORDE_ELIXIR_BERSERK_SPAWN = 3709,
+};
+
struct BattlegroundWGScore : public BattlegroundScore
{
BattlegroundWGScore(Player* player): BattlegroundScore(player), FlagCaptures(0), FlagReturns(0) { }
@@ -163,6 +178,7 @@ public:
void SetFlagPicker(ObjectGuid guid, TeamId teamId) { _flagKeepers[teamId] = guid; }
void RespawnFlagAfterDrop(TeamId teamId);
uint8 GetFlagState(TeamId teamId) const { return _flagState[teamId]; }
+ void CheckFlagKeeperInArea(TeamId teamId);
/* Battleground Events */
void EventPlayerDroppedFlag(Player* player) override;
diff --git a/src/server/game/Conditions/DisableMgr.cpp b/src/server/game/Conditions/DisableMgr.cpp
index 7aaff1d3e7..85b6b3f541 100644
--- a/src/server/game/Conditions/DisableMgr.cpp
+++ b/src/server/game/Conditions/DisableMgr.cpp
@@ -5,16 +5,16 @@
*/
#include "DisableMgr.h"
+#include "MMapFactory.h"
#include "ObjectMgr.h"
#include "OutdoorPvP.h"
#include "Player.h"
#include "SpellInfo.h"
#include "SpellMgr.h"
-#include "VMapManager2.h"
+#include "World.h"
namespace DisableMgr
{
-
namespace
{
struct DisableData
@@ -197,28 +197,28 @@ namespace DisableMgr
switch (mapEntry->map_type)
{
case MAP_COMMON:
- if (flags & VMAP_DISABLE_AREAFLAG)
+ if (flags & VMAP::VMAP_DISABLE_AREAFLAG)
LOG_INFO("server", "Areaflag disabled for world map %u.", entry);
- if (flags & VMAP_DISABLE_LIQUIDSTATUS)
+ if (flags & VMAP::VMAP_DISABLE_LIQUIDSTATUS)
LOG_INFO("server", "Liquid status disabled for world map %u.", entry);
break;
case MAP_INSTANCE:
case MAP_RAID:
- if (flags & VMAP_DISABLE_HEIGHT)
+ if (flags & VMAP::VMAP_DISABLE_HEIGHT)
LOG_INFO("server", "Height disabled for instance map %u.", entry);
- if (flags & VMAP_DISABLE_LOS)
+ if (flags & VMAP::VMAP_DISABLE_LOS)
LOG_INFO("server", "LoS disabled for instance map %u.", entry);
break;
case MAP_BATTLEGROUND:
- if (flags & VMAP_DISABLE_HEIGHT)
+ if (flags & VMAP::VMAP_DISABLE_HEIGHT)
LOG_INFO("server", "Height disabled for battleground map %u.", entry);
- if (flags & VMAP_DISABLE_LOS)
+ if (flags & VMAP::VMAP_DISABLE_LOS)
LOG_INFO("server", "LoS disabled for battleground map %u.", entry);
break;
case MAP_ARENA:
- if (flags & VMAP_DISABLE_HEIGHT)
+ if (flags & VMAP::VMAP_DISABLE_HEIGHT)
LOG_INFO("server", "Height disabled for arena map %u.", entry);
- if (flags & VMAP_DISABLE_LOS)
+ if (flags & VMAP::VMAP_DISABLE_LOS)
LOG_INFO("server", "LoS disabled for arena map %u.", entry);
break;
default:
@@ -360,4 +360,17 @@ namespace DisableMgr
return false;
}
+ bool IsVMAPDisabledFor(uint32 entry, uint8 flags)
+ {
+ return IsDisabledFor(DISABLE_TYPE_VMAP, entry, nullptr, flags);
+ }
+
+ bool IsPathfindingEnabled(const Map* map)
+ {
+ if (!map)
+ return false;
+
+ return !MMAP::MMapFactory::forbiddenMaps[map->GetId()] && (sWorld->getBoolConfig(CONFIG_ENABLE_MMAPS) ? true : map->IsBattlegroundOrArena());
+ }
+
} // Namespace
diff --git a/src/server/game/Conditions/DisableMgr.h b/src/server/game/Conditions/DisableMgr.h
index 9770c092ff..92c35d8c40 100644
--- a/src/server/game/Conditions/DisableMgr.h
+++ b/src/server/game/Conditions/DisableMgr.h
@@ -8,6 +8,8 @@
#define ACORE_DISABLEMGR_H
#include "Define.h"
+#include "Map.h"
+#include "VMapManager2.h"
class Unit;
@@ -38,19 +40,13 @@ enum SpellDisableTypes
SPELL_DISABLE_LOS)
};
-enum VmapDisableTypes
-{
- VMAP_DISABLE_AREAFLAG = 0x1,
- VMAP_DISABLE_HEIGHT = 0x2,
- VMAP_DISABLE_LOS = 0x4,
- VMAP_DISABLE_LIQUIDSTATUS = 0x8,
-};
-
namespace DisableMgr
{
void LoadDisables();
bool IsDisabledFor(DisableType type, uint32 entry, Unit const* unit, uint8 flags = 0);
void CheckQuestDisables();
+ bool IsVMAPDisabledFor(uint32 entry, uint8 flags);
+ bool IsPathfindingEnabled(const Map* map);
}
#endif //ACORE_DISABLEMGR_H
diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp
index e00bfe2348..d40716982e 100644
--- a/src/server/game/Entities/Creature/Creature.cpp
+++ b/src/server/game/Entities/Creature/Creature.cpp
@@ -2236,8 +2236,8 @@ bool Creature::_IsTargetAcceptable(const Unit* target) const
if (target->HasUnitState(UNIT_STATE_DIED))
{
- // guards can detect fake death
- if (IsGuard() && target->HasFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_FEIGN_DEATH))
+ // some creatures can detect fake death
+ if (CanIgnoreFeignDeath() && target->HasFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_FEIGN_DEATH))
return true;
else
return false;
diff --git a/src/server/game/Entities/Creature/Creature.h b/src/server/game/Entities/Creature/Creature.h
index de79c537db..3072e7ca59 100644
--- a/src/server/game/Entities/Creature/Creature.h
+++ b/src/server/game/Entities/Creature/Creature.h
@@ -44,7 +44,7 @@ enum CreatureFlagsExtra : uint32
CREATURE_FLAG_EXTRA_IGNORE_COMBAT = 0x00002000,
CREATURE_FLAG_EXTRA_WORLDEVENT = 0x00004000, // custom flag for world event creatures (left room for merging)
CREATURE_FLAG_EXTRA_GUARD = 0x00008000, // Creature is guard
- CREATURE_FLAG_EXTRA_UNUSED_17 = 0x00010000,
+ CREATURE_FLAG_EXTRA_IGNORE_FEIGN_DEATH = 0x00010000, // creature ignores feign death
CREATURE_FLAG_EXTRA_NO_CRIT = 0x00020000, // creature can't do critical strikes
CREATURE_FLAG_EXTRA_NO_SKILL_GAINS = 0x00040000, // creature won't increase weapon skills
CREATURE_FLAG_EXTRA_OBEYS_TAUNT_DIMINISHING_RETURNS = 0x00080000, // Taunt is subject to diminishing returns on this creature
@@ -62,7 +62,7 @@ enum CreatureFlagsExtra : uint32
CREATURE_FLAG_EXTRA_UNUSED_32 = 0x80000000,
// Masks
- CREATURE_FLAG_EXTRA_UNUSED = (CREATURE_FLAG_EXTRA_UNUSED_10 | CREATURE_FLAG_EXTRA_UNUSED_12 | CREATURE_FLAG_EXTRA_UNUSED_17 |
+ CREATURE_FLAG_EXTRA_UNUSED = (CREATURE_FLAG_EXTRA_UNUSED_10 | CREATURE_FLAG_EXTRA_UNUSED_12 |
CREATURE_FLAG_EXTRA_UNUSED_22 | CREATURE_FLAG_EXTRA_UNUSED_25 | CREATURE_FLAG_EXTRA_UNUSED_26 |
CREATURE_FLAG_EXTRA_UNUSED_27 | CREATURE_FLAG_EXTRA_UNUSED_28 | CREATURE_FLAG_EXTRA_UNUSED_32),
CREATURE_FLAG_EXTRA_DB_ALLOWED = (0xFFFFFFFF & ~(CREATURE_FLAG_EXTRA_UNUSED | CREATURE_FLAG_EXTRA_DUNGEON_BOSS))
@@ -635,6 +635,7 @@ public:
bool HasSearchedAssistance() { return m_AlreadySearchedAssistance; }
bool CanAssistTo(const Unit* u, const Unit* enemy, bool checkfaction = true) const;
bool _IsTargetAcceptable(const Unit* target) const;
+ bool CanIgnoreFeignDeath() const { return (GetCreatureTemplate()->flags_extra & CREATURE_FLAG_EXTRA_IGNORE_FEIGN_DEATH) != 0; }
bool _CanDetectFeignDeathOf(const Unit* target) const; // pussywizard
// pussywizard: updated at faction change, disable move in line of sight if actual faction is not hostile to anyone
diff --git a/src/server/game/Entities/Creature/CreatureGroups.h b/src/server/game/Entities/Creature/CreatureGroups.h
index c3b17bb7d4..19041c6f0f 100644
--- a/src/server/game/Entities/Creature/CreatureGroups.h
+++ b/src/server/game/Entities/Creature/CreatureGroups.h
@@ -21,8 +21,8 @@ struct FormationInfo
float follow_dist;
float follow_angle;
uint8 groupAI;
- uint16 point_1;
- uint16 point_2;
+ uint32 point_1;
+ uint32 point_2;
};
typedef std::unordered_map CreatureGroupInfoType;
diff --git a/src/server/game/Entities/GameObject/GameObject.cpp b/src/server/game/Entities/GameObject/GameObject.cpp
index 1c0d4ea152..1d3b8c3306 100644
--- a/src/server/game/Entities/GameObject/GameObject.cpp
+++ b/src/server/game/Entities/GameObject/GameObject.cpp
@@ -58,6 +58,7 @@ GameObject::GameObject() : WorldObject(false), MovableMapObject(),
m_lootGenerationTime = 0;
ResetLootMode(); // restore default loot mode
+ loot.sourceGameObject = this;
m_stationaryPosition.Relocate(0.0f, 0.0f, 0.0f, 0.0f);
}
@@ -310,7 +311,7 @@ bool GameObject::Create(ObjectGuid::LowType guidlow, uint32 name_id, Map* map, u
SetDisplayId(goinfo->displayId);
if (!m_model)
- m_model = GameObjectModel::Create(*this);
+ m_model = CreateModel();
switch (goinfo->type)
{
@@ -844,7 +845,7 @@ void GameObject::getFishLootJunk(Loot* fishloot, Player* loot_owner)
}
}
-void GameObject::SaveToDB()
+void GameObject::SaveToDB(bool saveAddon /*= false*/)
{
// this should only be used when the gameobject has already been loaded
// preferably after adding to map, because mapid may not be valid otherwise
@@ -855,10 +856,10 @@ void GameObject::SaveToDB()
return;
}
- SaveToDB(GetMapId(), data->spawnMask, data->phaseMask);
+ SaveToDB(GetMapId(), data->spawnMask, data->phaseMask, saveAddon);
}
-void GameObject::SaveToDB(uint32 mapid, uint8 spawnMask, uint32 phaseMask)
+void GameObject::SaveToDB(uint32 mapid, uint8 spawnMask, uint32 phaseMask, bool saveAddon /*= false*/)
{
const GameObjectTemplate* goI = GetGOInfo();
@@ -913,6 +914,14 @@ void GameObject::SaveToDB(uint32 mapid, uint8 spawnMask, uint32 phaseMask)
stmt->setUInt8(index++, uint8(GetGoState()));
trans->Append(stmt);
+ if (saveAddon && !sObjectMgr->GetGameObjectAddon(m_spawnId))
+ {
+ index = 0;
+ stmt = WorldDatabase.GetPreparedStatement(WORLD_INS_GAMEOBJECT_ADDON);
+ stmt->setUInt32(index++, m_spawnId);
+ trans->Append(stmt);
+ }
+
WorldDatabase.CommitTransaction(trans);
}
@@ -1952,7 +1961,7 @@ bool GameObject::IsInRange(float x, float y, float z, float radius) const
if (G3D::fuzzyEq(dist, 0.0f))
return true;
- float scale = GetFloatValue(OBJECT_FIELD_SCALE_X);
+ float scale = GetObjectScale();
float sinB = dx / dist;
float cosB = dy / dist;
dx = dist * (cosA * cosB + sinA * sinB);
@@ -2289,7 +2298,7 @@ void GameObject::UpdateModel()
if (GetMap()->ContainsGameObjectModel(*m_model))
GetMap()->RemoveGameObjectModel(*m_model);
delete m_model;
- m_model = GameObjectModel::Create(*this);
+ m_model = CreateModel();
if (m_model)
GetMap()->InsertGameObjectModel(*m_model);
}
@@ -2508,4 +2517,26 @@ void GameObject::UpdateModelPosition()
}
}
-std::unordered_map GameObject::gameObjectToEventFlag = {};
+std::unordered_map GameObject::gameObjectToEventFlag = { };
+
+class GameObjectModelOwnerImpl : public GameObjectModelOwnerBase
+{
+public:
+ explicit GameObjectModelOwnerImpl(GameObject* owner) : _owner(owner) { }
+
+ bool IsSpawned() const override { return _owner->isSpawned(); }
+ uint32 GetDisplayId() const override { return _owner->GetDisplayId(); }
+ uint32 GetPhaseMask() const override { return (_owner->GetGoState() == GO_STATE_READY || _owner->IsTransport()) ? _owner->GetPhaseMask() : 0; }
+ G3D::Vector3 GetPosition() const override { return G3D::Vector3(_owner->GetPositionX(), _owner->GetPositionY(), _owner->GetPositionZ()); }
+ float GetOrientation() const override { return _owner->GetOrientation(); }
+ float GetScale() const override { return _owner->GetObjectScale(); }
+ void DebugVisualizeCorner(G3D::Vector3 const& corner) const override { const_cast(_owner)->SummonCreature(1, corner.x, corner.y, corner.z, 0.0f, TEMPSUMMON_TIMED_DESPAWN, 10000); }
+
+private:
+ GameObject* _owner;
+};
+
+GameObjectModel* GameObject::CreateModel()
+{
+ return GameObjectModel::Create(std::make_unique(this), sWorld->GetDataPath());
+}
diff --git a/src/server/game/Entities/GameObject/GameObject.h b/src/server/game/Entities/GameObject/GameObject.h
index aa88c63bcf..e139f39f81 100644
--- a/src/server/game/Entities/GameObject/GameObject.h
+++ b/src/server/game/Entities/GameObject/GameObject.h
@@ -759,8 +759,8 @@ public:
// overwrite WorldObject function for proper name localization
[[nodiscard]] std::string const& GetNameForLocaleIdx(LocaleConstant locale_idx) const override;
- void SaveToDB();
- void SaveToDB(uint32 mapid, uint8 spawnMask, uint32 phaseMask);
+ void SaveToDB(bool saveAddon = false);
+ void SaveToDB(uint32 mapid, uint8 spawnMask, uint32 phaseMask, bool saveAddon = false);
bool LoadFromDB(ObjectGuid::LowType guid, Map* map) { return LoadGameObjectFromDB(guid, map, false); }
bool LoadGameObjectFromDB(ObjectGuid::LowType guid, Map* map, bool addToMap = true);
void DeleteFromDB();
@@ -953,6 +953,7 @@ public:
protected:
bool AIM_Initialize();
+ GameObjectModel* CreateModel();
void UpdateModel(); // updates model in case displayId were changed
uint32 m_spellId;
time_t m_respawnTime; // (secs) time of next respawn (or despawn if GO have owner()),
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index adcdc73a26..992b0d8af7 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -1824,6 +1824,8 @@ void Player::Update(uint32 p_time)
m_zoneUpdateTimer -= p_time;
}
+ sScriptMgr->OnPlayerUpdate(this, p_time);
+
if (IsAlive())
{
m_regenTimer += p_time;
@@ -2221,6 +2223,9 @@ void Player::SendTeleportAckPacket()
bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientation, uint32 options /*= 0*/, Unit* target /*= nullptr*/)
{
+ // for except kick by antispeedhack
+ sScriptMgr->AnticheatSetSkipOnePacketForASH(this, true);
+
if (!MapManager::IsValidMapCoord(mapid, x, y, z, orientation))
{
LOG_ERROR("server", "TeleportTo: invalid map (%d) or invalid coordinates (X: %f, Y: %f, Z: %f, O: %f) given when teleporting player (%s, name: %s, map: %d, X: %f, Y: %f, Z: %f, O: %f).",
@@ -24857,7 +24862,7 @@ void Player::ResurectUsingRequestData()
void Player::SetClientControl(Unit* target, bool allowMove, bool packetOnly /*= false*/)
{
WorldPacket data(SMSG_CLIENT_CONTROL_UPDATE, target->GetPackGUID().size() + 1);
- data.append(target->GetPackGUID());
+ data << target->GetPackGUID();
data << uint8((allowMove && !target->HasUnitState(UNIT_STATE_FLEEING | UNIT_STATE_CONFUSED)) ? 1 : 0);
GetSession()->SendPacket(&data);
@@ -25843,7 +25848,7 @@ void Player::StoreLootItem(uint8 lootSlot, Loot* loot)
// Xinef: exploit protection, dont allow to loot normal items if player is not master loot and not below loot threshold
// Xinef: only quest, ffa and conditioned items
- if (!item->is_underthreshold && !GetLootGUID().IsItem() && GetGroup() && GetGroup()->GetLootMethod() == MASTER_LOOT && GetGUID() != GetGroup()->GetMasterLooterGuid())
+ if (!item->is_underthreshold && loot->roundRobinPlayer && !GetLootGUID().IsItem() && GetGroup() && GetGroup()->GetLootMethod() == MASTER_LOOT && GetGUID() != GetGroup()->GetMasterLooterGuid())
if (qitem == nullptr && ffaitem == nullptr && conditem == nullptr)
{
SendLootRelease(GetLootGUID());
@@ -28125,6 +28130,8 @@ bool Player::SetDisableGravity(bool disable, bool packetOnly /*= false*/)
bool Player::SetCanFly(bool apply, bool packetOnly /*= false*/)
{
+ sScriptMgr->AnticheatSetCanFlybyServer(this, apply);
+
if (!packetOnly && !Unit::SetCanFly(apply))
return false;
diff --git a/src/server/game/Entities/Transport/Transport.cpp b/src/server/game/Entities/Transport/Transport.cpp
index 1abbe77ecc..002906ab24 100644
--- a/src/server/game/Entities/Transport/Transport.cpp
+++ b/src/server/game/Entities/Transport/Transport.cpp
@@ -91,7 +91,7 @@ bool MotionTransport::CreateMoTrans(ObjectGuid::LowType guidlow, uint32 entry, u
// pussywizard: no PathRotation for MotionTransports
SetTransportPathRotation(0.0f, 0.0f, 0.0f, 1.0f);
- m_model = GameObjectModel::Create(*this);
+ m_model = CreateModel();
return true;
}
@@ -722,7 +722,7 @@ bool StaticTransport::Create(ObjectGuid::LowType guidlow, uint32 name_id, Map* m
SetDisplayId(goinfo->displayId);
if (!m_model)
- m_model = GameObjectModel::Create(*this);
+ m_model = CreateModel();
SetGoType(GameobjectTypes(goinfo->type));
SetGoState(go_state);
diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp
index d79c8371fe..f9e63895e7 100644
--- a/src/server/game/Entities/Unit/Unit.cpp
+++ b/src/server/game/Entities/Unit/Unit.cpp
@@ -16,6 +16,7 @@
#include "CreatureAI.h"
#include "CreatureAIImpl.h"
#include "CreatureGroups.h"
+#include "DisableMgr.h"
#include "DynamicVisibility.h"
#include "Formulas.h"
#include "GridNotifiersImpl.h"
@@ -1612,8 +1613,12 @@ void Unit::DealMeleeDamage(CalcDamageInfo* damageInfo, bool durabilityLoss)
if (Unit* caster = (*dmgShieldItr)->GetCaster())
damage = this->SpellDamageBonusTaken(caster, i_spellProto, damage, SPELL_DIRECT_DAMAGE);
- // No Unit::CalcAbsorbResist here - opcode doesn't send that data - this damage is probably not affected by that
- Unit::DealDamageMods(this, damage, nullptr);
+ uint32 absorb = 0;
+ uint32 resist = 0;
+ Unit::CalcAbsorbResist(victim, this, i_spellProto->GetSchoolMask(), SPELL_DIRECT_DAMAGE, damage, &absorb, &resist, i_spellProto);
+ damage -= absorb + resist;
+
+ Unit::DealDamageMods(this, damage, &absorb);
// TODO: Move this to a packet handler
WorldPacket data(SMSG_SPELLDAMAGESHIELD, (8 + 8 + 4 + 4 + 4 + 4));
@@ -1623,7 +1628,7 @@ void Unit::DealMeleeDamage(CalcDamageInfo* damageInfo, bool durabilityLoss)
data << uint32(damage); // Damage
int32 overkill = int32(damage) - int32(GetHealth());
data << uint32(overkill > 0 ? overkill : 0); // Overkill
- data << uint32(i_spellProto->SchoolMask);
+ data << uint32(i_spellProto->GetSchoolMask());
victim->SendMessageToSet(&data, true);
Unit::DealDamage(victim, this, damage, 0, SPELL_DIRECT_DAMAGE, i_spellProto->GetSchoolMask(), i_spellProto, true);
@@ -2230,24 +2235,24 @@ void Unit::AttackerStateUpdate(Unit* victim, WeaponAttackType attType, bool extr
}
}
-Position* Unit::GetMeleeAttackPoint(Unit* attacker)
+bool Unit::GetMeleeAttackPoint(Unit* attacker, Position& pos)
{
if (!attacker)
{
- return nullptr;
+ return false;
}
AttackerSet attackers = getAttackers();
if (attackers.size() <= 1) // if the attackers are not more than one
{
- return nullptr;
+ return false;
}
float meleeReach = GetExactDist2d(attacker);
if (meleeReach <= 0)
{
- return nullptr;
+ return false;
}
float minAngle = 0;
@@ -2259,17 +2264,13 @@ Position* Unit::GetMeleeAttackPoint(Unit* attacker)
for (const auto& otherAttacker: attackers)
{
// if the otherAttacker is not valid, skip
- if (!otherAttacker ||
- otherAttacker->GetGUID() == attacker->GetGUID() ||
- !otherAttacker->IsWithinMeleeRange(this) ||
- otherAttacker->isMoving()
- )
+ if (!otherAttacker || otherAttacker->GetGUID() == attacker->GetGUID() ||
+ !otherAttacker->IsWithinMeleeRange(this) || otherAttacker->isMoving())
{
continue;
}
float curretAngle = atan(attacker->GetExactDist2d(otherAttacker) / meleeReach);
-
if (minAngle == 0 || curretAngle < minAngle)
{
minAngle = curretAngle;
@@ -2280,7 +2281,9 @@ Position* Unit::GetMeleeAttackPoint(Unit* attacker)
}
if (!validAttackers || !refUnit)
- return nullptr;
+ {
+ return false;
+ }
float contactDist = attackerSize + refUnit->GetCollisionRadius();
float requiredAngle = atan(contactDist / meleeReach);
@@ -2292,7 +2295,7 @@ Position* Unit::GetMeleeAttackPoint(Unit* attacker)
if (attackersAngle > angleTollerance)
{
- return nullptr;
+ return false;
}
double angle = atan(contactDist / meleeReach);
@@ -2312,11 +2315,13 @@ Position* Unit::GetMeleeAttackPoint(Unit* attacker)
if (!GetMap()->CanReachPositionAndGetValidCoords(this, x, y, z, true, true))
{
- return nullptr;
+ return false;
}
}
- return new Position(x,y,z);
+ pos.Relocate(x, y, z);
+
+ return true;
}
void Unit::HandleProcExtraAttackFor(Unit* victim)
@@ -11237,25 +11242,7 @@ uint32 Unit::SpellDamageBonusTaken(Unit* caster, SpellInfo const* spellProto, ui
if (spellProto->ValidateAttribute6SpellDamageMods(caster, *i, damagetype == DOT))
AddPct(TakenTotalMod, (*i)->GetAmount());
- // .. taken pct: dummy auras
- AuraEffectList const& mDummyAuras = GetAuraEffectsByType(SPELL_AURA_DUMMY);
- for (AuraEffectList::const_iterator i = mDummyAuras.begin(); i != mDummyAuras.end(); ++i)
- {
- switch ((*i)->GetSpellInfo()->SpellIconID)
- {
- // Cheat Death
- case 2109:
- if ((*i)->GetMiscValue() & SPELL_SCHOOL_MASK_NORMAL)
- {
- // Patch 2.4.3: The resilience required to reach the 90% damage reduction cap
- // is 22.5% critical strike damage reduction, or 444 resilience.
- // To calculate for 90%, we multiply the 100% by 4 (22.5% * 4 = 90%)
- float mod = -1.0f * GetMeleeCritDamageReduction(400);
- AddPct(TakenTotalMod, std::max(mod, float((*i)->GetAmount())));
- }
- break;
- }
- }
+ TakenTotalMod = processDummyAuras(TakenTotalMod);
// From caster spells
if (caster)
@@ -11350,6 +11337,41 @@ uint32 Unit::SpellDamageBonusTaken(Unit* caster, SpellInfo const* spellProto, ui
return uint32(std::max(tmpDamage, 0.0f));
}
+float Unit::processDummyAuras(float TakenTotalMod) const
+{
+ // note: old code coming from TC, just extracted here to remove the code duplication + solve potential crash
+ // see: https://github.com/TrinityCore/TrinityCore/commit/c85710e148d75450baedf6632b9ca6fd40b4148e
+
+ // .. taken pct: dummy auras
+ auto const& mDummyAuras = GetAuraEffectsByType(SPELL_AURA_DUMMY);
+ for (auto i = mDummyAuras.begin(); i != mDummyAuras.end(); ++i)
+ {
+ if (!(*i) || !(*i)->GetSpellInfo())
+ {
+ continue;
+ }
+
+ if (auto spellIconId = (*i)->GetSpellInfo()->SpellIconID)
+ {
+ switch (spellIconId)
+ {
+ // Cheat Death
+ case 2109:
+ if ((*i)->GetMiscValue() & SPELL_SCHOOL_MASK_NORMAL)
+ {
+ // Patch 2.4.3: The resilience required to reach the 90% damage reduction cap
+ // is 22.5% critical strike damage reduction, or 444 resilience.
+ // To calculate for 90%, we multiply the 100% by 4 (22.5% * 4 = 90%)
+ float mod = -1.0f * GetMeleeCritDamageReduction(400);
+ AddPct(TakenTotalMod, std::max(mod, float((*i)->GetAmount())));
+ }
+ break;
+ }
+ }
+ }
+ return TakenTotalMod;
+}
+
int32 Unit::SpellBaseDamageBonusDone(SpellSchoolMask schoolMask)
{
int32 DoneAdvertisedBenefit = 0;
@@ -12587,25 +12609,7 @@ uint32 Unit::MeleeDamageBonusTaken(Unit* attacker, uint32 pdamage, WeaponAttackT
}
}
- // .. taken pct: dummy auras
- AuraEffectList const& mDummyAuras = GetAuraEffectsByType(SPELL_AURA_DUMMY);
- for (AuraEffectList::const_iterator i = mDummyAuras.begin(); i != mDummyAuras.end(); ++i)
- {
- switch ((*i)->GetSpellInfo()->SpellIconID)
- {
- // Cheat Death
- case 2109:
- if ((*i)->GetMiscValue() & SPELL_SCHOOL_MASK_NORMAL)
- {
- // Patch 2.4.3: The resilience required to reach the 90% damage reduction cap
- // is 22.5% critical strike damage reduction, or 444 resilience.
- // To calculate for 90%, we multiply the 100% by 4 (22.5% * 4 = 90%)
- float mod = -1.0f * GetMeleeCritDamageReduction(400);
- AddPct(TakenTotalMod, std::max(mod, float((*i)->GetAmount())));
- }
- break;
- }
- }
+ TakenTotalMod = processDummyAuras(TakenTotalMod);
// .. taken pct: class scripts
/*AuraEffectList const& mclassScritAuras = GetAuraEffectsByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
@@ -12755,6 +12759,8 @@ void Unit::Mount(uint32 mount, uint32 VehicleId, uint32 creatureEntry)
if (Player* player = ToPlayer())
{
+ sScriptMgr->AnticheatSetUnderACKmount(player);
+
// mount as a vehicle
if (VehicleId)
{
@@ -12843,6 +12849,8 @@ void Unit::Dismount()
// (it could probably happen when logging in after a previous crash)
if (Player* player = ToPlayer())
{
+ sScriptMgr->AnticheatSetUnderACKmount(player);
+
if (Pet* pPet = player->GetPet())
{
if (pPet->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED) && !pPet->HasUnitState(UNIT_STATE_STUNNED))
@@ -17288,6 +17296,11 @@ void Unit::SetControlled(bool apply, UnitState state)
default:
break;
}
+
+ if (GetTypeId() == TYPEID_PLAYER)
+ {
+ sScriptMgr->AnticheatSetRootACKUpd(ToPlayer());
+ }
}
else
{
@@ -17379,7 +17392,10 @@ void Unit::SetStunned(bool apply)
if (GetTypeId() != TYPEID_PLAYER)
StopMoving();
else
+ {
SetStandState(UNIT_STAND_STATE_STAND);
+ sScriptMgr->AnticheatSetSkipOnePacketForASH(ToPlayer(), true);
+ }
CastStop();
}
@@ -17443,6 +17459,8 @@ void Unit::SetRooted(bool apply)
data << GetPackGUID();
data << m_rootTimes;
SendMessageToSet(&data, true);
+
+ sScriptMgr->AnticheatSetSkipOnePacketForASH(ToPlayer(), true);
}
else
{
@@ -17499,6 +17517,11 @@ void Unit::SetFeared(bool apply)
if (!caster)
caster = getAttackerForHelper();
GetMotionMaster()->MoveFleeing(caster, fearAuras.empty() ? sWorld->getIntConfig(CONFIG_CREATURE_FAMILY_FLEE_DELAY) : 0); // caster == nullptr processed in MoveFleeing
+
+ if (GetTypeId() == TYPEID_PLAYER)
+ {
+ sScriptMgr->AnticheatSetSkipOnePacketForASH(ToPlayer(), true);
+ }
}
else
{
@@ -17531,6 +17554,11 @@ void Unit::SetConfused(bool apply)
{
SetTarget();
GetMotionMaster()->MoveConfused();
+
+ if (GetTypeId() == TYPEID_PLAYER)
+ {
+ sScriptMgr->AnticheatSetSkipOnePacketForASH(ToPlayer(), true);
+ }
}
else
{
@@ -17859,6 +17887,11 @@ void Unit::RemoveCharmedBy(Unit* charmer)
}
}
+ if (Player* player = ToPlayer())
+ {
+ sScriptMgr->AnticheatSetUnderACKmount(player);
+ }
+
// xinef: restore threat
for (CharmThreatMap::const_iterator itr = _charmThreatInfo.begin(); itr != _charmThreatInfo.end(); ++itr)
{
@@ -18358,6 +18391,8 @@ void Unit::KnockbackFrom(float x, float y, float speedXY, float speedZ)
if (player->HasAuraType(SPELL_AURA_MOD_INCREASE_MOUNTED_FLIGHT_SPEED) || player->HasAuraType(SPELL_AURA_FLY))
player->SetCanFly(true, true);
+
+ sScriptMgr->AnticheatSetSkipOnePacketForASH(player, true);
}
}
@@ -18792,6 +18827,12 @@ bool Unit::HandleSpellClick(Unit* clicker, int8 seatId)
void Unit::EnterVehicle(Unit* base, int8 seatId)
{
CastCustomSpell(VEHICLE_SPELL_RIDE_HARDCODED, SPELLVALUE_BASE_POINT0, seatId + 1, base, TRIGGERED_IGNORE_CASTER_MOUNTED_OR_ON_VEHICLE);
+
+ if (Player* player = ToPlayer())
+ {
+ sScriptMgr->AnticheatSetUnderACKmount(player);
+ sScriptMgr->AnticheatSetSkipOnePacketForASH(player, true);
+ }
}
void Unit::EnterVehicleUnattackable(Unit* base, int8 seatId)
@@ -18836,6 +18877,9 @@ void Unit::_EnterVehicle(Vehicle* vehicle, int8 seatId, AuraApplication const* a
if (vehicle->GetBase()->GetTypeId() == TYPEID_PLAYER && player->IsInCombat())
return;
+ sScriptMgr->AnticheatSetUnderACKmount(player);
+ sScriptMgr->AnticheatSetSkipOnePacketForASH(player, true);
+
InterruptNonMeleeSpells(false);
player->StopCastingCharm();
player->StopCastingBindSight();
@@ -18899,6 +18943,12 @@ void Unit::ExitVehicle(Position const* /*exitPosition*/)
//! init spline movement based on those coordinates in unapply handlers, and
//! relocate exiting passengers based on Unit::moveSpline data. Either way,
//! Coming Soon(TM)
+
+ if (Player* player = ToPlayer())
+ {
+ sScriptMgr->AnticheatSetUnderACKmount(player);
+ sScriptMgr->AnticheatSetSkipOnePacketForASH(player, true);
+ }
}
bool VehicleDespawnEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/)
@@ -18954,7 +19004,12 @@ void Unit::_ExitVehicle(Position const* exitPosition)
AddUnitState(UNIT_STATE_MOVE);
if (player)
+ {
player->SetFallInformation(time(nullptr), GetPositionZ());
+
+ sScriptMgr->AnticheatSetUnderACKmount(player);
+ sScriptMgr->AnticheatSetSkipOnePacketForASH(player, true);
+ }
else if (HasUnitMovementFlag(MOVEMENTFLAG_ROOT))
{
WorldPacket data(SMSG_SPLINE_MOVE_UNROOT, 8);
@@ -19515,7 +19570,7 @@ void Unit::PetSpellFail(const SpellInfo* spellInfo, Unit* target, uint32 result)
if (!charmInfo || GetTypeId() != TYPEID_UNIT)
return;
- if ((MMAP::MMapFactory::IsPathfindingEnabled(GetMap()) || result != SPELL_FAILED_LINE_OF_SIGHT) && target)
+ if ((DisableMgr::IsPathfindingEnabled(GetMap()) || result != SPELL_FAILED_LINE_OF_SIGHT) && target)
{
if ((result == SPELL_FAILED_LINE_OF_SIGHT || result == SPELL_FAILED_OUT_OF_RANGE) || !ToCreature()->HasReactState(REACT_PASSIVE))
if (Unit* owner = GetOwner())
diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h
index f7d25cdee1..4f61395fbd 100644
--- a/src/server/game/Entities/Unit/Unit.h
+++ b/src/server/game/Entities/Unit/Unit.h
@@ -500,17 +500,18 @@ enum UnitState
| UNIT_STATE_EVADE | UNIT_STATE_ROAMING_MOVE | UNIT_STATE_CONFUSED_MOVE | UNIT_STATE_FLEEING_MOVE
| UNIT_STATE_CHASE_MOVE | UNIT_STATE_FOLLOW_MOVE | UNIT_STATE_IGNORE_PATHFINDING | UNIT_STATE_NO_ENVIRONMENT_UPD,
- UNIT_STATE_UNATTACKABLE = UNIT_STATE_IN_FLIGHT,
+ UNIT_STATE_UNATTACKABLE = UNIT_STATE_IN_FLIGHT,
// for real move using movegen check and stop (except unstoppable flight)
- UNIT_STATE_MOVING = UNIT_STATE_ROAMING_MOVE | UNIT_STATE_CONFUSED_MOVE | UNIT_STATE_FLEEING_MOVE | UNIT_STATE_CHASE_MOVE | UNIT_STATE_FOLLOW_MOVE,
- UNIT_STATE_CONTROLLED = (UNIT_STATE_CONFUSED | UNIT_STATE_STUNNED | UNIT_STATE_FLEEING),
- UNIT_STATE_LOST_CONTROL = (UNIT_STATE_CONTROLLED | UNIT_STATE_JUMPING | UNIT_STATE_CHARGING),
- UNIT_STATE_SIGHTLESS = (UNIT_STATE_LOST_CONTROL | UNIT_STATE_EVADE),
- UNIT_STATE_CANNOT_AUTOATTACK = (UNIT_STATE_LOST_CONTROL | UNIT_STATE_CASTING),
- UNIT_STATE_CANNOT_TURN = (UNIT_STATE_LOST_CONTROL | UNIT_STATE_ROTATING | UNIT_STATE_ROOT),
+ UNIT_STATE_MOVING = UNIT_STATE_ROAMING_MOVE | UNIT_STATE_CONFUSED_MOVE | UNIT_STATE_FLEEING_MOVE | UNIT_STATE_CHASE_MOVE | UNIT_STATE_FOLLOW_MOVE,
+ UNIT_STATE_CONTROLLED = (UNIT_STATE_CONFUSED | UNIT_STATE_STUNNED | UNIT_STATE_FLEEING),
+ UNIT_STATE_LOST_CONTROL = (UNIT_STATE_CONTROLLED | UNIT_STATE_JUMPING | UNIT_STATE_CHARGING),
+ UNIT_STATE_SIGHTLESS = (UNIT_STATE_LOST_CONTROL | UNIT_STATE_EVADE),
+ UNIT_STATE_CANNOT_AUTOATTACK = (UNIT_STATE_LOST_CONTROL | UNIT_STATE_CASTING),
+ UNIT_STATE_CANNOT_TURN = (UNIT_STATE_LOST_CONTROL | UNIT_STATE_ROTATING | UNIT_STATE_ROOT),
// stay by different reasons
- UNIT_STATE_NOT_MOVE = UNIT_STATE_ROOT | UNIT_STATE_STUNNED | UNIT_STATE_DIED | UNIT_STATE_DISTRACTED,
- UNIT_STATE_ALL_STATE = 0xffffffff //(UNIT_STATE_STOPPED | UNIT_STATE_MOVING | UNIT_STATE_IN_COMBAT | UNIT_STATE_IN_FLIGHT)
+ UNIT_STATE_NOT_MOVE = UNIT_STATE_ROOT | UNIT_STATE_STUNNED | UNIT_STATE_DIED | UNIT_STATE_DISTRACTED,
+ UNIT_STATE_IGNORE_ANTISPEEDHACK = UNIT_STATE_FLEEING | UNIT_STATE_CONFUSED | UNIT_STATE_CHARGING | UNIT_STATE_DISTRACTED | UNIT_STATE_POSSESSED,
+ UNIT_STATE_ALL_STATE = 0xffffffff //(UNIT_STATE_STOPPED | UNIT_STATE_MOVING | UNIT_STATE_IN_COMBAT | UNIT_STATE_IN_FLIGHT)
};
enum UnitMoveType
@@ -1467,7 +1468,7 @@ public:
bool AttackStop();
void RemoveAllAttackers();
[[nodiscard]] AttackerSet const& getAttackers() const { return m_attackers; }
- [[nodiscard]] Position* GetMeleeAttackPoint(Unit* attacker);
+ [[nodiscard]] bool GetMeleeAttackPoint(Unit* attacker, Position& pos);
[[nodiscard]] bool isAttackingPlayer() const;
[[nodiscard]] Unit* GetVictim() const { return m_attacking; }
@@ -2620,6 +2621,8 @@ private:
uint32 _oldFactionId; ///< faction before charm
bool m_petCatchUp;
+
+ float processDummyAuras(float TakenTotalMod) const;
};
namespace acore
diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp
index 759480b648..477c5e091e 100644
--- a/src/server/game/Globals/ObjectMgr.cpp
+++ b/src/server/game/Globals/ObjectMgr.cpp
@@ -423,14 +423,15 @@ void ObjectMgr::LoadGossipMenuItemsLocales()
uint16 MenuID = fields[0].GetUInt16();
uint16 OptionID = fields[1].GetUInt16();
std::string LocaleName = fields[2].GetString();
- std::string OptionText = fields[3].GetString();
- std::string BoxText = fields[4].GetString();
- GossipMenuItemsLocale& data = _gossipMenuItemsLocaleStore[MAKE_PAIR32(MenuID, OptionID)];
LocaleConstant locale = GetLocaleByName(LocaleName);
if (locale == LOCALE_enUS)
continue;
+ std::string OptionText = fields[3].GetString();
+ std::string BoxText = fields[4].GetString();
+
+ GossipMenuItemsLocale& data = _gossipMenuItemsLocaleStore[MAKE_PAIR32(MenuID, OptionID)];
AddLocaleString(OptionText, locale, data.OptionText);
AddLocaleString(BoxText, locale, data.BoxText);
} while (result->NextRow());
diff --git a/src/server/game/Grids/GridDefines.h b/src/server/game/Grids/GridDefines.h
index deaf07835e..1f0b957547 100644
--- a/src/server/game/Grids/GridDefines.h
+++ b/src/server/game/Grids/GridDefines.h
@@ -9,6 +9,7 @@
#include "Common.h"
#include "NGrid.h"
+#include "MapDefines.h"
#include
// Forward class definitions
@@ -22,10 +23,7 @@ class ObjectGuid;
#define MAX_NUMBER_OF_CELLS 8
-#define MAX_NUMBER_OF_GRIDS 64
-
-#define SIZE_OF_GRIDS 533.3333f
-#define CENTER_GRID_ID (MAX_NUMBER_OF_GRIDS/2)
+#define CENTER_GRID_ID (MAX_NUMBER_OF_GRIDS/2)
#define CENTER_GRID_OFFSET (SIZE_OF_GRIDS/2)
diff --git a/src/server/game/Grids/Notifiers/GridNotifiers.h b/src/server/game/Grids/Notifiers/GridNotifiers.h
index 84f4b27610..1b97b7fe06 100644
--- a/src/server/game/Grids/Notifiers/GridNotifiers.h
+++ b/src/server/game/Grids/Notifiers/GridNotifiers.h
@@ -931,7 +931,7 @@ namespace acore
bool operator()(Unit* u)
{
if (u->isTargetableForAttack(true, i_funit) && i_obj->IsWithinDistInMap(u, i_range) &&
- !i_funit->IsFriendlyTo(u) && i_funit->CanSeeOrDetect(u))
+ (i_funit->IsInCombatWith(u) || i_funit->IsHostileTo(u)) && i_obj->CanSeeOrDetect(u))
{
i_range = i_obj->GetDistance(u); // use found unit range as new range limit for next check
return true;
diff --git a/src/server/game/Groups/Group.cpp b/src/server/game/Groups/Group.cpp
index bc4f39d9ac..ba03535bac 100644
--- a/src/server/game/Groups/Group.cpp
+++ b/src/server/game/Groups/Group.cpp
@@ -557,10 +557,6 @@ bool Group::RemoveMember(ObjectGuid guid, const RemoveMethod& method /*= GROUP_R
CharacterDatabase.Execute(stmt);
}
- // Reevaluate group enchanter if the leaving player had enchanting skill or the player is offline
- if (!player || player->GetSkillValue(SKILL_ENCHANTING))
- ResetMaxEnchantingLevel();
-
// Remove player from loot rolls
for (Rolls::iterator it = RollId.begin(); it != RollId.end();)
{
@@ -602,6 +598,12 @@ bool Group::RemoveMember(ObjectGuid guid, const RemoveMethod& method /*= GROUP_R
sWorld->UpdateGlobalPlayerGroup(guid.GetCounter(), 0);
}
+ // Reevaluate group enchanter if the leaving player had enchanting skill or the player is offline
+ if (!player || player->GetSkillValue(SKILL_ENCHANTING))
+ {
+ ResetMaxEnchantingLevel();
+ }
+
// Pick new leader if necessary
bool validLeader = true;
if (m_leaderGuid == guid)
@@ -1493,6 +1495,16 @@ void Group::CountTheRoll(Rolls::iterator rollI, Map* allowedMap)
item->is_blocked = false;
}
+ if (Loot* loot = roll->getLoot(); loot && loot->isLooted() && loot->sourceGameObject)
+ {
+ const GameObjectTemplate* goInfo = loot->sourceGameObject->GetGOInfo();
+ if (goInfo && goInfo->type == GAMEOBJECT_TYPE_CHEST)
+ {
+ // Deactivate chest if the last item was rolled in group
+ loot->sourceGameObject->SetLootState(GO_JUST_DEACTIVATED);
+ }
+ }
+
RollId.erase(rollI);
delete roll;
}
@@ -2047,8 +2059,11 @@ void Group::ResetMaxEnchantingLevel()
for (member_citerator citr = m_memberSlots.begin(); citr != m_memberSlots.end(); ++citr)
{
pMember = ObjectAccessor::FindPlayer(citr->guid);
- if (pMember && m_maxEnchantingLevel < pMember->GetSkillValue(SKILL_ENCHANTING))
+ if (pMember && pMember->GetSession() && !pMember->GetSession()->IsSocketClosed()
+ && m_maxEnchantingLevel < pMember->GetSkillValue(SKILL_ENCHANTING))
+ {
m_maxEnchantingLevel = pMember->GetSkillValue(SKILL_ENCHANTING);
+ }
}
}
diff --git a/src/server/game/Guilds/Guild.cpp b/src/server/game/Guilds/Guild.cpp
index 41b03c6a1c..5022cc61f6 100644
--- a/src/server/game/Guilds/Guild.cpp
+++ b/src/server/game/Guilds/Guild.cpp
@@ -1517,7 +1517,7 @@ void Guild::HandleInviteMember(WorldSession* session, std::string const& name)
if (pInvitee->GetSocial()->HasIgnore(player->GetGUID()))
return;
- if (!sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GUILD) && pInvitee->GetTeamId() != player->GetTeamId())
+ if (!sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GUILD) && pInvitee->GetTeamId(true) != player->GetTeamId(true))
{
SendCommandResult(session, GUILD_COMMAND_INVITE, ERR_GUILD_NOT_ALLIED, name);
return;
diff --git a/src/server/game/Handlers/MiscHandler.cpp b/src/server/game/Handlers/MiscHandler.cpp
index 15d70f4f23..67d9ecdc5d 100644
--- a/src/server/game/Handlers/MiscHandler.cpp
+++ b/src/server/game/Handlers/MiscHandler.cpp
@@ -1623,8 +1623,7 @@ void WorldSession::HandleMoveSetCanFlyAckOpcode(WorldPacket& recv_data)
ObjectGuid guid;
recv_data >> guid.ReadAsPacked();
- // pussywizard: typical check for incomming movement packets
- if (!_player->m_mover || !_player->m_mover->IsInWorld() || _player->m_mover->IsDuringRemoveFromWorld() || guid != _player->m_mover->GetGUID())
+ if (!_player)
{
recv_data.rfinish(); // prevent warnings spam
return;
@@ -1638,6 +1637,8 @@ void WorldSession::HandleMoveSetCanFlyAckOpcode(WorldPacket& recv_data)
recv_data.read_skip(); // unk2
+ sScriptMgr->AnticheatSetCanFlybyServer(_player, movementInfo.HasMovementFlag(MOVEMENTFLAG_CAN_FLY));
+
_player->m_mover->m_movementInfo.flags = movementInfo.GetMovementFlags();
}
diff --git a/src/server/game/Handlers/MovementHandler.cpp b/src/server/game/Handlers/MovementHandler.cpp
index d30e1458b6..6c0992c2d0 100644
--- a/src/server/game/Handlers/MovementHandler.cpp
+++ b/src/server/game/Handlers/MovementHandler.cpp
@@ -13,6 +13,7 @@
#include "Corpse.h"
#include "GameGraveyard.h"
#include "InstanceSaveMgr.h"
+#include "Language.h"
#include "Log.h"
#include "MathUtil.h"
#include "MapManager.h"
@@ -26,6 +27,7 @@
#include "WaypointMovementGenerator.h"
#include "WorldPacket.h"
#include "WorldSession.h"
+#include "Vehicle.h"
#define MOVEMENT_PACKET_TIME_DELAY 0
@@ -328,8 +330,8 @@ void WorldSession::HandleMovementOpcodes(WorldPacket& recvData)
return;
}
- // pussywizard: typical check for incomming movement packets
- if (!mover || !(mover->IsInWorld()) || mover->IsDuringRemoveFromWorld() || !(mover->movespline->Finalized()))
+ // pussywizard: typical check for incomming movement packets | prevent tampered movement data
+ if (!mover || !(mover->IsInWorld()) || mover->IsDuringRemoveFromWorld() || guid != mover->GetGUID())
{
recvData.rfinish(); // prevent warnings spam
return;
@@ -341,30 +343,69 @@ void WorldSession::HandleMovementOpcodes(WorldPacket& recvData)
if (!movementInfo.pos.IsPositionValid())
{
+ if (plrMover)
+ {
+ sScriptMgr->AnticheatSetSkipOnePacketForASH(plrMover, true);
+ sScriptMgr->AnticheatUpdateMovementInfo(plrMover, movementInfo);
+ }
+
recvData.rfinish(); // prevent warnings spam
return;
}
- recvData.rfinish(); // prevent warnings spam
-
- if (movementInfo.flags & MOVEMENTFLAG_ONTRANSPORT)
+ if (!mover->movespline->Finalized())
{
- // T_POS ON VEHICLES!
- if (mover->GetVehicle())
- movementInfo.transport.pos = mover->m_movementInfo.transport.pos;
+ recvData.rfinish(); // prevent warnings spam
+ return;
+ }
- // transports size limited
- // (also received at zeppelin leave by some reason with t_* as absolute in continent coordinates, can be safely skipped)
- if (movementInfo.transport.pos.GetPositionX() > 75.0f || movementInfo.transport.pos.GetPositionY() > 75.0f || movementInfo.transport.pos.GetPositionZ() > 75.0f ||
- movementInfo.transport.pos.GetPositionX() < -75.0f || movementInfo.transport.pos.GetPositionY() < -75.0f || movementInfo.transport.pos.GetPositionZ() < -75.0f)
+ // Xinef: do not allow to move with UNIT_FLAG_DISABLE_MOVE
+ if (mover->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE))
+ {
+ // Xinef: skip moving packets
+ if (movementInfo.HasMovementFlag(MOVEMENTFLAG_MASK_MOVING))
{
- recvData.rfinish(); // prevent warnings spam
+ if (plrMover)
+ {
+ sScriptMgr->AnticheatSetSkipOnePacketForASH(plrMover, true);
+ sScriptMgr->AnticheatUpdateMovementInfo(plrMover, movementInfo);
+ }
+ return;
+ }
+ movementInfo.pos.Relocate(mover->GetPositionX(), mover->GetPositionY(), mover->GetPositionZ());
+
+ if (mover->GetTypeId() == TYPEID_UNIT)
+ {
+ movementInfo.transport.guid = mover->m_movementInfo.transport.guid;
+ movementInfo.transport.pos.Relocate(mover->m_movementInfo.transport.pos.GetPositionX(), mover->m_movementInfo.transport.pos.GetPositionY(), mover->m_movementInfo.transport.pos.GetPositionZ());
+ movementInfo.transport.seat = mover->m_movementInfo.transport.seat;
+ }
+ }
+
+ if (movementInfo.HasMovementFlag(MOVEMENTFLAG_ONTRANSPORT))
+ {
+ // We were teleported, skip packets that were broadcast before teleport
+ if (movementInfo.pos.GetExactDist2d(mover) > SIZE_OF_GRIDS)
+ {
+ if (plrMover)
+ {
+ sScriptMgr->AnticheatSetSkipOnePacketForASH(plrMover, true);
+ sScriptMgr->AnticheatUpdateMovementInfo(plrMover, movementInfo);
+ //TC_LOG_INFO("anticheat", "MovementHandler:: 2 We were teleported, skip packets that were broadcast before teleport");
+ }
+ recvData.rfinish(); // prevent warnings spam
return;
}
if (!acore::IsValidMapCoord(movementInfo.pos.GetPositionX() + movementInfo.transport.pos.GetPositionX(), movementInfo.pos.GetPositionY() + movementInfo.transport.pos.GetPositionY(),
movementInfo.pos.GetPositionZ() + movementInfo.transport.pos.GetPositionZ(), movementInfo.pos.GetOrientation() + movementInfo.transport.pos.GetOrientation()))
{
+ if (plrMover)
+ {
+ sScriptMgr->AnticheatSetSkipOnePacketForASH(plrMover, true);
+ sScriptMgr->AnticheatUpdateMovementInfo(plrMover, movementInfo);
+ }
+
recvData.rfinish(); // prevent warnings spam
return;
}
@@ -382,6 +423,8 @@ void WorldSession::HandleMovementOpcodes(WorldPacket& recvData)
}
else if (plrMover->GetTransport()->GetGUID() != movementInfo.transport.guid)
{
+ sScriptMgr->AnticheatSetSkipOnePacketForASH(plrMover, true);
+
bool foundNewTransport = false;
plrMover->m_transport->RemovePassenger(plrMover);
if (Transport* transport = plrMover->GetMap()->GetTransport(movementInfo.transport.guid))
@@ -400,42 +443,66 @@ void WorldSession::HandleMovementOpcodes(WorldPacket& recvData)
}
if (!mover->GetTransport() && !mover->GetVehicle())
- movementInfo.flags &= ~MOVEMENTFLAG_ONTRANSPORT;
+ {
+ GameObject* go = mover->GetMap()->GetGameObject(movementInfo.transport.guid);
+ if (!go || go->GetGoType() != GAMEOBJECT_TYPE_TRANSPORT)
+ {
+ movementInfo.RemoveMovementFlag(MOVEMENTFLAG_ONTRANSPORT);
+ }
+ }
}
else if (plrMover && plrMover->GetTransport()) // if we were on a transport, leave
{
+ sScriptMgr->AnticheatSetUnderACKmount(plrMover); // just for safe
+
plrMover->m_transport->RemovePassenger(plrMover);
plrMover->m_transport = nullptr;
movementInfo.transport.Reset();
}
+ // fall damage generation (ignore in flight case that can be triggered also at lags in moment teleportation to another map).
+ if (opcode == MSG_MOVE_FALL_LAND && plrMover && !plrMover->IsInFlight())
+ {
+ plrMover->HandleFall(movementInfo);
+
+ sScriptMgr->AnticheatSetJumpingbyOpcode(plrMover, false);
+ }
+
+ // interrupt parachutes upon falling or landing in water
+ if (opcode == MSG_MOVE_FALL_LAND || opcode == MSG_MOVE_START_SWIM)
+ {
+ mover->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_LANDING); // Parachutes
+
+ if (plrMover)
+ {
+ sScriptMgr->AnticheatSetJumpingbyOpcode(plrMover, false);
+ }
+ }
+
if (plrMover && ((movementInfo.flags & MOVEMENTFLAG_SWIMMING) != 0) != plrMover->IsInWater())
{
// now client not include swimming flag in case jumping under water
plrMover->SetInWater(!plrMover->IsInWater() || plrMover->GetBaseMap()->IsUnderWater(movementInfo.pos.GetPositionX(), movementInfo.pos.GetPositionY(), movementInfo.pos.GetPositionZ()));
}
- if (plrMover)//Hook for OnPlayerMove
- sScriptMgr->OnPlayerMove(plrMover, movementInfo, opcode);
- // Dont allow to turn on walking if charming other player
- if (mover->GetGUID() != _player->GetGUID())
- movementInfo.flags &= ~MOVEMENTFLAG_WALKING;
- // Xinef: do not allow to move with UNIT_FLAG_DISABLE_MOVE
- if (mover->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE))
+ bool jumpopcode = false;
+ if (opcode == MSG_MOVE_JUMP)
{
- // Xinef: skip moving packets
- if (movementInfo.HasMovementFlag(MOVEMENTFLAG_MASK_MOVING))
- return;
- movementInfo.pos.Relocate(mover->GetPositionX(), mover->GetPositionY(), mover->GetPositionZ());
-
- if (mover->GetTypeId() == TYPEID_UNIT)
+ jumpopcode = true;
+ if (plrMover && !sScriptMgr->AnticheatHandleDoubleJump(plrMover, mover))
{
- movementInfo.transport.guid = mover->m_movementInfo.transport.guid;
- movementInfo.transport.pos.Relocate(mover->m_movementInfo.transport.pos.GetPositionX(), mover->m_movementInfo.transport.pos.GetPositionY(), mover->m_movementInfo.transport.pos.GetPositionZ());
- movementInfo.transport.seat = mover->m_movementInfo.transport.seat;
+ plrMover->GetSession()->KickPlayer();
+ return;
}
}
+ /* start some hack detection */
+ if (plrMover && !sScriptMgr->AnticheatCheckMovementInfo(plrMover, movementInfo, mover, jumpopcode))
+ {
+ plrMover->GetSession()->KickPlayer();
+ return;
+ }
+
/* process position-change */
WorldPacket data(opcode, recvData.size());
int64 movementTime = (int64)movementInfo.time + _timeSyncClockDelta;
@@ -455,32 +522,22 @@ void WorldSession::HandleMovementOpcodes(WorldPacket& recvData)
mover->m_movementInfo = movementInfo;
- // this is almost never true (pussywizard: only one packet when entering vehicle), normally use mover->IsVehicle()
- if (mover->GetVehicle())
+ // Some vehicles allow the passenger to turn by himself
+ if (Vehicle* vehicle = mover->GetVehicle())
{
- mover->SetOrientation(movementInfo.pos.GetOrientation());
- mover->UpdatePosition(movementInfo.pos);
+ if (VehicleSeatEntry const* seat = vehicle->GetSeatForPassenger(mover))
+ {
+ if (seat->m_flags & VEHICLE_SEAT_FLAG_ALLOW_TURNING && movementInfo.pos.GetOrientation() != mover->GetOrientation())
+ {
+ mover->SetOrientation(movementInfo.pos.GetOrientation());
+ mover->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_TURNING);
+ }
+ }
+
return;
}
- // pussywizard: previously always mover->UpdatePosition(movementInfo.pos);
- if (movementInfo.flags & MOVEMENTFLAG_ONTRANSPORT && mover->GetTransport())
- {
- float x, y, z, o;
- movementInfo.transport.pos.GetPosition(x, y, z, o);
- mover->GetTransport()->CalculatePassengerPosition(x, y, z, &o);
- mover->UpdatePosition(x, y, z, o);
- }
- else
- mover->UpdatePosition(movementInfo.pos);
-
- // fall damage generation (ignore in flight case that can be triggered also at lags in moment teleportation to another map).
- // Xinef: moved it here, previously StopMoving function called when player died relocated him to last saved coordinates (which were in air)
- if (opcode == MSG_MOVE_FALL_LAND && plrMover && !plrMover->IsInFlight() && (!plrMover->GetTransport() || plrMover->GetTransport()->IsStaticTransport()))
- plrMover->HandleFall(movementInfo);
- // Xinef: interrupt parachutes upon falling or landing in water
- if (opcode == MSG_MOVE_FALL_LAND || opcode == MSG_MOVE_START_SWIM)
- mover->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_LANDING); // Parachutes
+ mover->UpdatePosition(movementInfo.pos);
if (plrMover) // nothing is charmed, or player charmed
{
@@ -597,6 +654,8 @@ void WorldSession::HandleForceSpeedChangeAck(WorldPacket& recvData)
return;
}
+ sScriptMgr->AnticheatSetUnderACKmount(_player);
+
// skip all forced speed changes except last and unexpected
// in run/mounted case used one ACK and it must be skipped.m_forced_speed_changes[MOVE_RUN} store both.
if (_player->m_forced_speed_changes[force_move_type] > 0)
diff --git a/src/server/game/Handlers/PetHandler.cpp b/src/server/game/Handlers/PetHandler.cpp
index 2368a21fce..1ec4644d49 100644
--- a/src/server/game/Handlers/PetHandler.cpp
+++ b/src/server/game/Handlers/PetHandler.cpp
@@ -7,6 +7,7 @@
#include "Chat.h"
#include "Common.h"
#include "CreatureAI.h"
+#include "DisableMgr.h"
#include "Group.h"
#include "Log.h"
#include "ObjectAccessor.h"
@@ -559,7 +560,7 @@ void WorldSession::HandlePetActionHelper(Unit* pet, ObjectGuid guid1, uint16 spe
return;
// Not let attack through obstructions
- bool checkLos = !MMAP::MMapFactory::IsPathfindingEnabled(pet->GetMap()) ||
+ bool checkLos = !DisableMgr::IsPathfindingEnabled(pet->GetMap()) ||
(TargetUnit->GetTypeId() == TYPEID_UNIT && (TargetUnit->ToCreature()->isWorldBoss() || TargetUnit->ToCreature()->IsDungeonBoss()));
if (checkLos && !pet->IsWithinLOSInMap(TargetUnit))
diff --git a/src/server/game/Handlers/TaxiHandler.cpp b/src/server/game/Handlers/TaxiHandler.cpp
index 73fdfc18b1..1e7e3031ba 100644
--- a/src/server/game/Handlers/TaxiHandler.cpp
+++ b/src/server/game/Handlers/TaxiHandler.cpp
@@ -10,6 +10,7 @@
#include "ObjectMgr.h"
#include "Opcodes.h"
#include "Player.h"
+#include "ScriptMgr.h"
#include "UpdateMask.h"
#include "WaypointMovementGenerator.h"
#include "WorldPacket.h"
@@ -131,6 +132,8 @@ void WorldSession::SendDoFlight(uint32 mountDisplayId, uint32 path, uint32 pathN
GetPlayer()->Mount(mountDisplayId);
GetPlayer()->GetMotionMaster()->MoveTaxiFlight(path, pathNode);
+
+ sScriptMgr->AnticheatSetSkipOnePacketForASH(GetPlayer(), true);
}
bool WorldSession::SendLearnNewTaxiNode(Creature* unit)
diff --git a/src/server/game/Loot/LootMgr.h b/src/server/game/Loot/LootMgr.h
index f55ca83e81..8f98c6b627 100644
--- a/src/server/game/Loot/LootMgr.h
+++ b/src/server/game/Loot/LootMgr.h
@@ -111,6 +111,7 @@ enum LootSlotType
class Player;
class LootStore;
class ConditionMgr;
+class GameObject;
struct Loot;
struct LootStoreItem
@@ -313,6 +314,7 @@ struct Loot
// GUID of container that holds this loot (item_instance.entry), set for items that can be looted
ObjectGuid containerGUID;
+ GameObject* sourceGameObject{nullptr};
Loot(uint32 _gold = 0) : gold(_gold) { }
~Loot() { clear(); }
diff --git a/src/server/game/Maps/Map.cpp b/src/server/game/Maps/Map.cpp
index 9797fbff68..641f18e2df 100644
--- a/src/server/game/Maps/Map.cpp
+++ b/src/server/game/Maps/Map.cpp
@@ -7,6 +7,7 @@
#include "Battleground.h"
#include "CellImpl.h"
#include "Chat.h"
+#include "DisableMgr.h"
#include "DynamicTree.h"
#include "Geometry.h"
#include "GridNotifiers.h"
@@ -24,6 +25,7 @@
#include "Transport.h"
#include "Vehicle.h"
#include "VMapFactory.h"
+#include "VMapManager2.h"
#ifdef ELUNA
#include "LuaEngine.h"
@@ -111,7 +113,7 @@ bool Map::ExistVMap(uint32 mapid, int gx, int gy)
void Map::LoadMMap(int gx, int gy)
{
- if (!MMAP::MMapFactory::IsPathfindingEnabled(this)) // pussywizard
+ if (!DisableMgr::IsPathfindingEnabled(this)) // pussywizard
return;
int mmapLoadResult = MMAP::MMapFactory::createOrGetMMapManager()->loadMap(GetId(), gx, gy);
@@ -138,7 +140,7 @@ void Map::LoadMMap(int gx, int gy)
void Map::LoadVMap(int gx, int gy)
{
// x and y are swapped !!
- int vmapLoadResult = VMAP::VMapFactory::createOrGetVMapManager()->loadMap((sWorld->GetDataPath() + "vmaps").c_str(), GetId(), gx, gy);
+ int vmapLoadResult = VMAP::VMapFactory::createOrGetVMapManager()->loadMap((sWorld->GetDataPath() + "vmaps").c_str(), GetId(), gx, gy);
switch (vmapLoadResult)
{
case VMAP::VMAP_LOAD_RESULT_OK:
@@ -3721,23 +3723,23 @@ bool Map::CheckCollisionAndGetValidCoords(const WorldObject* source, float start
bool isWaterNext = IsInWater(destX, destY, destZ);
- PathGenerator* path = new PathGenerator(source);
+ PathGenerator path(source);
// Use a detour raycast to get our first collision point
- path->SetUseRaycast(true);
- bool result = path->CalculatePath(startX, startY, startZ, destX, destY, destZ, false);
+ path.SetUseRaycast(true);
+ bool result = path.CalculatePath(startX, startY, startZ, destX, destY, destZ, false);
const Unit* unit = source->ToUnit();
- bool notOnGround = path->GetPathType() & PATHFIND_NOT_USING_PATH
+ bool notOnGround = path.GetPathType() & PATHFIND_NOT_USING_PATH
|| isWaterNext || (unit && unit->IsFlying());
// Check for valid path types before we proceed
- if (!result || (!notOnGround && path->GetPathType() & ~(PATHFIND_NORMAL | PATHFIND_SHORTCUT | PATHFIND_INCOMPLETE | PATHFIND_FARFROMPOLY_END)))
+ if (!result || (!notOnGround && path.GetPathType() & ~(PATHFIND_NORMAL | PATHFIND_SHORTCUT | PATHFIND_INCOMPLETE | PATHFIND_FARFROMPOLY_END)))
{
return false;
}
- G3D::Vector3 endPos = path->GetPath().back();
+ G3D::Vector3 endPos = path.GetPath().back();
destX = endPos.x;
destY = endPos.y;
destZ = endPos.z;
@@ -3790,7 +3792,9 @@ bool Map::CheckCollisionAndGetValidCoords(const WorldObject* source, float start
if (gridHeight > INVALID_HEIGHT)
{
destZ = gridHeight + unit->GetHoverHeight();
- } else {
+ }
+ else
+ {
return false;
}
}
diff --git a/src/server/game/Miscellaneous/Language.h b/src/server/game/Miscellaneous/Language.h
index dd7e6d2035..faea05c80a 100644
--- a/src/server/game/Miscellaneous/Language.h
+++ b/src/server/game/Miscellaneous/Language.h
@@ -1332,6 +1332,8 @@ enum AcoreStrings
LANG_BG_READY_CHECK_ERROR = 30084,
LANG_DEBUG_BG_CONF = 30085,
- LANG_DEBUG_ARENA_CONF = 30086,
+ LANG_DEBUG_ARENA_CONF = 30086
+
+ // 30087-30095 reserved for passive anticheat
};
#endif
diff --git a/src/server/game/Movement/MotionMaster.cpp b/src/server/game/Movement/MotionMaster.cpp
index b1e6b33a0f..146ef47fb2 100644
--- a/src/server/game/Movement/MotionMaster.cpp
+++ b/src/server/game/Movement/MotionMaster.cpp
@@ -364,14 +364,14 @@ void MotionMaster::MoveCircleTarget(Unit* target)
return;
}
- Position* point = target->GetMeleeAttackPoint(_owner);
- if (point == nullptr)
+ Position pos;
+ if (!target->GetMeleeAttackPoint(_owner, pos))
{
return;
}
Movement::MoveSplineInit init(_owner);
- init.MoveTo(point->m_positionX, point->m_positionY, point->m_positionZ, false);
+ init.MoveTo(pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), false);
init.SetWalk(true);
init.SetFacing(target);
init.Launch();
diff --git a/src/server/game/Movement/MovementGenerators/HomeMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/HomeMovementGenerator.cpp
index 477bad32e7..cf0cb8b46b 100644
--- a/src/server/game/Movement/MovementGenerators/HomeMovementGenerator.cpp
+++ b/src/server/game/Movement/MovementGenerators/HomeMovementGenerator.cpp
@@ -4,9 +4,10 @@
* Copyright (C) 2005-2009 MaNGOS
*/
+#include "HomeMovementGenerator.h"
#include "Creature.h"
#include "CreatureAI.h"
-#include "HomeMovementGenerator.h"
+#include "DisableMgr.h"
#include "MoveSpline.h"
#include "MoveSplineInit.h"
#include "WorldPacket.h"
@@ -55,7 +56,7 @@ void HomeMovementGenerator::_setTargetLocation(Creature* owner)
}
owner->UpdateAllowedPositionZ(x, y, z);
- init.MoveTo(x, y, z, MMAP::MMapFactory::IsPathfindingEnabled(owner->FindMap()), true);
+ init.MoveTo(x, y, z, DisableMgr::IsPathfindingEnabled(owner->FindMap()), true);
init.SetWalk(false);
init.Launch();
diff --git a/src/server/game/Movement/MovementGenerators/PathGenerator.cpp b/src/server/game/Movement/MovementGenerators/PathGenerator.cpp
index 861076455e..5e5636c593 100644
--- a/src/server/game/Movement/MovementGenerators/PathGenerator.cpp
+++ b/src/server/game/Movement/MovementGenerators/PathGenerator.cpp
@@ -24,7 +24,7 @@ PathGenerator::PathGenerator(WorldObject const* owner) :
memset(_pathPolyRefs, 0, sizeof(_pathPolyRefs));
uint32 mapId = _source->GetMapId();
- //if (MMAP::MMapFactory::IsPathfindingEnabled(_sourceUnit->FindMap()))
+ //if (DisableMgr::IsPathfindingEnabled(_sourceUnit->FindMap()))
{
MMAP::MMapManager* mmap = MMAP::MMapFactory::createOrGetMMapManager();
_navMesh = mmap->GetNavMesh(mapId);
diff --git a/src/server/game/Movement/MovementGenerators/PathGenerator.h b/src/server/game/Movement/MovementGenerators/PathGenerator.h
index 0386f7df3d..9f1d768a0c 100644
--- a/src/server/game/Movement/MovementGenerators/PathGenerator.h
+++ b/src/server/game/Movement/MovementGenerators/PathGenerator.h
@@ -9,6 +9,7 @@
#include "DetourNavMesh.h"
#include "DetourNavMeshQuery.h"
+#include "MapDefines.h"
#include "MMapFactory.h"
#include "MMapManager.h"
#include "MoveSplineInitArgs.h"
diff --git a/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.cpp
index 39ac661cd9..a106f0a428 100644
--- a/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.cpp
+++ b/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.cpp
@@ -13,6 +13,15 @@
#include "Spell.h"
#include "Util.h"
+template
+RandomMovementGenerator::~RandomMovementGenerator() { }
+
+template<>
+RandomMovementGenerator::~RandomMovementGenerator()
+{
+ delete _pathGenerator;
+}
+
template<>
void RandomMovementGenerator::_setRandomLocation(Creature* creature)
{
diff --git a/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.h b/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.h
index 8428ab2085..b768b48916 100644
--- a/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.h
+++ b/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.h
@@ -34,6 +34,7 @@ public:
for (uint8 i = 0; i < RANDOM_POINTS_NUMBER; ++i)
_validPointsVector[RANDOM_POINTS_NUMBER].push_back(i);
}
+ ~RandomMovementGenerator();
void _setRandomLocation(T*);
void DoInitialize(T*);
diff --git a/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.h b/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.h
index 97f3834370..13b64ea707 100644
--- a/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.h
+++ b/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.h
@@ -29,7 +29,7 @@ class ChaseMovementGenerator : public MovementGeneratorMedium range = {}, std::optional angle = {})
: TargetedMovementGeneratorBase(target), i_path(nullptr), i_recheckDistance(0), i_recalculateTravel(true), _range(range), _angle(angle) {}
- ~ChaseMovementGenerator() {}
+ ~ChaseMovementGenerator() { delete i_path; }
MovementGeneratorType GetMovementGeneratorType() { return CHASE_MOTION_TYPE; }
@@ -65,7 +65,7 @@ class FollowMovementGenerator : public MovementGeneratorMediumOnBeforeUpdate(player, p_time);
}
+void ScriptMgr::OnPlayerUpdate(Player* player, uint32 p_time)
+{
+ FOREACH_SCRIPT(PlayerScript)->OnUpdate(player, p_time);
+}
+
void ScriptMgr::OnPlayerLogin(Player* player)
{
#ifdef ELUNA
@@ -2632,6 +2637,58 @@ void ScriptMgr::OnSetServerSideVisibilityDetect(Player* player, ServerSideVisibi
FOREACH_SCRIPT(PlayerScript)->OnSetServerSideVisibilityDetect(player, type, sec);
}
+void ScriptMgr::AnticheatSetSkipOnePacketForASH(Player* player, bool apply)
+{
+ FOREACH_SCRIPT(PlayerScript)->AnticheatSetSkipOnePacketForASH(player, apply);
+}
+
+void ScriptMgr::AnticheatSetCanFlybyServer(Player* player, bool apply)
+{
+ FOREACH_SCRIPT(PlayerScript)->AnticheatSetCanFlybyServer(player, apply);
+}
+
+void ScriptMgr::AnticheatSetUnderACKmount(Player* player)
+{
+ FOREACH_SCRIPT(PlayerScript)->AnticheatSetUnderACKmount(player);
+}
+
+void ScriptMgr::AnticheatSetRootACKUpd(Player* player)
+{
+ FOREACH_SCRIPT(PlayerScript)->AnticheatSetRootACKUpd(player);
+}
+
+void ScriptMgr::AnticheatSetJumpingbyOpcode(Player* player, bool jump)
+{
+ FOREACH_SCRIPT(PlayerScript)->AnticheatSetJumpingbyOpcode(player, jump);
+}
+
+void ScriptMgr::AnticheatUpdateMovementInfo(Player* player, MovementInfo const& movementInfo)
+{
+ FOREACH_SCRIPT(PlayerScript)->AnticheatUpdateMovementInfo(player, movementInfo);
+}
+
+bool ScriptMgr::AnticheatHandleDoubleJump(Player* player, Unit* mover)
+{
+ bool ret = true;
+
+ FOR_SCRIPTS_RET(PlayerScript, itr, end, ret) // return true by default if not scripts
+ if (!itr->second->AnticheatHandleDoubleJump(player, mover))
+ ret = false; // we change ret value only when scripts return true
+
+ return ret;
+}
+
+bool ScriptMgr::AnticheatCheckMovementInfo(Player* player, MovementInfo const& movementInfo, Unit* mover, bool jump)
+{
+ bool ret = true;
+
+ FOR_SCRIPTS_RET(PlayerScript, itr, end, ret) // return true by default if not scripts
+ if (!itr->second->AnticheatCheckMovementInfo(player, movementInfo, mover, jump))
+ ret = false; // we change ret value only when scripts return true
+
+ return ret;
+}
+
bool ScriptMgr::CanGuildSendBankList(Guild const* guild, WorldSession* session, uint8 tabId, bool sendAllSlots)
{
bool ret = true;
diff --git a/src/server/game/Scripting/ScriptMgr.h b/src/server/game/Scripting/ScriptMgr.h
index bc4b1391b6..598b68c4f5 100644
--- a/src/server/game/Scripting/ScriptMgr.h
+++ b/src/server/game/Scripting/ScriptMgr.h
@@ -732,6 +732,7 @@ public:
// Called for player::update
virtual void OnBeforeUpdate(Player* /*player*/, uint32 /*p_time*/) { }
+ virtual void OnUpdate(Player* /*player*/, uint32 /*p_time*/) { }
// Called when a player's money is modified (before the modification is done)
virtual void OnMoneyChanged(Player* /*player*/, int32& /*amount*/) { }
@@ -1014,6 +1015,16 @@ public:
virtual void OnSetServerSideVisibility(Player* /*player*/, ServerSideVisibilityType& /*type*/, AccountTypes& /*sec*/) { }
virtual void OnSetServerSideVisibilityDetect(Player* /*player*/, ServerSideVisibilityType& /*type*/, AccountTypes& /*sec*/) { }
+
+ // Passive Anticheat System
+ virtual void AnticheatSetSkipOnePacketForASH(Player* /*player*/, bool /*apply*/) { }
+ virtual void AnticheatSetCanFlybyServer(Player* /*player*/, bool /*apply*/) { }
+ virtual void AnticheatSetUnderACKmount(Player* /*player*/) { }
+ virtual void AnticheatSetRootACKUpd(Player* /*player*/) { }
+ virtual void AnticheatSetJumpingbyOpcode(Player* /*player*/, bool /*jump*/) { }
+ virtual void AnticheatUpdateMovementInfo(Player* /*player*/, MovementInfo const& /*movementInfo*/) { }
+ [[nodiscard]] virtual bool AnticheatHandleDoubleJump(Player* /*player*/, Unit* /*mover*/) { return true; }
+ [[nodiscard]] virtual bool AnticheatCheckMovementInfo(Player* /*player*/, MovementInfo const& /*movementInfo*/, Unit* /*mover*/, bool /*jump*/) { return true; }
};
class AccountScript : public ScriptObject
@@ -1542,6 +1553,7 @@ public: /* AchievementCriteriaScript */
public: /* PlayerScript */
void OnBeforePlayerUpdate(Player* player, uint32 p_time);
+ void OnPlayerUpdate(Player* player, uint32 p_time);
void OnSendInitialPacketsBeforeAddToMap(Player* player, WorldPacket& data);
void OnPlayerReleasedGhost(Player* player);
void OnPVPKill(Player* killer, Player* killed);
@@ -1667,6 +1679,14 @@ public: /* PlayerScript */
bool CanInitTrade(Player* player, Player* target);
void OnSetServerSideVisibility(Player* player, ServerSideVisibilityType& type, AccountTypes& sec);
void OnSetServerSideVisibilityDetect(Player* player, ServerSideVisibilityType& type, AccountTypes& sec);
+ void AnticheatSetSkipOnePacketForASH(Player* player, bool apply);
+ void AnticheatSetCanFlybyServer(Player* player, bool apply);
+ void AnticheatSetUnderACKmount(Player* player);
+ void AnticheatSetRootACKUpd(Player* player);
+ void AnticheatUpdateMovementInfo(Player* player, MovementInfo const& movementInfo);
+ void AnticheatSetJumpingbyOpcode(Player* player, bool jump);
+ bool AnticheatHandleDoubleJump(Player* player, Unit* mover);
+ bool AnticheatCheckMovementInfo(Player* player, MovementInfo const& movementInfo, Unit* mover, bool jump);
public: /* AccountScript */
void OnAccountLogin(uint32 accountId);
diff --git a/src/server/game/Server/WorldSession.cpp b/src/server/game/Server/WorldSession.cpp
index 2b9460005b..3e715fc0fa 100644
--- a/src/server/game/Server/WorldSession.cpp
+++ b/src/server/game/Server/WorldSession.cpp
@@ -450,6 +450,10 @@ bool WorldSession::HandleSocketClosed()
return false;
}
+bool WorldSession::IsSocketClosed() const {
+ return !m_Socket || m_Socket->IsClosed();
+}
+
void WorldSession::HandleTeleportTimeout(bool updateInSessions)
{
// pussywizard: handle teleport ack timeout
diff --git a/src/server/game/Server/WorldSession.h b/src/server/game/Server/WorldSession.h
index 45da8c8e38..3b2eee0ecb 100644
--- a/src/server/game/Server/WorldSession.h
+++ b/src/server/game/Server/WorldSession.h
@@ -926,6 +926,7 @@ public: // opcodes handlers
void SetKicked(bool val) { _kicked = val; }
void SetShouldSetOfflineInDB(bool val) { _shouldSetOfflineInDB = val; }
bool GetShouldSetOfflineInDB() const { return _shouldSetOfflineInDB; }
+ bool IsSocketClosed() const;
/***
CALLBACKS
diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp
index 780296a130..157e7967ca 100644
--- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp
+++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp
@@ -2339,7 +2339,7 @@ void AuraEffect::HandleAuraModScale(AuraApplication const* aurApp, uint8 mode, b
Unit* target = aurApp->GetTarget();
- float scale = target->GetFloatValue(OBJECT_FIELD_SCALE_X);
+ float scale = target->GetObjectScale();
ApplyPercentModFloatVar(scale, float(GetAmount()), apply);
target->SetObjectScale(scale);
}
@@ -2359,7 +2359,6 @@ void AuraEffect::HandleAuraCloneCaster(AuraApplication const* aurApp, uint8 mode
// What must be cloned? at least display and scale
target->SetDisplayId(caster->GetDisplayId());
- //target->SetObjectScale(caster->GetFloatValue(OBJECT_FIELD_SCALE_X)); // we need retail info about how scaling is handled (aura maybe?)
target->SetFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_MIRROR_IMAGE);
}
else
@@ -2383,6 +2382,11 @@ void AuraEffect::HandleFeignDeath(AuraApplication const* aurApp, uint8 mode, boo
if (target->GetTypeId() != TYPEID_PLAYER)
return;
+ if (Player* targetPlayer = target->ToPlayer())
+ {
+ sScriptMgr->AnticheatSetUnderACKmount(targetPlayer);
+ }
+
if (apply)
{
/*
@@ -2875,6 +2879,11 @@ void AuraEffect::HandleAuraWaterWalk(AuraApplication const* aurApp, uint8 mode,
Unit* target = aurApp->GetTarget();
+ if (Player* targetPlayer = target->ToPlayer())
+ {
+ sScriptMgr->AnticheatSetUnderACKmount(targetPlayer);
+ }
+
if (!apply)
{
// do not remove unit flag if there are more than this auraEffect of that kind on unit on unit
@@ -2892,6 +2901,11 @@ void AuraEffect::HandleAuraFeatherFall(AuraApplication const* aurApp, uint8 mode
Unit* target = aurApp->GetTarget();
+ if (Player* targetPlayer = target->ToPlayer())
+ {
+ sScriptMgr->AnticheatSetUnderACKmount(targetPlayer);
+ }
+
if (!apply)
{
// do not remove unit flag if there are more than this auraEffect of that kind on unit on unit
@@ -2913,6 +2927,11 @@ void AuraEffect::HandleAuraHover(AuraApplication const* aurApp, uint8 mode, bool
Unit* target = aurApp->GetTarget();
+ if (Player* targetPlayer = target->ToPlayer())
+ {
+ sScriptMgr->AnticheatSetUnderACKmount(targetPlayer);
+ }
+
if (!apply)
{
// do not remove unit flag if there are more than this auraEffect of that kind on unit on unit
@@ -3227,6 +3246,11 @@ void AuraEffect::HandleAuraModIncreaseSpeed(AuraApplication const* aurApp, uint8
Unit* target = aurApp->GetTarget();
target->UpdateSpeed(MOVE_RUN, true);
+
+ if (Player* targetPlayer = target->ToPlayer())
+ {
+ sScriptMgr->AnticheatSetUnderACKmount(targetPlayer);
+ }
}
void AuraEffect::HandleAuraModIncreaseMountedSpeed(AuraApplication const* aurApp, uint8 mode, bool apply) const
@@ -3267,6 +3291,11 @@ void AuraEffect::HandleAuraModIncreaseFlightSpeed(AuraApplication const* aurApp,
target->SetUInt32Value(UNIT_FIELD_MOUNTDISPLAYID, 16314);
}
}
+
+ if (Player* targetPlayer = target->ToPlayer())
+ {
+ sScriptMgr->AnticheatSetUnderACKmount(targetPlayer);
+ }
}
void AuraEffect::HandleAuraModIncreaseSwimSpeed(AuraApplication const* aurApp, uint8 mode, bool /*apply*/) const
@@ -3277,6 +3306,11 @@ void AuraEffect::HandleAuraModIncreaseSwimSpeed(AuraApplication const* aurApp, u
Unit* target = aurApp->GetTarget();
target->UpdateSpeed(MOVE_SWIM, true);
+
+ if (Player* targetPlayer = target->ToPlayer())
+ {
+ sScriptMgr->AnticheatSetUnderACKmount(targetPlayer);
+ }
}
void AuraEffect::HandleAuraModDecreaseSpeed(AuraApplication const* aurApp, uint8 mode, bool /*apply*/) const
@@ -3292,6 +3326,11 @@ void AuraEffect::HandleAuraModDecreaseSpeed(AuraApplication const* aurApp, uint8
target->UpdateSpeed(MOVE_RUN_BACK, true);
target->UpdateSpeed(MOVE_SWIM_BACK, true);
target->UpdateSpeed(MOVE_FLIGHT_BACK, true);
+
+ if (Player* targetPlayer = target->ToPlayer())
+ {
+ sScriptMgr->AnticheatSetUnderACKmount(targetPlayer);
+ }
}
void AuraEffect::HandleAuraModUseNormalSpeed(AuraApplication const* aurApp, uint8 mode, bool /*apply*/) const
@@ -3304,6 +3343,11 @@ void AuraEffect::HandleAuraModUseNormalSpeed(AuraApplication const* aurApp, uint
target->UpdateSpeed(MOVE_RUN, true);
target->UpdateSpeed(MOVE_SWIM, true);
target->UpdateSpeed(MOVE_FLIGHT, true);
+
+ if (Player* targetPlayer = target->ToPlayer())
+ {
+ sScriptMgr->AnticheatSetUnderACKmount(targetPlayer);
+ }
}
/*********************************************************/
diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp
index feda1c46e7..f779cbec38 100644
--- a/src/server/game/Spells/Spell.cpp
+++ b/src/server/game/Spells/Spell.cpp
@@ -5678,7 +5678,7 @@ SpellCastResult Spell::CheckCast(bool strict)
return SPELL_FAILED_BAD_TARGETS;
// Xinef: Pass only explicit unit target spells
// pussywizard:
- if (MMAP::MMapFactory::IsPathfindingEnabled(m_caster->FindMap()) && m_spellInfo->NeedsExplicitUnitTarget())
+ if (DisableMgr::IsPathfindingEnabled(m_caster->FindMap()) && m_spellInfo->NeedsExplicitUnitTarget())
{
Unit* target = m_targets.GetUnitTarget();
if (!target)
@@ -7337,12 +7337,6 @@ bool Spell::CheckEffectTarget(Unit const* target, uint32 eff) const
return false;
}
break;
- /*case SPELL_EFFECT_CHARGE:
- if (MMAP::MMapFactory::IsPathfindingEnabled(m_caster->FindMap()))
- break;
- [[fallthrough]];
- */
-
case SPELL_EFFECT_SUMMON_RAF_FRIEND:
if (m_caster->GetTypeId() != TYPEID_PLAYER || target->GetTypeId() != TYPEID_PLAYER)
return false;
diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp
index 4da2e908a8..1eac370943 100644
--- a/src/server/game/Spells/SpellEffects.cpp
+++ b/src/server/game/Spells/SpellEffects.cpp
@@ -1113,6 +1113,11 @@ void Spell::EffectJump(SpellEffIndex effIndex)
float speedXY, speedZ;
CalculateJumpSpeeds(effIndex, m_caster->GetExactDist2d(unitTarget), speedXY, speedZ);
m_caster->GetMotionMaster()->MoveJump(*unitTarget, speedXY, speedZ);
+
+ if (m_caster->GetTypeId() == TYPEID_PLAYER)
+ {
+ sScriptMgr->AnticheatSetUnderACKmount(m_caster->ToPlayer());
+ }
}
void Spell::EffectJumpDest(SpellEffIndex effIndex)
@@ -1142,6 +1147,12 @@ void Spell::EffectJumpDest(SpellEffIndex effIndex)
{
speedXY = pow(speedZ * 10, 8);
m_caster->GetMotionMaster()->MoveJump(x, y, z, speedXY, speedZ, 0, ObjectAccessor::GetUnit(*m_caster, m_caster->GetGuidValue(UNIT_FIELD_TARGET)));
+
+ if (m_caster->GetTypeId() == TYPEID_PLAYER)
+ {
+ sScriptMgr->AnticheatSetUnderACKmount(m_caster->ToPlayer());
+ }
+
return;
}
@@ -1156,6 +1167,11 @@ void Spell::EffectJumpDest(SpellEffIndex effIndex)
speedXY = 1.0f;
m_caster->GetMotionMaster()->MoveJump(x, y, z, speedXY, speedZ);
+
+ if (m_caster->GetTypeId() == TYPEID_PLAYER)
+ {
+ sScriptMgr->AnticheatSetUnderACKmount(m_caster->ToPlayer());
+ }
}
void Spell::CalculateJumpSpeeds(uint8 i, float dist, float& speedXY, float& speedZ)
@@ -1177,6 +1193,11 @@ void Spell::EffectTeleportUnits(SpellEffIndex /*effIndex*/)
if (!unitTarget || unitTarget->IsInFlight())
return;
+ if (unitTarget->GetTypeId() == TYPEID_PLAYER)
+ {
+ sScriptMgr->AnticheatSetUnderACKmount(unitTarget->ToPlayer());
+ }
+
// Pre effects
switch (m_spellInfo->Id)
{
@@ -5056,6 +5077,11 @@ void Spell::EffectCharge(SpellEffIndex /*effIndex*/)
if (!unitTarget)
return;
+ if (m_caster->GetTypeId() == TYPEID_PLAYER)
+ {
+ sScriptMgr->AnticheatSetSkipOnePacketForASH(m_caster->ToPlayer(), true);
+ }
+
// charge changes fall time
if( m_caster->GetTypeId() == TYPEID_PLAYER )
m_caster->ToPlayer()->SetFallInformation(time(nullptr), m_caster->GetPositionZ());
@@ -5063,6 +5089,13 @@ void Spell::EffectCharge(SpellEffIndex /*effIndex*/)
if (m_pathFinder)
{
m_caster->GetMotionMaster()->MoveCharge(m_pathFinder->GetEndPosition().x, m_pathFinder->GetEndPosition().y, m_pathFinder->GetEndPosition().z, 42.0f, EVENT_CHARGE, &m_pathFinder->GetPath());
+
+ if (m_caster->GetTypeId() == TYPEID_PLAYER)
+ {
+ sScriptMgr->AnticheatSetUnderACKmount(m_caster->ToPlayer());
+ }
+
+ m_caster->AddUnitState(UNIT_STATE_CHARGING);
}
else
{
@@ -5077,6 +5110,13 @@ void Spell::EffectCharge(SpellEffIndex /*effIndex*/)
}
m_caster->GetMotionMaster()->MoveCharge(pos.m_positionX, pos.m_positionY, pos.m_positionZ + Z_OFFSET_FIND_HEIGHT);
+
+ if (m_caster->GetTypeId() == TYPEID_PLAYER)
+ {
+ sScriptMgr->AnticheatSetUnderACKmount(m_caster->ToPlayer());
+ }
+
+ m_caster->AddUnitState(UNIT_STATE_CHARGING);
}
}
@@ -5085,6 +5125,13 @@ void Spell::EffectCharge(SpellEffIndex /*effIndex*/)
if (!unitTarget)
return;
+ m_caster->ClearUnitState(UNIT_STATE_CHARGING);
+
+ if (m_caster->ToPlayer())
+ {
+ sScriptMgr->AnticheatSetSkipOnePacketForASH(m_caster->ToPlayer(), true);
+ }
+
// not all charge effects used in negative spells
if (!m_spellInfo->IsPositive() && m_caster->GetTypeId() == TYPEID_PLAYER)
m_caster->Attack(unitTarget, true);
@@ -5096,6 +5143,11 @@ void Spell::EffectChargeDest(SpellEffIndex /*effIndex*/)
if (effectHandleMode != SPELL_EFFECT_HANDLE_LAUNCH)
return;
+ if (m_caster->ToPlayer())
+ {
+ sScriptMgr->AnticheatSetSkipOnePacketForASH(m_caster->ToPlayer(), true);
+ }
+
if (m_targets.HasDst())
{
Position pos;
@@ -5109,6 +5161,11 @@ void Spell::EffectChargeDest(SpellEffIndex /*effIndex*/)
}
m_caster->GetMotionMaster()->MoveCharge(pos.m_positionX, pos.m_positionY, pos.m_positionZ);
+
+ if (m_caster->GetTypeId() == TYPEID_PLAYER)
+ {
+ sScriptMgr->AnticheatSetUnderACKmount(m_caster->ToPlayer());
+ }
}
}
@@ -5162,6 +5219,11 @@ void Spell::EffectKnockBack(SpellEffIndex effIndex)
}
unitTarget->KnockbackFrom(x, y, speedxy, speedz);
+
+ if (unitTarget->GetTypeId() == TYPEID_PLAYER)
+ {
+ sScriptMgr->AnticheatSetUnderACKmount(unitTarget->ToPlayer());
+ }
}
void Spell::EffectLeapBack(SpellEffIndex effIndex)
@@ -5177,6 +5239,11 @@ void Spell::EffectLeapBack(SpellEffIndex effIndex)
//1891: Disengage
m_caster->JumpTo(speedxy, speedz, m_spellInfo->SpellFamilyName != SPELLFAMILY_HUNTER);
+ if (m_caster->GetTypeId() == TYPEID_PLAYER)
+ {
+ sScriptMgr->AnticheatSetUnderACKmount(m_caster->ToPlayer());
+ }
+
// xinef: changes fall time
if (m_caster->GetTypeId() == TYPEID_PLAYER)
m_caster->ToPlayer()->SetFallInformation(time(nullptr), m_caster->GetPositionZ());
@@ -5262,6 +5329,12 @@ void Spell::EffectPullTowards(SpellEffIndex effIndex)
float speedZ = unitTarget->GetDistance(pos) / speedXY * 0.5f * Movement::gravity;
unitTarget->GetMotionMaster()->MoveJump(pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), speedXY, speedZ);
+
+ if (unitTarget->GetTypeId() == TYPEID_PLAYER)
+ {
+ sScriptMgr->AnticheatSetSkipOnePacketForASH(unitTarget->ToPlayer(), true);
+ sScriptMgr->AnticheatSetUnderACKmount(unitTarget->ToPlayer());
+ }
}
void Spell::EffectDispelMechanic(SpellEffIndex effIndex)
diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp
index 44fb101b3b..a05c534110 100644
--- a/src/server/game/World/World.cpp
+++ b/src/server/game/World/World.cpp
@@ -1415,8 +1415,6 @@ void World::LoadConfigSettings(bool reload)
sScriptMgr->OnAfterConfigLoad(reload);
}
-extern void LoadGameObjectModelList();
-
/// Initialize the World
void World::SetInitialWorldSettings()
{
@@ -1433,10 +1431,9 @@ void World::SetInitialWorldSettings()
sScriptMgr->Initialize();
///- Initialize VMapManager function pointers (to untangle game/collision circular deps)
- if (VMAP::VMapManager2* vmmgr2 = dynamic_cast(VMAP::VMapFactory::createOrGetVMapManager()))
- {
- vmmgr2->GetLiquidFlagsPtr = &GetLiquidFlags;
- }
+ VMAP::VMapManager2* vmmgr2 = VMAP::VMapFactory::createOrGetVMapManager();
+ vmmgr2->GetLiquidFlagsPtr = &GetLiquidFlags;
+ vmmgr2->IsVMAPDisabledForPtr = &DisableMgr::IsVMAPDisabledFor;
///- Initialize config settings
LoadConfigSettings();
@@ -1498,6 +1495,15 @@ void World::SetInitialWorldSettings()
LoadDBCStores(m_dataPath);
DetectDBCLang();
+ std::vector mapIds;
+ for (auto const& map : sMapStore)
+ mapIds.emplace_back(map->MapID);
+
+ vmmgr2->InitializeThreadUnsafe(mapIds);
+
+ MMAP::MMapManager* mmmgr = MMAP::MMapFactory::createOrGetMMapManager();
+ mmmgr->InitializeThreadUnsafe(mapIds);
+
LOG_INFO("server", "Loading Game Graveyard...");
sGraveyard->LoadGraveyardFromDB();
@@ -1520,7 +1526,7 @@ void World::SetInitialWorldSettings()
sSpellMgr->LoadSpellCustomAttr();
LOG_INFO("server", "Loading GameObject models...");
- LoadGameObjectModelList();
+ LoadGameObjectModelList(m_dataPath);
LOG_INFO("server", "Loading Script Names...");
sObjectMgr->LoadScriptNames();
diff --git a/src/server/scripts/Commands/cs_gm.cpp b/src/server/scripts/Commands/cs_gm.cpp
index 24e8f2d6e4..718c924126 100644
--- a/src/server/scripts/Commands/cs_gm.cpp
+++ b/src/server/scripts/Commands/cs_gm.cpp
@@ -88,9 +88,15 @@ public:
WorldPacket data(12);
if (strncmp(args, "on", 3) == 0)
+ {
data.SetOpcode(SMSG_MOVE_SET_CAN_FLY);
+ sScriptMgr->AnticheatSetCanFlybyServer(target, true);
+ }
else if (strncmp(args, "off", 4) == 0)
+ {
data.SetOpcode(SMSG_MOVE_UNSET_CAN_FLY);
+ sScriptMgr->AnticheatSetCanFlybyServer(target, false);
+ }
else
{
handler->SendSysMessage(LANG_USE_BOL);
diff --git a/src/server/scripts/Commands/cs_gobject.cpp b/src/server/scripts/Commands/cs_gobject.cpp
index f04081d5e4..05b31cdd2c 100644
--- a/src/server/scripts/Commands/cs_gobject.cpp
+++ b/src/server/scripts/Commands/cs_gobject.cpp
@@ -402,12 +402,25 @@ public:
oz = player->GetOrientation();
}
- object->SetWorldRotationAngles(oz, oy, ox);
- object->DestroyForNearbyPlayers();
- object->UpdateObjectVisibility();
+ Map* map = object->GetMap();
- object->SaveToDB();
- object->Refresh();
+ object->Relocate(object->GetPositionX(), object->GetPositionY(), object->GetPositionZ(), oz);
+ object->SetWorldRotationAngles(oz, oy, ox);
+
+ object->SaveToDB(true);
+
+ // Generate a completely new spawn with new guid
+ // 3.3.5a client caches recently deleted objects and brings them back to life
+ // when CreateObject block for this guid is received again
+ // however it entirely skips parsing that block and only uses already known location
+ object->Delete();
+
+ object = new GameObject();
+ if (!object->LoadGameObjectFromDB(guidLow, map))
+ {
+ delete object;
+ return false;
+ }
handler->PSendSysMessage(LANG_COMMAND_TURNOBJMESSAGE, object->GetSpawnId(), object->GetGOInfo()->name.c_str(), object->GetSpawnId(), oz, oy, ox);
@@ -438,12 +451,10 @@ public:
char* toY = strtok(nullptr, " ");
char* toZ = strtok(nullptr, " ");
+ Position pos;
if (!toX)
{
- Player* player = handler->GetSession()->GetPlayer();
- object->GetMap()->GameObjectRelocation(object, player->GetPositionX(), player->GetPositionY(), player->GetPositionZ(), object->GetOrientation());
- object->DestroyForNearbyPlayers();
- object->UpdateObjectVisibility();
+ pos = handler->GetSession()->GetPlayer()->GetPosition();
}
else
{
@@ -461,13 +472,31 @@ public:
return false;
}
- object->GetMap()->GameObjectRelocation(object, x, y, z, object->GetOrientation());
- object->DestroyForNearbyPlayers();
- object->UpdateObjectVisibility();
+ pos.Relocate(x, y, z);
}
+ Map* map = object->GetMap();
+
+ pos.SetOrientation(object->GetOrientation());
+ object->Relocate(pos);
+
+ // update which cell has this gameobject registered for loading
+ sObjectMgr->RemoveGameobjectFromGrid(guidLow, object->GetGOData());
object->SaveToDB();
- object->Refresh();
+ sObjectMgr->AddGameobjectToGrid(guidLow, object->GetGOData());
+
+ // Generate a completely new spawn with new guid
+ // 3.3.5a client caches recently deleted objects and brings them back to life
+ // when CreateObject block for this guid is received again
+ // however it entirely skips parsing that block and only uses already known location
+ object->Delete();
+
+ object = new GameObject();
+ if (!object->LoadGameObjectFromDB(guidLow, map))
+ {
+ delete object;
+ return false;
+ }
handler->PSendSysMessage(LANG_COMMAND_MOVEOBJMESSAGE, object->GetSpawnId(), object->GetGOInfo()->name.c_str(), object->GetSpawnId());
diff --git a/src/server/scripts/Commands/cs_misc.cpp b/src/server/scripts/Commands/cs_misc.cpp
index 02dbaecafa..95f45e4632 100644
--- a/src/server/scripts/Commands/cs_misc.cpp
+++ b/src/server/scripts/Commands/cs_misc.cpp
@@ -1541,15 +1541,19 @@ public:
// Subtract
if (count < 0)
{
- if (!playerTarget->HasItemCount(itemId, 0))
+ // Only have scam check on player accounts
+ if (playerTarget->GetSession()->GetSecurity() == SEC_PLAYER)
{
- // output that player don't have any items to destroy
- handler->PSendSysMessage(LANG_REMOVEITEM_FAILURE, handler->GetNameLink(playerTarget).c_str(), itemId);
- }
- else if (!playerTarget->HasItemCount(itemId, -count))
- {
- // output that player don't have as many items that you want to destroy
- handler->PSendSysMessage(LANG_REMOVEITEM_ERROR, handler->GetNameLink(playerTarget).c_str(), itemId);
+ if (!playerTarget->HasItemCount(itemId, 0))
+ {
+ // output that player don't have any items to destroy
+ handler->PSendSysMessage(LANG_REMOVEITEM_FAILURE, handler->GetNameLink(playerTarget).c_str(), itemId);
+ }
+ else if (!playerTarget->HasItemCount(itemId, -count))
+ {
+ // output that player don't have as many items that you want to destroy
+ handler->PSendSysMessage(LANG_REMOVEITEM_ERROR, handler->GetNameLink(playerTarget).c_str(), itemId);
+ }
}
else
{
@@ -1561,14 +1565,6 @@ public:
return true;
}
- /* [AC] Sunwell hack
- if (handler->GetSession()->GetSecurity() < SEC_ADMINISTRATOR)
- {
- handler->PSendSysMessage("You may only remove items. Adding items is available for higher GMLevel.");
- return false;
- }
- */
-
// Adding items
uint32 noSpaceForCount = 0;
diff --git a/src/server/scripts/EasternKingdoms/Deadmines/boss_mr_smite.cpp b/src/server/scripts/EasternKingdoms/Deadmines/boss_mr_smite.cpp
index 5fb5046ee7..c8c702b62d 100644
--- a/src/server/scripts/EasternKingdoms/Deadmines/boss_mr_smite.cpp
+++ b/src/server/scripts/EasternKingdoms/Deadmines/boss_mr_smite.cpp
@@ -6,7 +6,7 @@
#include "ScriptedCreature.h"
#include "ScriptMgr.h"
-enum Spels
+enum Spells
{
SPELL_SMITE_STOMP = 6432,
SPELL_SMITE_SLAM = 6435,
@@ -73,10 +73,6 @@ public:
events.Update(diff);
switch (events.ExecuteEvent())
{
- case EVENT_SMITE_SLAM:
- me->CastSpell(me->GetVictim(), SPELL_SMITE_SLAM, false);
- events.ScheduleEvent(EVENT_SMITE_SLAM, 15000);
- break;
case EVENT_CHECK_HEALTH1:
if (me->HealthBelowPct(67) && !health67)
{
@@ -107,6 +103,15 @@ public:
}
events.ScheduleEvent(EVENT_CHECK_HEALTH2, 500);
break;
+ case EVENT_SMITE_SLAM:
+ if (me->HealthBelowPct(33))
+ {
+ me->CastSpell(me->GetVictim(), SPELL_SMITE_SLAM, false);
+ events.ScheduleEvent(EVENT_SMITE_SLAM, 6000);
+ break;
+ }
+ events.ScheduleEvent(EVENT_SMITE_SLAM, 500);
+ break;
case EVENT_SWAP_WEAPON1:
me->LoadEquipment(EQUIP_TWO_SWORDS);
me->SetCanDualWield(true);
diff --git a/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp b/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp
index cfa8da8b09..406d9b182e 100644
--- a/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp
+++ b/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp
@@ -517,10 +517,16 @@ public:
pPlayer->SetUnitMovementFlags(MOVEMENTFLAG_NONE);
pPlayer->SetDisableGravity(true, true);
+
+ sScriptMgr->AnticheatSetCanFlybyServer(pPlayer, true);
+
WorldPacket data(SMSG_SPLINE_MOVE_UNROOT, 8);
data << pPlayer->GetPackGUID();
pPlayer->SendMessageToSet(&data, true);
+ sScriptMgr->AnticheatSetUnderACKmount(pPlayer);
+ sScriptMgr->AnticheatSetSkipOnePacketForASH(pPlayer, true);
+
pPlayer->SetGuidValue(PLAYER_FARSIGHT, vp->GetGUID());
c->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
}
@@ -704,6 +710,9 @@ public:
for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i)
if (Player* pPlayer = i->GetSource())
{
+ sScriptMgr->AnticheatSetUnderACKmount(pPlayer);
+ sScriptMgr->AnticheatSetSkipOnePacketForASH(pPlayer, true);
+
if (!pPlayer->IsAlive() || pPlayer->IsGameMaster())
continue;
@@ -884,6 +893,10 @@ public:
plr->RemoveAura(SPELL_FREEZE_ANIM);
plr->SetDisableGravity(false, true);
plr->SetGuidValue(PLAYER_FARSIGHT, ObjectGuid::Empty);
+
+ sScriptMgr->AnticheatSetCanFlybyServer(plr, false);
+ sScriptMgr->AnticheatSetUnderACKmount(plr);
+ sScriptMgr->AnticheatSetSkipOnePacketForASH(plr, true);
}
}
@@ -921,6 +934,10 @@ public:
{
bUpdatedFlying = true;
plr->SetDisableGravity(true, true);
+
+ sScriptMgr->AnticheatSetCanFlybyServer(plr, true);
+ sScriptMgr->AnticheatSetSkipOnePacketForASH(plr, true);
+ sScriptMgr->AnticheatSetUnderACKmount(plr);
}
plr->SendMonsterMove(me->GetPositionX() + dist * cos(arcangle), me->GetPositionY() + dist * sin(arcangle), me->GetPositionZ(), VORTEX_DEFAULT_DIFF * 2, SPLINEFLAG_FLYING);
diff --git a/src/server/scripts/Spells/spell_druid.cpp b/src/server/scripts/Spells/spell_druid.cpp
index d93b893e08..be31c06a2f 100644
--- a/src/server/scripts/Spells/spell_druid.cpp
+++ b/src/server/scripts/Spells/spell_druid.cpp
@@ -1347,6 +1347,48 @@ public:
}
};
+// -50334 - Berserk
+class spell_dru_berserk : public SpellScriptLoader
+{
+public:
+ spell_dru_berserk() : SpellScriptLoader("spell_dru_berserk") { }
+
+ class spell_dru_berserk_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_dru_berserk_SpellScript);
+
+ void HandleAfterCast()
+ {
+ Unit* caster = GetCaster();
+
+ if (caster->GetTypeId() == TYPEID_PLAYER)
+ {
+ // Remove tiger fury / mangle(bear)
+ const uint32 TigerFury[6] = { 5217, 6793, 9845, 9846, 50212, 50213 };
+ const uint32 DireMaul[6] = { 33878, 33986, 33987, 48563, 48564 };
+
+ // remove aura
+ for (auto& i : TigerFury)
+ caster->RemoveAurasDueToSpell(i);
+
+ // reset dire bear maul cd
+ for (auto& i : DireMaul)
+ caster->ToPlayer()->RemoveSpellCooldown(i, true);
+ }
+ }
+
+ void Register() override
+ {
+ AfterCast += SpellCastFn(spell_dru_berserk_SpellScript::HandleAfterCast);
+ }
+ };
+
+ SpellScript* GetSpellScript() const
+ {
+ return new spell_dru_berserk_SpellScript();
+ }
+};
+
void AddSC_druid_spell_scripts()
{
// Ours
@@ -1357,6 +1399,7 @@ void AddSC_druid_spell_scripts()
new spell_dru_brambles_treant();
new spell_dru_barkskin();
new spell_dru_treant_scaling();
+ new spell_dru_berserk();
// Theirs
new spell_dru_dash();
diff --git a/src/server/game/Miscellaneous/SharedDefines.h b/src/server/shared/SharedDefines.h
similarity index 99%
rename from src/server/game/Miscellaneous/SharedDefines.h
rename to src/server/shared/SharedDefines.h
index 4f8bfea5f0..fd3bb43ed9 100644
--- a/src/server/game/Miscellaneous/SharedDefines.h
+++ b/src/server/shared/SharedDefines.h
@@ -3567,42 +3567,4 @@ enum PartyResult
ERR_PARTY_LFG_TELEPORT_IN_COMBAT = 30
};
-#define MMAP_MAGIC 0x4d4d4150 // 'MMAP'
-#define MMAP_VERSION 11
-
-struct MmapTileHeader
-{
- uint32 mmapMagic{MMAP_MAGIC};
- uint32 dtVersion;
- uint32 mmapVersion{MMAP_VERSION};
- uint32 size{0};
- char usesLiquids{true};
- char padding[3]{};
-
- MmapTileHeader() : dtVersion(DT_NAVMESH_VERSION) { }
-};
-
-// All padding fields must be handled and initialized to ensure mmaps_generator will produce binary-identical *.mmtile files
-static_assert(sizeof(MmapTileHeader) == 20, "MmapTileHeader size is not correct, adjust the padding field size");
-static_assert(sizeof(MmapTileHeader) == (sizeof(MmapTileHeader::mmapMagic) +
- sizeof(MmapTileHeader::dtVersion) +
- sizeof(MmapTileHeader::mmapVersion) +
- sizeof(MmapTileHeader::size) +
- sizeof(MmapTileHeader::usesLiquids) +
- sizeof(MmapTileHeader::padding)), "MmapTileHeader has uninitialized padding fields");
-
-enum NavTerrain
-{
- NAV_EMPTY = 0x00,
- NAV_GROUND = 0x01,
- NAV_MAGMA = 0x02,
- NAV_SLIME = 0x04,
- NAV_WATER = 0x08,
- NAV_UNUSED1 = 0x10,
- NAV_UNUSED2 = 0x20,
- NAV_UNUSED3 = 0x40,
- NAV_UNUSED4 = 0x80
- // we only have 8 bits
-};
-
#endif
diff --git a/src/tools/mesh_extractor/Utils.h b/src/tools/mesh_extractor/Utils.h
index 872a37f6d8..c1dd825473 100644
--- a/src/tools/mesh_extractor/Utils.h
+++ b/src/tools/mesh_extractor/Utils.h
@@ -6,6 +6,7 @@
#ifndef UTILS_H
#define UTILS_H
+
#include
#include
#include
@@ -337,9 +338,6 @@ public:
virtual float Scale() const { return 1.0f; };
};
-#define MMAP_MAGIC 0x4d4d4150 // 'MMAP'
-#define MMAP_VERSION 10
-
struct MmapTileHeader
{
uint32 mmapMagic;
diff --git a/src/tools/mmaps_generator/MapBuilder.cpp b/src/tools/mmaps_generator/MapBuilder.cpp
index 866b63c968..20a325b4c8 100644
--- a/src/tools/mmaps_generator/MapBuilder.cpp
+++ b/src/tools/mmaps_generator/MapBuilder.cpp
@@ -5,45 +5,14 @@
*/
#include "MapBuilder.h"
+#include "MapDefines.h"
#include "MapTree.h"
#include "ModelInstance.h"
#include "PathCommon.h"
-
#include
#include
#include
-#include "DisableMgr.h"
-
-namespace DisableMgr
-{
- bool IsDisabledFor(DisableType /*type*/, uint32 /*entry*/, Unit const* /*unit*/, uint8 /*flags*/ /*= 0*/) { return false; }
-}
-
-#define MMAP_MAGIC 0x4d4d4150 // 'MMAP'
-#define MMAP_VERSION 11
-
-struct MmapTileHeader
-{
- uint32 mmapMagic{MMAP_MAGIC};
- uint32 dtVersion;
- uint32 mmapVersion{MMAP_VERSION};
- uint32 size{0};
- char usesLiquids{true};
- char padding[3]{};
-
- MmapTileHeader() : dtVersion(DT_NAVMESH_VERSION) {}
-};
-
-// All padding fields must be handled and initialized to ensure mmaps_generator will produce binary-identical *.mmtile files
-static_assert(sizeof(MmapTileHeader) == 20, "MmapTileHeader size is not correct, adjust the padding field size");
-static_assert(sizeof(MmapTileHeader) == (sizeof(MmapTileHeader::mmapMagic) +
- sizeof(MmapTileHeader::dtVersion) +
- sizeof(MmapTileHeader::mmapVersion) +
- sizeof(MmapTileHeader::size) +
- sizeof(MmapTileHeader::usesLiquids) +
- sizeof(MmapTileHeader::padding)), "MmapTileHeader has uninitialized padding fields");
-
namespace MMAP
{
MapBuilder::MapBuilder(float maxWalkableAngle, bool skipLiquid,
diff --git a/src/tools/mmaps_generator/PathCommon.h b/src/tools/mmaps_generator/PathCommon.h
index 7aae074488..c196cf4ce6 100644
--- a/src/tools/mmaps_generator/PathCommon.h
+++ b/src/tools/mmaps_generator/PathCommon.h
@@ -20,20 +20,6 @@
#include
#endif
-enum NavTerrain
-{
- NAV_EMPTY = 0x00,
- NAV_GROUND = 0x01,
- NAV_MAGMA = 0x02,
- NAV_SLIME = 0x04,
- NAV_WATER = 0x08,
- NAV_UNUSED1 = 0x10,
- NAV_UNUSED2 = 0x20,
- NAV_UNUSED3 = 0x40,
- NAV_UNUSED4 = 0x80
- // we only have 8 bits
-};
-
namespace MMAP
{
inline bool matchWildcardFilter(const char* filter, const char* str)
diff --git a/src/tools/mmaps_generator/TerrainBuilder.cpp b/src/tools/mmaps_generator/TerrainBuilder.cpp
index 3c56e49c39..aaf33f675e 100644
--- a/src/tools/mmaps_generator/TerrainBuilder.cpp
+++ b/src/tools/mmaps_generator/TerrainBuilder.cpp
@@ -5,10 +5,9 @@
*/
#include "TerrainBuilder.h"
-
#include "PathCommon.h"
#include "MapBuilder.h"
-
+#include "MapDefines.h"
#include "VMapManager2.h"
#include "MapTree.h"
#include "ModelInstance.h"
diff --git a/src/tools/mmaps_generator/VMapExtensions.cpp b/src/tools/mmaps_generator/VMapExtensions.cpp
deleted file mode 100644
index 29970ae15c..0000000000
--- a/src/tools/mmaps_generator/VMapExtensions.cpp
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (C) 2016+ AzerothCore , released under GNU GPL v2 license: http://github.com/azerothcore/azerothcore-wotlk/LICENSE-GPL2
- * Copyright (C) 2008-2016 TrinityCore
- * Copyright (C) 2005-2009 MaNGOS
- */
-
-#include
-#include "MapTree.h"
-#include "VMapManager2.h"
-#include "WorldModel.h"
-#include "ModelInstance.h"
-
-namespace VMAP
-{
- // Need direct access to encapsulated VMAP data, so we add functions for MMAP generator
- // maybe add MapBuilder as friend to all of the below classes would be better?
-
- // declared in src/common/vmap/MapTree.h
- void StaticMapTree::getModelInstances(ModelInstance*& models, uint32& count)
- {
- models = iTreeValues;
- count = iNTreeValues;
- }
-
- // declared in src/common/vmap/VMapManager2.h
- void VMapManager2::getInstanceMapTree(InstanceTreeMap& instanceMapTree)
- {
- instanceMapTree = iInstanceMapTrees;
- }
-
- // declared in src/common/vmap/WorldModel.h
- void WorldModel::getGroupModels(std::vector& groupModels)
- {
- groupModels = this->groupModels;
- }
-
- // declared in src/common/vmap/WorldModel.h
- void GroupModel::getMeshData(std::vector& vertices, std::vector& triangles, WmoLiquid*& liquid)
- {
- vertices = this->vertices;
- triangles = this->triangles;
- liquid = iLiquid;
- }
-
- // declared in src/common/vmap/ModelInstance.h
- WorldModel* ModelInstance::getWorldModel()
- {
- return iModel;
- }
-
- // declared in src/common/vmap/WorldModel.h
- void WmoLiquid::getPosInfo(uint32& tilesX, uint32& tilesY, G3D::Vector3& corner) const
- {
- tilesX = iTilesX;
- tilesY = iTilesY;
- corner = iCorner;
- }
-}
diff --git a/var/ccache/.gitkeep b/var/ccache/.gitkeep
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/var/docker/build/.gitkeep b/var/docker/build/.gitkeep
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/var/docker/ccache/.gitkeep b/var/docker/ccache/.gitkeep
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/var/extractors/dbc/.gitkeep b/var/extractors/dbc/.gitkeep
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/var/extractors/maps/.gitkeep b/var/extractors/maps/.gitkeep
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/var/extractors/mmaps/.gitkeep b/var/extractors/mmaps/.gitkeep
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/var/extractors/vmaps/.gitkeep b/var/extractors/vmaps/.gitkeep
new file mode 100644
index 0000000000..e69de29bb2