fix(Core/Pathfinding): Creatures regen health, spells LOD (#4509)

This commit is contained in:
Footman
2021-02-10 02:37:05 +03:00
committed by GitHub
parent 98a61b71e5
commit 522eb9a7e4
12 changed files with 132 additions and 115 deletions
@@ -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()); }
+6 -1
View File
@@ -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();
} }
+2 -9
View File
@@ -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;
} }
-6
View File
@@ -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
+1
View File
@@ -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
}; };
+1
View File
@@ -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
# #
################################################################################################### ###################################################################################################