minimize delta, legacy and merge mistakes over the years

This commit is contained in:
bash
2026-01-08 00:50:49 +01:00
parent ae2af138e2
commit 0a0ba0a53f
64 changed files with 908 additions and 1278 deletions
+1 -1
View File
@@ -31,7 +31,7 @@ body:
description: | description: |
Do you have any logs or screenshots that can be useful? Do you have any logs or screenshots that can be useful?
Crash logs in text are preffered over screenshots. Crash logs in text are preffered over screenshots.
If you have logs in text form please upload them to [Gist](https://gist.github.com/) or PasteBin and upload the link. DO NOT POST THE FULL CRASH LOG IN THE ISSUE BODY. DO NOT UPLOAD TEXT FILES. USE [GITHUB GIST](https://gist.github.com/), PASTEBIN, OR ANY SIMILAR SERVICE INSTEAD.
validations: validations:
required: false required: false
- type: input - type: input
-5
View File
@@ -1,10 +1,5 @@
# List of AUTHORS who contributed over time to the AzerothCore project # List of AUTHORS who contributed over time to the AzerothCore project
## Warning
The code of AzerothCore is shipped as it is without any form of warranty,
and - except for third party libraries licensed under the AGPL 3,
which you can read from the file "LICENSE".
## Point of current development ## Point of current development
The project is currently hosted at https://www.azerothcore.org/ and developed under https://github.com/azerothcore The project is currently hosted at https://www.azerothcore.org/ and developed under https://github.com/azerothcore
+1 -1
View File
@@ -258,4 +258,4 @@ COPY --chown=$DOCKER_USER:$DOCKER_USER --from=build \
/azerothcore/env/dist/bin/vmap4_assembler /azerothcore/env/dist/bin/vmap4_assembler /azerothcore/env/dist/bin/vmap4_assembler /azerothcore/env/dist/bin/vmap4_assembler
COPY --chown=$DOCKER_USER:$DOCKER_USER --from=build \ COPY --chown=$DOCKER_USER:$DOCKER_USER --from=build \
/azerothcore/env/dist/bin/vmap4_extractor /azerothcore/env/dist/bin/vmap4_extractor /azerothcore/env/dist/bin/vmap4_extractor /azerothcore/env/dist/bin/vmap4_extractor
+1 -1
View File
@@ -1,5 +1,5 @@
# #
# Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU AGPL v3 license: https://github.com/azerothcore/azerothcore-wotlk/blob/master/LICENSE # Copyright (C) 2016+ AzerothCore <www.azerothcore.org>
# Copyright (C) 2021+ WarheadCore <https://github.com/WarheadCore> # Copyright (C) 2021+ WarheadCore <https://github.com/WarheadCore>
# #
# This file is free software; as a special exception the author gives # This file is free software; as a special exception the author gives
+1 -1
View File
@@ -1,5 +1,5 @@
# Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> # Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/>
# Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU AGPL v3 license: https://github.com/azerothcore/azerothcore-wotlk/blob/master/LICENSE # Copyright (C) 2016+ AzerothCore <www.azerothcore.org>
# #
# This file is free software; as a special exception the author gives # This file is free software; as a special exception the author gives
# unlimited permission to copy and/or distribute it, with or without # unlimited permission to copy and/or distribute it, with or without
+1 -1
View File
@@ -1,5 +1,5 @@
# Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> # Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/>
# Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU AGPL v3 license: https://github.com/azerothcore/azerothcore-wotlk/blob/master/LICENSE # Copyright (C) 2016+ AzerothCore <www.azerothcore.org>
# #
# This file is free software; as a special exception the author gives # This file is free software; as a special exception the author gives
# unlimited permission to copy and/or distribute it, with or without # unlimited permission to copy and/or distribute it, with or without
@@ -1,7 +0,0 @@
### Added
- New hook for OnQuestComputeXP(). The intended use is to change the XP values for certain quests programmatically. The hook is triggered after XP calculation and before rewarding XP or gold to the player.
### How to upgrade
- No special changes needed. The new hook is available for use and should not interfere with any existing hooks or logic.
@@ -70,6 +70,7 @@ private:
{ {
tree.clear(); tree.clear();
objects.clear(); objects.clear();
bounds = G3D::AABox::empty();
// create space for the first node // create space for the first node
tree.push_back(3u << 30u); // dummy leaf tree.push_back(3u << 30u); // dummy leaf
tree.insert(tree.end(), 2, 0); tree.insert(tree.end(), 2, 0);
@@ -116,6 +117,7 @@ public:
delete[] dat.indices; delete[] dat.indices;
} }
[[nodiscard]] uint32 primCount() const { return objects.size(); } [[nodiscard]] uint32 primCount() const { return objects.size(); }
G3D::AABox const& bound() const { return bounds; }
template<typename RayCallback> template<typename RayCallback>
void intersectRay(const G3D::Ray& r, RayCallback& intersectCallback, float& maxDist, bool stopAtFirstHit) const void intersectRay(const G3D::Ray& r, RayCallback& intersectCallback, float& maxDist, bool stopAtFirstHit) const
+8 -41
View File
@@ -170,25 +170,6 @@ private:
VMAP::ModelIgnoreFlags _ignoreFlags; VMAP::ModelIgnoreFlags _ignoreFlags;
}; };
struct DynamicTreeAreaInfoCallback
{
DynamicTreeAreaInfoCallback(uint32 phaseMask) : _phaseMask(phaseMask) { }
void operator()(G3D::Vector3 const& p, GameObjectModel const& obj)
{
obj.IntersectPoint(p, _areaInfo, _phaseMask);
}
VMAP::AreaInfo const& GetAreaInfo() const
{
return _areaInfo;
}
private:
uint32 _phaseMask;
VMAP::AreaInfo _areaInfo;
};
struct DynamicTreeLocationInfoCallback struct DynamicTreeLocationInfoCallback
{ {
DynamicTreeLocationInfoCallback(uint32 phaseMask) DynamicTreeLocationInfoCallback(uint32 phaseMask)
@@ -308,24 +289,7 @@ float DynamicMapTree::getHeight(float x, float y, float z, float maxSearchDist,
} }
} }
bool DynamicMapTree::GetAreaInfo(float x, float y, float& z, uint32 phasemask, uint32& flags, int32& adtId, int32& rootId, int32& groupId) const bool DynamicMapTree::GetAreaAndLiquidData(float x, float y, float z, uint32 phasemask, Optional<uint8> reqLiquidType, VMAP::AreaAndLiquidData& data) const
{
G3D::Vector3 v(x, y, z + 0.5f);
DynamicTreeAreaInfoCallback intersectionCallBack(phasemask);
impl->intersectPoint(v, intersectionCallBack);
if (intersectionCallBack.GetAreaInfo().result)
{
flags = intersectionCallBack.GetAreaInfo().flags;
adtId = intersectionCallBack.GetAreaInfo().adtId;
rootId = intersectionCallBack.GetAreaInfo().rootId;
groupId = intersectionCallBack.GetAreaInfo().groupId;
z = intersectionCallBack.GetAreaInfo().ground_Z;
return true;
}
return false;
}
void DynamicMapTree::GetAreaAndLiquidData(float x, float y, float z, uint32 phasemask, uint8 reqLiquidType, VMAP::AreaAndLiquidData& data) const
{ {
G3D::Vector3 v(x, y, z + 0.5f); G3D::Vector3 v(x, y, z + 0.5f);
DynamicTreeLocationInfoCallback intersectionCallBack(phasemask); DynamicTreeLocationInfoCallback intersectionCallBack(phasemask);
@@ -335,13 +299,16 @@ void DynamicMapTree::GetAreaAndLiquidData(float x, float y, float z, uint32 phas
data.floorZ = intersectionCallBack.GetLocationInfo().ground_Z; data.floorZ = intersectionCallBack.GetLocationInfo().ground_Z;
uint32 liquidType = intersectionCallBack.GetLocationInfo().hitModel->GetLiquidType(); uint32 liquidType = intersectionCallBack.GetLocationInfo().hitModel->GetLiquidType();
float liquidLevel; float liquidLevel;
if (!reqLiquidType || (dynamic_cast<VMAP::VMapMgr2*>(VMAP::VMapFactory::createOrGetVMapMgr())->GetLiquidFlagsPtr(liquidType) & reqLiquidType)) if (!reqLiquidType || (dynamic_cast<VMAP::VMapMgr2*>(VMAP::VMapFactory::createOrGetVMapMgr())->GetLiquidFlagsPtr(liquidType) & *reqLiquidType))
if (intersectionCallBack.GetHitModel()->GetLiquidLevel(v, intersectionCallBack.GetLocationInfo(), liquidLevel)) if (intersectionCallBack.GetHitModel()->GetLiquidLevel(v, intersectionCallBack.GetLocationInfo(), liquidLevel))
data.liquidInfo.emplace(liquidType, liquidLevel); data.liquidInfo.emplace(liquidType, liquidLevel);
data.areaInfo.emplace(0, data.areaInfo.emplace(intersectionCallBack.GetLocationInfo().hitModel->GetWmoID(),
0,
intersectionCallBack.GetLocationInfo().rootId, intersectionCallBack.GetLocationInfo().rootId,
intersectionCallBack.GetLocationInfo().hitModel->GetWmoID(), intersectionCallBack.GetLocationInfo().hitModel->GetMogpFlags(),
intersectionCallBack.GetLocationInfo().hitModel->GetMogpFlags()); 0);
return true;
} }
return false;
} }
+2 -2
View File
@@ -19,6 +19,7 @@
#define _DYNTREE_H #define _DYNTREE_H
#include "Define.h" #include "Define.h"
#include "Optional.h"
namespace G3D namespace G3D
{ {
@@ -47,8 +48,7 @@ public:
bool GetIntersectionTime(uint32 phasemask, const G3D::Ray& ray, const G3D::Vector3& endPos, float& maxDist) const; bool GetIntersectionTime(uint32 phasemask, const G3D::Ray& ray, const G3D::Vector3& endPos, float& maxDist) const;
bool GetAreaInfo(float x, float y, float& z, uint32 phasemask, uint32& flags, int32& adtId, int32& rootId, int32& groupId) const; bool GetAreaAndLiquidData(float x, float y, float z, uint32 phasemask, Optional<uint8> reqLiquidType, VMAP::AreaAndLiquidData& data) const;
void GetAreaAndLiquidData(float x, float y, float z, uint32 phasemask, uint8 reqLiquidType, VMAP::AreaAndLiquidData& data) const;
bool GetObjectHitPos(uint32 phasemask, const G3D::Vector3& pPos1, bool GetObjectHitPos(uint32 phasemask, const G3D::Vector3& pPos1,
const G3D::Vector3& pPos2, G3D::Vector3& pResultHitPos, const G3D::Vector3& pPos2, G3D::Vector3& pResultHitPos,
+13 -12
View File
@@ -52,20 +52,23 @@ namespace VMAP
{ {
struct AreaInfo struct AreaInfo
{ {
AreaInfo(int32 _adtId, int32 _rootId, int32 _groupId, uint32 _flags) AreaInfo() = default;
: adtId(_adtId), rootId(_rootId), groupId(_groupId), mogpFlags(_flags) { } AreaInfo(int32 _groupId, int32 _adtId, int32 _rootId, uint32 _mogpFlags, uint32 _uniqueId)
int32 const adtId; : groupId(_groupId), adtId(_adtId), rootId(_rootId), mogpFlags(_mogpFlags), uniqueId(_uniqueId) { }
int32 const rootId; int32 groupId = 0;
int32 const groupId; int32 adtId = 0;
uint32 const mogpFlags; int32 rootId = 0;
uint32 mogpFlags = 0;
uint32 uniqueId = 0;
}; };
struct LiquidInfo struct LiquidInfo
{ {
LiquidInfo() = default;
LiquidInfo(uint32 _type, float _level) LiquidInfo(uint32 _type, float _level)
: type(_type), level(_level) {} : type(_type), level(_level) {}
uint32 const type; uint32 type = 0;
float const level; float level = 0.0f;
}; };
float floorZ = VMAP_INVALID_HEIGHT; float floorZ = VMAP_INVALID_HEIGHT;
@@ -120,14 +123,12 @@ namespace VMAP
[[nodiscard]] bool isMapLoadingEnabled() const { return (iEnableLineOfSightCalc || iEnableHeightCalc ); } [[nodiscard]] bool isMapLoadingEnabled() const { return (iEnableLineOfSightCalc || iEnableHeightCalc ); }
[[nodiscard]] virtual std::string getDirFileName(unsigned int pMapId, int x, int y) const = 0; [[nodiscard]] virtual std::string getDirFileName(unsigned int pMapId, int x, int y) const = 0;
/** /**
Query world model area info. Query world model area info.
\param z gets adjusted to the ground height for which this are info is valid \param z gets adjusted to the ground height for which this are info is valid
*/ */
virtual bool GetAreaInfo(uint32 pMapId, float x, float y, float& z, uint32& flags, int32& adtId, int32& rootId, int32& groupId) const = 0; virtual bool GetAreaAndLiquidData(uint32 mapId, float x, float y, float z, Optional<uint8> reqLiquidType, AreaAndLiquidData& data) const = 0;
virtual bool GetLiquidLevel(uint32 pMapId, float x, float y, float z, uint8 ReqLiquidType, float& level, float& floor, uint32& type, uint32& mogpFlags) const = 0;
// get both area + liquid data in a single vmap lookup
virtual void GetAreaAndLiquidData(uint32 mapId, float x, float y, float z, uint8 reqLiquidType, AreaAndLiquidData& data) const = 0;
}; };
} }
+1 -2
View File
@@ -138,8 +138,7 @@ namespace MMAP
uint32 packedGridPos = packTileID(x, y); uint32 packedGridPos = packTileID(x, y);
if (mmap->loadedTileRefs.find(packedGridPos) != mmap->loadedTileRefs.end()) if (mmap->loadedTileRefs.find(packedGridPos) != mmap->loadedTileRefs.end())
{ {
// Peiru: Commented out for now because Playerbots system uses this method to load or check loaded maps and will spam logs LOG_ERROR("maps", "MMAP:loadMap: Asked to load already loaded navmesh tile. {:03}{:02}{:02}.mmtile", mapId, x, y);
// LOG_ERROR("maps", "MMAP:loadMap: Asked to load already loaded navmesh tile. {:03}{:02}{:02}.mmtile", mapId, x, y);
return false; return false;
} }
+13 -69
View File
@@ -253,70 +253,8 @@ namespace VMAP
return VMAP_INVALID_HEIGHT_VALUE; return VMAP_INVALID_HEIGHT_VALUE;
} }
bool VMapMgr2::GetAreaInfo(uint32 mapId, float x, float y, float& z, uint32& flags, int32& adtId, int32& rootId, int32& groupId) const bool VMapMgr2::GetAreaAndLiquidData(uint32 mapId, float x, float y, float z, Optional<uint8> reqLiquidType, AreaAndLiquidData& data) const
{ {
#if defined(ENABLE_VMAP_CHECKS)
if (!IsVMAPDisabledForPtr(mapId, VMAP_DISABLE_AREAFLAG))
#endif
{
InstanceTreeMap::const_iterator instanceTree = GetMapTree(mapId);
if (instanceTree != iInstanceMapTrees.end())
{
Vector3 pos = convertPositionToInternalRep(x, y, z);
bool result = instanceTree->second->GetAreaInfo(pos, flags, adtId, rootId, groupId);
// z is not touched by convertPositionToInternalRep(), so just copy
z = pos.z;
return result;
}
}
return false;
}
bool VMapMgr2::GetLiquidLevel(uint32 mapId, float x, float y, float z, uint8 reqLiquidType, float& level, float& floor, uint32& type, uint32& mogpFlags) const
{
#if defined(ENABLE_VMAP_CHECKS)
if (!IsVMAPDisabledForPtr(mapId, VMAP_DISABLE_LIQUIDSTATUS))
#endif
{
InstanceTreeMap::const_iterator instanceTree = GetMapTree(mapId);
if (instanceTree != iInstanceMapTrees.end())
{
LocationInfo info;
Vector3 pos = convertPositionToInternalRep(x, y, z);
if (instanceTree->second->GetLocationInfo(pos, info))
{
floor = info.ground_Z;
ASSERT(floor < std::numeric_limits<float>::max());
type = info.hitModel->GetLiquidType(); // entry from LiquidType.dbc
mogpFlags = info.hitModel->GetMogpFlags();
if (reqLiquidType && !(GetLiquidFlagsPtr(type) & reqLiquidType))
{
return false;
}
if (info.hitInstance->GetLiquidLevel(pos, info, level))
{
return true;
}
}
}
}
return false;
}
void VMapMgr2::GetAreaAndLiquidData(uint32 mapId, float x, float y, float z, uint8 reqLiquidType, AreaAndLiquidData& data) const
{
if (IsVMAPDisabledForPtr(mapId, VMAP_DISABLE_LIQUIDSTATUS))
{
data.floorZ = z;
int32 adtId, rootId, groupId;
uint32 flags;
if (GetAreaInfo(mapId, x, y, data.floorZ, flags, adtId, rootId, groupId))
data.areaInfo.emplace(adtId, rootId, groupId, flags);
return;
}
InstanceTreeMap::const_iterator instanceTree = GetMapTree(mapId); InstanceTreeMap::const_iterator instanceTree = GetMapTree(mapId);
if (instanceTree != iInstanceMapTrees.end()) if (instanceTree != iInstanceMapTrees.end())
{ {
@@ -325,16 +263,22 @@ namespace VMAP
if (instanceTree->second->GetLocationInfo(pos, info)) if (instanceTree->second->GetLocationInfo(pos, info))
{ {
data.floorZ = info.ground_Z; data.floorZ = info.ground_Z;
uint32 liquidType = info.hitModel->GetLiquidType(); if (!IsVMAPDisabledForPtr(mapId, VMAP_DISABLE_LIQUIDSTATUS))
float liquidLevel; {
if (!reqLiquidType || (GetLiquidFlagsPtr(liquidType) & reqLiquidType)) uint32 liquidType = info.hitModel->GetLiquidType(); // entry from LiquidType.dbc
if (info.hitInstance->GetLiquidLevel(pos, info, liquidLevel)) float liquidLevel;
data.liquidInfo.emplace(liquidType, liquidLevel); if (!reqLiquidType || (GetLiquidFlagsPtr(liquidType) & *reqLiquidType))
if (info.hitInstance->GetLiquidLevel(pos, info, liquidLevel))
data.liquidInfo.emplace(liquidType, liquidLevel);
}
if (!IsVMAPDisabledForPtr(mapId, VMAP_DISABLE_AREAFLAG)) if (!IsVMAPDisabledForPtr(mapId, VMAP_DISABLE_AREAFLAG))
data.areaInfo.emplace(info.hitInstance->adtId, info.rootId, info.hitModel->GetWmoID(), info.hitModel->GetMogpFlags()); data.areaInfo.emplace(info.hitModel->GetWmoID(), info.hitInstance->adtId, info.rootId, info.hitModel->GetMogpFlags(), info.hitInstance->ID);
return true;
} }
} }
return false;
} }
WorldModel* VMapMgr2::acquireModelInstance(const std::string& basepath, const std::string& filename, uint32 flags/* Only used when creating the model */) WorldModel* VMapMgr2::acquireModelInstance(const std::string& basepath, const std::string& filename, uint32 flags/* Only used when creating the model */)
+1 -3
View File
@@ -115,9 +115,7 @@ namespace VMAP
bool processCommand(char* /*command*/) override { return false; } // for debug and extensions bool processCommand(char* /*command*/) override { return false; } // for debug and extensions
bool GetAreaInfo(uint32 pMapId, float x, float y, float& z, uint32& flags, int32& adtId, int32& rootId, int32& groupId) const override; bool GetAreaAndLiquidData(uint32 mapId, float x, float y, float z, Optional<uint8> reqLiquidType, AreaAndLiquidData& data) const override;
bool GetLiquidLevel(uint32 pMapId, float x, float y, float z, uint8 reqLiquidType, float& level, float& floor, uint32& type, uint32& mogpFlags) const override;
void GetAreaAndLiquidData(uint32 mapId, float x, float y, float z, uint8 reqLiquidType, AreaAndLiquidData& data) const override;
WorldModel* acquireModelInstance(const std::string& basepath, const std::string& filename, uint32 flags); WorldModel* acquireModelInstance(const std::string& basepath, const std::string& filename, uint32 flags);
void releaseModelInstance(const std::string& filename); void releaseModelInstance(const std::string& filename);
-32
View File
@@ -51,22 +51,6 @@ namespace VMAP
bool hit; bool hit;
}; };
class AreaInfoCallback
{
public:
AreaInfoCallback(ModelInstance* val): prims(val) {}
void operator()(const Vector3& point, uint32 entry)
{
#if defined(VMAP_DEBUG)
LOG_DEBUG("maps", "AreaInfoCallback: trying to intersect '{}'", prims[entry].name);
#endif
prims[entry].intersectPoint(point, aInfo);
}
ModelInstance* prims;
AreaInfo aInfo;
};
class LocationInfoCallback class LocationInfoCallback
{ {
public: public:
@@ -99,22 +83,6 @@ namespace VMAP
return tilefilename.str(); return tilefilename.str();
} }
bool StaticMapTree::GetAreaInfo(Vector3& pos, uint32& flags, int32& adtId, int32& rootId, int32& groupId) const
{
AreaInfoCallback intersectionCallBack(iTreeValues);
iTree.intersectPoint(pos, intersectionCallBack);
if (intersectionCallBack.aInfo.result)
{
flags = intersectionCallBack.aInfo.flags;
adtId = intersectionCallBack.aInfo.adtId;
rootId = intersectionCallBack.aInfo.rootId;
groupId = intersectionCallBack.aInfo.groupId;
pos.z = intersectionCallBack.aInfo.ground_Z;
return true;
}
return false;
}
bool StaticMapTree::GetLocationInfo(const Vector3& pos, LocationInfo& info) const bool StaticMapTree::GetLocationInfo(const Vector3& pos, LocationInfo& info) const
{ {
LocationInfoCallback intersectionCallBack(iTreeValues, info); LocationInfoCallback intersectionCallBack(iTreeValues, info);
+6 -1
View File
@@ -30,6 +30,12 @@ namespace VMAP
enum class ModelIgnoreFlags : uint32; enum class ModelIgnoreFlags : uint32;
enum class LoadResult : uint8; enum class LoadResult : uint8;
struct GroupLocationInfo
{
const GroupModel* hitModel = nullptr;
int32 rootId = -1;
};
struct LocationInfo struct LocationInfo
{ {
LocationInfo(): ground_Z(-G3D::inf()) { } LocationInfo(): ground_Z(-G3D::inf()) { }
@@ -73,7 +79,6 @@ namespace VMAP
[[nodiscard]] bool isInLineOfSight(const G3D::Vector3& pos1, const G3D::Vector3& pos2, ModelIgnoreFlags ignoreFlags) const; [[nodiscard]] bool isInLineOfSight(const G3D::Vector3& pos1, const G3D::Vector3& pos2, ModelIgnoreFlags ignoreFlags) const;
bool GetObjectHitPos(const G3D::Vector3& pos1, const G3D::Vector3& pos2, G3D::Vector3& pResultHitPos, float pModifyDist) const; bool GetObjectHitPos(const G3D::Vector3& pos1, const G3D::Vector3& pos2, G3D::Vector3& pResultHitPos, float pModifyDist) const;
[[nodiscard]] float getHeight(const G3D::Vector3& pPos, float maxSearchDist) const; [[nodiscard]] float getHeight(const G3D::Vector3& pPos, float maxSearchDist) const;
bool GetAreaInfo(G3D::Vector3& pos, uint32& flags, int32& adtId, int32& rootId, int32& groupId) const;
bool GetLocationInfo(const G3D::Vector3& pos, LocationInfo& info) const; bool GetLocationInfo(const G3D::Vector3& pos, LocationInfo& info) const;
bool InitMap(const std::string& fname, VMapMgr2* vm); bool InitMap(const std::string& fname, VMapMgr2* vm);
@@ -203,27 +203,6 @@ bool GameObjectModel::intersectRay(const G3D::Ray& ray, float& MaxDist, bool Sto
return hit; return hit;
} }
void GameObjectModel::IntersectPoint(G3D::Vector3 const& point, VMAP::AreaInfo& info, uint32 ph_mask) const
{
if (!(phasemask & ph_mask) || !owner->IsSpawned() || !IsMapObject())
return;
if (!iBound.contains(point))
return;
// child bounds are defined in object space:
Vector3 pModel = iInvRot * (point - iPos) * iInvScale;
Vector3 zDirModel = iInvRot * Vector3(0.f, 0.f, -1.f);
float zDist;
if (iModel->IntersectPoint(pModel, zDirModel, zDist, info))
{
Vector3 modelGround = pModel + zDist * zDirModel;
float world_Z = ((modelGround * iInvRot) * iScale + iPos).z;
if (info.ground_Z < world_Z)
info.ground_Z = world_Z;
}
}
bool GameObjectModel::GetLocationInfo(G3D::Vector3 const& point, VMAP::LocationInfo& info, uint32 ph_mask) const bool GameObjectModel::GetLocationInfo(G3D::Vector3 const& point, VMAP::LocationInfo& info, uint32 ph_mask) const
{ {
if (!(phasemask & ph_mask) || !owner->IsSpawned() || !IsMapObject()) if (!(phasemask & ph_mask) || !owner->IsSpawned() || !IsMapObject())
@@ -236,7 +215,9 @@ bool GameObjectModel::GetLocationInfo(G3D::Vector3 const& point, VMAP::LocationI
Vector3 pModel = iInvRot * (point - iPos) * iInvScale; Vector3 pModel = iInvRot * (point - iPos) * iInvScale;
Vector3 zDirModel = iInvRot * Vector3(0.f, 0.f, -1.f); Vector3 zDirModel = iInvRot * Vector3(0.f, 0.f, -1.f);
float zDist; float zDist;
if (iModel->GetLocationInfo(pModel, zDirModel, zDist, info))
VMAP::GroupLocationInfo groupInfo;
if (iModel->GetLocationInfo(pModel, zDirModel, zDist, groupInfo))
{ {
Vector3 modelGround = pModel + zDist * zDirModel; Vector3 modelGround = pModel + zDist * zDirModel;
float world_Z = ((modelGround * iInvRot) * iScale + iPos).z; float world_Z = ((modelGround * iInvRot) * iScale + iPos).z;
@@ -70,7 +70,6 @@ public:
[[nodiscard]] bool IsMapObject() const { return isWmo; } [[nodiscard]] bool IsMapObject() const { return isWmo; }
bool intersectRay(const G3D::Ray& Ray, float& MaxDist, bool StopAtFirstHit, uint32 ph_mask, VMAP::ModelIgnoreFlags ignoreFlags) const; bool intersectRay(const G3D::Ray& Ray, float& MaxDist, bool StopAtFirstHit, uint32 ph_mask, VMAP::ModelIgnoreFlags ignoreFlags) const;
void IntersectPoint(G3D::Vector3 const& point, VMAP::AreaInfo& info, uint32 ph_mask) const;
bool GetLocationInfo(G3D::Vector3 const& point, VMAP::LocationInfo& info, uint32 ph_mask) const; bool GetLocationInfo(G3D::Vector3 const& point, VMAP::LocationInfo& info, uint32 ph_mask) const;
bool GetLiquidLevel(G3D::Vector3 const& point, VMAP::LocationInfo& info, float& liqHeight) const; bool GetLiquidLevel(G3D::Vector3 const& point, VMAP::LocationInfo& info, float& liqHeight) const;
+5 -39
View File
@@ -63,44 +63,6 @@ namespace VMAP
return hit; return hit;
} }
void ModelInstance::intersectPoint(const G3D::Vector3& p, AreaInfo& info) const
{
if (!iModel)
{
#ifdef VMAP_DEBUG
std::cout << "<object not loaded>\n";
#endif
return;
}
// M2 files don't contain area info, only WMO files
if (flags & MOD_M2)
{
return;
}
if (!iBound.contains(p))
{
return;
}
// child bounds are defined in object space:
Vector3 pModel = iInvRot * (p - iPos) * iInvScale;
Vector3 zDirModel = iInvRot * Vector3(0.f, 0.f, -1.f);
float zDist;
if (iModel->IntersectPoint(pModel, zDirModel, zDist, info))
{
Vector3 modelGround = pModel + zDist * zDirModel;
// Transform back to world space. Note that:
// Mat * vec == vec * Mat.transpose()
// and for rotation matrices: Mat.inverse() == Mat.transpose()
float world_Z = ((modelGround * iInvRot) * iScale + iPos).z;
if (info.ground_Z < world_Z)
{
info.ground_Z = world_Z;
info.adtId = adtId;
}
}
}
bool ModelInstance::GetLocationInfo(const G3D::Vector3& p, LocationInfo& info) const bool ModelInstance::GetLocationInfo(const G3D::Vector3& p, LocationInfo& info) const
{ {
if (!iModel) if (!iModel)
@@ -124,7 +86,9 @@ namespace VMAP
Vector3 pModel = iInvRot * (p - iPos) * iInvScale; Vector3 pModel = iInvRot * (p - iPos) * iInvScale;
Vector3 zDirModel = iInvRot * Vector3(0.f, 0.f, -1.f); Vector3 zDirModel = iInvRot * Vector3(0.f, 0.f, -1.f);
float zDist; float zDist;
if (iModel->GetLocationInfo(pModel, zDirModel, zDist, info))
GroupLocationInfo groupInfo;
if (iModel->GetLocationInfo(pModel, zDirModel, zDist, groupInfo))
{ {
Vector3 modelGround = pModel + zDist * zDirModel; Vector3 modelGround = pModel + zDist * zDirModel;
// Transform back to world space. Note that: // Transform back to world space. Note that:
@@ -133,6 +97,8 @@ namespace VMAP
float world_Z = ((modelGround * iInvRot) * iScale + iPos).z; float world_Z = ((modelGround * iInvRot) * iScale + iPos).z;
if (info.ground_Z < world_Z) // hm...could it be handled automatically with zDist at intersection? if (info.ground_Z < world_Z) // hm...could it be handled automatically with zDist at intersection?
{ {
info.rootId = groupInfo.rootId;
info.hitModel = groupInfo.hitModel;
info.ground_Z = world_Z; info.ground_Z = world_Z;
info.hitInstance = this; info.hitInstance = this;
return true; return true;
@@ -66,7 +66,6 @@ namespace VMAP
ModelInstance(const ModelSpawn& spawn, WorldModel* model); ModelInstance(const ModelSpawn& spawn, WorldModel* model);
void setUnloaded() { iModel = nullptr; } void setUnloaded() { iModel = nullptr; }
bool intersectRay(const G3D::Ray& pRay, float& pMaxDist, bool StopAtFirstHit, ModelIgnoreFlags ignoreFlags) const; bool intersectRay(const G3D::Ray& pRay, float& pMaxDist, bool StopAtFirstHit, ModelIgnoreFlags ignoreFlags) const;
void intersectPoint(const G3D::Vector3& p, AreaInfo& info) const;
bool GetLocationInfo(const G3D::Vector3& p, LocationInfo& info) const; bool GetLocationInfo(const G3D::Vector3& p, LocationInfo& info) const;
bool GetLiquidLevel(const G3D::Vector3& p, LocationInfo& info, float& liqHeight) const; bool GetLiquidLevel(const G3D::Vector3& p, LocationInfo& info, float& liqHeight) const;
WorldModel* getWorldModel() { return iModel; } WorldModel* getWorldModel() { return iModel; }
+66 -59
View File
@@ -20,9 +20,9 @@
#include "ModelIgnoreFlags.h" #include "ModelIgnoreFlags.h"
#include "ModelInstance.h" #include "ModelInstance.h"
#include "VMapDefinitions.h" #include "VMapDefinitions.h"
#include <array>
using G3D::Vector3; using G3D::Vector3;
using G3D::Ray;
template<> struct BoundsTrait<VMAP::GroupModel> template<> struct BoundsTrait<VMAP::GroupModel>
{ {
@@ -451,21 +451,46 @@ namespace VMAP
return callback.hit; return callback.hit;
} }
bool GroupModel::IsInsideObject(const Vector3& pos, const Vector3& down, float& z_dist) const inline bool IsInsideOrAboveBound(G3D::AABox const& bounds, const G3D::Point3& point)
{ {
if (triangles.empty() || !iBound.contains(pos)) return point.x >= bounds.low().x
&& point.y >= bounds.low().y
&& point.z >= bounds.low().z
&& point.x <= bounds.high().x
&& point.y <= bounds.high().y;
}
GroupModel::InsideResult GroupModel::IsInsideObject(G3D::Ray const& ray, float& z_dist) const
{
if (triangles.empty() || !IsInsideOrAboveBound(iBound, ray.origin()))
return OUT_OF_BOUNDS;
if (meshTree.bound().high().z >= ray.origin().z)
{ {
return false; float dist = G3D::finf();
if (IntersectRay(ray, dist, false))
{
z_dist = dist - 0.1f;
return INSIDE;
}
if (meshTree.bound().contains(ray.origin()))
return MAYBE_INSIDE;
} }
Vector3 rPos = pos - 0.1f * down; else
float dist = G3D::inf();
G3D::Ray ray(rPos, down);
bool hit = IntersectRay(ray, dist, false);
if (hit)
{ {
z_dist = dist - 0.1f; // some group models don't have any floor to intersect with
// so we should attempt to intersect with a model part below this group
// then find back where we originated from (in WorldModel::GetLocationInfo)
float dist = G3D::finf();
float delta = ray.origin().z - meshTree.bound().high().z;
if (IntersectRay(ray.bumpedRay(delta), dist, false))
{
z_dist = dist - 0.1f + delta;
return ABOVE;
}
} }
return hit;
return OUT_OF_BOUNDS;
} }
bool GroupModel::GetLiquidLevel(const Vector3& pos, float& liqHeight) const bool GroupModel::GetLiquidLevel(const Vector3& pos, float& liqHeight) const
@@ -541,76 +566,58 @@ namespace VMAP
class WModelAreaCallback class WModelAreaCallback
{ {
public: public:
WModelAreaCallback(const std::vector<GroupModel>& vals, const Vector3& down): WModelAreaCallback(std::vector<GroupModel> const& vals) :
prims(vals.begin()), hit(vals.end()), minVol(G3D::inf()), zDist(G3D::inf()), zVec(down) { } prims(vals), hit() { }
std::vector<GroupModel>::const_iterator prims; std::vector<GroupModel> const& prims;
std::vector<GroupModel>::const_iterator hit; std::array<GroupModel const*, 3> hit;
float minVol; bool operator()(G3D::Ray const& ray, uint32 entry, float& distance, bool /*stopAtFirstHit*/)
float zDist;
Vector3 zVec;
void operator()(const Vector3& point, uint32 entry)
{ {
float group_Z; float group_Z;
//float pVol = prims[entry].GetBound().volume(); if (GroupModel::InsideResult result = prims[entry].IsInsideObject(ray, group_Z); result != GroupModel::OUT_OF_BOUNDS)
//if (pVol < minVol)
//{
/* if (prims[entry].iBound.contains(point)) */
if (prims[entry].IsInsideObject(point, zVec, group_Z))
{ {
//minVol = pVol; if (result != GroupModel::MAYBE_INSIDE)
//hit = prims + entry;
if (group_Z < zDist)
{ {
zDist = group_Z; if (group_Z < distance)
hit = prims + entry; {
distance = group_Z;
hit[result] = &prims[entry];
return true;
}
} }
#ifdef VMAP_DEBUG else
const GroupModel& gm = prims[entry]; hit[result] = &prims[entry];
printf("%10u %8X %7.3f, %7.3f, %7.3f | %7.3f, %7.3f, %7.3f | z=%f, p_z=%f\n", gm.GetWmoID(), gm.GetMogpFlags(),
gm.GetBound().low().x, gm.GetBound().low().y, gm.GetBound().low().z,
gm.GetBound().high().x, gm.GetBound().high().y, gm.GetBound().high().z, group_Z, point.z);
#endif
} }
//} return false;
//std::cout << "trying to intersect '" << prims[entry].name << "'\n";
} }
}; };
bool WorldModel::IntersectPoint(const G3D::Vector3& p, const G3D::Vector3& down, float& dist, AreaInfo& info) const bool WorldModel::GetLocationInfo(const G3D::Vector3& p, const G3D::Vector3& down, float& dist, GroupLocationInfo& info) const
{ {
if (groupModels.empty()) if (groupModels.empty())
{ {
return false; return false;
} }
WModelAreaCallback callback(groupModels, down); WModelAreaCallback callback(groupModels);
groupTree.intersectPoint(p, callback); G3D::Ray r(p - down * 0.1f, down);
if (callback.hit != groupModels.end()) float zDist = groupTree.bound().extent().length();
groupTree.intersectRay(r, callback, zDist, false);
if (callback.hit[GroupModel::INSIDE])
{ {
info.rootId = RootWMOID; info.rootId = RootWMOID;
info.groupId = callback.hit->GetWmoID(); info.hitModel = callback.hit[GroupModel::INSIDE];
info.flags = callback.hit->GetMogpFlags(); dist = zDist;
info.result = true;
dist = callback.zDist;
return true; return true;
} }
return false;
}
bool WorldModel::GetLocationInfo(const G3D::Vector3& p, const G3D::Vector3& down, float& dist, LocationInfo& info) const // some group models don't have any floor to intersect with
{ // so we should attempt to intersect with a model part below the group `p` is in (stored in GroupModel::ABOVE)
if (groupModels.empty()) // then find back where we originated from (GroupModel::MAYBE_INSIDE)
{ if (callback.hit[GroupModel::MAYBE_INSIDE] && callback.hit[GroupModel::ABOVE])
return false;
}
WModelAreaCallback callback(groupModels, down);
groupTree.intersectPoint(p, callback);
if (callback.hit != groupModels.end())
{ {
info.rootId = RootWMOID; info.rootId = RootWMOID;
info.hitModel = &(*callback.hit); info.hitModel = callback.hit[GroupModel::MAYBE_INSIDE];
dist = callback.zDist; dist = zDist;
return true; return true;
} }
return false; return false;
+6 -4
View File
@@ -29,6 +29,7 @@ namespace VMAP
class TreeNode; class TreeNode;
struct AreaInfo; struct AreaInfo;
struct LocationInfo; struct LocationInfo;
struct GroupLocationInfo;
enum class ModelIgnoreFlags : uint32; enum class ModelIgnoreFlags : uint32;
class MeshTriangle class MeshTriangle
@@ -81,12 +82,14 @@ namespace VMAP
void setMeshData(std::vector<G3D::Vector3>& vert, std::vector<MeshTriangle>& tri); void setMeshData(std::vector<G3D::Vector3>& vert, std::vector<MeshTriangle>& tri);
void setLiquidData(WmoLiquid*& liquid) { iLiquid = liquid; liquid = nullptr; } void setLiquidData(WmoLiquid*& liquid) { iLiquid = liquid; liquid = nullptr; }
bool IntersectRay(const G3D::Ray& ray, float& distance, bool stopAtFirstHit) const; bool IntersectRay(const G3D::Ray& ray, float& distance, bool stopAtFirstHit) const;
bool IsInsideObject(const G3D::Vector3& pos, const G3D::Vector3& down, float& z_dist) const; enum InsideResult { INSIDE = 0, MAYBE_INSIDE = 1, ABOVE = 2, OUT_OF_BOUNDS = -1 };
InsideResult IsInsideObject(G3D::Ray const& ray, float& z_dist) const;
bool GetLiquidLevel(const G3D::Vector3& pos, float& liqHeight) const; bool GetLiquidLevel(const G3D::Vector3& pos, float& liqHeight) const;
[[nodiscard]] uint32 GetLiquidType() const; [[nodiscard]] uint32 GetLiquidType() const;
bool writeToFile(FILE* wf); bool writeToFile(FILE* wf);
bool readFromFile(FILE* rf); bool readFromFile(FILE* rf);
[[nodiscard]] const G3D::AABox& GetBound() const { return iBound; } [[nodiscard]] G3D::AABox const& GetBound() const { return iBound; }
[[nodiscard]] G3D::AABox const& GetMeshTreeBound() const { return meshTree.bound(); }
[[nodiscard]] uint32 GetMogpFlags() const { return iMogpFlags; } [[nodiscard]] uint32 GetMogpFlags() const { return iMogpFlags; }
[[nodiscard]] uint32 GetWmoID() const { return iGroupWMOID; } [[nodiscard]] uint32 GetWmoID() const { return iGroupWMOID; }
void GetMeshData(std::vector<G3D::Vector3>& outVertices, std::vector<MeshTriangle>& outTriangles, WmoLiquid*& liquid); void GetMeshData(std::vector<G3D::Vector3>& outVertices, std::vector<MeshTriangle>& outTriangles, WmoLiquid*& liquid);
@@ -109,8 +112,7 @@ namespace VMAP
void setGroupModels(std::vector<GroupModel>& models); void setGroupModels(std::vector<GroupModel>& models);
void setRootWmoID(uint32 id) { RootWMOID = id; } void setRootWmoID(uint32 id) { RootWMOID = id; }
bool IntersectRay(const G3D::Ray& ray, float& distance, bool stopAtFirstHit, ModelIgnoreFlags ignoreFlags) const; bool IntersectRay(const G3D::Ray& ray, float& distance, bool stopAtFirstHit, ModelIgnoreFlags ignoreFlags) const;
bool IntersectPoint(const G3D::Vector3& p, const G3D::Vector3& down, float& dist, AreaInfo& info) const; bool GetLocationInfo(const G3D::Vector3& p, const G3D::Vector3& down, float& dist, GroupLocationInfo& info) const;
bool GetLocationInfo(const G3D::Vector3& p, const G3D::Vector3& down, float& dist, LocationInfo& info) const;
bool writeFile(const std::string& filename); bool writeFile(const std::string& filename);
bool readFile(const std::string& filename); bool readFile(const std::string& filename);
void GetGroupModels(std::vector<GroupModel>& outGroupModels); void GetGroupModels(std::vector<GroupModel>& outGroupModels);
+1 -1
View File
@@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU AGPL v3 license: https://github.com/azerothcore/azerothcore-wotlk/blob/master/LICENSE # Copyright (C) 2016+ AzerothCore <www.azerothcore.org>
* *
* This file was based on * This file was based on
* https://embeddedartistry.com/blog/2017/05/17/creating-a-circular-buffer-in-c-and-c/ * https://embeddedartistry.com/blog/2017/05/17/creating-a-circular-buffer-in-c-and-c/
+1 -1
View File
@@ -1,5 +1,5 @@
/* /*
* Originally written by Rochet2 - Copyright (C) 2018+ AzerothCore <www.azerothcore.org>, released under GNU AGPL v3 license: http://github.com/azerothcore/azerothcore-wotlk/blob/master/LICENSE * Originally written by Rochet2 - Copyright (C) 2018+ AzerothCore <www.azerothcore.org>
*/ */
#ifndef _DATA_MAP_H_ #ifndef _DATA_MAP_H_
-26
View File
@@ -97,32 +97,6 @@ public:
return _eventMap.empty(); return _eventMap.empty();
} }
/**
* @return Current internal time as uint32 milliseconds
*
* was removed in core https://github.com/azerothcore/azerothcore-wotlk/pull/23121,
* but still required atm for mod-playerbot.
*/
uint32 GetTimer() const
{
return static_cast<uint32>(duration_cast<Milliseconds>(_time.time_since_epoch()).count());
}
/**
* @return Time of found even
*
* was removed in core https://github.com/azerothcore/azerothcore-wotlk/pull/23121,
* but still required atm for mod-playerbot.
*/
uint32 GetNextEventTime(uint16 eventId) const
{
auto timeUntil = GetTimeUntilEvent(eventId);
if (timeUntil == Milliseconds::max())
return 0;
return GetTimer() + static_cast<uint32>(timeUntil.count());
}
/** /**
* @name SetPhase * @name SetPhase
* @brief Sets the phase of the map (absolute). * @brief Sets the phase of the map (absolute).
+1 -1
View File
@@ -120,7 +120,7 @@ class EventProcessor
[[nodiscard]] uint64 CalculateQueueTime(uint64 delay) const; [[nodiscard]] uint64 CalculateQueueTime(uint64 delay) const;
void CancelEventGroup(uint8 group); void CancelEventGroup(uint8 group);
bool HaveEventList() const { return !m_events.empty(); } bool HasEvents() const { return !m_events.empty(); }
protected: protected:
uint64 m_time{0}; uint64 m_time{0};
-1
View File
@@ -347,7 +347,6 @@ inline wchar_t wcharToLower(wchar_t wchar)
void wstrToUpper(std::wstring& str); void wstrToUpper(std::wstring& str);
void wstrToLower(std::wstring& str); void wstrToLower(std::wstring& str);
void strToLower(std::string& str);
std::wstring GetMainPartOfName(std::wstring const& wname, uint32 declension); std::wstring GetMainPartOfName(std::wstring const& wname, uint32 declension);
@@ -162,7 +162,7 @@ UpdateFetcher::DirectoryStorage UpdateFetcher::ReceiveIncludedDirectories() cons
// data/sql // data/sql
for (auto const& itr : moduleList) for (auto const& itr : moduleList)
{ {
std::string path = _sourceDirectory->generic_string() + "/modules/" + itr + "/data/sql/" + _dbModuleName; // modules/mod-name/sql/world std::string path = _sourceDirectory->generic_string() + "/modules/" + itr + "/data/sql/" + _dbModuleName; // modules/mod-name/data/sql/db-world
Path const p(path); Path const p(path);
if (!is_directory(p)) if (!is_directory(p))
+1 -11
View File
@@ -83,29 +83,19 @@ WorldObject* CreatureAI::GetSummoner() const
inline bool IsValidCombatTarget(Creature* source, Player* target) inline bool IsValidCombatTarget(Creature* source, Player* target)
{ {
if (target->IsGameMaster()) if (target->IsGameMaster())
{
return false; return false;
}
if (!source->IsInWorld() || !target->IsInWorld()) if (!source->IsInWorld() || !target->IsInWorld())
{
return false; return false;
}
if (!source->IsAlive() || !target->IsAlive()) if (!source->IsAlive() || !target->IsAlive())
{
return false; return false;
}
if (!source->InSamePhase(target)) if (!source->InSamePhase(target))
{
return false; return false;
}
if (source->HasUnitState(UNIT_STATE_IN_FLIGHT) || target->HasUnitState(UNIT_STATE_IN_FLIGHT)) if (source->IsInFlight() || target->IsInFlight())
{
return false; return false;
}
return true; return true;
} }
@@ -950,6 +950,9 @@ bool SmartAIMgr::CheckUnusedTargetParams(SmartScriptHolder const& e)
case SMART_TARGET_VEHICLE_PASSENGER: return sizeof(SmartTarget::vehicle); case SMART_TARGET_VEHICLE_PASSENGER: return sizeof(SmartTarget::vehicle);
// case SMART_TARGET_CLOSEST_UNSPAWNED_GAMEOBJECT: return sizeof(SmartTarget::goClosest); // case SMART_TARGET_CLOSEST_UNSPAWNED_GAMEOBJECT: return sizeof(SmartTarget::goClosest);
case SMART_TARGET_PLAYER_WITH_AURA: return sizeof(SmartTarget::playerWithAura); case SMART_TARGET_PLAYER_WITH_AURA: return sizeof(SmartTarget::playerWithAura);
case SMART_TARGET_RANDOM_POINT: return sizeof(SmartTarget::randomPoint);
case SMART_TARGET_SUMMONED_CREATURES: return sizeof(SmartTarget::summonedCreatures);
case SMART_TARGET_INSTANCE_STORAGE: return sizeof(SmartTarget::instanceStorage);
default: default:
LOG_WARN("sql.sql", "SmartAIMgr: entryorguid {} source_type {} id {} action_type {} is using a target {} with no unused params specified in SmartAIMgr::CheckUnusedTargetParams(), please report this.", LOG_WARN("sql.sql", "SmartAIMgr: entryorguid {} source_type {} id {} action_type {} is using a target {} with no unused params specified in SmartAIMgr::CheckUnusedTargetParams(), please report this.",
e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.GetTargetType()); e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.GetTargetType());
@@ -1826,6 +1826,15 @@ bool AchievementMgr::IsCompletedCriteria(AchievementCriteriaEntry const* achieve
// someone on this realm has already completed that achievement // someone on this realm has already completed that achievement
if (sAchievementMgr->IsRealmCompleted(achievement)) if (sAchievementMgr->IsRealmCompleted(achievement))
return false; return false;
// A character may only have 1 race-specific 'Realm First!' achievement
// prevent clever use of the race/faction change service to obtain multiple 'Realm First!' achievements
constexpr std::array<uint32, 9> raceSpecificRealmFirstAchievements { 1405, 1406, 1407, 1408, 1409, 1410, 1411, 1412, 1413 };
bool isRaceSpecific = std::ranges::find(raceSpecificRealmFirstAchievements, achievement->ID) != std::ranges::end(raceSpecificRealmFirstAchievements);
if (isRaceSpecific)
for (uint32 raceAchievementId : raceSpecificRealmFirstAchievements)
if (raceAchievementId != achievement->ID && HasAchieved(raceAchievementId))
return false;
} }
// pussywizard: progress will be deleted after getting the achievement (optimization) // pussywizard: progress will be deleted after getting the achievement (optimization)
-11
View File
@@ -33,17 +33,6 @@ class WorldObject;
struct GameTele; struct GameTele;
enum PlayerChatTag
{
CHAT_TAG_NONE = 0x00,
CHAT_TAG_AFK = 0x01,
CHAT_TAG_DND = 0x02,
CHAT_TAG_GM = 0x04,
CHAT_TAG_COM = 0x08, // Commentator
CHAT_TAG_DEV = 0x10, // Developer
};
typedef uint32 ChatTagFlags;
class AC_GAME_API ChatHandler class AC_GAME_API ChatHandler
{ {
public: public:
+4 -18
View File
@@ -92,27 +92,13 @@ private:
}; };
ThreatMgr* iThreatMgr; ThreatMgr* iThreatMgr;
public: public:
ThreatRefStatusChangeEvent(uint32 pType) : UnitBaseEvent(pType), iFValue(0.f), iThreatMgr(nullptr) ThreatRefStatusChangeEvent(uint32 pType) : UnitBaseEvent(pType), iThreatMgr(nullptr) { iHostileReference = nullptr; }
{
iHostileReference = nullptr;
}
ThreatRefStatusChangeEvent(uint32 pType, HostileReference* pHostileReference) : UnitBaseEvent(pType), iFValue(0.f), iThreatMgr(nullptr) ThreatRefStatusChangeEvent(uint32 pType, HostileReference* pHostileReference) : UnitBaseEvent(pType), iThreatMgr(nullptr) { iHostileReference = pHostileReference; }
{
iHostileReference = pHostileReference;
}
ThreatRefStatusChangeEvent(uint32 pType, HostileReference* pHostileReference, float pValue) : UnitBaseEvent(pType), iThreatMgr(nullptr) ThreatRefStatusChangeEvent(uint32 pType, HostileReference* pHostileReference, float pValue) : UnitBaseEvent(pType), iThreatMgr(nullptr) { iHostileReference = pHostileReference; iFValue = pValue; }
{
iHostileReference = pHostileReference;
iFValue = pValue;
}
ThreatRefStatusChangeEvent(uint32 pType, HostileReference* pHostileReference, bool pValue) : UnitBaseEvent(pType), iThreatMgr(nullptr) ThreatRefStatusChangeEvent(uint32 pType, HostileReference* pHostileReference, bool pValue) : UnitBaseEvent(pType), iThreatMgr(nullptr) { iHostileReference = pHostileReference; iBValue = pValue; }
{
iHostileReference = pHostileReference;
iBValue = pValue;
}
[[nodiscard]] int32 getIValue() const { return iIValue; } [[nodiscard]] int32 getIValue() const { return iIValue; }
@@ -1373,8 +1373,7 @@ void Creature::SaveToDB(uint32 mapid, uint8 spawnMask, uint32 phaseMask)
m_spawnId = sObjectMgr->GenerateCreatureSpawnId(); m_spawnId = sObjectMgr->GenerateCreatureSpawnId();
CreatureData& data = sObjectMgr->NewOrExistCreatureData(m_spawnId); CreatureData& data = sObjectMgr->NewOrExistCreatureData(m_spawnId);
data.spawnId = m_spawnId; data.spawnId = m_spawnId; // mod_playerbots
uint32 displayId = GetNativeDisplayId(); uint32 displayId = GetNativeDisplayId();
uint32 npcflag = GetNpcFlags(); uint32 npcflag = GetNpcFlags();
uint32 unit_flags = GetUnitFlags(); uint32 unit_flags = GetUnitFlags();
@@ -3498,7 +3497,7 @@ bool Creature::IsMovementPreventedByCasting() const
void Creature::SetCannotReachTarget(ObjectGuid const& cannotReach) void Creature::SetCannotReachTarget(ObjectGuid const& cannotReach)
{ {
if (cannotReach == m_cannotReachTarget) if (cannotReach == m_cannotReachTarget)
{ {
return; return;
} }
@@ -365,7 +365,7 @@ typedef std::unordered_map<uint32, EquipmentInfoContainerInternal> EquipmentInfo
struct CreatureData struct CreatureData
{ {
CreatureData() = default; CreatureData() = default;
ObjectGuid::LowType spawnId{0}; ObjectGuid::LowType spawnId{ 0 }; // mod_playerbots
uint32 id1{0}; // entry in creature_template uint32 id1{0}; // entry in creature_template
uint32 id2{0}; // entry in creature_template uint32 id2{0}; // entry in creature_template
uint32 id3{0}; // entry in creature_template uint32 id3{0}; // entry in creature_template
+1 -55
View File
@@ -3294,9 +3294,7 @@ void Player::learnSpell(uint32 spellId, bool temporary /*= false*/, bool learnFr
// Xinef: don't allow to learn active spell once more // Xinef: don't allow to learn active spell once more
if (HasActiveSpell(spellId)) if (HasActiveSpell(spellId))
{ {
#ifndef MOD_PLAYERBOTS
LOG_DEBUG("entities.player", "Player ({}) tries to learn already active spell: {}", GetGUID().ToString(), spellId); LOG_DEBUG("entities.player", "Player ({}) tries to learn already active spell: {}", GetGUID().ToString(), spellId);
#endif
return; return;
} }
@@ -4332,28 +4330,6 @@ void Player::DeleteOldRecoveryItems(uint32 keepDays)
} }
} }
void Player::SetMovement(PlayerMovementType pType)
{
WorldPacket data;
const PackedGuid& guid = GetPackGUID();
switch (pType)
{
case MOVE_WATER_WALK:
data.Initialize(SMSG_MOVE_WATER_WALK, guid.size() + 4);
break;
case MOVE_LAND_WALK:
data.Initialize(SMSG_MOVE_LAND_WALK, guid.size() + 4);
break;
default:
LOG_ERROR("entities.player", "Player::SetMovement: Unsupported move type ({}), data not sent to client.", pType);
return;
}
data << guid;
data << GetSession()->GetOrderCounter(); // movement counter
SendDirectMessage(&data);
GetSession()->IncrementOrderCounter();
}
/* Preconditions: /* Preconditions:
- a resurrectable corpse must not be loaded for the player (only bones) - a resurrectable corpse must not be loaded for the player (only bones)
- the player must be in world - the player must be in world
@@ -4389,7 +4365,6 @@ void Player::BuildPlayerRepop()
} }
GetMap()->AddToMap(corpse); GetMap()->AddToMap(corpse);
SetHealth(1); // convert player body to ghost SetHealth(1); // convert player body to ghost
SetMovement(MOVE_WATER_WALK);
SetWaterWalking(true); SetWaterWalking(true);
if (!IsImmobilizedState()) if (!IsImmobilizedState())
@@ -4430,7 +4405,6 @@ void Player::ResurrectPlayer(float restore_percent, bool applySickness)
SetDynamicFlag(UNIT_DYNFLAG_REFER_A_FRIEND); SetDynamicFlag(UNIT_DYNFLAG_REFER_A_FRIEND);
setDeathState(DeathState::Alive); setDeathState(DeathState::Alive);
SetMovement(MOVE_LAND_WALK);
SendMoveRoot(false); SendMoveRoot(false);
SetWaterWalking(false); SetWaterWalking(false);
m_deathTimer = 0; m_deathTimer = 0;
@@ -9390,11 +9364,7 @@ void Player::Say(std::string_view text, Language language, WorldObject const* /*
{ {
std::string _text(text); std::string _text(text);
if (!sScriptMgr->OnPlayerCanUseChat(this, CHAT_MSG_SAY, language, _text)) if (!sScriptMgr->OnPlayerCanUseChat(this, CHAT_MSG_SAY, language, _text))
{
return; return;
}
sScriptMgr->OnPlayerChat(this, CHAT_MSG_SAY, language, _text);
WorldPacket data; WorldPacket data;
ChatHandler::BuildChatPacket(data, CHAT_MSG_SAY, language, this, this, _text); ChatHandler::BuildChatPacket(data, CHAT_MSG_SAY, language, this, this, _text);
@@ -9416,11 +9386,7 @@ void Player::Yell(std::string_view text, Language language, WorldObject const* /
std::string _text(text); std::string _text(text);
if (!sScriptMgr->OnPlayerCanUseChat(this, CHAT_MSG_YELL, language, _text)) if (!sScriptMgr->OnPlayerCanUseChat(this, CHAT_MSG_YELL, language, _text))
{
return; return;
}
sScriptMgr->OnPlayerChat(this, CHAT_MSG_YELL, language, _text);
WorldPacket data; WorldPacket data;
ChatHandler::BuildChatPacket(data, CHAT_MSG_YELL, language, this, this, _text); ChatHandler::BuildChatPacket(data, CHAT_MSG_YELL, language, this, this, _text);
@@ -9442,11 +9408,7 @@ void Player::TextEmote(std::string_view text, WorldObject const* /*= nullptr*/,
std::string _text(text); std::string _text(text);
if (!sScriptMgr->OnPlayerCanUseChat(this, CHAT_MSG_EMOTE, LANG_UNIVERSAL, _text)) if (!sScriptMgr->OnPlayerCanUseChat(this, CHAT_MSG_EMOTE, LANG_UNIVERSAL, _text))
{
return; return;
}
sScriptMgr->OnPlayerChat(this, CHAT_MSG_EMOTE, LANG_UNIVERSAL, _text);
WorldPacket data; WorldPacket data;
ChatHandler::BuildChatPacket(data, CHAT_MSG_EMOTE, LANG_UNIVERSAL, this, this, _text); ChatHandler::BuildChatPacket(data, CHAT_MSG_EMOTE, LANG_UNIVERSAL, this, this, _text);
@@ -9475,11 +9437,7 @@ void Player::Whisper(std::string_view text, Language language, Player* target, b
std::string _text(text); std::string _text(text);
if (!sScriptMgr->OnPlayerCanUseChat(this, CHAT_MSG_WHISPER, language, _text, target)) if (!sScriptMgr->OnPlayerCanUseChat(this, CHAT_MSG_WHISPER, language, _text, target))
{
return; return;
}
sScriptMgr->OnPlayerChat(this, CHAT_MSG_WHISPER, language, _text, target);
WorldPacket data; WorldPacket data;
ChatHandler::BuildChatPacket(data, CHAT_MSG_WHISPER, language, this, this, _text); ChatHandler::BuildChatPacket(data, CHAT_MSG_WHISPER, language, this, this, _text);
@@ -11686,7 +11644,7 @@ void Player::SendInitialPacketsAfterAddToMap()
GetSession()->IncrementOrderCounter(); GetSession()->IncrementOrderCounter();
} }
if (HasAuraType(SPELL_AURA_WATER_WALK)) if (HasAuraType(SPELL_AURA_WATER_WALK) || HasAura(8326))
{ {
uint32 const counter = GetSession()->GetOrderCounter(); uint32 const counter = GetSession()->GetOrderCounter();
setCompoundState << uint8(2 + GetPackGUID().size() + 4); setCompoundState << uint8(2 + GetPackGUID().size() + 4);
@@ -12096,18 +12054,6 @@ void Player::GetAurasForTarget(Unit* target, bool force /*= false*/)
if (!target || (!force && target->GetVisibleAuras()->empty())) // speedup things if (!target || (!force && target->GetVisibleAuras()->empty())) // speedup things
return; return;
/*! Blizz sends certain movement packets sometimes even before CreateObject
These movement packets are usually found in SMSG_COMPRESSED_MOVES
*/
if (target->HasFeatherFallAura())
target->SendMovementFeatherFall(this);
if (target->HasWaterWalkAura())
target->SendMovementWaterWalking(this);
if (target->HasHoverAura())
target->SendMovementHover(this);
WorldPacket data(SMSG_AURA_UPDATE_ALL); WorldPacket data(SMSG_AURA_UPDATE_ALL);
data<< target->GetPackGUID(); data<< target->GetPackGUID();
+11 -1
View File
@@ -656,7 +656,7 @@ enum PlayerSlots
#define INVENTORY_SLOT_BAG_0 255 #define INVENTORY_SLOT_BAG_0 255
enum EquipmentSlots : uint32 // 19 slots enum EquipmentSlots : uint32 // 19 slots
{ {
EQUIPMENT_SLOT_START = 0, EQUIPMENT_SLOT_START = 0,
EQUIPMENT_SLOT_HEAD = 0, EQUIPMENT_SLOT_HEAD = 0,
@@ -827,6 +827,16 @@ enum EnviromentalDamage
DAMAGE_FALL_TO_VOID = 6 // custom case for fall without durability loss DAMAGE_FALL_TO_VOID = 6 // custom case for fall without durability loss
}; };
enum PlayerChatTag
{
CHAT_TAG_NONE = 0x00,
CHAT_TAG_AFK = 0x01,
CHAT_TAG_DND = 0x02,
CHAT_TAG_GM = 0x04,
CHAT_TAG_COM = 0x08, // Commentator tag. Do not exist in clean client
CHAT_TAG_DEV = 0x10,
};
enum PlayedTimeIndex enum PlayedTimeIndex
{ {
PLAYED_TIME_TOTAL = 0, PLAYED_TIME_TOTAL = 0,
@@ -1463,6 +1463,9 @@ void Player::UpdatePvPState()
if (pvpInfo.IsHostile) // in hostile area if (pvpInfo.IsHostile) // in hostile area
{ {
if (IsInFlight()) // on taxi
return;
if (!IsPvP() || pvpInfo.EndTimer != 0) if (!IsPvP() || pvpInfo.EndTimer != 0)
UpdatePvP(true, true); UpdatePvP(true, true);
} }
+4 -20
View File
@@ -1864,7 +1864,7 @@ void Unit::DealMeleeDamage(CalcDamageInfo* damageInfo, bool durabilityLoss)
auto canTakeMeleeDamage = [&]() auto canTakeMeleeDamage = [&]()
{ {
return victim->IsAlive() && !victim->HasUnitState(UNIT_STATE_IN_FLIGHT) && (!victim->IsCreature() || !victim->ToCreature()->IsEvadingAttacks()); return victim->IsAlive() && !victim->IsInFlight() && (!victim->IsCreature() || !victim->ToCreature()->IsEvadingAttacks());
}; };
if (!canTakeMeleeDamage()) if (!canTakeMeleeDamage())
@@ -1956,10 +1956,11 @@ void Unit::DealMeleeDamage(CalcDamageInfo* damageInfo, bool durabilityLoss)
Probability = 0.65f * victim->GetLevel() + 0.5f; Probability = 0.65f * victim->GetLevel() + 0.5f;
uint32 VictimDefense = victim->GetDefenseSkillValue(); uint32 VictimDefense = victim->GetDefenseSkillValue();
uint32 VictimAuraDefense = -victim->GetTotalAuraModifier(SPELL_AURA_MOD_ATTACKER_MELEE_CRIT_CHANCE) * 25;
uint32 AttackerMeleeSkill = GetUnitMeleeSkill(); uint32 AttackerMeleeSkill = GetUnitMeleeSkill();
// xinef: fix daze mechanics // xinef: fix daze mechanics
Probability -= ((float)VictimDefense - AttackerMeleeSkill) * 0.1428f; Probability -= ((float)VictimDefense + (float)VictimAuraDefense - AttackerMeleeSkill) * 0.1428f;
if (Probability > 40.0f) if (Probability > 40.0f)
Probability = 40.0f; Probability = 40.0f;
@@ -18429,10 +18430,8 @@ void Unit::SetControlled(bool apply, UnitState state, Unit* source /*= nullptr*/
void Unit::SetStunned(bool apply) void Unit::SetStunned(bool apply)
{ {
if (HasUnitState(UNIT_STATE_IN_FLIGHT)) if (IsInFlight())
{
return; return;
}
if (apply) if (apply)
{ {
@@ -21520,18 +21519,3 @@ Player const* Unit::GetClientControlling() const
} }
return nullptr; return nullptr;
} }
void Unit::SetCannotReachTargetUnit(bool cannotReach, bool isChase)
{
if (cannotReach == m_cannotReachTarget)
{
return;
}
m_cannotReachTarget = cannotReach;
}
bool Unit::CanNotReachTarget() const
{
return m_cannotReachTarget;
}
-2
View File
@@ -2051,8 +2051,6 @@ public:
// Debug // Debug
void OutDebugInfo() const; void OutDebugInfo() const;
std::string GetDebugInfo() const override; std::string GetDebugInfo() const override;
void SetCannotReachTargetUnit(bool target, bool isChase);
[[nodiscard]] bool CanNotReachTarget() const;
bool m_cannotReachTarget; bool m_cannotReachTarget;
@@ -45,7 +45,7 @@ enum VehicleFlags
VEHICLE_FLAG_CUSTOM_PITCH = 0x00000040, // If set use pitchMin and pitchMax from DBC, otherwise pitchMin = -pi/2, pitchMax = pi/2 VEHICLE_FLAG_CUSTOM_PITCH = 0x00000040, // If set use pitchMin and pitchMax from DBC, otherwise pitchMin = -pi/2, pitchMax = pi/2
VEHICLE_FLAG_ADJUST_AIM_ANGLE = 0x00000400, // Lua_IsVehicleAimAngleAdjustable VEHICLE_FLAG_ADJUST_AIM_ANGLE = 0x00000400, // Lua_IsVehicleAimAngleAdjustable
VEHICLE_FLAG_ADJUST_AIM_POWER = 0x00000800, // Lua_IsVehicleAimPowerAdjustable VEHICLE_FLAG_ADJUST_AIM_POWER = 0x00000800, // Lua_IsVehicleAimPowerAdjustable
VEHICLE_FLAG_FIXED_POSITION = 0x00200000 // Used for cannons, when they should be rooted VEHICLE_FLAG_FIXED_POSITION = 0x00200000 // Used for cannons, when they should be rooted (mod_playerbots, not sure this is still valid since its only used my playerbot)
}; };
enum VehicleSpells enum VehicleSpells
+4 -2
View File
@@ -527,9 +527,11 @@ float GridTerrainData::getLiquidLevel(float x, float y) const
} }
// Get water state on map // Get water state on map
LiquidData const GridTerrainData::GetLiquidData(float x, float y, float z, float collisionHeight, uint8 ReqLiquidType) const LiquidData const GridTerrainData::GetLiquidData(float x, float y, float z, float collisionHeight, Optional<uint8> ReqLiquidType) const
{ {
LiquidData liquidData; LiquidData liquidData;
liquidData.Status = LIQUID_MAP_NO_WATER;
if (!_loadedLiquidData) if (!_loadedLiquidData)
return liquidData; return liquidData;
@@ -575,7 +577,7 @@ LiquidData const GridTerrainData::GetLiquidData(float x, float y, float z, float
} }
// Check req liquid type mask // Check req liquid type mask
if (type != 0 && (!ReqLiquidType || (ReqLiquidType & type) != 0)) if (type != 0 && (!ReqLiquidType || (*ReqLiquidType & type) != 0))
{ {
// Check water level: // Check water level:
// Check water height map // Check water height map
+2 -2
View File
@@ -186,7 +186,7 @@ struct LoadedHoleData
HolesType holes; HolesType holes;
}; };
enum LiquidStatus enum LiquidStatus : uint32
{ {
LIQUID_MAP_NO_WATER = 0x00000000, LIQUID_MAP_NO_WATER = 0x00000000,
LIQUID_MAP_ABOVE_WATER = 0x00000001, LIQUID_MAP_ABOVE_WATER = 0x00000001,
@@ -249,7 +249,7 @@ public:
inline float getHeight(float x, float y) const { return (this->*_gridGetHeight)(x, y); } inline float getHeight(float x, float y) const { return (this->*_gridGetHeight)(x, y); }
float getMinHeight(float x, float y) const; float getMinHeight(float x, float y) const;
float getLiquidLevel(float x, float y) const; float getLiquidLevel(float x, float y) const;
LiquidData const GetLiquidData(float x, float y, float z, float collisionHeight, uint8 ReqLiquidType) const; LiquidData const GetLiquidData(float x, float y, float z, float collisionHeight, Optional<uint8> ReqLiquidType) const;
}; };
#endif #endif
+1
View File
@@ -262,6 +262,7 @@ public:
void SetGroupMemberFlag(ObjectGuid guid, bool apply, GroupMemberFlags flag); void SetGroupMemberFlag(ObjectGuid guid, bool apply, GroupMemberFlags flag);
void RemoveUniqueGroupMemberFlag(GroupMemberFlags flag); void RemoveUniqueGroupMemberFlag(GroupMemberFlags flag);
//mod_playerbots
ObjectGuid const GetTargetIcon(uint8 id) const { return m_targetIcons[id]; } ObjectGuid const GetTargetIcon(uint8 id) const { return m_targetIcons[id]; }
Difficulty GetDifficulty(bool isRaid) const; Difficulty GetDifficulty(bool isRaid) const;
+215 -213
View File
@@ -44,48 +44,48 @@ std::string _GetGuildEventString(GuildEvents event)
{ {
switch (event) switch (event)
{ {
case GE_PROMOTION: case GE_PROMOTION:
return "Member promotion"; return "Member promotion";
case GE_DEMOTION: case GE_DEMOTION:
return "Member demotion"; return "Member demotion";
case GE_MOTD: case GE_MOTD:
return "Guild MOTD"; return "Guild MOTD";
case GE_JOINED: case GE_JOINED:
return "Member joined"; return "Member joined";
case GE_LEFT: case GE_LEFT:
return "Member left"; return "Member left";
case GE_REMOVED: case GE_REMOVED:
return "Member removed"; return "Member removed";
case GE_LEADER_IS: case GE_LEADER_IS:
return "Leader is"; return "Leader is";
case GE_LEADER_CHANGED: case GE_LEADER_CHANGED:
return "Leader changed"; return "Leader changed";
case GE_DISBANDED: case GE_DISBANDED:
return "Guild disbanded"; return "Guild disbanded";
case GE_TABARDCHANGE: case GE_TABARDCHANGE:
return "Tabard change"; return "Tabard change";
case GE_RANK_UPDATED: case GE_RANK_UPDATED:
return "Rank updated"; return "Rank updated";
case GE_RANK_DELETED: case GE_RANK_DELETED:
return "Rank deleted"; return "Rank deleted";
case GE_SIGNED_ON: case GE_SIGNED_ON:
return "Member signed on"; return "Member signed on";
case GE_SIGNED_OFF: case GE_SIGNED_OFF:
return "Member signed off"; return "Member signed off";
case GE_GUILDBANKBAGSLOTS_CHANGED: case GE_GUILDBANKBAGSLOTS_CHANGED:
return "Bank bag slots changed"; return "Bank bag slots changed";
case GE_BANK_TAB_PURCHASED: case GE_BANK_TAB_PURCHASED:
return "Bank tab purchased"; return "Bank tab purchased";
case GE_BANK_TAB_UPDATED: case GE_BANK_TAB_UPDATED:
return "Bank tab updated"; return "Bank tab updated";
case GE_BANK_MONEY_SET: case GE_BANK_MONEY_SET:
return "Bank money set"; return "Bank money set";
case GE_BANK_TAB_AND_MONEY_UPDATED: case GE_BANK_TAB_AND_MONEY_UPDATED:
return "Bank and money updated"; return "Bank and money updated";
case GE_BANK_TEXT_CHANGED: case GE_BANK_TEXT_CHANGED:
return "Bank tab text changed"; return "Bank tab text changed";
default: default:
break; break;
} }
return "<None>"; return "<None>";
} }
@@ -94,20 +94,20 @@ inline uint32 _GetGuildBankTabPrice(uint8 tabId)
{ {
switch (tabId) switch (tabId)
{ {
case 0: case 0:
return sWorld->getIntConfig(CONFIG_GUILD_BANK_TAB_COST_0); return sWorld->getIntConfig(CONFIG_GUILD_BANK_TAB_COST_0);
case 1: case 1:
return sWorld->getIntConfig(CONFIG_GUILD_BANK_TAB_COST_1); return sWorld->getIntConfig(CONFIG_GUILD_BANK_TAB_COST_1);
case 2: case 2:
return sWorld->getIntConfig(CONFIG_GUILD_BANK_TAB_COST_2); return sWorld->getIntConfig(CONFIG_GUILD_BANK_TAB_COST_2);
case 3: case 3:
return sWorld->getIntConfig(CONFIG_GUILD_BANK_TAB_COST_3); return sWorld->getIntConfig(CONFIG_GUILD_BANK_TAB_COST_3);
case 4: case 4:
return sWorld->getIntConfig(CONFIG_GUILD_BANK_TAB_COST_4); return sWorld->getIntConfig(CONFIG_GUILD_BANK_TAB_COST_4);
case 5: case 5:
return sWorld->getIntConfig(CONFIG_GUILD_BANK_TAB_COST_5); return sWorld->getIntConfig(CONFIG_GUILD_BANK_TAB_COST_5);
default: default:
return 0; return 0;
} }
} }
@@ -134,8 +134,9 @@ void Guild::SendSaveEmblemResult(WorldSession* session, GuildEmblemError errCode
// LogHolder // LogHolder
template <typename Entry> template <typename Entry>
Guild::LogHolder<Entry>::LogHolder() Guild::LogHolder<Entry>::LogHolder()
: m_maxRecords(sWorld->getIntConfig(std::is_same_v<Entry, BankEventLogEntry> ? CONFIG_GUILD_BANK_EVENT_LOG_COUNT : CONFIG_GUILD_EVENT_LOG_COUNT)), m_nextGUID(uint32(GUILD_EVENT_LOG_GUID_UNDEFINED)) : m_maxRecords(sWorld->getIntConfig(std::is_same_v<Entry, BankEventLogEntry> ? CONFIG_GUILD_BANK_EVENT_LOG_COUNT : CONFIG_GUILD_EVENT_LOG_COUNT)), m_nextGUID(uint32(GUILD_EVENT_LOG_GUID_UNDEFINED))
{ } {
}
template <typename Entry> template <typename... Ts> template <typename Entry> template <typename... Ts>
void Guild::LogHolder<Entry>::LoadEvent(Ts&&... args) void Guild::LogHolder<Entry>::LoadEvent(Ts&&... args)
@@ -173,7 +174,8 @@ inline uint32 Guild::LogHolder<Entry>::GetNextGUID()
} }
Guild::LogEntry::LogEntry(uint32 guildId, ObjectGuid::LowType guid) : Guild::LogEntry::LogEntry(uint32 guildId, ObjectGuid::LowType guid) :
m_guildId(guildId), m_guid(guid), m_timestamp(GameTime::GetGameTime().count()) { } m_guildId(guildId), m_guid(guid), m_timestamp(GameTime::GetGameTime().count()) {
}
// EventLogEntry // EventLogEntry
void Guild::EventLogEntry::SaveToDB(CharacterDatabaseTransaction trans) const void Guild::EventLogEntry::SaveToDB(CharacterDatabaseTransaction trans) const
@@ -185,12 +187,12 @@ void Guild::EventLogEntry::SaveToDB(CharacterDatabaseTransaction trans) const
uint8 index = 0; uint8 index = 0;
stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_GUILD_EVENTLOG); stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_GUILD_EVENTLOG);
stmt->SetData( index, m_guildId); stmt->SetData(index, m_guildId);
stmt->SetData(++index, m_guid); stmt->SetData(++index, m_guid);
stmt->SetData (++index, uint8(m_eventType)); stmt->SetData(++index, uint8(m_eventType));
stmt->SetData(++index, m_playerGuid1.GetCounter()); stmt->SetData(++index, m_playerGuid1.GetCounter());
stmt->SetData(++index, m_playerGuid2.GetCounter()); stmt->SetData(++index, m_playerGuid2.GetCounter());
stmt->SetData (++index, m_newRank); stmt->SetData(++index, m_newRank);
stmt->SetData(++index, m_timestamp); stmt->SetData(++index, m_timestamp);
CharacterDatabase.ExecuteOrAppend(trans, stmt); CharacterDatabase.ExecuteOrAppend(trans, stmt);
} }
@@ -215,21 +217,21 @@ void Guild::BankEventLogEntry::SaveToDB(CharacterDatabaseTransaction trans) cons
uint8 index = 0; uint8 index = 0;
CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_GUILD_BANK_EVENTLOG); CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_GUILD_BANK_EVENTLOG);
stmt->SetData( index, m_guildId); stmt->SetData(index, m_guildId);
stmt->SetData(++index, m_guid); stmt->SetData(++index, m_guid);
stmt->SetData (++index, m_bankTabId); stmt->SetData(++index, m_bankTabId);
CharacterDatabase.ExecuteOrAppend(trans, stmt); CharacterDatabase.ExecuteOrAppend(trans, stmt);
index = 0; index = 0;
stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_GUILD_BANK_EVENTLOG); stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_GUILD_BANK_EVENTLOG);
stmt->SetData( index, m_guildId); stmt->SetData(index, m_guildId);
stmt->SetData(++index, m_guid); stmt->SetData(++index, m_guid);
stmt->SetData (++index, m_bankTabId); stmt->SetData(++index, m_bankTabId);
stmt->SetData (++index, uint8(m_eventType)); stmt->SetData(++index, uint8(m_eventType));
stmt->SetData(++index, m_playerGuid.GetCounter()); stmt->SetData(++index, m_playerGuid.GetCounter());
stmt->SetData(++index, m_itemOrMoney); stmt->SetData(++index, m_itemOrMoney);
stmt->SetData(++index, m_itemStackCount); stmt->SetData(++index, m_itemStackCount);
stmt->SetData (++index, m_destTabId); stmt->SetData(++index, m_destTabId);
stmt->SetData(++index, m_timestamp); stmt->SetData(++index, m_timestamp);
CharacterDatabase.ExecuteOrAppend(trans, stmt); CharacterDatabase.ExecuteOrAppend(trans, stmt);
} }
@@ -243,19 +245,19 @@ void Guild::BankEventLogEntry::WritePacket(WorldPackets::Guild::GuildBankLogQuer
switch (m_eventType) switch (m_eventType)
{ {
case GUILD_BANK_LOG_DEPOSIT_ITEM: case GUILD_BANK_LOG_DEPOSIT_ITEM:
case GUILD_BANK_LOG_WITHDRAW_ITEM: case GUILD_BANK_LOG_WITHDRAW_ITEM:
bankLogEntry.ItemID = int32(m_itemOrMoney); bankLogEntry.ItemID = int32(m_itemOrMoney);
bankLogEntry.Count = int32(m_itemStackCount); bankLogEntry.Count = int32(m_itemStackCount);
break; break;
case GUILD_BANK_LOG_MOVE_ITEM: case GUILD_BANK_LOG_MOVE_ITEM:
case GUILD_BANK_LOG_MOVE_ITEM2: case GUILD_BANK_LOG_MOVE_ITEM2:
bankLogEntry.ItemID = int32(m_itemOrMoney); bankLogEntry.ItemID = int32(m_itemOrMoney);
bankLogEntry.Count = int32(m_itemStackCount); bankLogEntry.Count = int32(m_itemStackCount);
bankLogEntry.OtherTab = int8(m_destTabId); bankLogEntry.OtherTab = int8(m_destTabId);
break; break;
default: default:
bankLogEntry.Money = uint32(m_itemOrMoney); bankLogEntry.Money = uint32(m_itemOrMoney);
} }
packet.Entry.push_back(bankLogEntry); packet.Entry.push_back(bankLogEntry);
@@ -264,10 +266,10 @@ void Guild::BankEventLogEntry::WritePacket(WorldPackets::Guild::GuildBankLogQuer
// RankInfo // RankInfo
void Guild::RankInfo::LoadFromDB(Field* fields) void Guild::RankInfo::LoadFromDB(Field* fields)
{ {
m_rankId = fields[1].Get<uint8>(); m_rankId = fields[1].Get<uint8>();
m_name = fields[2].Get<std::string>(); m_name = fields[2].Get<std::string>();
m_rights = fields[3].Get<uint32>(); m_rights = fields[3].Get<uint32>();
m_bankMoneyPerDay = fields[4].Get<uint32>(); m_bankMoneyPerDay = fields[4].Get<uint32>();
if (m_rankId == GR_GUILDMASTER) // Prevent loss of leader rights if (m_rankId == GR_GUILDMASTER) // Prevent loss of leader rights
m_rights |= GR_RIGHT_ALL; m_rights |= GR_RIGHT_ALL;
} }
@@ -276,7 +278,7 @@ void Guild::RankInfo::SaveToDB(CharacterDatabaseTransaction trans) const
{ {
CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_GUILD_RANK); CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_GUILD_RANK);
stmt->SetData(0, m_guildId); stmt->SetData(0, m_guildId);
stmt->SetData (1, m_rankId); stmt->SetData(1, m_rankId);
stmt->SetData(2, m_name); stmt->SetData(2, m_name);
stmt->SetData(3, m_rights); stmt->SetData(3, m_rights);
stmt->SetData(4, m_bankMoneyPerDay); stmt->SetData(4, m_bankMoneyPerDay);
@@ -317,7 +319,7 @@ void Guild::RankInfo::SetName(std::string_view name)
CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_GUILD_RANK_NAME); CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_GUILD_RANK_NAME);
stmt->SetData(0, m_name); stmt->SetData(0, m_name);
stmt->SetData (1, m_rankId); stmt->SetData(1, m_rankId);
stmt->SetData(2, m_guildId); stmt->SetData(2, m_guildId);
CharacterDatabase.Execute(stmt); CharacterDatabase.Execute(stmt);
} }
@@ -334,7 +336,7 @@ void Guild::RankInfo::SetRights(uint32 rights)
CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_GUILD_RANK_RIGHTS); CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_GUILD_RANK_RIGHTS);
stmt->SetData(0, m_rights); stmt->SetData(0, m_rights);
stmt->SetData (1, m_rankId); stmt->SetData(1, m_rankId);
stmt->SetData(2, m_guildId); stmt->SetData(2, m_guildId);
CharacterDatabase.Execute(stmt); CharacterDatabase.Execute(stmt);
} }
@@ -351,7 +353,7 @@ void Guild::RankInfo::SetBankMoneyPerDay(uint32 money)
CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_GUILD_RANK_BANK_MONEY); CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_GUILD_RANK_BANK_MONEY);
stmt->SetData(0, money); stmt->SetData(0, money);
stmt->SetData (1, m_rankId); stmt->SetData(1, m_rankId);
stmt->SetData(2, m_guildId); stmt->SetData(2, m_guildId);
CharacterDatabase.Execute(stmt); CharacterDatabase.Execute(stmt);
} }
@@ -368,9 +370,9 @@ void Guild::RankInfo::SetBankTabSlotsAndRights(GuildBankRightsAndSlots rightsAnd
{ {
CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_GUILD_BANK_RIGHT); CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_GUILD_BANK_RIGHT);
stmt->SetData(0, m_guildId); stmt->SetData(0, m_guildId);
stmt->SetData (1, guildBR.GetTabId()); stmt->SetData(1, guildBR.GetTabId());
stmt->SetData (2, m_rankId); stmt->SetData(2, m_rankId);
stmt->SetData (3, guildBR.GetRights()); stmt->SetData(3, guildBR.GetRights());
stmt->SetData(4, guildBR.GetSlots()); stmt->SetData(4, guildBR.GetSlots());
CharacterDatabase.Execute(stmt); CharacterDatabase.Execute(stmt);
} }
@@ -409,8 +411,8 @@ bool Guild::BankTab::LoadItemFromDB(Field* fields)
CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_NONEXISTENT_GUILD_BANK_ITEM); CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_NONEXISTENT_GUILD_BANK_ITEM);
stmt->SetData(0, m_guildId); stmt->SetData(0, m_guildId);
stmt->SetData (1, m_tabId); stmt->SetData(1, m_tabId);
stmt->SetData (2, slotId); stmt->SetData(2, slotId);
CharacterDatabase.Execute(stmt); CharacterDatabase.Execute(stmt);
delete pItem; delete pItem;
@@ -448,7 +450,7 @@ void Guild::BankTab::SetInfo(std::string_view name, std::string_view icon)
stmt->SetData(0, m_name); stmt->SetData(0, m_name);
stmt->SetData(1, m_icon); stmt->SetData(1, m_icon);
stmt->SetData(2, m_guildId); stmt->SetData(2, m_guildId);
stmt->SetData (3, m_tabId); stmt->SetData(3, m_tabId);
CharacterDatabase.Execute(stmt); CharacterDatabase.Execute(stmt);
} }
@@ -463,7 +465,7 @@ void Guild::BankTab::SetText(std::string_view text)
CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_GUILD_BANK_TAB_TEXT); CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_GUILD_BANK_TAB_TEXT);
stmt->SetData(0, m_text); stmt->SetData(0, m_text);
stmt->SetData(1, m_guildId); stmt->SetData(1, m_guildId);
stmt->SetData (2, m_tabId); stmt->SetData(2, m_tabId);
CharacterDatabase.Execute(stmt); CharacterDatabase.Execute(stmt);
} }
@@ -478,16 +480,16 @@ bool Guild::BankTab::SetItem(CharacterDatabaseTransaction trans, uint8 slotId, I
CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_GUILD_BANK_ITEM); CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_GUILD_BANK_ITEM);
stmt->SetData(0, m_guildId); stmt->SetData(0, m_guildId);
stmt->SetData (1, m_tabId); stmt->SetData(1, m_tabId);
stmt->SetData (2, slotId); stmt->SetData(2, slotId);
CharacterDatabase.ExecuteOrAppend(trans, stmt); CharacterDatabase.ExecuteOrAppend(trans, stmt);
if (item) if (item)
{ {
stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_GUILD_BANK_ITEM); stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_GUILD_BANK_ITEM);
stmt->SetData(0, m_guildId); stmt->SetData(0, m_guildId);
stmt->SetData (1, m_tabId); stmt->SetData(1, m_tabId);
stmt->SetData (2, slotId); stmt->SetData(2, slotId);
stmt->SetData(3, item->GetGUID().GetCounter()); stmt->SetData(3, item->GetGUID().GetCounter());
CharacterDatabase.ExecuteOrAppend(trans, stmt); CharacterDatabase.ExecuteOrAppend(trans, stmt);
@@ -508,7 +510,7 @@ void Guild::BankTab::SendText(Guild const* guild, WorldSession* session) const
if (session) if (session)
{ {
LOG_DEBUG("guild", "MSG_QUERY_GUILD_BANK_TEXT [{}]: Tabid: {}, Text: {}" LOG_DEBUG("guild", "MSG_QUERY_GUILD_BANK_TEXT [{}]: Tabid: {}, Text: {}"
, session->GetPlayerInfo(), m_tabId, m_text); , session->GetPlayerInfo(), m_tabId, m_text);
session->SendPacket(textQuery.Write()); session->SendPacket(textQuery.Write());
} }
else else
@@ -521,21 +523,21 @@ void Guild::BankTab::SendText(Guild const* guild, WorldSession* session) const
// Member // Member
void Guild::Member::SetStats(Player* player) void Guild::Member::SetStats(Player* player)
{ {
m_name = player->GetName(); m_name = player->GetName();
m_level = player->GetLevel(); m_level = player->GetLevel();
m_class = player->getClass(); m_class = player->getClass();
m_gender = player->getGender(); m_gender = player->getGender();
m_zoneId = player->GetZoneId(); m_zoneId = player->GetZoneId();
m_accountId = player->GetSession()->GetAccountId(); m_accountId = player->GetSession()->GetAccountId();
} }
void Guild::Member::SetStats(std::string_view name, uint8 level, uint8 _class, uint8 gender, uint32 zoneId, uint32 accountId) void Guild::Member::SetStats(std::string_view name, uint8 level, uint8 _class, uint8 gender, uint32 zoneId, uint32 accountId)
{ {
m_name = name; m_name = name;
m_level = level; m_level = level;
m_class = _class; m_class = _class;
m_gender = gender; m_gender = gender;
m_zoneId = zoneId; m_zoneId = zoneId;
m_accountId = accountId; m_accountId = accountId;
} }
@@ -574,7 +576,7 @@ void Guild::Member::ChangeRank(uint8 newRank)
player->SetRank(newRank); player->SetRank(newRank);
CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_GUILD_MEMBER_RANK); CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_GUILD_MEMBER_RANK);
stmt->SetData (0, newRank); stmt->SetData(0, newRank);
stmt->SetData(1, m_guid.GetCounter()); stmt->SetData(1, m_guid.GetCounter());
CharacterDatabase.Execute(stmt); CharacterDatabase.Execute(stmt);
} }
@@ -589,7 +591,7 @@ void Guild::Member::SaveToDB(CharacterDatabaseTransaction trans) const
CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_GUILD_MEMBER); CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_GUILD_MEMBER);
stmt->SetData(0, m_guildId); stmt->SetData(0, m_guildId);
stmt->SetData(1, m_guid.GetCounter()); stmt->SetData(1, m_guid.GetCounter());
stmt->SetData (2, m_rankId); stmt->SetData(2, m_rankId);
stmt->SetData(3, m_publicNote); stmt->SetData(3, m_publicNote);
stmt->SetData(4, m_officerNote); stmt->SetData(4, m_officerNote);
CharacterDatabase.ExecuteOrAppend(trans, stmt); CharacterDatabase.ExecuteOrAppend(trans, stmt);
@@ -600,18 +602,18 @@ void Guild::Member::SaveToDB(CharacterDatabaseTransaction trans) const
// In this case member has to be removed from guild. // In this case member has to be removed from guild.
bool Guild::Member::LoadFromDB(Field* fields) bool Guild::Member::LoadFromDB(Field* fields)
{ {
m_publicNote = fields[3].Get<std::string>(); m_publicNote = fields[3].Get<std::string>();
m_officerNote = fields[4].Get<std::string>(); m_officerNote = fields[4].Get<std::string>();
for (uint8 i = 0; i <= GUILD_BANK_MAX_TABS; ++i) for (uint8 i = 0; i <= GUILD_BANK_MAX_TABS; ++i)
m_bankWithdraw[i] = fields[5 + i].Get<uint32>(); m_bankWithdraw[i] = fields[5 + i].Get<uint32>();
SetStats(fields[12].Get<std::string>(), SetStats(fields[12].Get<std::string>(),
fields[13].Get<uint8>(), // characters.level fields[13].Get<uint8>(), // characters.level
fields[14].Get<uint8>(), // characters.class fields[14].Get<uint8>(), // characters.class
fields[15].Get<uint8>(), // characters.gender fields[15].Get<uint8>(), // characters.gender
fields[16].Get<uint16>(), // characters.zone fields[16].Get<uint16>(), // characters.zone
fields[17].Get<uint32>()); // characters.account fields[17].Get<uint32>()); // characters.account
m_logoutTime = fields[18].Get<uint32>(); // characters.logout_time m_logoutTime = fields[18].Get<uint32>(); // characters.logout_time
if (!CheckStats()) if (!CheckStats())
@@ -691,11 +693,11 @@ void EmblemInfo::ReadPacket(WorldPackets::Guild::SaveGuildEmblem& packet)
void EmblemInfo::LoadFromDB(Field* fields) void EmblemInfo::LoadFromDB(Field* fields)
{ {
m_style = fields[3].Get<uint8>(); m_style = fields[3].Get<uint8>();
m_color = fields[4].Get<uint8>(); m_color = fields[4].Get<uint8>();
m_borderStyle = fields[5].Get<uint8>(); m_borderStyle = fields[5].Get<uint8>();
m_borderColor = fields[6].Get<uint8>(); m_borderColor = fields[6].Get<uint8>();
m_backgroundColor = fields[7].Get<uint8>(); m_backgroundColor = fields[7].Get<uint8>();
} }
void EmblemInfo::SaveToDB(uint32 guildId) const void EmblemInfo::SaveToDB(uint32 guildId) const
@@ -747,8 +749,8 @@ void Guild::MoveItemData::LogAction(MoveItemData* pFrom) const
ASSERT(pFrom->GetItem()); ASSERT(pFrom->GetItem());
sScriptMgr->OnGuildItemMove(m_pGuild, m_pPlayer, pFrom->GetItem(), sScriptMgr->OnGuildItemMove(m_pGuild, m_pPlayer, pFrom->GetItem(),
pFrom->IsBank(), pFrom->GetContainer(), pFrom->GetSlotId(), pFrom->IsBank(), pFrom->GetContainer(), pFrom->GetSlotId(),
IsBank(), GetContainer(), GetSlotId()); IsBank(), GetContainer(), GetSlotId());
} }
inline void Guild::MoveItemData::CopySlots(SlotIds& ids) const inline void Guild::MoveItemData::CopySlots(SlotIds& ids) const
@@ -808,7 +810,7 @@ void Guild::PlayerMoveItemData::LogBankEvent(CharacterDatabaseTransaction trans,
ASSERT(pFrom); ASSERT(pFrom);
// Bank -> Char // Bank -> Char
m_pGuild->_LogBankEvent(trans, GUILD_BANK_LOG_WITHDRAW_ITEM, pFrom->GetContainer(), m_pPlayer->GetGUID(), m_pGuild->_LogBankEvent(trans, GUILD_BANK_LOG_WITHDRAW_ITEM, pFrom->GetContainer(), m_pPlayer->GetGUID(),
pFrom->GetItem()->GetEntry(), count); pFrom->GetItem()->GetEntry(), count);
} }
inline InventoryResult Guild::PlayerMoveItemData::CanStore(Item* pItem, bool swap) inline InventoryResult Guild::PlayerMoveItemData::CanStore(Item* pItem, bool swap)
@@ -881,7 +883,7 @@ Item* Guild::BankMoveItemData::StoreItem(CharacterDatabaseTransaction trans, Ite
++itr; ++itr;
LOG_DEBUG("guild", "GUILD STORAGE: StoreItem tab = {}, slot = {}, item = {}, count = {}", LOG_DEBUG("guild", "GUILD STORAGE: StoreItem tab = {}, slot = {}, item = {}, count = {}",
m_container, m_slotId, pItem->GetEntry(), pItem->GetCount()); m_container, m_slotId, pItem->GetEntry(), pItem->GetCount());
pLastItem = _StoreItem(trans, pTab, pItem, pos, itr != m_vec.end()); pLastItem = _StoreItem(trans, pTab, pItem, pos, itr != m_vec.end());
} }
return pLastItem; return pLastItem;
@@ -893,11 +895,11 @@ void Guild::BankMoveItemData::LogBankEvent(CharacterDatabaseTransaction trans, M
if (pFrom->IsBank()) if (pFrom->IsBank())
// Bank -> Bank // Bank -> Bank
m_pGuild->_LogBankEvent(trans, GUILD_BANK_LOG_MOVE_ITEM, pFrom->GetContainer(), m_pPlayer->GetGUID(), m_pGuild->_LogBankEvent(trans, GUILD_BANK_LOG_MOVE_ITEM, pFrom->GetContainer(), m_pPlayer->GetGUID(),
pFrom->GetItem()->GetEntry(), count, m_container); pFrom->GetItem()->GetEntry(), count, m_container);
else else
// Char -> Bank // Char -> Bank
m_pGuild->_LogBankEvent(trans, GUILD_BANK_LOG_DEPOSIT_ITEM, m_container, m_pPlayer->GetGUID(), m_pGuild->_LogBankEvent(trans, GUILD_BANK_LOG_DEPOSIT_ITEM, m_container, m_pPlayer->GetGUID(),
pFrom->GetItem()->GetEntry(), count); pFrom->GetItem()->GetEntry(), count);
} }
void Guild::BankMoveItemData::LogAction(MoveItemData* pFrom) const void Guild::BankMoveItemData::LogAction(MoveItemData* pFrom) const
@@ -984,7 +986,7 @@ void Guild::BankMoveItemData::CanStoreItemInTab(Item* pItem, uint8 skipSlotId, b
InventoryResult Guild::BankMoveItemData::CanStore(Item* pItem, bool swap) InventoryResult Guild::BankMoveItemData::CanStore(Item* pItem, bool swap)
{ {
LOG_DEBUG("guild", "GUILD STORAGE: CanStore() tab = {}, slot = {}, item = {}, count = {}", LOG_DEBUG("guild", "GUILD STORAGE: CanStore() tab = {}, slot = {}, item = {}, count = {}",
m_container, m_slotId, pItem->GetEntry(), pItem->GetCount()); m_container, m_slotId, pItem->GetEntry(), pItem->GetCount());
uint32 count = pItem->GetCount(); uint32 count = pItem->GetCount();
// Soulbound items cannot be moved // Soulbound items cannot be moved
if (pItem->IsSoulBound()) if (pItem->IsSoulBound())
@@ -1031,7 +1033,7 @@ InventoryResult Guild::BankMoveItemData::CanStore(Item* pItem, bool swap)
} }
// Guild // Guild
Guild::Guild(): Guild::Guild() :
m_id(0), m_id(0),
m_createdDate(0), m_createdDate(0),
m_accountsNumber(0), m_accountsNumber(0),
@@ -1065,7 +1067,7 @@ bool Guild::Create(Player* pLeader, std::string_view name)
m_createdDate = GameTime::GetGameTime().count(); m_createdDate = GameTime::GetGameTime().count();
LOG_DEBUG("guild", "GUILD: creating guild [{}] for leader {} ({})", LOG_DEBUG("guild", "GUILD: creating guild [{}] for leader {} ({})",
m_name, pLeader->GetName(), m_leaderGuid.ToString()); m_name, pLeader->GetName(), m_leaderGuid.ToString());
CharacterDatabaseTransaction trans = CharacterDatabase.BeginTransaction(); CharacterDatabaseTransaction trans = CharacterDatabase.BeginTransaction();
@@ -1075,7 +1077,7 @@ bool Guild::Create(Player* pLeader, std::string_view name)
uint8 index = 0; uint8 index = 0;
stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_GUILD); stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_GUILD);
stmt->SetData( index, m_id); stmt->SetData(index, m_id);
stmt->SetData(++index, m_name); stmt->SetData(++index, m_name);
stmt->SetData(++index, m_leaderGuid.GetCounter()); stmt->SetData(++index, m_leaderGuid.GetCounter());
stmt->SetData(++index, m_info); stmt->SetData(++index, m_info);
@@ -1161,15 +1163,15 @@ void Guild::UpdateMemberData(Player* player, uint8 dataid, uint32 value)
{ {
switch (dataid) switch (dataid)
{ {
case GUILD_MEMBER_DATA_ZONEID: case GUILD_MEMBER_DATA_ZONEID:
member->SetZoneID(value); member->SetZoneID(value);
break; break;
case GUILD_MEMBER_DATA_LEVEL: case GUILD_MEMBER_DATA_LEVEL:
member->SetLevel(value); member->SetLevel(value);
break; break;
default: default:
LOG_ERROR("guild", "Guild::UpdateMemberData: Called with incorrect DATAID {} (value {})", dataid, value); LOG_ERROR("guild", "Guild::UpdateMemberData: Called with incorrect DATAID {} (value {})", dataid, value);
return; return;
} }
//HandleRoster(); //HandleRoster();
} }
@@ -1207,7 +1209,7 @@ void Guild::HandleRoster(WorldSession* session)
roster.RankData.reserve(m_ranks.size()); roster.RankData.reserve(m_ranks.size());
for (RankInfo const& rank : m_ranks) for (RankInfo const& rank : m_ranks)
{ {
WorldPackets::Guild::GuildRankData& rankData = roster.RankData.emplace_back(); WorldPackets::Guild::GuildRankData& rankData = roster.RankData.emplace_back();
rankData.Flags = rank.GetRights(); rankData.Flags = rank.GetRights();
rankData.WithdrawGoldLimit = rank.GetBankMoneyPerDay(); rankData.WithdrawGoldLimit = rank.GetBankMoneyPerDay();
@@ -1362,7 +1364,7 @@ void Guild::HandleSetBankTabInfo(WorldSession* session, uint8 tabId, std::string
if (!tab) if (!tab)
{ {
LOG_ERROR("guild", "Guild::HandleSetBankTabInfo: Player {} trying to change bank tab info from unexisting tab {}.", LOG_ERROR("guild", "Guild::HandleSetBankTabInfo: Player {} trying to change bank tab info from unexisting tab {}.",
session->GetPlayerInfo(), tabId); session->GetPlayerInfo(), tabId);
return; return;
} }
@@ -1931,14 +1933,14 @@ void Guild::SendLoginInfo(WorldSession* session)
// Loading methods // Loading methods
bool Guild::LoadFromDB(Field* fields) bool Guild::LoadFromDB(Field* fields)
{ {
m_id = fields[0].Get<uint32>(); m_id = fields[0].Get<uint32>();
m_name = fields[1].Get<std::string>(); m_name = fields[1].Get<std::string>();
m_leaderGuid = ObjectGuid::Create<HighGuid::Player>(fields[2].Get<uint32>()); m_leaderGuid = ObjectGuid::Create<HighGuid::Player>(fields[2].Get<uint32>());
m_emblemInfo.LoadFromDB(fields); m_emblemInfo.LoadFromDB(fields);
m_info = fields[8].Get<std::string>(); m_info = fields[8].Get<std::string>();
m_motd = fields[9].Get<std::string>(); m_motd = fields[9].Get<std::string>();
m_createdDate = time_t(fields[10].Get<uint32>()); m_createdDate = time_t(fields[10].Get<uint32>());
m_bankMoney = fields[11].Get<uint64>(); m_bankMoney = fields[11].Get<uint64>();
uint8 purchasedTabs = uint8(fields[12].Get<uint64>()); uint8 purchasedTabs = uint8(fields[12].Get<uint64>());
if (purchasedTabs > GUILD_BANK_MAX_TABS) if (purchasedTabs > GUILD_BANK_MAX_TABS)
@@ -1997,13 +1999,13 @@ bool Guild::LoadEventLogFromDB(Field* fields)
if (m_eventLog.CanInsert()) if (m_eventLog.CanInsert())
{ {
m_eventLog.LoadEvent( m_eventLog.LoadEvent(
m_id, // guild id m_id, // guild id
fields[1].Get<uint32>(), // guid fields[1].Get<uint32>(), // guid
time_t(fields[6].Get<uint32>()), // timestamp time_t(fields[6].Get<uint32>()), // timestamp
GuildEventLogTypes(fields[2].Get<uint8>()), // event type GuildEventLogTypes(fields[2].Get<uint8>()), // event type
ObjectGuid::Create<HighGuid::Player>(fields[3].Get<uint32>()), // player guid 1 ObjectGuid::Create<HighGuid::Player>(fields[3].Get<uint32>()), // player guid 1
ObjectGuid::Create<HighGuid::Player>(fields[4].Get<uint32>()), // player guid 2 ObjectGuid::Create<HighGuid::Player>(fields[4].Get<uint32>()), // player guid 2
fields[5].Get<uint8>()); // rank fields[5].Get<uint8>()); // rank
return true; return true;
} }
return false; return false;
@@ -2035,15 +2037,15 @@ bool Guild::LoadBankEventLogFromDB(Field* fields)
return false; return false;
} }
bankLog.LoadEvent( bankLog.LoadEvent(
m_id, // guild id m_id, // guild id
guid, // guid guid, // guid
time_t(fields[8].Get<uint32>()), // timestamp time_t(fields[8].Get<uint32>()), // timestamp
dbTabId, // tab id dbTabId, // tab id
eventType, // event type eventType, // event type
ObjectGuid::Create<HighGuid::Player>(fields[4].Get<uint32>()), // player guid ObjectGuid::Create<HighGuid::Player>(fields[4].Get<uint32>()), // player guid
fields[5].Get<uint32>(), // item or money fields[5].Get<uint32>(), // item or money
fields[6].Get<uint16>(), // itam stack count fields[6].Get<uint16>(), // itam stack count
fields[7].Get<uint8>()); // dest tab id fields[7].Get<uint8>()); // dest tab id
} }
} }
return true; return true;
@@ -2064,7 +2066,7 @@ bool Guild::LoadBankItemFromDB(Field* fields)
if (tabId >= _GetPurchasedTabsSize()) if (tabId >= _GetPurchasedTabsSize())
{ {
LOG_ERROR("guild", "Invalid tab for item (GUID: {}, id: #{}) in guild bank, skipped.", LOG_ERROR("guild", "Invalid tab for item (GUID: {}, id: #{}) in guild bank, skipped.",
fields[14].Get<uint32>(), fields[15].Get<uint32>()); fields[14].Get<uint32>(), fields[15].Get<uint32>());
return false; return false;
} }
return m_bankTabs[tabId].LoadItemFromDB(fields); return m_bankTabs[tabId].LoadItemFromDB(fields);
@@ -2383,7 +2385,7 @@ bool Guild::ChangeMemberRank(ObjectGuid guid, uint8 newRank)
void Guild::SwapItems(Player* player, uint8 tabId, uint8 slotId, uint8 destTabId, uint8 destSlotId, uint32 splitedAmount) void Guild::SwapItems(Player* player, uint8 tabId, uint8 slotId, uint8 destTabId, uint8 destSlotId, uint32 splitedAmount)
{ {
if (tabId >= _GetPurchasedTabsSize() || slotId >= GUILD_BANK_MAX_SLOTS || if (tabId >= _GetPurchasedTabsSize() || slotId >= GUILD_BANK_MAX_SLOTS ||
destTabId >= _GetPurchasedTabsSize() || destSlotId >= GUILD_BANK_MAX_SLOTS) destTabId >= _GetPurchasedTabsSize() || destSlotId >= GUILD_BANK_MAX_SLOTS)
return; return;
if (tabId == destTabId && slotId == destSlotId) if (tabId == destTabId && slotId == destSlotId)
@@ -2427,12 +2429,12 @@ void Guild::_CreateNewBankTab()
CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_GUILD_BANK_TAB); CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_GUILD_BANK_TAB);
stmt->SetData(0, m_id); stmt->SetData(0, m_id);
stmt->SetData (1, tabId); stmt->SetData(1, tabId);
trans->Append(stmt); trans->Append(stmt);
stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_GUILD_BANK_TAB); stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_GUILD_BANK_TAB);
stmt->SetData(0, m_id); stmt->SetData(0, m_id);
stmt->SetData (1, tabId); stmt->SetData(1, tabId);
trans->Append(stmt); trans->Append(stmt);
++tabId; ++tabId;
@@ -2452,10 +2454,10 @@ void Guild::_CreateDefaultGuildRanks(LocaleConstant loc)
stmt->SetData(0, m_id); stmt->SetData(0, m_id);
CharacterDatabase.Execute(stmt); CharacterDatabase.Execute(stmt);
_CreateRank(sObjectMgr->GetAcoreString(LANG_GUILD_MASTER, loc), GR_RIGHT_ALL); _CreateRank(sObjectMgr->GetAcoreString(LANG_GUILD_MASTER, loc), GR_RIGHT_ALL);
_CreateRank(sObjectMgr->GetAcoreString(LANG_GUILD_OFFICER, loc), GR_RIGHT_ALL); _CreateRank(sObjectMgr->GetAcoreString(LANG_GUILD_OFFICER, loc), GR_RIGHT_ALL);
_CreateRank(sObjectMgr->GetAcoreString(LANG_GUILD_VETERAN, loc), GR_RIGHT_GCHATLISTEN | GR_RIGHT_GCHATSPEAK); _CreateRank(sObjectMgr->GetAcoreString(LANG_GUILD_VETERAN, loc), GR_RIGHT_GCHATLISTEN | GR_RIGHT_GCHATSPEAK);
_CreateRank(sObjectMgr->GetAcoreString(LANG_GUILD_MEMBER, loc), GR_RIGHT_GCHATLISTEN | GR_RIGHT_GCHATSPEAK); _CreateRank(sObjectMgr->GetAcoreString(LANG_GUILD_MEMBER, loc), GR_RIGHT_GCHATLISTEN | GR_RIGHT_GCHATSPEAK);
_CreateRank(sObjectMgr->GetAcoreString(LANG_GUILD_INITIATE, loc), GR_RIGHT_GCHATLISTEN | GR_RIGHT_GCHATSPEAK); _CreateRank(sObjectMgr->GetAcoreString(LANG_GUILD_INITIATE, loc), GR_RIGHT_GCHATLISTEN | GR_RIGHT_GCHATSPEAK);
} }
@@ -2626,7 +2628,7 @@ inline void Guild::_UpdateMemberWithdrawSlots(CharacterDatabaseTransaction trans
{ {
uint8 rankId = member->GetRankId(); uint8 rankId = member->GetRankId();
if (rankId != GR_GUILDMASTER if (rankId != GR_GUILDMASTER
&& member->GetBankWithdrawValue(tabId) < _GetRankBankTabSlotsPerDay(rankId, tabId)) && member->GetBankWithdrawValue(tabId) < _GetRankBankTabSlotsPerDay(rankId, tabId))
member->UpdateBankWithdrawValue(trans, tabId, 1); member->UpdateBankWithdrawValue(trans, tabId, 1);
} }
} }
@@ -2850,7 +2852,7 @@ void Guild::_SendBankContentUpdate(uint8 tabId, SlotIds slots) const
} }
void Guild::_BroadcastEvent(GuildEvents guildEvent, ObjectGuid guid, void Guild::_BroadcastEvent(GuildEvents guildEvent, ObjectGuid guid,
Optional<std::string_view> param1 /*= {}*/, Optional<std::string_view> param2 /*= {}*/, Optional<std::string_view> param3 /*= {}*/) const Optional<std::string_view> param1 /*= {}*/, Optional<std::string_view> param2 /*= {}*/, Optional<std::string_view> param3 /*= {}*/) const
{ {
WorldPackets::Guild::GuildEvent event; WorldPackets::Guild::GuildEvent event;
event.Type = guildEvent; event.Type = guildEvent;
@@ -2873,7 +2875,7 @@ void Guild::_BroadcastEvent(GuildEvents guildEvent, ObjectGuid guid,
LOG_DEBUG("guild", "SMSG_GUILD_EVENT [Broadcast] Event: {}", guildEvent); LOG_DEBUG("guild", "SMSG_GUILD_EVENT [Broadcast] Event: {}", guildEvent);
} }
void Guild::_SendBankList(WorldSession* session /* = nullptr*/, uint8 tabId /*= 0*/, bool sendAllSlots /*= false*/, SlotIds *slots /*= nullptr*/) const void Guild::_SendBankList(WorldSession* session /* = nullptr*/, uint8 tabId /*= 0*/, bool sendAllSlots /*= false*/, SlotIds* slots /*= nullptr*/) const
{ {
if (!sScriptMgr->CanGuildSendBankList(this, session, tabId, sendAllSlots)) if (!sScriptMgr->CanGuildSendBankList(this, session, tabId, sendAllSlots))
return; return;
@@ -2899,47 +2901,47 @@ void Guild::_SendBankList(WorldSession* session /* = nullptr*/, uint8 tabId /*=
if (BankTab const* tab = GetBankTab(tabId)) if (BankTab const* tab = GetBankTab(tabId))
{ {
auto fillItems = [&](auto begin, auto end, bool skipEmpty) auto fillItems = [&](auto begin, auto end, bool skipEmpty)
{
for (auto itr = begin; itr != end; ++itr)
{ {
if (Item* tabItem = tab->GetItem(*itr)) for (auto itr = begin; itr != end; ++itr)
{ {
WorldPackets::Guild::GuildBankItemInfo itemInfo; if (Item* tabItem = tab->GetItem(*itr))
itemInfo.Slot = *itr;
itemInfo.ItemID = tabItem->GetEntry();
itemInfo.Count = int32(tabItem->GetCount());
itemInfo.Charges = int32(std::abs(tabItem->GetSpellCharges()));
itemInfo.EnchantmentID = int32(tabItem->GetEnchantmentId(PERM_ENCHANTMENT_SLOT));
itemInfo.Flags = tabItem->GetInt32Value(ITEM_FIELD_FLAGS);
itemInfo.RandomPropertiesID = tabItem->GetItemRandomPropertyId();
itemInfo.RandomPropertiesSeed = int32(tabItem->GetItemSuffixFactor());
for (uint32 socketSlot = 0; socketSlot < MAX_GEM_SOCKETS; ++socketSlot)
{ {
if (uint32 enchId = tabItem->GetEnchantmentId(EnchantmentSlot(SOCK_ENCHANTMENT_SLOT + socketSlot))) WorldPackets::Guild::GuildBankItemInfo itemInfo;
itemInfo.Slot = *itr;
itemInfo.ItemID = tabItem->GetEntry();
itemInfo.Count = int32(tabItem->GetCount());
itemInfo.Charges = int32(std::abs(tabItem->GetSpellCharges()));
itemInfo.EnchantmentID = int32(tabItem->GetEnchantmentId(PERM_ENCHANTMENT_SLOT));
itemInfo.Flags = tabItem->GetInt32Value(ITEM_FIELD_FLAGS);
itemInfo.RandomPropertiesID = tabItem->GetItemRandomPropertyId();
itemInfo.RandomPropertiesSeed = int32(tabItem->GetItemSuffixFactor());
for (uint32 socketSlot = 0; socketSlot < MAX_GEM_SOCKETS; ++socketSlot)
{ {
WorldPackets::Guild::GuildBankSocketEnchant gem; if (uint32 enchId = tabItem->GetEnchantmentId(EnchantmentSlot(SOCK_ENCHANTMENT_SLOT + socketSlot)))
gem.SocketIndex = socketSlot; {
gem.SocketEnchantID = int32(enchId); WorldPackets::Guild::GuildBankSocketEnchant gem;
itemInfo.SocketEnchant.push_back(gem); gem.SocketIndex = socketSlot;
gem.SocketEnchantID = int32(enchId);
itemInfo.SocketEnchant.push_back(gem);
}
} }
packet.ItemInfo.push_back(itemInfo);
} }
else if (!skipEmpty)
{
WorldPackets::Guild::GuildBankItemInfo itemInfo;
packet.ItemInfo.push_back(itemInfo); itemInfo.Slot = *itr;
itemInfo.ItemID = 0;
packet.ItemInfo.push_back(itemInfo);
}
} }
else if (!skipEmpty)
{
WorldPackets::Guild::GuildBankItemInfo itemInfo;
itemInfo.Slot = *itr; };
itemInfo.ItemID = 0;
packet.ItemInfo.push_back(itemInfo);
}
}
};
if (sendAllSlots) if (sendAllSlots)
fillItems(boost::make_counting_iterator(uint8(0)), boost::make_counting_iterator(uint8(GUILD_BANK_MAX_SLOTS)), true); fillItems(boost::make_counting_iterator(uint8(0)), boost::make_counting_iterator(uint8(GUILD_BANK_MAX_SLOTS)), true);
@@ -2954,7 +2956,7 @@ void Guild::_SendBankList(WorldSession* session /* = nullptr*/, uint8 tabId /*=
session->SendPacket(packet.Write()); session->SendPacket(packet.Write());
LOG_DEBUG("guild", "SMSG_GUILD_BANK_LIST [{}]: TabId: {}, FullSlots: {}, slots: {}", LOG_DEBUG("guild", "SMSG_GUILD_BANK_LIST [{}]: TabId: {}, FullSlots: {}, slots: {}",
session->GetPlayerInfo(), tabId, sendAllSlots, packet.WithdrawalsRemaining); session->GetPlayerInfo(), tabId, sendAllSlots, packet.WithdrawalsRemaining);
} }
else else
{ {
@@ -2974,7 +2976,7 @@ void Guild::_SendBankList(WorldSession* session /* = nullptr*/, uint8 tabId /*=
packet.SetWithdrawalsRemaining(_GetMemberRemainingSlots(member, tabId)); packet.SetWithdrawalsRemaining(_GetMemberRemainingSlots(member, tabId));
player->SendDirectMessage(packet.GetRawPacket()); player->SendDirectMessage(packet.GetRawPacket());
LOG_DEBUG("guild", "SMSG_GUILD_BANK_LIST [{}]: TabId: {}, FullSlots: {}, slots: {}" LOG_DEBUG("guild", "SMSG_GUILD_BANK_LIST [{}]: TabId: {}, FullSlots: {}, slots: {}"
, player->GetName(), tabId, sendAllSlots, packet.WithdrawalsRemaining); , player->GetName(), tabId, sendAllSlots, packet.WithdrawalsRemaining);
} }
} }
} }
+164 -155
View File
@@ -39,16 +39,16 @@ namespace WorldPackets
enum GuildMisc enum GuildMisc
{ {
GUILD_BANK_MAX_TABS = 6, // send by client for money log also GUILD_BANK_MAX_TABS = 6, // send by client for money log also
GUILD_BANK_MAX_SLOTS = 98, GUILD_BANK_MAX_SLOTS = 98,
GUILD_BANK_MONEY_LOGS_TAB = 100, // used for money log in DB GUILD_BANK_MONEY_LOGS_TAB = 100, // used for money log in DB
GUILD_RANKS_MIN_COUNT = 5, GUILD_RANKS_MIN_COUNT = 5,
GUILD_RANKS_MAX_COUNT = 10, GUILD_RANKS_MAX_COUNT = 10,
GUILD_RANK_NONE = 0xFF, GUILD_RANK_NONE = 0xFF,
GUILD_WITHDRAW_MONEY_UNLIMITED = 0xFFFFFFFF, GUILD_WITHDRAW_MONEY_UNLIMITED = 0xFFFFFFFF,
GUILD_WITHDRAW_SLOT_UNLIMITED = 0xFFFFFFFF, GUILD_WITHDRAW_SLOT_UNLIMITED = 0xFFFFFFFF,
GUILD_EVENT_LOG_GUID_UNDEFINED = 0xFFFFFFFF, GUILD_EVENT_LOG_GUID_UNDEFINED = 0xFFFFFFFF,
TAB_UNDEFINED = 0xFF, TAB_UNDEFINED = 0xFF,
}; };
constexpr uint64 GUILD_BANK_MONEY_LIMIT = UI64LIT(0x7FFFFFFFFFFFF); constexpr uint64 GUILD_BANK_MONEY_LIMIT = UI64LIT(0x7FFFFFFFFFFFF);
@@ -62,176 +62,176 @@ enum GuildMemberData
enum GuildDefaultRanks enum GuildDefaultRanks
{ {
// These ranks can be modified, but they cannot be deleted // These ranks can be modified, but they cannot be deleted
GR_GUILDMASTER = 0, GR_GUILDMASTER = 0,
GR_OFFICER = 1, GR_OFFICER = 1,
GR_VETERAN = 2, GR_VETERAN = 2,
GR_MEMBER = 3, GR_MEMBER = 3,
GR_INITIATE = 4 GR_INITIATE = 4
// When promoting member server does: rank-- // When promoting member server does: rank--
// When demoting member server does: rank++ // When demoting member server does: rank++
}; };
enum GuildRankRights enum GuildRankRights
{ {
GR_RIGHT_EMPTY = 0x00000040, GR_RIGHT_EMPTY = 0x00000040,
GR_RIGHT_GCHATLISTEN = GR_RIGHT_EMPTY | 0x00000001, GR_RIGHT_GCHATLISTEN = GR_RIGHT_EMPTY | 0x00000001,
GR_RIGHT_GCHATSPEAK = GR_RIGHT_EMPTY | 0x00000002, GR_RIGHT_GCHATSPEAK = GR_RIGHT_EMPTY | 0x00000002,
GR_RIGHT_OFFCHATLISTEN = GR_RIGHT_EMPTY | 0x00000004, GR_RIGHT_OFFCHATLISTEN = GR_RIGHT_EMPTY | 0x00000004,
GR_RIGHT_OFFCHATSPEAK = GR_RIGHT_EMPTY | 0x00000008, GR_RIGHT_OFFCHATSPEAK = GR_RIGHT_EMPTY | 0x00000008,
GR_RIGHT_INVITE = GR_RIGHT_EMPTY | 0x00000010, GR_RIGHT_INVITE = GR_RIGHT_EMPTY | 0x00000010,
GR_RIGHT_REMOVE = GR_RIGHT_EMPTY | 0x00000020, GR_RIGHT_REMOVE = GR_RIGHT_EMPTY | 0x00000020,
GR_RIGHT_PROMOTE = GR_RIGHT_EMPTY | 0x00000080, GR_RIGHT_PROMOTE = GR_RIGHT_EMPTY | 0x00000080,
GR_RIGHT_DEMOTE = GR_RIGHT_EMPTY | 0x00000100, GR_RIGHT_DEMOTE = GR_RIGHT_EMPTY | 0x00000100,
GR_RIGHT_SETMOTD = GR_RIGHT_EMPTY | 0x00001000, GR_RIGHT_SETMOTD = GR_RIGHT_EMPTY | 0x00001000,
GR_RIGHT_EPNOTE = GR_RIGHT_EMPTY | 0x00002000, GR_RIGHT_EPNOTE = GR_RIGHT_EMPTY | 0x00002000,
GR_RIGHT_VIEWOFFNOTE = GR_RIGHT_EMPTY | 0x00004000, GR_RIGHT_VIEWOFFNOTE = GR_RIGHT_EMPTY | 0x00004000,
GR_RIGHT_EOFFNOTE = GR_RIGHT_EMPTY | 0x00008000, GR_RIGHT_EOFFNOTE = GR_RIGHT_EMPTY | 0x00008000,
GR_RIGHT_MODIFY_GUILD_INFO = GR_RIGHT_EMPTY | 0x00010000, GR_RIGHT_MODIFY_GUILD_INFO = GR_RIGHT_EMPTY | 0x00010000,
GR_RIGHT_WITHDRAW_GOLD_LOCK = 0x00020000, // remove money withdraw capacity GR_RIGHT_WITHDRAW_GOLD_LOCK = 0x00020000, // remove money withdraw capacity
GR_RIGHT_WITHDRAW_REPAIR = 0x00040000, // withdraw for repair GR_RIGHT_WITHDRAW_REPAIR = 0x00040000, // withdraw for repair
GR_RIGHT_WITHDRAW_GOLD = 0x00080000, // withdraw gold GR_RIGHT_WITHDRAW_GOLD = 0x00080000, // withdraw gold
GR_RIGHT_CREATE_GUILD_EVENT = 0x00100000, // wotlk GR_RIGHT_CREATE_GUILD_EVENT = 0x00100000, // wotlk
GR_RIGHT_ALL = 0x001DF1FF GR_RIGHT_ALL = 0x001DF1FF
}; };
enum GuildCommandType enum GuildCommandType
{ {
GUILD_COMMAND_CREATE = 0, GUILD_COMMAND_CREATE = 0,
GUILD_COMMAND_INVITE = 1, GUILD_COMMAND_INVITE = 1,
GUILD_COMMAND_QUIT = 3, GUILD_COMMAND_QUIT = 3,
GUILD_COMMAND_ROSTER = 5, GUILD_COMMAND_ROSTER = 5,
GUILD_COMMAND_PROMOTE = 6, GUILD_COMMAND_PROMOTE = 6,
GUILD_COMMAND_DEMOTE = 7, GUILD_COMMAND_DEMOTE = 7,
GUILD_COMMAND_REMOVE = 8, GUILD_COMMAND_REMOVE = 8,
GUILD_COMMAND_CHANGE_LEADER = 10, GUILD_COMMAND_CHANGE_LEADER = 10,
GUILD_COMMAND_EDIT_MOTD = 11, GUILD_COMMAND_EDIT_MOTD = 11,
GUILD_COMMAND_GUILD_CHAT = 13, GUILD_COMMAND_GUILD_CHAT = 13,
GUILD_COMMAND_FOUNDER = 14, GUILD_COMMAND_FOUNDER = 14,
GUILD_COMMAND_CHANGE_RANK = 16, GUILD_COMMAND_CHANGE_RANK = 16,
GUILD_COMMAND_PUBLIC_NOTE = 19, GUILD_COMMAND_PUBLIC_NOTE = 19,
GUILD_COMMAND_VIEW_TAB = 21, GUILD_COMMAND_VIEW_TAB = 21,
GUILD_COMMAND_MOVE_ITEM = 22, GUILD_COMMAND_MOVE_ITEM = 22,
GUILD_COMMAND_REPAIR = 25, GUILD_COMMAND_REPAIR = 25,
}; };
enum GuildCommandError enum GuildCommandError
{ {
ERR_GUILD_COMMAND_SUCCESS = 0, ERR_GUILD_COMMAND_SUCCESS = 0,
ERR_GUILD_INTERNAL = 1, ERR_GUILD_INTERNAL = 1,
ERR_ALREADY_IN_GUILD = 2, ERR_ALREADY_IN_GUILD = 2,
ERR_ALREADY_IN_GUILD_S = 3, ERR_ALREADY_IN_GUILD_S = 3,
ERR_INVITED_TO_GUILD = 4, ERR_INVITED_TO_GUILD = 4,
ERR_ALREADY_INVITED_TO_GUILD_S = 5, ERR_ALREADY_INVITED_TO_GUILD_S = 5,
ERR_GUILD_NAME_INVALID = 6, ERR_GUILD_NAME_INVALID = 6,
ERR_GUILD_NAME_EXISTS_S = 7, ERR_GUILD_NAME_EXISTS_S = 7,
ERR_GUILD_LEADER_LEAVE = 8, ERR_GUILD_LEADER_LEAVE = 8,
ERR_GUILD_PERMISSIONS = 8, ERR_GUILD_PERMISSIONS = 8,
ERR_GUILD_PLAYER_NOT_IN_GUILD = 9, ERR_GUILD_PLAYER_NOT_IN_GUILD = 9,
ERR_GUILD_PLAYER_NOT_IN_GUILD_S = 10, ERR_GUILD_PLAYER_NOT_IN_GUILD_S = 10,
ERR_GUILD_PLAYER_NOT_FOUND_S = 11, ERR_GUILD_PLAYER_NOT_FOUND_S = 11,
ERR_GUILD_NOT_ALLIED = 12, ERR_GUILD_NOT_ALLIED = 12,
ERR_GUILD_RANK_TOO_HIGH_S = 13, ERR_GUILD_RANK_TOO_HIGH_S = 13,
ERR_GUILD_RANK_TOO_LOW_S = 14, ERR_GUILD_RANK_TOO_LOW_S = 14,
ERR_GUILD_RANKS_LOCKED = 17, ERR_GUILD_RANKS_LOCKED = 17,
ERR_GUILD_RANK_IN_USE = 18, ERR_GUILD_RANK_IN_USE = 18,
ERR_GUILD_IGNORING_YOU_S = 19, ERR_GUILD_IGNORING_YOU_S = 19,
ERR_GUILD_UNK1 = 20, // Forces roster update ERR_GUILD_UNK1 = 20, // Forces roster update
ERR_GUILD_WITHDRAW_LIMIT = 25, ERR_GUILD_WITHDRAW_LIMIT = 25,
ERR_GUILD_NOT_ENOUGH_MONEY = 26, ERR_GUILD_NOT_ENOUGH_MONEY = 26,
ERR_GUILD_BANK_FULL = 28, ERR_GUILD_BANK_FULL = 28,
ERR_GUILD_ITEM_NOT_FOUND = 29, ERR_GUILD_ITEM_NOT_FOUND = 29,
}; };
enum GuildEvents enum GuildEvents
{ {
GE_PROMOTION = 0, GE_PROMOTION = 0,
GE_DEMOTION = 1, GE_DEMOTION = 1,
GE_MOTD = 2, GE_MOTD = 2,
GE_JOINED = 3, GE_JOINED = 3,
GE_LEFT = 4, GE_LEFT = 4,
GE_REMOVED = 5, GE_REMOVED = 5,
GE_LEADER_IS = 6, GE_LEADER_IS = 6,
GE_LEADER_CHANGED = 7, GE_LEADER_CHANGED = 7,
GE_DISBANDED = 8, GE_DISBANDED = 8,
GE_TABARDCHANGE = 9, GE_TABARDCHANGE = 9,
GE_RANK_UPDATED = 10, GE_RANK_UPDATED = 10,
GE_RANK_DELETED = 11, GE_RANK_DELETED = 11,
GE_SIGNED_ON = 12, GE_SIGNED_ON = 12,
GE_SIGNED_OFF = 13, GE_SIGNED_OFF = 13,
GE_GUILDBANKBAGSLOTS_CHANGED = 14, /// @todo: Sent when items are moved in gbank - all players with bank open will send tab query GE_GUILDBANKBAGSLOTS_CHANGED = 14, /// @todo: Sent when items are moved in gbank - all players with bank open will send tab query
GE_BANK_TAB_PURCHASED = 15, GE_BANK_TAB_PURCHASED = 15,
GE_BANK_TAB_UPDATED = 16, GE_BANK_TAB_UPDATED = 16,
GE_BANK_MONEY_SET = 17, GE_BANK_MONEY_SET = 17,
GE_BANK_TAB_AND_MONEY_UPDATED = 18, GE_BANK_TAB_AND_MONEY_UPDATED = 18,
GE_BANK_TEXT_CHANGED = 19, GE_BANK_TEXT_CHANGED = 19,
}; };
enum PetitionTurns enum PetitionTurns
{ {
PETITION_TURN_OK = 0, PETITION_TURN_OK = 0,
PETITION_TURN_ALREADY_IN_GUILD = 2, PETITION_TURN_ALREADY_IN_GUILD = 2,
PETITION_TURN_NEED_MORE_SIGNATURES = 4 PETITION_TURN_NEED_MORE_SIGNATURES = 4
}; };
enum PetitionSigns enum PetitionSigns
{ {
PETITION_SIGN_OK = 0, PETITION_SIGN_OK = 0,
PETITION_SIGN_ALREADY_SIGNED = 1, PETITION_SIGN_ALREADY_SIGNED = 1,
PETITION_SIGN_ALREADY_IN_GUILD = 2, PETITION_SIGN_ALREADY_IN_GUILD = 2,
PETITION_SIGN_CANT_SIGN_OWN = 3, PETITION_SIGN_CANT_SIGN_OWN = 3,
PETITION_SIGN_NOT_SERVER = 4 PETITION_SIGN_NOT_SERVER = 4
}; };
enum GuildBankRights enum GuildBankRights
{ {
GUILD_BANK_RIGHT_VIEW_TAB = 0x01, GUILD_BANK_RIGHT_VIEW_TAB = 0x01,
GUILD_BANK_RIGHT_PUT_ITEM = 0x02, GUILD_BANK_RIGHT_PUT_ITEM = 0x02,
GUILD_BANK_RIGHT_UPDATE_TEXT = 0x04, GUILD_BANK_RIGHT_UPDATE_TEXT = 0x04,
GUILD_BANK_RIGHT_DEPOSIT_ITEM = GUILD_BANK_RIGHT_VIEW_TAB | GUILD_BANK_RIGHT_PUT_ITEM, GUILD_BANK_RIGHT_DEPOSIT_ITEM = GUILD_BANK_RIGHT_VIEW_TAB | GUILD_BANK_RIGHT_PUT_ITEM,
GUILD_BANK_RIGHT_FULL = 0xFF GUILD_BANK_RIGHT_FULL = 0xFF
}; };
enum GuildBankEventLogTypes enum GuildBankEventLogTypes
{ {
GUILD_BANK_LOG_DEPOSIT_ITEM = 1, GUILD_BANK_LOG_DEPOSIT_ITEM = 1,
GUILD_BANK_LOG_WITHDRAW_ITEM = 2, GUILD_BANK_LOG_WITHDRAW_ITEM = 2,
GUILD_BANK_LOG_MOVE_ITEM = 3, GUILD_BANK_LOG_MOVE_ITEM = 3,
GUILD_BANK_LOG_DEPOSIT_MONEY = 4, GUILD_BANK_LOG_DEPOSIT_MONEY = 4,
GUILD_BANK_LOG_WITHDRAW_MONEY = 5, GUILD_BANK_LOG_WITHDRAW_MONEY = 5,
GUILD_BANK_LOG_REPAIR_MONEY = 6, GUILD_BANK_LOG_REPAIR_MONEY = 6,
GUILD_BANK_LOG_MOVE_ITEM2 = 7, GUILD_BANK_LOG_MOVE_ITEM2 = 7,
GUILD_BANK_LOG_UNK1 = 8, GUILD_BANK_LOG_UNK1 = 8,
GUILD_BANK_LOG_BUY_SLOT = 9 GUILD_BANK_LOG_BUY_SLOT = 9
}; };
enum GuildEventLogTypes enum GuildEventLogTypes
{ {
GUILD_EVENT_LOG_INVITE_PLAYER = 1, GUILD_EVENT_LOG_INVITE_PLAYER = 1,
GUILD_EVENT_LOG_JOIN_GUILD = 2, GUILD_EVENT_LOG_JOIN_GUILD = 2,
GUILD_EVENT_LOG_PROMOTE_PLAYER = 3, GUILD_EVENT_LOG_PROMOTE_PLAYER = 3,
GUILD_EVENT_LOG_DEMOTE_PLAYER = 4, GUILD_EVENT_LOG_DEMOTE_PLAYER = 4,
GUILD_EVENT_LOG_UNINVITE_PLAYER = 5, GUILD_EVENT_LOG_UNINVITE_PLAYER = 5,
GUILD_EVENT_LOG_LEAVE_GUILD = 6 GUILD_EVENT_LOG_LEAVE_GUILD = 6
}; };
enum GuildEmblemError enum GuildEmblemError
{ {
ERR_GUILDEMBLEM_SUCCESS = 0, ERR_GUILDEMBLEM_SUCCESS = 0,
ERR_GUILDEMBLEM_INVALID_TABARD_COLORS = 1, ERR_GUILDEMBLEM_INVALID_TABARD_COLORS = 1,
ERR_GUILDEMBLEM_NOGUILD = 2, ERR_GUILDEMBLEM_NOGUILD = 2,
ERR_GUILDEMBLEM_NOTGUILDMASTER = 3, ERR_GUILDEMBLEM_NOTGUILDMASTER = 3,
ERR_GUILDEMBLEM_NOTENOUGHMONEY = 4, ERR_GUILDEMBLEM_NOTENOUGHMONEY = 4,
ERR_GUILDEMBLEM_INVALIDVENDOR = 5 ERR_GUILDEMBLEM_INVALIDVENDOR = 5
}; };
enum GuildMemberFlags enum GuildMemberFlags
{ {
GUILDMEMBER_STATUS_NONE = 0x0000, GUILDMEMBER_STATUS_NONE = 0x0000,
GUILDMEMBER_STATUS_ONLINE = 0x0001, GUILDMEMBER_STATUS_ONLINE = 0x0001,
GUILDMEMBER_STATUS_AFK = 0x0002, GUILDMEMBER_STATUS_AFK = 0x0002,
GUILDMEMBER_STATUS_DND = 0x0004, GUILDMEMBER_STATUS_DND = 0x0004,
GUILDMEMBER_STATUS_MOBILE = 0x0008, // remote chat from mobile app GUILDMEMBER_STATUS_MOBILE = 0x0008, // remote chat from mobile app
}; };
// Emblem info // Emblem info
@@ -239,7 +239,8 @@ class EmblemInfo
{ {
public: public:
EmblemInfo(uint32 /*style*/ = 0, uint32 /*color*/ = 0, uint32 /*borderStyle*/ = 0, uint32 /*borderColor*/ = 0, uint32 /*backgroundColor*/ = 0) : EmblemInfo(uint32 /*style*/ = 0, uint32 /*color*/ = 0, uint32 /*borderStyle*/ = 0, uint32 /*borderColor*/ = 0, uint32 /*backgroundColor*/ = 0) :
m_style(0), m_color(0), m_borderStyle(0), m_borderColor(0), m_backgroundColor(0) { } m_style(0), m_color(0), m_borderStyle(0), m_borderColor(0), m_backgroundColor(0) {
}
void LoadFromDB(Field* fields); void LoadFromDB(Field* fields);
void SaveToDB(uint32 guildId) const; void SaveToDB(uint32 guildId) const;
@@ -263,9 +264,9 @@ private:
class GuildBankRightsAndSlots class GuildBankRightsAndSlots
{ {
public: public:
GuildBankRightsAndSlots() : tabId(TAB_UNDEFINED), rights(0), slots(0) { } GuildBankRightsAndSlots() : tabId(TAB_UNDEFINED), rights(0), slots(0) {}
GuildBankRightsAndSlots(uint8 _tabId) : tabId(_tabId), rights(0), slots(0) { } GuildBankRightsAndSlots(uint8 _tabId) : tabId(_tabId), rights(0), slots(0) {}
GuildBankRightsAndSlots(uint8 _tabId, uint8 _rights, uint32 _slots) : tabId(_tabId), rights(_rights), slots(_slots) { } GuildBankRightsAndSlots(uint8 _tabId, uint8 _rights, uint32 _slots) : tabId(_tabId), rights(_rights), slots(_slots) {}
void SetGuildMasterValues() void SetGuildMasterValues()
{ {
@@ -296,7 +297,7 @@ public: // pussywizard: public class Member
class Member class Member
{ {
public: public:
Member(uint32 guildId, ObjectGuid guid, uint8 rankId): Member(uint32 guildId, ObjectGuid guid, uint8 rankId) :
m_guildId(guildId), m_guildId(guildId),
m_guid(guid), m_guid(guid),
m_zoneId(0), m_zoneId(0),
@@ -404,8 +405,8 @@ private:
{ {
public: public:
LogEntry(uint32 guildId, ObjectGuid::LowType guid); LogEntry(uint32 guildId, ObjectGuid::LowType guid);
LogEntry(uint32 guildId, ObjectGuid::LowType guid, time_t timestamp) : m_guildId(guildId), m_guid(guid), m_timestamp(timestamp) { } LogEntry(uint32 guildId, ObjectGuid::LowType guid, time_t timestamp) : m_guildId(guildId), m_guid(guid), m_timestamp(timestamp) {}
virtual ~LogEntry() { } virtual ~LogEntry() {}
ObjectGuid::LowType GetGUID() const { return m_guid; } ObjectGuid::LowType GetGUID() const { return m_guid; }
uint64 GetTimestamp() const { return m_timestamp; } uint64 GetTimestamp() const { return m_timestamp; }
@@ -423,12 +424,14 @@ private:
{ {
public: public:
EventLogEntry(uint32 guildId, ObjectGuid::LowType guid, GuildEventLogTypes eventType, ObjectGuid playerGuid1, ObjectGuid playerGuid2, uint8 newRank) : EventLogEntry(uint32 guildId, ObjectGuid::LowType guid, GuildEventLogTypes eventType, ObjectGuid playerGuid1, ObjectGuid playerGuid2, uint8 newRank) :
LogEntry(guildId, guid), m_eventType(eventType), m_playerGuid1(playerGuid1), m_playerGuid2(playerGuid2), m_newRank(newRank) { } LogEntry(guildId, guid), m_eventType(eventType), m_playerGuid1(playerGuid1), m_playerGuid2(playerGuid2), m_newRank(newRank) {
}
EventLogEntry(uint32 guildId, ObjectGuid::LowType guid, time_t timestamp, GuildEventLogTypes eventType, ObjectGuid playerGuid1, ObjectGuid playerGuid2, uint8 newRank) : EventLogEntry(uint32 guildId, ObjectGuid::LowType guid, time_t timestamp, GuildEventLogTypes eventType, ObjectGuid playerGuid1, ObjectGuid playerGuid2, uint8 newRank) :
LogEntry(guildId, guid, timestamp), m_eventType(eventType), m_playerGuid1(playerGuid1), m_playerGuid2(playerGuid2), m_newRank(newRank) { } LogEntry(guildId, guid, timestamp), m_eventType(eventType), m_playerGuid1(playerGuid1), m_playerGuid2(playerGuid2), m_newRank(newRank) {
}
~EventLogEntry() override { } ~EventLogEntry() override {}
void SaveToDB(CharacterDatabaseTransaction trans) const override; void SaveToDB(CharacterDatabaseTransaction trans) const override;
void WritePacket(WorldPackets::Guild::GuildEventLogQueryResults& packet) const; void WritePacket(WorldPackets::Guild::GuildEventLogQueryResults& packet) const;
@@ -459,13 +462,15 @@ private:
BankEventLogEntry(uint32 guildId, ObjectGuid::LowType guid, GuildBankEventLogTypes eventType, uint8 tabId, ObjectGuid playerGuid, uint32 itemOrMoney, uint16 itemStackCount, uint8 destTabId) : BankEventLogEntry(uint32 guildId, ObjectGuid::LowType guid, GuildBankEventLogTypes eventType, uint8 tabId, ObjectGuid playerGuid, uint32 itemOrMoney, uint16 itemStackCount, uint8 destTabId) :
LogEntry(guildId, guid), m_eventType(eventType), m_bankTabId(tabId), m_playerGuid(playerGuid), LogEntry(guildId, guid), m_eventType(eventType), m_bankTabId(tabId), m_playerGuid(playerGuid),
m_itemOrMoney(itemOrMoney), m_itemStackCount(itemStackCount), m_destTabId(destTabId) { } m_itemOrMoney(itemOrMoney), m_itemStackCount(itemStackCount), m_destTabId(destTabId) {
}
BankEventLogEntry(uint32 guildId, ObjectGuid::LowType guid, time_t timestamp, uint8 tabId, GuildBankEventLogTypes eventType, ObjectGuid playerGuid, uint32 itemOrMoney, uint16 itemStackCount, uint8 destTabId) : BankEventLogEntry(uint32 guildId, ObjectGuid::LowType guid, time_t timestamp, uint8 tabId, GuildBankEventLogTypes eventType, ObjectGuid playerGuid, uint32 itemOrMoney, uint16 itemStackCount, uint8 destTabId) :
LogEntry(guildId, guid, timestamp), m_eventType(eventType), m_bankTabId(tabId), m_playerGuid(playerGuid), LogEntry(guildId, guid, timestamp), m_eventType(eventType), m_bankTabId(tabId), m_playerGuid(playerGuid),
m_itemOrMoney(itemOrMoney), m_itemStackCount(itemStackCount), m_destTabId(destTabId) { } m_itemOrMoney(itemOrMoney), m_itemStackCount(itemStackCount), m_destTabId(destTabId) {
}
~BankEventLogEntry() override { } ~BankEventLogEntry() override {}
void SaveToDB(CharacterDatabaseTransaction trans) const override; void SaveToDB(CharacterDatabaseTransaction trans) const override;
void WritePacket(WorldPackets::Guild::GuildBankLogQueryResults& packet) const; void WritePacket(WorldPackets::Guild::GuildBankLogQueryResults& packet) const;
@@ -510,11 +515,12 @@ private:
class RankInfo class RankInfo
{ {
public: public:
RankInfo(): m_guildId(0), m_rankId(GUILD_RANK_NONE), m_rights(GR_RIGHT_EMPTY), m_bankMoneyPerDay(0) { } RankInfo() : m_guildId(0), m_rankId(GUILD_RANK_NONE), m_rights(GR_RIGHT_EMPTY), m_bankMoneyPerDay(0) {}
RankInfo(uint32 guildId) : m_guildId(guildId), m_rankId(GUILD_RANK_NONE), m_rights(GR_RIGHT_EMPTY), m_bankMoneyPerDay(0) { } RankInfo(uint32 guildId) : m_guildId(guildId), m_rankId(GUILD_RANK_NONE), m_rights(GR_RIGHT_EMPTY), m_bankMoneyPerDay(0) {}
RankInfo(uint32 guildId, uint8 rankId, std::string_view name, uint32 rights, uint32 money) : RankInfo(uint32 guildId, uint8 rankId, std::string_view name, uint32 rights, uint32 money) :
m_guildId(guildId), m_rankId(rankId), m_name(name), m_rights(rights), m_guildId(guildId), m_rankId(rankId), m_name(name), m_rights(rights),
m_bankMoneyPerDay(rankId != GR_GUILDMASTER ? money : GUILD_WITHDRAW_MONEY_UNLIMITED) { } m_bankMoneyPerDay(rankId != GR_GUILDMASTER ? money : GUILD_WITHDRAW_MONEY_UNLIMITED) {
}
void LoadFromDB(Field* fields); void LoadFromDB(Field* fields);
void SaveToDB(CharacterDatabaseTransaction trans) const; void SaveToDB(CharacterDatabaseTransaction trans) const;
@@ -573,7 +579,7 @@ private:
std::string const& GetIcon() const { return m_icon; } std::string const& GetIcon() const { return m_icon; }
std::string const& GetText() const { return m_text; } std::string const& GetText() const { return m_text; }
inline Item* GetItem(uint8 slotId) const { return slotId < GUILD_BANK_MAX_SLOTS ? m_items[slotId] : nullptr; } inline Item* GetItem(uint8 slotId) const { return slotId < GUILD_BANK_MAX_SLOTS ? m_items[slotId] : nullptr; }
bool SetItem(CharacterDatabaseTransaction trans, uint8 slotId, Item* pItem); bool SetItem(CharacterDatabaseTransaction trans, uint8 slotId, Item* pItem);
private: private:
@@ -591,8 +597,9 @@ private:
{ {
public: public:
MoveItemData(Guild* guild, Player* player, uint8 container, uint8 slotId) : m_pGuild(guild), m_pPlayer(player), MoveItemData(Guild* guild, Player* player, uint8 container, uint8 slotId) : m_pGuild(guild), m_pPlayer(player),
m_container(container), m_slotId(slotId), m_pItem(nullptr), m_pClonedItem(nullptr) { } m_container(container), m_slotId(slotId), m_pItem(nullptr), m_pClonedItem(nullptr) {
virtual ~MoveItemData() { } }
virtual ~MoveItemData() {}
virtual bool IsBank() const = 0; virtual bool IsBank() const = 0;
// Initializes item pointer. Returns true, if item exists, false otherwise. // Initializes item pointer. Returns true, if item exists, false otherwise.
@@ -638,7 +645,8 @@ private:
{ {
public: public:
PlayerMoveItemData(Guild* guild, Player* player, uint8 container, uint8 slotId) : PlayerMoveItemData(Guild* guild, Player* player, uint8 container, uint8 slotId) :
MoveItemData(guild, player, container, slotId) { } MoveItemData(guild, player, container, slotId) {
}
bool IsBank() const override { return false; } bool IsBank() const override { return false; }
bool InitItem() override; bool InitItem() override;
@@ -653,7 +661,8 @@ private:
{ {
public: public:
BankMoveItemData(Guild* guild, Player* player, uint8 container, uint8 slotId) : BankMoveItemData(Guild* guild, Player* player, uint8 container, uint8 slotId) :
MoveItemData(guild, player, container, slotId) { } MoveItemData(guild, player, container, slotId) {
}
bool IsBank() const override { return true; } bool IsBank() const override { return true; }
bool InitItem() override; bool InitItem() override;
+258 -259
View File
@@ -264,15 +264,15 @@ void WorldSession::HandleCharCreateOpcode(WorldPacket& recvData)
std::shared_ptr<CharacterCreateInfo> createInfo = std::make_shared<CharacterCreateInfo>(); std::shared_ptr<CharacterCreateInfo> createInfo = std::make_shared<CharacterCreateInfo>();
recvData >> createInfo->Name recvData >> createInfo->Name
>> createInfo->Race >> createInfo->Race
>> createInfo->Class >> createInfo->Class
>> createInfo->Gender >> createInfo->Gender
>> createInfo->Skin >> createInfo->Skin
>> createInfo->Face >> createInfo->Face
>> createInfo->HairStyle >> createInfo->HairStyle
>> createInfo->HairColor >> createInfo->HairColor
>> createInfo->FacialHair >> createInfo->FacialHair
>> createInfo->OutfitId; >> createInfo->OutfitId;
if (AccountMgr::IsPlayerAccount(GetSecurity())) if (AccountMgr::IsPlayerAccount(GetSecurity()))
{ {
@@ -371,233 +371,233 @@ void WorldSession::HandleCharCreateOpcode(WorldPacket& recvData)
stmt->SetData(0, createInfo->Name); stmt->SetData(0, createInfo->Name);
_queryProcessor.AddCallback(CharacterDatabase.AsyncQuery(stmt) _queryProcessor.AddCallback(CharacterDatabase.AsyncQuery(stmt)
.WithChainingPreparedCallback([this](QueryCallback& queryCallback, PreparedQueryResult result) .WithChainingPreparedCallback([this](QueryCallback& queryCallback, PreparedQueryResult result)
{
if (result)
{
SendCharCreate(CHAR_CREATE_NAME_IN_USE);
return;
}
LoginDatabasePreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_SUM_REALM_CHARACTERS);
stmt->SetData(0, GetAccountId());
queryCallback.SetNextQuery(LoginDatabase.AsyncQuery(stmt));
})
.WithChainingPreparedCallback([this](QueryCallback& queryCallback, PreparedQueryResult result)
{
uint64 acctCharCount = 0;
if (result)
{
Field* fields = result->Fetch();
acctCharCount = uint64(fields[0].Get<double>());
}
if (acctCharCount >= static_cast<uint64>(sWorld->getIntConfig(CONFIG_CHARACTERS_PER_ACCOUNT)))
{
SendCharCreate(CHAR_CREATE_ACCOUNT_LIMIT);
return;
}
CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_SUM_CHARS);
stmt->SetData(0, GetAccountId());
queryCallback.SetNextQuery(CharacterDatabase.AsyncQuery(stmt));
})
.WithChainingPreparedCallback([this, createInfo](QueryCallback& queryCallback, PreparedQueryResult result)
{
if (result)
{
Field* fields = result->Fetch();
createInfo->CharCount = uint8(fields[0].Get<uint64>()); // SQL's COUNT() returns uint64 but it will always be less than uint8.Max
if (createInfo->CharCount >= sWorld->getIntConfig(CONFIG_CHARACTERS_PER_REALM))
{ {
SendCharCreate(CHAR_CREATE_SERVER_LIMIT); if (result)
return;
}
}
bool allowTwoSideAccounts = !sWorld->IsPvPRealm() || sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_ACCOUNTS) || !AccountMgr::IsPlayerAccount(GetSecurity());
uint32 skipCinematics = sWorld->getIntConfig(CONFIG_SKIP_CINEMATICS);
std::function<void(PreparedQueryResult)> finalizeCharacterCreation = [this, createInfo](PreparedQueryResult result)
{
if (!sScriptMgr->CanAccountCreateCharacter(GetAccountId(), createInfo->Race, createInfo->Class))
{
SendCharCreate(CHAR_CREATE_DISABLED);
return;
}
bool haveSameRace = false;
uint32 heroicReqLevel = sWorld->getIntConfig(CONFIG_CHARACTER_CREATING_MIN_LEVEL_FOR_HEROIC_CHARACTER);
bool hasHeroicReqLevel = (heroicReqLevel == 0);
bool allowTwoSideAccounts = !sWorld->IsPvPRealm() || sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_ACCOUNTS) || !AccountMgr::IsPlayerAccount(GetSecurity());
uint32 skipCinematics = sWorld->getIntConfig(CONFIG_SKIP_CINEMATICS);
bool checkDeathKnightReqs = AccountMgr::IsPlayerAccount(GetSecurity()) && createInfo->Class == CLASS_DEATH_KNIGHT;
if (result)
{
TeamId teamId = Player::TeamIdForRace(createInfo->Race);
uint32 freeDeathKnightSlots = sWorld->getIntConfig(CONFIG_HEROIC_CHARACTERS_PER_REALM);
Field* field = result->Fetch();
uint8 accRace = field[1].Get<uint8>();
if (checkDeathKnightReqs)
{ {
uint8 accClass = field[2].Get<uint8>(); SendCharCreate(CHAR_CREATE_NAME_IN_USE);
if (accClass == CLASS_DEATH_KNIGHT) return;
{
if (freeDeathKnightSlots > 0)
--freeDeathKnightSlots;
if (freeDeathKnightSlots == 0)
{
SendCharCreate(CHAR_CREATE_UNIQUE_CLASS_LIMIT);
return;
}
}
if (!hasHeroicReqLevel)
{
uint8 accLevel = field[0].Get<uint8>();
if (accLevel >= heroicReqLevel)
hasHeroicReqLevel = true;
}
} }
// need to check team only for first character LoginDatabasePreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_SUM_REALM_CHARACTERS);
/// @todo what to if account already has characters of both races? stmt->SetData(0, GetAccountId());
if (!allowTwoSideAccounts) queryCallback.SetNextQuery(LoginDatabase.AsyncQuery(stmt));
})
.WithChainingPreparedCallback([this](QueryCallback& queryCallback, PreparedQueryResult result)
{
uint64 acctCharCount = 0;
if (result)
{ {
uint32 accTeam = 0; Field* fields = result->Fetch();
if (accRace > 0) acctCharCount = uint64(fields[0].Get<double>());
accTeam = Player::TeamIdForRace(accRace); }
if (accTeam != teamId) if (acctCharCount >= static_cast<uint64>(sWorld->getIntConfig(CONFIG_CHARACTERS_PER_ACCOUNT)))
{
SendCharCreate(CHAR_CREATE_ACCOUNT_LIMIT);
return;
}
CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_SUM_CHARS);
stmt->SetData(0, GetAccountId());
queryCallback.SetNextQuery(CharacterDatabase.AsyncQuery(stmt));
})
.WithChainingPreparedCallback([this, createInfo](QueryCallback& queryCallback, PreparedQueryResult result)
{
if (result)
{
Field* fields = result->Fetch();
createInfo->CharCount = uint8(fields[0].Get<uint64>()); // SQL's COUNT() returns uint64 but it will always be less than uint8.Max
if (createInfo->CharCount >= sWorld->getIntConfig(CONFIG_CHARACTERS_PER_REALM))
{ {
SendCharCreate(CHAR_CREATE_PVP_TEAMS_VIOLATION); SendCharCreate(CHAR_CREATE_SERVER_LIMIT);
return; return;
} }
} }
// search same race for cinematic or same class if need bool allowTwoSideAccounts = !sWorld->IsPvPRealm() || sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_ACCOUNTS) || !AccountMgr::IsPlayerAccount(GetSecurity());
/// @todo check if cinematic already shown? (already logged in?; cinematic field) uint32 skipCinematics = sWorld->getIntConfig(CONFIG_SKIP_CINEMATICS);
while ((skipCinematics == 1 && !haveSameRace) || createInfo->Class == CLASS_DEATH_KNIGHT)
{
if (!result->NextRow())
break;
field = result->Fetch(); std::function<void(PreparedQueryResult)> finalizeCharacterCreation = [this, createInfo](PreparedQueryResult result)
accRace = field[1].Get<uint8>();
if (!haveSameRace)
haveSameRace = createInfo->Race == accRace;
if (checkDeathKnightReqs)
{ {
uint8 acc_class = field[2].Get<uint8>(); if (!sScriptMgr->CanAccountCreateCharacter(GetAccountId(), createInfo->Race, createInfo->Class))
if (acc_class == CLASS_DEATH_KNIGHT)
{ {
if (freeDeathKnightSlots > 0) SendCharCreate(CHAR_CREATE_DISABLED);
--freeDeathKnightSlots; return;
}
bool haveSameRace = false;
uint32 heroicReqLevel = sWorld->getIntConfig(CONFIG_CHARACTER_CREATING_MIN_LEVEL_FOR_HEROIC_CHARACTER);
bool hasHeroicReqLevel = (heroicReqLevel == 0);
bool allowTwoSideAccounts = !sWorld->IsPvPRealm() || sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_ACCOUNTS) || !AccountMgr::IsPlayerAccount(GetSecurity());
uint32 skipCinematics = sWorld->getIntConfig(CONFIG_SKIP_CINEMATICS);
bool checkDeathKnightReqs = AccountMgr::IsPlayerAccount(GetSecurity()) && createInfo->Class == CLASS_DEATH_KNIGHT;
if (freeDeathKnightSlots == 0) if (result)
{
TeamId teamId = Player::TeamIdForRace(createInfo->Race);
uint32 freeDeathKnightSlots = sWorld->getIntConfig(CONFIG_HEROIC_CHARACTERS_PER_REALM);
Field* field = result->Fetch();
uint8 accRace = field[1].Get<uint8>();
if (checkDeathKnightReqs)
{ {
SendCharCreate(CHAR_CREATE_UNIQUE_CLASS_LIMIT); uint8 accClass = field[2].Get<uint8>();
return; if (accClass == CLASS_DEATH_KNIGHT)
{
if (freeDeathKnightSlots > 0)
--freeDeathKnightSlots;
if (freeDeathKnightSlots == 0)
{
SendCharCreate(CHAR_CREATE_UNIQUE_CLASS_LIMIT);
return;
}
}
if (!hasHeroicReqLevel)
{
uint8 accLevel = field[0].Get<uint8>();
if (accLevel >= heroicReqLevel)
hasHeroicReqLevel = true;
}
}
// need to check team only for first character
/// @todo what to if account already has characters of both races?
if (!allowTwoSideAccounts)
{
uint32 accTeam = 0;
if (accRace > 0)
accTeam = Player::TeamIdForRace(accRace);
if (accTeam != teamId)
{
SendCharCreate(CHAR_CREATE_PVP_TEAMS_VIOLATION);
return;
}
}
// search same race for cinematic or same class if need
/// @todo check if cinematic already shown? (already logged in?; cinematic field)
while ((skipCinematics == 1 && !haveSameRace) || createInfo->Class == CLASS_DEATH_KNIGHT)
{
if (!result->NextRow())
break;
field = result->Fetch();
accRace = field[1].Get<uint8>();
if (!haveSameRace)
haveSameRace = createInfo->Race == accRace;
if (checkDeathKnightReqs)
{
uint8 acc_class = field[2].Get<uint8>();
if (acc_class == CLASS_DEATH_KNIGHT)
{
if (freeDeathKnightSlots > 0)
--freeDeathKnightSlots;
if (freeDeathKnightSlots == 0)
{
SendCharCreate(CHAR_CREATE_UNIQUE_CLASS_LIMIT);
return;
}
}
if (!hasHeroicReqLevel)
{
uint8 acc_level = field[0].Get<uint8>();
if (acc_level >= heroicReqLevel)
hasHeroicReqLevel = true;
}
}
} }
} }
if (!hasHeroicReqLevel) if (checkDeathKnightReqs && !hasHeroicReqLevel)
{ {
uint8 acc_level = field[0].Get<uint8>(); SendCharCreate(CHAR_CREATE_LEVEL_REQUIREMENT);
if (acc_level >= heroicReqLevel) return;
hasHeroicReqLevel = true;
} }
}
}
}
if (checkDeathKnightReqs && !hasHeroicReqLevel) // Check name uniqueness in the same step as saving to database
{ if (sCharacterCache->GetCharacterGuidByName(createInfo->Name))
SendCharCreate(CHAR_CREATE_LEVEL_REQUIREMENT); {
return; SendCharCreate(CHAR_CREATE_NAME_IN_USE);
} return;
}
// Check name uniqueness in the same step as saving to database std::shared_ptr<Player> newChar(new Player(this), [](Player* ptr)
if (sCharacterCache->GetCharacterGuidByName(createInfo->Name)) {
{ // Only when player is created correctly do clean
SendCharCreate(CHAR_CREATE_NAME_IN_USE); if (ptr->HasAtLoginFlag(AT_LOGIN_FIRST))
return; {
} ptr->CleanupsBeforeDelete();
}
delete ptr;
});
std::shared_ptr<Player> newChar(new Player(this), [](Player* ptr) newChar->GetMotionMaster()->Initialize();
{ if (!newChar->Create(sObjectMgr->GetGenerator<HighGuid::Player>().Generate(), createInfo.get()))
// Only when player is created correctly do clean {
if (ptr->HasAtLoginFlag(AT_LOGIN_FIRST)) // Player not create (race/class/etc problem?)
SendCharCreate(CHAR_CREATE_ERROR);
return;
}
if ((haveSameRace && skipCinematics == 1) || skipCinematics == 2)
newChar->setCinematic(1); // not show intro
newChar->SetAtLoginFlag(AT_LOGIN_FIRST); // First login
CharacterDatabaseTransaction characterTransaction = CharacterDatabase.BeginTransaction();
LoginDatabaseTransaction trans = LoginDatabase.BeginTransaction();
// Player created, save it now
newChar->SaveToDB(characterTransaction, true, false);
createInfo->CharCount++;
LoginDatabasePreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_DEL_REALM_CHARACTERS_BY_REALM);
stmt->SetData(0, GetAccountId());
stmt->SetData(1, realm.Id.Realm);
trans->Append(stmt);
stmt = LoginDatabase.GetPreparedStatement(LOGIN_REP_REALM_CHARACTERS);
stmt->SetData(0, createInfo->CharCount);
stmt->SetData(1, GetAccountId());
stmt->SetData(2, realm.Id.Realm);
trans->Append(stmt);
LoginDatabase.CommitTransaction(trans);
AddTransactionCallback(CharacterDatabase.AsyncCommitTransaction(characterTransaction)).AfterComplete([this, newChar = std::move(newChar)](bool success)
{
if (success)
{
LOG_INFO("entities.player.character", "Account: {} (IP: {}) Create Character: {} {}", GetAccountId(), GetRemoteAddress(), newChar->GetName(), newChar->GetGUID().ToString());
sScriptMgr->OnPlayerCreate(newChar.get());
sCharacterCache->AddCharacterCacheEntry(newChar->GetGUID(), GetAccountId(), newChar->GetName(), newChar->getGender(), newChar->getRace(), newChar->getClass(), newChar->GetLevel());
SendCharCreate(CHAR_CREATE_SUCCESS);
}
else
SendCharCreate(CHAR_CREATE_ERROR);
});
};
if (allowTwoSideAccounts && !skipCinematics && createInfo->Class != CLASS_DEATH_KNIGHT)
{ {
ptr->CleanupsBeforeDelete(); finalizeCharacterCreation(PreparedQueryResult(nullptr));
return;
} }
delete ptr;
});
newChar->GetMotionMaster()->Initialize(); CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHAR_CREATE_INFO);
if (!newChar->Create(sObjectMgr->GetGenerator<HighGuid::Player>().Generate(), createInfo.get())) stmt->SetData(0, GetAccountId());
{ stmt->SetData(1, (skipCinematics == 1 || createInfo->Class == CLASS_DEATH_KNIGHT) ? 10 : 1);
// Player not create (race/class/etc problem?) queryCallback.WithPreparedCallback(std::move(finalizeCharacterCreation)).SetNextQuery(CharacterDatabase.AsyncQuery(stmt));
SendCharCreate(CHAR_CREATE_ERROR); }));
return;
}
if ((haveSameRace && skipCinematics == 1) || skipCinematics == 2)
newChar->setCinematic(1); // not show intro
newChar->SetAtLoginFlag(AT_LOGIN_FIRST); // First login
CharacterDatabaseTransaction characterTransaction = CharacterDatabase.BeginTransaction();
LoginDatabaseTransaction trans = LoginDatabase.BeginTransaction();
// Player created, save it now
newChar->SaveToDB(characterTransaction, true, false);
createInfo->CharCount++;
LoginDatabasePreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_DEL_REALM_CHARACTERS_BY_REALM);
stmt->SetData(0, GetAccountId());
stmt->SetData(1, realm.Id.Realm);
trans->Append(stmt);
stmt = LoginDatabase.GetPreparedStatement(LOGIN_REP_REALM_CHARACTERS);
stmt->SetData(0, createInfo->CharCount);
stmt->SetData(1, GetAccountId());
stmt->SetData(2, realm.Id.Realm);
trans->Append(stmt);
LoginDatabase.CommitTransaction(trans);
AddTransactionCallback(CharacterDatabase.AsyncCommitTransaction(characterTransaction)).AfterComplete([this, newChar = std::move(newChar)](bool success)
{
if (success)
{
LOG_INFO("entities.player.character", "Account: {} (IP: {}) Create Character: {} {}", GetAccountId(), GetRemoteAddress(), newChar->GetName(), newChar->GetGUID().ToString());
sScriptMgr->OnPlayerCreate(newChar.get());
sCharacterCache->AddCharacterCacheEntry(newChar->GetGUID(), GetAccountId(), newChar->GetName(), newChar->getGender(), newChar->getRace(), newChar->getClass(), newChar->GetLevel());
SendCharCreate(CHAR_CREATE_SUCCESS);
}
else
SendCharCreate(CHAR_CREATE_ERROR);
});
};
if (allowTwoSideAccounts && !skipCinematics && createInfo->Class != CLASS_DEATH_KNIGHT)
{
finalizeCharacterCreation(PreparedQueryResult(nullptr));
return;
}
CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHAR_CREATE_INFO);
stmt->SetData(0, GetAccountId());
stmt->SetData(1, (skipCinematics == 1 || createInfo->Class == CLASS_DEATH_KNIGHT) ? 10 : 1);
queryCallback.WithPreparedCallback(std::move(finalizeCharacterCreation)).SetNextQuery(CharacterDatabase.AsyncQuery(stmt));
}));
} }
void WorldSession::HandleCharDeleteOpcode(WorldPacket& recvData) void WorldSession::HandleCharDeleteOpcode(WorldPacket& recvData)
@@ -775,9 +775,9 @@ void WorldSession::HandlePlayerLoginOpcode(WorldPacket& recvData)
m_playerLoading = true; m_playerLoading = true;
AddQueryHolderCallback(CharacterDatabase.DelayQueryHolder(holder)).AfterComplete([this](SQLQueryHolderBase const& holder) AddQueryHolderCallback(CharacterDatabase.DelayQueryHolder(holder)).AfterComplete([this](SQLQueryHolderBase const& holder)
{ {
HandlePlayerLoginFromDB(static_cast<LoginQueryHolder const&>(holder)); HandlePlayerLoginFromDB(static_cast<LoginQueryHolder const&>(holder));
}); });
} }
void WorldSession::HandlePlayerLoginFromDB(LoginQueryHolder const& holder) void WorldSession::HandlePlayerLoginFromDB(LoginQueryHolder const& holder)
@@ -945,14 +945,13 @@ void WorldSession::HandlePlayerLoginFromDB(LoginQueryHolder const& holder)
pCurrChar->CastSpell(pCurrChar, 20584, true, 0); // auras SPELL_AURA_INCREASE_SPEED(+speed in wisp form), SPELL_AURA_INCREASE_SWIM_SPEED(+swim speed in wisp form), SPELL_AURA_TRANSFORM (to wisp form) pCurrChar->CastSpell(pCurrChar, 20584, true, 0); // auras SPELL_AURA_INCREASE_SPEED(+speed in wisp form), SPELL_AURA_INCREASE_SWIM_SPEED(+swim speed in wisp form), SPELL_AURA_TRANSFORM (to wisp form)
pCurrChar->CastSpell(pCurrChar, 8326, true, 0); // auras SPELL_AURA_GHOST, SPELL_AURA_INCREASE_SPEED(why?), SPELL_AURA_INCREASE_SWIM_SPEED(why?) pCurrChar->CastSpell(pCurrChar, 8326, true, 0); // auras SPELL_AURA_GHOST, SPELL_AURA_INCREASE_SPEED(why?), SPELL_AURA_INCREASE_SWIM_SPEED(why?)
pCurrChar->SetMovement(MOVE_WATER_WALK);
} }
// Set FFA PvP for non GM in non-rest mode // Set FFA PvP for non GM in non-rest mode
if (sWorld->IsFFAPvPRealm() && !pCurrChar->IsGameMaster() && !pCurrChar->HasPlayerFlag(PLAYER_FLAGS_RESTING)) if (sWorld->IsFFAPvPRealm() && !pCurrChar->IsGameMaster() && !pCurrChar->HasPlayerFlag(PLAYER_FLAGS_RESTING))
if (!pCurrChar->HasByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP)) if (!pCurrChar->HasByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP))
{ {
sScriptMgr->OnPlayerFfaPvpStateUpdate(pCurrChar,true); sScriptMgr->OnPlayerFfaPvpStateUpdate(pCurrChar, true);
pCurrChar->SetByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP); pCurrChar->SetByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP);
} }
@@ -979,10 +978,10 @@ void WorldSession::HandlePlayerLoginFromDB(LoginQueryHolder const& holder)
{ {
// If we process the check while players are loading they won't be notified of the changes. // If we process the check while players are loading they won't be notified of the changes.
pCurrChar->m_Events.AddEventAtOffset([pCurrChar] pCurrChar->m_Events.AddEventAtOffset([pCurrChar]
{ {
pCurrChar->RemoveAtLoginFlag(AT_LOGIN_CHECK_ACHIEVS, true); pCurrChar->RemoveAtLoginFlag(AT_LOGIN_CHECK_ACHIEVS, true);
pCurrChar->CheckAllAchievementCriteria(); pCurrChar->CheckAllAchievementCriteria();
}, 1s); }, 1s);
} }
bool firstLogin = pCurrChar->HasAtLoginFlag(AT_LOGIN_FIRST); bool firstLogin = pCurrChar->HasAtLoginFlag(AT_LOGIN_FIRST);
@@ -1009,25 +1008,25 @@ void WorldSession::HandlePlayerLoginFromDB(LoginQueryHolder const& holder)
ReputationMgr& repMgr = pCurrChar->GetReputationMgr(); ReputationMgr& repMgr = pCurrChar->GetReputationMgr();
auto SendFullReputation = [&repMgr](std::initializer_list<uint32> factionsList) auto SendFullReputation = [&repMgr](std::initializer_list<uint32> factionsList)
{
for (auto const& itr : factionsList)
{ {
repMgr.SetOneFactionReputation(sFactionStore.LookupEntry(itr), 42999.f, false); for (auto const& itr : factionsList)
} {
}; repMgr.SetOneFactionReputation(sFactionStore.LookupEntry(itr), 42999.f, false);
}
};
SendFullReputation({ 942, 935, 936, 1011, 970, 967, 989, 932, 934, 1038, 1077, 1106, 1104, 1090, 1098, 1156, 1073, 1105, 1119, 1091 }); SendFullReputation({ 942, 935, 936, 1011, 970, 967, 989, 932, 934, 1038, 1077, 1106, 1104, 1090, 1098, 1156, 1073, 1105, 1119, 1091 });
switch (pCurrChar->GetFaction()) switch (pCurrChar->GetFaction())
{ {
case ALLIANCE: case ALLIANCE:
SendFullReputation({ 72, 47, 69, 930, 730, 978, 54, 946, 1037, 1068, 1126, 1094, 1050 }); SendFullReputation({ 72, 47, 69, 930, 730, 978, 54, 946, 1037, 1068, 1126, 1094, 1050 });
break; break;
case HORDE: case HORDE:
SendFullReputation({ 76, 68, 81, 911, 729, 941, 530, 947, 1052, 1067, 1124, 1064, 1085 }); SendFullReputation({ 76, 68, 81, 911, 729, 941, 530, 947, 1052, 1067, 1124, 1064, 1085 });
break; break;
default: default:
break; break;
} }
repMgr.SendStates(); repMgr.SendStates();
@@ -1046,7 +1045,7 @@ void WorldSession::HandlePlayerLoginFromDB(LoginQueryHolder const& holder)
std::string IP_str = GetRemoteAddress(); std::string IP_str = GetRemoteAddress();
LOG_INFO("entities.player", "Account: {} (IP: {}) Login Character:[{}] ({}) Level: {}", LOG_INFO("entities.player", "Account: {} (IP: {}) Login Character:[{}] ({}) Level: {}",
GetAccountId(), IP_str, pCurrChar->GetName(), pCurrChar->GetGUID().ToString(), pCurrChar->GetLevel()); GetAccountId(), IP_str, pCurrChar->GetName(), pCurrChar->GetGUID().ToString(), pCurrChar->GetLevel());
if (!pCurrChar->IsStandState() && !pCurrChar->HasUnitState(UNIT_STATE_STUNNED)) if (!pCurrChar->IsStandState() && !pCurrChar->HasUnitState(UNIT_STATE_STUNNED))
pCurrChar->SetStandState(UNIT_STAND_STATE_STAND); pCurrChar->SetStandState(UNIT_STAND_STATE_STAND);
@@ -1341,7 +1340,7 @@ void WorldSession::HandleCharRenameOpcode(WorldPacket& recvData)
std::shared_ptr<CharacterRenameInfo> renameInfo = std::make_shared<CharacterRenameInfo>(); std::shared_ptr<CharacterRenameInfo> renameInfo = std::make_shared<CharacterRenameInfo>();
recvData >> renameInfo->Guid recvData >> renameInfo->Guid
>> renameInfo->Name; >> renameInfo->Name;
// prevent character rename to invalid name // prevent character rename to invalid name
if (!normalizePlayerName(renameInfo->Name)) if (!normalizePlayerName(renameInfo->Name))
@@ -1638,12 +1637,12 @@ void WorldSession::HandleCharCustomize(WorldPacket& recvData)
} }
recvData >> customizeInfo->Name recvData >> customizeInfo->Name
>> customizeInfo->Gender >> customizeInfo->Gender
>> customizeInfo->Skin >> customizeInfo->Skin
>> customizeInfo->HairColor >> customizeInfo->HairColor
>> customizeInfo->HairStyle >> customizeInfo->HairStyle
>> customizeInfo->FacialHair >> customizeInfo->FacialHair
>> customizeInfo->Face; >> customizeInfo->Face;
CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHAR_CUSTOMIZE_INFO); CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHAR_CUSTOMIZE_INFO);
stmt->SetData(0, customizeInfo->Guid.GetCounter()); stmt->SetData(0, customizeInfo->Guid.GetCounter());
@@ -1775,10 +1774,10 @@ void WorldSession::HandleEquipmentSetSave(WorldPacket& recvData)
EquipmentSet eqSet; EquipmentSet eqSet;
eqSet.Guid = setGuid; eqSet.Guid = setGuid;
eqSet.Name = name; eqSet.Name = name;
eqSet.IconName = iconName; eqSet.IconName = iconName;
eqSet.state = EQUIPMENT_SET_NEW; eqSet.state = EQUIPMENT_SET_NEW;
for (uint32 i = 0; i < EQUIPMENT_SLOT_END; ++i) for (uint32 i = 0; i < EQUIPMENT_SLOT_END; ++i)
{ {
@@ -1933,13 +1932,13 @@ void WorldSession::HandleCharFactionOrRaceChange(WorldPacket& recvData)
} }
recvData >> factionChangeInfo->Name recvData >> factionChangeInfo->Name
>> factionChangeInfo->Gender >> factionChangeInfo->Gender
>> factionChangeInfo->Skin >> factionChangeInfo->Skin
>> factionChangeInfo->HairColor >> factionChangeInfo->HairColor
>> factionChangeInfo->HairStyle >> factionChangeInfo->HairStyle
>> factionChangeInfo->FacialHair >> factionChangeInfo->FacialHair
>> factionChangeInfo->Face >> factionChangeInfo->Face
>> factionChangeInfo->Race; >> factionChangeInfo->Race;
// pussywizard: // pussywizard:
if (ObjectAccessor::FindConnectedPlayer(factionChangeInfo->Guid) || sWorldSessionMgr->FindOfflineSessionForCharacterGUID(factionChangeInfo->Guid.GetCounter())) if (ObjectAccessor::FindConnectedPlayer(factionChangeInfo->Guid) || sWorldSessionMgr->FindOfflineSessionForCharacterGUID(factionChangeInfo->Guid.GetCounter()))
@@ -2217,16 +2216,16 @@ void WorldSession::HandleCharFactionOrRaceChangeCallback(std::shared_ptr<Charact
for (auto const& itr : sTaxiPathSetBySource) for (auto const& itr : sTaxiPathSetBySource)
{ {
auto FillTaxiMask = [&](uint8 field, uint32 mask) auto FillTaxiMask = [&](uint8 field, uint32 mask)
{
if (playerClass == CLASS_DEATH_KNIGHT)
{ {
newTaxiMask[field] |= uint32(mask | (sDeathKnightTaxiNodesMask[field] & mask)); if (playerClass == CLASS_DEATH_KNIGHT)
} {
else newTaxiMask[field] |= uint32(mask | (sDeathKnightTaxiNodesMask[field] & mask));
{ }
newTaxiMask[field] |= mask; else
} {
}; newTaxiMask[field] |= mask;
}
};
uint32 nodeId = itr.first; uint32 nodeId = itr.first;
uint8 field = (uint8)((nodeId - 1) / 32); uint8 field = (uint8)((nodeId - 1) / 32);
+3 -56
View File
@@ -335,15 +335,10 @@ void WorldSession::HandleMessagechatOpcode(WorldPacket& recvData)
msg.erase(end, msg.end()); msg.erase(end, msg.end());
} }
// Skip validation for playerbots module // Validate hyperlinks
auto playerbotsHyperlink = msg.find("Hfound:") != std::string::npos; if (!ValidateHyperlinksAndMaybeKick(msg))
if (!playerbotsHyperlink)
{ {
// Validate hyperlinks return;
if (!ValidateHyperlinksAndMaybeKick(msg))
{
return;
}
} }
} }
@@ -439,11 +434,7 @@ void WorldSession::HandleMessagechatOpcode(WorldPacket& recvData)
return; return;
if (!sScriptMgr->OnPlayerCanUseChat(GetPlayer(), type, lang, msg, group)) if (!sScriptMgr->OnPlayerCanUseChat(GetPlayer(), type, lang, msg, group))
{
return; return;
}
sScriptMgr->OnPlayerChat(GetPlayer(), type, lang, msg, group);
WorldPacket data; WorldPacket data;
ChatHandler::BuildChatPacket(data, ChatMsg(type), Language(lang), sender, nullptr, msg); ChatHandler::BuildChatPacket(data, ChatMsg(type), Language(lang), sender, nullptr, msg);
@@ -457,18 +448,10 @@ void WorldSession::HandleMessagechatOpcode(WorldPacket& recvData)
if (Guild* guild = sGuildMgr->GetGuildById(GetPlayer()->GetGuildId())) if (Guild* guild = sGuildMgr->GetGuildById(GetPlayer()->GetGuildId()))
{ {
if (!sScriptMgr->OnPlayerCanUseChat(GetPlayer(), type, lang, msg, guild)) if (!sScriptMgr->OnPlayerCanUseChat(GetPlayer(), type, lang, msg, guild))
{
return; return;
}
sScriptMgr->OnPlayerChat(GetPlayer(), type, lang, msg, guild);
guild->BroadcastToGuild(this, false, msg, lang == LANG_ADDON ? LANG_ADDON : LANG_UNIVERSAL); guild->BroadcastToGuild(this, false, msg, lang == LANG_ADDON ? LANG_ADDON : LANG_UNIVERSAL);
} }
else
{
sScriptMgr->OnPlayerChat(GetPlayer(), type, lang, msg);
}
} }
} }
break; break;
@@ -479,11 +462,7 @@ void WorldSession::HandleMessagechatOpcode(WorldPacket& recvData)
if (Guild* guild = sGuildMgr->GetGuildById(GetPlayer()->GetGuildId())) if (Guild* guild = sGuildMgr->GetGuildById(GetPlayer()->GetGuildId()))
{ {
if (!sScriptMgr->OnPlayerCanUseChat(GetPlayer(), type, lang, msg, guild)) if (!sScriptMgr->OnPlayerCanUseChat(GetPlayer(), type, lang, msg, guild))
{
return; return;
}
sScriptMgr->OnPlayerChat(GetPlayer(), type, lang, msg, guild);
guild->BroadcastToGuild(this, true, msg, lang == LANG_ADDON ? LANG_ADDON : LANG_UNIVERSAL); guild->BroadcastToGuild(this, true, msg, lang == LANG_ADDON ? LANG_ADDON : LANG_UNIVERSAL);
} }
@@ -502,11 +481,7 @@ void WorldSession::HandleMessagechatOpcode(WorldPacket& recvData)
} }
if (!sScriptMgr->OnPlayerCanUseChat(GetPlayer(), type, lang, msg, group)) if (!sScriptMgr->OnPlayerCanUseChat(GetPlayer(), type, lang, msg, group))
{
return; return;
}
sScriptMgr->OnPlayerChat(GetPlayer(), type, lang, msg, group);
WorldPacket data; WorldPacket data;
ChatHandler::BuildChatPacket(data, CHAT_MSG_RAID, Language(lang), sender, nullptr, msg); ChatHandler::BuildChatPacket(data, CHAT_MSG_RAID, Language(lang), sender, nullptr, msg);
@@ -525,11 +500,7 @@ void WorldSession::HandleMessagechatOpcode(WorldPacket& recvData)
} }
if (!sScriptMgr->OnPlayerCanUseChat(GetPlayer(), type, lang, msg, group)) if (!sScriptMgr->OnPlayerCanUseChat(GetPlayer(), type, lang, msg, group))
{
return; return;
}
sScriptMgr->OnPlayerChat(GetPlayer(), type, lang, msg, group);
WorldPacket data; WorldPacket data;
ChatHandler::BuildChatPacket(data, CHAT_MSG_RAID_LEADER, Language(lang), sender, nullptr, msg); ChatHandler::BuildChatPacket(data, CHAT_MSG_RAID_LEADER, Language(lang), sender, nullptr, msg);
@@ -543,11 +514,7 @@ void WorldSession::HandleMessagechatOpcode(WorldPacket& recvData)
return; return;
if (!sScriptMgr->OnPlayerCanUseChat(GetPlayer(), type, lang, msg, group)) if (!sScriptMgr->OnPlayerCanUseChat(GetPlayer(), type, lang, msg, group))
{
return; return;
}
sScriptMgr->OnPlayerChat(GetPlayer(), type, lang, msg, group);
// In battleground, raid warning is sent only to players in battleground - code is ok // In battleground, raid warning is sent only to players in battleground - code is ok
WorldPacket data; WorldPacket data;
@@ -563,11 +530,7 @@ void WorldSession::HandleMessagechatOpcode(WorldPacket& recvData)
return; return;
if (!sScriptMgr->OnPlayerCanUseChat(GetPlayer(), type, lang, msg, group)) if (!sScriptMgr->OnPlayerCanUseChat(GetPlayer(), type, lang, msg, group))
{
return; return;
}
sScriptMgr->OnPlayerChat(GetPlayer(), type, lang, msg, group);
WorldPacket data; WorldPacket data;
ChatHandler::BuildChatPacket(data, CHAT_MSG_BATTLEGROUND, Language(lang), sender, nullptr, msg); ChatHandler::BuildChatPacket(data, CHAT_MSG_BATTLEGROUND, Language(lang), sender, nullptr, msg);
@@ -582,11 +545,7 @@ void WorldSession::HandleMessagechatOpcode(WorldPacket& recvData)
return; return;
if (!sScriptMgr->OnPlayerCanUseChat(GetPlayer(), type, lang, msg, group)) if (!sScriptMgr->OnPlayerCanUseChat(GetPlayer(), type, lang, msg, group))
{
return; return;
}
sScriptMgr->OnPlayerChat(GetPlayer(), type, lang, msg, group);
WorldPacket data; WorldPacket data;
ChatHandler::BuildChatPacket(data, CHAT_MSG_BATTLEGROUND_LEADER, Language(lang), sender, nullptr, msg); ChatHandler::BuildChatPacket(data, CHAT_MSG_BATTLEGROUND_LEADER, Language(lang), sender, nullptr, msg);
@@ -609,11 +568,7 @@ void WorldSession::HandleMessagechatOpcode(WorldPacket& recvData)
if (Channel* chn = cMgr->GetChannel(channel, sender)) if (Channel* chn = cMgr->GetChannel(channel, sender))
{ {
if (!sScriptMgr->OnPlayerCanUseChat(sender, type, lang, msg, chn)) if (!sScriptMgr->OnPlayerCanUseChat(sender, type, lang, msg, chn))
{
return; return;
}
sScriptMgr->OnPlayerChat(sender, type, lang, msg, chn);
chn->Say(sender->GetGUID(), msg.c_str(), lang); chn->Say(sender->GetGUID(), msg.c_str(), lang);
} }
@@ -642,11 +597,7 @@ void WorldSession::HandleMessagechatOpcode(WorldPacket& recvData)
} }
if (!sScriptMgr->OnPlayerCanUseChat(sender, type, lang, msg)) if (!sScriptMgr->OnPlayerCanUseChat(sender, type, lang, msg))
{
return; return;
}
sScriptMgr->OnPlayerChat(sender, type, lang, msg);
} }
break; break;
} }
@@ -670,11 +621,7 @@ void WorldSession::HandleMessagechatOpcode(WorldPacket& recvData)
} }
if (!sScriptMgr->OnPlayerCanUseChat(sender, type, lang, msg)) if (!sScriptMgr->OnPlayerCanUseChat(sender, type, lang, msg))
{
return; return;
}
sScriptMgr->OnPlayerChat(sender, type, lang, msg);
break; break;
} }
@@ -482,8 +482,6 @@ void WorldSession::HandlePetitionSignOpcode(WorldPacket& recvData)
break; break;
} }
sScriptMgr->OnPlayerbotCheckPetitionAccount(_player, found);
if (found) if (found)
{ {
WorldPacket data(SMSG_PETITION_SIGN_RESULTS, (8 + 8 + 4)); WorldPacket data(SMSG_PETITION_SIGN_RESULTS, (8 + 8 + 4));
+34 -47
View File
@@ -54,6 +54,10 @@ Map::~Map()
{ {
// UnloadAll must be called before deleting the map // UnloadAll must be called before deleting the map
// Kill all scheduled events without executing them, since the map and its objects are being destroyed.
// This prevents events from running on invalid or deleted objects during map destruction.
Events.KillAllEvents(false);
sScriptMgr->OnDestroyMap(this); sScriptMgr->OnDestroyMap(this);
if (!m_scriptSchedule.empty()) if (!m_scriptSchedule.empty())
@@ -447,7 +451,7 @@ void Map::Update(const uint32 t_diff, const uint32 s_diff, bool /*thread*/)
} }
} }
_creatureRespawnScheduler.Update(t_diff); Events.Update(t_diff);
if (!t_diff) if (!t_diff)
{ {
@@ -1097,7 +1101,7 @@ float Map::GetWaterOrGroundLevel(uint32 phasemask, float x, float y, float z, fl
if (ground) if (ground)
*ground = ground_z; *ground = ground_z;
LiquidData const& liquidData = const_cast<Map*>(this)->GetLiquidData(phasemask, x, y, ground_z, collisionHeight, MAP_ALL_LIQUIDS); LiquidData const& liquidData = const_cast<Map*>(this)->GetLiquidData(phasemask, x, y, ground_z, collisionHeight, {});
switch (liquidData.Status) switch (liquidData.Status)
{ {
case LIQUID_MAP_ABOVE_WATER: case LIQUID_MAP_ABOVE_WATER:
@@ -1198,27 +1202,18 @@ static inline bool IsInWMOInterior(uint32 mogpFlags)
bool Map::GetAreaInfo(uint32 phaseMask, float x, float y, float z, uint32& flags, int32& adtId, int32& rootId, int32& groupId) const bool Map::GetAreaInfo(uint32 phaseMask, float x, float y, float z, uint32& flags, int32& adtId, int32& rootId, int32& groupId) const
{ {
float vmap_z = z;
float dynamic_z = z;
float check_z = z; float check_z = z;
VMAP::IVMapMgr* vmgr = VMAP::VMapFactory::createOrGetVMapMgr(); VMAP::IVMapMgr* vmgr = VMAP::VMapFactory::createOrGetVMapMgr();
uint32 vflags; VMAP::AreaAndLiquidData vdata;
int32 vadtId; VMAP::AreaAndLiquidData ddata;
int32 vrootId;
int32 vgroupId;
uint32 dflags;
int32 dadtId;
int32 drootId;
int32 dgroupId;
bool hasVmapAreaInfo = vmgr->GetAreaInfo(GetId(), x, y, vmap_z, vflags, vadtId, vrootId, vgroupId);
bool hasDynamicAreaInfo = _dynamicTree.GetAreaInfo(x, y, dynamic_z, phaseMask, dflags, dadtId, drootId, dgroupId);
auto useVmap = [&]() { check_z = vmap_z; flags = vflags; adtId = vadtId; rootId = vrootId; groupId = vgroupId; };
auto useDyn = [&]() { check_z = dynamic_z; flags = dflags; adtId = dadtId; rootId = drootId; groupId = dgroupId; };
bool hasVmapAreaInfo = vmgr->GetAreaAndLiquidData(GetId(), x, y, z, {}, vdata) && vdata.areaInfo.has_value();
bool hasDynamicAreaInfo = _dynamicTree.GetAreaAndLiquidData(x, y, z, phaseMask, {}, ddata) && ddata.areaInfo.has_value();
auto useVmap = [&] { check_z = vdata.floorZ; groupId = vdata.areaInfo->groupId; adtId = vdata.areaInfo->adtId; rootId = vdata.areaInfo->rootId; flags = vdata.areaInfo->mogpFlags; };
auto useDyn = [&] { check_z = ddata.floorZ; groupId = ddata.areaInfo->groupId; adtId = ddata.areaInfo->adtId; rootId = ddata.areaInfo->rootId; flags = ddata.areaInfo->mogpFlags; };
if (hasVmapAreaInfo) if (hasVmapAreaInfo)
{ {
if (hasDynamicAreaInfo && dynamic_z > vmap_z) if (hasDynamicAreaInfo && ddata.floorZ > vdata.floorZ)
useDyn(); useDyn();
else else
useVmap(); useVmap();
@@ -1299,32 +1294,30 @@ void Map::GetZoneAndAreaId(uint32 phaseMask, uint32& zoneid, uint32& areaid, flo
zoneid = area->zone; zoneid = area->zone;
} }
LiquidData const Map::GetLiquidData(uint32 phaseMask, float x, float y, float z, float collisionHeight, uint8 ReqLiquidType) LiquidData const Map::GetLiquidData(uint32 phaseMask, float x, float y, float z, float collisionHeight, Optional<uint8> ReqLiquidType)
{ {
LiquidData liquidData; LiquidData liquidData;
liquidData.Status = LIQUID_MAP_NO_WATER;
VMAP::IVMapMgr* vmgr = VMAP::VMapFactory::createOrGetVMapMgr(); VMAP::IVMapMgr* vmgr = VMAP::VMapFactory::createOrGetVMapMgr();
float liquid_level = INVALID_HEIGHT; VMAP::AreaAndLiquidData vmapData;
float ground_level = INVALID_HEIGHT;
uint32 liquid_type = 0;
uint32 mogpFlags = 0;
bool useGridLiquid = true; bool useGridLiquid = true;
if (vmgr->GetLiquidLevel(GetId(), x, y, z, ReqLiquidType, liquid_level, ground_level, liquid_type, mogpFlags)) if (vmgr->GetAreaAndLiquidData(GetId(), x, y, z, ReqLiquidType, vmapData) && vmapData.liquidInfo)
{ {
useGridLiquid = !IsInWMOInterior(mogpFlags); useGridLiquid = !vmapData.areaInfo || !IsInWMOInterior(vmapData.areaInfo->mogpFlags);
LOG_DEBUG("maps", "GetLiquidStatus(): vmap liquid level: {} ground: {} type: {}", liquid_level, ground_level, liquid_type); LOG_DEBUG("maps", "GetLiquidStatus(): vmap liquid level: {} ground: {} type: {}", vmapData.liquidInfo->level, vmapData.floorZ, vmapData.liquidInfo->type);
// Check water level and ground level // Check water level and ground level
if (liquid_level > ground_level && G3D::fuzzyGe(z, ground_level - GROUND_HEIGHT_TOLERANCE)) if (vmapData.liquidInfo->level > vmapData.floorZ && G3D::fuzzyGe(z, vmapData.floorZ - GROUND_HEIGHT_TOLERANCE))
{ {
// hardcoded in client like this // hardcoded in client like this
if (GetId() == MAP_OUTLAND && liquid_type == 2) if (GetId() == MAP_OUTLAND && vmapData.liquidInfo->type == 2)
liquid_type = 15; vmapData.liquidInfo->type = 15;
uint32 liquidFlagType = 0; uint32 liquidFlagType = 0;
if (LiquidTypeEntry const* liq = sLiquidTypeStore.LookupEntry(liquid_type)) if (LiquidTypeEntry const* liq = sLiquidTypeStore.LookupEntry(vmapData.liquidInfo->type))
liquidFlagType = liq->Type; liquidFlagType = liq->Type;
if (liquid_type && liquid_type < 21) if (vmapData.liquidInfo->type && vmapData.liquidInfo->type < 21)
{ {
if (AreaTableEntry const* area = sAreaTableStore.LookupEntry(GetAreaId(phaseMask, x, y, z))) if (AreaTableEntry const* area = sAreaTableStore.LookupEntry(GetAreaId(phaseMask, x, y, z)))
{ {
@@ -1338,19 +1331,19 @@ LiquidData const Map::GetLiquidData(uint32 phaseMask, float x, float y, float z,
if (LiquidTypeEntry const* liq = sLiquidTypeStore.LookupEntry(overrideLiquid)) if (LiquidTypeEntry const* liq = sLiquidTypeStore.LookupEntry(overrideLiquid))
{ {
liquid_type = overrideLiquid; vmapData.liquidInfo->type = overrideLiquid;
liquidFlagType = liq->Type; liquidFlagType = liq->Type;
} }
} }
} }
liquidData.Level = liquid_level; liquidData.Level = vmapData.liquidInfo->level;
liquidData.DepthLevel = ground_level; liquidData.DepthLevel = vmapData.floorZ;
liquidData.Entry = liquid_type; liquidData.Entry = vmapData.liquidInfo->type;
liquidData.Flags = 1 << liquidFlagType; liquidData.Flags = 1 << liquidFlagType;
} }
float delta = liquid_level - z; float delta = vmapData.liquidInfo->level - z;
// Get position delta // Get position delta
if (delta > collisionHeight) if (delta > collisionHeight)
@@ -1369,7 +1362,7 @@ LiquidData const Map::GetLiquidData(uint32 phaseMask, float x, float y, float z,
{ {
LiquidData const& map_data = gmap->GetLiquidData(x, y, z, collisionHeight, ReqLiquidType); LiquidData const& map_data = gmap->GetLiquidData(x, y, z, collisionHeight, ReqLiquidType);
// Not override LIQUID_MAP_ABOVE_WATER with LIQUID_MAP_NO_WATER: // Not override LIQUID_MAP_ABOVE_WATER with LIQUID_MAP_NO_WATER:
if (map_data.Status != LIQUID_MAP_NO_WATER && (map_data.Level > ground_level)) if (map_data.Status != LIQUID_MAP_NO_WATER && (map_data.Level > vmapData.floorZ))
{ {
// hardcoded in client like this // hardcoded in client like this
uint32 liquidEntry = map_data.Entry; uint32 liquidEntry = map_data.Entry;
@@ -1385,7 +1378,7 @@ LiquidData const Map::GetLiquidData(uint32 phaseMask, float x, float y, float z,
return liquidData; return liquidData;
} }
void Map::GetFullTerrainStatusForPosition(uint32 /*phaseMask*/, float x, float y, float z, float collisionHeight, PositionFullTerrainStatus& data, uint8 reqLiquidType) void Map::GetFullTerrainStatusForPosition(uint32 /*phaseMask*/, float x, float y, float z, float collisionHeight, PositionFullTerrainStatus& data, Optional<uint8> reqLiquidType)
{ {
GridTerrainData* gmap = GetGridTerrainData(x, y); GridTerrainData* gmap = GetGridTerrainData(x, y);
@@ -1600,7 +1593,7 @@ float Map::GetHeight(uint32 phasemask, float x, float y, float z, bool vmap/*=tr
bool Map::IsInWater(uint32 phaseMask, float x, float y, float pZ, float collisionHeight) const bool Map::IsInWater(uint32 phaseMask, float x, float y, float pZ, float collisionHeight) const
{ {
LiquidData const& liquidData = const_cast<Map*>(this)->GetLiquidData(phaseMask, x, y, pZ, collisionHeight, MAP_ALL_LIQUIDS); LiquidData const& liquidData = const_cast<Map*>(this)->GetLiquidData(phaseMask, x, y, pZ, collisionHeight, {});
return (liquidData.Status & MAP_LIQUID_STATUS_SWIMMING) != 0; return (liquidData.Status & MAP_LIQUID_STATUS_SWIMMING) != 0;
} }
@@ -1729,12 +1722,6 @@ void Map::SendObjectUpdates()
WorldPacket packet; // here we allocate a std::vector with a size of 0x10000 WorldPacket packet; // here we allocate a std::vector with a size of 0x10000
for (UpdateDataMapType::iterator iter = update_players.begin(); iter != update_players.end(); ++iter) for (UpdateDataMapType::iterator iter = update_players.begin(); iter != update_players.end(); ++iter)
{ {
if (!sScriptMgr->OnPlayerbotCheckUpdatesToSend(iter->first))
{
iter->second.Clear();
continue;
}
iter->second.BuildPacket(packet); iter->second.BuildPacket(packet);
iter->first->SendDirectMessage(&packet); iter->first->SendDirectMessage(&packet);
packet.clear(); // clean the string packet.clear(); // clean the string
@@ -2764,13 +2751,13 @@ void Map::RemoveOldCorpses()
void Map::ScheduleCreatureRespawn(ObjectGuid creatureGuid, Milliseconds respawnTimer, Position pos) void Map::ScheduleCreatureRespawn(ObjectGuid creatureGuid, Milliseconds respawnTimer, Position pos)
{ {
_creatureRespawnScheduler.Schedule(respawnTimer, [this, creatureGuid, pos](TaskContext) Events.AddEventAtOffset([this, creatureGuid, pos]()
{ {
if (Creature* creature = GetCreature(creatureGuid)) if (Creature* creature = GetCreature(creatureGuid))
creature->Respawn(); creature->Respawn();
else else
SummonCreature(creatureGuid.GetEntry(), pos); SummonCreature(creatureGuid.GetEntry(), pos);
}); }, respawnTimer);
} }
/// Send a packet to all players (or players selected team) in the zone (except self if mentioned) /// Send a packet to all players (or players selected team) in the zone (except self if mentioned)
+5 -5
View File
@@ -23,6 +23,7 @@
#include "DataMap.h" #include "DataMap.h"
#include "Define.h" #include "Define.h"
#include "DynamicTree.h" #include "DynamicTree.h"
#include "EventProcessor.h"
#include "GameObjectModel.h" #include "GameObjectModel.h"
#include "GridDefines.h" #include "GridDefines.h"
#include "GridRefMgr.h" #include "GridRefMgr.h"
@@ -33,7 +34,6 @@
#include "PathGenerator.h" #include "PathGenerator.h"
#include "Position.h" #include "Position.h"
#include "SharedDefines.h" #include "SharedDefines.h"
#include "TaskScheduler.h"
#include "Timer.h" #include "Timer.h"
#include "GridTerrainData.h" #include "GridTerrainData.h"
#include <bitset> #include <bitset>
@@ -172,7 +172,7 @@ public:
// currently unused for normal maps // currently unused for normal maps
bool CanUnload(uint32 diff) bool CanUnload(uint32 diff)
{ {
if (!m_unloadTimer) if (!m_unloadTimer || Events.HasEvents())
return false; return false;
if (m_unloadTimer <= diff) if (m_unloadTimer <= diff)
@@ -243,8 +243,8 @@ public:
[[nodiscard]] float GetMinHeight(float x, float y) const; [[nodiscard]] float GetMinHeight(float x, float y) const;
Transport* GetTransportForPos(uint32 phase, float x, float y, float z, WorldObject* worldobject = nullptr); Transport* GetTransportForPos(uint32 phase, float x, float y, float z, WorldObject* worldobject = nullptr);
void GetFullTerrainStatusForPosition(uint32 phaseMask, float x, float y, float z, float collisionHeight, PositionFullTerrainStatus& data, uint8 reqLiquidType = MAP_ALL_LIQUIDS); void GetFullTerrainStatusForPosition(uint32 phaseMask, float x, float y, float z, float collisionHeight, PositionFullTerrainStatus& data, Optional<uint8> reqLiquidType = {});
LiquidData const GetLiquidData(uint32 phaseMask, float x, float y, float z, float collisionHeight, uint8 ReqLiquidType); LiquidData const GetLiquidData(uint32 phaseMask, float x, float y, float z, float collisionHeight, Optional<uint8> ReqLiquidType);
[[nodiscard]] bool GetAreaInfo(uint32 phaseMask, float x, float y, float z, uint32& mogpflags, int32& adtId, int32& rootId, int32& groupId) const; [[nodiscard]] bool GetAreaInfo(uint32 phaseMask, float x, float y, float z, uint32& mogpflags, int32& adtId, int32& rootId, int32& groupId) const;
[[nodiscard]] uint32 GetAreaId(uint32 phaseMask, float x, float y, float z) const; [[nodiscard]] uint32 GetAreaId(uint32 phaseMask, float x, float y, float z) const;
@@ -430,7 +430,7 @@ public:
void UpdatePlayerZoneStats(uint32 oldZone, uint32 newZone); void UpdatePlayerZoneStats(uint32 oldZone, uint32 newZone);
[[nodiscard]] uint32 ApplyDynamicModeRespawnScaling(WorldObject const* obj, uint32 respawnDelay) const; [[nodiscard]] uint32 ApplyDynamicModeRespawnScaling(WorldObject const* obj, uint32 respawnDelay) const;
TaskScheduler _creatureRespawnScheduler; EventProcessor Events;
void ScheduleCreatureRespawn(ObjectGuid /*creatureGuid*/, Milliseconds /*respawnTimer*/, Position pos = Position()); void ScheduleCreatureRespawn(ObjectGuid /*creatureGuid*/, Milliseconds /*respawnTimer*/, Position pos = Position());
@@ -211,8 +211,8 @@ void PathGenerator::BuildPolyPath(G3D::Vector3 const& startPos, G3D::Vector3 con
{ {
bool buildShortcut = false; bool buildShortcut = false;
auto liquidDataStart = _source->GetMap()->GetLiquidData(_source->GetPhaseMask(), startPos.x, startPos.y, startPos.z, _source->GetCollisionHeight(), MAP_ALL_LIQUIDS); auto liquidDataStart = _source->GetMap()->GetLiquidData(_source->GetPhaseMask(), startPos.x, startPos.y, startPos.z, _source->GetCollisionHeight(), {});
auto liquidDataEnd = _source->GetMap()->GetLiquidData(_source->GetPhaseMask(), endPos.x, endPos.y, endPos.z, _source->GetCollisionHeight(), MAP_ALL_LIQUIDS); auto liquidDataEnd = _source->GetMap()->GetLiquidData(_source->GetPhaseMask(), endPos.x, endPos.y, endPos.z, _source->GetCollisionHeight(), {});
bool startUnderWaterEndInWater = liquidDataStart.Status == LIQUID_MAP_UNDER_WATER && bool startUnderWaterEndInWater = liquidDataStart.Status == LIQUID_MAP_UNDER_WATER &&
(liquidDataEnd.Status & MAP_LIQUID_STATUS_IN_CONTACT) != 0; (liquidDataEnd.Status & MAP_LIQUID_STATUS_IN_CONTACT) != 0;
@@ -698,7 +698,7 @@ void PathGenerator::UpdateFilter()
NavTerrain PathGenerator::GetNavTerrain(float x, float y, float z) const NavTerrain PathGenerator::GetNavTerrain(float x, float y, float z) const
{ {
LiquidData const& liquidData = _source->GetMap()->GetLiquidData(_source->GetPhaseMask(), x, y, z, _source->GetCollisionHeight(), MAP_ALL_LIQUIDS); LiquidData const& liquidData = _source->GetMap()->GetLiquidData(_source->GetPhaseMask(), x, y, z, _source->GetCollisionHeight(), {});
if (liquidData.Status == LIQUID_MAP_NO_WATER) if (liquidData.Status == LIQUID_MAP_NO_WATER)
return NAV_GROUND; return NAV_GROUND;
@@ -47,10 +47,6 @@ void PointMovementGenerator<T>::DoInitialize(T* unit)
i_recalculateSpeed = false; i_recalculateSpeed = false;
Movement::MoveSplineInit init(unit); Movement::MoveSplineInit init(unit);
/// Added by mod-playerbots
if (_reverseOrientation)
init.SetOrientationInversed();
/// End added
if (m_precomputedPath.size() > 2) // pussywizard: for charge if (m_precomputedPath.size() > 2) // pussywizard: for charge
init.MovebyPath(m_precomputedPath); init.MovebyPath(m_precomputedPath);
else if (_generatePath) else if (_generatePath)
@@ -220,9 +216,14 @@ template <> void PointMovementGenerator<Creature>::MovementInform(Creature* unit
if (Unit* summoner = unit->GetCharmerOrOwner()) if (Unit* summoner = unit->GetCharmerOrOwner())
{ {
if (UnitAI* AI = summoner->GetAI()) if (UnitAI* AI = summoner->GetAI())
{
AI->SummonMovementInform(unit, POINT_MOTION_TYPE, id); AI->SummonMovementInform(unit, POINT_MOTION_TYPE, id);
} }
else
{
if (TempSummon* tempSummon = unit->ToTempSummon())
if (Unit* summoner = tempSummon->GetSummonerUnit())
if (UnitAI* AI = summoner->GetAI())
AI->SummonMovementInform(unit, POINT_MOTION_TYPE, id);
} }
} }
@@ -276,22 +276,14 @@ void WaypointMovementGenerator<Creature>::MovementInform(Creature* creature)
if (Unit* owner = creature->GetCharmerOrOwner()) if (Unit* owner = creature->GetCharmerOrOwner())
{ {
if (UnitAI* AI = owner->GetAI()) if (UnitAI* AI = owner->GetAI())
{
AI->SummonMovementInform(creature, WAYPOINT_MOTION_TYPE, i_currentNode); AI->SummonMovementInform(creature, WAYPOINT_MOTION_TYPE, i_currentNode);
}
} }
else else
{ {
if (TempSummon* tempSummon = creature->ToTempSummon()) if (TempSummon* tempSummon = creature->ToTempSummon())
{
if (Unit* owner = tempSummon->GetSummonerUnit()) if (Unit* owner = tempSummon->GetSummonerUnit())
{
if (UnitAI* AI = owner->GetAI()) if (UnitAI* AI = owner->GetAI())
{
AI->SummonMovementInform(creature, WAYPOINT_MOTION_TYPE, i_currentNode); AI->SummonMovementInform(creature, WAYPOINT_MOTION_TYPE, i_currentNode);
}
}
}
} }
} }
@@ -418,6 +410,7 @@ void FlightPathMovementGenerator::DoFinalize(Player* player)
player->m_taxi.ClearTaxiDestinations(); player->m_taxi.ClearTaxiDestinations();
player->Dismount(); player->Dismount();
player->RemoveUnitFlag(UNIT_FLAG_DISABLE_MOVE | UNIT_FLAG_TAXI_FLIGHT); player->RemoveUnitFlag(UNIT_FLAG_DISABLE_MOVE | UNIT_FLAG_TAXI_FLIGHT);
player->UpdatePvPState(); // to account for cases such as flying into a PvP territory, as it does not flag on the way in
if (player->m_taxi.empty()) if (player->m_taxi.empty())
{ {
@@ -447,6 +440,9 @@ void FlightPathMovementGenerator::DoReset(Player* player)
return; return;
} }
if (player->pvpInfo.EndTimer)
player->UpdatePvP(false, true); // PvP flag timer immediately ends when starting taxi
player->getHostileRefMgr().setOnlineOfflineState(false); player->getHostileRefMgr().setOnlineOfflineState(false);
player->AddUnitState(UNIT_STATE_IN_FLIGHT); player->AddUnitState(UNIT_STATE_IN_FLIGHT);
player->SetUnitFlag(UNIT_FLAG_DISABLE_MOVE | UNIT_FLAG_TAXI_FLIGHT); player->SetUnitFlag(UNIT_FLAG_DISABLE_MOVE | UNIT_FLAG_TAXI_FLIGHT);
@@ -169,36 +169,11 @@ void ScriptMgr::OnPlayerDuelEnd(Player* winner, Player* loser, DuelCompleteType
CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_DUEL_END, script->OnPlayerDuelEnd(winner, loser, type)); CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_DUEL_END, script->OnPlayerDuelEnd(winner, loser, type));
} }
void ScriptMgr::OnPlayerChat(Player* player, uint32 type, uint32 lang, std::string& msg)
{
CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_CHAT, script->OnPlayerChat(player, type, lang, msg));
}
void ScriptMgr::OnPlayerBeforeSendChatMessage(Player* player, uint32& type, uint32& lang, std::string& msg) void ScriptMgr::OnPlayerBeforeSendChatMessage(Player* player, uint32& type, uint32& lang, std::string& msg)
{ {
CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_BEFORE_SEND_CHAT_MESSAGE, script->OnPlayerBeforeSendChatMessage(player, type, lang, msg)); CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_BEFORE_SEND_CHAT_MESSAGE, script->OnPlayerBeforeSendChatMessage(player, type, lang, msg));
} }
void ScriptMgr::OnPlayerChat(Player* player, uint32 type, uint32 lang, std::string& msg, Player* receiver)
{
CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_CHAT_WITH_RECEIVER, script->OnPlayerChat(player, type, lang, msg, receiver));
}
void ScriptMgr::OnPlayerChat(Player* player, uint32 type, uint32 lang, std::string& msg, Group* group)
{
CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_CHAT_WITH_GROUP, script->OnPlayerChat(player, type, lang, msg, group));
}
void ScriptMgr::OnPlayerChat(Player* player, uint32 type, uint32 lang, std::string& msg, Guild* guild)
{
CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_CHAT_WITH_GUILD, script->OnPlayerChat(player, type, lang, msg, guild));
}
void ScriptMgr::OnPlayerChat(Player* player, uint32 type, uint32 lang, std::string& msg, Channel* channel)
{
CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_CHAT_WITH_CHANNEL, script->OnPlayerChat(player, type, lang, msg, channel));
}
void ScriptMgr::OnPlayerEmote(Player* player, uint32 emote) void ScriptMgr::OnPlayerEmote(Player* player, uint32 emote)
{ {
CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_EMOTE, script->OnPlayerEmote(player, emote)); CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_EMOTE, script->OnPlayerEmote(player, emote));
@@ -306,18 +306,8 @@ public:
virtual void OnPlayerDuelEnd(Player* /*winner*/, Player* /*loser*/, DuelCompleteType /*type*/) { } virtual void OnPlayerDuelEnd(Player* /*winner*/, Player* /*loser*/, DuelCompleteType /*type*/) { }
// The following methods are called when a player sends a chat message. // The following methods are called when a player sends a chat message.
virtual void OnPlayerChat(Player* /*player*/, uint32 /*type*/, uint32 /*lang*/, std::string& /*msg*/) { }
virtual void OnPlayerBeforeSendChatMessage(Player* /*player*/, uint32& /*type*/, uint32& /*lang*/, std::string& /*msg*/) { } virtual void OnPlayerBeforeSendChatMessage(Player* /*player*/, uint32& /*type*/, uint32& /*lang*/, std::string& /*msg*/) { }
virtual void OnPlayerChat(Player* /*player*/, uint32 /*type*/, uint32 /*lang*/, std::string& /*msg*/, Player* /*receiver*/) { }
virtual void OnPlayerChat(Player* /*player*/, uint32 /*type*/, uint32 /*lang*/, std::string& /*msg*/, Group* /*group*/) { }
virtual void OnPlayerChat(Player* /*player*/, uint32 /*type*/, uint32 /*lang*/, std::string& /*msg*/, Guild* /*guild*/) { }
virtual void OnPlayerChat(Player* /*player*/, uint32 /*type*/, uint32 /*lang*/, std::string& /*msg*/, Channel* /*channel*/) { }
// Both of the below are called on emote opcodes. // Both of the below are called on emote opcodes.
virtual void OnPlayerEmote(Player* /*player*/, uint32 /*emote*/) { } virtual void OnPlayerEmote(Player* /*player*/, uint32 /*emote*/) { }
-5
View File
@@ -340,12 +340,7 @@ public: /* PlayerScript */
void OnPlayerDuelRequest(Player* target, Player* challenger); void OnPlayerDuelRequest(Player* target, Player* challenger);
void OnPlayerDuelStart(Player* player1, Player* player2); void OnPlayerDuelStart(Player* player1, Player* player2);
void OnPlayerDuelEnd(Player* winner, Player* loser, DuelCompleteType type); void OnPlayerDuelEnd(Player* winner, Player* loser, DuelCompleteType type);
void OnPlayerChat(Player* player, uint32 type, uint32 lang, std::string& msg);
void OnPlayerBeforeSendChatMessage(Player* player, uint32& type, uint32& lang, std::string& msg); void OnPlayerBeforeSendChatMessage(Player* player, uint32& type, uint32& lang, std::string& msg);
void OnPlayerChat(Player* player, uint32 type, uint32 lang, std::string& msg, Player* receiver);
void OnPlayerChat(Player* player, uint32 type, uint32 lang, std::string& msg, Group* group);
void OnPlayerChat(Player* player, uint32 type, uint32 lang, std::string& msg, Guild* guild);
void OnPlayerChat(Player* player, uint32 type, uint32 lang, std::string& msg, Channel* channel);
void OnPlayerEmote(Player* player, uint32 emote); void OnPlayerEmote(Player* player, uint32 emote);
void OnPlayerTextEmote(Player* player, uint32 textEmote, uint32 emoteNum, ObjectGuid guid); void OnPlayerTextEmote(Player* player, uint32 textEmote, uint32 emoteNum, ObjectGuid guid);
void OnPlayerSpellCast(Player* player, Spell* spell, bool skipCheck); void OnPlayerSpellCast(Player* player, Spell* spell, bool skipCheck);
+1 -1
View File
@@ -1377,7 +1377,7 @@ void Spell::SelectImplicitCasterDestTargets(SpellEffIndex effIndex, SpellImplici
float ground = m_caster->GetMapHeight(x, y, z, true); float ground = m_caster->GetMapHeight(x, y, z, true);
float liquidLevel = VMAP_INVALID_HEIGHT_VALUE; float liquidLevel = VMAP_INVALID_HEIGHT_VALUE;
LiquidData const& liquidData = m_caster->GetMap()->GetLiquidData(m_caster->GetPhaseMask(), x, y, z, m_caster->GetCollisionHeight(), MAP_ALL_LIQUIDS); LiquidData const& liquidData = m_caster->GetMap()->GetLiquidData(m_caster->GetPhaseMask(), x, y, z, m_caster->GetCollisionHeight(), {});
if (liquidData.Status) if (liquidData.Status)
liquidLevel = liquidData.Level; liquidLevel = liquidData.Level;
+2 -2
View File
@@ -156,13 +156,13 @@ public:
if (enable) if (enable)
{ {
handler->GetSession()->GetPlayer()->SetCommandStatusOn(CHEAT_WATERWALK); handler->GetSession()->GetPlayer()->SetCommandStatusOn(CHEAT_WATERWALK);
handler->GetSession()->GetPlayer()->SetMovement(MOVE_WATER_WALK); // ON handler->GetSession()->GetPlayer()->SetWaterWalking(true); // ON
handler->SendSysMessage("Waterwalking is ON. You can walk on water."); handler->SendSysMessage("Waterwalking is ON. You can walk on water.");
} }
else else
{ {
handler->GetSession()->GetPlayer()->SetCommandStatusOff(CHEAT_WATERWALK); handler->GetSession()->GetPlayer()->SetCommandStatusOff(CHEAT_WATERWALK);
handler->GetSession()->GetPlayer()->SetMovement(MOVE_LAND_WALK); // OFF handler->GetSession()->GetPlayer()->SetWaterWalking(false); // OFF
handler->SendSysMessage("Waterwalking is OFF. You can't walk on water."); handler->SendSysMessage("Waterwalking is OFF. You can't walk on water.");
} }
+1 -1
View File
@@ -1949,7 +1949,7 @@ public:
// the max level of the new profession. // the max level of the new profession.
uint16 max = maxPureSkill ? *maxPureSkill : targetHasSkill ? target->GetPureMaxSkillValue(skillID) : uint16(level); uint16 max = maxPureSkill ? *maxPureSkill : targetHasSkill ? target->GetPureMaxSkillValue(skillID) : uint16(level);
if (level < 0 || level > max || max < 0) if (level <= 0 || level > max || max <= 0)
{ {
return false; return false;
} }
-1
View File
@@ -219,7 +219,6 @@ public:
{ {
ObjectGuid::LowType guid = sObjectMgr->GenerateCreatureSpawnId(); ObjectGuid::LowType guid = sObjectMgr->GenerateCreatureSpawnId();
CreatureData& data = sObjectMgr->NewOrExistCreatureData(guid); CreatureData& data = sObjectMgr->NewOrExistCreatureData(guid);
data.spawnId = guid;
data.id1 = id; data.id1 = id;
data.phaseMask = chr->GetPhaseMaskForSpawn(); data.phaseMask = chr->GetPhaseMaskForSpawn();
data.posX = chr->GetTransOffsetX(); data.posX = chr->GetTransOffsetX();
+5 -2
View File
@@ -2019,11 +2019,14 @@ class spell_gen_animal_blood : public AuraScript
{ {
// Remove all auras with spell id 46221, except the one currently being applied // Remove all auras with spell id 46221, except the one currently being applied
while (Aura* aur = GetUnitOwner()->GetOwnedAura(SPELL_ANIMAL_BLOOD, ObjectGuid::Empty, ObjectGuid::Empty, 0, GetAura())) while (Aura* aur = GetUnitOwner()->GetOwnedAura(SPELL_ANIMAL_BLOOD, ObjectGuid::Empty, ObjectGuid::Empty, 0, GetAura()))
GetUnitOwner()->RemoveOwnedAura(aur); GetUnitOwner()->RemoveOwnedAura(aur, AURA_REMOVE_BY_EXPIRE);
} }
void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
{ {
if (GetTargetApplication()->GetRemoveMode() == AURA_REMOVE_BY_EXPIRE)
return;
if (Unit* owner = GetUnitOwner()) if (Unit* owner = GetUnitOwner())
if (owner->IsInWater()) if (owner->IsInWater())
owner->CastSpell(owner, SPELL_SPAWN_BLOOD_POOL, true); owner->CastSpell(owner, SPELL_SPAWN_BLOOD_POOL, true);
@@ -2044,7 +2047,7 @@ class spell_spawn_blood_pool : public SpellScript
void SetDest(SpellDestination &dest) void SetDest(SpellDestination &dest)
{ {
Unit* caster = GetCaster(); Unit* caster = GetCaster();
LiquidData liquidStatus = caster->GetMap()->GetLiquidData(caster->GetPhaseMask(), caster->GetPositionX(), caster->GetPositionY(), caster->GetPositionZ(), caster->GetCollisionHeight(), MAP_ALL_LIQUIDS); LiquidData liquidStatus = caster->GetMap()->GetLiquidData(caster->GetPhaseMask(), caster->GetPositionX(), caster->GetPositionY(), caster->GetPositionZ(), caster->GetCollisionHeight(), {});
float level = liquidStatus.Level > INVALID_HEIGHT ? liquidStatus.Level : caster->GetPositionZ(); float level = liquidStatus.Level > INVALID_HEIGHT ? liquidStatus.Level : caster->GetPositionZ();
Position pos = Position(caster->GetPositionX(), caster->GetPositionY(), level, caster->GetOrientation()); Position pos = Position(caster->GetPositionX(), caster->GetPositionY(), level, caster->GetOrientation());
@@ -170,7 +170,7 @@ public:
{ {
QuestStatus QLR = player->GetQuestStatus(QUEST_LAST_RITES); QuestStatus QLR = player->GetQuestStatus(QUEST_LAST_RITES);
QuestStatus QBT = player->GetQuestStatus(QUEST_BREAKING_THROUGH); QuestStatus QBT = player->GetQuestStatus(QUEST_BREAKING_THROUGH);
if (!(QLR == QUEST_STATUS_INCOMPLETE || QLR == QUEST_STATUS_COMPLETE || if (!(QLR == QUEST_STATUS_INCOMPLETE || QLR == QUEST_STATUS_COMPLETE || QLR == QUEST_STATUS_REWARDED ||
QBT == QUEST_STATUS_INCOMPLETE || QBT == QUEST_STATUS_COMPLETE)) QBT == QUEST_STATUS_INCOMPLETE || QBT == QUEST_STATUS_COMPLETE))
return false; return false;
+23 -13
View File
@@ -27,16 +27,16 @@ public:
ChatLogScript() : ChatLogScript() :
PlayerScript("ChatLogScript", PlayerScript("ChatLogScript",
{ {
PLAYERHOOK_ON_CHAT, PLAYERHOOK_CAN_PLAYER_USE_CHAT,
PLAYERHOOK_ON_CHAT_WITH_GROUP, PLAYERHOOK_CAN_PLAYER_USE_PRIVATE_CHAT,
PLAYERHOOK_ON_CHAT_WITH_GUILD, PLAYERHOOK_CAN_PLAYER_USE_GROUP_CHAT,
PLAYERHOOK_ON_CHAT_WITH_CHANNEL, PLAYERHOOK_CAN_PLAYER_USE_GUILD_CHAT,
PLAYERHOOK_ON_CHAT_WITH_RECEIVER PLAYERHOOK_CAN_PLAYER_USE_CHANNEL_CHAT,
}) })
{ {
} }
void OnPlayerChat(Player* player, uint32 type, uint32 lang, std::string& msg) override bool OnPlayerCanUseChat(Player* player, uint32 type, uint32 lang, std::string& msg) override
{ {
std::string logType = ""; std::string logType = "";
std::string chatType = ""; std::string chatType = "";
@@ -56,14 +56,16 @@ public:
chatType = "yells"; chatType = "yells";
break; break;
default: default:
return; return true;
} }
LOG_INFO(logType, "Player {} {} (language {}): {}", LOG_INFO(logType, "Player {} {} (language {}): {}",
player->GetName(), chatType, lang, msg); player->GetName(), chatType, lang, msg);
return true;
} }
void OnPlayerChat(Player* player, uint32 /*type*/, uint32 lang, std::string& msg, Player* receiver) override bool OnPlayerCanUseChat(Player* player, uint32 /*type*/, uint32 lang, std::string& msg, Player* receiver) override
{ {
//! NOTE: //! NOTE:
//! LANG_ADDON can only be sent by client in "PARTY", "RAID", "GUILD", "BATTLEGROUND", "WHISPER" //! LANG_ADDON can only be sent by client in "PARTY", "RAID", "GUILD", "BATTLEGROUND", "WHISPER"
@@ -72,9 +74,11 @@ public:
LOG_INFO(logType + msgType, "Player {} {} {}: {}", LOG_INFO(logType + msgType, "Player {} {} {}: {}",
player->GetName(), msgType, receiver ? receiver->GetName() : "<unknown>", msg); player->GetName(), msgType, receiver ? receiver->GetName() : "<unknown>", msg);
return true;
} }
void OnPlayerChat(Player* player, uint32 type, uint32 lang, std::string& msg, Group* group) override bool OnPlayerCanUseChat(Player* player, uint32 type, uint32 lang, std::string& msg, Group* group) override
{ {
//! NOTE: //! NOTE:
//! LANG_ADDON can only be sent by client in "PARTY", "RAID", "GUILD", "BATTLEGROUND", "WHISPER" //! LANG_ADDON can only be sent by client in "PARTY", "RAID", "GUILD", "BATTLEGROUND", "WHISPER"
@@ -97,7 +101,7 @@ public:
msgType = "bg"; msgType = "bg";
break; break;
default: default:
return; return true;
} }
std::string role = (type == CHAT_MSG_PARTY_LEADER || type == CHAT_MSG_RAID_LEADER || type == CHAT_MSG_BATTLEGROUND_LEADER) ? "Leader player" : "Player"; std::string role = (type == CHAT_MSG_PARTY_LEADER || type == CHAT_MSG_RAID_LEADER || type == CHAT_MSG_BATTLEGROUND_LEADER) ? "Leader player" : "Player";
@@ -106,9 +110,11 @@ public:
LOG_INFO(logType + msgType, "{} {} {} {} with leader {}: {}", LOG_INFO(logType + msgType, "{} {} {} {} with leader {}: {}",
role, player->GetName(), action, msgType, targetGroup, msg); role, player->GetName(), action, msgType, targetGroup, msg);
return true;
} }
void OnPlayerChat(Player* player, uint32 type, uint32 lang, std::string& msg, Guild* guild) override bool OnPlayerCanUseChat(Player* player, uint32 type, uint32 lang, std::string& msg, Guild* guild) override
{ {
//! NOTE: //! NOTE:
//! LANG_ADDON can only be sent by client in "PARTY", "RAID", "GUILD", "BATTLEGROUND", "WHISPER" //! LANG_ADDON can only be sent by client in "PARTY", "RAID", "GUILD", "BATTLEGROUND", "WHISPER"
@@ -124,14 +130,16 @@ public:
msgType = "guild.officer"; msgType = "guild.officer";
break; break;
default: default:
return; return true;
} }
LOG_INFO(logType + msgType, "Player {} tells {} \"{}\": {}", LOG_INFO(logType + msgType, "Player {} tells {} \"{}\": {}",
player->GetName(), msgType, guild ? guild->GetName() : "<unknown>", msg); player->GetName(), msgType, guild ? guild->GetName() : "<unknown>", msg);
return true;
} }
void OnPlayerChat(Player* player, uint32 /*type*/, uint32 /*lang*/, std::string& msg, Channel* channel) override bool OnPlayerCanUseChat(Player* player, uint32 /*type*/, uint32 /*lang*/, std::string& msg, Channel* channel) override
{ {
bool isSystem = channel && bool isSystem = channel &&
(channel->HasFlag(CHANNEL_FLAG_TRADE) || (channel->HasFlag(CHANNEL_FLAG_TRADE) ||
@@ -152,6 +160,8 @@ public:
LOG_INFO("chat.channel." + channelName, "Player {} tells channel {}: {}", LOG_INFO("chat.channel." + channelName, "Player {} tells channel {}: {}",
player->GetName(), channelName, msg); player->GetName(), channelName, msg);
} }
return true;
} }
}; };