mirror of
https://github.com/SapphireServer/Sapphire.git
synced 2025-04-28 15:17:46 +00:00
Detour crowd experiments
This commit is contained in:
parent
0527a28e14
commit
018096266a
9 changed files with 155 additions and 8 deletions
|
@ -283,8 +283,11 @@ bool Sapphire::Entity::BNpc::moveTo( const FFXIVARR_POSITION3& pos )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
step();
|
step();
|
||||||
|
auto pos1 = pNaviProvider->getMovePos( *this );
|
||||||
|
|
||||||
|
Logger::debug( "{} {} {}", pos1.x, pos1.y, pos1.z );
|
||||||
|
setPos( pos1 );
|
||||||
m_pCurrentZone->updateActorPosition( *this );
|
m_pCurrentZone->updateActorPosition( *this );
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -471,6 +474,14 @@ void Sapphire::Entity::BNpc::update( uint64_t tickCount )
|
||||||
|
|
||||||
case BNpcState::Roaming:
|
case BNpcState::Roaming:
|
||||||
{
|
{
|
||||||
|
auto pNaviMgr = m_pFw->get< World::Manager::NaviMgr >();
|
||||||
|
auto pNaviProvider = pNaviMgr->getNaviProvider( m_pCurrentZone->getBgPath() );
|
||||||
|
|
||||||
|
if( !pNaviProvider )
|
||||||
|
{
|
||||||
|
pNaviProvider->setMoveTarget( *this, m_roamPos );
|
||||||
|
}
|
||||||
|
|
||||||
if( moveTo( m_roamPos ) )
|
if( moveTo( m_roamPos ) )
|
||||||
{
|
{
|
||||||
m_lastRoamTargetReached = Util::getTimeSeconds();
|
m_lastRoamTargetReached = Util::getTimeSeconds();
|
||||||
|
|
|
@ -702,3 +702,13 @@ void Sapphire::Entity::Chara::setDirectorId( uint32_t directorId )
|
||||||
{
|
{
|
||||||
m_directorId = directorId;
|
m_directorId = directorId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t Sapphire::Entity::Chara::getAgentId() const
|
||||||
|
{
|
||||||
|
return m_agentId;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Sapphire::Entity::Chara::setAgentId( uint32_t agentId )
|
||||||
|
{
|
||||||
|
m_agentId = agentId;
|
||||||
|
}
|
||||||
|
|
|
@ -128,6 +128,9 @@ namespace Sapphire::Entity
|
||||||
std::map< uint8_t, StatusEffect::StatusEffectPtr > m_statusEffectMap;
|
std::map< uint8_t, StatusEffect::StatusEffectPtr > m_statusEffectMap;
|
||||||
FrameworkPtr m_pFw;
|
FrameworkPtr m_pFw;
|
||||||
|
|
||||||
|
/*! Detour Crowd AgentId */
|
||||||
|
uint32_t m_agentId;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Chara( Common::ObjKind type, FrameworkPtr pFw );
|
Chara( Common::ObjKind type, FrameworkPtr pFw );
|
||||||
|
|
||||||
|
@ -269,6 +272,9 @@ namespace Sapphire::Entity
|
||||||
uint32_t getDirectorId() const;
|
uint32_t getDirectorId() const;
|
||||||
void setDirectorId( uint32_t directorId );
|
void setDirectorId( uint32_t directorId );
|
||||||
|
|
||||||
|
uint32_t getAgentId() const;
|
||||||
|
void setAgentId( uint32_t agentId );
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,7 +33,8 @@ set_target_properties( world
|
||||||
target_link_libraries( world
|
target_link_libraries( world
|
||||||
PUBLIC
|
PUBLIC
|
||||||
common
|
common
|
||||||
Detour)
|
Detour
|
||||||
|
DetourCrowd )
|
||||||
target_include_directories( world
|
target_include_directories( world
|
||||||
PUBLIC
|
PUBLIC
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}"
|
"${CMAKE_CURRENT_SOURCE_DIR}"
|
||||||
|
|
|
@ -180,9 +180,12 @@ bool Sapphire::World::Manager::TerritoryMgr::createDefaultTerritories()
|
||||||
|
|
||||||
uint32_t guid = getNextInstanceId();
|
uint32_t guid = getNextInstanceId();
|
||||||
|
|
||||||
auto pNaviMgr = framework()->get< Manager::NaviMgr >();
|
auto pZone = make_Zone( territoryTypeId, guid, territoryInfo->name, pPlaceName->name, framework() );
|
||||||
|
pZone->init();
|
||||||
|
|
||||||
std::string bgPath = territoryInfo->bg;
|
std::string bgPath = territoryInfo->bg;
|
||||||
bool hasNaviMesh = pNaviMgr->setupTerritory( bgPath );
|
|
||||||
|
bool hasNaviMesh = pZone->getNaviProvider() != nullptr;
|
||||||
|
|
||||||
Logger::info( "{0}\t{1}\t{2}\t{3:<10}\t{4}\t{5}\t{6}",
|
Logger::info( "{0}\t{1}\t{2}\t{3:<10}\t{4}\t{5}\t{6}",
|
||||||
territoryTypeId,
|
territoryTypeId,
|
||||||
|
@ -193,9 +196,6 @@ bool Sapphire::World::Manager::TerritoryMgr::createDefaultTerritories()
|
||||||
hasNaviMesh ? "NAVI" : "",
|
hasNaviMesh ? "NAVI" : "",
|
||||||
pPlaceName->name );
|
pPlaceName->name );
|
||||||
|
|
||||||
auto pZone = make_Zone( territoryTypeId, guid, territoryInfo->name, pPlaceName->name, framework() );
|
|
||||||
pZone->init();
|
|
||||||
|
|
||||||
InstanceIdToZonePtrMap instanceMap;
|
InstanceIdToZonePtrMap instanceMap;
|
||||||
instanceMap[ guid ] = pZone;
|
instanceMap[ guid ] = pZone;
|
||||||
m_guIdToZonePtrMap[ guid ] = pZone;
|
m_guIdToZonePtrMap[ guid ] = pZone;
|
||||||
|
|
|
@ -4,6 +4,9 @@
|
||||||
#include <Logging/Logger.h>
|
#include <Logging/Logger.h>
|
||||||
#include <ServerMgr.h>
|
#include <ServerMgr.h>
|
||||||
|
|
||||||
|
#include "Actor/Actor.h"
|
||||||
|
#include "Actor/Chara.h"
|
||||||
|
|
||||||
#include <Manager/RNGMgr.h>
|
#include <Manager/RNGMgr.h>
|
||||||
|
|
||||||
#include "NaviProvider.h"
|
#include "NaviProvider.h"
|
||||||
|
@ -40,6 +43,11 @@ bool Sapphire::World::Navi::NaviProvider::init()
|
||||||
if( !loadMesh( baseMesh.string() ) )
|
if( !loadMesh( baseMesh.string() ) )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
m_pCrowd = std::make_unique< dtCrowd >();
|
||||||
|
|
||||||
|
if( !m_pCrowd->init( 1000, 10.f, m_naviMesh ) )
|
||||||
|
return false;
|
||||||
|
|
||||||
initQuery();
|
initQuery();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -521,3 +529,65 @@ bool Sapphire::World::Navi::NaviProvider::loadMesh( const std::string& path )
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int32_t Sapphire::World::Navi::NaviProvider::addAgent( Entity::Chara& chara )
|
||||||
|
{
|
||||||
|
dtCrowdAgentParams params;
|
||||||
|
std::memset( ¶ms, 0, sizeof( params ) );
|
||||||
|
params.height = 7.f;
|
||||||
|
params.maxAcceleration = 8.f;
|
||||||
|
params.maxSpeed = 3.5f;
|
||||||
|
params.radius = 5.f;
|
||||||
|
params.collisionQueryRange = params.radius * 12.0f;
|
||||||
|
params.pathOptimizationRange = params.radius * 30.0f;
|
||||||
|
|
||||||
|
float position[] = { chara.getPos().x, chara.getPos().y, chara.getPos().z };
|
||||||
|
return m_pCrowd->addAgent( position, ¶ms );
|
||||||
|
}
|
||||||
|
|
||||||
|
void Sapphire::World::Navi::NaviProvider::updateCrowd( float timeInSeconds )
|
||||||
|
{
|
||||||
|
dtCrowdAgentDebugInfo info;
|
||||||
|
m_pCrowd->update( timeInSeconds, &info );
|
||||||
|
}
|
||||||
|
|
||||||
|
void Sapphire::World::Navi::NaviProvider::removeAgent( Sapphire::Entity::Chara& chara )
|
||||||
|
{
|
||||||
|
m_pCrowd->removeAgent( chara.getAgentId() );
|
||||||
|
}
|
||||||
|
|
||||||
|
void Sapphire::World::Navi::NaviProvider::calcVel( float* vel, const float* pos, const float* tgt, const float speed )
|
||||||
|
{
|
||||||
|
dtVsub( vel, tgt, pos );
|
||||||
|
vel[ 1 ] = 0.0;
|
||||||
|
dtVnormalize( vel );
|
||||||
|
dtVscale( vel, vel, speed );
|
||||||
|
}
|
||||||
|
|
||||||
|
void Sapphire::World::Navi::NaviProvider::setMoveTarget( Entity::Chara& chara,
|
||||||
|
const Sapphire::Common::FFXIVARR_POSITION3& endPos )
|
||||||
|
{
|
||||||
|
// Find nearest point on navmesh and set move request to that location.
|
||||||
|
dtNavMeshQuery* navquery = m_naviMeshQuery;
|
||||||
|
|
||||||
|
const dtQueryFilter* filter = m_pCrowd->getFilter( 0 );
|
||||||
|
const float* halfExtents = m_pCrowd->getQueryExtents();
|
||||||
|
|
||||||
|
float vel[ 3 ];
|
||||||
|
float p[ 3 ] = { chara.getPos().x, chara.getPos().y, chara.getPos().z };
|
||||||
|
|
||||||
|
const dtCrowdAgent* ag = m_pCrowd->getAgent( chara.getAgentId() );
|
||||||
|
if( ag && ag->active )
|
||||||
|
{
|
||||||
|
calcVel( vel, ag->npos, p, ag->params.maxSpeed );
|
||||||
|
m_pCrowd->requestMoveVelocity( chara.getAgentId(), vel );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Sapphire::Common::FFXIVARR_POSITION3 Sapphire::World::Navi::NaviProvider::getMovePos( Entity::Chara& chara )
|
||||||
|
{
|
||||||
|
const dtCrowdAgent* ag = m_pCrowd->getAgent( chara.getAgentId() );
|
||||||
|
if( !ag )
|
||||||
|
return { 0.f, 0.f, 0.f };
|
||||||
|
return { ag->npos[ 0 ], ag->npos[ 1 ], ag->npos[ 2 ] };
|
||||||
|
}
|
|
@ -5,6 +5,7 @@
|
||||||
#include "ForwardsZone.h"
|
#include "ForwardsZone.h"
|
||||||
#include <recastnavigation/Detour/Include/DetourNavMesh.h>
|
#include <recastnavigation/Detour/Include/DetourNavMesh.h>
|
||||||
#include <recastnavigation/Detour/Include/DetourNavMeshQuery.h>
|
#include <recastnavigation/Detour/Include/DetourNavMeshQuery.h>
|
||||||
|
#include <recastnavigation/DetourCrowd/Include/DetourCrowd.h>
|
||||||
|
|
||||||
namespace Sapphire::World::Navi
|
namespace Sapphire::World::Navi
|
||||||
{
|
{
|
||||||
|
@ -47,11 +48,24 @@ namespace Sapphire::World::Navi
|
||||||
|
|
||||||
bool hasNaviMesh() const;
|
bool hasNaviMesh() const;
|
||||||
|
|
||||||
|
int32_t addAgent( Entity::Chara& chara );
|
||||||
|
|
||||||
|
void removeAgent( Entity::Chara& chara );
|
||||||
|
|
||||||
|
void updateCrowd( float timeInSeconds );
|
||||||
|
|
||||||
|
static void calcVel( float* vel, const float* pos, const float* tgt, const float speed );
|
||||||
|
|
||||||
|
void setMoveTarget( Entity::Chara& chara, const Common::FFXIVARR_POSITION3& endPos );
|
||||||
|
|
||||||
|
Common::FFXIVARR_POSITION3 getMovePos( Entity::Chara& chara );
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
std::string m_internalName;
|
std::string m_internalName;
|
||||||
|
|
||||||
dtNavMesh* m_naviMesh;
|
dtNavMesh* m_naviMesh;
|
||||||
dtNavMeshQuery* m_naviMeshQuery;
|
dtNavMeshQuery* m_naviMeshQuery;
|
||||||
|
std::unique_ptr< dtCrowd > m_pCrowd;
|
||||||
|
|
||||||
float m_polyFindRange[ 3 ];
|
float m_polyFindRange[ 3 ];
|
||||||
|
|
||||||
|
@ -63,6 +77,8 @@ namespace Sapphire::World::Navi
|
||||||
const dtPolyRef* path, const int32_t pathSize, float* steerPos, uint8_t& steerPosFlag,
|
const dtPolyRef* path, const int32_t pathSize, float* steerPos, uint8_t& steerPosFlag,
|
||||||
dtPolyRef& steerPosRef, float* outPoints = 0, int32_t* outPointCount = 0 );
|
dtPolyRef& steerPosRef, float* outPoints = 0, int32_t* outPointCount = 0 );
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
FrameworkPtr m_pFw;
|
FrameworkPtr m_pFw;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
#include "InstanceContent.h"
|
#include "InstanceContent.h"
|
||||||
#include "QuestBattle.h"
|
#include "QuestBattle.h"
|
||||||
#include "Manager/TerritoryMgr.h"
|
#include "Manager/TerritoryMgr.h"
|
||||||
|
#include "Navi/Naviprovider.h"
|
||||||
|
|
||||||
#include "Session.h"
|
#include "Session.h"
|
||||||
#include "Actor/Chara.h"
|
#include "Actor/Chara.h"
|
||||||
|
@ -41,7 +42,8 @@
|
||||||
#include "Zone.h"
|
#include "Zone.h"
|
||||||
#include "Framework.h"
|
#include "Framework.h"
|
||||||
|
|
||||||
#include <Manager/RNGMgr.h>
|
#include "Manager/RNGMgr.h"
|
||||||
|
#include "Manager/NaviMgr.h"
|
||||||
|
|
||||||
using namespace Sapphire::Common;
|
using namespace Sapphire::Common;
|
||||||
using namespace Sapphire::Network::Packets;
|
using namespace Sapphire::Network::Packets;
|
||||||
|
@ -129,6 +131,11 @@ bool Sapphire::Zone::init()
|
||||||
// all good
|
// all good
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto pNaviMgr = m_pFw->get< World::Manager::NaviMgr >();
|
||||||
|
pNaviMgr->setupTerritory( m_territoryTypeInfo->bg );
|
||||||
|
|
||||||
|
m_pNaviProvider = pNaviMgr->getNaviProvider( m_territoryTypeInfo->bg );
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -231,10 +238,16 @@ void Sapphire::Zone::pushActor( Entity::ActorPtr pActor )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int32_t agentId = -1;
|
||||||
|
|
||||||
if( pActor->isPlayer() )
|
if( pActor->isPlayer() )
|
||||||
{
|
{
|
||||||
auto pPlayer = pActor->getAsPlayer();
|
auto pPlayer = pActor->getAsPlayer();
|
||||||
|
|
||||||
|
if( m_pNaviProvider )
|
||||||
|
agentId = m_pNaviProvider->addAgent( *pPlayer );
|
||||||
|
pPlayer->setAgentId( agentId );
|
||||||
|
|
||||||
auto pServerZone = m_pFw->get< World::ServerMgr >();
|
auto pServerZone = m_pFw->get< World::ServerMgr >();
|
||||||
m_playerMap[ pPlayer->getId() ] = pPlayer;
|
m_playerMap[ pPlayer->getId() ] = pPlayer;
|
||||||
updateCellActivity( cx, cy, 2 );
|
updateCellActivity( cx, cy, 2 );
|
||||||
|
@ -243,6 +256,10 @@ void Sapphire::Zone::pushActor( Entity::ActorPtr pActor )
|
||||||
{
|
{
|
||||||
auto pBNpc = pActor->getAsBNpc();
|
auto pBNpc = pActor->getAsBNpc();
|
||||||
|
|
||||||
|
if( m_pNaviProvider )
|
||||||
|
agentId = m_pNaviProvider->addAgent( *pBNpc );
|
||||||
|
pBNpc->setAgentId( agentId );
|
||||||
|
|
||||||
m_bNpcMap[ pBNpc->getId() ] = pBNpc;
|
m_bNpcMap[ pBNpc->getId() ] = pBNpc;
|
||||||
updateCellActivity( cx, cy, 2 );
|
updateCellActivity( cx, cy, 2 );
|
||||||
|
|
||||||
|
@ -263,6 +280,9 @@ void Sapphire::Zone::removeActor( Entity::ActorPtr pActor )
|
||||||
if( pActor->isPlayer() )
|
if( pActor->isPlayer() )
|
||||||
{
|
{
|
||||||
|
|
||||||
|
if( m_pNaviProvider )
|
||||||
|
m_pNaviProvider->removeAgent( *pActor->getAsChara() );
|
||||||
|
|
||||||
// If it's a player and he's inside boundaries - update his nearby cells
|
// If it's a player and he's inside boundaries - update his nearby cells
|
||||||
if( pActor->getPos().x <= _maxX && pActor->getPos().x >= _minX &&
|
if( pActor->getPos().x <= _maxX && pActor->getPos().x >= _minX &&
|
||||||
pActor->getPos().z <= _maxY && pActor->getPos().z >= _minY )
|
pActor->getPos().z <= _maxY && pActor->getPos().z >= _minY )
|
||||||
|
@ -278,6 +298,8 @@ void Sapphire::Zone::removeActor( Entity::ActorPtr pActor )
|
||||||
}
|
}
|
||||||
else if( pActor->isBattleNpc() )
|
else if( pActor->isBattleNpc() )
|
||||||
{
|
{
|
||||||
|
if( m_pNaviProvider )
|
||||||
|
m_pNaviProvider->removeAgent( *pActor->getAsChara() );
|
||||||
m_bNpcMap.erase( pActor->getId() );
|
m_bNpcMap.erase( pActor->getId() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -451,6 +473,9 @@ bool Sapphire::Zone::update( uint64_t tickCount )
|
||||||
//TODO: this should be moved to a updateWeather call and pulled out of updateSessions
|
//TODO: this should be moved to a updateWeather call and pulled out of updateSessions
|
||||||
bool changedWeather = checkWeather();
|
bool changedWeather = checkWeather();
|
||||||
|
|
||||||
|
if( m_pNaviProvider )
|
||||||
|
m_pNaviProvider->updateCrowd( 0.001f * tickCount );
|
||||||
|
|
||||||
updateSessions( tickCount, changedWeather );
|
updateSessions( tickCount, changedWeather );
|
||||||
onUpdate( tickCount );
|
onUpdate( tickCount );
|
||||||
|
|
||||||
|
@ -983,3 +1008,8 @@ Sapphire::Entity::BNpcPtr Sapphire::Zone::getActiveBNpcByLevelId( uint32_t level
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::shared_ptr< Sapphire::World::Navi::NaviProvider > Sapphire::Zone::getNaviProvider()
|
||||||
|
{
|
||||||
|
return m_pNaviProvider;
|
||||||
|
}
|
||||||
|
|
|
@ -63,6 +63,7 @@ namespace Sapphire
|
||||||
std::vector< Entity::SpawnGroup > m_spawnGroups;
|
std::vector< Entity::SpawnGroup > m_spawnGroups;
|
||||||
|
|
||||||
uint32_t m_effectCounter;
|
uint32_t m_effectCounter;
|
||||||
|
std::shared_ptr< World::Navi::NaviProvider > m_pNaviProvider;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Zone();
|
Zone();
|
||||||
|
@ -171,6 +172,8 @@ namespace Sapphire
|
||||||
void updateSpawnPoints();
|
void updateSpawnPoints();
|
||||||
|
|
||||||
uint32_t getNextEffectSequence();
|
uint32_t getNextEffectSequence();
|
||||||
|
|
||||||
|
std::shared_ptr< World::Navi::NaviProvider > getNaviProvider();
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue