fix(Core/Pathfinding): Creatures regen health, spells LOD (#4509)
This commit is contained in:
@@ -641,7 +641,7 @@ void Creature::Update(uint32 diff)
|
|||||||
// regenerate health if not in combat or if polymorphed)
|
// regenerate health if not in combat or if polymorphed)
|
||||||
if (!IsInCombat() || IsPolymorphed())
|
if (!IsInCombat() || IsPolymorphed())
|
||||||
RegenerateHealth();
|
RegenerateHealth();
|
||||||
else if (CanNotReachTarget())
|
else if (IsNotReachableAndNeedRegen())
|
||||||
{
|
{
|
||||||
// regenerate health if cannot reach the target and the setting is set to do so.
|
// regenerate health if cannot reach the target and the setting is set to do so.
|
||||||
// this allows to disable the health regen of raid bosses if pathfinding has issues for whatever reason
|
// this allows to disable the health regen of raid bosses if pathfinding has issues for whatever reason
|
||||||
@@ -666,7 +666,7 @@ void Creature::Update(uint32 diff)
|
|||||||
if (CanNotReachTarget() && !IsInEvadeMode() && !GetMap()->IsRaid())
|
if (CanNotReachTarget() && !IsInEvadeMode() && !GetMap()->IsRaid())
|
||||||
{
|
{
|
||||||
m_cannotReachTimer += diff;
|
m_cannotReachTimer += diff;
|
||||||
if (m_cannotReachTimer >= (sWorld->getIntConfig(CONFIG_NPC_EVADE_IF_NOT_REACHABLE)*IN_MILLISECONDS) && IsAIEnabled)
|
if (IsNotReachable() && IsAIEnabled)
|
||||||
{
|
{
|
||||||
AI()->EnterEvadeMode();
|
AI()->EnterEvadeMode();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -688,6 +688,8 @@ public:
|
|||||||
|
|
||||||
void SetCannotReachTarget(bool cannotReach);
|
void SetCannotReachTarget(bool cannotReach);
|
||||||
[[nodiscard]] bool CanNotReachTarget() const { return m_cannotReachTarget; }
|
[[nodiscard]] bool CanNotReachTarget() const { return m_cannotReachTarget; }
|
||||||
|
[[nodiscard]] bool IsNotReachable() const { return (m_cannotReachTimer >= (sWorld->getIntConfig(CONFIG_NPC_EVADE_IF_NOT_REACHABLE) * IN_MILLISECONDS)) && m_cannotReachTarget; }
|
||||||
|
[[nodiscard]] bool IsNotReachableAndNeedRegen() const { return (m_cannotReachTimer >= (sWorld->getIntConfig(CONFIG_NPC_REGEN_TIME_IF_NOT_REACHABLE_IN_RAID) * IN_MILLISECONDS)) && m_cannotReachTarget; }
|
||||||
|
|
||||||
void SetPosition(float x, float y, float z, float o);
|
void SetPosition(float x, float y, float z, float o);
|
||||||
void SetPosition(const Position& pos) { SetPosition(pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), pos.GetOrientation()); }
|
void SetPosition(const Position& pos) { SetPosition(pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), pos.GetOrientation()); }
|
||||||
|
|||||||
@@ -553,7 +553,7 @@ void Unit::UpdateSplinePosition()
|
|||||||
|
|
||||||
void Unit::DisableSpline()
|
void Unit::DisableSpline()
|
||||||
{
|
{
|
||||||
m_movementInfo.RemoveMovementFlag(MovementFlags(MOVEMENTFLAG_SPLINE_ENABLED | MOVEMENTFLAG_FORWARD));
|
m_movementInfo.RemoveMovementFlag(MovementFlags(MOVEMENTFLAG_SPLINE_ENABLED | MOVEMENTFLAG_FORWARD | MOVEMENTFLAG_BACKWARD));
|
||||||
movespline->_Interrupt();
|
movespline->_Interrupt();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -13685,6 +13685,7 @@ void Unit::setDeathState(DeathState s, bool despawn)
|
|||||||
// remove aurastates allowing special moves
|
// remove aurastates allowing special moves
|
||||||
ClearAllReactives();
|
ClearAllReactives();
|
||||||
ClearDiminishings();
|
ClearDiminishings();
|
||||||
|
|
||||||
GetMotionMaster()->Clear(false);
|
GetMotionMaster()->Clear(false);
|
||||||
GetMotionMaster()->MoveIdle();
|
GetMotionMaster()->MoveIdle();
|
||||||
|
|
||||||
@@ -15894,6 +15895,10 @@ void Unit::StopMoving()
|
|||||||
if (movespline->Finalized())
|
if (movespline->Finalized())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
// Update position now since Stop does not start a new movement that can be updated later
|
||||||
|
if (movespline->HasStarted())
|
||||||
|
UpdateSplinePosition();
|
||||||
|
|
||||||
Movement::MoveSplineInit init(this);
|
Movement::MoveSplineInit init(this);
|
||||||
init.Stop();
|
init.Stop();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,6 @@
|
|||||||
#include "Group.h"
|
#include "Group.h"
|
||||||
#include "InstanceScript.h"
|
#include "InstanceScript.h"
|
||||||
#include "MapInstanced.h"
|
#include "MapInstanced.h"
|
||||||
#include "MapManager.h"
|
|
||||||
#include "ObjectAccessor.h"
|
#include "ObjectAccessor.h"
|
||||||
#include "ObjectMgr.h"
|
#include "ObjectMgr.h"
|
||||||
#include "Pet.h"
|
#include "Pet.h"
|
||||||
@@ -3577,8 +3576,6 @@ bool Map::CheckCollisionAndGetValidCoords(const WorldObject* source, float start
|
|||||||
// collision check
|
// collision check
|
||||||
bool collided = false;
|
bool collided = false;
|
||||||
|
|
||||||
float angle = getAngle(destX, destY, startX, startY);
|
|
||||||
|
|
||||||
// check static LOS
|
// check static LOS
|
||||||
float halfHeight = source->GetCollisionHeight() * 0.5f;
|
float halfHeight = source->GetCollisionHeight() * 0.5f;
|
||||||
|
|
||||||
@@ -3588,15 +3585,13 @@ bool Map::CheckCollisionAndGetValidCoords(const WorldObject* source, float start
|
|||||||
bool col = VMAP::VMapFactory::createOrGetVMapManager()->getObjectHitPos(source->GetMapId(),
|
bool col = VMAP::VMapFactory::createOrGetVMapManager()->getObjectHitPos(source->GetMapId(),
|
||||||
startX, startY, startZ + halfHeight,
|
startX, startY, startZ + halfHeight,
|
||||||
destX, destY, destZ + halfHeight,
|
destX, destY, destZ + halfHeight,
|
||||||
destX, destY, destZ, -0.5f);
|
destX, destY, destZ, -CONTACT_DISTANCE);
|
||||||
|
|
||||||
destZ -= halfHeight;
|
destZ -= halfHeight;
|
||||||
|
|
||||||
// Collided with static LOS object, move back to collision point
|
// Collided with static LOS object, move back to collision point
|
||||||
if (col)
|
if (col)
|
||||||
{
|
{
|
||||||
destX -= CONTACT_DISTANCE * std::cos(angle);
|
|
||||||
destY -= CONTACT_DISTANCE * std::sin(angle);
|
|
||||||
collided = true;
|
collided = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3605,15 +3600,13 @@ bool Map::CheckCollisionAndGetValidCoords(const WorldObject* source, float start
|
|||||||
bool col = source->GetMap()->getObjectHitPos(source->GetPhaseMask(),
|
bool col = source->GetMap()->getObjectHitPos(source->GetPhaseMask(),
|
||||||
startX, startY, startZ + halfHeight,
|
startX, startY, startZ + halfHeight,
|
||||||
destX, destY, destZ + halfHeight,
|
destX, destY, destZ + halfHeight,
|
||||||
destX, destY, destZ, -0.5f);
|
destX, destY, destZ, -CONTACT_DISTANCE);
|
||||||
|
|
||||||
destZ -= halfHeight;
|
destZ -= halfHeight;
|
||||||
|
|
||||||
// Collided with a gameobject, move back to collision point
|
// Collided with a gameobject, move back to collision point
|
||||||
if (col)
|
if (col)
|
||||||
{
|
{
|
||||||
destX -= CONTACT_DISTANCE * std::cos(angle);
|
|
||||||
destY -= CONTACT_DISTANCE * std::sin(angle);
|
|
||||||
collided = true;
|
collided = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,11 +7,6 @@
|
|||||||
#ifndef ACORE_MAP_H
|
#ifndef ACORE_MAP_H
|
||||||
#define ACORE_MAP_H
|
#define ACORE_MAP_H
|
||||||
|
|
||||||
// Pathfinding
|
|
||||||
#include "DetourAlloc.h"
|
|
||||||
#include "DetourNavMesh.h"
|
|
||||||
#include "DetourNavMeshQuery.h"
|
|
||||||
|
|
||||||
#include "Define.h"
|
#include "Define.h"
|
||||||
#include <ace/RW_Thread_Mutex.h>
|
#include <ace/RW_Thread_Mutex.h>
|
||||||
#include <ace/Thread_Mutex.h>
|
#include <ace/Thread_Mutex.h>
|
||||||
@@ -27,7 +22,6 @@
|
|||||||
#include "GameObjectModel.h"
|
#include "GameObjectModel.h"
|
||||||
#include "PathGenerator.h"
|
#include "PathGenerator.h"
|
||||||
#include "ObjectDefines.h"
|
#include "ObjectDefines.h"
|
||||||
#include "Log.h"
|
|
||||||
#include "DataMap.h"
|
#include "DataMap.h"
|
||||||
#include <bitset>
|
#include <bitset>
|
||||||
#include <list>
|
#include <list>
|
||||||
|
|||||||
@@ -12,7 +12,6 @@
|
|||||||
#include "Log.h"
|
#include "Log.h"
|
||||||
#include "DisableMgr.h"
|
#include "DisableMgr.h"
|
||||||
#include "DetourCommon.h"
|
#include "DetourCommon.h"
|
||||||
#include "DetourExtended.h"
|
|
||||||
#include "Geometry.h"
|
#include "Geometry.h"
|
||||||
|
|
||||||
////////////////// PathGenerator //////////////////
|
////////////////// PathGenerator //////////////////
|
||||||
@@ -189,23 +188,31 @@ void PathGenerator::BuildPolyPath(G3D::Vector3 const& startPos, G3D::Vector3 con
|
|||||||
// we may need a better number here
|
// we may need a better number here
|
||||||
bool startFarFromPoly = distToStartPoly > 7.0f;
|
bool startFarFromPoly = distToStartPoly > 7.0f;
|
||||||
bool endFarFromPoly = distToEndPoly > 7.0f;
|
bool endFarFromPoly = distToEndPoly > 7.0f;
|
||||||
|
|
||||||
// create a shortcut if the path begins or end too far
|
// create a shortcut if the path begins or end too far
|
||||||
// away from the desired path points.
|
// away from the desired path points.
|
||||||
// swimming creatures should not use a shortcut
|
// swimming creatures should not use a shortcut
|
||||||
// because exiting the water must be done following a proper path
|
// because exiting the water must be done following a proper path
|
||||||
// we just need to remove/normalize paths between 2 adjacent points
|
// we just need to remove/normalize paths between 2 adjacent points
|
||||||
if ((!creature || !creature->CanSwim() || !creature->IsInWater() || _useRaycast)
|
if (startFarFromPoly || endFarFromPoly)
|
||||||
&& (startFarFromPoly || endFarFromPoly))
|
|
||||||
{
|
{
|
||||||
bool buildShotrcut = false;
|
bool buildShotrcut = false;
|
||||||
|
|
||||||
|
bool isUnderWaterStart = _source->GetMap()->IsUnderWater(startPos.x, startPos.y, startPos.z);
|
||||||
|
bool isUnderWaterEnd = _source->GetMap()->IsUnderWater(endPos.x, endPos.y, endPos.z);
|
||||||
|
bool isFarUnderWater = startFarFromPoly ? isUnderWaterStart : isUnderWaterEnd;
|
||||||
|
|
||||||
Unit const* _sourceUnit = _source->ToUnit();
|
Unit const* _sourceUnit = _source->ToUnit();
|
||||||
if (_useRaycast ||
|
|
||||||
(_sourceUnit && (_sourceUnit->CanFly() || (_sourceUnit->IsFalling() && endPos.z < startPos.z)))
|
if (_sourceUnit)
|
||||||
)
|
{
|
||||||
|
bool isUnderWater = (_sourceUnit->CanSwim() && isUnderWaterStart && isUnderWaterEnd) || (isFarUnderWater && _useRaycast);
|
||||||
|
|
||||||
|
if (isUnderWater || _sourceUnit->CanFly() || (_sourceUnit->IsFalling() && endPos.z < startPos.z))
|
||||||
{
|
{
|
||||||
buildShotrcut = true;
|
buildShotrcut = true;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (buildShotrcut)
|
if (buildShotrcut)
|
||||||
{
|
{
|
||||||
@@ -216,7 +223,8 @@ void PathGenerator::BuildPolyPath(G3D::Vector3 const& startPos, G3D::Vector3 con
|
|||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
|
if (!isFarUnderWater)
|
||||||
{
|
{
|
||||||
float closestPoint[VERTEX_SIZE];
|
float closestPoint[VERTEX_SIZE];
|
||||||
// we may want to use closestPointOnPolyBoundary instead
|
// we may want to use closestPointOnPolyBoundary instead
|
||||||
|
|||||||
@@ -126,6 +126,7 @@ bool ChaseMovementGenerator<T>::DoUpdate(T* owner, uint32 time_diff)
|
|||||||
{
|
{
|
||||||
cOwner->SetCannotReachTarget(true);
|
cOwner->SetCannotReachTarget(true);
|
||||||
cOwner->StopMoving();
|
cOwner->StopMoving();
|
||||||
|
i_path = nullptr;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -112,6 +112,10 @@ namespace Movement
|
|||||||
|
|
||||||
bool onTransport;
|
bool onTransport;
|
||||||
[[nodiscard]] std::string ToString() const;
|
[[nodiscard]] std::string ToString() const;
|
||||||
|
[[nodiscard]] bool HasStarted() const
|
||||||
|
{
|
||||||
|
return time_passed > 0;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
#endif // TRINITYSERVER_MOVEPLINE_H
|
#endif // TRINITYSERVER_MOVEPLINE_H
|
||||||
|
|||||||
@@ -373,6 +373,7 @@ enum WorldIntConfigs
|
|||||||
CONFIG_GM_LEVEL_CHANNEL_MODERATION,
|
CONFIG_GM_LEVEL_CHANNEL_MODERATION,
|
||||||
CONFIG_TOGGLE_XP_COST,
|
CONFIG_TOGGLE_XP_COST,
|
||||||
CONFIG_NPC_EVADE_IF_NOT_REACHABLE,
|
CONFIG_NPC_EVADE_IF_NOT_REACHABLE,
|
||||||
|
CONFIG_NPC_REGEN_TIME_IF_NOT_REACHABLE_IN_RAID,
|
||||||
INT_CONFIG_VALUE_COUNT
|
INT_CONFIG_VALUE_COUNT
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1404,6 +1404,7 @@ void World::LoadConfigSettings(bool reload)
|
|||||||
m_int_configs[CONFIG_WAYPOINT_MOVEMENT_STOP_TIME_FOR_PLAYER] = sConfigMgr->GetIntDefault("WaypointMovementStopTimeForPlayer", 120);
|
m_int_configs[CONFIG_WAYPOINT_MOVEMENT_STOP_TIME_FOR_PLAYER] = sConfigMgr->GetIntDefault("WaypointMovementStopTimeForPlayer", 120);
|
||||||
|
|
||||||
m_int_configs[CONFIG_NPC_EVADE_IF_NOT_REACHABLE] = sConfigMgr->GetIntDefault("NpcEvadeIfTargetIsUnreachable", 5);
|
m_int_configs[CONFIG_NPC_EVADE_IF_NOT_REACHABLE] = sConfigMgr->GetIntDefault("NpcEvadeIfTargetIsUnreachable", 5);
|
||||||
|
m_int_configs[CONFIG_NPC_REGEN_TIME_IF_NOT_REACHABLE_IN_RAID] = sConfigMgr->GetIntDefault("NpcRegenHPTimeIfTargetIsUnreachable", 10);
|
||||||
m_bool_configs[CONFIG_REGEN_HP_CANNOT_REACH_TARGET_IN_RAID] = sConfigMgr->GetBoolDefault("NpcRegenHPIfTargetIsUnreachable", true);
|
m_bool_configs[CONFIG_REGEN_HP_CANNOT_REACH_TARGET_IN_RAID] = sConfigMgr->GetBoolDefault("NpcRegenHPIfTargetIsUnreachable", true);
|
||||||
|
|
||||||
//Debug
|
//Debug
|
||||||
|
|||||||
@@ -1967,6 +1967,14 @@ NpcEvadeIfTargetIsUnreachable = 5
|
|||||||
|
|
||||||
NpcRegenHPIfTargetIsUnreachable = 1
|
NpcRegenHPIfTargetIsUnreachable = 1
|
||||||
|
|
||||||
|
|
||||||
|
# NpcRegenHPTimeIfTargetIsUnreachable
|
||||||
|
# Description: Specifies the time (in seconds) that a creature whom target
|
||||||
|
# is unreachable in raid to end up regenerate health.
|
||||||
|
# Default: 10
|
||||||
|
|
||||||
|
NpcRegenHPTimeIfTargetIsUnreachable = 10
|
||||||
|
|
||||||
#
|
#
|
||||||
###################################################################################################
|
###################################################################################################
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user