From a29039b1640b3f2d63a9aaecf825fdc3dd308f27 Mon Sep 17 00:00:00 2001 From: goaaats Date: Sun, 20 Jan 2019 16:10:48 +0100 Subject: [PATCH 01/15] pathing things? --- src/world/CMakeLists.txt | 9 +- src/world/Manager/TerritoryMgr.cpp | 11 +-- src/world/Navi/NaviProvider.cpp | 135 +++++++++++++++++++++++++++++ src/world/Navi/NaviProvider.h | 51 +++++++++++ src/world/Territory/Zone.cpp | 13 ++- src/world/Territory/Zone.h | 5 ++ 6 files changed, 214 insertions(+), 10 deletions(-) create mode 100644 src/world/Navi/NaviProvider.cpp create mode 100644 src/world/Navi/NaviProvider.h diff --git a/src/world/CMakeLists.txt b/src/world/CMakeLists.txt index 7d25aae6..7954ae70 100644 --- a/src/world/CMakeLists.txt +++ b/src/world/CMakeLists.txt @@ -19,7 +19,8 @@ file( GLOB SERVER_SOURCE_FILES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} Script/*.c* StatusEffect/*.c* Territory/*.c* - Territory/Housing/*.c*) + Territory/Housing/*.c* + Navi/*.c*) add_executable( world ${SERVER_SOURCE_FILES} ) @@ -30,10 +31,12 @@ set_target_properties( world target_link_libraries( world PUBLIC - common ) + common + Detour) target_include_directories( world PUBLIC - "${CMAKE_CURRENT_SOURCE_DIR}" ) + "${CMAKE_CURRENT_SOURCE_DIR}" + Detour ) if( UNIX ) diff --git a/src/world/Manager/TerritoryMgr.cpp b/src/world/Manager/TerritoryMgr.cpp index 81c1aa96..f4abad11 100644 --- a/src/world/Manager/TerritoryMgr.cpp +++ b/src/world/Manager/TerritoryMgr.cpp @@ -163,16 +163,17 @@ bool Sapphire::World::Manager::TerritoryMgr::createDefaultTerritories() uint32_t guid = getNextInstanceId(); - Logger::info( "{0}\t{1}\t{2}\t{3:<10}\t{4}\t{5}", + auto pZone = make_Zone( territoryTypeId, guid, territoryInfo->name, pPlaceName->name, framework() ); + pZone->init(); + + Logger::info( "{0}\t{1}\t{2}\t{3:<10}\t{4}\t{5}\t{6}", territoryTypeId, guid, territoryInfo->territoryIntendedUse, territoryInfo->name, ( isPrivateTerritory( territoryTypeId ) ? "PRIVATE" : "PUBLIC" ), - pPlaceName->name ); - - auto pZone = make_Zone( territoryTypeId, guid, territoryInfo->name, pPlaceName->name, framework() ); - pZone->init(); + pPlaceName->name, + pZone->GetNaviProvider()->HasNaviMesh() ? "NAVI" : ""); InstanceIdToZonePtrMap instanceMap; instanceMap[ guid ] = pZone; diff --git a/src/world/Navi/NaviProvider.cpp b/src/world/Navi/NaviProvider.cpp new file mode 100644 index 00000000..a252b772 --- /dev/null +++ b/src/world/Navi/NaviProvider.cpp @@ -0,0 +1,135 @@ +#include +#include + +#include "Framework.h" +#include "NaviProvider.h" +#include +#include +#include +#include + +#include "../Territory/Zone.h" +#include + +Sapphire::NaviProvider::NaviProvider( Sapphire::ZonePtr pZone, Sapphire::FrameworkPtr pFw ) : + m_pFw( pFw ), + m_pZone( pZone ), + m_naviMesh( nullptr ), + m_naviMeshQuery( nullptr ) +{ +} + +void Sapphire::NaviProvider::init() +{ + auto meshesFolder = std::filesystem::path( "navi" ); + auto meshFolder = meshesFolder / std::filesystem::path( m_pZone->getInternalName() ); + + if( std::filesystem::exists( meshFolder ) ) + { + auto baseMesh = meshFolder / std::filesystem::path( m_pZone->getInternalName() + ".nav" ); + + //m_naviMesh = LoadMesh( baseMesh.string() ); + + // Load all meshes for testing + for( const auto & entry : std::filesystem::directory_iterator( meshFolder ) ) + { + if( entry.path().extension().string() == ".nav" ) + { + Logger::debug( "Loading " + entry.path().string() ); + LoadMesh( entry.path().string() ); + } + } + + InitQuery(); + } +} + +bool Sapphire::NaviProvider::HasNaviMesh() const +{ + return m_naviMesh != nullptr; +} + +void Sapphire::NaviProvider::InitQuery() +{ + if(m_naviMeshQuery != nullptr) + dtFreeNavMeshQuery( m_naviMeshQuery ); + + m_naviMeshQuery = dtAllocNavMeshQuery(); + m_naviMeshQuery->init( m_naviMesh, 2048 ); +} + +void Sapphire::NaviProvider::LoadMesh( std::string path ) +{ + FILE* fp = fopen( path.c_str(), "rb" ); + if( !fp ) + throw std::exception( "Could open navimesh file" ); + + // Read header. + NavMeshSetHeader header; + + size_t readLen = fread( &header, sizeof( NavMeshSetHeader ), 1, fp ); + if( readLen != 1 ) + { + fclose( fp ); + throw std::exception( "Could not read NavMeshSetHeader" ); + } + + if( header.magic != NAVMESHSET_MAGIC ) + { + fclose( fp ); + throw std::exception( "Not a NavMeshSet" ); + } + + if( header.version != NAVMESHSET_VERSION ) + { + fclose( fp ); + throw std::exception( "Invalid NavMeshSet version" ); + } + + if( !m_naviMesh ) + { + m_naviMesh = dtAllocNavMesh(); + if( !m_naviMesh ) + { + fclose( fp ); + throw std::exception( "Could not allocate dtNavMesh" ); + } + + dtStatus status = m_naviMesh->init( &header.params ); + if( dtStatusFailed( status ) ) + { + fclose( fp ); + throw std::exception( "Could not initialize dtNavMesh" ); + } + } + + // Read tiles. + for( int i = 0; i < header.numTiles; ++i ) + { + NavMeshTileHeader tileHeader; + readLen = fread( &tileHeader, sizeof( tileHeader ), 1, fp ); + if( readLen != 1 ) + { + fclose( fp ); + throw std::exception( "Could not read NavMeshTileHeader" ); + } + + if( !tileHeader.tileRef || !tileHeader.dataSize ) + break; + + unsigned char* data = (unsigned char*)dtAlloc( tileHeader.dataSize, DT_ALLOC_PERM ); + if( !data ) break; + memset( data, 0, tileHeader.dataSize ); + readLen = fread( data, tileHeader.dataSize, 1, fp ); + if( readLen != 1 ) + { + dtFree( data ); + fclose( fp ); + throw std::exception( "Could not read tile data" ); + } + + m_naviMesh->addTile( data, tileHeader.dataSize, DT_TILE_FREE_DATA, tileHeader.tileRef, 0 ); + } + + fclose( fp ); +} \ No newline at end of file diff --git a/src/world/Navi/NaviProvider.h b/src/world/Navi/NaviProvider.h new file mode 100644 index 00000000..706c3a9b --- /dev/null +++ b/src/world/Navi/NaviProvider.h @@ -0,0 +1,51 @@ +#ifndef _NAVIPROVIDER_H_ +#define _NAVIPROVIDER_H_ + +#include +#include "ForwardsZone.h" +#include +#include + +namespace Sapphire +{ + + class NaviProvider + { + + static const int NAVMESHSET_MAGIC = 'M' << 24 | 'S' << 16 | 'E' << 8 | 'T'; //'MSET'; + static const int NAVMESHSET_VERSION = 1; + + struct NavMeshSetHeader + { + int magic; + int version; + int numTiles; + dtNavMeshParams params; + }; + + struct NavMeshTileHeader + { + dtTileRef tileRef; + int dataSize; + }; + + public: + NaviProvider( const ZonePtr pZone, Sapphire::FrameworkPtr pFw ); + + void init(); + void LoadMesh( std::string path ); + void InitQuery(); + + bool HasNaviMesh() const; + + protected: + FrameworkPtr m_pFw; + ZonePtr m_pZone; + + dtNavMesh* m_naviMesh; + dtNavMeshQuery* m_naviMeshQuery; + }; + +} + +#endif diff --git a/src/world/Territory/Zone.cpp b/src/world/Territory/Zone.cpp index 21817559..0cd0c9fc 100644 --- a/src/world/Territory/Zone.cpp +++ b/src/world/Territory/Zone.cpp @@ -124,6 +124,9 @@ bool Sapphire::Zone::init() // all good } + m_naviProvider = new NaviProvider( shared_from_this(), m_pFw ); + m_naviProvider->init(); + return true; } @@ -782,7 +785,7 @@ bool Sapphire::Zone::loadSpawnGroups() m_spawnGroups.emplace_back( id, templateId, level, maxHp ); - Logger::debug( "id: {0}, template: {1}, level: {2}, maxHp: {3}", id, m_spawnGroups.back().getTemplateId(), level, maxHp ); + //Logger::debug( "id: {0}, template: {1}, level: {2}, maxHp: {3}", id, m_spawnGroups.back().getTemplateId(), level, maxHp ); } res.reset(); @@ -805,7 +808,7 @@ bool Sapphire::Zone::loadSpawnGroups() group.getSpawnPointList().emplace_back( std::make_shared< Entity::SpawnPoint >( x, y, z, r, gimmickId ) ); - Logger::debug( "id: {0}, x: {1}, y: {2}, z: {3}, gimmickId: {4}", id, x, y, z, gimmickId ); + //Logger::debug( "id: {0}, x: {1}, y: {2}, z: {3}, gimmickId: {4}", id, x, y, z, gimmickId ); } } return false; @@ -848,3 +851,9 @@ void Sapphire::Zone::updateSpawnPoints() } } + +Sapphire::NaviProvider* Sapphire::Zone::GetNaviProvider() const +{ + return m_naviProvider; +} + diff --git a/src/world/Territory/Zone.h b/src/world/Territory/Zone.h index 657b99c9..192c3fde 100644 --- a/src/world/Territory/Zone.h +++ b/src/world/Territory/Zone.h @@ -6,6 +6,7 @@ #include "Cell.h" #include "CellHandler.h" +#include "Navi/NaviProvider.h" #include "ForwardsZone.h" @@ -62,6 +63,8 @@ namespace Sapphire std::vector< Entity::SpawnGroup > m_spawnGroups; + NaviProvider* m_naviProvider; + public: Zone(); @@ -158,6 +161,8 @@ namespace Sapphire InstanceContentPtr getAsInstanceContent(); void updateSpawnPoints(); + + NaviProvider* GetNaviProvider() const; }; } From 916aa81441225af5031e48787183fc3b43ee3d14 Mon Sep 17 00:00:00 2001 From: goaaats Date: Mon, 21 Jan 2019 02:08:38 +0100 Subject: [PATCH 02/15] Add path follow code from RecastDemo --- src/world/Navi/NaviProvider.cpp | 320 +++++++++++++++++++++++++++++++- src/world/Navi/NaviProvider.h | 7 + 2 files changed, 324 insertions(+), 3 deletions(-) diff --git a/src/world/Navi/NaviProvider.cpp b/src/world/Navi/NaviProvider.cpp index a252b772..46b4c83b 100644 --- a/src/world/Navi/NaviProvider.cpp +++ b/src/world/Navi/NaviProvider.cpp @@ -10,13 +10,19 @@ #include "../Territory/Zone.h" #include +#include +#include Sapphire::NaviProvider::NaviProvider( Sapphire::ZonePtr pZone, Sapphire::FrameworkPtr pFw ) : m_pFw( pFw ), m_pZone( pZone ), m_naviMesh( nullptr ), m_naviMeshQuery( nullptr ) -{ +{ + // Set defaults + m_polyFindRange[0] = 2; + m_polyFindRange[1] = 4; + m_polyFindRange[2] = 2; } void Sapphire::NaviProvider::init() @@ -51,11 +57,319 @@ bool Sapphire::NaviProvider::HasNaviMesh() const void Sapphire::NaviProvider::InitQuery() { - if(m_naviMeshQuery != nullptr) + if( m_naviMeshQuery != nullptr ) dtFreeNavMeshQuery( m_naviMeshQuery ); m_naviMeshQuery = dtAllocNavMeshQuery(); m_naviMeshQuery->init( m_naviMesh, 2048 ); +} + +static int fixupCorridor( dtPolyRef* path, const int npath, const int maxPath, + const dtPolyRef* visited, const int nvisited ) +{ + int furthestPath = -1; + int furthestVisited = -1; + + // Find furthest common polygon. + for( int i = npath - 1; i >= 0; --i ) + { + bool found = false; + for( int j = nvisited - 1; j >= 0; --j ) + { + if( path[i] == visited[j] ) + { + furthestPath = i; + furthestVisited = j; + found = true; + } + } + if( found ) + break; + } + + // If no intersection found just return current path. + if( furthestPath == -1 || furthestVisited == -1 ) + return npath; + + // Concatenate paths. + + // Adjust beginning of the buffer to include the visited. + const int req = nvisited - furthestVisited; + const int orig = rcMin( furthestPath + 1, npath ); + int size = rcMax( 0, npath - orig ); + if( req + size > maxPath ) + size = maxPath - req; + if( size ) + memmove( path + req, path + orig, size * sizeof( dtPolyRef ) ); + + // Store visited + for( int i = 0; i < req; ++i ) + path[i] = visited[( nvisited - 1 ) - i]; + + return req + size; +} + +static int fixupShortcuts( dtPolyRef* path, int npath, dtNavMeshQuery* navQuery ) +{ + if( npath < 3 ) + return npath; + + // Get connected polygons + static const int maxNeis = 16; + dtPolyRef neis[maxNeis]; + int nneis = 0; + + const dtMeshTile* tile = 0; + const dtPoly* poly = 0; + if( dtStatusFailed( navQuery->getAttachedNavMesh()->getTileAndPolyByRef( path[0], &tile, &poly ) ) ) + return npath; + + for( unsigned int k = poly->firstLink; k != DT_NULL_LINK; k = tile->links[k].next ) + { + const dtLink* link = &tile->links[k]; + if( link->ref != 0 ) + { + if( nneis < maxNeis ) + neis[nneis++] = link->ref; + } + } + + // If any of the neighbour polygons is within the next few polygons + // in the path, short cut to that polygon directly. + static const int maxLookAhead = 6; + int cut = 0; + for( int i = dtMin( maxLookAhead, npath ) - 1; i > 1 && cut == 0; i-- ) { + for( int j = 0; j < nneis; j++ ) + { + if( path[i] == neis[j] ) { + cut = i; + break; + } + } + } + if( cut > 1 ) + { + int offset = cut - 1; + npath -= offset; + for( int i = 1; i < npath; i++ ) + path[i] = path[i + offset]; + } + + return npath; +} + +inline bool inRange( const float* v1, const float* v2, const float r, const float h ) +{ + const float dx = v2[0] - v1[0]; + const float dy = v2[1] - v1[1]; + const float dz = v2[2] - v1[2]; + return ( dx*dx + dz * dz ) < r*r && fabsf( dy ) < h; +} + +static bool getSteerTarget( dtNavMeshQuery* navQuery, const float* startPos, const float* endPos, + const float minTargetDist, + const dtPolyRef* path, const int pathSize, + float* steerPos, unsigned char& steerPosFlag, dtPolyRef& steerPosRef, + float* outPoints = 0, int* outPointCount = 0 ) +{ + // Find steer target. + static const int MAX_STEER_POINTS = 3; + float steerPath[MAX_STEER_POINTS * 3]; + unsigned char steerPathFlags[MAX_STEER_POINTS]; + dtPolyRef steerPathPolys[MAX_STEER_POINTS]; + int nsteerPath = 0; + navQuery->findStraightPath( startPos, endPos, path, pathSize, + steerPath, steerPathFlags, steerPathPolys, &nsteerPath, MAX_STEER_POINTS ); + if( !nsteerPath ) + return false; + + if( outPoints && outPointCount ) + { + *outPointCount = nsteerPath; + for( int i = 0; i < nsteerPath; ++i ) + dtVcopy( &outPoints[i * 3], &steerPath[i * 3] ); + } + + + // Find vertex far enough to steer to. + int ns = 0; + while( ns < nsteerPath ) + { + // Stop at Off-Mesh link or when point is further than slop away. + if( ( steerPathFlags[ns] & DT_STRAIGHTPATH_OFFMESH_CONNECTION ) || + !inRange( &steerPath[ns * 3], startPos, minTargetDist, 1000.0f ) ) + break; + ns++; + } + // Failed to find good point to steer to. + if( ns >= nsteerPath ) + return false; + + dtVcopy( steerPos, &steerPath[ns * 3] ); + steerPos[1] = startPos[1]; + steerPosFlag = steerPathFlags[ns]; + steerPosRef = steerPathPolys[ns]; + + return true; +} + +std::vector< Sapphire::Common::FFXIVARR_POSITION3 > Sapphire::NaviProvider::PathFindFollow( Common::FFXIVARR_POSITION3 startPos, Common::FFXIVARR_POSITION3 endPos ) +{ + if( !m_naviMesh || !m_naviMeshQuery ) + throw std::exception( "No navimesh loaded" ); + + dtPolyRef startRef, endRef = 0; + + float start[3] = { startPos.x, startPos.y, startPos.z }; + float end[3] = { startPos.x, startPos.y, startPos.z }; + + dtQueryFilter filter; + filter.setAreaCost( 0, 0 ); + + m_naviMeshQuery->findNearestPoly( start, m_polyFindRange, &filter, &startRef, 0 ); + m_naviMeshQuery->findNearestPoly( end, m_polyFindRange, &filter, &endRef, 0 ); + + // Couldn't find any close polys to navigate from + if( !startRef || !endRef ) + return {}; + + auto pathFindStatus = DT_FAILURE; + + auto pathIterNum = 0; + dtPolyRef polys[MAX_POLYS]; + int numPolys = 0; + + m_naviMeshQuery->findPath( startRef, endRef, start, end, &filter, polys, &numPolys, MAX_POLYS ); + + // Check if we got polys back for navigation + if( numPolys ) + { + // Iterate over the path to find smooth path on the detail mesh surface. + dtPolyRef polys[MAX_POLYS]; + memcpy( polys, polys, sizeof( dtPolyRef )*numPolys ); + int npolys = numPolys; + + float iterPos[3], targetPos[3]; + m_naviMeshQuery->closestPointOnPoly( startRef, start, iterPos, 0 ); + m_naviMeshQuery->closestPointOnPoly( polys[npolys - 1], end, targetPos, 0 ); + + static const float STEP_SIZE = 0.5f; + static const float SLOP = 0.01f; + + int numSmoothPath = 0; + float smoothPath[MAX_SMOOTH * 3]; + + dtVcopy( &smoothPath[numSmoothPath * 3], iterPos ); + numSmoothPath++; + + // Move towards target a small advancement at a time until target reached or + // when ran out of memory to store the path. + while( npolys && numSmoothPath < MAX_SMOOTH ) + { + // Find location to steer towards. + float steerPos[3]; + unsigned char steerPosFlag; + dtPolyRef steerPosRef; + + if( !getSteerTarget( m_naviMeshQuery, iterPos, targetPos, SLOP, + polys, npolys, steerPos, steerPosFlag, steerPosRef ) ) + break; + + bool endOfPath = ( steerPosFlag & DT_STRAIGHTPATH_END ) ? true : false; + bool offMeshConnection = ( steerPosFlag & DT_STRAIGHTPATH_OFFMESH_CONNECTION ) ? true : false; + + // Find movement delta. + float delta[3], len; + dtVsub( delta, steerPos, iterPos ); + len = dtMathSqrtf( dtVdot( delta, delta ) ); + // If the steer target is end of path or off-mesh link, do not move past the location. + if( ( endOfPath || offMeshConnection ) && len < STEP_SIZE ) + len = 1; + else + len = STEP_SIZE / len; + float moveTgt[3]; + dtVmad( moveTgt, iterPos, delta, len ); + + // Move + float result[3]; + dtPolyRef visited[16]; + int nvisited = 0; + m_naviMeshQuery->moveAlongSurface( polys[0], iterPos, moveTgt, &filter, + result, visited, &nvisited, 16 ); + + npolys = fixupCorridor( polys, npolys, MAX_POLYS, visited, nvisited ); + npolys = fixupShortcuts( polys, npolys, m_naviMeshQuery ); + + float h = 0; + m_naviMeshQuery->getPolyHeight( polys[0], result, &h ); + result[1] = h; + dtVcopy( iterPos, result ); + + // Handle end of path and off-mesh links when close enough. + if( endOfPath && inRange( iterPos, steerPos, SLOP, 1.0f ) ) + { + // Reached end of path. + dtVcopy( iterPos, targetPos ); + if( numSmoothPath < MAX_SMOOTH ) + { + dtVcopy( &smoothPath[numSmoothPath * 3], iterPos ); + numSmoothPath++; + } + break; + } + else if( offMeshConnection && inRange( iterPos, steerPos, SLOP, 1.0f ) ) + { + // Reached off-mesh connection. + float startPos[3], endPos[3]; + + // Advance the path up to and over the off-mesh connection. + dtPolyRef prevRef = 0, polyRef = polys[0]; + int npos = 0; + while( npos < npolys && polyRef != steerPosRef ) + { + prevRef = polyRef; + polyRef = polys[npos]; + npos++; + } + for( int i = npos; i < npolys; ++i ) + polys[i - npos] = polys[i]; + npolys -= npos; + + // Handle the connection. + dtStatus status = m_naviMesh->getOffMeshConnectionPolyEndPoints( prevRef, polyRef, startPos, endPos ); + if( dtStatusSucceed( status ) ) + { + if( numSmoothPath < MAX_SMOOTH ) + { + dtVcopy( &smoothPath[numSmoothPath * 3], startPos ); + numSmoothPath++; + // Hack to make the dotted path not visible during off-mesh connection. + if( numSmoothPath & 1 ) + { + dtVcopy( &smoothPath[numSmoothPath * 3], startPos ); + numSmoothPath++; + } + } + // Move position at the other side of the off-mesh link. + dtVcopy( iterPos, endPos ); + float eh = 0.0f; + m_naviMeshQuery->getPolyHeight( polys[0], iterPos, &eh ); + iterPos[1] = eh; + } + } + + // Store results. + if( numSmoothPath < MAX_SMOOTH ) + { + dtVcopy( &smoothPath[numSmoothPath * 3], iterPos ); + numSmoothPath++; + } + } + } + else + { + return {}; + } } void Sapphire::NaviProvider::LoadMesh( std::string path ) @@ -130,6 +444,6 @@ void Sapphire::NaviProvider::LoadMesh( std::string path ) m_naviMesh->addTile( data, tileHeader.dataSize, DT_TILE_FREE_DATA, tileHeader.tileRef, 0 ); } - + fclose( fp ); } \ No newline at end of file diff --git a/src/world/Navi/NaviProvider.h b/src/world/Navi/NaviProvider.h index 706c3a9b..1e70753b 100644 --- a/src/world/Navi/NaviProvider.h +++ b/src/world/Navi/NaviProvider.h @@ -29,6 +29,9 @@ namespace Sapphire int dataSize; }; + static const int MAX_POLYS = 256; + static const int MAX_SMOOTH = 2048; + public: NaviProvider( const ZonePtr pZone, Sapphire::FrameworkPtr pFw ); @@ -36,6 +39,8 @@ namespace Sapphire void LoadMesh( std::string path ); void InitQuery(); + std::vector< Sapphire::Common::FFXIVARR_POSITION3 > PathFindFollow(Common::FFXIVARR_POSITION3 startPos, Common::FFXIVARR_POSITION3 endPos); + bool HasNaviMesh() const; protected: @@ -44,6 +49,8 @@ namespace Sapphire dtNavMesh* m_naviMesh; dtNavMeshQuery* m_naviMeshQuery; + + float m_polyFindRange[3]; }; } From 78c0878610f4b7901f198d11ee10006500edfbe8 Mon Sep 17 00:00:00 2001 From: goaaats Date: Mon, 21 Jan 2019 02:42:47 +0100 Subject: [PATCH 03/15] path things --- src/world/Actor/BNpc.cpp | 138 +++++++++++++++++--------------- src/world/Navi/NaviProvider.cpp | 25 ++++-- 2 files changed, 91 insertions(+), 72 deletions(-) diff --git a/src/world/Actor/BNpc.cpp b/src/world/Actor/BNpc.cpp index 2fb811a3..dca819f7 100644 --- a/src/world/Actor/BNpc.cpp +++ b/src/world/Actor/BNpc.cpp @@ -153,6 +153,11 @@ bool Sapphire::Entity::BNpc::moveTo( const FFXIVARR_POSITION3& pos ) // reached destination return true; + auto path = m_pCurrentZone->GetNaviProvider()->PathFindFollow( m_pos, pos ); + + //face( path[0] ); + + /* float rot = Util::calcAngFrom( getPos().x, getPos().z, pos.x, pos.z ); float newRot = PI - rot + ( PI / 2 ); @@ -171,6 +176,7 @@ bool Sapphire::Entity::BNpc::moveTo( const FFXIVARR_POSITION3& pos ) setRot( newRot ); sendPositionUpdate(); + */ return false; } @@ -306,87 +312,87 @@ void Sapphire::Entity::BNpc::update( int64_t currTime ) switch( m_state ) { - case BNpcState::Retreat: + case BNpcState::Retreat: + { + if( moveTo( m_spawnPos ) ) + m_state = BNpcState::Idle; + } + break; + + case BNpcState::Idle: + { + // passive mobs should ignore players unless aggro'd + if( m_aggressionMode == 1 ) + return; + + CharaPtr pClosestChara = getClosestChara(); + + if( pClosestChara && pClosestChara->isAlive() ) { - if( moveTo( m_spawnPos ) ) - m_state = BNpcState::Idle; + auto distance = Util::distance( getPos().x, getPos().y, getPos().z, + pClosestChara->getPos().x, + pClosestChara->getPos().y, + pClosestChara->getPos().z ); + + if( distance < aggroRange && pClosestChara->isPlayer() ) + aggro( pClosestChara ); + //if( distance < aggroRange && getbehavior() == 2 ) + // aggro( pClosestActor ); } - break; + } - case BNpcState::Idle: + case BNpcState::Combat: + { + auto pHatedActor = hateListGetHighest(); + if( !pHatedActor ) + return; + + auto distanceOrig = Util::distance( getPos().x, getPos().y, getPos().z, + m_spawnPos.x, + m_spawnPos.y, + m_spawnPos.z ); + + if( pHatedActor && !pHatedActor->isAlive() ) { - // passive mobs should ignore players unless aggro'd - if( m_aggressionMode == 1 ) - return; - - CharaPtr pClosestChara = getClosestChara(); - - if( pClosestChara && pClosestChara->isAlive() ) - { - auto distance = Util::distance( getPos().x, getPos().y, getPos().z, - pClosestChara->getPos().x, - pClosestChara->getPos().y, - pClosestChara->getPos().z ); - - if( distance < aggroRange && pClosestChara->isPlayer() ) - aggro( pClosestChara ); - //if( distance < aggroRange && getbehavior() == 2 ) - // aggro( pClosestActor ); - } + hateListRemove( pHatedActor ); + pHatedActor = hateListGetHighest(); } - case BNpcState::Combat: + if( pHatedActor ) { - auto pHatedActor = hateListGetHighest(); - if( !pHatedActor ) - return; + auto distance = Util::distance( getPos().x, getPos().y, getPos().z, + pHatedActor->getPos().x, + pHatedActor->getPos().y, + pHatedActor->getPos().z ); - auto distanceOrig = Util::distance( getPos().x, getPos().y, getPos().z, - m_spawnPos.x, - m_spawnPos.y, - m_spawnPos.z ); - - if( pHatedActor && !pHatedActor->isAlive() ) - { - hateListRemove( pHatedActor ); - pHatedActor = hateListGetHighest(); - } - - if( pHatedActor ) - { - auto distance = Util::distance( getPos().x, getPos().y, getPos().z, - pHatedActor->getPos().x, - pHatedActor->getPos().y, - pHatedActor->getPos().z ); - - if( distanceOrig > maxDistanceToOrigin ) - { - hateListClear(); - changeTarget( INVALID_GAME_OBJECT_ID ); - setStance( Stance::Passive ); - //setOwner( nullptr ); - m_state = BNpcState::Retreat; - break; - } - - if( distance > minActorDistance ) - moveTo( pHatedActor->getPos() ); - else - { - if( face( pHatedActor->getPos() ) ) - sendPositionUpdate(); - // in combat range. ATTACK! - autoAttack( pHatedActor ); - } - } - else + if( distanceOrig > maxDistanceToOrigin ) { + hateListClear(); changeTarget( INVALID_GAME_OBJECT_ID ); setStance( Stance::Passive ); //setOwner( nullptr ); m_state = BNpcState::Retreat; + break; + } + + if( distance > minActorDistance ) + moveTo( pHatedActor->getPos() ); + else + { + if( face( pHatedActor->getPos() ) ) + sendPositionUpdate(); + // in combat range. ATTACK! + autoAttack( pHatedActor ); } } + else + { + changeTarget( INVALID_GAME_OBJECT_ID ); + setStance( Stance::Passive ); + //setOwner( nullptr ); + m_state = BNpcState::Retreat; + } + } } } diff --git a/src/world/Navi/NaviProvider.cpp b/src/world/Navi/NaviProvider.cpp index 46b4c83b..9e80a007 100644 --- a/src/world/Navi/NaviProvider.cpp +++ b/src/world/Navi/NaviProvider.cpp @@ -20,9 +20,9 @@ Sapphire::NaviProvider::NaviProvider( Sapphire::ZonePtr pZone, Sapphire::Framewo m_naviMeshQuery( nullptr ) { // Set defaults - m_polyFindRange[0] = 2; - m_polyFindRange[1] = 4; - m_polyFindRange[2] = 2; + m_polyFindRange[0] = 10; + m_polyFindRange[1] = 20; + m_polyFindRange[2] = 10; } void Sapphire::NaviProvider::init() @@ -34,9 +34,11 @@ void Sapphire::NaviProvider::init() { auto baseMesh = meshFolder / std::filesystem::path( m_pZone->getInternalName() + ".nav" ); - //m_naviMesh = LoadMesh( baseMesh.string() ); + LoadMesh( baseMesh.string() ); // Load all meshes for testing + + /* for( const auto & entry : std::filesystem::directory_iterator( meshFolder ) ) { if( entry.path().extension().string() == ".nav" ) @@ -45,6 +47,7 @@ void Sapphire::NaviProvider::init() LoadMesh( entry.path().string() ); } } + */ InitQuery(); } @@ -221,10 +224,11 @@ std::vector< Sapphire::Common::FFXIVARR_POSITION3 > Sapphire::NaviProvider::Path dtPolyRef startRef, endRef = 0; float start[3] = { startPos.x, startPos.y, startPos.z }; - float end[3] = { startPos.x, startPos.y, startPos.z }; + float end[3] = { endPos.x, endPos.y, endPos.z }; dtQueryFilter filter; - filter.setAreaCost( 0, 0 ); + filter.setIncludeFlags(0xffff); + filter.setExcludeFlags(0); m_naviMeshQuery->findNearestPoly( start, m_polyFindRange, &filter, &startRef, 0 ); m_naviMeshQuery->findNearestPoly( end, m_polyFindRange, &filter, &endRef, 0 ); @@ -262,6 +266,8 @@ std::vector< Sapphire::Common::FFXIVARR_POSITION3 > Sapphire::NaviProvider::Path dtVcopy( &smoothPath[numSmoothPath * 3], iterPos ); numSmoothPath++; + auto resultCoords = std::vector< Common::FFXIVARR_POSITION3 >(); + // Move towards target a small advancement at a time until target reached or // when ran out of memory to store the path. while( npolys && numSmoothPath < MAX_SMOOTH ) @@ -365,6 +371,13 @@ std::vector< Sapphire::Common::FFXIVARR_POSITION3 > Sapphire::NaviProvider::Path numSmoothPath++; } } + + for( int i = 0; i < numSmoothPath; i += 3 ) + { + resultCoords.push_back( Common::FFXIVARR_POSITION3{ smoothPath[i], smoothPath[i + 2], smoothPath[i + 3] } ); + } + + return resultCoords; } else { From 8c6c8bc787e70fffad66ec69941ad11d23c6d619 Mon Sep 17 00:00:00 2001 From: goaaats Date: Mon, 21 Jan 2019 14:02:47 +0100 Subject: [PATCH 04/15] More pathing --- src/world/Actor/BNpc.cpp | 2 +- src/world/Manager/TerritoryMgr.cpp | 2 +- src/world/Navi/NaviProvider.cpp | 59 ++++++++++++++++-------------- src/world/Navi/NaviProvider.h | 10 +++-- src/world/Territory/Zone.cpp | 2 +- src/world/Territory/Zone.h | 2 +- 6 files changed, 42 insertions(+), 35 deletions(-) diff --git a/src/world/Actor/BNpc.cpp b/src/world/Actor/BNpc.cpp index dca819f7..1e105142 100644 --- a/src/world/Actor/BNpc.cpp +++ b/src/world/Actor/BNpc.cpp @@ -153,7 +153,7 @@ bool Sapphire::Entity::BNpc::moveTo( const FFXIVARR_POSITION3& pos ) // reached destination return true; - auto path = m_pCurrentZone->GetNaviProvider()->PathFindFollow( m_pos, pos ); + auto path = m_pCurrentZone->getNaviProvider()->findFollowPath( m_pos, pos ); //face( path[0] ); diff --git a/src/world/Manager/TerritoryMgr.cpp b/src/world/Manager/TerritoryMgr.cpp index f4abad11..09885244 100644 --- a/src/world/Manager/TerritoryMgr.cpp +++ b/src/world/Manager/TerritoryMgr.cpp @@ -173,7 +173,7 @@ bool Sapphire::World::Manager::TerritoryMgr::createDefaultTerritories() territoryInfo->name, ( isPrivateTerritory( territoryTypeId ) ? "PRIVATE" : "PUBLIC" ), pPlaceName->name, - pZone->GetNaviProvider()->HasNaviMesh() ? "NAVI" : ""); + pZone->getNaviProvider()->hasNaviMesh() ? "NAVI" : ""); InstanceIdToZonePtrMap instanceMap; instanceMap[ guid ] = pZone; diff --git a/src/world/Navi/NaviProvider.cpp b/src/world/Navi/NaviProvider.cpp index 9e80a007..5bb3e031 100644 --- a/src/world/Navi/NaviProvider.cpp +++ b/src/world/Navi/NaviProvider.cpp @@ -34,7 +34,7 @@ void Sapphire::NaviProvider::init() { auto baseMesh = meshFolder / std::filesystem::path( m_pZone->getInternalName() + ".nav" ); - LoadMesh( baseMesh.string() ); + loadMesh( baseMesh.string() ); // Load all meshes for testing @@ -49,16 +49,16 @@ void Sapphire::NaviProvider::init() } */ - InitQuery(); + initQuery(); } } -bool Sapphire::NaviProvider::HasNaviMesh() const +bool Sapphire::NaviProvider::hasNaviMesh() const { return m_naviMesh != nullptr; } -void Sapphire::NaviProvider::InitQuery() +void Sapphire::NaviProvider::initQuery() { if( m_naviMeshQuery != nullptr ) dtFreeNavMeshQuery( m_naviMeshQuery ); @@ -216,34 +216,45 @@ static bool getSteerTarget( dtNavMeshQuery* navQuery, const float* startPos, con return true; } -std::vector< Sapphire::Common::FFXIVARR_POSITION3 > Sapphire::NaviProvider::PathFindFollow( Common::FFXIVARR_POSITION3 startPos, Common::FFXIVARR_POSITION3 endPos ) +void Sapphire::NaviProvider::toDetourPos( const Sapphire::Common::FFXIVARR_POSITION3 pos, float* out ) { + float y = pos.y; + float z = pos.z; + + out[0] = pos.x; + out[1] = y * -1; + out[2] = z * -1; +} + +std::vector< Sapphire::Common::FFXIVARR_POSITION3 > Sapphire::NaviProvider::findFollowPath( Common::FFXIVARR_POSITION3 startPos, Common::FFXIVARR_POSITION3 endPos ) { if( !m_naviMesh || !m_naviMeshQuery ) throw std::exception( "No navimesh loaded" ); + auto resultCoords = std::vector< Common::FFXIVARR_POSITION3 >(); + dtPolyRef startRef, endRef = 0; - float start[3] = { startPos.x, startPos.y, startPos.z }; - float end[3] = { endPos.x, endPos.y, endPos.z }; + float spos[3]; + NaviProvider::toDetourPos( startPos, spos ); + + float epos[3]; + NaviProvider::toDetourPos( endPos, epos ); dtQueryFilter filter; - filter.setIncludeFlags(0xffff); - filter.setExcludeFlags(0); + filter.setIncludeFlags( 0xffff ); + filter.setExcludeFlags( 0 ); - m_naviMeshQuery->findNearestPoly( start, m_polyFindRange, &filter, &startRef, 0 ); - m_naviMeshQuery->findNearestPoly( end, m_polyFindRange, &filter, &endRef, 0 ); + m_naviMeshQuery->findNearestPoly( spos, m_polyFindRange, &filter, &startRef, 0 ); + m_naviMeshQuery->findNearestPoly( epos, m_polyFindRange, &filter, &endRef, 0 ); // Couldn't find any close polys to navigate from if( !startRef || !endRef ) - return {}; + return resultCoords; - auto pathFindStatus = DT_FAILURE; - - auto pathIterNum = 0; dtPolyRef polys[MAX_POLYS]; int numPolys = 0; - m_naviMeshQuery->findPath( startRef, endRef, start, end, &filter, polys, &numPolys, MAX_POLYS ); + m_naviMeshQuery->findPath( startRef, endRef, spos, epos, &filter, polys, &numPolys, MAX_POLYS ); // Check if we got polys back for navigation if( numPolys ) @@ -254,8 +265,8 @@ std::vector< Sapphire::Common::FFXIVARR_POSITION3 > Sapphire::NaviProvider::Path int npolys = numPolys; float iterPos[3], targetPos[3]; - m_naviMeshQuery->closestPointOnPoly( startRef, start, iterPos, 0 ); - m_naviMeshQuery->closestPointOnPoly( polys[npolys - 1], end, targetPos, 0 ); + m_naviMeshQuery->closestPointOnPoly( startRef, spos, iterPos, 0 ); + m_naviMeshQuery->closestPointOnPoly( polys[npolys - 1], epos, targetPos, 0 ); static const float STEP_SIZE = 0.5f; static const float SLOP = 0.01f; @@ -266,8 +277,6 @@ std::vector< Sapphire::Common::FFXIVARR_POSITION3 > Sapphire::NaviProvider::Path dtVcopy( &smoothPath[numSmoothPath * 3], iterPos ); numSmoothPath++; - auto resultCoords = std::vector< Common::FFXIVARR_POSITION3 >(); - // Move towards target a small advancement at a time until target reached or // when ran out of memory to store the path. while( npolys && numSmoothPath < MAX_SMOOTH ) @@ -376,16 +385,12 @@ std::vector< Sapphire::Common::FFXIVARR_POSITION3 > Sapphire::NaviProvider::Path { resultCoords.push_back( Common::FFXIVARR_POSITION3{ smoothPath[i], smoothPath[i + 2], smoothPath[i + 3] } ); } + } - return resultCoords; - } - else - { - return {}; - } + return resultCoords; } -void Sapphire::NaviProvider::LoadMesh( std::string path ) +void Sapphire::NaviProvider::loadMesh( std::string path ) { FILE* fp = fopen( path.c_str(), "rb" ); if( !fp ) diff --git a/src/world/Navi/NaviProvider.h b/src/world/Navi/NaviProvider.h index 1e70753b..a4d598da 100644 --- a/src/world/Navi/NaviProvider.h +++ b/src/world/Navi/NaviProvider.h @@ -36,12 +36,14 @@ namespace Sapphire NaviProvider( const ZonePtr pZone, Sapphire::FrameworkPtr pFw ); void init(); - void LoadMesh( std::string path ); - void InitQuery(); + void loadMesh( std::string path ); + void initQuery(); - std::vector< Sapphire::Common::FFXIVARR_POSITION3 > PathFindFollow(Common::FFXIVARR_POSITION3 startPos, Common::FFXIVARR_POSITION3 endPos); + void toDetourPos(const Common::FFXIVARR_POSITION3 position, float* out); - bool HasNaviMesh() const; + std::vector< Sapphire::Common::FFXIVARR_POSITION3 > findFollowPath(Common::FFXIVARR_POSITION3 startPos, Common::FFXIVARR_POSITION3 endPos); + + bool hasNaviMesh() const; protected: FrameworkPtr m_pFw; diff --git a/src/world/Territory/Zone.cpp b/src/world/Territory/Zone.cpp index 0cd0c9fc..5e53b5eb 100644 --- a/src/world/Territory/Zone.cpp +++ b/src/world/Territory/Zone.cpp @@ -852,7 +852,7 @@ void Sapphire::Zone::updateSpawnPoints() } -Sapphire::NaviProvider* Sapphire::Zone::GetNaviProvider() const +Sapphire::NaviProvider* Sapphire::Zone::getNaviProvider() const { return m_naviProvider; } diff --git a/src/world/Territory/Zone.h b/src/world/Territory/Zone.h index 192c3fde..b556bff4 100644 --- a/src/world/Territory/Zone.h +++ b/src/world/Territory/Zone.h @@ -162,7 +162,7 @@ namespace Sapphire void updateSpawnPoints(); - NaviProvider* GetNaviProvider() const; + NaviProvider* getNaviProvider() const; }; } From 1927b2b1a44d0c60ec2c903311a0c46ba1dc8f53 Mon Sep 17 00:00:00 2001 From: goaaats Date: Mon, 21 Jan 2019 15:15:28 +0100 Subject: [PATCH 05/15] More pathing --- src/world/Actor/BNpc.cpp | 12 +++++++++++- src/world/Navi/NaviProvider.cpp | 14 +++++++++++++- src/world/Navi/NaviProvider.h | 1 + 3 files changed, 25 insertions(+), 2 deletions(-) diff --git a/src/world/Actor/BNpc.cpp b/src/world/Actor/BNpc.cpp index 1e105142..6da0e92f 100644 --- a/src/world/Actor/BNpc.cpp +++ b/src/world/Actor/BNpc.cpp @@ -31,6 +31,7 @@ #include "BNpcTemplate.h" #include "Manager/TerritoryMgr.h" #include "Common.h" +#include using namespace Sapphire::Common; using namespace Sapphire::Network::Packets; @@ -155,7 +156,16 @@ bool Sapphire::Entity::BNpc::moveTo( const FFXIVARR_POSITION3& pos ) auto path = m_pCurrentZone->getNaviProvider()->findFollowPath( m_pos, pos ); - //face( path[0] ); + if(!path.empty()) + { + for(int i = 0; i < path.size(); i++) + Logger::debug("{0}: {1} {2} {3}", i, path[i].x, path[i].y, path[i].z); + + face( path[0] ); + setPos(path[0]); + } + + sendPositionUpdate(); /* float rot = Util::calcAngFrom( getPos().x, getPos().z, pos.x, pos.z ); diff --git a/src/world/Navi/NaviProvider.cpp b/src/world/Navi/NaviProvider.cpp index 5bb3e031..eb3bf39e 100644 --- a/src/world/Navi/NaviProvider.cpp +++ b/src/world/Navi/NaviProvider.cpp @@ -225,6 +225,13 @@ void Sapphire::NaviProvider::toDetourPos( const Sapphire::Common::FFXIVARR_POSIT out[2] = z * -1; } +Sapphire::Common::FFXIVARR_POSITION3 Sapphire::NaviProvider::toGamePos( float* pos ) { + float y = pos[1]; + float z = pos[2]; + + return Common::FFXIVARR_POSITION3 { pos[0], y * -1, z * -1 }; +} + std::vector< Sapphire::Common::FFXIVARR_POSITION3 > Sapphire::NaviProvider::findFollowPath( Common::FFXIVARR_POSITION3 startPos, Common::FFXIVARR_POSITION3 endPos ) { if( !m_naviMesh || !m_naviMeshQuery ) @@ -234,11 +241,16 @@ std::vector< Sapphire::Common::FFXIVARR_POSITION3 > Sapphire::NaviProvider::find dtPolyRef startRef, endRef = 0; + /* float spos[3]; NaviProvider::toDetourPos( startPos, spos ); float epos[3]; NaviProvider::toDetourPos( endPos, epos ); + */ + + float spos[3] = {startPos.x, startPos.y, startPos.z}; + float epos[3] = {endPos.x, endPos.y, endPos.z}; dtQueryFilter filter; filter.setIncludeFlags( 0xffff ); @@ -383,7 +395,7 @@ std::vector< Sapphire::Common::FFXIVARR_POSITION3 > Sapphire::NaviProvider::find for( int i = 0; i < numSmoothPath; i += 3 ) { - resultCoords.push_back( Common::FFXIVARR_POSITION3{ smoothPath[i], smoothPath[i + 2], smoothPath[i + 3] } ); + resultCoords.push_back( Common::FFXIVARR_POSITION3{ smoothPath[i], smoothPath[i + 1], smoothPath[i + 2] } ); } } diff --git a/src/world/Navi/NaviProvider.h b/src/world/Navi/NaviProvider.h index a4d598da..5b9592da 100644 --- a/src/world/Navi/NaviProvider.h +++ b/src/world/Navi/NaviProvider.h @@ -40,6 +40,7 @@ namespace Sapphire void initQuery(); void toDetourPos(const Common::FFXIVARR_POSITION3 position, float* out); + Sapphire::Common::FFXIVARR_POSITION3 toGamePos( float* pos ); std::vector< Sapphire::Common::FFXIVARR_POSITION3 > findFollowPath(Common::FFXIVARR_POSITION3 startPos, Common::FFXIVARR_POSITION3 endPos); From 30f4040774d74ccfe764e7386f08820661757f1f Mon Sep 17 00:00:00 2001 From: goaaats Date: Mon, 21 Jan 2019 18:25:22 +0100 Subject: [PATCH 06/15] More pathfinding --- src/world/Actor/BNpc.cpp | 2 +- src/world/Manager/DebugCommandMgr.cpp | 12 ++++++++++++ src/world/Navi/NaviProvider.cpp | 2 ++ 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/world/Actor/BNpc.cpp b/src/world/Actor/BNpc.cpp index 6da0e92f..48bf3c3e 100644 --- a/src/world/Actor/BNpc.cpp +++ b/src/world/Actor/BNpc.cpp @@ -315,7 +315,7 @@ void Sapphire::Entity::BNpc::update( int64_t currTime ) { const uint8_t minActorDistance = 4; const uint8_t aggroRange = 8; - const uint8_t maxDistanceToOrigin = 30; + const uint8_t maxDistanceToOrigin = 1000; if( m_status == ActorStatus::Dead ) return; diff --git a/src/world/Manager/DebugCommandMgr.cpp b/src/world/Manager/DebugCommandMgr.cpp index 957b1320..70bec2eb 100644 --- a/src/world/Manager/DebugCommandMgr.cpp +++ b/src/world/Manager/DebugCommandMgr.cpp @@ -367,6 +367,18 @@ void Sapphire::World::Manager::DebugCommandMgr::set( char* data, Entity::Player& } } } + else if( subCommand == "mobaggro" ) + { + auto inRange = player.getInRangeActors(); + + for( auto actor : inRange ) + { + if( actor->getId() == player.getTargetId() && actor->getAsChara()->isAlive() ) + { + actor->getAsBNpc()->onActionHostile( player.getAsChara() ); + } + } + } else { player.sendUrgent( "{0} is not a valid SET command.", subCommand ); diff --git a/src/world/Navi/NaviProvider.cpp b/src/world/Navi/NaviProvider.cpp index eb3bf39e..4694179c 100644 --- a/src/world/Navi/NaviProvider.cpp +++ b/src/world/Navi/NaviProvider.cpp @@ -280,6 +280,8 @@ std::vector< Sapphire::Common::FFXIVARR_POSITION3 > Sapphire::NaviProvider::find m_naviMeshQuery->closestPointOnPoly( startRef, spos, iterPos, 0 ); m_naviMeshQuery->closestPointOnPoly( polys[npolys - 1], epos, targetPos, 0 ); + Logger::debug("IterPos: {0} {1} {2}; TargetPos: {3} {4} {5}", iterPos[0], iterPos[1], iterPos[2], targetPos[0], targetPos[1], targetPos[2]); + static const float STEP_SIZE = 0.5f; static const float SLOP = 0.01f; From 65e9d578806e669d2fcf9d195ee516253d2f5a04 Mon Sep 17 00:00:00 2001 From: goaaats Date: Tue, 22 Jan 2019 00:41:18 +0100 Subject: [PATCH 07/15] it works --- src/world/Actor/BNpc.cpp | 4 ++-- src/world/Navi/NaviProvider.cpp | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/world/Actor/BNpc.cpp b/src/world/Actor/BNpc.cpp index 48bf3c3e..81c36de8 100644 --- a/src/world/Actor/BNpc.cpp +++ b/src/world/Actor/BNpc.cpp @@ -161,8 +161,8 @@ bool Sapphire::Entity::BNpc::moveTo( const FFXIVARR_POSITION3& pos ) for(int i = 0; i < path.size(); i++) Logger::debug("{0}: {1} {2} {3}", i, path[i].x, path[i].y, path[i].z); - face( path[0] ); - setPos(path[0]); + face( path[1] ); + setPos(path[1]); } sendPositionUpdate(); diff --git a/src/world/Navi/NaviProvider.cpp b/src/world/Navi/NaviProvider.cpp index 4694179c..c375f3a1 100644 --- a/src/world/Navi/NaviProvider.cpp +++ b/src/world/Navi/NaviProvider.cpp @@ -272,7 +272,6 @@ std::vector< Sapphire::Common::FFXIVARR_POSITION3 > Sapphire::NaviProvider::find if( numPolys ) { // Iterate over the path to find smooth path on the detail mesh surface. - dtPolyRef polys[MAX_POLYS]; memcpy( polys, polys, sizeof( dtPolyRef )*numPolys ); int npolys = numPolys; From 09ce04b37e61d6a654b3f8da86515bfd4c2a50e5 Mon Sep 17 00:00:00 2001 From: goaaats Date: Wed, 23 Jan 2019 17:07:40 +0100 Subject: [PATCH 08/15] change movement in BNpc --- src/world/Actor/BNpc.cpp | 90 ++++++++++++++++++++++++++++++--- src/world/Actor/BNpc.h | 8 +++ src/world/Navi/NaviProvider.cpp | 4 +- 3 files changed, 92 insertions(+), 10 deletions(-) diff --git a/src/world/Actor/BNpc.cpp b/src/world/Actor/BNpc.cpp index 81c36de8..7c95aed2 100644 --- a/src/world/Actor/BNpc.cpp +++ b/src/world/Actor/BNpc.cpp @@ -148,24 +148,96 @@ void Sapphire::Entity::BNpc::setState( BNpcState state ) m_state = state; } +void Sapphire::Entity::BNpc::step() +{ + if( m_naviLastPath.empty() ) + // No path to track + return; + + if( Util::distance( getPos().x, getPos().y, getPos().z, m_naviTarget.x, m_naviTarget.y, m_naviTarget.z ) <= 4 ) + { + // Reached target + m_naviLastPath.clear(); + return; + } + + // Check if we have to recalculate + if( Util::getTimeMs() - m_lastUpdate > 500 ) + { + auto path = m_pCurrentZone->getNaviProvider()->findFollowPath( m_pos, m_naviTarget ); + + if( !path.empty() ) + { + for( int i = 0; i < path.size(); i++ ) + Logger::debug( "[STEP] {0}: {1} {2} {3}", i, path[i].x, path[i].y, path[i].z ); + + m_naviLastPath = path; + m_naviLastUpdate = Util::getTimeMs(); + m_naviPathStep = 0; + } + else + { + Logger::debug( "No path found for target: {0} {1} {2}", m_naviTarget.x, m_naviTarget.y, m_naviTarget.z ); + } + } + + auto stepPos = m_naviLastPath[m_naviPathStep]; + + if( Util::distance( getPos().x, getPos().y, getPos().z, stepPos.x, stepPos.y, stepPos.z ) <= 4 ) + { + // Reached step in path + m_naviPathStep++; + Logger::debug( "Reached step {0}", m_naviPathStep ); + + stepPos = m_naviLastPath[m_naviPathStep]; + } + + float rot = Util::calcAngFrom( getPos().x, getPos().z, stepPos.x, stepPos.z ); + float newRot = PI - rot + ( PI / 2 ); + + face( stepPos ); + float angle = Util::calcAngFrom( getPos().x, getPos().z, stepPos.x, stepPos.z ) + PI; + + auto x = ( cosf( angle ) * 1.1f ); + auto y = ( getPos().y + stepPos.y ) * 0.5f; // fake value while there is no collision + auto z = ( sinf( angle ) * 1.1f ); + + Common::FFXIVARR_POSITION3 newPos{ getPos().x + x, y, getPos().z + z }; + setPos( newPos ); + + Common::FFXIVARR_POSITION3 tmpPos{ getPos().x + x, y, getPos().z + z }; + setPos( tmpPos ); + setRot( newRot ); + + sendPositionUpdate(); +} + bool Sapphire::Entity::BNpc::moveTo( const FFXIVARR_POSITION3& pos ) { if( Util::distance( getPos().x, getPos().y, getPos().z, pos.x, pos.y, pos.z ) <= 4 ) - // reached destination + // Reached destination return true; + if( m_naviTarget.x == pos.x && m_naviTarget.y == pos.y && m_naviTarget.z == pos.z ) + // Targets are the same + return false; + auto path = m_pCurrentZone->getNaviProvider()->findFollowPath( m_pos, pos ); - if(!path.empty()) + if( !path.empty() ) { - for(int i = 0; i < path.size(); i++) - Logger::debug("{0}: {1} {2} {3}", i, path[i].x, path[i].y, path[i].z); + for( int i = 0; i < path.size(); i++ ) + Logger::debug( "[MOVETO] {0}: {1} {2} {3}", i, path[i].x, path[i].y, path[i].z ); - face( path[1] ); - setPos(path[1]); + m_naviLastPath = path; + m_naviTarget = pos; + m_naviPathStep = 0; + m_naviLastUpdate = Util::getTimeMs(); + } + else + { + Logger::debug( "No path found for target: {0} {1} {2}", pos.x, pos.y, pos.z ); } - - sendPositionUpdate(); /* float rot = Util::calcAngFrom( getPos().x, getPos().z, pos.x, pos.z ); @@ -404,6 +476,8 @@ void Sapphire::Entity::BNpc::update( int64_t currTime ) } } } + + step(); } void Sapphire::Entity::BNpc::onActionHostile( Sapphire::Entity::CharaPtr pSource ) diff --git a/src/world/Actor/BNpc.h b/src/world/Actor/BNpc.h index db0fb1f9..aa546747 100644 --- a/src/world/Actor/BNpc.h +++ b/src/world/Actor/BNpc.h @@ -62,6 +62,9 @@ namespace Sapphire::Entity // return true if it reached the position bool moveTo( const Common::FFXIVARR_POSITION3& pos ); + // processes movement + void step(); + void sendPositionUpdate(); BNpcState getState() const; @@ -101,6 +104,11 @@ namespace Sapphire::Entity BNpcState m_state; std::set< std::shared_ptr< HateListEntry > > m_hateList; + uint64_t m_naviLastUpdate; + std::vector< Common::FFXIVARR_POSITION3 > m_naviLastPath; + uint8_t m_naviPathStep; + Common::FFXIVARR_POSITION3 m_naviTarget; + }; } diff --git a/src/world/Navi/NaviProvider.cpp b/src/world/Navi/NaviProvider.cpp index c375f3a1..064095dc 100644 --- a/src/world/Navi/NaviProvider.cpp +++ b/src/world/Navi/NaviProvider.cpp @@ -281,8 +281,8 @@ std::vector< Sapphire::Common::FFXIVARR_POSITION3 > Sapphire::NaviProvider::find Logger::debug("IterPos: {0} {1} {2}; TargetPos: {3} {4} {5}", iterPos[0], iterPos[1], iterPos[2], targetPos[0], targetPos[1], targetPos[2]); - static const float STEP_SIZE = 0.5f; - static const float SLOP = 0.01f; + static const float STEP_SIZE = 1.2f; + static const float SLOP = 0.15f; int numSmoothPath = 0; float smoothPath[MAX_SMOOTH * 3]; From 7552c08ae3e3e060e5abd248703e7a81cd6e76e7 Mon Sep 17 00:00:00 2001 From: goaaats Date: Wed, 23 Jan 2019 17:42:09 +0100 Subject: [PATCH 09/15] Handle steps better --- src/world/Actor/BNpc.cpp | 59 ++++++++++++++-------------------------- 1 file changed, 20 insertions(+), 39 deletions(-) diff --git a/src/world/Actor/BNpc.cpp b/src/world/Actor/BNpc.cpp index 7c95aed2..92d020bd 100644 --- a/src/world/Actor/BNpc.cpp +++ b/src/world/Actor/BNpc.cpp @@ -161,29 +161,9 @@ void Sapphire::Entity::BNpc::step() return; } - // Check if we have to recalculate - if( Util::getTimeMs() - m_lastUpdate > 500 ) - { - auto path = m_pCurrentZone->getNaviProvider()->findFollowPath( m_pos, m_naviTarget ); - - if( !path.empty() ) - { - for( int i = 0; i < path.size(); i++ ) - Logger::debug( "[STEP] {0}: {1} {2} {3}", i, path[i].x, path[i].y, path[i].z ); - - m_naviLastPath = path; - m_naviLastUpdate = Util::getTimeMs(); - m_naviPathStep = 0; - } - else - { - Logger::debug( "No path found for target: {0} {1} {2}", m_naviTarget.x, m_naviTarget.y, m_naviTarget.z ); - } - } - auto stepPos = m_naviLastPath[m_naviPathStep]; - if( Util::distance( getPos().x, getPos().y, getPos().z, stepPos.x, stepPos.y, stepPos.z ) <= 4 ) + if( Util::distance( getPos().x, getPos().y, getPos().z, stepPos.x, stepPos.y, stepPos.z ) <= 4 && m_naviPathStep < m_naviLastPath.size() - 1 ) { // Reached step in path m_naviPathStep++; @@ -192,6 +172,7 @@ void Sapphire::Entity::BNpc::step() stepPos = m_naviLastPath[m_naviPathStep]; } + // This is probably not a good way to do it but works fine for now float rot = Util::calcAngFrom( getPos().x, getPos().z, stepPos.x, stepPos.z ); float newRot = PI - rot + ( PI / 2 ); @@ -199,14 +180,11 @@ void Sapphire::Entity::BNpc::step() float angle = Util::calcAngFrom( getPos().x, getPos().z, stepPos.x, stepPos.z ) + PI; auto x = ( cosf( angle ) * 1.1f ); - auto y = ( getPos().y + stepPos.y ) * 0.5f; // fake value while there is no collision + auto y = ( getPos().y + stepPos.y ) * 0.5f; // Get speed from somewhere else? auto z = ( sinf( angle ) * 1.1f ); Common::FFXIVARR_POSITION3 newPos{ getPos().x + x, y, getPos().z + z }; setPos( newPos ); - - Common::FFXIVARR_POSITION3 tmpPos{ getPos().x + x, y, getPos().z + z }; - setPos( tmpPos ); setRot( newRot ); sendPositionUpdate(); @@ -222,23 +200,26 @@ bool Sapphire::Entity::BNpc::moveTo( const FFXIVARR_POSITION3& pos ) // Targets are the same return false; - auto path = m_pCurrentZone->getNaviProvider()->findFollowPath( m_pos, pos ); - - if( !path.empty() ) + // Check if we have to recalculate + if( Util::getTimeMs() - m_naviLastUpdate > 500 ) { - for( int i = 0; i < path.size(); i++ ) - Logger::debug( "[MOVETO] {0}: {1} {2} {3}", i, path[i].x, path[i].y, path[i].z ); + auto path = m_pCurrentZone->getNaviProvider()->findFollowPath( m_pos, pos ); - m_naviLastPath = path; - m_naviTarget = pos; - m_naviPathStep = 0; - m_naviLastUpdate = Util::getTimeMs(); - } - else - { - Logger::debug( "No path found for target: {0} {1} {2}", pos.x, pos.y, pos.z ); - } + if( !path.empty() ) + { + for( int i = 0; i < path.size(); i++ ) + Logger::debug( "[MOVETO] {0}: {1} {2} {3}", i, path[i].x, path[i].y, path[i].z ); + m_naviLastPath = path; + m_naviTarget = pos; + m_naviPathStep = 0; + m_naviLastUpdate = Util::getTimeMs(); + } + else + { + Logger::debug( "No path found for target: {0} {1} {2}", pos.x, pos.y, pos.z ); + } + } /* float rot = Util::calcAngFrom( getPos().x, getPos().z, pos.x, pos.z ); float newRot = PI - rot + ( PI / 2 ); From 9423a8576edd9913a4e48f0089013cb770ab139e Mon Sep 17 00:00:00 2001 From: goaaats Date: Wed, 23 Jan 2019 19:23:49 +0100 Subject: [PATCH 10/15] Add NaviMgr --- src/world/Actor/BNpc.cpp | 13 ++++++++++++- src/world/Manager/NaviMgr.cpp | 29 ++++++++++++++++++++++++++++ src/world/Manager/NaviMgr.h | 31 ++++++++++++++++++++++++++++++ src/world/Manager/TerritoryMgr.cpp | 10 +++++++--- src/world/Navi/NaviProvider.cpp | 17 +++++++++------- src/world/Navi/NaviProvider.h | 7 +++---- src/world/ServerMgr.cpp | 20 +++++++++++-------- src/world/Territory/Zone.cpp | 8 -------- src/world/Territory/Zone.h | 4 ---- 9 files changed, 104 insertions(+), 35 deletions(-) create mode 100644 src/world/Manager/NaviMgr.cpp create mode 100644 src/world/Manager/NaviMgr.h diff --git a/src/world/Actor/BNpc.cpp b/src/world/Actor/BNpc.cpp index 92d020bd..1f1f7ee7 100644 --- a/src/world/Actor/BNpc.cpp +++ b/src/world/Actor/BNpc.cpp @@ -31,7 +31,9 @@ #include "BNpcTemplate.h" #include "Manager/TerritoryMgr.h" #include "Common.h" +#include "Framework.h" #include +#include using namespace Sapphire::Common; using namespace Sapphire::Network::Packets; @@ -203,7 +205,16 @@ bool Sapphire::Entity::BNpc::moveTo( const FFXIVARR_POSITION3& pos ) // Check if we have to recalculate if( Util::getTimeMs() - m_naviLastUpdate > 500 ) { - auto path = m_pCurrentZone->getNaviProvider()->findFollowPath( m_pos, pos ); + auto pNaviMgr = m_pFw->get< World::Manager::NaviMgr >(); + auto pNaviProvider = pNaviMgr->getNaviProvider( m_pCurrentZone->getInternalName() ); + + if(!pNaviProvider) + { + Logger::error( "No NaviProvider for zone#{0} - {1}", m_pCurrentZone->getGuId(), m_pCurrentZone->getInternalName() ); + return false; + } + + auto path = pNaviProvider->findFollowPath( m_pos, pos ); if( !path.empty() ) { diff --git a/src/world/Manager/NaviMgr.cpp b/src/world/Manager/NaviMgr.cpp new file mode 100644 index 00000000..9b6f161c --- /dev/null +++ b/src/world/Manager/NaviMgr.cpp @@ -0,0 +1,29 @@ +#include "NaviMgr.h" +#include + +Sapphire::World::Manager::NaviMgr::NaviMgr( FrameworkPtr pFw ) : + BaseManager( pFw ), + m_pFw( pFw ) +{ +} + +bool Sapphire::World::Manager::NaviMgr::setupTerritory( std::string internalName ) +{ + auto provider = new NaviProvider( internalName ); + + if( provider->init() ) + { + m_naviProviderTerritoryMap.insert( std::make_pair( internalName, provider ) ); + return true; + } + + return false; +} + +Sapphire::NaviProvider* Sapphire::World::Manager::NaviMgr::getNaviProvider( std::string internalName ) +{ + if( m_naviProviderTerritoryMap.find( internalName ) != m_naviProviderTerritoryMap.end() ) + return m_naviProviderTerritoryMap[internalName]; + + return nullptr; +} diff --git a/src/world/Manager/NaviMgr.h b/src/world/Manager/NaviMgr.h new file mode 100644 index 00000000..5dee0c87 --- /dev/null +++ b/src/world/Manager/NaviMgr.h @@ -0,0 +1,31 @@ +#ifndef SAPPHIRE_NAVIMGR_H +#define SAPPHIRE_NAVIMGR_H + +#include "Forwards.h" +#include "BaseManager.h" + +#include +#include + +namespace Sapphire::World::Manager +{ + class NaviMgr : public BaseManager + { + + public: + + NaviMgr( FrameworkPtr pFw ); + virtual ~NaviMgr() = default; + + bool setupTerritory( std::string internalName ); + NaviProvider* getNaviProvider( std::string internalName ); + + private: + FrameworkPtr m_pFw; + + std::unordered_map m_naviProviderTerritoryMap; + }; + +} + +#endif // SAPPHIRE_NAVIMGR_H diff --git a/src/world/Manager/TerritoryMgr.cpp b/src/world/Manager/TerritoryMgr.cpp index 09885244..fcbb4223 100644 --- a/src/world/Manager/TerritoryMgr.cpp +++ b/src/world/Manager/TerritoryMgr.cpp @@ -16,6 +16,7 @@ #include "Territory/Land.h" #include "Territory/House.h" #include "Territory/Housing/HousingInteriorTerritory.h" +#include "NaviMgr.h" Sapphire::World::Manager::TerritoryMgr::TerritoryMgr( Sapphire::FrameworkPtr pFw ) : BaseManager( pFw ), @@ -163,8 +164,8 @@ bool Sapphire::World::Manager::TerritoryMgr::createDefaultTerritories() uint32_t guid = getNextInstanceId(); - auto pZone = make_Zone( territoryTypeId, guid, territoryInfo->name, pPlaceName->name, framework() ); - pZone->init(); + auto pNaviMgr = framework()->get< Manager::NaviMgr >(); + bool hasNaviMesh = pNaviMgr->setupTerritory( territoryInfo->name ); Logger::info( "{0}\t{1}\t{2}\t{3:<10}\t{4}\t{5}\t{6}", territoryTypeId, @@ -173,7 +174,10 @@ bool Sapphire::World::Manager::TerritoryMgr::createDefaultTerritories() territoryInfo->name, ( isPrivateTerritory( territoryTypeId ) ? "PRIVATE" : "PUBLIC" ), pPlaceName->name, - pZone->getNaviProvider()->hasNaviMesh() ? "NAVI" : ""); + hasNaviMesh ? "NAVI" : ""); + + auto pZone = make_Zone( territoryTypeId, guid, territoryInfo->name, pPlaceName->name, framework() ); + pZone->init(); InstanceIdToZonePtrMap instanceMap; instanceMap[ guid ] = pZone; diff --git a/src/world/Navi/NaviProvider.cpp b/src/world/Navi/NaviProvider.cpp index 064095dc..e50660c3 100644 --- a/src/world/Navi/NaviProvider.cpp +++ b/src/world/Navi/NaviProvider.cpp @@ -13,11 +13,10 @@ #include #include -Sapphire::NaviProvider::NaviProvider( Sapphire::ZonePtr pZone, Sapphire::FrameworkPtr pFw ) : - m_pFw( pFw ), - m_pZone( pZone ), +Sapphire::NaviProvider::NaviProvider( std::string internalName ) : m_naviMesh( nullptr ), - m_naviMeshQuery( nullptr ) + m_naviMeshQuery( nullptr ), + m_internalName( internalName ) { // Set defaults m_polyFindRange[0] = 10; @@ -25,14 +24,14 @@ Sapphire::NaviProvider::NaviProvider( Sapphire::ZonePtr pZone, Sapphire::Framewo m_polyFindRange[2] = 10; } -void Sapphire::NaviProvider::init() +bool Sapphire::NaviProvider::init() { auto meshesFolder = std::filesystem::path( "navi" ); - auto meshFolder = meshesFolder / std::filesystem::path( m_pZone->getInternalName() ); + auto meshFolder = meshesFolder / std::filesystem::path( m_internalName ); if( std::filesystem::exists( meshFolder ) ) { - auto baseMesh = meshFolder / std::filesystem::path( m_pZone->getInternalName() + ".nav" ); + auto baseMesh = meshFolder / std::filesystem::path( m_internalName + ".nav" ); loadMesh( baseMesh.string() ); @@ -50,7 +49,11 @@ void Sapphire::NaviProvider::init() */ initQuery(); + + return true; } + + return false; } bool Sapphire::NaviProvider::hasNaviMesh() const diff --git a/src/world/Navi/NaviProvider.h b/src/world/Navi/NaviProvider.h index 5b9592da..3b0424db 100644 --- a/src/world/Navi/NaviProvider.h +++ b/src/world/Navi/NaviProvider.h @@ -33,9 +33,9 @@ namespace Sapphire static const int MAX_SMOOTH = 2048; public: - NaviProvider( const ZonePtr pZone, Sapphire::FrameworkPtr pFw ); + NaviProvider( const std::string internalName ); - void init(); + bool init(); void loadMesh( std::string path ); void initQuery(); @@ -47,8 +47,7 @@ namespace Sapphire bool hasNaviMesh() const; protected: - FrameworkPtr m_pFw; - ZonePtr m_pZone; + std::string m_internalName; dtNavMesh* m_naviMesh; dtNavMeshQuery* m_naviMeshQuery; diff --git a/src/world/ServerMgr.cpp b/src/world/ServerMgr.cpp index 3de61f73..24624678 100644 --- a/src/world/ServerMgr.cpp +++ b/src/world/ServerMgr.cpp @@ -41,6 +41,7 @@ #include "Manager/ItemMgr.h" #include "Manager/MarketMgr.h" #include "Manager/RNGMgr.h" +#include "Manager/NaviMgr.h" using namespace Sapphire::World::Manager; @@ -166,6 +167,9 @@ void Sapphire::World::ServerMgr::run( int32_t argc, char* argv[] ) loadBNpcTemplates(); + auto pNaviMgr = std::make_shared< Manager::NaviMgr >( framework() ); + framework()->set< Manager::NaviMgr >( pNaviMgr ); + Logger::info( "TerritoryMgr: Setting up zones" ); auto pTeriMgr = std::make_shared< Manager::TerritoryMgr >( framework() ); auto pHousingMgr = std::make_shared< Manager::HousingMgr >( framework() ); @@ -343,7 +347,7 @@ bool Sapphire::World::ServerMgr::createSession( uint32_t sessionId ) Logger::info( "[{0}] Creating new session", session_id_str ); std::shared_ptr< Session > newSession( new Session( sessionId, framework() ) ); - m_sessionMapById[ sessionId ] = newSession; + m_sessionMapById[sessionId] = newSession; if( !newSession->loadPlayer() ) { @@ -351,7 +355,7 @@ bool Sapphire::World::ServerMgr::createSession( uint32_t sessionId ) return false; } - m_sessionMapByName[ newSession->getPlayer()->getName() ] = newSession; + m_sessionMapByName[newSession->getPlayer()->getName()] = newSession; return true; @@ -420,7 +424,7 @@ std::string Sapphire::World::ServerMgr::getPlayerNameFromDb( uint32_t playerId, void Sapphire::World::ServerMgr::updatePlayerName( uint32_t playerId, const std::string & playerNewName ) { - m_playerNameMapById[ playerId ] = playerNewName; + m_playerNameMapById[playerId] = playerNewName; } void Sapphire::World::ServerMgr::loadBNpcTemplates() @@ -452,12 +456,12 @@ void Sapphire::World::ServerMgr::loadBNpcTemplates() auto models = res->getBlobVector( 13 ); auto bnpcTemplate = std::make_shared< Entity::BNpcTemplate >( - id, bNPCBaseId, bNPCNameId, mainWeaponModel, secWeaponModel, - aggressionMode, enemyType, 0, pose, modelChara, displayFlags, - reinterpret_cast< uint32_t* >( &models[ 0 ] ), - reinterpret_cast< uint8_t* >( &look[ 0 ] ) ); + id, bNPCBaseId, bNPCNameId, mainWeaponModel, secWeaponModel, + aggressionMode, enemyType, 0, pose, modelChara, displayFlags, + reinterpret_cast( &models[0] ), + reinterpret_cast( &look[0] ) ); - m_bNpcTemplateMap[ name ] = bnpcTemplate; + m_bNpcTemplateMap[name] = bnpcTemplate; } Logger::debug( "BNpc Templates loaded: {0}", m_bNpcTemplateMap.size() ); diff --git a/src/world/Territory/Zone.cpp b/src/world/Territory/Zone.cpp index 5e53b5eb..6dcad395 100644 --- a/src/world/Territory/Zone.cpp +++ b/src/world/Territory/Zone.cpp @@ -124,9 +124,6 @@ bool Sapphire::Zone::init() // all good } - m_naviProvider = new NaviProvider( shared_from_this(), m_pFw ); - m_naviProvider->init(); - return true; } @@ -852,8 +849,3 @@ void Sapphire::Zone::updateSpawnPoints() } -Sapphire::NaviProvider* Sapphire::Zone::getNaviProvider() const -{ - return m_naviProvider; -} - diff --git a/src/world/Territory/Zone.h b/src/world/Territory/Zone.h index b556bff4..ac436be7 100644 --- a/src/world/Territory/Zone.h +++ b/src/world/Territory/Zone.h @@ -63,8 +63,6 @@ namespace Sapphire std::vector< Entity::SpawnGroup > m_spawnGroups; - NaviProvider* m_naviProvider; - public: Zone(); @@ -161,8 +159,6 @@ namespace Sapphire InstanceContentPtr getAsInstanceContent(); void updateSpawnPoints(); - - NaviProvider* getNaviProvider() const; }; } From 1ac495192a8f8884b6aeba96a6a2708f066207bb Mon Sep 17 00:00:00 2001 From: goaaats Date: Wed, 23 Jan 2019 21:10:53 +0100 Subject: [PATCH 11/15] Cleanup --- src/world/Actor/BNpc.cpp | 10 ++---- src/world/Navi/NaviProvider.cpp | 60 +++++++++------------------------ src/world/Navi/NaviProvider.h | 12 +++++++ src/world/Territory/Zone.cpp | 4 +-- src/world/Territory/Zone.h | 1 - 5 files changed, 32 insertions(+), 55 deletions(-) diff --git a/src/world/Actor/BNpc.cpp b/src/world/Actor/BNpc.cpp index 1f1f7ee7..93de9409 100644 --- a/src/world/Actor/BNpc.cpp +++ b/src/world/Actor/BNpc.cpp @@ -169,7 +169,6 @@ void Sapphire::Entity::BNpc::step() { // Reached step in path m_naviPathStep++; - Logger::debug( "Reached step {0}", m_naviPathStep ); stepPos = m_naviLastPath[m_naviPathStep]; } @@ -218,9 +217,6 @@ bool Sapphire::Entity::BNpc::moveTo( const FFXIVARR_POSITION3& pos ) if( !path.empty() ) { - for( int i = 0; i < path.size(); i++ ) - Logger::debug( "[MOVETO] {0}: {1} {2} {3}", i, path[i].x, path[i].y, path[i].z ); - m_naviLastPath = path; m_naviTarget = pos; m_naviPathStep = 0; @@ -228,11 +224,11 @@ bool Sapphire::Entity::BNpc::moveTo( const FFXIVARR_POSITION3& pos ) } else { - Logger::debug( "No path found for target: {0} {1} {2}", pos.x, pos.y, pos.z ); + Logger::debug( "No path found for target: {0} {1} {2} in ", pos.x, pos.y, pos.z, m_pCurrentZone->getInternalName() ); } } /* - float rot = Util::calcAngFrom( getPos().x, getPos().z, pos.x, pos.z ); + float rot = Util::calcAngFrom( getPos().x, getPos().z, pos.x, pos.z ); float newRot = PI - rot + ( PI / 2 ); face( pos ); @@ -379,7 +375,7 @@ void Sapphire::Entity::BNpc::update( int64_t currTime ) { const uint8_t minActorDistance = 4; const uint8_t aggroRange = 8; - const uint8_t maxDistanceToOrigin = 1000; + const uint8_t maxDistanceToOrigin = 40; if( m_status == ActorStatus::Dead ) return; diff --git a/src/world/Navi/NaviProvider.cpp b/src/world/Navi/NaviProvider.cpp index e50660c3..dbba2801 100644 --- a/src/world/Navi/NaviProvider.cpp +++ b/src/world/Navi/NaviProvider.cpp @@ -1,17 +1,16 @@ #include -#include +#include +#include +#include -#include "Framework.h" #include "NaviProvider.h" + #include #include -#include -#include - -#include "../Territory/Zone.h" -#include #include #include +#include + Sapphire::NaviProvider::NaviProvider( std::string internalName ) : m_naviMesh( nullptr ), @@ -26,28 +25,15 @@ Sapphire::NaviProvider::NaviProvider( std::string internalName ) : bool Sapphire::NaviProvider::init() { - auto meshesFolder = std::filesystem::path( "navi" ); - auto meshFolder = meshesFolder / std::filesystem::path( m_internalName ); + auto meshesFolder = std::experimental::filesystem::path( "navi" ); + auto meshFolder = meshesFolder / std::experimental::filesystem::path( m_internalName ); - if( std::filesystem::exists( meshFolder ) ) + if( std::experimental::filesystem::exists( meshFolder ) ) { - auto baseMesh = meshFolder / std::filesystem::path( m_internalName + ".nav" ); + auto baseMesh = meshFolder / std::experimental::filesystem::path( m_internalName + ".nav" ); loadMesh( baseMesh.string() ); - // Load all meshes for testing - - /* - for( const auto & entry : std::filesystem::directory_iterator( meshFolder ) ) - { - if( entry.path().extension().string() == ".nav" ) - { - Logger::debug( "Loading " + entry.path().string() ); - LoadMesh( entry.path().string() ); - } - } - */ - initQuery(); return true; @@ -70,7 +56,7 @@ void Sapphire::NaviProvider::initQuery() m_naviMeshQuery->init( m_naviMesh, 2048 ); } -static int fixupCorridor( dtPolyRef* path, const int npath, const int maxPath, +int Sapphire::NaviProvider::fixupCorridor( dtPolyRef* path, const int npath, const int maxPath, const dtPolyRef* visited, const int nvisited ) { int furthestPath = -1; @@ -115,7 +101,7 @@ static int fixupCorridor( dtPolyRef* path, const int npath, const int maxPath, return req + size; } -static int fixupShortcuts( dtPolyRef* path, int npath, dtNavMeshQuery* navQuery ) +int Sapphire::NaviProvider::fixupShortcuts( dtPolyRef* path, int npath, dtNavMeshQuery* navQuery ) { if( npath < 3 ) return npath; @@ -164,7 +150,7 @@ static int fixupShortcuts( dtPolyRef* path, int npath, dtNavMeshQuery* navQuery return npath; } -inline bool inRange( const float* v1, const float* v2, const float r, const float h ) +bool Sapphire::NaviProvider::inRange( const float* v1, const float* v2, const float r, const float h ) { const float dx = v2[0] - v1[0]; const float dy = v2[1] - v1[1]; @@ -172,11 +158,11 @@ inline bool inRange( const float* v1, const float* v2, const float r, const floa return ( dx*dx + dz * dz ) < r*r && fabsf( dy ) < h; } -static bool getSteerTarget( dtNavMeshQuery* navQuery, const float* startPos, const float* endPos, +bool Sapphire::NaviProvider::getSteerTarget( dtNavMeshQuery* navQuery, const float* startPos, const float* endPos, const float minTargetDist, const dtPolyRef* path, const int pathSize, float* steerPos, unsigned char& steerPosFlag, dtPolyRef& steerPosRef, - float* outPoints = 0, int* outPointCount = 0 ) + float* outPoints, int* outPointCount ) { // Find steer target. static const int MAX_STEER_POINTS = 3; @@ -219,22 +205,6 @@ static bool getSteerTarget( dtNavMeshQuery* navQuery, const float* startPos, con return true; } -void Sapphire::NaviProvider::toDetourPos( const Sapphire::Common::FFXIVARR_POSITION3 pos, float* out ) { - float y = pos.y; - float z = pos.z; - - out[0] = pos.x; - out[1] = y * -1; - out[2] = z * -1; -} - -Sapphire::Common::FFXIVARR_POSITION3 Sapphire::NaviProvider::toGamePos( float* pos ) { - float y = pos[1]; - float z = pos[2]; - - return Common::FFXIVARR_POSITION3 { pos[0], y * -1, z * -1 }; -} - std::vector< Sapphire::Common::FFXIVARR_POSITION3 > Sapphire::NaviProvider::findFollowPath( Common::FFXIVARR_POSITION3 startPos, Common::FFXIVARR_POSITION3 endPos ) { if( !m_naviMesh || !m_naviMeshQuery ) diff --git a/src/world/Navi/NaviProvider.h b/src/world/Navi/NaviProvider.h index 3b0424db..3108a47a 100644 --- a/src/world/Navi/NaviProvider.h +++ b/src/world/Navi/NaviProvider.h @@ -53,6 +53,18 @@ namespace Sapphire dtNavMeshQuery* m_naviMeshQuery; float m_polyFindRange[3]; + + private: + static int fixupCorridor( dtPolyRef* path, const int npath, const int maxPath, + const dtPolyRef* visited, const int nvisited ); + static int fixupShortcuts( dtPolyRef* path, int npath, dtNavMeshQuery* navQuery ); + inline static bool inRange( const float* v1, const float* v2, const float r, const float h ); + static bool getSteerTarget( dtNavMeshQuery* navQuery, const float* startPos, const float* endPos, + const float minTargetDist, + const dtPolyRef* path, const int pathSize, + float* steerPos, unsigned char& steerPosFlag, dtPolyRef& steerPosRef, + float* outPoints = 0, int* outPointCount = 0 ); + }; } diff --git a/src/world/Territory/Zone.cpp b/src/world/Territory/Zone.cpp index 6dcad395..f5be48e3 100644 --- a/src/world/Territory/Zone.cpp +++ b/src/world/Territory/Zone.cpp @@ -722,7 +722,7 @@ void Sapphire::Zone::registerEObj( Entity::EventObjectPtr object ) onRegisterEObj( object ); - //Logger::debug( "Registered instance eobj: " + std::to_string( object->getId() ) ); + Logger::debug( "Registered instance eobj: " + std::to_string( object->getId() ) ); } Sapphire::Entity::EventObjectPtr Sapphire::Zone::getEObj( uint32_t objId ) @@ -782,7 +782,7 @@ bool Sapphire::Zone::loadSpawnGroups() m_spawnGroups.emplace_back( id, templateId, level, maxHp ); - //Logger::debug( "id: {0}, template: {1}, level: {2}, maxHp: {3}", id, m_spawnGroups.back().getTemplateId(), level, maxHp ); + Logger::debug( "id: {0}, template: {1}, level: {2}, maxHp: {3}", id, m_spawnGroups.back().getTemplateId(), level, maxHp ); } res.reset(); diff --git a/src/world/Territory/Zone.h b/src/world/Territory/Zone.h index ac436be7..657b99c9 100644 --- a/src/world/Territory/Zone.h +++ b/src/world/Territory/Zone.h @@ -6,7 +6,6 @@ #include "Cell.h" #include "CellHandler.h" -#include "Navi/NaviProvider.h" #include "ForwardsZone.h" From 116af3409e6105bf62e543c1ac49cd09aee872c0 Mon Sep 17 00:00:00 2001 From: goaaats Date: Wed, 23 Jan 2019 21:14:17 +0100 Subject: [PATCH 12/15] Uncomment logs --- src/world/Territory/Zone.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/world/Territory/Zone.cpp b/src/world/Territory/Zone.cpp index f5be48e3..e1594560 100644 --- a/src/world/Territory/Zone.cpp +++ b/src/world/Territory/Zone.cpp @@ -722,7 +722,7 @@ void Sapphire::Zone::registerEObj( Entity::EventObjectPtr object ) onRegisterEObj( object ); - Logger::debug( "Registered instance eobj: " + std::to_string( object->getId() ) ); + //Logger::debug( "Registered instance eobj: " + std::to_string( object->getId() ) ); } Sapphire::Entity::EventObjectPtr Sapphire::Zone::getEObj( uint32_t objId ) @@ -805,7 +805,7 @@ bool Sapphire::Zone::loadSpawnGroups() group.getSpawnPointList().emplace_back( std::make_shared< Entity::SpawnPoint >( x, y, z, r, gimmickId ) ); - //Logger::debug( "id: {0}, x: {1}, y: {2}, z: {3}, gimmickId: {4}", id, x, y, z, gimmickId ); + Logger::debug( "id: {0}, x: {1}, y: {2}, z: {3}, gimmickId: {4}", id, x, y, z, gimmickId ); } } return false; From 258eb1d1abd7b30494446c77a3d06deaf4a521a8 Mon Sep 17 00:00:00 2001 From: goaaats Date: Wed, 23 Jan 2019 21:26:48 +0100 Subject: [PATCH 13/15] Style --- src/world/Actor/BNpc.cpp | 2 +- src/world/Manager/DebugCommandMgr.cpp | 8 ++++---- src/world/Navi/NaviProvider.h | 9 ++------- 3 files changed, 7 insertions(+), 12 deletions(-) diff --git a/src/world/Actor/BNpc.cpp b/src/world/Actor/BNpc.cpp index 78990c0f..70250b62 100644 --- a/src/world/Actor/BNpc.cpp +++ b/src/world/Actor/BNpc.cpp @@ -211,7 +211,7 @@ bool Sapphire::Entity::BNpc::moveTo( const FFXIVARR_POSITION3& pos ) auto pNaviMgr = m_pFw->get< World::Manager::NaviMgr >(); auto pNaviProvider = pNaviMgr->getNaviProvider( m_pCurrentZone->getInternalName() ); - if(!pNaviProvider) + if( !pNaviProvider ) { Logger::error( "No NaviProvider for zone#{0} - {1}", m_pCurrentZone->getGuId(), m_pCurrentZone->getInternalName() ); return false; diff --git a/src/world/Manager/DebugCommandMgr.cpp b/src/world/Manager/DebugCommandMgr.cpp index 70bec2eb..e79e3d2c 100644 --- a/src/world/Manager/DebugCommandMgr.cpp +++ b/src/world/Manager/DebugCommandMgr.cpp @@ -372,12 +372,12 @@ void Sapphire::World::Manager::DebugCommandMgr::set( char* data, Entity::Player& auto inRange = player.getInRangeActors(); for( auto actor : inRange ) + { + if( actor->getId() == player.getTargetId() && actor->getAsChara()->isAlive() ) { - if( actor->getId() == player.getTargetId() && actor->getAsChara()->isAlive() ) - { - actor->getAsBNpc()->onActionHostile( player.getAsChara() ); - } + actor->getAsBNpc()->onActionHostile( player.getAsChara() ); } + } } else { diff --git a/src/world/Navi/NaviProvider.h b/src/world/Navi/NaviProvider.h index 3108a47a..3f54c502 100644 --- a/src/world/Navi/NaviProvider.h +++ b/src/world/Navi/NaviProvider.h @@ -55,15 +55,10 @@ namespace Sapphire float m_polyFindRange[3]; private: - static int fixupCorridor( dtPolyRef* path, const int npath, const int maxPath, - const dtPolyRef* visited, const int nvisited ); + static int fixupCorridor( dtPolyRef* path, const int npath, const int maxPath, const dtPolyRef* visited, const int nvisited ); static int fixupShortcuts( dtPolyRef* path, int npath, dtNavMeshQuery* navQuery ); inline static bool inRange( const float* v1, const float* v2, const float r, const float h ); - static bool getSteerTarget( dtNavMeshQuery* navQuery, const float* startPos, const float* endPos, - const float minTargetDist, - const dtPolyRef* path, const int pathSize, - float* steerPos, unsigned char& steerPosFlag, dtPolyRef& steerPosRef, - float* outPoints = 0, int* outPointCount = 0 ); + static bool getSteerTarget( dtNavMeshQuery* navQuery, const float* startPos, const float* endPos, const float minTargetDist, const dtPolyRef* path, const int pathSize, float* steerPos, unsigned char& steerPosFlag, dtPolyRef& steerPosRef, float* outPoints = 0, int* outPointCount = 0 ); }; From 25478e3a1c4ebb8ebbf911e28a083bdc2a5c7a72 Mon Sep 17 00:00:00 2001 From: goaaats Date: Wed, 23 Jan 2019 21:36:26 +0100 Subject: [PATCH 14/15] Spaces --- src/world/Actor/BNpc.cpp | 4 ++-- src/world/Manager/NaviMgr.cpp | 2 +- src/world/ServerMgr.cpp | 18 +++++++++--------- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/world/Actor/BNpc.cpp b/src/world/Actor/BNpc.cpp index 70250b62..c13f2fe3 100644 --- a/src/world/Actor/BNpc.cpp +++ b/src/world/Actor/BNpc.cpp @@ -167,14 +167,14 @@ void Sapphire::Entity::BNpc::step() return; } - auto stepPos = m_naviLastPath[m_naviPathStep]; + auto stepPos = m_naviLastPath[ m_naviPathStep ]; if( Util::distance( getPos().x, getPos().y, getPos().z, stepPos.x, stepPos.y, stepPos.z ) <= 4 && m_naviPathStep < m_naviLastPath.size() - 1 ) { // Reached step in path m_naviPathStep++; - stepPos = m_naviLastPath[m_naviPathStep]; + stepPos = m_naviLastPath[ m_naviPathStep ]; } // This is probably not a good way to do it but works fine for now diff --git a/src/world/Manager/NaviMgr.cpp b/src/world/Manager/NaviMgr.cpp index 9b6f161c..9300aa3f 100644 --- a/src/world/Manager/NaviMgr.cpp +++ b/src/world/Manager/NaviMgr.cpp @@ -23,7 +23,7 @@ bool Sapphire::World::Manager::NaviMgr::setupTerritory( std::string internalName Sapphire::NaviProvider* Sapphire::World::Manager::NaviMgr::getNaviProvider( std::string internalName ) { if( m_naviProviderTerritoryMap.find( internalName ) != m_naviProviderTerritoryMap.end() ) - return m_naviProviderTerritoryMap[internalName]; + return m_naviProviderTerritoryMap[ internalName ]; return nullptr; } diff --git a/src/world/ServerMgr.cpp b/src/world/ServerMgr.cpp index 24624678..be23f8c9 100644 --- a/src/world/ServerMgr.cpp +++ b/src/world/ServerMgr.cpp @@ -347,7 +347,7 @@ bool Sapphire::World::ServerMgr::createSession( uint32_t sessionId ) Logger::info( "[{0}] Creating new session", session_id_str ); std::shared_ptr< Session > newSession( new Session( sessionId, framework() ) ); - m_sessionMapById[sessionId] = newSession; + m_sessionMapById[ sessionId ] = newSession; if( !newSession->loadPlayer() ) { @@ -355,7 +355,7 @@ bool Sapphire::World::ServerMgr::createSession( uint32_t sessionId ) return false; } - m_sessionMapByName[newSession->getPlayer()->getName()] = newSession; + m_sessionMapByName[ newSession->getPlayer()->getName() ] = newSession; return true; @@ -424,7 +424,7 @@ std::string Sapphire::World::ServerMgr::getPlayerNameFromDb( uint32_t playerId, void Sapphire::World::ServerMgr::updatePlayerName( uint32_t playerId, const std::string & playerNewName ) { - m_playerNameMapById[playerId] = playerNewName; + m_playerNameMapById[ playerId ] = playerNewName; } void Sapphire::World::ServerMgr::loadBNpcTemplates() @@ -455,13 +455,13 @@ void Sapphire::World::ServerMgr::loadBNpcTemplates() auto look = res->getBlobVector( 12 ); auto models = res->getBlobVector( 13 ); - auto bnpcTemplate = std::make_shared< Entity::BNpcTemplate >( - id, bNPCBaseId, bNPCNameId, mainWeaponModel, secWeaponModel, - aggressionMode, enemyType, 0, pose, modelChara, displayFlags, - reinterpret_cast( &models[0] ), - reinterpret_cast( &look[0] ) ); + auto bnpcTemplate = std::make_shared< Entity::BNpcTemplate >( + id, bNPCBaseId, bNPCNameId, mainWeaponModel, secWeaponModel, + aggressionMode, enemyType, 0, pose, modelChara, displayFlags, + reinterpret_cast< uint32_t* >( &models[ 0 ] ), + reinterpret_cast< uint8_t* >( &look[ 0 ] ) ); - m_bNpcTemplateMap[name] = bnpcTemplate; + m_bNpcTemplateMap[ name ] = bnpcTemplate; } Logger::debug( "BNpc Templates loaded: {0}", m_bNpcTemplateMap.size() ); From 8da67dd2c5b6ded9587d4c7fea3d20efbd93366f Mon Sep 17 00:00:00 2001 From: goaaats Date: Wed, 23 Jan 2019 23:50:31 +0100 Subject: [PATCH 15/15] Fix logging, Linux --- src/world/Actor/BNpc.cpp | 2 +- src/world/Navi/NaviProvider.cpp | 26 +++++++++----------------- 2 files changed, 10 insertions(+), 18 deletions(-) diff --git a/src/world/Actor/BNpc.cpp b/src/world/Actor/BNpc.cpp index c13f2fe3..f1cce290 100644 --- a/src/world/Actor/BNpc.cpp +++ b/src/world/Actor/BNpc.cpp @@ -228,7 +228,7 @@ bool Sapphire::Entity::BNpc::moveTo( const FFXIVARR_POSITION3& pos ) } else { - Logger::debug( "No path found for target: {0} {1} {2} in ", pos.x, pos.y, pos.z, m_pCurrentZone->getInternalName() ); + Logger::debug( "No path found from x{0} y{1} z{2} to x{3} y{4} z{5} in {6}", getPos().x, getPos().y, getPos().z, pos.x, pos.y, pos.z, m_pCurrentZone->getInternalName() ); } } /* diff --git a/src/world/Navi/NaviProvider.cpp b/src/world/Navi/NaviProvider.cpp index dbba2801..4e656796 100644 --- a/src/world/Navi/NaviProvider.cpp +++ b/src/world/Navi/NaviProvider.cpp @@ -208,20 +208,12 @@ bool Sapphire::NaviProvider::getSteerTarget( dtNavMeshQuery* navQuery, const flo std::vector< Sapphire::Common::FFXIVARR_POSITION3 > Sapphire::NaviProvider::findFollowPath( Common::FFXIVARR_POSITION3 startPos, Common::FFXIVARR_POSITION3 endPos ) { if( !m_naviMesh || !m_naviMeshQuery ) - throw std::exception( "No navimesh loaded" ); + throw std::runtime_error( "No navimesh loaded" ); auto resultCoords = std::vector< Common::FFXIVARR_POSITION3 >(); dtPolyRef startRef, endRef = 0; - /* - float spos[3]; - NaviProvider::toDetourPos( startPos, spos ); - - float epos[3]; - NaviProvider::toDetourPos( endPos, epos ); - */ - float spos[3] = {startPos.x, startPos.y, startPos.z}; float epos[3] = {endPos.x, endPos.y, endPos.z}; @@ -380,7 +372,7 @@ void Sapphire::NaviProvider::loadMesh( std::string path ) { FILE* fp = fopen( path.c_str(), "rb" ); if( !fp ) - throw std::exception( "Could open navimesh file" ); + throw std::runtime_error( "Could open navimesh file" ); // Read header. NavMeshSetHeader header; @@ -389,19 +381,19 @@ void Sapphire::NaviProvider::loadMesh( std::string path ) if( readLen != 1 ) { fclose( fp ); - throw std::exception( "Could not read NavMeshSetHeader" ); + throw std::runtime_error( "Could not read NavMeshSetHeader" ); } if( header.magic != NAVMESHSET_MAGIC ) { fclose( fp ); - throw std::exception( "Not a NavMeshSet" ); + throw std::runtime_error( "Not a NavMeshSet" ); } if( header.version != NAVMESHSET_VERSION ) { fclose( fp ); - throw std::exception( "Invalid NavMeshSet version" ); + throw std::runtime_error( "Invalid NavMeshSet version" ); } if( !m_naviMesh ) @@ -410,14 +402,14 @@ void Sapphire::NaviProvider::loadMesh( std::string path ) if( !m_naviMesh ) { fclose( fp ); - throw std::exception( "Could not allocate dtNavMesh" ); + throw std::runtime_error( "Could not allocate dtNavMesh" ); } dtStatus status = m_naviMesh->init( &header.params ); if( dtStatusFailed( status ) ) { fclose( fp ); - throw std::exception( "Could not initialize dtNavMesh" ); + throw std::runtime_error( "Could not initialize dtNavMesh" ); } } @@ -429,7 +421,7 @@ void Sapphire::NaviProvider::loadMesh( std::string path ) if( readLen != 1 ) { fclose( fp ); - throw std::exception( "Could not read NavMeshTileHeader" ); + throw std::runtime_error( "Could not read NavMeshTileHeader" ); } if( !tileHeader.tileRef || !tileHeader.dataSize ) @@ -443,7 +435,7 @@ void Sapphire::NaviProvider::loadMesh( std::string path ) { dtFree( data ); fclose( fp ); - throw std::exception( "Could not read tile data" ); + throw std::runtime_error( "Could not read tile data" ); } m_naviMesh->addTile( data, tileHeader.dataSize, DT_TILE_FREE_DATA, tileHeader.tileRef, 0 );