From 018096266aec1b6d4a852b46c2f0c1d691d6c1bb Mon Sep 17 00:00:00 2001 From: Mordred Date: Fri, 19 Apr 2019 00:39:42 +0200 Subject: [PATCH 001/351] Detour crowd experiments --- src/world/Actor/BNpc.cpp | 13 +++++- src/world/Actor/Chara.cpp | 10 +++++ src/world/Actor/Chara.h | 6 +++ src/world/CMakeLists.txt | 3 +- src/world/Manager/TerritoryMgr.cpp | 10 ++--- src/world/Navi/NaviProvider.cpp | 70 ++++++++++++++++++++++++++++++ src/world/Navi/NaviProvider.h | 16 +++++++ src/world/Territory/Zone.cpp | 32 +++++++++++++- src/world/Territory/Zone.h | 3 ++ 9 files changed, 155 insertions(+), 8 deletions(-) diff --git a/src/world/Actor/BNpc.cpp b/src/world/Actor/BNpc.cpp index 93f96f25..e41f08f1 100644 --- a/src/world/Actor/BNpc.cpp +++ b/src/world/Actor/BNpc.cpp @@ -283,8 +283,11 @@ bool Sapphire::Entity::BNpc::moveTo( const FFXIVARR_POSITION3& pos ) } } - step(); + auto pos1 = pNaviProvider->getMovePos( *this ); + + Logger::debug( "{} {} {}", pos1.x, pos1.y, pos1.z ); + setPos( pos1 ); m_pCurrentZone->updateActorPosition( *this ); return false; } @@ -471,6 +474,14 @@ void Sapphire::Entity::BNpc::update( uint64_t tickCount ) 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 ) ) { m_lastRoamTargetReached = Util::getTimeSeconds(); diff --git a/src/world/Actor/Chara.cpp b/src/world/Actor/Chara.cpp index 7fcae496..3af406f6 100644 --- a/src/world/Actor/Chara.cpp +++ b/src/world/Actor/Chara.cpp @@ -702,3 +702,13 @@ void Sapphire::Entity::Chara::setDirectorId( uint32_t 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; +} diff --git a/src/world/Actor/Chara.h b/src/world/Actor/Chara.h index 0f219638..a6a95776 100644 --- a/src/world/Actor/Chara.h +++ b/src/world/Actor/Chara.h @@ -128,6 +128,9 @@ namespace Sapphire::Entity std::map< uint8_t, StatusEffect::StatusEffectPtr > m_statusEffectMap; FrameworkPtr m_pFw; + /*! Detour Crowd AgentId */ + uint32_t m_agentId; + public: Chara( Common::ObjKind type, FrameworkPtr pFw ); @@ -269,6 +272,9 @@ namespace Sapphire::Entity uint32_t getDirectorId() const; void setDirectorId( uint32_t directorId ); + uint32_t getAgentId() const; + void setAgentId( uint32_t agentId ); + }; } diff --git a/src/world/CMakeLists.txt b/src/world/CMakeLists.txt index 66756f1d..824e9ed8 100644 --- a/src/world/CMakeLists.txt +++ b/src/world/CMakeLists.txt @@ -33,7 +33,8 @@ set_target_properties( world target_link_libraries( world PUBLIC common - Detour) + Detour + DetourCrowd ) target_include_directories( world PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}" diff --git a/src/world/Manager/TerritoryMgr.cpp b/src/world/Manager/TerritoryMgr.cpp index 0ad37bd1..87474f17 100644 --- a/src/world/Manager/TerritoryMgr.cpp +++ b/src/world/Manager/TerritoryMgr.cpp @@ -180,9 +180,12 @@ bool Sapphire::World::Manager::TerritoryMgr::createDefaultTerritories() 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; - 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}", territoryTypeId, @@ -193,9 +196,6 @@ bool Sapphire::World::Manager::TerritoryMgr::createDefaultTerritories() hasNaviMesh ? "NAVI" : "", pPlaceName->name ); - auto pZone = make_Zone( territoryTypeId, guid, territoryInfo->name, pPlaceName->name, framework() ); - pZone->init(); - InstanceIdToZonePtrMap instanceMap; instanceMap[ guid ] = pZone; m_guIdToZonePtrMap[ guid ] = pZone; diff --git a/src/world/Navi/NaviProvider.cpp b/src/world/Navi/NaviProvider.cpp index 2ba88eeb..edcbabe3 100644 --- a/src/world/Navi/NaviProvider.cpp +++ b/src/world/Navi/NaviProvider.cpp @@ -4,6 +4,9 @@ #include #include +#include "Actor/Actor.h" +#include "Actor/Chara.h" + #include #include "NaviProvider.h" @@ -40,6 +43,11 @@ bool Sapphire::World::Navi::NaviProvider::init() if( !loadMesh( baseMesh.string() ) ) return false; + m_pCrowd = std::make_unique< dtCrowd >(); + + if( !m_pCrowd->init( 1000, 10.f, m_naviMesh ) ) + return false; + initQuery(); return true; @@ -521,3 +529,65 @@ bool Sapphire::World::Navi::NaviProvider::loadMesh( const std::string& path ) 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 ] }; +} \ No newline at end of file diff --git a/src/world/Navi/NaviProvider.h b/src/world/Navi/NaviProvider.h index 8547849f..2ad60cf2 100644 --- a/src/world/Navi/NaviProvider.h +++ b/src/world/Navi/NaviProvider.h @@ -5,6 +5,7 @@ #include "ForwardsZone.h" #include #include +#include namespace Sapphire::World::Navi { @@ -47,11 +48,24 @@ namespace Sapphire::World::Navi 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: std::string m_internalName; dtNavMesh* m_naviMesh; dtNavMeshQuery* m_naviMeshQuery; + std::unique_ptr< dtCrowd > m_pCrowd; float m_polyFindRange[ 3 ]; @@ -63,6 +77,8 @@ namespace Sapphire::World::Navi const dtPolyRef* path, const int32_t pathSize, float* steerPos, uint8_t& steerPosFlag, dtPolyRef& steerPosRef, float* outPoints = 0, int32_t* outPointCount = 0 ); + + FrameworkPtr m_pFw; }; diff --git a/src/world/Territory/Zone.cpp b/src/world/Territory/Zone.cpp index cd314158..94c780cd 100644 --- a/src/world/Territory/Zone.cpp +++ b/src/world/Territory/Zone.cpp @@ -19,6 +19,7 @@ #include "InstanceContent.h" #include "QuestBattle.h" #include "Manager/TerritoryMgr.h" +#include "Navi/Naviprovider.h" #include "Session.h" #include "Actor/Chara.h" @@ -41,7 +42,8 @@ #include "Zone.h" #include "Framework.h" -#include +#include "Manager/RNGMgr.h" +#include "Manager/NaviMgr.h" using namespace Sapphire::Common; using namespace Sapphire::Network::Packets; @@ -129,6 +131,11 @@ bool Sapphire::Zone::init() // all good } + auto pNaviMgr = m_pFw->get< World::Manager::NaviMgr >(); + pNaviMgr->setupTerritory( m_territoryTypeInfo->bg ); + + m_pNaviProvider = pNaviMgr->getNaviProvider( m_territoryTypeInfo->bg ); + return true; } @@ -231,10 +238,16 @@ void Sapphire::Zone::pushActor( Entity::ActorPtr pActor ) } } + int32_t agentId = -1; + if( pActor->isPlayer() ) { auto pPlayer = pActor->getAsPlayer(); + if( m_pNaviProvider ) + agentId = m_pNaviProvider->addAgent( *pPlayer ); + pPlayer->setAgentId( agentId ); + auto pServerZone = m_pFw->get< World::ServerMgr >(); m_playerMap[ pPlayer->getId() ] = pPlayer; updateCellActivity( cx, cy, 2 ); @@ -243,6 +256,10 @@ void Sapphire::Zone::pushActor( Entity::ActorPtr pActor ) { auto pBNpc = pActor->getAsBNpc(); + if( m_pNaviProvider ) + agentId = m_pNaviProvider->addAgent( *pBNpc ); + pBNpc->setAgentId( agentId ); + m_bNpcMap[ pBNpc->getId() ] = pBNpc; updateCellActivity( cx, cy, 2 ); @@ -263,6 +280,9 @@ void Sapphire::Zone::removeActor( Entity::ActorPtr pActor ) 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( pActor->getPos().x <= _maxX && pActor->getPos().x >= _minX && pActor->getPos().z <= _maxY && pActor->getPos().z >= _minY ) @@ -278,6 +298,8 @@ void Sapphire::Zone::removeActor( Entity::ActorPtr pActor ) } else if( pActor->isBattleNpc() ) { + if( m_pNaviProvider ) + m_pNaviProvider->removeAgent( *pActor->getAsChara() ); 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 bool changedWeather = checkWeather(); + if( m_pNaviProvider ) + m_pNaviProvider->updateCrowd( 0.001f * tickCount ); + updateSessions( tickCount, changedWeather ); onUpdate( tickCount ); @@ -983,3 +1008,8 @@ Sapphire::Entity::BNpcPtr Sapphire::Zone::getActiveBNpcByLevelId( uint32_t level } return nullptr; } + +std::shared_ptr< Sapphire::World::Navi::NaviProvider > Sapphire::Zone::getNaviProvider() +{ + return m_pNaviProvider; +} diff --git a/src/world/Territory/Zone.h b/src/world/Territory/Zone.h index 3f871f7c..217f0230 100644 --- a/src/world/Territory/Zone.h +++ b/src/world/Territory/Zone.h @@ -63,6 +63,7 @@ namespace Sapphire std::vector< Entity::SpawnGroup > m_spawnGroups; uint32_t m_effectCounter; + std::shared_ptr< World::Navi::NaviProvider > m_pNaviProvider; public: Zone(); @@ -171,6 +172,8 @@ namespace Sapphire void updateSpawnPoints(); uint32_t getNextEffectSequence(); + + std::shared_ptr< World::Navi::NaviProvider > getNaviProvider(); }; } From a344990a63de2f4f4376522cbd7db91dcd3bafd5 Mon Sep 17 00:00:00 2001 From: Mordred Date: Fri, 19 Apr 2019 02:15:18 +0200 Subject: [PATCH 002/351] Crowd avoidance works. Roaming and following a player, not so much --- src/world/Actor/BNpc.cpp | 20 +++++++---- src/world/Navi/NaviProvider.cpp | 59 +++++++++++++++++++++++++++++---- src/world/Navi/NaviProvider.h | 3 ++ src/world/Territory/Zone.cpp | 2 +- 4 files changed, 70 insertions(+), 14 deletions(-) diff --git a/src/world/Actor/BNpc.cpp b/src/world/Actor/BNpc.cpp index e41f08f1..bb5e8d4e 100644 --- a/src/world/Actor/BNpc.cpp +++ b/src/world/Actor/BNpc.cpp @@ -232,7 +232,7 @@ bool Sapphire::Entity::BNpc::moveTo( const FFXIVARR_POSITION3& pos ) { // Reached destination m_naviLastPath.clear(); - return true; + // return true; } auto pNaviMgr = m_pFw->get< World::Manager::NaviMgr >(); @@ -246,7 +246,7 @@ bool Sapphire::Entity::BNpc::moveTo( const FFXIVARR_POSITION3& pos ) return false; } - auto path = pNaviProvider->findFollowPath( m_pos, pos ); + /*auto path = pNaviProvider->findFollowPath( m_pos, pos ); if( !path.empty() ) { @@ -283,12 +283,17 @@ bool Sapphire::Entity::BNpc::moveTo( const FFXIVARR_POSITION3& pos ) } } - step(); + step();*/ + + //pNaviProvider->setMoveTarget( *this, pos ); auto pos1 = pNaviProvider->getMovePos( *this ); - Logger::debug( "{} {} {}", pos1.x, pos1.y, pos1.z ); - setPos( pos1 ); + //Logger::debug( "{} {} {}", pos1.x, pos1.y, pos1.z ); + m_pCurrentZone->updateActorPosition( *this ); + face( pos1 ); + setPos( pos1 ); + sendPositionUpdate(); return false; } @@ -477,9 +482,10 @@ void Sapphire::Entity::BNpc::update( uint64_t tickCount ) auto pNaviMgr = m_pFw->get< World::Manager::NaviMgr >(); auto pNaviProvider = pNaviMgr->getNaviProvider( m_pCurrentZone->getBgPath() ); - if( !pNaviProvider ) + if( pNaviProvider ) { - pNaviProvider->setMoveTarget( *this, m_roamPos ); + //if( !pNaviProvider->isAgentActive( *this ) ) + pNaviProvider->setMoveTarget( *this, m_roamPos ); } if( moveTo( m_roamPos ) ) diff --git a/src/world/Navi/NaviProvider.cpp b/src/world/Navi/NaviProvider.cpp index edcbabe3..f17b7f5e 100644 --- a/src/world/Navi/NaviProvider.cpp +++ b/src/world/Navi/NaviProvider.cpp @@ -48,6 +48,42 @@ bool Sapphire::World::Navi::NaviProvider::init() if( !m_pCrowd->init( 1000, 10.f, m_naviMesh ) ) return false; + dtObstacleAvoidanceParams params; + // Use mostly default settings, copy from dtCrowd. + memcpy(¶ms, m_pCrowd->getObstacleAvoidanceParams(0), sizeof(dtObstacleAvoidanceParams)); + + // Low (11) + params.velBias = 0.5f; + params.adaptiveDivs = 5; + params.adaptiveRings = 2; + params.adaptiveDepth = 1; + m_pCrowd->setObstacleAvoidanceParams(0, ¶ms); + + // Medium (22) + params.velBias = 0.5f; + params.adaptiveDivs = 5; + params.adaptiveRings = 2; + params.adaptiveDepth = 2; + m_pCrowd->setObstacleAvoidanceParams(1, ¶ms); + + // Good (45) + params.velBias = 0.5f; + params.adaptiveDivs = 7; + params.adaptiveRings = 2; + params.adaptiveDepth = 3; + m_pCrowd->setObstacleAvoidanceParams(2, ¶ms); + + // High (66) + params.velBias = 0.5f; + params.adaptiveDivs = 7; + params.adaptiveRings = 3; + params.adaptiveDepth = 3; + + m_pCrowd->setObstacleAvoidanceParams(3, ¶ms); + + m_vod = dtAllocObstacleAvoidanceDebugData(); + m_vod->init( 2048 ); + initQuery(); return true; @@ -535,19 +571,23 @@ 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.maxAcceleration = 16.f; + params.maxSpeed = 13.5f; + params.radius = 2.f; params.collisionQueryRange = params.radius * 12.0f; params.pathOptimizationRange = params.radius * 30.0f; - + params.updateFlags = 0; + //params.updateFlags |= DT_CROWD_OBSTACLE_AVOIDANCE; 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; + info.idx = -1; + info.vod = m_vod; m_pCrowd->update( timeInSeconds, &info ); } @@ -574,7 +614,7 @@ void Sapphire::World::Navi::NaviProvider::setMoveTarget( Entity::Chara& chara, const float* halfExtents = m_pCrowd->getQueryExtents(); float vel[ 3 ]; - float p[ 3 ] = { chara.getPos().x, chara.getPos().y, chara.getPos().z }; + float p[ 3 ] = { endPos.x, endPos.y, endPos.z }; const dtCrowdAgent* ag = m_pCrowd->getAgent( chara.getAgentId() ); if( ag && ag->active ) @@ -590,4 +630,11 @@ Sapphire::Common::FFXIVARR_POSITION3 Sapphire::World::Navi::NaviProvider::getMov if( !ag ) return { 0.f, 0.f, 0.f }; return { ag->npos[ 0 ], ag->npos[ 1 ], ag->npos[ 2 ] }; -} \ No newline at end of file +} + +bool Sapphire::World::Navi::NaviProvider::isAgentActive( Entity::Chara& chara ) const +{ + const dtCrowdAgent* ag = m_pCrowd->getAgent( chara.getAgentId() ); + return ag && ag->active; + +} diff --git a/src/world/Navi/NaviProvider.h b/src/world/Navi/NaviProvider.h index 2ad60cf2..9053dcd0 100644 --- a/src/world/Navi/NaviProvider.h +++ b/src/world/Navi/NaviProvider.h @@ -60,11 +60,14 @@ namespace Sapphire::World::Navi Common::FFXIVARR_POSITION3 getMovePos( Entity::Chara& chara ); + bool isAgentActive( Entity::Chara& chara ) const; + protected: std::string m_internalName; dtNavMesh* m_naviMesh; dtNavMeshQuery* m_naviMeshQuery; + dtObstacleAvoidanceDebugData* m_vod; std::unique_ptr< dtCrowd > m_pCrowd; float m_polyFindRange[ 3 ]; diff --git a/src/world/Territory/Zone.cpp b/src/world/Territory/Zone.cpp index 94c780cd..ee52d012 100644 --- a/src/world/Territory/Zone.cpp +++ b/src/world/Territory/Zone.cpp @@ -474,7 +474,7 @@ bool Sapphire::Zone::update( uint64_t tickCount ) bool changedWeather = checkWeather(); if( m_pNaviProvider ) - m_pNaviProvider->updateCrowd( 0.001f * tickCount ); + m_pNaviProvider->updateCrowd( 0.02f ); updateSessions( tickCount, changedWeather ); onUpdate( tickCount ); From a7f31c77a997684f0cb56ce71b9cb76768acc3db Mon Sep 17 00:00:00 2001 From: NotAdam Date: Fri, 19 Apr 2019 18:52:55 +1000 Subject: [PATCH 003/351] fix naviprovider not being set on instances --- src/world/Actor/BNpc.cpp | 47 +++---------------------- src/world/Actor/BNpc.h | 2 -- src/world/Manager/NaviMgr.cpp | 2 +- src/world/Territory/InstanceContent.cpp | 5 ++- src/world/Territory/QuestBattle.cpp | 3 ++ 5 files changed, 13 insertions(+), 46 deletions(-) diff --git a/src/world/Actor/BNpc.cpp b/src/world/Actor/BNpc.cpp index bb5e8d4e..28390970 100644 --- a/src/world/Actor/BNpc.cpp +++ b/src/world/Actor/BNpc.cpp @@ -224,19 +224,15 @@ void Sapphire::Entity::BNpc::step() bool Sapphire::Entity::BNpc::moveTo( const FFXIVARR_POSITION3& pos ) { - // do this first, this will update local actor position and the position of other actors - // and then this npc will then path from the position after pushing/being pushed - //pushNearbyBNpcs(); - if( Util::distance( getPos(), pos ) <= m_naviTargetReachedDistance ) { // Reached destination m_naviLastPath.clear(); - // return true; + return true; } auto pNaviMgr = m_pFw->get< World::Manager::NaviMgr >(); - auto pNaviProvider = pNaviMgr->getNaviProvider( m_pCurrentZone->getBgPath() ); + auto pNaviProvider = m_pCurrentZone->getNaviProvider(); if( !pNaviProvider ) { @@ -285,7 +281,7 @@ bool Sapphire::Entity::BNpc::moveTo( const FFXIVARR_POSITION3& pos ) step();*/ - //pNaviProvider->setMoveTarget( *this, pos ); + pNaviProvider->setMoveTarget( *this, pos ); auto pos1 = pNaviProvider->getMovePos( *this ); //Logger::debug( "{} {} {}", pos1.x, pos1.y, pos1.z ); @@ -480,7 +476,7 @@ void Sapphire::Entity::BNpc::update( uint64_t tickCount ) case BNpcState::Roaming: { auto pNaviMgr = m_pFw->get< World::Manager::NaviMgr >(); - auto pNaviProvider = pNaviMgr->getNaviProvider( m_pCurrentZone->getBgPath() ); + auto pNaviProvider = m_pCurrentZone->getNaviProvider(); if( pNaviProvider ) { @@ -507,7 +503,7 @@ void Sapphire::Entity::BNpc::update( uint64_t tickCount ) if( !hasFlag( Immobile ) && ( Util::getTimeSeconds() - m_lastRoamTargetReached > roamTick ) ) { auto pNaviMgr = m_pFw->get< World::Manager::NaviMgr >(); - auto pNaviProvider = pNaviMgr->getNaviProvider( m_pCurrentZone->getBgPath() ); + auto pNaviProvider = m_pCurrentZone->getNaviProvider(); if( !pNaviProvider ) { @@ -671,39 +667,6 @@ void Sapphire::Entity::BNpc::checkAggro() } } -void Sapphire::Entity::BNpc::pushNearbyBNpcs() -{ - for( auto& bNpc : m_inRangeBNpc ) - { - auto pos = bNpc->getPos(); - auto distance = Util::distance( m_pos, bNpc->getPos() ); - - - // todo: not sure what's good here - auto factor = bNpc->getNaviTargetReachedDistance(); - - auto delta = static_cast< float >( Util::getTimeMs() - bNpc->getLastUpdateTime() ) / 1000.f; - delta = std::min< float >( factor, delta ); - - // too far away, ignore it - if( distance > factor ) - continue; - - auto angle = Util::calcAngFrom( m_pos.x, m_pos.y, pos.x, pos.y ) + PI; - - auto x = ( cosf( angle ) ); - auto z = ( sinf( angle ) ); - - bNpc->setPos( pos.x + ( x * factor * delta ), - pos.y, - pos.z + ( z * factor * delta ), true ); - -// setPos( m_pos.x + ( xBase * -pushDistance ), -// m_pos.y, -// m_pos.z + ( zBase * -pushDistance ) ); - } -} - void Sapphire::Entity::BNpc::setOwner( Sapphire::Entity::CharaPtr m_pChara ) { m_pOwner = m_pChara; diff --git a/src/world/Actor/BNpc.h b/src/world/Actor/BNpc.h index f9709745..453c178d 100644 --- a/src/world/Actor/BNpc.h +++ b/src/world/Actor/BNpc.h @@ -111,8 +111,6 @@ namespace Sapphire::Entity void checkAggro(); - void pushNearbyBNpcs(); - void setOwner( CharaPtr m_pChara ); void setLevelId( uint32_t levelId ); diff --git a/src/world/Manager/NaviMgr.cpp b/src/world/Manager/NaviMgr.cpp index c3490920..62877ace 100644 --- a/src/world/Manager/NaviMgr.cpp +++ b/src/world/Manager/NaviMgr.cpp @@ -39,7 +39,7 @@ Sapphire::World::Navi::NaviProviderPtr Sapphire::World::Manager::NaviMgr::getNav std::string Sapphire::World::Manager::NaviMgr::getBgName( const std::string& bgPath ) { - auto findPos = bgPath.find_last_of( "/" ); + auto findPos = bgPath.find_last_of( '/' ); if( findPos != std::string::npos ) return bgPath.substr( findPos + 1 ); diff --git a/src/world/Territory/InstanceContent.cpp b/src/world/Territory/InstanceContent.cpp index f6c0e77a..688b90a7 100644 --- a/src/world/Territory/InstanceContent.cpp +++ b/src/world/Territory/InstanceContent.cpp @@ -48,6 +48,9 @@ Sapphire::InstanceContent::InstanceContent( std::shared_ptr< Sapphire::Data::Ins bool Sapphire::InstanceContent::init() { + if( !Zone::init() ) + return false; + auto pScriptMgr = m_pFw->get< Scripting::ScriptMgr >(); pScriptMgr->onInstanceInit( getAsInstanceContent() ); @@ -99,7 +102,7 @@ void Sapphire::InstanceContent::onUpdate( uint64_t tickCount ) { case Created: { - if( m_boundPlayerIds.size() == 0 ) + if( m_boundPlayerIds.empty() ) return; for( auto playerId : m_boundPlayerIds ) diff --git a/src/world/Territory/QuestBattle.cpp b/src/world/Territory/QuestBattle.cpp index ef23f08e..df3b71e8 100644 --- a/src/world/Territory/QuestBattle.cpp +++ b/src/world/Territory/QuestBattle.cpp @@ -48,6 +48,9 @@ Sapphire::QuestBattle::QuestBattle( std::shared_ptr< Sapphire::Data::QuestBattle bool Sapphire::QuestBattle::init() { + if( !Zone::init() ) + return false; + auto pScriptMgr = m_pFw->get< Scripting::ScriptMgr >(); pScriptMgr->onInstanceInit( getAsQuestBattle() ); From 018046d03bb69a8cc41e9c972bc28b644c9ea7c3 Mon Sep 17 00:00:00 2001 From: Mordred Date: Fri, 19 Apr 2019 12:15:09 +0200 Subject: [PATCH 004/351] Some progress on the crowd front, somehwat working roaming... --- src/world/Actor/BNpc.cpp | 16 ++++++++-------- src/world/Navi/NaviProvider.cpp | 11 +++++++++++ src/world/Navi/NaviProvider.h | 3 +++ 3 files changed, 22 insertions(+), 8 deletions(-) diff --git a/src/world/Actor/BNpc.cpp b/src/world/Actor/BNpc.cpp index 28390970..7c0e8808 100644 --- a/src/world/Actor/BNpc.cpp +++ b/src/world/Actor/BNpc.cpp @@ -224,12 +224,6 @@ void Sapphire::Entity::BNpc::step() bool Sapphire::Entity::BNpc::moveTo( const FFXIVARR_POSITION3& pos ) { - if( Util::distance( getPos(), pos ) <= m_naviTargetReachedDistance ) - { - // Reached destination - m_naviLastPath.clear(); - return true; - } auto pNaviMgr = m_pFw->get< World::Manager::NaviMgr >(); auto pNaviProvider = m_pCurrentZone->getNaviProvider(); @@ -281,9 +275,15 @@ bool Sapphire::Entity::BNpc::moveTo( const FFXIVARR_POSITION3& pos ) step();*/ - pNaviProvider->setMoveTarget( *this, pos ); + //pNaviProvider->setMoveTarget( *this, pos ); auto pos1 = pNaviProvider->getMovePos( *this ); + if( Util::distance( pos1, pos ) < 0.1f ) + { + // Reached destination + pNaviProvider->resetMoveTarget( *this ); + return true; + } //Logger::debug( "{} {} {}", pos1.x, pos1.y, pos1.z ); m_pCurrentZone->updateActorPosition( *this ); @@ -480,7 +480,7 @@ void Sapphire::Entity::BNpc::update( uint64_t tickCount ) if( pNaviProvider ) { - //if( !pNaviProvider->isAgentActive( *this ) ) + //if( !pNaviProvider->hasTargetState( *this ) ) pNaviProvider->setMoveTarget( *this, m_roamPos ); } diff --git a/src/world/Navi/NaviProvider.cpp b/src/world/Navi/NaviProvider.cpp index f17b7f5e..ff735ac6 100644 --- a/src/world/Navi/NaviProvider.cpp +++ b/src/world/Navi/NaviProvider.cpp @@ -638,3 +638,14 @@ bool Sapphire::World::Navi::NaviProvider::isAgentActive( Entity::Chara& chara ) return ag && ag->active; } + +bool Sapphire::World::Navi::NaviProvider::hasTargetState( Entity::Chara& chara ) const +{ + const dtCrowdAgent* ag = m_pCrowd->getAgent( chara.getAgentId() ); + return ag->targetState != DT_CROWDAGENT_TARGET_NONE; +} + +void Sapphire::World::Navi::NaviProvider::resetMoveTarget( Entity::Chara& chara ) +{ + m_pCrowd->resetMoveTarget( chara.getAgentId() ); +} diff --git a/src/world/Navi/NaviProvider.h b/src/world/Navi/NaviProvider.h index 9053dcd0..95f7b488 100644 --- a/src/world/Navi/NaviProvider.h +++ b/src/world/Navi/NaviProvider.h @@ -61,6 +61,9 @@ namespace Sapphire::World::Navi Common::FFXIVARR_POSITION3 getMovePos( Entity::Chara& chara ); bool isAgentActive( Entity::Chara& chara ) const; + bool hasTargetState( Entity::Chara& chara ) const; + + void resetMoveTarget( Entity::Chara& chara ); protected: std::string m_internalName; From 19a0ea2e93e7331b7f8ce2b6ccfed0b6e92170bf Mon Sep 17 00:00:00 2001 From: Mordred Date: Fri, 19 Apr 2019 14:04:38 +0200 Subject: [PATCH 005/351] Fix roaming --- src/world/Actor/BNpc.cpp | 6 +++++- src/world/Navi/NaviProvider.cpp | 7 +++++++ src/world/Navi/NaviProvider.h | 2 ++ 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/world/Actor/BNpc.cpp b/src/world/Actor/BNpc.cpp index 7c0e8808..0080d550 100644 --- a/src/world/Actor/BNpc.cpp +++ b/src/world/Actor/BNpc.cpp @@ -278,10 +278,14 @@ bool Sapphire::Entity::BNpc::moveTo( const FFXIVARR_POSITION3& pos ) //pNaviProvider->setMoveTarget( *this, pos ); auto pos1 = pNaviProvider->getMovePos( *this ); - if( Util::distance( pos1, pos ) < 0.1f ) + if( Util::distance( pos1, pos ) < 1.1f ) { // Reached destination + face( pos1 ); + setPos( pos1 ); + sendPositionUpdate(); pNaviProvider->resetMoveTarget( *this ); + pNaviProvider->updateAgentPosition( *this ); return true; } //Logger::debug( "{} {} {}", pos1.x, pos1.y, pos1.z ); diff --git a/src/world/Navi/NaviProvider.cpp b/src/world/Navi/NaviProvider.cpp index ff735ac6..3d983b19 100644 --- a/src/world/Navi/NaviProvider.cpp +++ b/src/world/Navi/NaviProvider.cpp @@ -649,3 +649,10 @@ void Sapphire::World::Navi::NaviProvider::resetMoveTarget( Entity::Chara& chara { m_pCrowd->resetMoveTarget( chara.getAgentId() ); } + +void Sapphire::World::Navi::NaviProvider::updateAgentPosition( Entity::Chara& chara ) +{ + removeAgent( chara ); + auto newIndex = addAgent( chara ); + chara.setAgentId( newIndex ); +} diff --git a/src/world/Navi/NaviProvider.h b/src/world/Navi/NaviProvider.h index 95f7b488..965de453 100644 --- a/src/world/Navi/NaviProvider.h +++ b/src/world/Navi/NaviProvider.h @@ -65,6 +65,8 @@ namespace Sapphire::World::Navi void resetMoveTarget( Entity::Chara& chara ); + void updateAgentPosition( Entity::Chara& chara ); + protected: std::string m_internalName; From eeded4c4f0c26b91d22345fdd4e0b66519fd9cb6 Mon Sep 17 00:00:00 2001 From: Mordred Date: Fri, 19 Apr 2019 14:19:14 +0200 Subject: [PATCH 006/351] Pushing of idle actors implemented --- src/world/Actor/BNpc.cpp | 51 +++++---------------------------- src/world/Navi/NaviProvider.cpp | 10 +++++++ src/world/Navi/NaviProvider.h | 2 ++ 3 files changed, 19 insertions(+), 44 deletions(-) diff --git a/src/world/Actor/BNpc.cpp b/src/world/Actor/BNpc.cpp index 0080d550..fc453a9d 100644 --- a/src/world/Actor/BNpc.cpp +++ b/src/world/Actor/BNpc.cpp @@ -236,46 +236,6 @@ bool Sapphire::Entity::BNpc::moveTo( const FFXIVARR_POSITION3& pos ) return false; } - /*auto path = pNaviProvider->findFollowPath( m_pos, pos ); - - if( !path.empty() ) - { - m_naviLastPath = path; - m_naviTarget = pos; - m_naviPathStep = 0; - m_naviLastUpdate = Util::getTimeMs(); - } - else - { - 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() ); - - - hateListClear(); - - if( m_state == BNpcState::Roaming ) - { - Logger::warn( "BNpc Base#{0} Name#{1} unable to path from x{2} y{3} z{4} while roaming. " - "Possible pathing error in area. Returning BNpc to spawn position x{5} y{6} z{7}.", - m_bNpcBaseId, m_bNpcNameId, - getPos().x, getPos().y, getPos().z, - m_spawnPos.x, m_spawnPos.y, m_spawnPos.z ); - - m_lastRoamTargetReached = Util::getTimeSeconds(); - m_state = BNpcState::Idle; - - m_naviLastPath.clear(); - - setPos( m_spawnPos ); - sendPositionUpdate(); - - return true; - } - } - - step();*/ - - //pNaviProvider->setMoveTarget( *this, pos ); auto pos1 = pNaviProvider->getMovePos( *this ); if( Util::distance( pos1, pos ) < 1.1f ) @@ -284,11 +244,10 @@ bool Sapphire::Entity::BNpc::moveTo( const FFXIVARR_POSITION3& pos ) face( pos1 ); setPos( pos1 ); sendPositionUpdate(); - pNaviProvider->resetMoveTarget( *this ); + //pNaviProvider->resetMoveTarget( *this ); pNaviProvider->updateAgentPosition( *this ); return true; } - //Logger::debug( "{} {} {}", pos1.x, pos1.y, pos1.z ); m_pCurrentZone->updateActorPosition( *this ); face( pos1 ); @@ -504,10 +463,14 @@ void Sapphire::Entity::BNpc::update( uint64_t tickCount ) if( pHatedActor ) aggro( pHatedActor ); + auto pNaviMgr = m_pFw->get< World::Manager::NaviMgr >(); + auto pNaviProvider = m_pCurrentZone->getNaviProvider(); + + if( pNaviProvider->syncPosToChara( *this ) ) + sendPositionUpdate(); + if( !hasFlag( Immobile ) && ( Util::getTimeSeconds() - m_lastRoamTargetReached > roamTick ) ) { - auto pNaviMgr = m_pFw->get< World::Manager::NaviMgr >(); - auto pNaviProvider = m_pCurrentZone->getNaviProvider(); if( !pNaviProvider ) { diff --git a/src/world/Navi/NaviProvider.cpp b/src/world/Navi/NaviProvider.cpp index 3d983b19..690070a7 100644 --- a/src/world/Navi/NaviProvider.cpp +++ b/src/world/Navi/NaviProvider.cpp @@ -656,3 +656,13 @@ void Sapphire::World::Navi::NaviProvider::updateAgentPosition( Entity::Chara& ch auto newIndex = addAgent( chara ); chara.setAgentId( newIndex ); } + +bool Sapphire::World::Navi::NaviProvider::syncPosToChara( Entity::Chara& chara ) +{ + auto pos = getMovePos( chara ); + if( pos.x == chara.getPos().x && pos.y == chara.getPos().y && pos.z == chara.getPos().z ) + return false; + + chara.setPos( pos ); + return true; +} \ No newline at end of file diff --git a/src/world/Navi/NaviProvider.h b/src/world/Navi/NaviProvider.h index 965de453..80cba51d 100644 --- a/src/world/Navi/NaviProvider.h +++ b/src/world/Navi/NaviProvider.h @@ -67,6 +67,8 @@ namespace Sapphire::World::Navi void updateAgentPosition( Entity::Chara& chara ); + bool syncPosToChara( Entity::Chara& chara ); + protected: std::string m_internalName; From c0c88ca783285d804d91101c052569c8101c8eeb Mon Sep 17 00:00:00 2001 From: Mordred Date: Fri, 19 Apr 2019 14:50:00 +0200 Subject: [PATCH 007/351] Following and retreating works --- src/world/Actor/BNpc.cpp | 17 ++++++++++++++++- src/world/Navi/NaviProvider.cpp | 2 +- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/src/world/Actor/BNpc.cpp b/src/world/Actor/BNpc.cpp index fc453a9d..586341ba 100644 --- a/src/world/Actor/BNpc.cpp +++ b/src/world/Actor/BNpc.cpp @@ -419,6 +419,14 @@ void Sapphire::Entity::BNpc::update( uint64_t tickCount ) { setInvincibilityType( InvincibilityType::InvincibilityIgnoreDamage ); + auto pNaviMgr = m_pFw->get< World::Manager::NaviMgr >(); + auto pNaviProvider = m_pCurrentZone->getNaviProvider(); + if( pNaviProvider ) + { + //if( !pNaviProvider->hasTargetState( *this ) ) + pNaviProvider->setMoveTarget( *this, m_spawnPos ); + } + if( moveTo( m_spawnPos ) ) { setInvincibilityType( InvincibilityType::InvincibilityNone ); @@ -521,9 +529,16 @@ void Sapphire::Entity::BNpc::update( uint64_t tickCount ) if( !hasFlag( Immobile ) && ( distance > minActorDistance ) ) { + auto pNaviMgr = m_pFw->get< World::Manager::NaviMgr >(); + auto pNaviProvider = m_pCurrentZone->getNaviProvider(); + if( pNaviProvider ) + { + //if( !pNaviProvider->hasTargetState( *this ) ) + pNaviProvider->setMoveTarget( *this, pHatedActor->getPos() ); + } //auto pTeriMgr = m_pFw->get< World::Manager::TerritoryMgr >(); //if ( ( currTime - m_lastAttack ) > 600 && pTeriMgr->isDefaultTerritory( getCurrentZone()->getTerritoryTypeId() ) ) - moveTo( pHatedActor->getPos() ); + moveTo( pHatedActor->getPos() ); } else { diff --git a/src/world/Navi/NaviProvider.cpp b/src/world/Navi/NaviProvider.cpp index 690070a7..da0338c6 100644 --- a/src/world/Navi/NaviProvider.cpp +++ b/src/world/Navi/NaviProvider.cpp @@ -571,7 +571,7 @@ int32_t Sapphire::World::Navi::NaviProvider::addAgent( Entity::Chara& chara ) dtCrowdAgentParams params; std::memset( ¶ms, 0, sizeof( params ) ); params.height = 7.f; - params.maxAcceleration = 16.f; + params.maxAcceleration = 26.f; params.maxSpeed = 13.5f; params.radius = 2.f; params.collisionQueryRange = params.radius * 12.0f; From 19e6a0f748d9983e5c7444622a727453123802ec Mon Sep 17 00:00:00 2001 From: NotAdam Date: Fri, 19 Apr 2019 23:01:27 +1000 Subject: [PATCH 008/351] more accurate bnpc scale calculation --- src/common/Exd/ExdDataGenerated.cpp | 7 +++++++ src/common/Exd/ExdDataGenerated.h | 17 +++++++++++++++++ src/world/Actor/BNpc.cpp | 13 ++++++++----- src/world/Actor/BNpc.h | 2 +- src/world/Actor/Chara.cpp | 9 ++++++++- src/world/Actor/Chara.h | 5 +++++ src/world/Navi/NaviProvider.cpp | 3 +-- 7 files changed, 47 insertions(+), 9 deletions(-) diff --git a/src/common/Exd/ExdDataGenerated.cpp b/src/common/Exd/ExdDataGenerated.cpp index da9df8b1..c7485692 100644 --- a/src/common/Exd/ExdDataGenerated.cpp +++ b/src/common/Exd/ExdDataGenerated.cpp @@ -3906,6 +3906,12 @@ Sapphire::Data::ModelChara::ModelChara( uint32_t row_id, Sapphire::Data::ExdData variant = exdData->getField< uint8_t >( row, 3 ); } +Sapphire::Data::ModelSkeleton::ModelSkeleton( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ) +{ + auto row = exdData->m_ModelSkeletonDat.get_row( row_id ); + scaleFactor = exdData->getField< float >( row, 0 ); +} + Sapphire::Data::ModelState::ModelState( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ) { auto row = exdData->m_ModelStateDat.get_row( row_id ); @@ -6935,6 +6941,7 @@ bool Sapphire::Data::ExdDataGenerated::init( const std::string& path ) m_MobHuntOrderTypeDat = setupDatAccess( "MobHuntOrderType", xiv::exd::Language::none ); m_MobHuntTargetDat = setupDatAccess( "MobHuntTarget", xiv::exd::Language::none ); m_ModelCharaDat = setupDatAccess( "ModelChara", xiv::exd::Language::none ); + m_ModelSkeletonDat = setupDatAccess( "ModelSkeleton", xiv::exd::Language::none ); m_ModelStateDat = setupDatAccess( "ModelState", xiv::exd::Language::none ); m_MonsterNoteDat = setupDatAccess( "MonsterNote", xiv::exd::Language::en ); m_MonsterNoteTargetDat = setupDatAccess( "MonsterNoteTarget", xiv::exd::Language::none ); diff --git a/src/common/Exd/ExdDataGenerated.h b/src/common/Exd/ExdDataGenerated.h index 525c3bd3..97c6122b 100644 --- a/src/common/Exd/ExdDataGenerated.h +++ b/src/common/Exd/ExdDataGenerated.h @@ -342,6 +342,7 @@ struct MinionSkillType; struct MobHuntOrderType; struct MobHuntTarget; struct ModelChara; +struct ModelSkeleton; struct ModelState; struct MonsterNote; struct MonsterNoteTarget; @@ -3934,6 +3935,13 @@ struct ModelChara ModelChara( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ); }; +struct ModelSkeleton +{ + float scaleFactor; + + ModelSkeleton( uint32_t row_id, Sapphire::Data::ExdDataGenerated* exdData ); +}; + struct ModelState { uint16_t start; @@ -5802,6 +5810,7 @@ struct ZoneSharedGroup xiv::exd::Exd m_MobHuntOrderTypeDat; xiv::exd::Exd m_MobHuntTargetDat; xiv::exd::Exd m_ModelCharaDat; + xiv::exd::Exd m_ModelSkeletonDat; xiv::exd::Exd m_ModelStateDat; xiv::exd::Exd m_MonsterNoteDat; xiv::exd::Exd m_MonsterNoteTargetDat; @@ -6274,6 +6283,7 @@ struct ZoneSharedGroup using MobHuntOrderTypePtr = std::shared_ptr< MobHuntOrderType >; using MobHuntTargetPtr = std::shared_ptr< MobHuntTarget >; using ModelCharaPtr = std::shared_ptr< ModelChara >; + using ModelSkeletonPtr = std::shared_ptr< ModelSkeleton >; using ModelStatePtr = std::shared_ptr< ModelState >; using MonsterNotePtr = std::shared_ptr< MonsterNote >; using MonsterNoteTargetPtr = std::shared_ptr< MonsterNoteTarget >; @@ -6777,6 +6787,7 @@ struct ZoneSharedGroup std::set< uint32_t > m_MobHuntOrderTypeIdList; std::set< uint32_t > m_MobHuntTargetIdList; std::set< uint32_t > m_ModelCharaIdList; + std::set< uint32_t > m_ModelSkeletonIdList; std::set< uint32_t > m_ModelStateIdList; std::set< uint32_t > m_MonsterNoteIdList; std::set< uint32_t > m_MonsterNoteTargetIdList; @@ -8869,6 +8880,12 @@ const std::set< uint32_t >& getModelCharaIdList() loadIdList( m_ModelCharaDat, m_ModelCharaIdList ); return m_ModelCharaIdList; } +const std::set< uint32_t >& getModelSkeletonIdList() +{ + if( m_ModelSkeletonIdList.size() == 0 ) + loadIdList( m_ModelSkeletonDat, m_ModelSkeletonIdList ); + return m_ModelSkeletonIdList; +} const std::set< uint32_t >& getModelStateIdList() { if( m_ModelStateIdList.size() == 0 ) diff --git a/src/world/Actor/BNpc.cpp b/src/world/Actor/BNpc.cpp index 586341ba..a9e8be94 100644 --- a/src/world/Actor/BNpc.cpp +++ b/src/world/Actor/BNpc.cpp @@ -100,6 +100,14 @@ Sapphire::Entity::BNpc::BNpc( uint32_t id, BNpcTemplatePtr pTemplate, float posX m_scale = bNpcBaseData->scale; + auto modelChara = exdData->get< Data::ModelChara >( bNpcBaseData->modelChara ); + if( modelChara ) + { + auto modelSkeleton = exdData->get< Data::ModelSkeleton >( modelChara->model ); + if( modelSkeleton ) + m_scale *= modelSkeleton->scaleFactor; + } + // todo: is this actually good? //m_naviTargetReachedDistance = m_scale * 2.f; m_naviTargetReachedDistance = 4.f; @@ -117,11 +125,6 @@ float Sapphire::Entity::BNpc::getNaviTargetReachedDistance() const return m_naviTargetReachedDistance; } -float Sapphire::Entity::BNpc::getScale() const -{ - return m_scale; -} - uint8_t Sapphire::Entity::BNpc::getEnemyType() const { return m_enemyType; diff --git a/src/world/Actor/BNpc.h b/src/world/Actor/BNpc.h index 453c178d..8ed859b9 100644 --- a/src/world/Actor/BNpc.h +++ b/src/world/Actor/BNpc.h @@ -71,7 +71,7 @@ namespace Sapphire::Entity uint8_t getAggressionMode() const; - float getScale() const; + float getNaviTargetReachedDistance() const; // return true if it reached the position diff --git a/src/world/Actor/Chara.cpp b/src/world/Actor/Chara.cpp index 3af406f6..6eba77f9 100644 --- a/src/world/Actor/Chara.cpp +++ b/src/world/Actor/Chara.cpp @@ -38,7 +38,8 @@ Sapphire::Entity::Chara::Chara( ObjKind type, FrameworkPtr pFw ) : m_pose( 0 ), m_targetId( INVALID_GAME_OBJECT_ID64 ), m_pFw( std::move( std::move( pFw ) ) ), - m_directorId( 0 ) + m_directorId( 0 ), + m_scale( 2.f ) { m_lastTickTime = 0; @@ -712,3 +713,9 @@ void Sapphire::Entity::Chara::setAgentId( uint32_t agentId ) { m_agentId = agentId; } + + +float Sapphire::Entity::Chara::getScale() const +{ + return m_scale; +} \ No newline at end of file diff --git a/src/world/Actor/Chara.h b/src/world/Actor/Chara.h index a6a95776..56638255 100644 --- a/src/world/Actor/Chara.h +++ b/src/world/Actor/Chara.h @@ -131,6 +131,9 @@ namespace Sapphire::Entity /*! Detour Crowd AgentId */ uint32_t m_agentId; + /*! Detour Crowd actor scale */ + float m_scale; + public: Chara( Common::ObjKind type, FrameworkPtr pFw ); @@ -275,6 +278,8 @@ namespace Sapphire::Entity uint32_t getAgentId() const; void setAgentId( uint32_t agentId ); + float getScale() const; + }; } diff --git a/src/world/Navi/NaviProvider.cpp b/src/world/Navi/NaviProvider.cpp index da0338c6..2db4bdcb 100644 --- a/src/world/Navi/NaviProvider.cpp +++ b/src/world/Navi/NaviProvider.cpp @@ -573,7 +573,7 @@ int32_t Sapphire::World::Navi::NaviProvider::addAgent( Entity::Chara& chara ) params.height = 7.f; params.maxAcceleration = 26.f; params.maxSpeed = 13.5f; - params.radius = 2.f; + params.radius = chara.getScale() / 2; params.collisionQueryRange = params.radius * 12.0f; params.pathOptimizationRange = params.radius * 30.0f; params.updateFlags = 0; @@ -584,7 +584,6 @@ int32_t Sapphire::World::Navi::NaviProvider::addAgent( Entity::Chara& chara ) void Sapphire::World::Navi::NaviProvider::updateCrowd( float timeInSeconds ) { - dtCrowdAgentDebugInfo info; info.idx = -1; info.vod = m_vod; From 8fa3fa325db7c33064e481d7b777b3630a3d7f08 Mon Sep 17 00:00:00 2001 From: Mordred Date: Sat, 20 Apr 2019 00:11:00 +0200 Subject: [PATCH 009/351] Further improvement of crowd logic --- src/world/Actor/BNpc.cpp | 67 +++++++++++++++++++++++---------- src/world/Actor/BNpc.h | 2 + src/world/Navi/NaviProvider.cpp | 6 +-- 3 files changed, 53 insertions(+), 22 deletions(-) diff --git a/src/world/Actor/BNpc.cpp b/src/world/Actor/BNpc.cpp index a9e8be94..5ec37921 100644 --- a/src/world/Actor/BNpc.cpp +++ b/src/world/Actor/BNpc.cpp @@ -241,7 +241,7 @@ bool Sapphire::Entity::BNpc::moveTo( const FFXIVARR_POSITION3& pos ) auto pos1 = pNaviProvider->getMovePos( *this ); - if( Util::distance( pos1, pos ) < 1.1f ) + if( Util::distance( pos1, pos ) < ( getScale() / 2 ) ) { // Reached destination face( pos1 ); @@ -259,6 +259,41 @@ bool Sapphire::Entity::BNpc::moveTo( const FFXIVARR_POSITION3& pos ) return false; } +bool Sapphire::Entity::BNpc::moveTo( const Entity::Chara& targetChara ) +{ + + auto pNaviMgr = m_pFw->get< World::Manager::NaviMgr >(); + auto pNaviProvider = m_pCurrentZone->getNaviProvider(); + + if( !pNaviProvider ) + { + Logger::error( "No NaviProvider for zone#{0} - {1}", + m_pCurrentZone->getGuId(), + m_pCurrentZone->getInternalName() ); + return false; + } + + auto pos1 = pNaviProvider->getMovePos( *this ); + + if( Util::distance( pos1, targetChara.getPos() ) <= ( ( getScale() / 2 + targetChara.getScale() / 2 ) ) ) + { + // Reached destination + face( pos1 ); + setPos( pos1 ); + sendPositionUpdate(); + //pNaviProvider->resetMoveTarget( *this ); + pNaviProvider->updateAgentPosition( *this ); + return true; + } + + m_pCurrentZone->updateActorPosition( *this ); + face( pos1 ); + setPos( pos1 ); + sendPositionUpdate(); + return false; +} + + void Sapphire::Entity::BNpc::sendPositionUpdate() { uint8_t unk1 = 0x3a; @@ -411,6 +446,8 @@ void Sapphire::Entity::BNpc::update( uint64_t tickCount ) const uint8_t maxDistanceToOrigin = 40; const uint32_t roamTick = 20; + auto pNaviMgr = m_pFw->get< World::Manager::NaviMgr >(); + auto pNaviProvider = m_pCurrentZone->getNaviProvider(); switch( m_state ) { @@ -422,11 +459,8 @@ void Sapphire::Entity::BNpc::update( uint64_t tickCount ) { setInvincibilityType( InvincibilityType::InvincibilityIgnoreDamage ); - auto pNaviMgr = m_pFw->get< World::Manager::NaviMgr >(); - auto pNaviProvider = m_pCurrentZone->getNaviProvider(); if( pNaviProvider ) { - //if( !pNaviProvider->hasTargetState( *this ) ) pNaviProvider->setMoveTarget( *this, m_spawnPos ); } @@ -449,13 +483,10 @@ void Sapphire::Entity::BNpc::update( uint64_t tickCount ) case BNpcState::Roaming: { - auto pNaviMgr = m_pFw->get< World::Manager::NaviMgr >(); - auto pNaviProvider = m_pCurrentZone->getNaviProvider(); if( pNaviProvider ) { - //if( !pNaviProvider->hasTargetState( *this ) ) - pNaviProvider->setMoveTarget( *this, m_roamPos ); + pNaviProvider->setMoveTarget( *this, m_roamPos ); } if( moveTo( m_roamPos ) ) @@ -474,9 +505,6 @@ void Sapphire::Entity::BNpc::update( uint64_t tickCount ) if( pHatedActor ) aggro( pHatedActor ); - auto pNaviMgr = m_pFw->get< World::Manager::NaviMgr >(); - auto pNaviProvider = m_pCurrentZone->getNaviProvider(); - if( pNaviProvider->syncPosToChara( *this ) ) sendPositionUpdate(); @@ -513,6 +541,9 @@ void Sapphire::Entity::BNpc::update( uint64_t tickCount ) pHatedActor = hateListGetHighest(); } + if( pNaviProvider->syncPosToChara( *this ) ) + sendPositionUpdate(); + if( pHatedActor ) { auto distance = Util::distance( getPos().x, getPos().y, getPos().z, @@ -530,18 +561,16 @@ void Sapphire::Entity::BNpc::update( uint64_t tickCount ) break; } - if( !hasFlag( Immobile ) && ( distance > minActorDistance ) ) + if( distance > ( getScale() / 2 + pHatedActor->getScale() / 2 ) ) { - auto pNaviMgr = m_pFw->get< World::Manager::NaviMgr >(); - auto pNaviProvider = m_pCurrentZone->getNaviProvider(); + if( hasFlag( Immobile ) ) + break; + if( pNaviProvider ) { - //if( !pNaviProvider->hasTargetState( *this ) ) pNaviProvider->setMoveTarget( *this, pHatedActor->getPos() ); } - //auto pTeriMgr = m_pFw->get< World::Manager::TerritoryMgr >(); - //if ( ( currTime - m_lastAttack ) > 600 && pTeriMgr->isDefaultTerritory( getCurrentZone()->getTerritoryTypeId() ) ) - moveTo( pHatedActor->getPos() ); + moveTo( *pHatedActor ); } else { @@ -666,7 +695,7 @@ void Sapphire::Entity::BNpc::setOwner( Sapphire::Entity::CharaPtr m_pChara ) { auto setOwnerPacket = makeZonePacket< FFXIVIpcActorOwner >( getId() ); setOwnerPacket->data().type = 0x01; - setOwnerPacket->data().actorId = 0; + setOwnerPacket->data().actorId = INVALID_GAME_OBJECT_ID; sendToInRangeSet( setOwnerPacket ); } } diff --git a/src/world/Actor/BNpc.h b/src/world/Actor/BNpc.h index 8ed859b9..cb8156bc 100644 --- a/src/world/Actor/BNpc.h +++ b/src/world/Actor/BNpc.h @@ -77,6 +77,8 @@ namespace Sapphire::Entity // return true if it reached the position bool moveTo( const Common::FFXIVARR_POSITION3& pos ); + bool moveTo( const Entity::Chara& targetChara ); + // processes movement void step(); diff --git a/src/world/Navi/NaviProvider.cpp b/src/world/Navi/NaviProvider.cpp index 2db4bdcb..3feff0ed 100644 --- a/src/world/Navi/NaviProvider.cpp +++ b/src/world/Navi/NaviProvider.cpp @@ -571,11 +571,11 @@ int32_t Sapphire::World::Navi::NaviProvider::addAgent( Entity::Chara& chara ) dtCrowdAgentParams params; std::memset( ¶ms, 0, sizeof( params ) ); params.height = 7.f; - params.maxAcceleration = 26.f; + params.maxAcceleration = 126.f; params.maxSpeed = 13.5f; params.radius = chara.getScale() / 2; - params.collisionQueryRange = params.radius * 12.0f; - params.pathOptimizationRange = params.radius * 30.0f; + params.collisionQueryRange = params.radius * 20.0f; + params.pathOptimizationRange = params.radius * 10.0f; params.updateFlags = 0; //params.updateFlags |= DT_CROWD_OBSTACLE_AVOIDANCE; float position[] = { chara.getPos().x, chara.getPos().y, chara.getPos().z }; From 4112ae712adb1d871d2d740ff6b94d3903d816f1 Mon Sep 17 00:00:00 2001 From: NotAdam Date: Sat, 20 Apr 2019 15:13:46 +1000 Subject: [PATCH 010/351] correctly calculate deltatime, set agent flags on dormant bnpcs --- src/world/Actor/BNpc.cpp | 21 +++++++++-------- src/world/Actor/BNpc.h | 1 - src/world/Navi/NaviProvider.cpp | 30 ++++++++++++++++++++----- src/world/Navi/NaviProvider.h | 3 +++ src/world/Territory/InstanceContent.cpp | 2 ++ src/world/Territory/QuestBattle.cpp | 2 ++ src/world/Territory/Zone.cpp | 10 +++++---- 7 files changed, 50 insertions(+), 19 deletions(-) diff --git a/src/world/Actor/BNpc.cpp b/src/world/Actor/BNpc.cpp index 5ec37921..1196341e 100644 --- a/src/world/Actor/BNpc.cpp +++ b/src/world/Actor/BNpc.cpp @@ -228,7 +228,6 @@ void Sapphire::Entity::BNpc::step() bool Sapphire::Entity::BNpc::moveTo( const FFXIVARR_POSITION3& pos ) { - auto pNaviMgr = m_pFw->get< World::Manager::NaviMgr >(); auto pNaviProvider = m_pCurrentZone->getNaviProvider(); if( !pNaviProvider ) @@ -239,21 +238,24 @@ bool Sapphire::Entity::BNpc::moveTo( const FFXIVARR_POSITION3& pos ) return false; } + pNaviProvider->addAgentUpdateFlag( *this, DT_CROWD_OBSTACLE_AVOIDANCE ); + auto pos1 = pNaviProvider->getMovePos( *this ); - if( Util::distance( pos1, pos ) < ( getScale() / 2 ) ) + if( Util::distance( pos1, pos ) < getScale() ) { // Reached destination - face( pos1 ); + face( pos ); setPos( pos1 ); sendPositionUpdate(); //pNaviProvider->resetMoveTarget( *this ); pNaviProvider->updateAgentPosition( *this ); + pNaviProvider->removeAgentUpdateFlag( *this, DT_CROWD_OBSTACLE_AVOIDANCE ); return true; } m_pCurrentZone->updateActorPosition( *this ); - face( pos1 ); + face( pos ); setPos( pos1 ); sendPositionUpdate(); return false; @@ -262,7 +264,6 @@ bool Sapphire::Entity::BNpc::moveTo( const FFXIVARR_POSITION3& pos ) bool Sapphire::Entity::BNpc::moveTo( const Entity::Chara& targetChara ) { - auto pNaviMgr = m_pFw->get< World::Manager::NaviMgr >(); auto pNaviProvider = m_pCurrentZone->getNaviProvider(); if( !pNaviProvider ) @@ -273,21 +274,24 @@ bool Sapphire::Entity::BNpc::moveTo( const Entity::Chara& targetChara ) return false; } + pNaviProvider->addAgentUpdateFlag( *this, DT_CROWD_OBSTACLE_AVOIDANCE ); + auto pos1 = pNaviProvider->getMovePos( *this ); - if( Util::distance( pos1, targetChara.getPos() ) <= ( ( getScale() / 2 + targetChara.getScale() / 2 ) ) ) + if( Util::distance( pos1, targetChara.getPos() ) <= ( getScale() + targetChara.getScale() ) ) { // Reached destination - face( pos1 ); + face( targetChara.getPos() ); setPos( pos1 ); sendPositionUpdate(); //pNaviProvider->resetMoveTarget( *this ); pNaviProvider->updateAgentPosition( *this ); + pNaviProvider->removeAgentUpdateFlag( *this, DT_CROWD_OBSTACLE_AVOIDANCE ); return true; } m_pCurrentZone->updateActorPosition( *this ); - face( pos1 ); + face( targetChara.getPos() ); setPos( pos1 ); sendPositionUpdate(); return false; @@ -446,7 +450,6 @@ void Sapphire::Entity::BNpc::update( uint64_t tickCount ) const uint8_t maxDistanceToOrigin = 40; const uint32_t roamTick = 20; - auto pNaviMgr = m_pFw->get< World::Manager::NaviMgr >(); auto pNaviProvider = m_pCurrentZone->getNaviProvider(); switch( m_state ) diff --git a/src/world/Actor/BNpc.h b/src/world/Actor/BNpc.h index cb8156bc..5042118c 100644 --- a/src/world/Actor/BNpc.h +++ b/src/world/Actor/BNpc.h @@ -137,7 +137,6 @@ namespace Sapphire::Entity uint32_t m_flags; - float m_scale; float m_naviTargetReachedDistance; uint32_t m_timeOfDeath; diff --git a/src/world/Navi/NaviProvider.cpp b/src/world/Navi/NaviProvider.cpp index 3feff0ed..49383f59 100644 --- a/src/world/Navi/NaviProvider.cpp +++ b/src/world/Navi/NaviProvider.cpp @@ -570,12 +570,12 @@ int32_t Sapphire::World::Navi::NaviProvider::addAgent( Entity::Chara& chara ) { dtCrowdAgentParams params; std::memset( ¶ms, 0, sizeof( params ) ); - params.height = 7.f; - params.maxAcceleration = 126.f; - params.maxSpeed = 13.5f; + params.height = 3.f; + params.maxAcceleration = 25.f; + params.maxSpeed = std::pow( 2, chara.getScale() * 0.35f ) + 1.f; params.radius = chara.getScale() / 2; - params.collisionQueryRange = params.radius * 20.0f; - params.pathOptimizationRange = params.radius * 10.0f; + params.collisionQueryRange = params.radius * 12.0f; + params.pathOptimizationRange = params.radius * 20.0f; params.updateFlags = 0; //params.updateFlags |= DT_CROWD_OBSTACLE_AVOIDANCE; float position[] = { chara.getPos().x, chara.getPos().y, chara.getPos().z }; @@ -664,4 +664,24 @@ bool Sapphire::World::Navi::NaviProvider::syncPosToChara( Entity::Chara& chara ) chara.setPos( pos ); return true; +} + +void Sapphire::World::Navi::NaviProvider::addAgentUpdateFlag( Sapphire::Entity::Chara& chara, uint8_t flags ) +{ + auto ag = m_pCrowd->getEditableAgent( chara.getAgentId() ); + + if( !ag ) + return; + + ag->params.updateFlags |= flags; +} + +void Sapphire::World::Navi::NaviProvider::removeAgentUpdateFlag( Sapphire::Entity::Chara& chara, uint8_t flags ) +{ + auto ag = m_pCrowd->getEditableAgent( chara.getAgentId() ); + + if( !ag ) + return; + + ag->params.updateFlags ^= flags; } \ No newline at end of file diff --git a/src/world/Navi/NaviProvider.h b/src/world/Navi/NaviProvider.h index 80cba51d..d402cda0 100644 --- a/src/world/Navi/NaviProvider.h +++ b/src/world/Navi/NaviProvider.h @@ -69,6 +69,9 @@ namespace Sapphire::World::Navi bool syncPosToChara( Entity::Chara& chara ); + void addAgentUpdateFlag( Entity::Chara& chara, uint8_t flags ); + void removeAgentUpdateFlag( Entity::Chara& chara, uint8_t flags ); + protected: std::string m_internalName; diff --git a/src/world/Territory/InstanceContent.cpp b/src/world/Territory/InstanceContent.cpp index 688b90a7..81b9f868 100644 --- a/src/world/Territory/InstanceContent.cpp +++ b/src/world/Territory/InstanceContent.cpp @@ -159,6 +159,8 @@ void Sapphire::InstanceContent::onUpdate( uint64_t tickCount ) auto pScriptMgr = m_pFw->get< Scripting::ScriptMgr >(); pScriptMgr->onInstanceUpdate( getAsInstanceContent(), tickCount ); + + m_lastUpdate = tickCount; } void Sapphire::InstanceContent::onFinishLoading( Entity::Player& player ) diff --git a/src/world/Territory/QuestBattle.cpp b/src/world/Territory/QuestBattle.cpp index df3b71e8..39d0f821 100644 --- a/src/world/Territory/QuestBattle.cpp +++ b/src/world/Territory/QuestBattle.cpp @@ -159,6 +159,8 @@ void Sapphire::QuestBattle::onUpdate( uint64_t tickCount ) auto pScriptMgr = m_pFw->get< Scripting::ScriptMgr >(); pScriptMgr->onInstanceUpdate( getAsQuestBattle(), tickCount ); + + m_lastUpdate = tickCount; } void Sapphire::QuestBattle::onFinishLoading( Entity::Player& player ) diff --git a/src/world/Territory/Zone.cpp b/src/world/Territory/Zone.cpp index ee52d012..7245323f 100644 --- a/src/world/Territory/Zone.cpp +++ b/src/world/Territory/Zone.cpp @@ -473,17 +473,21 @@ bool Sapphire::Zone::update( uint64_t tickCount ) //TODO: this should be moved to a updateWeather call and pulled out of updateSessions bool changedWeather = checkWeather(); + auto dt = std::difftime( tickCount, m_lastUpdate ) / 1000.f; + if( m_pNaviProvider ) - m_pNaviProvider->updateCrowd( 0.02f ); + m_pNaviProvider->updateCrowd( dt ); updateSessions( tickCount, changedWeather ); onUpdate( tickCount ); updateSpawnPoints(); - if( m_playerMap.size() > 0 ) + if( !m_playerMap.empty() ) m_lastActivityTime = tickCount; + m_lastUpdate = tickCount; + return true; } @@ -508,8 +512,6 @@ void Sapphire::Zone::updateSessions( uint64_t tickCount, bool changedWeather ) return; } - m_lastUpdate = tickCount; - if( changedWeather ) { auto weatherChangePacket = makeZonePacket< FFXIVIpcWeatherChange >( pPlayer->getId() ); From c1da01436f66b712ba3e56986b77f984dd6c508c Mon Sep 17 00:00:00 2001 From: NotAdam Date: Sat, 20 Apr 2019 19:40:44 +1000 Subject: [PATCH 011/351] fix build, not sure how that happened --- src/world/Territory/Zone.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/world/Territory/Zone.cpp b/src/world/Territory/Zone.cpp index 7245323f..c9c2402b 100644 --- a/src/world/Territory/Zone.cpp +++ b/src/world/Territory/Zone.cpp @@ -19,7 +19,7 @@ #include "InstanceContent.h" #include "QuestBattle.h" #include "Manager/TerritoryMgr.h" -#include "Navi/Naviprovider.h" +#include "Navi/NaviProvider.h" #include "Session.h" #include "Actor/Chara.h" From 8f9c4dd960ebd659b56d5ddba6ebc215449d1131 Mon Sep 17 00:00:00 2001 From: NotAdam Date: Sat, 20 Apr 2019 22:50:05 +1000 Subject: [PATCH 012/351] fix dumb mistake --- src/world/Navi/NaviProvider.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/world/Navi/NaviProvider.cpp b/src/world/Navi/NaviProvider.cpp index 49383f59..2390e818 100644 --- a/src/world/Navi/NaviProvider.cpp +++ b/src/world/Navi/NaviProvider.cpp @@ -683,5 +683,5 @@ void Sapphire::World::Navi::NaviProvider::removeAgentUpdateFlag( Sapphire::Entit if( !ag ) return; - ag->params.updateFlags ^= flags; + ag->params.updateFlags &= ~flags; } \ No newline at end of file From d934863673f5300fdaa3cabc46f5cb624f76643d Mon Sep 17 00:00:00 2001 From: Mordred Date: Sat, 20 Apr 2019 15:42:48 +0200 Subject: [PATCH 013/351] Maybe better scales? --- src/world/Actor/BNpc.cpp | 12 ++++-------- src/world/Actor/Player.cpp | 1 + src/world/Navi/NaviProvider.cpp | 2 +- 3 files changed, 6 insertions(+), 9 deletions(-) diff --git a/src/world/Actor/BNpc.cpp b/src/world/Actor/BNpc.cpp index 1196341e..fd44a708 100644 --- a/src/world/Actor/BNpc.cpp +++ b/src/world/Actor/BNpc.cpp @@ -278,7 +278,7 @@ bool Sapphire::Entity::BNpc::moveTo( const Entity::Chara& targetChara ) auto pos1 = pNaviProvider->getMovePos( *this ); - if( Util::distance( pos1, targetChara.getPos() ) <= ( getScale() + targetChara.getScale() ) ) + if( Util::distance( pos1, targetChara.getPos() ) <= ( getScale() + targetChara.getScale() ) + 0.25f ) { // Reached destination face( targetChara.getPos() ); @@ -534,9 +534,7 @@ void Sapphire::Entity::BNpc::update( uint64_t tickCount ) return; auto distanceOrig = Util::distance( getPos().x, getPos().y, getPos().z, - m_spawnPos.x, - m_spawnPos.y, - m_spawnPos.z ); + m_spawnPos.x, m_spawnPos.y, m_spawnPos.z ); if( pHatedActor && !pHatedActor->isAlive() ) { @@ -550,9 +548,7 @@ void Sapphire::Entity::BNpc::update( uint64_t tickCount ) if( pHatedActor ) { auto distance = Util::distance( getPos().x, getPos().y, getPos().z, - pHatedActor->getPos().x, - pHatedActor->getPos().y, - pHatedActor->getPos().z ); + pHatedActor->getPos().x, pHatedActor->getPos().y, pHatedActor->getPos().z ); if( !hasFlag( NoDeaggro ) && ( distanceOrig > maxDistanceToOrigin ) ) { @@ -564,7 +560,7 @@ void Sapphire::Entity::BNpc::update( uint64_t tickCount ) break; } - if( distance > ( getScale() / 2 + pHatedActor->getScale() / 2 ) ) + if( distance > ( getScale() + pHatedActor->getScale() ) ) { if( hasFlag( Immobile ) ) break; diff --git a/src/world/Actor/Player.cpp b/src/world/Actor/Player.cpp index de231a2b..84b1be39 100644 --- a/src/world/Actor/Player.cpp +++ b/src/world/Actor/Player.cpp @@ -84,6 +84,7 @@ Sapphire::Entity::Player::Player( FrameworkPtr pFw ) : m_queuedZoneing = nullptr; m_status = ActorStatus::Idle; m_invincibilityType = InvincibilityType::InvincibilityNone; + m_scale = 1.f; memset( m_questTracking, 0, sizeof( m_questTracking ) ); memset( m_name, 0, sizeof( m_name ) ); diff --git a/src/world/Navi/NaviProvider.cpp b/src/world/Navi/NaviProvider.cpp index 2390e818..9934b8cb 100644 --- a/src/world/Navi/NaviProvider.cpp +++ b/src/world/Navi/NaviProvider.cpp @@ -573,7 +573,7 @@ int32_t Sapphire::World::Navi::NaviProvider::addAgent( Entity::Chara& chara ) params.height = 3.f; params.maxAcceleration = 25.f; params.maxSpeed = std::pow( 2, chara.getScale() * 0.35f ) + 1.f; - params.radius = chara.getScale() / 2; + params.radius = ( chara.getScale() ) * 0.9f; params.collisionQueryRange = params.radius * 12.0f; params.pathOptimizationRange = params.radius * 20.0f; params.updateFlags = 0; From 37cff8580f23530025b0c9f581994ee64704f1ad Mon Sep 17 00:00:00 2001 From: Mordred Date: Sat, 20 Apr 2019 23:15:58 +0200 Subject: [PATCH 014/351] Fix autoattack --- src/world/Actor/BNpc.cpp | 3 ++- src/world/Navi/NaviProvider.cpp | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/world/Actor/BNpc.cpp b/src/world/Actor/BNpc.cpp index fd44a708..e14b0f4b 100644 --- a/src/world/Actor/BNpc.cpp +++ b/src/world/Actor/BNpc.cpp @@ -571,7 +571,8 @@ void Sapphire::Entity::BNpc::update( uint64_t tickCount ) } moveTo( *pHatedActor ); } - else + + if( ( distance - getScale() ) < 5 ) { if( !hasFlag( TurningDisabled ) && face( pHatedActor->getPos() ) ) sendPositionUpdate(); diff --git a/src/world/Navi/NaviProvider.cpp b/src/world/Navi/NaviProvider.cpp index 9934b8cb..7a0d728a 100644 --- a/src/world/Navi/NaviProvider.cpp +++ b/src/world/Navi/NaviProvider.cpp @@ -573,7 +573,7 @@ int32_t Sapphire::World::Navi::NaviProvider::addAgent( Entity::Chara& chara ) params.height = 3.f; params.maxAcceleration = 25.f; params.maxSpeed = std::pow( 2, chara.getScale() * 0.35f ) + 1.f; - params.radius = ( chara.getScale() ) * 0.9f; + params.radius = ( chara.getScale() ) * 0.75f; params.collisionQueryRange = params.radius * 12.0f; params.pathOptimizationRange = params.radius * 20.0f; params.updateFlags = 0; From 6ebdad3855893cf1dab31d596f3fcc54836cb14a Mon Sep 17 00:00:00 2001 From: NotAdam Date: Sun, 21 Apr 2019 23:52:41 +1000 Subject: [PATCH 015/351] make larger enemies stack further away from the player --- src/world/Actor/BNpc.cpp | 13 +++++++------ src/world/Actor/Chara.cpp | 6 +++--- src/world/Actor/Chara.h | 4 ++-- src/world/Actor/Player.cpp | 2 +- src/world/Navi/NaviProvider.cpp | 4 ++-- 5 files changed, 15 insertions(+), 14 deletions(-) diff --git a/src/world/Actor/BNpc.cpp b/src/world/Actor/BNpc.cpp index e14b0f4b..49ced95d 100644 --- a/src/world/Actor/BNpc.cpp +++ b/src/world/Actor/BNpc.cpp @@ -98,14 +98,14 @@ Sapphire::Entity::BNpc::BNpc( uint32_t id, BNpcTemplatePtr pTemplate, float posX auto bNpcBaseData = exdData->get< Data::BNpcBase >( m_bNpcBaseId ); assert( bNpcBaseData ); - m_scale = bNpcBaseData->scale; + m_radius = bNpcBaseData->scale; auto modelChara = exdData->get< Data::ModelChara >( bNpcBaseData->modelChara ); if( modelChara ) { auto modelSkeleton = exdData->get< Data::ModelSkeleton >( modelChara->model ); if( modelSkeleton ) - m_scale *= modelSkeleton->scaleFactor; + m_radius *= modelSkeleton->scaleFactor; } // todo: is this actually good? @@ -242,7 +242,7 @@ bool Sapphire::Entity::BNpc::moveTo( const FFXIVARR_POSITION3& pos ) auto pos1 = pNaviProvider->getMovePos( *this ); - if( Util::distance( pos1, pos ) < getScale() ) + if( Util::distance( pos1, pos ) < getRadius() + 3.f ) { // Reached destination face( pos ); @@ -278,7 +278,7 @@ bool Sapphire::Entity::BNpc::moveTo( const Entity::Chara& targetChara ) auto pos1 = pNaviProvider->getMovePos( *this ); - if( Util::distance( pos1, targetChara.getPos() ) <= ( getScale() + targetChara.getScale() ) + 0.25f ) + if( Util::distance( pos1, targetChara.getPos() ) <= ( getRadius() + targetChara.getRadius() ) + 3.f ) { // Reached destination face( targetChara.getPos() ); @@ -560,7 +560,7 @@ void Sapphire::Entity::BNpc::update( uint64_t tickCount ) break; } - if( distance > ( getScale() + pHatedActor->getScale() ) ) + if( distance > ( getRadius() + pHatedActor->getRadius() ) ) { if( hasFlag( Immobile ) ) break; @@ -572,10 +572,11 @@ void Sapphire::Entity::BNpc::update( uint64_t tickCount ) moveTo( *pHatedActor ); } - if( ( distance - getScale() ) < 5 ) + if( distance < ( getRadius() + pHatedActor->getRadius() + 3.f ) ) { if( !hasFlag( TurningDisabled ) && face( pHatedActor->getPos() ) ) sendPositionUpdate(); + // in combat range. ATTACK! autoAttack( pHatedActor ); } diff --git a/src/world/Actor/Chara.cpp b/src/world/Actor/Chara.cpp index 6eba77f9..b4e9303d 100644 --- a/src/world/Actor/Chara.cpp +++ b/src/world/Actor/Chara.cpp @@ -39,7 +39,7 @@ Sapphire::Entity::Chara::Chara( ObjKind type, FrameworkPtr pFw ) : m_targetId( INVALID_GAME_OBJECT_ID64 ), m_pFw( std::move( std::move( pFw ) ) ), m_directorId( 0 ), - m_scale( 2.f ) + m_radius( 1.f ) { m_lastTickTime = 0; @@ -715,7 +715,7 @@ void Sapphire::Entity::Chara::setAgentId( uint32_t agentId ) } -float Sapphire::Entity::Chara::getScale() const +float Sapphire::Entity::Chara::getRadius() const { - return m_scale; + return m_radius; } \ No newline at end of file diff --git a/src/world/Actor/Chara.h b/src/world/Actor/Chara.h index 56638255..d882a18a 100644 --- a/src/world/Actor/Chara.h +++ b/src/world/Actor/Chara.h @@ -132,7 +132,7 @@ namespace Sapphire::Entity uint32_t m_agentId; /*! Detour Crowd actor scale */ - float m_scale; + float m_radius; public: Chara( Common::ObjKind type, FrameworkPtr pFw ); @@ -278,7 +278,7 @@ namespace Sapphire::Entity uint32_t getAgentId() const; void setAgentId( uint32_t agentId ); - float getScale() const; + float getRadius() const; }; diff --git a/src/world/Actor/Player.cpp b/src/world/Actor/Player.cpp index 84b1be39..f6d32053 100644 --- a/src/world/Actor/Player.cpp +++ b/src/world/Actor/Player.cpp @@ -84,7 +84,7 @@ Sapphire::Entity::Player::Player( FrameworkPtr pFw ) : m_queuedZoneing = nullptr; m_status = ActorStatus::Idle; m_invincibilityType = InvincibilityType::InvincibilityNone; - m_scale = 1.f; + m_radius = 1.f; memset( m_questTracking, 0, sizeof( m_questTracking ) ); memset( m_name, 0, sizeof( m_name ) ); diff --git a/src/world/Navi/NaviProvider.cpp b/src/world/Navi/NaviProvider.cpp index 7a0d728a..99cb7079 100644 --- a/src/world/Navi/NaviProvider.cpp +++ b/src/world/Navi/NaviProvider.cpp @@ -572,8 +572,8 @@ int32_t Sapphire::World::Navi::NaviProvider::addAgent( Entity::Chara& chara ) std::memset( ¶ms, 0, sizeof( params ) ); params.height = 3.f; params.maxAcceleration = 25.f; - params.maxSpeed = std::pow( 2, chara.getScale() * 0.35f ) + 1.f; - params.radius = ( chara.getScale() ) * 0.75f; + params.maxSpeed = std::pow( 2, chara.getRadius() * 0.35f ) + 1.f; + params.radius = ( chara.getRadius() ) * 0.75f; params.collisionQueryRange = params.radius * 12.0f; params.pathOptimizationRange = params.radius * 20.0f; params.updateFlags = 0; From cb7a91d9d8d62e181b9d9e121e61aa5cc591bb2f Mon Sep 17 00:00:00 2001 From: NotAdam Date: Mon, 22 Apr 2019 00:05:04 +1000 Subject: [PATCH 016/351] fix bnpcs not being pushed --- src/world/Actor/BNpc.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/world/Actor/BNpc.cpp b/src/world/Actor/BNpc.cpp index 49ced95d..1b211251 100644 --- a/src/world/Actor/BNpc.cpp +++ b/src/world/Actor/BNpc.cpp @@ -238,7 +238,7 @@ bool Sapphire::Entity::BNpc::moveTo( const FFXIVARR_POSITION3& pos ) return false; } - pNaviProvider->addAgentUpdateFlag( *this, DT_CROWD_OBSTACLE_AVOIDANCE ); +// pNaviProvider->addAgentUpdateFlag( *this, DT_CROWD_OBSTACLE_AVOIDANCE ); auto pos1 = pNaviProvider->getMovePos( *this ); @@ -250,7 +250,7 @@ bool Sapphire::Entity::BNpc::moveTo( const FFXIVARR_POSITION3& pos ) sendPositionUpdate(); //pNaviProvider->resetMoveTarget( *this ); pNaviProvider->updateAgentPosition( *this ); - pNaviProvider->removeAgentUpdateFlag( *this, DT_CROWD_OBSTACLE_AVOIDANCE ); +// pNaviProvider->removeAgentUpdateFlag( *this, DT_CROWD_OBSTACLE_AVOIDANCE ); return true; } @@ -274,7 +274,7 @@ bool Sapphire::Entity::BNpc::moveTo( const Entity::Chara& targetChara ) return false; } - pNaviProvider->addAgentUpdateFlag( *this, DT_CROWD_OBSTACLE_AVOIDANCE ); +// pNaviProvider->addAgentUpdateFlag( *this, DT_CROWD_OBSTACLE_AVOIDANCE ); auto pos1 = pNaviProvider->getMovePos( *this ); @@ -286,7 +286,7 @@ bool Sapphire::Entity::BNpc::moveTo( const Entity::Chara& targetChara ) sendPositionUpdate(); //pNaviProvider->resetMoveTarget( *this ); pNaviProvider->updateAgentPosition( *this ); - pNaviProvider->removeAgentUpdateFlag( *this, DT_CROWD_OBSTACLE_AVOIDANCE ); +// pNaviProvider->removeAgentUpdateFlag( *this, DT_CROWD_OBSTACLE_AVOIDANCE ); return true; } From 1621b9fd20ecc331f111a980e5b6c8aeed3f2f24 Mon Sep 17 00:00:00 2001 From: Mordred Date: Mon, 22 Apr 2019 00:16:39 +0200 Subject: [PATCH 017/351] Fxed bnpcs sometimes being immobile --- src/world/Actor/BNpc.cpp | 60 ++-------------------------------------- src/world/Actor/BNpc.h | 3 -- 2 files changed, 2 insertions(+), 61 deletions(-) diff --git a/src/world/Actor/BNpc.cpp b/src/world/Actor/BNpc.cpp index 1b211251..56ab6ead 100644 --- a/src/world/Actor/BNpc.cpp +++ b/src/world/Actor/BNpc.cpp @@ -70,6 +70,7 @@ Sapphire::Entity::BNpc::BNpc( uint32_t id, BNpcTemplatePtr pTemplate, float posX m_invincibilityType = InvincibilityNone; m_currentStance = Common::Stance::Passive; m_levelId = 0; + m_flags = 0; m_pCurrentZone = pZone; @@ -182,49 +183,6 @@ void Sapphire::Entity::BNpc::setState( BNpcState state ) m_state = state; } -void Sapphire::Entity::BNpc::step() -{ - if( m_naviLastPath.empty() ) - // No path to track - return; - - auto stepPos = m_naviLastPath[ m_naviPathStep ]; - - auto distanceToStep = Util::distance( getPos(), stepPos ); - auto distanceToDest = Util::distance( getPos(), m_naviTarget ); - - if( distanceToStep <= 4 && m_naviPathStep < m_naviLastPath.size() - 1 ) - { - // Reached step in path - m_naviPathStep++; - stepPos = m_naviLastPath[ m_naviPathStep ]; - } - - // This is probably not a good way to do it but works fine for now - float angle = Util::calcAngFrom( getPos().x, getPos().z, stepPos.x, stepPos.z ) + PI; - - auto delta = static_cast< float >( Util::getTimeMs() - m_lastUpdate ) / 1000.f; - - float speed = 7.5f * delta; - - if( m_state == BNpcState::Roaming ) - speed *= 0.27f; - - // this seems to fix it but i don't know why :( - if( speed > distanceToDest ) - speed = distanceToDest / delta; - - auto x = ( cosf( angle ) * speed ); - auto y = stepPos.y; - auto z = ( sinf( angle ) * speed ); - - - face( stepPos ); - setPos( { getPos().x + x, y, getPos().z + z } ); - sendPositionUpdate(); - -} - bool Sapphire::Entity::BNpc::moveTo( const FFXIVARR_POSITION3& pos ) { @@ -238,8 +196,6 @@ bool Sapphire::Entity::BNpc::moveTo( const FFXIVARR_POSITION3& pos ) return false; } -// pNaviProvider->addAgentUpdateFlag( *this, DT_CROWD_OBSTACLE_AVOIDANCE ); - auto pos1 = pNaviProvider->getMovePos( *this ); if( Util::distance( pos1, pos ) < getRadius() + 3.f ) @@ -248,9 +204,7 @@ bool Sapphire::Entity::BNpc::moveTo( const FFXIVARR_POSITION3& pos ) face( pos ); setPos( pos1 ); sendPositionUpdate(); - //pNaviProvider->resetMoveTarget( *this ); pNaviProvider->updateAgentPosition( *this ); -// pNaviProvider->removeAgentUpdateFlag( *this, DT_CROWD_OBSTACLE_AVOIDANCE ); return true; } @@ -274,8 +228,6 @@ bool Sapphire::Entity::BNpc::moveTo( const Entity::Chara& targetChara ) return false; } -// pNaviProvider->addAgentUpdateFlag( *this, DT_CROWD_OBSTACLE_AVOIDANCE ); - auto pos1 = pNaviProvider->getMovePos( *this ); if( Util::distance( pos1, targetChara.getPos() ) <= ( getRadius() + targetChara.getRadius() ) + 3.f ) @@ -284,9 +236,7 @@ bool Sapphire::Entity::BNpc::moveTo( const Entity::Chara& targetChara ) face( targetChara.getPos() ); setPos( pos1 ); sendPositionUpdate(); - //pNaviProvider->resetMoveTarget( *this ); pNaviProvider->updateAgentPosition( *this ); -// pNaviProvider->removeAgentUpdateFlag( *this, DT_CROWD_OBSTACLE_AVOIDANCE ); return true; } @@ -446,7 +396,6 @@ void Sapphire::Entity::BNpc::onTick() void Sapphire::Entity::BNpc::update( uint64_t tickCount ) { - const uint8_t minActorDistance = 4; const uint8_t maxDistanceToOrigin = 40; const uint32_t roamTick = 20; @@ -463,9 +412,7 @@ void Sapphire::Entity::BNpc::update( uint64_t tickCount ) setInvincibilityType( InvincibilityType::InvincibilityIgnoreDamage ); if( pNaviProvider ) - { pNaviProvider->setMoveTarget( *this, m_spawnPos ); - } if( moveTo( m_spawnPos ) ) { @@ -488,9 +435,7 @@ void Sapphire::Entity::BNpc::update( uint64_t tickCount ) { if( pNaviProvider ) - { pNaviProvider->setMoveTarget( *this, m_roamPos ); - } if( moveTo( m_roamPos ) ) { @@ -566,9 +511,8 @@ void Sapphire::Entity::BNpc::update( uint64_t tickCount ) break; if( pNaviProvider ) - { pNaviProvider->setMoveTarget( *this, pHatedActor->getPos() ); - } + moveTo( *pHatedActor ); } diff --git a/src/world/Actor/BNpc.h b/src/world/Actor/BNpc.h index 5042118c..6a38ecfa 100644 --- a/src/world/Actor/BNpc.h +++ b/src/world/Actor/BNpc.h @@ -79,9 +79,6 @@ namespace Sapphire::Entity bool moveTo( const Entity::Chara& targetChara ); - // processes movement - void step(); - void sendPositionUpdate(); BNpcState getState() const; From ad4d8049e030cdc7bbfdff309824f4668e5a53d0 Mon Sep 17 00:00:00 2001 From: Mordred Date: Mon, 22 Apr 2019 23:30:43 +0200 Subject: [PATCH 018/351] Movement speed of BNpcs will double when in combat or retreat mode --- src/world/Actor/BNpc.cpp | 4 +++- src/world/Navi/NaviProvider.cpp | 17 +++++++++++++++++ src/world/Navi/NaviProvider.h | 2 ++ 3 files changed, 22 insertions(+), 1 deletion(-) diff --git a/src/world/Actor/BNpc.cpp b/src/world/Actor/BNpc.cpp index 56ab6ead..4454af44 100644 --- a/src/world/Actor/BNpc.cpp +++ b/src/world/Actor/BNpc.cpp @@ -247,7 +247,6 @@ bool Sapphire::Entity::BNpc::moveTo( const Entity::Chara& targetChara ) return false; } - void Sapphire::Entity::BNpc::sendPositionUpdate() { uint8_t unk1 = 0x3a; @@ -478,6 +477,8 @@ void Sapphire::Entity::BNpc::update( uint64_t tickCount ) if( !pHatedActor ) return; + pNaviProvider->updateAgentParameters( *this ); + auto distanceOrig = Util::distance( getPos().x, getPos().y, getPos().z, m_spawnPos.x, m_spawnPos.y, m_spawnPos.z ); @@ -531,6 +532,7 @@ void Sapphire::Entity::BNpc::update( uint64_t tickCount ) setStance( Stance::Passive ); //setOwner( nullptr ); m_state = BNpcState::Retreat; + pNaviProvider->updateAgentParameters( *this ); } } } diff --git a/src/world/Navi/NaviProvider.cpp b/src/world/Navi/NaviProvider.cpp index 99cb7079..aaee0ba7 100644 --- a/src/world/Navi/NaviProvider.cpp +++ b/src/world/Navi/NaviProvider.cpp @@ -6,6 +6,7 @@ #include "Actor/Actor.h" #include "Actor/Chara.h" +#include "Actor/BNpc.h" #include @@ -582,6 +583,22 @@ int32_t Sapphire::World::Navi::NaviProvider::addAgent( Entity::Chara& chara ) return m_pCrowd->addAgent( position, ¶ms ); } +void Sapphire::World::Navi::NaviProvider::updateAgentParameters( Entity::BNpc& bnpc ) +{ + dtCrowdAgentParams params; + std::memset( ¶ms, 0, sizeof( params ) ); + params.height = 3.f; + params.maxAcceleration = 25.f; + params.maxSpeed = std::pow( 2, bnpc.getRadius() * 0.35f ) + 1.f; + if( bnpc.getState() == Entity::BNpcState::Combat || bnpc.getState() == Entity::BNpcState::Retreat ) + params.maxSpeed *= 2; + params.radius = ( bnpc.getRadius() ) * 0.75f; + params.collisionQueryRange = params.radius * 12.0f; + params.pathOptimizationRange = params.radius * 20.0f; + params.updateFlags = 0; + m_pCrowd->updateAgentParameters( bnpc.getAgentId(), ¶ms ); +} + void Sapphire::World::Navi::NaviProvider::updateCrowd( float timeInSeconds ) { dtCrowdAgentDebugInfo info; diff --git a/src/world/Navi/NaviProvider.h b/src/world/Navi/NaviProvider.h index d402cda0..047abf17 100644 --- a/src/world/Navi/NaviProvider.h +++ b/src/world/Navi/NaviProvider.h @@ -72,6 +72,8 @@ namespace Sapphire::World::Navi void addAgentUpdateFlag( Entity::Chara& chara, uint8_t flags ); void removeAgentUpdateFlag( Entity::Chara& chara, uint8_t flags ); + void updateAgentParameters( Entity::BNpc& bnpc ); + protected: std::string m_internalName; From 8002e88d10a0f6ce0574f6d66af5af5e0c1aaf3b Mon Sep 17 00:00:00 2001 From: Mordred Date: Tue, 23 Apr 2019 00:00:07 +0200 Subject: [PATCH 019/351] Properly reset aggro on mob retreat --- src/world/Actor/BNpc.cpp | 5 +++-- src/world/Navi/NaviProvider.cpp | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/world/Actor/BNpc.cpp b/src/world/Actor/BNpc.cpp index 4454af44..841ff2b9 100644 --- a/src/world/Actor/BNpc.cpp +++ b/src/world/Actor/BNpc.cpp @@ -352,7 +352,7 @@ bool Sapphire::Entity::BNpc::hateListHasActor( Sapphire::Entity::CharaPtr pChara void Sapphire::Entity::BNpc::aggro( Sapphire::Entity::CharaPtr pChara ) { auto pRNGMgr = m_pFw->get< World::Manager::RNGMgr >(); - auto variation = static_cast< uint32_t >( pRNGMgr->getRandGenerator< float >( 50, 600 ).next() ); + auto variation = static_cast< uint32_t >( pRNGMgr->getRandGenerator< float >( 500, 1000 ).next() ); m_lastAttack = Util::getTimeMs() + variation; hateListUpdate( pChara, 1 ); @@ -380,7 +380,8 @@ void Sapphire::Entity::BNpc::deaggro( Sapphire::Entity::CharaPtr pChara ) if( pChara->isPlayer() ) { PlayerPtr tmpPlayer = pChara->getAsPlayer(); - tmpPlayer->queuePacket( makeActorControl142( getId(), ActorControlType::ToggleWeapon, 0, 1, 1 ) ); + sendToInRangeSet( makeActorControl142( getId(), ActorControlType::ToggleWeapon, 0, 1, 1 ) ); + sendToInRangeSet( makeActorControl142( getId(), ActorControlType::ToggleAggro, 0, 0, 0 ) ); tmpPlayer->onMobDeaggro( getAsBNpc() ); } } diff --git a/src/world/Navi/NaviProvider.cpp b/src/world/Navi/NaviProvider.cpp index aaee0ba7..277f9299 100644 --- a/src/world/Navi/NaviProvider.cpp +++ b/src/world/Navi/NaviProvider.cpp @@ -578,7 +578,7 @@ int32_t Sapphire::World::Navi::NaviProvider::addAgent( Entity::Chara& chara ) params.collisionQueryRange = params.radius * 12.0f; params.pathOptimizationRange = params.radius * 20.0f; params.updateFlags = 0; - //params.updateFlags |= DT_CROWD_OBSTACLE_AVOIDANCE; + params.updateFlags |= DT_CROWD_ANTICIPATE_TURNS; float position[] = { chara.getPos().x, chara.getPos().y, chara.getPos().z }; return m_pCrowd->addAgent( position, ¶ms ); } From e951a33d96da61a5fedd58be2902976fa15edcc1 Mon Sep 17 00:00:00 2001 From: NotAdam Date: Tue, 23 Apr 2019 21:52:00 +1000 Subject: [PATCH 020/351] fix bnpcs not navigating around obstacles --- src/world/Navi/NaviProvider.cpp | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/src/world/Navi/NaviProvider.cpp b/src/world/Navi/NaviProvider.cpp index 277f9299..4ea29654 100644 --- a/src/world/Navi/NaviProvider.cpp +++ b/src/world/Navi/NaviProvider.cpp @@ -181,11 +181,11 @@ int32_t Sapphire::World::Navi::NaviProvider::fixupShortcuts( dtPolyRef* path, in // in the path, short cut to that polygon directly. const int32_t maxLookAhead = 6; int32_t cut = 0; - for( int32_t i = dtMin( maxLookAhead, npath ) - 1; i > 1 && cut == 0; i-- ) + for( int32_t i = dtMin( maxLookAhead, npath ) - 1; i > 1 && cut == 0; i-- ) { for( int32_t j = 0; j < nneis; j++ ) { - if( path[ i ] == neis[ j ] ) + if( path[ i ] == neis[ j ] ) { cut = i; break; @@ -310,7 +310,7 @@ Sapphire::Common::FFXIVARR_POSITION3 return { randomPt[ 0 ], randomPt[ 1 ], randomPt[ 2 ] }; } -std::vector< Sapphire::Common::FFXIVARR_POSITION3 > +std::vector< Sapphire::Common::FFXIVARR_POSITION3 > Sapphire::World::Navi::NaviProvider::findFollowPath( const Common::FFXIVARR_POSITION3& startPos, const Common::FFXIVARR_POSITION3& endPos ) { @@ -546,7 +546,7 @@ bool Sapphire::World::Navi::NaviProvider::loadMesh( const std::string& path ) break; auto data = reinterpret_cast< uint8_t* >( dtAlloc( tileHeader.dataSize, DT_ALLOC_PERM ) ); - if( !data ) + if( !data ) break; memset( data, 0, tileHeader.dataSize ); readLen = fread( data, tileHeader.dataSize, 1, fp ); @@ -632,11 +632,24 @@ void Sapphire::World::Navi::NaviProvider::setMoveTarget( Entity::Chara& chara, float vel[ 3 ]; float p[ 3 ] = { endPos.x, endPos.y, endPos.z }; + dtPolyRef ref; + + auto status = m_naviMeshQuery->findNearestPoly( p, halfExtents, filter, &ref, nullptr ); + + if( !dtStatusSucceed( status ) ) + { + Logger::error( "Failed to find nearest poly for Chara#{} for pos X: {} Y: {} Z: {}", + chara.getId(), endPos.x, endPos.y, endPos.z ); + + return; + } + 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 ); + //m_pCrowd->requestMoveVelocity( chara.getAgentId(), vel ); + m_pCrowd->requestMoveTarget( chara.getAgentId(), ref, p ); } } From a2e5d5a661dc6f4de22047b23e230afb6c80daf5 Mon Sep 17 00:00:00 2001 From: NotAdam Date: Tue, 23 Apr 2019 22:04:24 +1000 Subject: [PATCH 021/351] some cleanup --- src/world/Navi/NaviProvider.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/world/Navi/NaviProvider.cpp b/src/world/Navi/NaviProvider.cpp index 4ea29654..89534d0c 100644 --- a/src/world/Navi/NaviProvider.cpp +++ b/src/world/Navi/NaviProvider.cpp @@ -629,7 +629,6 @@ void Sapphire::World::Navi::NaviProvider::setMoveTarget( Entity::Chara& chara, const dtQueryFilter* filter = m_pCrowd->getFilter( 0 ); const float* halfExtents = m_pCrowd->getQueryExtents(); - float vel[ 3 ]; float p[ 3 ] = { endPos.x, endPos.y, endPos.z }; dtPolyRef ref; @@ -647,8 +646,6 @@ void Sapphire::World::Navi::NaviProvider::setMoveTarget( Entity::Chara& chara, 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 ); m_pCrowd->requestMoveTarget( chara.getAgentId(), ref, p ); } } From e2a3e560a6c45fe5e86aa13a834d67e9c5cda4cc Mon Sep 17 00:00:00 2001 From: mordred Date: Wed, 24 Apr 2019 08:31:42 +0200 Subject: [PATCH 022/351] nav_export takes a path to the dats again --- src/tools/nav_export/main.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/tools/nav_export/main.cpp b/src/tools/nav_export/main.cpp index 600ba1dd..043410a7 100644 --- a/src/tools/nav_export/main.cpp +++ b/src/tools/nav_export/main.cpp @@ -314,6 +314,9 @@ int main( int argc, char* argv[] ) if( generateNavmesh ) exportFileType |= ExportFileType::Navmesh; + if( argc > 1 ) + gamePath = std::string( argv[ 1 ] ); + try { initExd( gamePath ); @@ -321,7 +324,7 @@ int main( int argc, char* argv[] ) } catch( std::exception& e ) { - printf( "Unable to initialise EXD!\n Usage: pcb_reader \"path/to/FINAL FANTASY XIV - A REALM REBORN/game/sqpack\"\n" ); + printf( "Unable to initialise EXD!\n Usage: nav_export \"path/to/FINAL FANTASY XIV - A REALM REBORN/game/sqpack\"\n" ); return -1; } ExportMgr exportMgr( nJobs ); @@ -486,7 +489,7 @@ int main( int argc, char* argv[] ) { printf( "%s", ( std::string( e.what() ) + "\n" ).c_str() ); printf( "Unable to extract collision data.\n" ); - printf( "Usage: pcb_reader2 territory \"path/to/game/sqpack/ffxiv\"\n" ); + printf( "Usage: nav_export \"path/to/game/sqpack/ffxiv\"\n" ); } } pCache->purge(); From 4de66b10645cf8ea978f72ec4d78dcef64c36d27 Mon Sep 17 00:00:00 2001 From: NotAdam Date: Wed, 24 Apr 2019 23:25:07 +1000 Subject: [PATCH 023/351] autoattack damage stat calc funcs, bnpc stat calculation --- src/common/Exd/ExdDataGenerated.cpp | 1 + src/common/Exd/ExdDataGenerated.h | 1 + src/world/Actor/BNpc.cpp | 54 +++++++- src/world/Actor/BNpc.h | 2 + src/world/Actor/Chara.cpp | 11 ++ src/world/Actor/Chara.h | 2 + src/world/Actor/Player.cpp | 15 +- src/world/Actor/Player.h | 6 +- src/world/Actor/PlayerInventory.cpp | 15 +- src/world/Math/CalcStats.cpp | 207 +++++++++++++++++++++------- src/world/Math/CalcStats.h | 34 ++--- 11 files changed, 253 insertions(+), 95 deletions(-) diff --git a/src/common/Exd/ExdDataGenerated.cpp b/src/common/Exd/ExdDataGenerated.cpp index c7485692..fa51b627 100644 --- a/src/common/Exd/ExdDataGenerated.cpp +++ b/src/common/Exd/ExdDataGenerated.cpp @@ -1114,6 +1114,7 @@ Sapphire::Data::ClassJob::ClassJob( uint32_t row_id, Sapphire::Data::ExdDataGene classJobParent = exdData->getField< uint8_t >( row, 26 ); nameEnglish = exdData->getField< std::string >( row, 27 ); itemStartingWeapon = exdData->getField< int32_t >( row, 28 ); + primaryStat = exdData->getField< uint8_t >( row, 33 ); limitBreak1 = exdData->getField< uint16_t >( row, 34 ); limitBreak2 = exdData->getField< uint16_t >( row, 35 ); limitBreak3 = exdData->getField< uint16_t >( row, 36 ); diff --git a/src/common/Exd/ExdDataGenerated.h b/src/common/Exd/ExdDataGenerated.h index 97c6122b..bcbba9b2 100644 --- a/src/common/Exd/ExdDataGenerated.h +++ b/src/common/Exd/ExdDataGenerated.h @@ -1485,6 +1485,7 @@ struct ClassJob uint8_t classJobParent; std::string nameEnglish; int32_t itemStartingWeapon; + uint8_t primaryStat; uint16_t limitBreak1; uint16_t limitBreak2; uint16_t limitBreak3; diff --git a/src/world/Actor/BNpc.cpp b/src/world/Actor/BNpc.cpp index 841ff2b9..9f7bd41f 100644 --- a/src/world/Actor/BNpc.cpp +++ b/src/world/Actor/BNpc.cpp @@ -22,18 +22,22 @@ #include "Network/PacketWrappers/MoveActorPacket.h" #include "Navi/NaviProvider.h" +#include "Math/CalcBattle.h" +#include "Math/CalcStats.h" + #include "StatusEffect/StatusEffect.h" + #include "ServerMgr.h" #include "Session.h" -#include "Math/CalcBattle.h" #include "Chara.h" #include "Player.h" #include "BNpc.h" #include "BNpcTemplate.h" -#include "Manager/TerritoryMgr.h" + #include "Common.h" #include "Framework.h" -#include + +#include #include #include #include @@ -72,7 +76,9 @@ Sapphire::Entity::BNpc::BNpc( uint32_t id, BNpcTemplatePtr pTemplate, float posX m_levelId = 0; m_flags = 0; - m_pCurrentZone = pZone; + m_class = ClassJob::Adventurer; + + m_pCurrentZone = std::move( pZone ); m_spawnPos = m_pos; @@ -112,6 +118,8 @@ Sapphire::Entity::BNpc::BNpc( uint32_t id, BNpcTemplatePtr pTemplate, float posX // todo: is this actually good? //m_naviTargetReachedDistance = m_scale * 2.f; m_naviTargetReachedDistance = 4.f; + + calculateStats(); } Sapphire::Entity::BNpc::~BNpc() = default; @@ -262,7 +270,7 @@ void Sapphire::Entity::BNpc::sendPositionUpdate() void Sapphire::Entity::BNpc::hateListClear() { auto it = m_hateList.begin(); - for( auto listEntry : m_hateList ) + for( auto& listEntry : m_hateList ) { if( isInRangeSet( listEntry->m_pChara ) ) deaggro( listEntry->m_pChara ); @@ -681,7 +689,7 @@ void Sapphire::Entity::BNpc::autoAttack( CharaPtr pTarget ) srand( static_cast< uint32_t >( tick ) ); auto pRNGMgr = m_pFw->get< World::Manager::RNGMgr >(); - auto damage = static_cast< uint16_t >( pRNGMgr->getRandGenerator< float >( m_level, m_level + m_level * 1.5f ).next() ); + auto damage = Math::CalcStats::calculateAutoAttackDamage( *this ); auto effectPacket = std::make_shared< Server::EffectPacket >( getId(), pTarget->getId(), 7 ); effectPacket->setRotation( Util::floatToUInt16Rot( getRot() ) ); @@ -696,4 +704,38 @@ void Sapphire::Entity::BNpc::autoAttack( CharaPtr pTarget ) pTarget->takeDamage( damage ); } +} + +void Sapphire::Entity::BNpc::calculateStats() +{ + uint8_t level = getLevel(); + uint8_t job = static_cast< uint8_t >( getClass() ); + + auto pExdData = m_pFw->get< Data::ExdDataGenerated >(); + + auto classInfo = pExdData->get< Sapphire::Data::ClassJob >( job ); + auto paramGrowthInfo = pExdData->get< Sapphire::Data::ParamGrow >( level ); + + float base = Math::CalcStats::calculateBaseStat( *this ); + + m_baseStats.str = static_cast< uint32_t >( base * ( static_cast< float >( classInfo->modifierStrength ) / 100 ) ); + m_baseStats.dex = static_cast< uint32_t >( base * ( static_cast< float >( classInfo->modifierDexterity ) / 100 ) ); + m_baseStats.vit = static_cast< uint32_t >( base * ( static_cast< float >( classInfo->modifierVitality ) / 100 ) ); + m_baseStats.inte = static_cast< uint32_t >( base * ( static_cast< float >( classInfo->modifierIntelligence ) / 100 ) ); + m_baseStats.mnd = static_cast< uint32_t >( base * ( static_cast< float >( classInfo->modifierMind ) / 100 ) ); + m_baseStats.pie = static_cast< uint32_t >( base * ( static_cast< float >( classInfo->modifierPiety ) / 100 ) ); + + m_baseStats.determination = static_cast< uint32_t >( base ); + m_baseStats.pie = static_cast< uint32_t >( base ); + m_baseStats.skillSpeed = paramGrowthInfo->baseSpeed; + m_baseStats.spellSpeed = paramGrowthInfo->baseSpeed; + m_baseStats.accuracy = paramGrowthInfo->baseSpeed; + m_baseStats.critHitRate = paramGrowthInfo->baseSpeed; + m_baseStats.attackPotMagic = paramGrowthInfo->baseSpeed; + m_baseStats.healingPotMagic = paramGrowthInfo->baseSpeed; + m_baseStats.tenacity = paramGrowthInfo->baseSpeed; + + m_baseStats.attack = m_baseStats.str; + m_baseStats.attackPotMagic = m_baseStats.inte; + m_baseStats.healingPotMagic = m_baseStats.mnd; } \ No newline at end of file diff --git a/src/world/Actor/BNpc.h b/src/world/Actor/BNpc.h index 6a38ecfa..8f14e024 100644 --- a/src/world/Actor/BNpc.h +++ b/src/world/Actor/BNpc.h @@ -118,6 +118,8 @@ namespace Sapphire::Entity bool hasFlag( uint32_t flag ) const; void setFlag( uint32_t flags ); + void calculateStats() override; + private: uint32_t m_bNpcBaseId; uint32_t m_bNpcNameId; diff --git a/src/world/Actor/Chara.cpp b/src/world/Actor/Chara.cpp index b4e9303d..968698b0 100644 --- a/src/world/Actor/Chara.cpp +++ b/src/world/Actor/Chara.cpp @@ -718,4 +718,15 @@ void Sapphire::Entity::Chara::setAgentId( uint32_t agentId ) float Sapphire::Entity::Chara::getRadius() const { return m_radius; +} + +Sapphire::Common::BaseParam Sapphire::Entity::Chara::getPrimaryStat() const +{ + auto exdData = m_pFw->get< Data::ExdDataGenerated >(); + assert( exdData ); + + auto classJob = exdData->get< Data::ClassJob >( static_cast< uint16_t >( getClass() ) ); + assert( classJob ); + + return static_cast< Sapphire::Common::BaseParam >( classJob->primaryStat ); } \ No newline at end of file diff --git a/src/world/Actor/Chara.h b/src/world/Actor/Chara.h index d882a18a..4e2d8e9b 100644 --- a/src/world/Actor/Chara.h +++ b/src/world/Actor/Chara.h @@ -280,6 +280,8 @@ namespace Sapphire::Entity float getRadius() const; + Common::BaseParam getPrimaryStat() const; + }; } diff --git a/src/world/Actor/Player.cpp b/src/world/Actor/Player.cpp index f6d32053..1547a860 100644 --- a/src/world/Actor/Player.cpp +++ b/src/world/Actor/Player.cpp @@ -256,7 +256,7 @@ void Sapphire::Entity::Player::calculateStats() auto tribeInfo = pExdData->get< Sapphire::Data::Tribe >( tribe ); auto paramGrowthInfo = pExdData->get< Sapphire::Data::ParamGrow >( level ); - float base = Math::CalcStats::calculateBaseStat( getAsPlayer() ); + float base = Math::CalcStats::calculateBaseStat( *this ); m_baseStats.str = static_cast< uint32_t >( base * ( static_cast< float >( classInfo->modifierStrength ) / 100 ) + tribeInfo->sTR ); @@ -1559,8 +1559,7 @@ void Sapphire::Entity::Player::autoAttack( CharaPtr pTarget ) auto pRNGMgr = m_pFw->get< World::Manager::RNGMgr >(); auto variation = static_cast< uint32_t >( pRNGMgr->getRandGenerator< float >( 0, 3 ).next() ); - auto damage = static_cast< uint32_t >( pRNGMgr->getRandGenerator< float >( static_cast< uint32_t > ( getLevel() * 1.5f ), - getLevel() + static_cast< uint32_t >( mainWeap->getAutoAttackDmg() * 2 ) ).next() ); + auto damage = Math::CalcStats::calculateAutoAttackDamage( *this ); if( getClass() == ClassJob::Machinist || getClass() == ClassJob::Bard || getClass() == ClassJob::Archer ) { @@ -2116,3 +2115,13 @@ Sapphire::World::SessionPtr Sapphire::Entity::Player::getSession() return m_pSession; } +void Sapphire::Entity::Player::setActiveLand( uint8_t land, uint8_t ward ) +{ + m_activeLand.plot = land; + m_activeLand.ward = ward; +} + +Sapphire::Common::ActiveLand Sapphire::Entity::Player::getActiveLand() const +{ + return m_activeLand; +} diff --git a/src/world/Actor/Player.h b/src/world/Actor/Player.h index b7becacb..3fbf9f88 100644 --- a/src/world/Actor/Player.h +++ b/src/world/Actor/Player.h @@ -933,6 +933,8 @@ namespace Sapphire::Entity /*! calculate and return player ilvl based off equipped gear */ uint16_t calculateEquippedGearItemLevel(); + ItemPtr getEquippedWeapon(); + /*! return the current amount of currency of type */ uint32_t getCurrency( Common::CurrencyType type ); @@ -964,6 +966,8 @@ namespace Sapphire::Entity Sapphire::ItemPtr dropInventoryItem( Common::InventoryType type, uint16_t slotId ); + ////////////////////////////////////////////////////////////////////////////////////////////////////// + Common::HuntingLogEntry& getHuntingLogEntry( uint8_t index ); void sendHuntingLog(); @@ -974,8 +978,6 @@ namespace Sapphire::Entity World::SessionPtr getSession(); - ////////////////////////////////////////////////////////////////////////////////////////////////////// - uint64_t m_lastMoveTime; uint8_t m_lastMoveflag; bool m_falling; diff --git a/src/world/Actor/PlayerInventory.cpp b/src/world/Actor/PlayerInventory.cpp index 97fec07b..3d25ad4f 100644 --- a/src/world/Actor/PlayerInventory.cpp +++ b/src/world/Actor/PlayerInventory.cpp @@ -831,17 +831,6 @@ void Sapphire::Entity::Player::discardItem( uint16_t fromInventoryId, uint8_t fr queuePacket( invTransFinPacket ); } -void Sapphire::Entity::Player::setActiveLand( uint8_t land, uint8_t ward ) -{ - m_activeLand.plot = land; - m_activeLand.ward = ward; -} - -Sapphire::Common::ActiveLand Sapphire::Entity::Player::getActiveLand() const -{ - return m_activeLand; -} - uint16_t Sapphire::Entity::Player::calculateEquippedGearItemLevel() { uint32_t iLvlResult = 0; @@ -871,6 +860,10 @@ uint16_t Sapphire::Entity::Player::calculateEquippedGearItemLevel() return static_cast< uint16_t >( std::min( static_cast< int32_t >( iLvlResult / 13 ), 9999 ) ); } +Sapphire::ItemPtr Sapphire::Entity::Player::getEquippedWeapon() +{ + return m_storageMap[ GearSet0 ]->getItem( GearSetSlot::MainHand ); +} uint8_t Sapphire::Entity::Player::getFreeSlotsInBags() { diff --git a/src/world/Math/CalcStats.cpp b/src/world/Math/CalcStats.cpp index 859cedec..99c536c8 100644 --- a/src/world/Math/CalcStats.cpp +++ b/src/world/Math/CalcStats.cpp @@ -2,11 +2,13 @@ #include #include +#include #include "Actor/Chara.h" - #include "Actor/Player.h" +#include "Inventory/Item.h" + #include "CalcStats.h" #include "Framework.h" @@ -108,10 +110,10 @@ const int levelTable[71][7] = // 3 Versions. SB and HW are linear, ARR is polynomial. // Originally from Player.cpp, calculateStats(). -float CalcStats::calculateBaseStat( PlayerPtr pPlayer ) +float CalcStats::calculateBaseStat( const Chara& chara ) { float base = 0.0f; - uint8_t level = pPlayer->getLevel(); + uint8_t level = chara.getLevel(); if( level > 70 ) level = 70; @@ -138,7 +140,7 @@ uint32_t CalcStats::calculateMaxHp( PlayerPtr pPlayer, Sapphire::FrameworkPtr pF uint8_t level = pPlayer->getLevel(); auto vitMod = pPlayer->getBonusStat( Common::BaseParam::Vitality ); - float baseStat = calculateBaseStat( pPlayer ); + float baseStat = calculateBaseStat( *pPlayer ); uint16_t vitStat = pPlayer->getStats().vit + static_cast< uint16_t >( vitMod ); uint16_t hpMod = paramGrowthInfo->hpModifier; uint16_t jobModHp = classInfo->modifierHitPoints; @@ -173,7 +175,7 @@ uint32_t CalcStats::calculateMaxMp( PlayerPtr pPlayer, Sapphire::FrameworkPtr pF auto pieMod = pPlayer->getBonusStat( Common::BaseParam::Piety ); - float baseStat = calculateBaseStat( pPlayer ); + float baseStat = calculateBaseStat( *pPlayer ); uint16_t piety = pPlayer->getStats().pie + pieMod; uint16_t pietyScalar = paramGrowthInfo->mpModifier; uint16_t jobModMp = classInfo->modifierManaPoints; @@ -308,49 +310,67 @@ float CalcStats::potency( uint16_t potency ) return potency / 100.f; } -//float CalcStats::weaponDamage( const Sapphire::Entity::Chara& chara, float weaponDamage, bool isMagicDamage ) -//{ -// const auto& baseStats = chara.getStats(); -// auto level = chara.getLevel(); -// -// auto mainVal = static_cast< float >( levelTable[ level ][ Common::LevelTableEntry::MAIN ] ); -// -// float jobAttribute = 1.f; -// -// // todo: fix this -// return 1.f -//} +float CalcStats::weaponDamage( const Sapphire::Entity::Chara& chara, float weaponDamage ) +{ + const auto& baseStats = chara.getStats(); + auto level = chara.getLevel(); -// todo: this is all retarded, needs to be per weapon and etcetc -//uint32_t CalcStats::getPrimaryClassJobAttribute( const Sapphire::Entity::Chara& chara ) -//{ -// -//} + auto mainVal = static_cast< float >( levelTable[ level ][ Common::LevelTableEntry::MAIN ] ); + + uint32_t jobAttribute = 1; + + switch( chara.getPrimaryStat() ) + { + case Common::BaseParam::Intelligence: + { + jobAttribute = baseStats.healingPotMagic; + break; + } + case Common::BaseParam::Mind: + { + jobAttribute = baseStats.attackPotMagic; + break; + } + + default: + { + jobAttribute = baseStats.attack; + break; + } + } + + return std::floor( ( ( mainVal * jobAttribute ) / 1000.f ) + weaponDamage ); +} float CalcStats::calcAttackPower( uint32_t attackPower ) { return std::floor( ( 125.f * ( attackPower - 292.f ) / 292.f ) + 100.f ) / 100.f; } -float CalcStats::magicAttackPower( const Sapphire::Entity::Chara& chara ) -{ - const auto& baseStats = chara.getStats(); - - return calcAttackPower( baseStats.attackPotMagic ); -} - -float CalcStats::healingMagicPower( const Sapphire::Entity::Chara& chara ) -{ - const auto& baseStats = chara.getStats(); - - return calcAttackPower( baseStats.healingPotMagic ); -} - float CalcStats::attackPower( const Sapphire::Entity::Chara& chara ) { const auto& baseStats = chara.getStats(); - return calcAttackPower( baseStats.attack ); + // todo: this is wrong + if( chara.isBattleNpc() ) + return calcAttackPower( baseStats.attack ); + + switch( chara.getPrimaryStat() ) + { + case Common::BaseParam::Mind: + { + return calcAttackPower( baseStats.healingPotMagic ); + } + case Common::BaseParam::Intelligence: + { + return calcAttackPower( baseStats.attackPotMagic ); + } + + default: + { + return calcAttackPower( baseStats.attack ); + } + } } float CalcStats::determination( const Sapphire::Entity::Chara& chara ) @@ -386,18 +406,10 @@ float CalcStats::speed( const Sapphire::Entity::Chara& chara ) uint32_t speedVal = 0; // check whether we use spellspeed or skillspeed - // todo: this is kinda shitty though - switch( chara.getClass() ) + switch( chara.getPrimaryStat() ) { - case Common::ClassJob::Arcanist: - case Common::ClassJob::Astrologian: - case Common::ClassJob::Whitemage: - case Common::ClassJob::Redmage: - case Common::ClassJob::Bluemage: - case Common::ClassJob::Blackmage: - case Common::ClassJob::Summoner: - case Common::ClassJob::Scholar: - case Common::ClassJob::Thaumaturge: + case Common::BaseParam::Intelligence: + case Common::BaseParam::Mind: speedVal = baseStats.spellSpeed; break; @@ -439,14 +451,105 @@ float CalcStats::magicDefence( const Sapphire::Entity::Chara& chara ) return std::floor( 15.f * baseStats.magicDefense ) / 100.f; } -//float CalcStats::blockStrength( const Sapphire::Entity::Chara& chara ) -//{ -// -//} +float CalcStats::blockStrength( const Sapphire::Entity::Chara& chara ) +{ + auto level = chara.getLevel(); + auto blockStrength = static_cast< float >( chara.getBonusStat( Common::BaseParam::BlockStrength ) ); + auto levelVal = static_cast< float >( levelTable[ level ][ Common::LevelTableEntry::DIV ] ); + + return std::floor( ( 30 * blockStrength ) / levelVal + 10 ) / 100.f; +} + +float CalcStats::autoAttack( const Sapphire::Entity::Chara& chara ) +{ + // todo: default values for NPCs, not sure what we should have here + float autoAttackDelay = 2.f; + float weaponDamage = 10.f; + + // fetch actual auto attack delay if its a player + if( chara.isPlayer() ) + { + // todo: ew + auto pPlayer = const_cast< Entity::Chara& >( chara ).getAsPlayer(); + assert( pPlayer ); + + auto pItem = pPlayer->getEquippedWeapon(); + assert( pItem ); + + autoAttackDelay = pItem->getDelay() / 1000.f; + weaponDamage = pItem->getWeaponDmg(); + } + + auto level = chara.getLevel(); + auto mainVal = static_cast< float >( levelTable[ level ][ Common::LevelTableEntry::MAIN ] ); + + auto innerCalc = std::floor( ( ( mainVal * primaryStatValue( chara ) ) / 1000.f ) + weaponDamage ); + + return std::floor( innerCalc * ( autoAttackDelay / 3.f ) ); +} float CalcStats::healingMagicPotency( const Sapphire::Entity::Chara& chara ) { const auto& baseStats = chara.getStats(); return std::floor( 100.f * ( baseStats.healingPotMagic - 292.f ) / 264.f + 100.f ) / 100.f; +} + +//////// + +float CalcStats::calculateAutoAttackDamage( const Sapphire::Entity::Chara& chara ) +{ + // D = ⌊ f(ptc) × f(aa) × f(ap) × f(det) × f(tnc) × traits ⌋ × f(ss) ⌋ × + // f(chr) ⌋ × f(dhr) ⌋ × rand[ 0.95, 1.05 ] ⌋ × buff_1 ⌋ × buff... ⌋ + + auto pot = potency( AUTO_ATTACK_POTENCY ); + auto aa = autoAttack( chara ); + //auto ap = attackPower( chara ); + auto ap = 1.f; + auto det = determination( chara ); + auto ten = tenacity( chara ); + + Logger::info( "auto attack: pot: {} aa: {} ap: {} det: {} ten: {}", pot, aa, ap, det, ten ); + + auto factor = std::floor( pot * aa * ap * det * ten ); + + // todo: traits + + factor = std::floor( factor * speed( chara ) ); + + // todo: surely this aint right? + //factor = std::floor( factor * criticalHitProbability( chara ) ); + //factor = std::floor( factor * directHitProbability( chara ) ); + + // todo: random 0.95 - 1.05 factor + + // todo: buffs + + return factor; +} + +uint32_t CalcStats::primaryStatValue( const Sapphire::Entity::Chara& chara ) +{ + const auto& baseStats = chara.getStats(); + + switch( chara.getPrimaryStat() ) + { + default: + return 1; + + case Common::BaseParam::Intelligence: + return baseStats.inte; + + case Common::BaseParam::Mind: + return baseStats.mnd; + + case Common::BaseParam::Strength: + return baseStats.str; + + case Common::BaseParam::Vitality: + return baseStats.vit; + + case Common::BaseParam::Dexterity: + return baseStats.dex; + } } \ No newline at end of file diff --git a/src/world/Math/CalcStats.h b/src/world/Math/CalcStats.h index 6aab838d..11d9fac1 100644 --- a/src/world/Math/CalcStats.h +++ b/src/world/Math/CalcStats.h @@ -10,7 +10,9 @@ namespace Sapphire::Math class CalcStats { public: - static float calculateBaseStat( Sapphire::Entity::PlayerPtr pPlayer ); + static const uint32_t AUTO_ATTACK_POTENCY = 100; + + static float calculateBaseStat( const Entity::Chara& chara ); static uint32_t calculateMaxMp( Sapphire::Entity::PlayerPtr pPlayer, FrameworkPtr pFw ); @@ -52,33 +54,17 @@ namespace Sapphire::Math * * @param chara The source/casting character. * @param weaponDamage the weapons physical or magic damage - * @param isMagicDamage true if the damage is magical, otherwise it's treated as physical damage */ - static float weaponDamage( const Sapphire::Entity::Chara& chara, float weaponDamage, bool isMagicDamage ); + static float weaponDamage( const Sapphire::Entity::Chara& chara, float weaponDamage ); /*! - * @brief Calculates the contribution of physical attack power to damage dealt + * @brief Calculates the contribution of attack power to damage dealt with consideration for the primary stat * @todo Only works at level 70 * * @param chara The source/casting character. */ static float attackPower( const Sapphire::Entity::Chara& chara ); - /*! - * @brief Calculates the contribution of magical attack power to damage dealt - * @todo Only works at level 70 - * - * @param chara The source/casting character. - */ - static float magicAttackPower( const Sapphire::Entity::Chara& chara ); - - /*! - * @brief Calculates the contribution of healing magic power to healing dealt - * - * @param chara The source/casting character. - */ - static float healingMagicPower( const Sapphire::Entity::Chara& chara ); - /*! * @brief Calculates determinations contribution to damage and healing output. * @@ -131,6 +117,8 @@ namespace Sapphire::Math */ static float blockStrength( const Sapphire::Entity::Chara& chara ); + static float autoAttack( const Sapphire::Entity::Chara& chara ); + /*! * @brief Calculates the multiplier that healing magic potency affects healing output * @@ -140,9 +128,11 @@ namespace Sapphire::Math */ static float healingMagicPotency( const Sapphire::Entity::Chara& chara ); - private: + //////////////////////////////////////////// - static uint32_t getPrimaryClassJobAttribute( const Sapphire::Entity::Chara& chara ); + static float calculateAutoAttackDamage( const Sapphire::Entity::Chara& chara ); + + private: /*! * @brief Has the main attack power calculation allowing for de-duplication of functions. @@ -151,6 +141,8 @@ namespace Sapphire::Math */ static float calcAttackPower( uint32_t attackPower ); + static uint32_t primaryStatValue( const Sapphire::Entity::Chara& chara ); + }; } From c851a4a88b84cf10703119753e2e8abb94fb3aa1 Mon Sep 17 00:00:00 2001 From: NotAdam Date: Wed, 24 Apr 2019 23:35:26 +1000 Subject: [PATCH 024/351] slightly better stat calc for bnpcs --- src/world/Math/CalcStats.cpp | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/world/Math/CalcStats.cpp b/src/world/Math/CalcStats.cpp index 99c536c8..eda56f55 100644 --- a/src/world/Math/CalcStats.cpp +++ b/src/world/Math/CalcStats.cpp @@ -495,8 +495,6 @@ float CalcStats::healingMagicPotency( const Sapphire::Entity::Chara& chara ) return std::floor( 100.f * ( baseStats.healingPotMagic - 292.f ) / 264.f + 100.f ) / 100.f; } -//////// - float CalcStats::calculateAutoAttackDamage( const Sapphire::Entity::Chara& chara ) { // D = ⌊ f(ptc) × f(aa) × f(ap) × f(det) × f(tnc) × traits ⌋ × f(ss) ⌋ × @@ -534,8 +532,9 @@ uint32_t CalcStats::primaryStatValue( const Sapphire::Entity::Chara& chara ) switch( chara.getPrimaryStat() ) { + case Common::BaseParam::Strength: default: - return 1; + return baseStats.str; case Common::BaseParam::Intelligence: return baseStats.inte; @@ -543,9 +542,6 @@ uint32_t CalcStats::primaryStatValue( const Sapphire::Entity::Chara& chara ) case Common::BaseParam::Mind: return baseStats.mnd; - case Common::BaseParam::Strength: - return baseStats.str; - case Common::BaseParam::Vitality: return baseStats.vit; From fc9f1e6673dc6fb3a8246b4b889a28719d775f6d Mon Sep 17 00:00:00 2001 From: NotAdam Date: Wed, 24 Apr 2019 23:47:35 +1000 Subject: [PATCH 025/351] fix attack power calculation not using level value --- src/world/Math/CalcStats.cpp | 19 +++++++++++-------- src/world/Math/CalcStats.h | 2 +- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/src/world/Math/CalcStats.cpp b/src/world/Math/CalcStats.cpp index eda56f55..1134ffa0 100644 --- a/src/world/Math/CalcStats.cpp +++ b/src/world/Math/CalcStats.cpp @@ -342,9 +342,13 @@ float CalcStats::weaponDamage( const Sapphire::Entity::Chara& chara, float weapo return std::floor( ( ( mainVal * jobAttribute ) / 1000.f ) + weaponDamage ); } -float CalcStats::calcAttackPower( uint32_t attackPower ) +float CalcStats::calcAttackPower( const Sapphire::Entity::Chara& chara, uint32_t attackPower ) { - return std::floor( ( 125.f * ( attackPower - 292.f ) / 292.f ) + 100.f ) / 100.f; + auto level = chara.getLevel(); + auto mainVal = static_cast< float >( levelTable[ level ][ Common::LevelTableEntry::MAIN ] ); + auto divVal = static_cast< float >( levelTable[ level ][ Common::LevelTableEntry::DIV ] ); + + return std::floor( ( 125.f * ( attackPower - mainVal ) / divVal ) + 100.f ) / 100.f; } float CalcStats::attackPower( const Sapphire::Entity::Chara& chara ) @@ -353,22 +357,22 @@ float CalcStats::attackPower( const Sapphire::Entity::Chara& chara ) // todo: this is wrong if( chara.isBattleNpc() ) - return calcAttackPower( baseStats.attack ); + return calcAttackPower( chara, baseStats.attack ); switch( chara.getPrimaryStat() ) { case Common::BaseParam::Mind: { - return calcAttackPower( baseStats.healingPotMagic ); + return calcAttackPower( chara, baseStats.healingPotMagic ); } case Common::BaseParam::Intelligence: { - return calcAttackPower( baseStats.attackPotMagic ); + return calcAttackPower( chara, baseStats.attackPotMagic ); } default: { - return calcAttackPower( baseStats.attack ); + return calcAttackPower( chara, baseStats.attack ); } } } @@ -502,8 +506,7 @@ float CalcStats::calculateAutoAttackDamage( const Sapphire::Entity::Chara& chara auto pot = potency( AUTO_ATTACK_POTENCY ); auto aa = autoAttack( chara ); - //auto ap = attackPower( chara ); - auto ap = 1.f; + auto ap = attackPower( chara ); auto det = determination( chara ); auto ten = tenacity( chara ); diff --git a/src/world/Math/CalcStats.h b/src/world/Math/CalcStats.h index 11d9fac1..70859de6 100644 --- a/src/world/Math/CalcStats.h +++ b/src/world/Math/CalcStats.h @@ -139,7 +139,7 @@ namespace Sapphire::Math * * @param attackPower The magic/physical attack power value. */ - static float calcAttackPower( uint32_t attackPower ); + static float calcAttackPower( const Sapphire::Entity::Chara& chara, uint32_t attackPower ); static uint32_t primaryStatValue( const Sapphire::Entity::Chara& chara ); From 9a26a24d31d9c8096e7433904edf175c2463e007 Mon Sep 17 00:00:00 2001 From: NotAdam Date: Thu, 25 Apr 2019 18:26:35 +1000 Subject: [PATCH 026/351] ignore soulstones in ilvl calculation --- src/world/Actor/PlayerInventory.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/world/Actor/PlayerInventory.cpp b/src/world/Actor/PlayerInventory.cpp index 3d25ad4f..77677c64 100644 --- a/src/world/Actor/PlayerInventory.cpp +++ b/src/world/Actor/PlayerInventory.cpp @@ -843,7 +843,7 @@ uint16_t Sapphire::Entity::Player::calculateEquippedGearItemLevel() { auto currItem = it->second; - if( currItem ) + if( currItem && currItem->getCategory() != Common::ItemUICategory::SoulCrystal ) { iLvlResult += currItem->getItemLevel(); From 0005b672a7d662df87d9a967675b0388eaa0209b Mon Sep 17 00:00:00 2001 From: NotAdam Date: Thu, 25 Apr 2019 21:57:41 +1000 Subject: [PATCH 027/351] cleanup stat calculation code, slightly better working aa dmg calc --- src/world/Actor/Chara.cpp | 130 ++++++++++++++++++++++++++++++++++- src/world/Actor/Chara.h | 2 + src/world/Actor/Player.cpp | 38 +++++----- src/world/Math/CalcStats.cpp | 85 +++++++++-------------- src/world/Math/CalcStats.h | 8 ++- 5 files changed, 191 insertions(+), 72 deletions(-) diff --git a/src/world/Actor/Chara.cpp b/src/world/Actor/Chara.cpp index 968698b0..779c3afd 100644 --- a/src/world/Actor/Chara.cpp +++ b/src/world/Actor/Chara.cpp @@ -21,7 +21,7 @@ #include "Action/Action.h" #include "ServerMgr.h" #include "Session.h" -#include "Math/CalcBattle.h" +#include "Math/CalcStats.h" #include "Chara.h" #include "Player.h" #include "Manager/TerritoryMgr.h" @@ -729,4 +729,132 @@ Sapphire::Common::BaseParam Sapphire::Entity::Chara::getPrimaryStat() const assert( classJob ); return static_cast< Sapphire::Common::BaseParam >( classJob->primaryStat ); +} + +uint32_t Sapphire::Entity::Chara::getStatValue( Sapphire::Common::BaseParam baseParam ) const +{ + uint32_t value = 0; + + switch( baseParam ) + { + case Common::BaseParam::Strength: + { + value = m_baseStats.str; + break; + } + + case Common::BaseParam::Dexterity: + { + value = m_baseStats.dex; + break; + } + + case Common::BaseParam::Vitality: + { + value = m_baseStats.vit; + break; + } + + case Common::BaseParam::Intelligence: + { + value = m_baseStats.inte; + break; + } + + case Common::BaseParam::Mind: + { + value = m_baseStats.mnd; + break; + } + + case Common::BaseParam::Piety: + { + value = m_baseStats.pie; + break; + } + + case Common::BaseParam::Determination: + { + value = m_baseStats.determination; + break; + } + + case Common::BaseParam::HP: + { + value = m_baseStats.max_hp; + break; + } + + case Common::BaseParam::MP: + { + value = m_baseStats.max_mp; + break; + } + + case Common::BaseParam::AttackPower: + { + value = m_baseStats.attack; + break; + } + + case Common::BaseParam::AttackMagicPotency: + { + value = m_baseStats.attackPotMagic; + break; + } + + case Common::BaseParam::HealingMagicPotency: + { + value = m_baseStats.healingPotMagic; + break; + } + + case Common::BaseParam::SkillSpeed: + { + value = m_baseStats.skillSpeed; + break; + } + + case Common::BaseParam::SpellSpeed: + { + value = m_baseStats.spellSpeed; + break; + } + + case Common::BaseParam::CriticalHit: + { + value = m_baseStats.critHitRate; + break; + } + + case Common::BaseParam::Defense: + { + value = m_baseStats.defense; + break; + } + + case Common::BaseParam::MagicDefense: + { + value = m_baseStats.magicDefense; + break; + } + + case Common::BaseParam::Tenacity: + { + value = m_baseStats.tenacity; + break; + } + + // todo: not sure if this is right? + case Common::BaseParam::DirectHitRate: + { + value = m_baseStats.accuracy; + break; + } + + default: + break; + } + + return value + getBonusStat( baseParam ); } \ No newline at end of file diff --git a/src/world/Actor/Chara.h b/src/world/Actor/Chara.h index 4e2d8e9b..5679b2cb 100644 --- a/src/world/Actor/Chara.h +++ b/src/world/Actor/Chara.h @@ -191,6 +191,8 @@ namespace Sapphire::Entity ActorStats getStats() const; + uint32_t getStatValue( Common::BaseParam baseParam ) const; + uint32_t getHp() const; uint32_t getHpPercent() const; diff --git a/src/world/Actor/Player.cpp b/src/world/Actor/Player.cpp index 1547a860..32852714 100644 --- a/src/world/Actor/Player.cpp +++ b/src/world/Actor/Player.cpp @@ -313,28 +313,28 @@ void Sapphire::Entity::Player::sendStats() { auto statPacket = makeZonePacket< FFXIVIpcPlayerStats >( getId() ); - statPacket->data().strength = m_baseStats.str + m_bonusStats[ static_cast< uint8_t >( Common::BaseParam::Strength ) ]; - statPacket->data().dexterity = m_baseStats.dex + m_bonusStats[ static_cast< uint8_t >( Common::BaseParam::Dexterity ) ]; - statPacket->data().vitality = m_baseStats.vit + m_bonusStats[ static_cast< uint8_t >( Common::BaseParam::Vitality ) ]; - statPacket->data().intelligence = m_baseStats.inte + m_bonusStats[ static_cast< uint8_t >( Common::BaseParam::Intelligence ) ]; - statPacket->data().mind = m_baseStats.mnd + m_bonusStats[ static_cast< uint8_t >( Common::BaseParam::Mind ) ]; - statPacket->data().piety = m_baseStats.pie + m_bonusStats[ static_cast< uint8_t >( Common::BaseParam::Piety ) ]; - statPacket->data().determination = m_baseStats.determination + m_bonusStats[ static_cast< uint8_t >( Common::BaseParam::Determination ) ]; - statPacket->data().hp = m_baseStats.max_hp + m_bonusStats[ static_cast< uint8_t >( Common::BaseParam::HP ) ]; - statPacket->data().mp = m_baseStats.max_mp + m_bonusStats[ static_cast< uint8_t >( Common::BaseParam::MP ) ]; + statPacket->data().strength = getStatValue( Common::BaseParam::Strength ); + statPacket->data().dexterity = getStatValue( Common::BaseParam::Dexterity ); + statPacket->data().vitality = getStatValue( Common::BaseParam::Vitality ); + statPacket->data().intelligence = getStatValue( Common::BaseParam::Intelligence ); + statPacket->data().mind = getStatValue( Common::BaseParam::Mind ); + statPacket->data().piety = getStatValue( Common::BaseParam::Piety ); + statPacket->data().determination = getStatValue( Common::BaseParam::Determination ); + statPacket->data().hp = getStatValue( Common::BaseParam::HP ); + statPacket->data().mp = getStatValue( Common::BaseParam::MP ); statPacket->data().accuracy = m_baseStats.accuracy; - statPacket->data().attack = m_baseStats.attack + m_bonusStats[ static_cast< uint8_t >( Common::BaseParam::AttackPower ) ]; - statPacket->data().attackMagicPotency = m_baseStats.attackPotMagic + m_bonusStats[ static_cast< uint8_t >( Common::BaseParam::AttackMagicPotency ) ]; - statPacket->data().healingMagicPotency = m_baseStats.healingPotMagic + m_bonusStats[ static_cast< uint8_t >( Common::BaseParam::HealingMagicPotency ) ]; - statPacket->data().skillSpeed = m_baseStats.skillSpeed + m_bonusStats[ static_cast< uint8_t >( Common::BaseParam::SkillSpeed ) ]; - statPacket->data().spellSpeed = m_baseStats.spellSpeed + m_bonusStats[ static_cast< uint8_t >( Common::BaseParam::SpellSpeed ) ]; - statPacket->data().spellSpeed1 = m_baseStats.spellSpeed + m_bonusStats[ static_cast< uint8_t >( Common::BaseParam::SpellSpeed ) ]; + statPacket->data().attack = getStatValue( Common::BaseParam::AttackPower ); + statPacket->data().attackMagicPotency = getStatValue( Common::BaseParam::AttackMagicPotency ); + statPacket->data().healingMagicPotency = getStatValue( Common::BaseParam::HealingMagicPotency ); + statPacket->data().skillSpeed = getStatValue( Common::BaseParam::SkillSpeed ); + statPacket->data().spellSpeed = getStatValue( Common::BaseParam::SpellSpeed ); + statPacket->data().spellSpeed1 = getStatValue( Common::BaseParam::SpellSpeed ); statPacket->data().spellSpeedMod = 100; - statPacket->data().criticalHitRate = m_baseStats.critHitRate + m_bonusStats[ static_cast< uint8_t >( Common::BaseParam::CriticalHit ) ]; - statPacket->data().defense = m_baseStats.defense + m_bonusStats[ static_cast< uint8_t >( Common::BaseParam::Defense ) ]; - statPacket->data().magicDefense = m_baseStats.magicDefense + m_bonusStats[ static_cast< uint8_t >( Common::BaseParam::MagicDefense ) ]; - statPacket->data().tenacity = m_baseStats.tenacity + m_bonusStats[ static_cast< uint8_t >( Common::BaseParam::Tenacity ) ]; + statPacket->data().criticalHitRate = getStatValue( Common::BaseParam::CriticalHit ); + statPacket->data().defense = getStatValue( Common::BaseParam::Defense ); + statPacket->data().magicDefense = getStatValue( Common::BaseParam::MagicDefense ); + statPacket->data().tenacity = getStatValue( Common::BaseParam::Tenacity ); queuePacket( statPacket ); } diff --git a/src/world/Math/CalcStats.cpp b/src/world/Math/CalcStats.cpp index 1134ffa0..1542e2fd 100644 --- a/src/world/Math/CalcStats.cpp +++ b/src/world/Math/CalcStats.cpp @@ -270,7 +270,7 @@ uint16_t CalcStats::calculateMpCost( const Sapphire::Entity::Chara& chara, uint1 float CalcStats::blockProbability( const Chara& chara ) { auto level = chara.getLevel(); - auto blockRate = static_cast< float >( chara.getBonusStat( Common::BaseParam::BlockRate ) ); + auto blockRate = static_cast< float >( chara.getStatValue( Common::BaseParam::BlockRate ) ); auto levelVal = static_cast< float >( levelTable[ level ][ Common::LevelTableEntry::DIV ] ); return std::floor( ( 30 * blockRate ) / levelVal + 10 ); @@ -281,8 +281,7 @@ float CalcStats::directHitProbability( const Chara& chara ) const auto& baseStats = chara.getStats(); auto level = chara.getLevel(); - float dhRate = static_cast< float >( chara.getBonusStat( Common::BaseParam::DirectHitRate ) ) + - baseStats.accuracy; + float dhRate = chara.getStatValue( Common::BaseParam::DirectHitRate ); auto divVal = static_cast< float >( levelTable[ level ][ Common::LevelTableEntry::DIV ] ); auto subVal = static_cast< float >( levelTable[ level ][ Common::LevelTableEntry::SUB ] ); @@ -295,8 +294,7 @@ float CalcStats::criticalHitProbability( const Chara& chara ) const auto& baseStats = chara.getStats(); auto level = chara.getLevel(); - float chRate = static_cast< float >( chara.getBonusStat( Common::BaseParam::CriticalHit ) ) + - baseStats.critHitRate; + float chRate = chara.getStatValue( Common::BaseParam::CriticalHit ); auto divVal = static_cast< float >( levelTable[ level ][ Common::LevelTableEntry::DIV ] ); auto subVal = static_cast< float >( levelTable[ level ][ Common::LevelTableEntry::SUB ] ); @@ -348,61 +346,70 @@ float CalcStats::calcAttackPower( const Sapphire::Entity::Chara& chara, uint32_t auto mainVal = static_cast< float >( levelTable[ level ][ Common::LevelTableEntry::MAIN ] ); auto divVal = static_cast< float >( levelTable[ level ][ Common::LevelTableEntry::DIV ] ); + // todo: not sure if its ( ap - mv ) / mv or ( ap - mv ) / dv return std::floor( ( 125.f * ( attackPower - mainVal ) / divVal ) + 100.f ) / 100.f; } -float CalcStats::attackPower( const Sapphire::Entity::Chara& chara ) +float CalcStats::getPrimaryAttackPower( const Sapphire::Entity::Chara& chara ) { const auto& baseStats = chara.getStats(); - // todo: this is wrong - if( chara.isBattleNpc() ) - return calcAttackPower( chara, baseStats.attack ); - switch( chara.getPrimaryStat() ) { case Common::BaseParam::Mind: { - return calcAttackPower( chara, baseStats.healingPotMagic ); + return healingMagicPower( chara ); } case Common::BaseParam::Intelligence: { - return calcAttackPower( chara, baseStats.attackPotMagic ); + return magicAttackPower( chara ); } default: { - return calcAttackPower( chara, baseStats.attack ); + return attackPower( chara ); } } } +float CalcStats::attackPower( const Sapphire::Entity::Chara& chara ) +{ + return calcAttackPower( chara, chara.getStatValue( Common::BaseParam::AttackPower ) ); +} + +float CalcStats::magicAttackPower( const Sapphire::Entity::Chara& chara ) +{ + return calcAttackPower( chara, chara.getStatValue( Common::BaseParam::AttackMagicPotency ) ); +} + +float CalcStats::healingMagicPower( const Sapphire::Entity::Chara& chara ) +{ + return calcAttackPower( chara, chara.getStatValue( Common::BaseParam::HealingMagicPotency ) ); +} + float CalcStats::determination( const Sapphire::Entity::Chara& chara ) { auto level = chara.getLevel(); - const auto& baseStats = chara.getStats(); auto mainVal = static_cast< float >( levelTable[ level ][ Common::LevelTableEntry::MAIN ] ); auto divVal = static_cast< float >( levelTable[ level ][ Common::LevelTableEntry::DIV ] ); - return std::floor( 130.f * ( baseStats.determination - mainVal ) / divVal + 1000.f ) / 1000.f; + return std::floor( 130.f * ( chara.getStatValue( Common::BaseParam::Determination ) - mainVal ) / divVal + 1000.f ) / 1000.f; } float CalcStats::tenacity( const Sapphire::Entity::Chara& chara ) { auto level = chara.getLevel(); - const auto& baseStats = chara.getStats(); auto subVal = static_cast< float >( levelTable[ level ][ Common::LevelTableEntry::SUB ] ); auto divVal = static_cast< float >( levelTable[ level ][ Common::LevelTableEntry::DIV ] ); - return std::floor( 100.f * ( baseStats.tenacity - subVal ) / divVal + 1000.f ) / 1000.f; + return std::floor( 100.f * ( chara.getStatValue( Common::BaseParam::Tenacity ) - subVal ) / divVal + 1000.f ) / 1000.f; } float CalcStats::speed( const Sapphire::Entity::Chara& chara ) { auto level = chara.getLevel(); - const auto& baseStats = chara.getStats(); auto subVal = static_cast< float >( levelTable[ level ][ Common::LevelTableEntry::SUB ] ); auto divVal = static_cast< float >( levelTable[ level ][ Common::LevelTableEntry::DIV ] ); @@ -414,11 +421,11 @@ float CalcStats::speed( const Sapphire::Entity::Chara& chara ) { case Common::BaseParam::Intelligence: case Common::BaseParam::Mind: - speedVal = baseStats.spellSpeed; + speedVal = chara.getStatValue( Common::BaseParam::SpellSpeed ); break; default: - speedVal = baseStats.skillSpeed; + speedVal = chara.getStatValue( Common::BaseParam::SkillSpeed ); } return std::floor( 130.f * ( speedVal - subVal ) / divVal + 1000.f ) / 1000.f; @@ -427,32 +434,29 @@ float CalcStats::speed( const Sapphire::Entity::Chara& chara ) float CalcStats::criticalHitBonus( const Sapphire::Entity::Chara& chara ) { auto level = chara.getLevel(); - const auto& baseStats = chara.getStats(); auto subVal = static_cast< float >( levelTable[ level ][ Common::LevelTableEntry::SUB ] ); auto divVal = static_cast< float >( levelTable[ level ][ Common::LevelTableEntry::DIV ] ); - return std::floor( 200.f * ( baseStats.critHitRate - subVal ) / divVal + 1400.f ) / 1000.f; + return std::floor( 200.f * ( chara.getStatValue( Common::BaseParam::CriticalHit ) - subVal ) / divVal + 1400.f ) / 1000.f; } float CalcStats::physicalDefence( const Sapphire::Entity::Chara& chara ) { auto level = chara.getLevel(); - const auto& baseStats = chara.getStats(); auto divVal = static_cast< float >( levelTable[ level ][ Common::LevelTableEntry::DIV ] ); - return std::floor( 15.f * baseStats.defense ) / 100.f; + return std::floor( 15.f * chara.getStatValue( Common::BaseParam::Defense ) ) / 100.f; } float CalcStats::magicDefence( const Sapphire::Entity::Chara& chara ) { auto level = chara.getLevel(); - const auto& baseStats = chara.getStats(); auto divVal = static_cast< float >( levelTable[ level ][ Common::LevelTableEntry::DIV ] ); - return std::floor( 15.f * baseStats.magicDefense ) / 100.f; + return std::floor( 15.f * chara.getStatValue( Common::BaseParam::MagicDefense ) ) / 100.f; } float CalcStats::blockStrength( const Sapphire::Entity::Chara& chara ) @@ -494,9 +498,7 @@ float CalcStats::autoAttack( const Sapphire::Entity::Chara& chara ) float CalcStats::healingMagicPotency( const Sapphire::Entity::Chara& chara ) { - const auto& baseStats = chara.getStats(); - - return std::floor( 100.f * ( baseStats.healingPotMagic - 292.f ) / 264.f + 100.f ) / 100.f; + return std::floor( 100.f * ( chara.getStatValue( Common::BaseParam::HealingMagicPotency ) - 292.f ) / 264.f + 100.f ) / 100.f; } float CalcStats::calculateAutoAttackDamage( const Sapphire::Entity::Chara& chara ) @@ -506,11 +508,11 @@ float CalcStats::calculateAutoAttackDamage( const Sapphire::Entity::Chara& chara auto pot = potency( AUTO_ATTACK_POTENCY ); auto aa = autoAttack( chara ); - auto ap = attackPower( chara ); + auto ap = getPrimaryAttackPower( chara ); auto det = determination( chara ); auto ten = tenacity( chara ); - Logger::info( "auto attack: pot: {} aa: {} ap: {} det: {} ten: {}", pot, aa, ap, det, ten ); + Logger::debug( "auto attack: pot: {} aa: {} ap: {} det: {} ten: {}", pot, aa, ap, det, ten ); auto factor = std::floor( pot * aa * ap * det * ten ); @@ -531,24 +533,5 @@ float CalcStats::calculateAutoAttackDamage( const Sapphire::Entity::Chara& chara uint32_t CalcStats::primaryStatValue( const Sapphire::Entity::Chara& chara ) { - const auto& baseStats = chara.getStats(); - - switch( chara.getPrimaryStat() ) - { - case Common::BaseParam::Strength: - default: - return baseStats.str; - - case Common::BaseParam::Intelligence: - return baseStats.inte; - - case Common::BaseParam::Mind: - return baseStats.mnd; - - case Common::BaseParam::Vitality: - return baseStats.vit; - - case Common::BaseParam::Dexterity: - return baseStats.dex; - } + return chara.getStatValue( chara.getPrimaryStat() ); } \ No newline at end of file diff --git a/src/world/Math/CalcStats.h b/src/world/Math/CalcStats.h index 70859de6..5f2b4060 100644 --- a/src/world/Math/CalcStats.h +++ b/src/world/Math/CalcStats.h @@ -63,8 +63,14 @@ namespace Sapphire::Math * * @param chara The source/casting character. */ + static float getPrimaryAttackPower( const Sapphire::Entity::Chara& chara ); + static float attackPower( const Sapphire::Entity::Chara& chara ); + static float magicAttackPower( const Sapphire::Entity::Chara& chara ); + + static float healingMagicPower( const Sapphire::Entity::Chara& chara ); + /*! * @brief Calculates determinations contribution to damage and healing output. * @@ -132,6 +138,7 @@ namespace Sapphire::Math static float calculateAutoAttackDamage( const Sapphire::Entity::Chara& chara ); + static uint32_t primaryStatValue( const Sapphire::Entity::Chara& chara ); private: /*! @@ -141,7 +148,6 @@ namespace Sapphire::Math */ static float calcAttackPower( const Sapphire::Entity::Chara& chara, uint32_t attackPower ); - static uint32_t primaryStatValue( const Sapphire::Entity::Chara& chara ); }; From a0d596f40fa1b1c739624c0f361b290ab4e0f4b5 Mon Sep 17 00:00:00 2001 From: NotAdam Date: Thu, 25 Apr 2019 22:45:23 +1000 Subject: [PATCH 028/351] fix autoattack range --- src/world/Actor/Chara.cpp | 4 ++-- src/world/Actor/Player.cpp | 5 +++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/world/Actor/Chara.cpp b/src/world/Actor/Chara.cpp index 779c3afd..bb328c33 100644 --- a/src/world/Actor/Chara.cpp +++ b/src/world/Actor/Chara.cpp @@ -793,8 +793,8 @@ uint32_t Sapphire::Entity::Chara::getStatValue( Sapphire::Common::BaseParam base case Common::BaseParam::AttackPower: { - value = m_baseStats.attack; - break; + // todo: think this is right... not sure + return getStatValue( Common::BaseParam::Strength ); } case Common::BaseParam::AttackMagicPotency: diff --git a/src/world/Actor/Player.cpp b/src/world/Actor/Player.cpp index 32852714..bae8edb5 100644 --- a/src/world/Actor/Player.cpp +++ b/src/world/Actor/Player.cpp @@ -1105,9 +1105,10 @@ void Sapphire::Entity::Player::update( uint64_t tickCount ) { if( actor->getId() == m_targetId && actor->getAsChara()->isAlive() && mainWeap ) { + auto chara = actor->getAsChara(); + // default autoattack range - // TODO make this dependant on bnpc size - uint32_t range = 7; + float range = 3.f + chara->getRadius(); // default autoattack range for ranged classes if( getClass() == ClassJob::Machinist || From 8c3c6e7998053064c2eb196e812def57cf6accf7 Mon Sep 17 00:00:00 2001 From: Biscuit Date: Fri, 26 Apr 2019 17:47:59 +1000 Subject: [PATCH 029/351] Document world visit packet --- src/common/Network/PacketDef/Ipcs.h | 3 +++ src/common/Network/PacketDef/Zone/ServerZoneDef.h | 13 +++++++++++++ 2 files changed, 16 insertions(+) diff --git a/src/common/Network/PacketDef/Ipcs.h b/src/common/Network/PacketDef/Ipcs.h index daed4d35..3c98ae7f 100644 --- a/src/common/Network/PacketDef/Ipcs.h +++ b/src/common/Network/PacketDef/Ipcs.h @@ -74,6 +74,9 @@ namespace Sapphire::Network::Packets CancelAllianceForming = 0x00C6, // updated 4.2 Chat = 0x00F7, // updated 4.5? + + WorldVisitList = 0x00FE, // added 4.5 + SocialList = 0x0103, // updated 4.5 UpdateSearchInfo = 0x0106, // updated 4.5 diff --git a/src/common/Network/PacketDef/Zone/ServerZoneDef.h b/src/common/Network/PacketDef/Zone/ServerZoneDef.h index 650979e4..924b0912 100644 --- a/src/common/Network/PacketDef/Zone/ServerZoneDef.h +++ b/src/common/Network/PacketDef/Zone/ServerZoneDef.h @@ -52,6 +52,19 @@ namespace Sapphire::Network::Packets::Server // client doesn't care about the data (zero sized) for this opcode anyway. }; + /** + * Structural representation of the packet sent by the server + * to show a list of worlds for world visit + */ + struct FFXIVIpcWorldVisitList : FFXIVIpcBasePacket< WorldVisitList > + { + struct worldEntry + { + uint16_t id; // this is the id of the world from lobby + uint16_t status; // 1 = available (this is what retail sends) | 2+ = unavailable (this will need to be checked with retail if it's exactly 2 or not since it does not actually lock the option) + } world[16]; + }; + /** * Structural representation of the packet sent by the server * carrying chat messages From fc2c3248de979beae7b00f6dd7693c119fca552d Mon Sep 17 00:00:00 2001 From: Mordred Date: Sun, 28 Apr 2019 23:34:43 +0200 Subject: [PATCH 030/351] Some naming changes for actions --- src/common/Common.h | 1 + src/world/Action/Action.cpp | 4 ++-- src/world/Manager/ActionMgr.cpp | 4 ++-- src/world/Manager/ActionMgr.h | 4 ++-- src/world/Network/GameConnection.cpp | 2 +- src/world/Network/GameConnection.h | 4 ++-- src/world/Network/Handlers/ActionHandler.cpp | 14 +++++++------- 7 files changed, 17 insertions(+), 16 deletions(-) diff --git a/src/common/Common.h b/src/common/Common.h index a2d59028..5965228f 100644 --- a/src/common/Common.h +++ b/src/common/Common.h @@ -983,6 +983,7 @@ namespace Sapphire::Common SingleTarget = 1, CircularAOE = 2, RectangularAOE = 4, + CircularAoEPlaced = 7 }; using PlayerStateFlagList = std::vector< PlayerStateFlag >; diff --git a/src/world/Action/Action.cpp b/src/world/Action/Action.cpp index d00e4cc4..c7c7790f 100644 --- a/src/world/Action/Action.cpp +++ b/src/world/Action/Action.cpp @@ -100,7 +100,7 @@ bool Sapphire::Action::Action::init() m_primaryCostType = static_cast< Common::ActionPrimaryCostType >( m_actionData->costType ); m_primaryCost = m_actionData->cost; - if( !m_actionData->targetArea ) + /*if( !m_actionData->targetArea ) { // override pos to target position // todo: this is kinda dirty @@ -112,7 +112,7 @@ bool Sapphire::Action::Action::init() break; } } - } + }*/ // todo: add missing rows for secondaryCostType/secondaryCostType and rename the current rows to primaryCostX diff --git a/src/world/Manager/ActionMgr.cpp b/src/world/Manager/ActionMgr.cpp index aa02bb4d..1f03d840 100644 --- a/src/world/Manager/ActionMgr.cpp +++ b/src/world/Manager/ActionMgr.cpp @@ -17,8 +17,8 @@ World::Manager::ActionMgr::ActionMgr( Sapphire::FrameworkPtr pFw ) : } -void World::Manager::ActionMgr::handleAoEPlayerAction( Entity::Player& player, uint32_t actionId, - Data::ActionPtr actionData, Common::FFXIVARR_POSITION3 pos ) +void World::Manager::ActionMgr::handlePlacedPlayerAction( Entity::Player& player, uint32_t actionId, + Data::ActionPtr actionData, Common::FFXIVARR_POSITION3 pos ) { player.sendDebug( "got aoe act: {0}", actionData->name ); diff --git a/src/world/Manager/ActionMgr.h b/src/world/Manager/ActionMgr.h index 67d2ea5f..e3ab37d3 100644 --- a/src/world/Manager/ActionMgr.h +++ b/src/world/Manager/ActionMgr.h @@ -23,8 +23,8 @@ namespace Sapphire::World::Manager void handleTargetedPlayerAction( Entity::Player& player, uint32_t actionId, Data::ActionPtr actionData, uint64_t targetId ); - void handleAoEPlayerAction( Entity::Player& player, uint32_t actionId, - Data::ActionPtr actionData, Common::FFXIVARR_POSITION3 pos ); + void handlePlacedPlayerAction( Entity::Player& player, uint32_t actionId, + Data::ActionPtr actionData, Common::FFXIVARR_POSITION3 pos ); void handleItemAction( Entity::Player& player, uint32_t itemId, Data::ItemActionPtr itemActionData, uint16_t itemSourceSlot, uint16_t itemSourceContainer ); diff --git a/src/world/Network/GameConnection.cpp b/src/world/Network/GameConnection.cpp index 1f16ae03..799835bb 100644 --- a/src/world/Network/GameConnection.cpp +++ b/src/world/Network/GameConnection.cpp @@ -73,7 +73,7 @@ Sapphire::Network::GameConnection::GameConnection( Sapphire::Network::HivePtr pH setZoneHandler( ClientZoneIpcType::DiscoveryHandler, "DiscoveryHandler", &GameConnection::discoveryHandler ); setZoneHandler( ClientZoneIpcType::SkillHandler, "ActionHandler", &GameConnection::actionHandler ); - setZoneHandler( ClientZoneIpcType::AoESkillHandler, "AoESkillHandler", &GameConnection::aoeActionHandler ); + setZoneHandler( ClientZoneIpcType::AoESkillHandler, "AoESkillHandler", &GameConnection::placedActionHandler ); setZoneHandler( ClientZoneIpcType::GMCommand1, "GMCommand1", &GameConnection::gm1Handler ); setZoneHandler( ClientZoneIpcType::GMCommand2, "GMCommand2", &GameConnection::gm2Handler ); diff --git a/src/world/Network/GameConnection.h b/src/world/Network/GameConnection.h index a83735e5..61be56c5 100644 --- a/src/world/Network/GameConnection.h +++ b/src/world/Network/GameConnection.h @@ -157,8 +157,8 @@ namespace Sapphire::Network DECLARE_HANDLER( cfDutyAccepted ); DECLARE_HANDLER( actionHandler ); - - DECLARE_HANDLER( aoeActionHandler ); + + DECLARE_HANDLER( placedActionHandler ); DECLARE_HANDLER( gm1Handler ); diff --git a/src/world/Network/Handlers/ActionHandler.cpp b/src/world/Network/Handlers/ActionHandler.cpp index 367f46e9..460c294a 100644 --- a/src/world/Network/Handlers/ActionHandler.cpp +++ b/src/world/Network/Handlers/ActionHandler.cpp @@ -27,7 +27,7 @@ void Sapphire::Network::GameConnection::actionHandler( FrameworkPtr pFw, const auto itemSourceSlot = packet.data().itemSourceSlot; const auto itemSourceContainer = packet.data().itemSourceContainer; -// player.sendDebug( "Skill type: {0}, sequence: {1}, actionId: {2}, targetId: {3}", type, sequence, actionId, targetId ); + player.sendDebug( "Skill type: {0}, sequence: {1}, actionId: {2}, targetId: {3}", type, sequence, actionId, targetId ); auto exdData = m_pFw->get< Data::ExdDataGenerated >(); assert( exdData ); @@ -81,9 +81,9 @@ void Sapphire::Network::GameConnection::actionHandler( FrameworkPtr pFw, } -void Sapphire::Network::GameConnection::aoeActionHandler( FrameworkPtr pFw, - const Packets::FFXIVARR_PACKET_RAW& inPacket, - Entity::Player& player ) +void Sapphire::Network::GameConnection::placedActionHandler( FrameworkPtr pFw, + const Packets::FFXIVARR_PACKET_RAW& inPacket, + Entity::Player& player ) { const auto packet = ZoneChannelPacket< Client::FFXIVIpcAoESkillHandler >( inPacket ); @@ -99,8 +99,8 @@ void Sapphire::Network::GameConnection::aoeActionHandler( FrameworkPtr pFw, return; } -// player.sendDebug( "Skill type: {0}, sequence: {1}, actionId: {2}, x:{3}, y:{4}, z:{5}", -// type, sequence, actionId, pos.x, pos.y, pos.z ); + player.sendDebug( "Skill type: {0}, sequence: {1}, actionId: {2}, x:{3}, y:{4}, z:{5}", + type, sequence, actionId, pos.x, pos.y, pos.z ); auto exdData = m_pFw->get< Data::ExdDataGenerated >(); assert( exdData ); @@ -112,5 +112,5 @@ void Sapphire::Network::GameConnection::aoeActionHandler( FrameworkPtr pFw, return; auto actionMgr = pFw->get< World::Manager::ActionMgr >(); - actionMgr->handleAoEPlayerAction( player, actionId, action, pos ); + actionMgr->handlePlacedPlayerAction( player, actionId, action, pos ); } From 3e4483053e04f8f482277bc47c3715eb92c2cb53 Mon Sep 17 00:00:00 2001 From: NotAdam Date: Mon, 29 Apr 2019 19:36:57 +1000 Subject: [PATCH 031/351] fix stacktrace on windows --- CMakeLists.txt | 1 - deps/stackwalker/CMakeLists.txt | 11 - deps/stackwalker/StackWalker.cpp | 1469 ---------------------------- deps/stackwalker/StackWalker.h | 255 ----- src/common/Util/CrashHandler.cpp | 98 +- src/tools/exd_struct_test/main.cpp | 2 + 6 files changed, 88 insertions(+), 1748 deletions(-) delete mode 100644 deps/stackwalker/CMakeLists.txt delete mode 100644 deps/stackwalker/StackWalker.cpp delete mode 100644 deps/stackwalker/StackWalker.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 2454d90b..f6a3419f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -44,7 +44,6 @@ add_subdirectory( "deps/MySQL" ) add_subdirectory( "deps/datReader" ) add_subdirectory( "deps/mysqlConnector" ) add_subdirectory( "deps/recastnavigation" ) -add_subdirectory( "deps/stackwalker" ) ############################## # Main Sapphire Components # diff --git a/deps/stackwalker/CMakeLists.txt b/deps/stackwalker/CMakeLists.txt deleted file mode 100644 index d0111465..00000000 --- a/deps/stackwalker/CMakeLists.txt +++ /dev/null @@ -1,11 +0,0 @@ -cmake_minimum_required(VERSION 3.0.2) -project(Sapphire) - -if( WIN32 ) - - file( GLOB STACKWALKER_INCLUDE_FILES "${CMAKE_CURRENT_SOURCE_DIR}/*.h*" ) - file( GLOB STACKWALKER_SOURCE_FILES "${CMAKE_CURRENT_SOURCE_DIR}/*.c*" ) - - add_library( stackwalker ${STACKWALKER_INCLUDE_FILES} ${STACKWALKER_SOURCE_FILES} ) - -endif() \ No newline at end of file diff --git a/deps/stackwalker/StackWalker.cpp b/deps/stackwalker/StackWalker.cpp deleted file mode 100644 index 7008ac67..00000000 --- a/deps/stackwalker/StackWalker.cpp +++ /dev/null @@ -1,1469 +0,0 @@ -/********************************************************************** - * - * StackWalker.cpp - * https://github.com/JochenKalmbach/StackWalker - * - * Old location: http://stackwalker.codeplex.com/ - * - * - * History: - * 2005-07-27 v1 - First public release on http://www.codeproject.com/ - * http://www.codeproject.com/threads/StackWalker.asp - * 2005-07-28 v2 - Changed the params of the constructor and ShowCallstack - * (to simplify the usage) - * 2005-08-01 v3 - Changed to use 'CONTEXT_FULL' instead of CONTEXT_ALL - * (should also be enough) - * - Changed to compile correctly with the PSDK of VC7.0 - * (GetFileVersionInfoSizeA and GetFileVersionInfoA is wrongly defined: - * it uses LPSTR instead of LPCSTR as first parameter) - * - Added declarations to support VC5/6 without using 'dbghelp.h' - * - Added a 'pUserData' member to the ShowCallstack function and the - * PReadProcessMemoryRoutine declaration (to pass some user-defined data, - * which can be used in the readMemoryFunction-callback) - * 2005-08-02 v4 - OnSymInit now also outputs the OS-Version by default - * - Added example for doing an exception-callstack-walking in main.cpp - * (thanks to owillebo: http://www.codeproject.com/script/profile/whos_who.asp?id=536268) - * 2005-08-05 v5 - Removed most Lint (http://www.gimpel.com/) errors... thanks to Okko Willeboordse! - * 2008-08-04 v6 - Fixed Bug: Missing LEAK-end-tag - * http://www.codeproject.com/KB/applications/leakfinder.aspx?msg=2502890#xx2502890xx - * Fixed Bug: Compiled with "WIN32_LEAN_AND_MEAN" - * http://www.codeproject.com/KB/applications/leakfinder.aspx?msg=1824718#xx1824718xx - * Fixed Bug: Compiling with "/Wall" - * http://www.codeproject.com/KB/threads/StackWalker.aspx?msg=2638243#xx2638243xx - * Fixed Bug: Now checking SymUseSymSrv - * http://www.codeproject.com/KB/threads/StackWalker.aspx?msg=1388979#xx1388979xx - * Fixed Bug: Support for recursive function calls - * http://www.codeproject.com/KB/threads/StackWalker.aspx?msg=1434538#xx1434538xx - * Fixed Bug: Missing FreeLibrary call in "GetModuleListTH32" - * http://www.codeproject.com/KB/threads/StackWalker.aspx?msg=1326923#xx1326923xx - * Fixed Bug: SymDia is number 7, not 9! - * 2008-09-11 v7 For some (undocumented) reason, dbhelp.h is needing a packing of 8! - * Thanks to Teajay which reported the bug... - * http://www.codeproject.com/KB/applications/leakfinder.aspx?msg=2718933#xx2718933xx - * 2008-11-27 v8 Debugging Tools for Windows are now stored in a different directory - * Thanks to Luiz Salamon which reported this "bug"... - * http://www.codeproject.com/KB/threads/StackWalker.aspx?msg=2822736#xx2822736xx - * 2009-04-10 v9 License slightly corrected ( replaced) - * 2009-11-01 v10 Moved to http://stackwalker.codeplex.com/ - * 2009-11-02 v11 Now try to use IMAGEHLP_MODULE64_V3 if available - * 2010-04-15 v12 Added support for VS2010 RTM - * 2010-05-25 v13 Now using secure MyStrcCpy. Thanks to luke.simon: - * http://www.codeproject.com/KB/applications/leakfinder.aspx?msg=3477467#xx3477467xx - * 2013-01-07 v14 Runtime Check Error VS2010 Debug Builds fixed: - * http://stackwalker.codeplex.com/workitem/10511 - * - * - * LICENSE (http://www.opensource.org/licenses/bsd-license.php) - * - * Copyright (c) 2005-2013, Jochen Kalmbach - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * Neither the name of Jochen Kalmbach nor the names of its contributors may be - * used to endorse or promote products derived from this software without - * specific prior written permission. - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - **********************************************************************/ - -#include "StackWalker.h" - -#include -#include -#include -#include -#pragma comment(lib, "version.lib") // for "VerQueryValue" -#pragma warning(disable : 4826) - - -// If VC7 and later, then use the shipped 'dbghelp.h'-file -#pragma pack(push, 8) -#if _MSC_VER >= 1300 -#include -#else -// inline the important dbghelp.h-declarations... -typedef enum -{ - SymNone = 0, - SymCoff, - SymCv, - SymPdb, - SymExport, - SymDeferred, - SymSym, - SymDia, - SymVirtual, - NumSymTypes -} SYM_TYPE; -typedef struct _IMAGEHLP_LINE64 -{ - DWORD SizeOfStruct; // set to sizeof(IMAGEHLP_LINE64) - PVOID Key; // internal - DWORD LineNumber; // line number in file - PCHAR FileName; // full filename - DWORD64 Address; // first instruction of line -} IMAGEHLP_LINE64, *PIMAGEHLP_LINE64; -typedef struct _IMAGEHLP_MODULE64 -{ - DWORD SizeOfStruct; // set to sizeof(IMAGEHLP_MODULE64) - DWORD64 BaseOfImage; // base load address of module - DWORD ImageSize; // virtual size of the loaded module - DWORD TimeDateStamp; // date/time stamp from pe header - DWORD CheckSum; // checksum from the pe header - DWORD NumSyms; // number of symbols in the symbol table - SYM_TYPE SymType; // type of symbols loaded - CHAR ModuleName[32]; // module name - CHAR ImageName[256]; // image name - CHAR LoadedImageName[256]; // symbol file name -} IMAGEHLP_MODULE64, *PIMAGEHLP_MODULE64; -typedef struct _IMAGEHLP_SYMBOL64 -{ - DWORD SizeOfStruct; // set to sizeof(IMAGEHLP_SYMBOL64) - DWORD64 Address; // virtual address including dll base address - DWORD Size; // estimated size of symbol, can be zero - DWORD Flags; // info about the symbols, see the SYMF defines - DWORD MaxNameLength; // maximum size of symbol name in 'Name' - CHAR Name[1]; // symbol name (null terminated string) -} IMAGEHLP_SYMBOL64, *PIMAGEHLP_SYMBOL64; -typedef enum -{ - AddrMode1616, - AddrMode1632, - AddrModeReal, - AddrModeFlat -} ADDRESS_MODE; -typedef struct _tagADDRESS64 -{ - DWORD64 Offset; - WORD Segment; - ADDRESS_MODE Mode; -} ADDRESS64, *LPADDRESS64; -typedef struct _KDHELP64 -{ - DWORD64 Thread; - DWORD ThCallbackStack; - DWORD ThCallbackBStore; - DWORD NextCallback; - DWORD FramePointer; - DWORD64 KiCallUserMode; - DWORD64 KeUserCallbackDispatcher; - DWORD64 SystemRangeStart; - DWORD64 Reserved[8]; -} KDHELP64, *PKDHELP64; -typedef struct _tagSTACKFRAME64 -{ - ADDRESS64 AddrPC; // program counter - ADDRESS64 AddrReturn; // return address - ADDRESS64 AddrFrame; // frame pointer - ADDRESS64 AddrStack; // stack pointer - ADDRESS64 AddrBStore; // backing store pointer - PVOID FuncTableEntry; // pointer to pdata/fpo or NULL - DWORD64 Params[4]; // possible arguments to the function - BOOL Far; // WOW far call - BOOL Virtual; // is this a virtual frame? - DWORD64 Reserved[3]; - KDHELP64 KdHelp; -} STACKFRAME64, *LPSTACKFRAME64; -typedef BOOL(__stdcall* PREAD_PROCESS_MEMORY_ROUTINE64)(HANDLE hProcess, - DWORD64 qwBaseAddress, - PVOID lpBuffer, - DWORD nSize, - LPDWORD lpNumberOfBytesRead); -typedef PVOID(__stdcall* PFUNCTION_TABLE_ACCESS_ROUTINE64)(HANDLE hProcess, DWORD64 AddrBase); -typedef DWORD64(__stdcall* PGET_MODULE_BASE_ROUTINE64)(HANDLE hProcess, DWORD64 Address); -typedef DWORD64(__stdcall* PTRANSLATE_ADDRESS_ROUTINE64)(HANDLE hProcess, - HANDLE hThread, - LPADDRESS64 lpaddr); - -// clang-format off -#define SYMOPT_CASE_INSENSITIVE 0x00000001 -#define SYMOPT_UNDNAME 0x00000002 -#define SYMOPT_DEFERRED_LOADS 0x00000004 -#define SYMOPT_NO_CPP 0x00000008 -#define SYMOPT_LOAD_LINES 0x00000010 -#define SYMOPT_OMAP_FIND_NEAREST 0x00000020 -#define SYMOPT_LOAD_ANYTHING 0x00000040 -#define SYMOPT_IGNORE_CVREC 0x00000080 -#define SYMOPT_NO_UNQUALIFIED_LOADS 0x00000100 -#define SYMOPT_FAIL_CRITICAL_ERRORS 0x00000200 -#define SYMOPT_EXACT_SYMBOLS 0x00000400 -#define SYMOPT_ALLOW_ABSOLUTE_SYMBOLS 0x00000800 -#define SYMOPT_IGNORE_NT_SYMPATH 0x00001000 -#define SYMOPT_INCLUDE_32BIT_MODULES 0x00002000 -#define SYMOPT_PUBLICS_ONLY 0x00004000 -#define SYMOPT_NO_PUBLICS 0x00008000 -#define SYMOPT_AUTO_PUBLICS 0x00010000 -#define SYMOPT_NO_IMAGE_SEARCH 0x00020000 -#define SYMOPT_SECURE 0x00040000 -#define SYMOPT_DEBUG 0x80000000 -#define UNDNAME_COMPLETE (0x0000) // Enable full undecoration -#define UNDNAME_NAME_ONLY (0x1000) // Crack only the name for primary declaration; -// clang-format on - -#endif // _MSC_VER < 1300 -#pragma pack(pop) - -// Some missing defines (for VC5/6): -#ifndef INVALID_FILE_ATTRIBUTES -#define INVALID_FILE_ATTRIBUTES ((DWORD)-1) -#endif - -// secure-CRT_functions are only available starting with VC8 -#if _MSC_VER < 1400 -#define strcpy_s(dst, len, src) strcpy(dst, src) -#define strncpy_s(dst, len, src, maxLen) strncpy(dst, len, src) -#define strcat_s(dst, len, src) strcat(dst, src) -#define _snprintf_s _snprintf -#define _tcscat_s _tcscat -#endif - -static void MyStrCpy(char* szDest, size_t nMaxDestSize, const char* szSrc) -{ - if (nMaxDestSize <= 0) - return; - strncpy_s(szDest, nMaxDestSize, szSrc, _TRUNCATE); - // INFO: _TRUNCATE will ensure that it is null-terminated; - // but with older compilers (<1400) it uses "strncpy" and this does not!) - szDest[nMaxDestSize - 1] = 0; -} // MyStrCpy - -// Normally it should be enough to use 'CONTEXT_FULL' (better would be 'CONTEXT_ALL') -#define USED_CONTEXT_FLAGS CONTEXT_FULL - -class StackWalkerInternal -{ -public: - StackWalkerInternal(StackWalker* parent, HANDLE hProcess) - { - m_parent = parent; - m_hDbhHelp = NULL; - pSC = NULL; - m_hProcess = hProcess; - m_szSymPath = NULL; - pSFTA = NULL; - pSGLFA = NULL; - pSGMB = NULL; - pSGMI = NULL; - pSGO = NULL; - pSGSFA = NULL; - pSI = NULL; - pSLM = NULL; - pSSO = NULL; - pSW = NULL; - pUDSN = NULL; - pSGSP = NULL; - } - ~StackWalkerInternal() - { - if (pSC != NULL) - pSC(m_hProcess); // SymCleanup - if (m_hDbhHelp != NULL) - FreeLibrary(m_hDbhHelp); - m_hDbhHelp = NULL; - m_parent = NULL; - if (m_szSymPath != NULL) - free(m_szSymPath); - m_szSymPath = NULL; - } - BOOL Init(LPCSTR szSymPath) - { - if (m_parent == NULL) - return FALSE; - // Dynamically load the Entry-Points for dbghelp.dll: - // First try to load the newest one from - TCHAR szTemp[4096]; - // But before we do this, we first check if the ".local" file exists - if (GetModuleFileName(NULL, szTemp, 4096) > 0) - { - _tcscat_s(szTemp, _T(".local")); - if (GetFileAttributes(szTemp) == INVALID_FILE_ATTRIBUTES) - { - // ".local" file does not exist, so we can try to load the dbghelp.dll from the "Debugging Tools for Windows" - // Ok, first try the new path according to the architecture: -#ifdef _M_IX86 - if ((m_hDbhHelp == NULL) && (GetEnvironmentVariable(_T("ProgramFiles"), szTemp, 4096) > 0)) - { - _tcscat_s(szTemp, _T("\\Debugging Tools for Windows (x86)\\dbghelp.dll")); - // now check if the file exists: - if (GetFileAttributes(szTemp) != INVALID_FILE_ATTRIBUTES) - { - m_hDbhHelp = LoadLibrary(szTemp); - } - } -#elif _M_X64 - if ((m_hDbhHelp == NULL) && (GetEnvironmentVariable(_T("ProgramFiles"), szTemp, 4096) > 0)) - { - _tcscat_s(szTemp, _T("\\Debugging Tools for Windows (x64)\\dbghelp.dll")); - // now check if the file exists: - if (GetFileAttributes(szTemp) != INVALID_FILE_ATTRIBUTES) - { - m_hDbhHelp = LoadLibrary(szTemp); - } - } -#elif _M_IA64 - if ((m_hDbhHelp == NULL) && (GetEnvironmentVariable(_T("ProgramFiles"), szTemp, 4096) > 0)) - { - _tcscat_s(szTemp, _T("\\Debugging Tools for Windows (ia64)\\dbghelp.dll")); - // now check if the file exists: - if (GetFileAttributes(szTemp) != INVALID_FILE_ATTRIBUTES) - { - m_hDbhHelp = LoadLibrary(szTemp); - } - } -#endif - // If still not found, try the old directories... - if ((m_hDbhHelp == NULL) && (GetEnvironmentVariable(_T("ProgramFiles"), szTemp, 4096) > 0)) - { - _tcscat_s(szTemp, _T("\\Debugging Tools for Windows\\dbghelp.dll")); - // now check if the file exists: - if (GetFileAttributes(szTemp) != INVALID_FILE_ATTRIBUTES) - { - m_hDbhHelp = LoadLibrary(szTemp); - } - } -#if defined _M_X64 || defined _M_IA64 - // Still not found? Then try to load the (old) 64-Bit version: - if ((m_hDbhHelp == NULL) && (GetEnvironmentVariable(_T("ProgramFiles"), szTemp, 4096) > 0)) - { - _tcscat_s(szTemp, _T("\\Debugging Tools for Windows 64-Bit\\dbghelp.dll")); - if (GetFileAttributes(szTemp) != INVALID_FILE_ATTRIBUTES) - { - m_hDbhHelp = LoadLibrary(szTemp); - } - } -#endif - } - } - if (m_hDbhHelp == NULL) // if not already loaded, try to load a default-one - m_hDbhHelp = LoadLibrary(_T("dbghelp.dll")); - if (m_hDbhHelp == NULL) - return FALSE; - pSI = (tSI)GetProcAddress(m_hDbhHelp, "SymInitialize"); - pSC = (tSC)GetProcAddress(m_hDbhHelp, "SymCleanup"); - - pSW = (tSW)GetProcAddress(m_hDbhHelp, "StackWalk64"); - pSGO = (tSGO)GetProcAddress(m_hDbhHelp, "SymGetOptions"); - pSSO = (tSSO)GetProcAddress(m_hDbhHelp, "SymSetOptions"); - - pSFTA = (tSFTA)GetProcAddress(m_hDbhHelp, "SymFunctionTableAccess64"); - pSGLFA = (tSGLFA)GetProcAddress(m_hDbhHelp, "SymGetLineFromAddr64"); - pSGMB = (tSGMB)GetProcAddress(m_hDbhHelp, "SymGetModuleBase64"); - pSGMI = (tSGMI)GetProcAddress(m_hDbhHelp, "SymGetModuleInfo64"); - pSGSFA = (tSGSFA)GetProcAddress(m_hDbhHelp, "SymGetSymFromAddr64"); - pUDSN = (tUDSN)GetProcAddress(m_hDbhHelp, "UnDecorateSymbolName"); - pSLM = (tSLM)GetProcAddress(m_hDbhHelp, "SymLoadModule64"); - pSGSP = (tSGSP)GetProcAddress(m_hDbhHelp, "SymGetSearchPath"); - - if (pSC == NULL || pSFTA == NULL || pSGMB == NULL || pSGMI == NULL || pSGO == NULL || - pSGSFA == NULL || pSI == NULL || pSSO == NULL || pSW == NULL || pUDSN == NULL || - pSLM == NULL) - { - FreeLibrary(m_hDbhHelp); - m_hDbhHelp = NULL; - pSC = NULL; - return FALSE; - } - - // SymInitialize - if (szSymPath != NULL) - m_szSymPath = _strdup(szSymPath); - if (this->pSI(m_hProcess, m_szSymPath, FALSE) == FALSE) - this->m_parent->OnDbgHelpErr("SymInitialize", GetLastError(), 0); - - DWORD symOptions = this->pSGO(); // SymGetOptions - symOptions |= SYMOPT_LOAD_LINES; - symOptions |= SYMOPT_FAIL_CRITICAL_ERRORS; - //symOptions |= SYMOPT_NO_PROMPTS; - // SymSetOptions - symOptions = this->pSSO(symOptions); - - char buf[StackWalker::STACKWALK_MAX_NAMELEN] = {0}; - if (this->pSGSP != NULL) - { - if (this->pSGSP(m_hProcess, buf, StackWalker::STACKWALK_MAX_NAMELEN) == FALSE) - this->m_parent->OnDbgHelpErr("SymGetSearchPath", GetLastError(), 0); - } - char szUserName[1024] = {0}; - DWORD dwSize = 1024; - GetUserNameA(szUserName, &dwSize); - this->m_parent->OnSymInit(buf, symOptions, szUserName); - - return TRUE; - } - - StackWalker* m_parent; - - HMODULE m_hDbhHelp; - HANDLE m_hProcess; - LPSTR m_szSymPath; - -#pragma pack(push, 8) - typedef struct IMAGEHLP_MODULE64_V3 - { - DWORD SizeOfStruct; // set to sizeof(IMAGEHLP_MODULE64) - DWORD64 BaseOfImage; // base load address of module - DWORD ImageSize; // virtual size of the loaded module - DWORD TimeDateStamp; // date/time stamp from pe header - DWORD CheckSum; // checksum from the pe header - DWORD NumSyms; // number of symbols in the symbol table - SYM_TYPE SymType; // type of symbols loaded - CHAR ModuleName[32]; // module name - CHAR ImageName[256]; // image name - CHAR LoadedImageName[256]; // symbol file name - // new elements: 07-Jun-2002 - CHAR LoadedPdbName[256]; // pdb file name - DWORD CVSig; // Signature of the CV record in the debug directories - CHAR CVData[MAX_PATH * 3]; // Contents of the CV record - DWORD PdbSig; // Signature of PDB - GUID PdbSig70; // Signature of PDB (VC 7 and up) - DWORD PdbAge; // DBI age of pdb - BOOL PdbUnmatched; // loaded an unmatched pdb - BOOL DbgUnmatched; // loaded an unmatched dbg - BOOL LineNumbers; // we have line number information - BOOL GlobalSymbols; // we have internal symbol information - BOOL TypeInfo; // we have type information - // new elements: 17-Dec-2003 - BOOL SourceIndexed; // pdb supports source server - BOOL Publics; // contains public symbols - }; - - typedef struct IMAGEHLP_MODULE64_V2 - { - DWORD SizeOfStruct; // set to sizeof(IMAGEHLP_MODULE64) - DWORD64 BaseOfImage; // base load address of module - DWORD ImageSize; // virtual size of the loaded module - DWORD TimeDateStamp; // date/time stamp from pe header - DWORD CheckSum; // checksum from the pe header - DWORD NumSyms; // number of symbols in the symbol table - SYM_TYPE SymType; // type of symbols loaded - CHAR ModuleName[32]; // module name - CHAR ImageName[256]; // image name - CHAR LoadedImageName[256]; // symbol file name - }; -#pragma pack(pop) - - // SymCleanup() - typedef BOOL(__stdcall* tSC)(IN HANDLE hProcess); - tSC pSC; - - // SymFunctionTableAccess64() - typedef PVOID(__stdcall* tSFTA)(HANDLE hProcess, DWORD64 AddrBase); - tSFTA pSFTA; - - // SymGetLineFromAddr64() - typedef BOOL(__stdcall* tSGLFA)(IN HANDLE hProcess, - IN DWORD64 dwAddr, - OUT PDWORD pdwDisplacement, - OUT PIMAGEHLP_LINE64 Line); - tSGLFA pSGLFA; - - // SymGetModuleBase64() - typedef DWORD64(__stdcall* tSGMB)(IN HANDLE hProcess, IN DWORD64 dwAddr); - tSGMB pSGMB; - - // SymGetModuleInfo64() - typedef BOOL(__stdcall* tSGMI)(IN HANDLE hProcess, - IN DWORD64 dwAddr, - OUT IMAGEHLP_MODULE64_V3* ModuleInfo); - tSGMI pSGMI; - - // SymGetOptions() - typedef DWORD(__stdcall* tSGO)(VOID); - tSGO pSGO; - - // SymGetSymFromAddr64() - typedef BOOL(__stdcall* tSGSFA)(IN HANDLE hProcess, - IN DWORD64 dwAddr, - OUT PDWORD64 pdwDisplacement, - OUT PIMAGEHLP_SYMBOL64 Symbol); - tSGSFA pSGSFA; - - // SymInitialize() - typedef BOOL(__stdcall* tSI)(IN HANDLE hProcess, IN PSTR UserSearchPath, IN BOOL fInvadeProcess); - tSI pSI; - - // SymLoadModule64() - typedef DWORD64(__stdcall* tSLM)(IN HANDLE hProcess, - IN HANDLE hFile, - IN PSTR ImageName, - IN PSTR ModuleName, - IN DWORD64 BaseOfDll, - IN DWORD SizeOfDll); - tSLM pSLM; - - // SymSetOptions() - typedef DWORD(__stdcall* tSSO)(IN DWORD SymOptions); - tSSO pSSO; - - // StackWalk64() - typedef BOOL(__stdcall* tSW)(DWORD MachineType, - HANDLE hProcess, - HANDLE hThread, - LPSTACKFRAME64 StackFrame, - PVOID ContextRecord, - PREAD_PROCESS_MEMORY_ROUTINE64 ReadMemoryRoutine, - PFUNCTION_TABLE_ACCESS_ROUTINE64 FunctionTableAccessRoutine, - PGET_MODULE_BASE_ROUTINE64 GetModuleBaseRoutine, - PTRANSLATE_ADDRESS_ROUTINE64 TranslateAddress); - tSW pSW; - - // UnDecorateSymbolName() - typedef DWORD(__stdcall WINAPI* tUDSN)(PCSTR DecoratedName, - PSTR UnDecoratedName, - DWORD UndecoratedLength, - DWORD Flags); - tUDSN pUDSN; - - typedef BOOL(__stdcall WINAPI* tSGSP)(HANDLE hProcess, PSTR SearchPath, DWORD SearchPathLength); - tSGSP pSGSP; - -private: -// **************************************** ToolHelp32 ************************ -#define MAX_MODULE_NAME32 255 -#define TH32CS_SNAPMODULE 0x00000008 -#pragma pack(push, 8) - typedef struct tagMODULEENTRY32 - { - DWORD dwSize; - DWORD th32ModuleID; // This module - DWORD th32ProcessID; // owning process - DWORD GlblcntUsage; // Global usage count on the module - DWORD ProccntUsage; // Module usage count in th32ProcessID's context - BYTE* modBaseAddr; // Base address of module in th32ProcessID's context - DWORD modBaseSize; // Size in bytes of module starting at modBaseAddr - HMODULE hModule; // The hModule of this module in th32ProcessID's context - char szModule[MAX_MODULE_NAME32 + 1]; - char szExePath[MAX_PATH]; - } MODULEENTRY32; - typedef MODULEENTRY32* PMODULEENTRY32; - typedef MODULEENTRY32* LPMODULEENTRY32; -#pragma pack(pop) - - BOOL GetModuleListTH32(HANDLE hProcess, DWORD pid) - { - // CreateToolhelp32Snapshot() - typedef HANDLE(__stdcall * tCT32S)(DWORD dwFlags, DWORD th32ProcessID); - // Module32First() - typedef BOOL(__stdcall * tM32F)(HANDLE hSnapshot, LPMODULEENTRY32 lpme); - // Module32Next() - typedef BOOL(__stdcall * tM32N)(HANDLE hSnapshot, LPMODULEENTRY32 lpme); - - // try both dlls... - const TCHAR* dllname[] = {_T("kernel32.dll"), _T("tlhelp32.dll")}; - HINSTANCE hToolhelp = NULL; - tCT32S pCT32S = NULL; - tM32F pM32F = NULL; - tM32N pM32N = NULL; - - HANDLE hSnap; - MODULEENTRY32 me; - me.dwSize = sizeof(me); - BOOL keepGoing; - size_t i; - - for (i = 0; i < (sizeof(dllname) / sizeof(dllname[0])); i++) - { - hToolhelp = LoadLibrary(dllname[i]); - if (hToolhelp == NULL) - continue; - pCT32S = (tCT32S)GetProcAddress(hToolhelp, "CreateToolhelp32Snapshot"); - pM32F = (tM32F)GetProcAddress(hToolhelp, "Module32First"); - pM32N = (tM32N)GetProcAddress(hToolhelp, "Module32Next"); - if ((pCT32S != NULL) && (pM32F != NULL) && (pM32N != NULL)) - break; // found the functions! - FreeLibrary(hToolhelp); - hToolhelp = NULL; - } - - if (hToolhelp == NULL) - return FALSE; - - hSnap = pCT32S(TH32CS_SNAPMODULE, pid); - if (hSnap == (HANDLE)-1) - { - FreeLibrary(hToolhelp); - return FALSE; - } - - keepGoing = !!pM32F(hSnap, &me); - int cnt = 0; - while (keepGoing) - { - this->LoadModule(hProcess, me.szExePath, me.szModule, (DWORD64)me.modBaseAddr, - me.modBaseSize); - cnt++; - keepGoing = !!pM32N(hSnap, &me); - } - CloseHandle(hSnap); - FreeLibrary(hToolhelp); - if (cnt <= 0) - return FALSE; - return TRUE; - } // GetModuleListTH32 - - // **************************************** PSAPI ************************ - typedef struct _MODULEINFO - { - LPVOID lpBaseOfDll; - DWORD SizeOfImage; - LPVOID EntryPoint; - } MODULEINFO, *LPMODULEINFO; - - BOOL GetModuleListPSAPI(HANDLE hProcess) - { - // EnumProcessModules() - typedef BOOL(__stdcall * tEPM)(HANDLE hProcess, HMODULE * lphModule, DWORD cb, - LPDWORD lpcbNeeded); - // GetModuleFileNameEx() - typedef DWORD(__stdcall * tGMFNE)(HANDLE hProcess, HMODULE hModule, LPSTR lpFilename, - DWORD nSize); - // GetModuleBaseName() - typedef DWORD(__stdcall * tGMBN)(HANDLE hProcess, HMODULE hModule, LPSTR lpFilename, - DWORD nSize); - // GetModuleInformation() - typedef BOOL(__stdcall * tGMI)(HANDLE hProcess, HMODULE hModule, LPMODULEINFO pmi, DWORD nSize); - - HINSTANCE hPsapi; - tEPM pEPM; - tGMFNE pGMFNE; - tGMBN pGMBN; - tGMI pGMI; - - DWORD i; - //ModuleEntry e; - DWORD cbNeeded; - MODULEINFO mi; - HMODULE* hMods = 0; - char* tt = NULL; - char* tt2 = NULL; - const SIZE_T TTBUFLEN = 8096; - int cnt = 0; - - hPsapi = LoadLibrary(_T("psapi.dll")); - if (hPsapi == NULL) - return FALSE; - - pEPM = (tEPM)GetProcAddress(hPsapi, "EnumProcessModules"); - pGMFNE = (tGMFNE)GetProcAddress(hPsapi, "GetModuleFileNameExA"); - pGMBN = (tGMFNE)GetProcAddress(hPsapi, "GetModuleBaseNameA"); - pGMI = (tGMI)GetProcAddress(hPsapi, "GetModuleInformation"); - if ((pEPM == NULL) || (pGMFNE == NULL) || (pGMBN == NULL) || (pGMI == NULL)) - { - // we couldn't find all functions - FreeLibrary(hPsapi); - return FALSE; - } - - hMods = (HMODULE*)malloc(sizeof(HMODULE) * (TTBUFLEN / sizeof(HMODULE))); - tt = (char*)malloc(sizeof(char) * TTBUFLEN); - tt2 = (char*)malloc(sizeof(char) * TTBUFLEN); - if ((hMods == NULL) || (tt == NULL) || (tt2 == NULL)) - goto cleanup; - - if (!pEPM(hProcess, hMods, TTBUFLEN, &cbNeeded)) - { - //_ftprintf(fLogFile, _T("%lu: EPM failed, GetLastError = %lu\n"), g_dwShowCount, gle ); - goto cleanup; - } - - if (cbNeeded > TTBUFLEN) - { - //_ftprintf(fLogFile, _T("%lu: More than %lu module handles. Huh?\n"), g_dwShowCount, lenof( hMods ) ); - goto cleanup; - } - - for (i = 0; i < cbNeeded / sizeof(hMods[0]); i++) - { - // base address, size - pGMI(hProcess, hMods[i], &mi, sizeof(mi)); - // image file name - tt[0] = 0; - pGMFNE(hProcess, hMods[i], tt, TTBUFLEN); - // module name - tt2[0] = 0; - pGMBN(hProcess, hMods[i], tt2, TTBUFLEN); - - DWORD dwRes = this->LoadModule(hProcess, tt, tt2, (DWORD64)mi.lpBaseOfDll, mi.SizeOfImage); - if (dwRes != ERROR_SUCCESS) - this->m_parent->OnDbgHelpErr("LoadModule", dwRes, 0); - cnt++; - } - - cleanup: - if (hPsapi != NULL) - FreeLibrary(hPsapi); - if (tt2 != NULL) - free(tt2); - if (tt != NULL) - free(tt); - if (hMods != NULL) - free(hMods); - - return cnt != 0; - } // GetModuleListPSAPI - - DWORD LoadModule(HANDLE hProcess, LPCSTR img, LPCSTR mod, DWORD64 baseAddr, DWORD size) - { - CHAR* szImg = _strdup(img); - CHAR* szMod = _strdup(mod); - DWORD result = ERROR_SUCCESS; - if ((szImg == NULL) || (szMod == NULL)) - result = ERROR_NOT_ENOUGH_MEMORY; - else - { - if (pSLM(hProcess, 0, szImg, szMod, baseAddr, size) == 0) - result = GetLastError(); - } - ULONGLONG fileVersion = 0; - if ((m_parent != NULL) && (szImg != NULL)) - { - // try to retrieve the file-version: - if ((this->m_parent->m_options & StackWalker::RetrieveFileVersion) != 0) - { - VS_FIXEDFILEINFO* fInfo = NULL; - DWORD dwHandle; - DWORD dwSize = GetFileVersionInfoSizeA(szImg, &dwHandle); - if (dwSize > 0) - { - LPVOID vData = malloc(dwSize); - if (vData != NULL) - { - if (GetFileVersionInfoA(szImg, dwHandle, dwSize, vData) != 0) - { - UINT len; - TCHAR szSubBlock[] = _T("\\"); - if (VerQueryValue(vData, szSubBlock, (LPVOID*)&fInfo, &len) == 0) - fInfo = NULL; - else - { - fileVersion = - ((ULONGLONG)fInfo->dwFileVersionLS) + ((ULONGLONG)fInfo->dwFileVersionMS << 32); - } - } - free(vData); - } - } - } - - // Retrieve some additional-infos about the module - IMAGEHLP_MODULE64_V3 Module; - const char* szSymType = "-unknown-"; - if (this->GetModuleInfo(hProcess, baseAddr, &Module) != FALSE) - { - switch (Module.SymType) - { - case SymNone: - szSymType = "-nosymbols-"; - break; - case SymCoff: // 1 - szSymType = "COFF"; - break; - case SymCv: // 2 - szSymType = "CV"; - break; - case SymPdb: // 3 - szSymType = "PDB"; - break; - case SymExport: // 4 - szSymType = "-exported-"; - break; - case SymDeferred: // 5 - szSymType = "-deferred-"; - break; - case SymSym: // 6 - szSymType = "SYM"; - break; - case 7: // SymDia: - szSymType = "DIA"; - break; - case 8: //SymVirtual: - szSymType = "Virtual"; - break; - } - } - LPCSTR pdbName = Module.LoadedImageName; - if (Module.LoadedPdbName[0] != 0) - pdbName = Module.LoadedPdbName; - this->m_parent->OnLoadModule(img, mod, baseAddr, size, result, szSymType, pdbName, - fileVersion); - } - if (szImg != NULL) - free(szImg); - if (szMod != NULL) - free(szMod); - return result; - } - -public: - BOOL LoadModules(HANDLE hProcess, DWORD dwProcessId) - { - // first try toolhelp32 - if (GetModuleListTH32(hProcess, dwProcessId)) - return true; - // then try psapi - return GetModuleListPSAPI(hProcess); - } - - BOOL GetModuleInfo(HANDLE hProcess, DWORD64 baseAddr, IMAGEHLP_MODULE64_V3* pModuleInfo) - { - memset(pModuleInfo, 0, sizeof(IMAGEHLP_MODULE64_V3)); - if (this->pSGMI == NULL) - { - SetLastError(ERROR_DLL_INIT_FAILED); - return FALSE; - } - // First try to use the larger ModuleInfo-Structure - pModuleInfo->SizeOfStruct = sizeof(IMAGEHLP_MODULE64_V3); - void* pData = malloc( - 4096); // reserve enough memory, so the bug in v6.3.5.1 does not lead to memory-overwrites... - if (pData == NULL) - { - SetLastError(ERROR_NOT_ENOUGH_MEMORY); - return FALSE; - } - memcpy(pData, pModuleInfo, sizeof(IMAGEHLP_MODULE64_V3)); - static bool s_useV3Version = true; - if (s_useV3Version) - { - if (this->pSGMI(hProcess, baseAddr, (IMAGEHLP_MODULE64_V3*)pData) != FALSE) - { - // only copy as much memory as is reserved... - memcpy(pModuleInfo, pData, sizeof(IMAGEHLP_MODULE64_V3)); - pModuleInfo->SizeOfStruct = sizeof(IMAGEHLP_MODULE64_V3); - free(pData); - return TRUE; - } - s_useV3Version = false; // to prevent unnecessary calls with the larger struct... - } - - // could not retrieve the bigger structure, try with the smaller one (as defined in VC7.1)... - pModuleInfo->SizeOfStruct = sizeof(IMAGEHLP_MODULE64_V2); - memcpy(pData, pModuleInfo, sizeof(IMAGEHLP_MODULE64_V2)); - if (this->pSGMI(hProcess, baseAddr, (IMAGEHLP_MODULE64_V3*)pData) != FALSE) - { - // only copy as much memory as is reserved... - memcpy(pModuleInfo, pData, sizeof(IMAGEHLP_MODULE64_V2)); - pModuleInfo->SizeOfStruct = sizeof(IMAGEHLP_MODULE64_V2); - free(pData); - return TRUE; - } - free(pData); - SetLastError(ERROR_DLL_INIT_FAILED); - return FALSE; - } -}; - -// ############################################################# -StackWalker::StackWalker(DWORD dwProcessId, HANDLE hProcess) -{ - this->m_options = OptionsAll; - this->m_modulesLoaded = FALSE; - this->m_hProcess = hProcess; - this->m_sw = new StackWalkerInternal(this, this->m_hProcess); - this->m_dwProcessId = dwProcessId; - this->m_szSymPath = NULL; - this->m_MaxRecursionCount = 1000; -} -StackWalker::StackWalker(int options, LPCSTR szSymPath, DWORD dwProcessId, HANDLE hProcess) -{ - this->m_options = options; - this->m_modulesLoaded = FALSE; - this->m_hProcess = hProcess; - this->m_sw = new StackWalkerInternal(this, this->m_hProcess); - this->m_dwProcessId = dwProcessId; - if (szSymPath != NULL) - { - this->m_szSymPath = _strdup(szSymPath); - this->m_options |= SymBuildPath; - } - else - this->m_szSymPath = NULL; - this->m_MaxRecursionCount = 1000; -} - -StackWalker::~StackWalker() -{ - if (m_szSymPath != NULL) - free(m_szSymPath); - m_szSymPath = NULL; - if (this->m_sw != NULL) - delete this->m_sw; - this->m_sw = NULL; -} - -BOOL StackWalker::LoadModules() -{ - if (this->m_sw == NULL) - { - SetLastError(ERROR_DLL_INIT_FAILED); - return FALSE; - } - if (m_modulesLoaded != FALSE) - return TRUE; - - // Build the sym-path: - char* szSymPath = NULL; - if ((this->m_options & SymBuildPath) != 0) - { - const size_t nSymPathLen = 4096; - szSymPath = (char*)malloc(nSymPathLen); - if (szSymPath == NULL) - { - SetLastError(ERROR_NOT_ENOUGH_MEMORY); - return FALSE; - } - szSymPath[0] = 0; - // Now first add the (optional) provided sympath: - if (this->m_szSymPath != NULL) - { - strcat_s(szSymPath, nSymPathLen, this->m_szSymPath); - strcat_s(szSymPath, nSymPathLen, ";"); - } - - strcat_s(szSymPath, nSymPathLen, ".;"); - - const size_t nTempLen = 1024; - char szTemp[nTempLen]; - // Now add the current directory: - if (GetCurrentDirectoryA(nTempLen, szTemp) > 0) - { - szTemp[nTempLen - 1] = 0; - strcat_s(szSymPath, nSymPathLen, szTemp); - strcat_s(szSymPath, nSymPathLen, ";"); - } - - // Now add the path for the main-module: - if (GetModuleFileNameA(NULL, szTemp, nTempLen) > 0) - { - szTemp[nTempLen - 1] = 0; - for (char* p = (szTemp + strlen(szTemp) - 1); p >= szTemp; --p) - { - // locate the rightmost path separator - if ((*p == '\\') || (*p == '/') || (*p == ':')) - { - *p = 0; - break; - } - } // for (search for path separator...) - if (strlen(szTemp) > 0) - { - strcat_s(szSymPath, nSymPathLen, szTemp); - strcat_s(szSymPath, nSymPathLen, ";"); - } - } - if (GetEnvironmentVariableA("_NT_SYMBOL_PATH", szTemp, nTempLen) > 0) - { - szTemp[nTempLen - 1] = 0; - strcat_s(szSymPath, nSymPathLen, szTemp); - strcat_s(szSymPath, nSymPathLen, ";"); - } - if (GetEnvironmentVariableA("_NT_ALTERNATE_SYMBOL_PATH", szTemp, nTempLen) > 0) - { - szTemp[nTempLen - 1] = 0; - strcat_s(szSymPath, nSymPathLen, szTemp); - strcat_s(szSymPath, nSymPathLen, ";"); - } - if (GetEnvironmentVariableA("SYSTEMROOT", szTemp, nTempLen) > 0) - { - szTemp[nTempLen - 1] = 0; - strcat_s(szSymPath, nSymPathLen, szTemp); - strcat_s(szSymPath, nSymPathLen, ";"); - // also add the "system32"-directory: - strcat_s(szTemp, nTempLen, "\\system32"); - strcat_s(szSymPath, nSymPathLen, szTemp); - strcat_s(szSymPath, nSymPathLen, ";"); - } - - if ((this->m_options & SymUseSymSrv) != 0) - { - if (GetEnvironmentVariableA("SYSTEMDRIVE", szTemp, nTempLen) > 0) - { - szTemp[nTempLen - 1] = 0; - strcat_s(szSymPath, nSymPathLen, "SRV*"); - strcat_s(szSymPath, nSymPathLen, szTemp); - strcat_s(szSymPath, nSymPathLen, "\\websymbols"); - strcat_s(szSymPath, nSymPathLen, "*http://msdl.microsoft.com/download/symbols;"); - } - else - strcat_s(szSymPath, nSymPathLen, - "SRV*c:\\websymbols*http://msdl.microsoft.com/download/symbols;"); - } - } // if SymBuildPath - - // First Init the whole stuff... - BOOL bRet = this->m_sw->Init(szSymPath); - if (szSymPath != NULL) - free(szSymPath); - szSymPath = NULL; - if (bRet == FALSE) - { - this->OnDbgHelpErr("Error while initializing dbghelp.dll", 0, 0); - SetLastError(ERROR_DLL_INIT_FAILED); - return FALSE; - } - - bRet = this->m_sw->LoadModules(this->m_hProcess, this->m_dwProcessId); - if (bRet != FALSE) - m_modulesLoaded = TRUE; - return bRet; -} - -// The following is used to pass the "userData"-Pointer to the user-provided readMemoryFunction -// This has to be done due to a problem with the "hProcess"-parameter in x64... -// Because this class is in no case multi-threading-enabled (because of the limitations -// of dbghelp.dll) it is "safe" to use a static-variable -static StackWalker::PReadProcessMemoryRoutine s_readMemoryFunction = NULL; -static LPVOID s_readMemoryFunction_UserData = NULL; - -BOOL StackWalker::ShowCallstack(HANDLE hThread, - const CONTEXT* context, - PReadProcessMemoryRoutine readMemoryFunction, - LPVOID pUserData) -{ - CONTEXT c; - CallstackEntry csEntry; - IMAGEHLP_SYMBOL64* pSym = NULL; - StackWalkerInternal::IMAGEHLP_MODULE64_V3 Module; - IMAGEHLP_LINE64 Line; - int frameNum; - bool bLastEntryCalled = true; - int curRecursionCount = 0; - - if (m_modulesLoaded == FALSE) - this->LoadModules(); // ignore the result... - - if (this->m_sw->m_hDbhHelp == NULL) - { - SetLastError(ERROR_DLL_INIT_FAILED); - return FALSE; - } - - s_readMemoryFunction = readMemoryFunction; - s_readMemoryFunction_UserData = pUserData; - - if (context == NULL) - { - // If no context is provided, capture the context - // See: https://stackwalker.codeplex.com/discussions/446958 -#if _WIN32_WINNT <= 0x0501 - // If we need to support XP, we need to use the "old way", because "GetThreadId" is not available! - if (hThread == GetCurrentThread()) -#else - if (GetThreadId(hThread) == GetCurrentThreadId()) -#endif - { - GET_CURRENT_CONTEXT_STACKWALKER_CODEPLEX(c, USED_CONTEXT_FLAGS); - } - else - { - SuspendThread(hThread); - memset(&c, 0, sizeof(CONTEXT)); - c.ContextFlags = USED_CONTEXT_FLAGS; - - // TODO: Detect if you want to get a thread context of a different process, which is running a different processor architecture... - // This does only work if we are x64 and the target process is x64 or x86; - // It cannot work, if this process is x64 and the target process is x64... this is not supported... - // See also: http://www.howzatt.demon.co.uk/articles/DebuggingInWin64.html - if (GetThreadContext(hThread, &c) == FALSE) - { - ResumeThread(hThread); - return FALSE; - } - } - } - else - c = *context; - - // init STACKFRAME for first call - STACKFRAME64 s; // in/out stackframe - memset(&s, 0, sizeof(s)); - DWORD imageType; -#ifdef _M_IX86 - // normally, call ImageNtHeader() and use machine info from PE header - imageType = IMAGE_FILE_MACHINE_I386; - s.AddrPC.Offset = c.Eip; - s.AddrPC.Mode = AddrModeFlat; - s.AddrFrame.Offset = c.Ebp; - s.AddrFrame.Mode = AddrModeFlat; - s.AddrStack.Offset = c.Esp; - s.AddrStack.Mode = AddrModeFlat; -#elif _M_X64 - imageType = IMAGE_FILE_MACHINE_AMD64; - s.AddrPC.Offset = c.Rip; - s.AddrPC.Mode = AddrModeFlat; - s.AddrFrame.Offset = c.Rsp; - s.AddrFrame.Mode = AddrModeFlat; - s.AddrStack.Offset = c.Rsp; - s.AddrStack.Mode = AddrModeFlat; -#elif _M_IA64 - imageType = IMAGE_FILE_MACHINE_IA64; - s.AddrPC.Offset = c.StIIP; - s.AddrPC.Mode = AddrModeFlat; - s.AddrFrame.Offset = c.IntSp; - s.AddrFrame.Mode = AddrModeFlat; - s.AddrBStore.Offset = c.RsBSP; - s.AddrBStore.Mode = AddrModeFlat; - s.AddrStack.Offset = c.IntSp; - s.AddrStack.Mode = AddrModeFlat; -#else -#error "Platform not supported!" -#endif - - pSym = (IMAGEHLP_SYMBOL64*)malloc(sizeof(IMAGEHLP_SYMBOL64) + STACKWALK_MAX_NAMELEN); - if (!pSym) - goto cleanup; // not enough memory... - memset(pSym, 0, sizeof(IMAGEHLP_SYMBOL64) + STACKWALK_MAX_NAMELEN); - pSym->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64); - pSym->MaxNameLength = STACKWALK_MAX_NAMELEN; - - memset(&Line, 0, sizeof(Line)); - Line.SizeOfStruct = sizeof(Line); - - memset(&Module, 0, sizeof(Module)); - Module.SizeOfStruct = sizeof(Module); - - for (frameNum = 0;; ++frameNum) - { - // get next stack frame (StackWalk64(), SymFunctionTableAccess64(), SymGetModuleBase64()) - // if this returns ERROR_INVALID_ADDRESS (487) or ERROR_NOACCESS (998), you can - // assume that either you are done, or that the stack is so hosed that the next - // deeper frame could not be found. - // CONTEXT need not to be supplied if imageTyp is IMAGE_FILE_MACHINE_I386! - if (!this->m_sw->pSW(imageType, this->m_hProcess, hThread, &s, &c, myReadProcMem, - this->m_sw->pSFTA, this->m_sw->pSGMB, NULL)) - { - // INFO: "StackWalk64" does not set "GetLastError"... - this->OnDbgHelpErr("StackWalk64", 0, s.AddrPC.Offset); - break; - } - - csEntry.offset = s.AddrPC.Offset; - csEntry.name[0] = 0; - csEntry.undName[0] = 0; - csEntry.undFullName[0] = 0; - csEntry.offsetFromSmybol = 0; - csEntry.offsetFromLine = 0; - csEntry.lineFileName[0] = 0; - csEntry.lineNumber = 0; - csEntry.loadedImageName[0] = 0; - csEntry.moduleName[0] = 0; - if (s.AddrPC.Offset == s.AddrReturn.Offset) - { - if ((this->m_MaxRecursionCount > 0) && (curRecursionCount > m_MaxRecursionCount)) - { - this->OnDbgHelpErr("StackWalk64-Endless-Callstack!", 0, s.AddrPC.Offset); - break; - } - curRecursionCount++; - } - else - curRecursionCount = 0; - if (s.AddrPC.Offset != 0) - { - // we seem to have a valid PC - // show procedure info (SymGetSymFromAddr64()) - if (this->m_sw->pSGSFA(this->m_hProcess, s.AddrPC.Offset, &(csEntry.offsetFromSmybol), - pSym) != FALSE) - { - MyStrCpy(csEntry.name, STACKWALK_MAX_NAMELEN, pSym->Name); - // UnDecorateSymbolName() - this->m_sw->pUDSN(pSym->Name, csEntry.undName, STACKWALK_MAX_NAMELEN, UNDNAME_NAME_ONLY); - this->m_sw->pUDSN(pSym->Name, csEntry.undFullName, STACKWALK_MAX_NAMELEN, UNDNAME_COMPLETE); - } - else - { - this->OnDbgHelpErr("SymGetSymFromAddr64", GetLastError(), s.AddrPC.Offset); - } - - // show line number info, NT5.0-method (SymGetLineFromAddr64()) - if (this->m_sw->pSGLFA != NULL) - { // yes, we have SymGetLineFromAddr64() - if (this->m_sw->pSGLFA(this->m_hProcess, s.AddrPC.Offset, &(csEntry.offsetFromLine), - &Line) != FALSE) - { - csEntry.lineNumber = Line.LineNumber; - MyStrCpy(csEntry.lineFileName, STACKWALK_MAX_NAMELEN, Line.FileName); - } - else - { - this->OnDbgHelpErr("SymGetLineFromAddr64", GetLastError(), s.AddrPC.Offset); - } - } // yes, we have SymGetLineFromAddr64() - - // show module info (SymGetModuleInfo64()) - if (this->m_sw->GetModuleInfo(this->m_hProcess, s.AddrPC.Offset, &Module) != FALSE) - { // got module info OK - switch (Module.SymType) - { - case SymNone: - csEntry.symTypeString = "-nosymbols-"; - break; - case SymCoff: - csEntry.symTypeString = "COFF"; - break; - case SymCv: - csEntry.symTypeString = "CV"; - break; - case SymPdb: - csEntry.symTypeString = "PDB"; - break; - case SymExport: - csEntry.symTypeString = "-exported-"; - break; - case SymDeferred: - csEntry.symTypeString = "-deferred-"; - break; - case SymSym: - csEntry.symTypeString = "SYM"; - break; -#if API_VERSION_NUMBER >= 9 - case SymDia: - csEntry.symTypeString = "DIA"; - break; -#endif - case 8: //SymVirtual: - csEntry.symTypeString = "Virtual"; - break; - default: - //_snprintf( ty, sizeof(ty), "symtype=%ld", (long) Module.SymType ); - csEntry.symTypeString = NULL; - break; - } - - MyStrCpy(csEntry.moduleName, STACKWALK_MAX_NAMELEN, Module.ModuleName); - csEntry.baseOfImage = Module.BaseOfImage; - MyStrCpy(csEntry.loadedImageName, STACKWALK_MAX_NAMELEN, Module.LoadedImageName); - } // got module info OK - else - { - this->OnDbgHelpErr("SymGetModuleInfo64", GetLastError(), s.AddrPC.Offset); - } - } // we seem to have a valid PC - - CallstackEntryType et = nextEntry; - if (frameNum == 0) - et = firstEntry; - bLastEntryCalled = false; - this->OnCallstackEntry(et, csEntry); - - if (s.AddrReturn.Offset == 0) - { - bLastEntryCalled = true; - this->OnCallstackEntry(lastEntry, csEntry); - SetLastError(ERROR_SUCCESS); - break; - } - } // for ( frameNum ) - -cleanup: - if (pSym) - free(pSym); - - if (bLastEntryCalled == false) - this->OnCallstackEntry(lastEntry, csEntry); - - if (context == NULL) - ResumeThread(hThread); - - return TRUE; -} - -BOOL StackWalker::ShowObject(LPVOID pObject) -{ - // Load modules if not done yet - if (m_modulesLoaded == FALSE) - this->LoadModules(); // ignore the result... - - // Verify that the DebugHelp.dll was actually found - if (this->m_sw->m_hDbhHelp == NULL) - { - SetLastError(ERROR_DLL_INIT_FAILED); - return FALSE; - } - - // SymGetSymFromAddr64() is required - if (this->m_sw->pSGSFA == NULL) - return FALSE; - - // Show object info (SymGetSymFromAddr64()) - DWORD64 dwAddress = DWORD64(pObject); - DWORD64 dwDisplacement = 0; - IMAGEHLP_SYMBOL64* pSym = - (IMAGEHLP_SYMBOL64*)malloc(sizeof(IMAGEHLP_SYMBOL64) + STACKWALK_MAX_NAMELEN); - memset(pSym, 0, sizeof(IMAGEHLP_SYMBOL64) + STACKWALK_MAX_NAMELEN); - pSym->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64); - pSym->MaxNameLength = STACKWALK_MAX_NAMELEN; - if (this->m_sw->pSGSFA(this->m_hProcess, dwAddress, &dwDisplacement, pSym) == FALSE) - { - this->OnDbgHelpErr("SymGetSymFromAddr64", GetLastError(), dwAddress); - return FALSE; - } - // Object name output - this->OnOutput(pSym->Name); - - free(pSym); - return TRUE; -}; - -BOOL __stdcall StackWalker::myReadProcMem(HANDLE hProcess, - DWORD64 qwBaseAddress, - PVOID lpBuffer, - DWORD nSize, - LPDWORD lpNumberOfBytesRead) -{ - if (s_readMemoryFunction == NULL) - { - SIZE_T st; - BOOL bRet = ReadProcessMemory(hProcess, (LPVOID)qwBaseAddress, lpBuffer, nSize, &st); - *lpNumberOfBytesRead = (DWORD)st; - //printf("ReadMemory: hProcess: %p, baseAddr: %p, buffer: %p, size: %d, read: %d, result: %d\n", hProcess, (LPVOID) qwBaseAddress, lpBuffer, nSize, (DWORD) st, (DWORD) bRet); - return bRet; - } - else - { - return s_readMemoryFunction(hProcess, qwBaseAddress, lpBuffer, nSize, lpNumberOfBytesRead, - s_readMemoryFunction_UserData); - } -} - -void StackWalker::OnLoadModule(LPCSTR img, - LPCSTR mod, - DWORD64 baseAddr, - DWORD size, - DWORD result, - LPCSTR symType, - LPCSTR pdbName, - ULONGLONG fileVersion) -{ - CHAR buffer[STACKWALK_MAX_NAMELEN]; - size_t maxLen = STACKWALK_MAX_NAMELEN; -#if _MSC_VER >= 1400 - maxLen = _TRUNCATE; -#endif - if (fileVersion == 0) - _snprintf_s(buffer, maxLen, "%s:%s (%p), size: %d (result: %d), SymType: '%s', PDB: '%s'\n", - img, mod, (LPVOID)baseAddr, size, result, symType, pdbName); - else - { - DWORD v4 = (DWORD)(fileVersion & 0xFFFF); - DWORD v3 = (DWORD)((fileVersion >> 16) & 0xFFFF); - DWORD v2 = (DWORD)((fileVersion >> 32) & 0xFFFF); - DWORD v1 = (DWORD)((fileVersion >> 48) & 0xFFFF); - _snprintf_s( - buffer, maxLen, - "%s:%s (%p), size: %d (result: %d), SymType: '%s', PDB: '%s', fileVersion: %d.%d.%d.%d\n", - img, mod, (LPVOID)baseAddr, size, result, symType, pdbName, v1, v2, v3, v4); - } - buffer[STACKWALK_MAX_NAMELEN - 1] = 0; // be sure it is NULL terminated - OnOutput(buffer); -} - -void StackWalker::OnCallstackEntry(CallstackEntryType eType, CallstackEntry& entry) -{ - CHAR buffer[STACKWALK_MAX_NAMELEN]; - size_t maxLen = STACKWALK_MAX_NAMELEN; -#if _MSC_VER >= 1400 - maxLen = _TRUNCATE; -#endif - if ((eType != lastEntry) && (entry.offset != 0)) - { - if (entry.name[0] == 0) - MyStrCpy(entry.name, STACKWALK_MAX_NAMELEN, "(function-name not available)"); - if (entry.undName[0] != 0) - MyStrCpy(entry.name, STACKWALK_MAX_NAMELEN, entry.undName); - if (entry.undFullName[0] != 0) - MyStrCpy(entry.name, STACKWALK_MAX_NAMELEN, entry.undFullName); - if (entry.lineFileName[0] == 0) - { - MyStrCpy(entry.lineFileName, STACKWALK_MAX_NAMELEN, "(filename not available)"); - if (entry.moduleName[0] == 0) - MyStrCpy(entry.moduleName, STACKWALK_MAX_NAMELEN, "(module-name not available)"); - _snprintf_s(buffer, maxLen, "%p (%s): %s: %s\n", (LPVOID)entry.offset, entry.moduleName, - entry.lineFileName, entry.name); - } - else - _snprintf_s(buffer, maxLen, "%s (%d): %s\n", entry.lineFileName, entry.lineNumber, - entry.name); - buffer[STACKWALK_MAX_NAMELEN - 1] = 0; - OnOutput(buffer); - } -} - -void StackWalker::OnDbgHelpErr(LPCSTR szFuncName, DWORD gle, DWORD64 addr) -{ - CHAR buffer[STACKWALK_MAX_NAMELEN]; - size_t maxLen = STACKWALK_MAX_NAMELEN; -#if _MSC_VER >= 1400 - maxLen = _TRUNCATE; -#endif - _snprintf_s(buffer, maxLen, "ERROR: %s, GetLastError: %d (Address: %p)\n", szFuncName, gle, - (LPVOID)addr); - buffer[STACKWALK_MAX_NAMELEN - 1] = 0; - OnOutput(buffer); -} - -void StackWalker::OnSymInit(LPCSTR szSearchPath, DWORD symOptions, LPCSTR szUserName) -{ - CHAR buffer[STACKWALK_MAX_NAMELEN]; - size_t maxLen = STACKWALK_MAX_NAMELEN; -#if _MSC_VER >= 1400 - maxLen = _TRUNCATE; -#endif - _snprintf_s(buffer, maxLen, "SymInit: Symbol-SearchPath: '%s', symOptions: %d, UserName: '%s'\n", - szSearchPath, symOptions, szUserName); - buffer[STACKWALK_MAX_NAMELEN - 1] = 0; - OnOutput(buffer); - // Also display the OS-version -#if _MSC_VER <= 1200 - OSVERSIONINFOA ver; - ZeroMemory(&ver, sizeof(OSVERSIONINFOA)); - ver.dwOSVersionInfoSize = sizeof(ver); - if (GetVersionExA(&ver) != FALSE) - { - _snprintf_s(buffer, maxLen, "OS-Version: %d.%d.%d (%s)\n", ver.dwMajorVersion, - ver.dwMinorVersion, ver.dwBuildNumber, ver.szCSDVersion); - buffer[STACKWALK_MAX_NAMELEN - 1] = 0; - OnOutput(buffer); - } -#else - OSVERSIONINFOEXA ver; - ZeroMemory(&ver, sizeof(OSVERSIONINFOEXA)); - ver.dwOSVersionInfoSize = sizeof(ver); -#if _MSC_VER >= 1900 -#pragma warning(push) -#pragma warning(disable : 4996) -#endif - if (GetVersionExA((OSVERSIONINFOA*)&ver) != FALSE) - { - _snprintf_s(buffer, maxLen, "OS-Version: %d.%d.%d (%s) 0x%x-0x%x\n", ver.dwMajorVersion, - ver.dwMinorVersion, ver.dwBuildNumber, ver.szCSDVersion, ver.wSuiteMask, - ver.wProductType); - buffer[STACKWALK_MAX_NAMELEN - 1] = 0; - OnOutput(buffer); - } -#if _MSC_VER >= 1900 -#pragma warning(pop) -#endif -#endif -} - -void StackWalker::OnOutput(LPCSTR buffer) -{ - OutputDebugStringA(buffer); -} diff --git a/deps/stackwalker/StackWalker.h b/deps/stackwalker/StackWalker.h deleted file mode 100644 index 0a004d96..00000000 --- a/deps/stackwalker/StackWalker.h +++ /dev/null @@ -1,255 +0,0 @@ -#ifndef __STACKWALKER_H__ -#define __STACKWALKER_H__ - -#if defined(_MSC_VER) - -/********************************************************************** - * - * StackWalker.h - * - * - * - * LICENSE (http://www.opensource.org/licenses/bsd-license.php) - * - * Copyright (c) 2005-2009, Jochen Kalmbach - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * Neither the name of Jochen Kalmbach nor the names of its contributors may be - * used to endorse or promote products derived from this software without - * specific prior written permission. - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * **********************************************************************/ -// #pragma once is supported starting with _MSC_VER 1000, -// so we need not to check the version (because we only support _MSC_VER >= 1100)! -#pragma once - -#include - -#if _MSC_VER >= 1900 -#pragma warning(disable : 4091) -#endif - -// special defines for VC5/6 (if no actual PSDK is installed): -#if _MSC_VER < 1300 -typedef unsigned __int64 DWORD64, *PDWORD64; -#if defined(_WIN64) -typedef unsigned __int64 SIZE_T, *PSIZE_T; -#else -typedef unsigned long SIZE_T, *PSIZE_T; -#endif -#endif // _MSC_VER < 1300 - -class StackWalkerInternal; // forward -class StackWalker -{ -public: - typedef enum StackWalkOptions - { - // No addition info will be retrieved - // (only the address is available) - RetrieveNone = 0, - - // Try to get the symbol-name - RetrieveSymbol = 1, - - // Try to get the line for this symbol - RetrieveLine = 2, - - // Try to retrieve the module-infos - RetrieveModuleInfo = 4, - - // Also retrieve the version for the DLL/EXE - RetrieveFileVersion = 8, - - // Contains all the above - RetrieveVerbose = 0xF, - - // Generate a "good" symbol-search-path - SymBuildPath = 0x10, - - // Also use the public Microsoft-Symbol-Server - SymUseSymSrv = 0x20, - - // Contains all the above "Sym"-options - SymAll = 0x30, - - // Contains all options (default) - OptionsAll = 0x3F - } StackWalkOptions; - - StackWalker(int options = OptionsAll, // 'int' is by design, to combine the enum-flags - LPCSTR szSymPath = NULL, - DWORD dwProcessId = GetCurrentProcessId(), - HANDLE hProcess = GetCurrentProcess()); - StackWalker(DWORD dwProcessId, HANDLE hProcess); - virtual ~StackWalker(); - - typedef BOOL(__stdcall* PReadProcessMemoryRoutine)( - HANDLE hProcess, - DWORD64 qwBaseAddress, - PVOID lpBuffer, - DWORD nSize, - LPDWORD lpNumberOfBytesRead, - LPVOID pUserData // optional data, which was passed in "ShowCallstack" - ); - - BOOL LoadModules(); - - BOOL ShowCallstack( - HANDLE hThread = GetCurrentThread(), - const CONTEXT* context = NULL, - PReadProcessMemoryRoutine readMemoryFunction = NULL, - LPVOID pUserData = NULL // optional to identify some data in the 'readMemoryFunction'-callback - ); - - BOOL ShowObject(LPVOID pObject); - -#if _MSC_VER >= 1300 - // due to some reasons, the "STACKWALK_MAX_NAMELEN" must be declared as "public" - // in older compilers in order to use it... starting with VC7 we can declare it as "protected" -protected: -#endif - enum - { - STACKWALK_MAX_NAMELEN = 1024 - }; // max name length for found symbols - -protected: - // Entry for each Callstack-Entry - typedef struct CallstackEntry - { - DWORD64 offset; // if 0, we have no valid entry - CHAR name[STACKWALK_MAX_NAMELEN]; - CHAR undName[STACKWALK_MAX_NAMELEN]; - CHAR undFullName[STACKWALK_MAX_NAMELEN]; - DWORD64 offsetFromSmybol; - DWORD offsetFromLine; - DWORD lineNumber; - CHAR lineFileName[STACKWALK_MAX_NAMELEN]; - DWORD symType; - LPCSTR symTypeString; - CHAR moduleName[STACKWALK_MAX_NAMELEN]; - DWORD64 baseOfImage; - CHAR loadedImageName[STACKWALK_MAX_NAMELEN]; - } CallstackEntry; - - typedef enum CallstackEntryType - { - firstEntry, - nextEntry, - lastEntry - } CallstackEntryType; - - virtual void OnSymInit(LPCSTR szSearchPath, DWORD symOptions, LPCSTR szUserName); - virtual void OnLoadModule(LPCSTR img, - LPCSTR mod, - DWORD64 baseAddr, - DWORD size, - DWORD result, - LPCSTR symType, - LPCSTR pdbName, - ULONGLONG fileVersion); - virtual void OnCallstackEntry(CallstackEntryType eType, CallstackEntry& entry); - virtual void OnDbgHelpErr(LPCSTR szFuncName, DWORD gle, DWORD64 addr); - virtual void OnOutput(LPCSTR szText); - - StackWalkerInternal* m_sw; - HANDLE m_hProcess; - DWORD m_dwProcessId; - BOOL m_modulesLoaded; - LPSTR m_szSymPath; - - int m_options; - int m_MaxRecursionCount; - - static BOOL __stdcall myReadProcMem(HANDLE hProcess, - DWORD64 qwBaseAddress, - PVOID lpBuffer, - DWORD nSize, - LPDWORD lpNumberOfBytesRead); - - friend StackWalkerInternal; -}; // class StackWalker - -// The "ugly" assembler-implementation is needed for systems before XP -// If you have a new PSDK and you only compile for XP and later, then you can use -// the "RtlCaptureContext" -// Currently there is no define which determines the PSDK-Version... -// So we just use the compiler-version (and assumes that the PSDK is -// the one which was installed by the VS-IDE) - -// INFO: If you want, you can use the RtlCaptureContext if you only target XP and later... -// But I currently use it in x64/IA64 environments... -//#if defined(_M_IX86) && (_WIN32_WINNT <= 0x0500) && (_MSC_VER < 1400) - -#if defined(_M_IX86) -#ifdef CURRENT_THREAD_VIA_EXCEPTION -// TODO: The following is not a "good" implementation, -// because the callstack is only valid in the "__except" block... -#define GET_CURRENT_CONTEXT_STACKWALKER_CODEPLEX(c, contextFlags) \ - do \ - { \ - memset(&c, 0, sizeof(CONTEXT)); \ - EXCEPTION_POINTERS* pExp = NULL; \ - __try \ - { \ - throw 0; \ - } \ - __except (((pExp = GetExceptionInformation()) ? EXCEPTION_EXECUTE_HANDLER \ - : EXCEPTION_EXECUTE_HANDLER)) \ - { \ - } \ - if (pExp != NULL) \ - memcpy(&c, pExp->ContextRecord, sizeof(CONTEXT)); \ - c.ContextFlags = contextFlags; \ - } while (0); -#else -// clang-format off -// The following should be enough for walking the callstack... -#define GET_CURRENT_CONTEXT_STACKWALKER_CODEPLEX(c, contextFlags) \ - do \ - { \ - memset(&c, 0, sizeof(CONTEXT)); \ - c.ContextFlags = contextFlags; \ - __asm call x \ - __asm x: pop eax \ - __asm mov c.Eip, eax \ - __asm mov c.Ebp, ebp \ - __asm mov c.Esp, esp \ - } while (0) -// clang-format on -#endif - -#else - -// The following is defined for x86 (XP and higher), x64 and IA64: -#define GET_CURRENT_CONTEXT_STACKWALKER_CODEPLEX(c, contextFlags) \ - do \ - { \ - memset(&c, 0, sizeof(CONTEXT)); \ - c.ContextFlags = contextFlags; \ - RtlCaptureContext(&c); \ - } while (0); -#endif - -#endif //defined(_MSC_VER) - -#endif // __STACKWALKER_H__ diff --git a/src/common/Util/CrashHandler.cpp b/src/common/Util/CrashHandler.cpp index 462c19ae..065256e5 100644 --- a/src/common/Util/CrashHandler.cpp +++ b/src/common/Util/CrashHandler.cpp @@ -7,18 +7,26 @@ #include #include #else -#include -class SapphireStackWalker : public StackWalker +#include +#include +#include + +#pragma comment(lib, "dbghelp.lib") + +inline std::string basename( const std::string& file ) { -public: - SapphireStackWalker() : StackWalker() {} -protected: - virtual void OnOutput( LPCSTR szText ) - { - Sapphire::Logger::fatal( "{}", szText ); - } -}; + size_t i = file.find_last_of( "\\/" ); + if ( i == std::string::npos ) + { + return file; + } + else + { + return file.substr( i + 1 ); + } +} + #endif using namespace Sapphire::Common; @@ -148,8 +156,74 @@ void Util::CrashHandler::printStackTrace( unsigned int max_frames ) #else - SapphireStackWalker sw; - sw.ShowCallstack(); + DWORD machine = IMAGE_FILE_MACHINE_AMD64; + + HANDLE process = GetCurrentProcess(); + HANDLE thread = GetCurrentThread(); + CONTEXT context = {}; + context.ContextFlags = CONTEXT_FULL; + RtlCaptureContext( &context ); + + SymInitialize( process, NULL, TRUE ); + SymSetOptions( SYMOPT_LOAD_LINES ); + + STACKFRAME frame = {}; + frame.AddrPC.Offset = context.Rip; + frame.AddrPC.Mode = AddrModeFlat; + frame.AddrFrame.Offset = context.Rbp; + frame.AddrFrame.Mode = AddrModeFlat; + frame.AddrStack.Offset = context.Rsp; + frame.AddrStack.Mode = AddrModeFlat; + + while( StackWalk( machine, process, thread, &frame, &context, NULL, SymFunctionTableAccess, SymGetModuleBase, NULL ) ) + { + auto moduleBase = SymGetModuleBase( process, frame.AddrPC.Offset ); + + std::string moduleName; + std::string funcName; + std::string fileName; + int lineNum = 0; + + char moduelBuff[MAX_PATH]; + if( moduleBase && GetModuleFileNameA( ( HINSTANCE ) moduleBase, moduelBuff, MAX_PATH ) ) + { + moduleName = basename( moduelBuff ); + } + else + { + moduleName = "Unknown Module"; + } + + + DWORD64 offset = 0; + char symbolBuffer[sizeof( IMAGEHLP_SYMBOL ) + 255]; + PIMAGEHLP_SYMBOL symbol = ( PIMAGEHLP_SYMBOL ) symbolBuffer; + symbol->SizeOfStruct = ( sizeof IMAGEHLP_SYMBOL ) + 255; + symbol->MaxNameLength = 254; + + if( SymGetSymFromAddr( process, frame.AddrPC.Offset, &offset, symbol ) ) + { + funcName = symbol->Name; + } + else + { + funcName = "Unknown Function"; + } + + IMAGEHLP_LINE line; + line.SizeOfStruct = sizeof( IMAGEHLP_LINE ); + + DWORD offset_ln = 0; + if( SymGetLineFromAddr( process, frame.AddrPC.Offset, &offset_ln, &line ) ) + { + fileName = line.FileName; + lineNum = line.LineNumber; + } + + Logger::fatal( "[{:x}] {}({}): {} ({})", frame.AddrPC.Offset, fileName, lineNum, funcName, moduleName ); + } + + SymCleanup( process ); #endif } \ No newline at end of file diff --git a/src/tools/exd_struct_test/main.cpp b/src/tools/exd_struct_test/main.cpp index 88ad0d46..ff783369 100644 --- a/src/tools/exd_struct_test/main.cpp +++ b/src/tools/exd_struct_test/main.cpp @@ -111,6 +111,8 @@ int main( int argc, char* argv[] ) Logger::init( "struct_test" ); + assert(false); + Logger::info( "Setting up EXD data" ); if( !g_exdData.init( datLocation ) ) { From 2b217a545bd862d41df3e3443d38048e315c7c53 Mon Sep 17 00:00:00 2001 From: NotAdam Date: Mon, 29 Apr 2019 19:59:19 +1000 Subject: [PATCH 032/351] gracefully crash the server if no navmeshes exist with a useful error --- src/world/Manager/TerritoryMgr.cpp | 3 ++- src/world/Territory/Zone.cpp | 6 ++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/world/Manager/TerritoryMgr.cpp b/src/world/Manager/TerritoryMgr.cpp index 87474f17..a43ce775 100644 --- a/src/world/Manager/TerritoryMgr.cpp +++ b/src/world/Manager/TerritoryMgr.cpp @@ -66,8 +66,9 @@ bool Sapphire::World::Manager::TerritoryMgr::init() createDefaultTerritories(); createHousingTerritories(); } - catch( std::runtime_error& ) + catch( const std::runtime_error& ex ) { + Logger::fatal( "Caught exception during territory init: {}", ex.what() ); return false; } diff --git a/src/world/Territory/Zone.cpp b/src/world/Territory/Zone.cpp index c9c2402b..e735c6d1 100644 --- a/src/world/Territory/Zone.cpp +++ b/src/world/Territory/Zone.cpp @@ -136,6 +136,12 @@ bool Sapphire::Zone::init() m_pNaviProvider = pNaviMgr->getNaviProvider( m_territoryTypeInfo->bg ); + if( !m_pNaviProvider ) + { + Logger::fatal( "No navmesh found for TerritoryType#{}", getTerritoryTypeId() ); + throw std::runtime_error( "Missing navmesh file(s)." ); + } + return true; } From 6a20fc32f4d23f999b2200b9a0d9c347571a7d4d Mon Sep 17 00:00:00 2001 From: NotAdam Date: Mon, 29 Apr 2019 20:01:27 +1000 Subject: [PATCH 033/351] remove assert left in for testing --- src/tools/exd_struct_test/main.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/tools/exd_struct_test/main.cpp b/src/tools/exd_struct_test/main.cpp index ff783369..88ad0d46 100644 --- a/src/tools/exd_struct_test/main.cpp +++ b/src/tools/exd_struct_test/main.cpp @@ -111,8 +111,6 @@ int main( int argc, char* argv[] ) Logger::init( "struct_test" ); - assert(false); - Logger::info( "Setting up EXD data" ); if( !g_exdData.init( datLocation ) ) { From 75b7fb4c034c1703668b252ffa0fd2438139238c Mon Sep 17 00:00:00 2001 From: NotAdam Date: Mon, 29 Apr 2019 20:29:50 +1000 Subject: [PATCH 034/351] fix build --- src/common/CMakeLists.txt | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index 0b494d98..88ab338d 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -26,10 +26,6 @@ if( UNIX ) PUBLIC pthread stdc++fs ) -else() - target_link_libraries( common - PUBLIC - stackwalker ) endif() target_include_directories( common From 0bc5d545d50a309703361cbae46d1cf3ff54b6af Mon Sep 17 00:00:00 2001 From: mordred Date: Mon, 29 Apr 2019 15:53:03 +0200 Subject: [PATCH 035/351] Parse more action info from tooltips --- src/tools/action_parse/main.cpp | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/tools/action_parse/main.cpp b/src/tools/action_parse/main.cpp index 74c496c3..01e759e2 100644 --- a/src/tools/action_parse/main.cpp +++ b/src/tools/action_parse/main.cpp @@ -54,7 +54,9 @@ int main() auto gld1 = g_exdData.get< Sapphire::Data::ActionTransient >( id ); if( gld ) { - Logger::info( "got {0}", gld->name ); + if( gld->classJob == -1 || gld->name.empty() ) + continue; + Logger::info( "{0} - {1}", id, gld->name ); std::string desc = gld1->description; stripUnicode( desc );; desc = std::regex_replace( desc, std::regex( "HI" ), "\n" ); @@ -125,7 +127,21 @@ int main() Logger::info( "Combo Potency: {}", potStr); } } + + std::smatch sm5; + std::regex r5(R"(Cure Potency: \d*)"); + if( std::regex_search(desc, sm5, r5 ) ) + { + std::string potStr = sm5.str(); + auto pos = potStr.find_last_of( " " ); + if( pos != std::string::npos ) + { + potStr = potStr.substr( pos + 1 ); + Logger::info( "Cure Potency: {}", potStr); + } + } + Logger::info( "-" ); } else Logger::warn( "failed to get classjob {}", 1 ); From 3f6d7934a5bf3d6e78181fadeaf6c7b555859a1a Mon Sep 17 00:00:00 2001 From: NotAdam Date: Tue, 30 Apr 2019 21:41:10 +1000 Subject: [PATCH 036/351] warn instead of crash with missing navmeshes --- src/common/Logging/Logger.cpp | 2 +- src/world/Actor/BNpc.cpp | 3 +++ src/world/Territory/Zone.cpp | 3 +-- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/common/Logging/Logger.cpp b/src/common/Logging/Logger.cpp index bc063b25..221f9291 100644 --- a/src/common/Logging/Logger.cpp +++ b/src/common/Logging/Logger.cpp @@ -1,6 +1,6 @@ #include "Logger.h" -#define SPDLOG_LEVEL_NAMES { "trace", "debug", "info", "warning", "error", "fatal", "off" } +#define SPDLOG_LEVEL_NAMES { "trace", "debug", "info", "warn", "error", "fatal", "off" } #include #include diff --git a/src/world/Actor/BNpc.cpp b/src/world/Actor/BNpc.cpp index 841ff2b9..57b0a842 100644 --- a/src/world/Actor/BNpc.cpp +++ b/src/world/Actor/BNpc.cpp @@ -401,6 +401,9 @@ void Sapphire::Entity::BNpc::update( uint64_t tickCount ) auto pNaviProvider = m_pCurrentZone->getNaviProvider(); + if( !pNaviProvider ) + return; + switch( m_state ) { case BNpcState::Dead: diff --git a/src/world/Territory/Zone.cpp b/src/world/Territory/Zone.cpp index e735c6d1..339f6399 100644 --- a/src/world/Territory/Zone.cpp +++ b/src/world/Territory/Zone.cpp @@ -138,8 +138,7 @@ bool Sapphire::Zone::init() if( !m_pNaviProvider ) { - Logger::fatal( "No navmesh found for TerritoryType#{}", getTerritoryTypeId() ); - throw std::runtime_error( "Missing navmesh file(s)." ); + Logger::warn( "No navmesh found for TerritoryType#{}", getTerritoryTypeId() ); } return true; From b6863678c8ebc5a94148f9c6392ae8ce9326540f Mon Sep 17 00:00:00 2001 From: Mordred Date: Tue, 30 Apr 2019 22:54:35 +0200 Subject: [PATCH 037/351] Show default hit effect on autoattacks, also send 2nd hate packet --- src/common/Network/PacketDef/Ipcs.h | 2 +- src/common/Network/PacketDef/Zone/ServerZoneDef.h | 11 +++++++++++ src/world/Actor/BNpc.cpp | 1 + src/world/Actor/Chara.cpp | 1 + src/world/Actor/Player.cpp | 10 +++++++++- 5 files changed, 23 insertions(+), 2 deletions(-) diff --git a/src/common/Network/PacketDef/Ipcs.h b/src/common/Network/PacketDef/Ipcs.h index 3c98ae7f..c6fdac98 100644 --- a/src/common/Network/PacketDef/Ipcs.h +++ b/src/common/Network/PacketDef/Ipcs.h @@ -131,7 +131,7 @@ namespace Sapphire::Network::Packets ActorCast = 0x017C, // updated 4.5 PartyList = 0x017E, // updated 4.5 - + HateRank = 0x017F, // updated 4.5 HateList = 0x0180, // updated 4.5 ObjectSpawn = 0x0181, // updated 4.5 ObjectDespawn = 0x0182, // updated 4.5 diff --git a/src/common/Network/PacketDef/Zone/ServerZoneDef.h b/src/common/Network/PacketDef/Zone/ServerZoneDef.h index 924b0912..80588a04 100644 --- a/src/common/Network/PacketDef/Zone/ServerZoneDef.h +++ b/src/common/Network/PacketDef/Zone/ServerZoneDef.h @@ -719,6 +719,17 @@ namespace Sapphire::Network::Packets::Server uint32_t padding; }; + struct FFXIVIpcHateRank : FFXIVIpcBasePacket< HateRank > + { + uint32_t numEntries; + struct + { + uint32_t actorId; + uint32_t hateAmount; + } entry[32]; + uint32_t padding; + }; + struct FFXIVIpcUpdateClassInfo : FFXIVIpcBasePacket< UpdateClassInfo > { uint8_t classId; diff --git a/src/world/Actor/BNpc.cpp b/src/world/Actor/BNpc.cpp index 841ff2b9..03e143c9 100644 --- a/src/world/Actor/BNpc.cpp +++ b/src/world/Actor/BNpc.cpp @@ -689,6 +689,7 @@ void Sapphire::Entity::BNpc::autoAttack( CharaPtr pTarget ) effectEntry.value = damage; effectEntry.effectType = ActionEffectType::Damage; effectEntry.hitSeverity = ActionHitSeverityType::NormalDamage; + effectEntry.param = 0x71; effectPacket->addEffect( effectEntry ); sendToInRangeSet( effectPacket ); diff --git a/src/world/Actor/Chara.cpp b/src/world/Actor/Chara.cpp index b4e9303d..3da8d362 100644 --- a/src/world/Actor/Chara.cpp +++ b/src/world/Actor/Chara.cpp @@ -436,6 +436,7 @@ void Sapphire::Entity::Chara::autoAttack( CharaPtr pTarget ) effectEntry.value = damage; effectEntry.effectType = ActionEffectType::Damage; effectEntry.hitSeverity = ActionHitSeverityType::NormalDamage; + effectEntry.param = 0x71; effectPacket->addEffect( effectEntry ); sendToInRangeSet( effectPacket ); diff --git a/src/world/Actor/Player.cpp b/src/world/Actor/Player.cpp index f6d32053..925f7e11 100644 --- a/src/world/Actor/Player.cpp +++ b/src/world/Actor/Player.cpp @@ -1411,12 +1411,19 @@ void Sapphire::Entity::Player::sendHateList() { auto hateListPacket = makeZonePacket< FFXIVIpcHateList >( getId() ); hateListPacket->data().numEntries = m_actorIdTohateSlotMap.size(); + auto hateRankPacket = makeZonePacket< FFXIVIpcHateRank >( getId() ); + hateRankPacket->data().numEntries = m_actorIdTohateSlotMap.size(); auto it = m_actorIdTohateSlotMap.begin(); for( int32_t i = 0; it != m_actorIdTohateSlotMap.end(); ++it, i++ ) { + // TODO: get actual hate values for these hateListPacket->data().entry[ i ].actorId = it->first; hateListPacket->data().entry[ i ].hatePercent = 100; + + hateRankPacket->data().entry[ i ].actorId = it->first; + hateRankPacket->data().entry[ i ].hateAmount = 1; } + queuePacket( hateRankPacket ); queuePacket( hateListPacket ); } @@ -1571,7 +1578,7 @@ void Sapphire::Entity::Player::autoAttack( CharaPtr pTarget ) entry.value = damage; entry.effectType = Common::ActionEffectType::Damage; entry.hitSeverity = Common::ActionHitSeverityType::NormalDamage; - entry.param = variation; + entry.param = 0x72; effectPacket->addEffect( entry ); @@ -1586,6 +1593,7 @@ void Sapphire::Entity::Player::autoAttack( CharaPtr pTarget ) entry.value = damage; entry.effectType = Common::ActionEffectType::Damage; entry.hitSeverity = Common::ActionHitSeverityType::NormalDamage; + entry.param = 0x73; effectPacket->addEffect( entry ); From 591f57cec2476d67de0cc9bf39d3daac66269dd1 Mon Sep 17 00:00:00 2001 From: NotAdam Date: Tue, 7 May 2019 22:10:55 +1000 Subject: [PATCH 038/351] fix a crash where !instance bind is used incorrectly, better getter name --- src/world/Actor/Player.cpp | 2 +- src/world/Manager/DebugCommandMgr.cpp | 14 ++++++++++---- src/world/Manager/TerritoryMgr.cpp | 6 +++--- src/world/Manager/TerritoryMgr.h | 2 +- src/world/Network/Handlers/GMCommandHandlers.cpp | 2 +- 5 files changed, 16 insertions(+), 10 deletions(-) diff --git a/src/world/Actor/Player.cpp b/src/world/Actor/Player.cpp index 925f7e11..3a96b640 100644 --- a/src/world/Actor/Player.cpp +++ b/src/world/Actor/Player.cpp @@ -430,7 +430,7 @@ bool Sapphire::Entity::Player::setInstance( uint32_t instanceContentId ) m_onEnterEventDone = false; auto pTeriMgr = m_pFw->get< TerritoryMgr >(); - auto instance = pTeriMgr->getInstanceZonePtr( instanceContentId ); + auto instance = pTeriMgr->getTerritoryByGuId( instanceContentId ); if( !instance ) return false; diff --git a/src/world/Manager/DebugCommandMgr.cpp b/src/world/Manager/DebugCommandMgr.cpp index a9687604..f414c1bd 100644 --- a/src/world/Manager/DebugCommandMgr.cpp +++ b/src/world/Manager/DebugCommandMgr.cpp @@ -822,10 +822,16 @@ void Sapphire::World::Manager::DebugCommandMgr::instance( char* data, Entity::Pl uint32_t instanceId; sscanf( params.c_str(), "%d", &instanceId ); - auto instance = pTeriMgr->getInstanceZonePtr( instanceId ); - if( instance ) + auto terri = pTeriMgr->getTerritoryByGuId( instanceId ); + if( terri ) { - auto pInstanceContent = instance->getAsInstanceContent(); + auto pInstanceContent = terri->getAsInstanceContent(); + if( !pInstanceContent ) + { + player.sendDebug( "Instance id#{} is not an InstanceContent territory.", instanceId ); + return; + } + pInstanceContent->bindPlayer( player.getId() ); player.sendDebug( "Now bound to instance with id: " + std::to_string( pInstanceContent->getGuId() ) + @@ -839,7 +845,7 @@ void Sapphire::World::Manager::DebugCommandMgr::instance( char* data, Entity::Pl uint32_t instanceId; sscanf( params.c_str(), "%d", &instanceId ); - auto instance = pTeriMgr->getInstanceZonePtr( instanceId ); + auto instance = pTeriMgr->getTerritoryByGuId( instanceId ); if( !instance ) { player.sendDebug( "Unknown instance with id#{0} ", instanceId ); diff --git a/src/world/Manager/TerritoryMgr.cpp b/src/world/Manager/TerritoryMgr.cpp index a43ce775..6c3d2769 100644 --- a/src/world/Manager/TerritoryMgr.cpp +++ b/src/world/Manager/TerritoryMgr.cpp @@ -436,7 +436,7 @@ Sapphire::ZonePtr Sapphire::World::Manager::TerritoryMgr::findOrCreateHousingInt bool Sapphire::World::Manager::TerritoryMgr::removeTerritoryInstance( uint32_t guId ) { ZonePtr pZone; - if( ( pZone = getInstanceZonePtr( guId ) ) == nullptr ) + if( ( pZone = getTerritoryByGuId( guId ) ) == nullptr ) return false; m_guIdToZonePtrMap.erase( pZone->getGuId() ); @@ -455,7 +455,7 @@ bool Sapphire::World::Manager::TerritoryMgr::removeTerritoryInstance( uint32_t g return true; } -Sapphire::ZonePtr Sapphire::World::Manager::TerritoryMgr::getInstanceZonePtr( uint32_t guId ) const +Sapphire::ZonePtr Sapphire::World::Manager::TerritoryMgr::getTerritoryByGuId( uint32_t guId ) const { auto it = m_guIdToZonePtrMap.find( guId ); if( it == m_guIdToZonePtrMap.end() ) @@ -646,7 +646,7 @@ Sapphire::ZonePtr Sapphire::World::Manager::TerritoryMgr::getLinkedInstance( uin auto it = m_playerIdToInstanceMap.find( playerId ); if( it != m_playerIdToInstanceMap.end() ) { - return getInstanceZonePtr( it->second ); + return getTerritoryByGuId( it->second ); } return nullptr; } diff --git a/src/world/Manager/TerritoryMgr.h b/src/world/Manager/TerritoryMgr.h index b9628756..67b0229b 100644 --- a/src/world/Manager/TerritoryMgr.h +++ b/src/world/Manager/TerritoryMgr.h @@ -116,7 +116,7 @@ namespace Sapphire::World::Manager bool removeTerritoryInstance( uint32_t guId ); /*! returns a ZonePtr to the instance or nullptr if not found */ - ZonePtr getInstanceZonePtr( uint32_t guId ) const; + ZonePtr getTerritoryByGuId( uint32_t guId ) const; /*! returns the cached detail of a territory, nullptr if not found */ Data::TerritoryTypePtr getTerritoryDetail( uint32_t territoryTypeId ) const; diff --git a/src/world/Network/Handlers/GMCommandHandlers.cpp b/src/world/Network/Handlers/GMCommandHandlers.cpp index 4b8fb084..9b806521 100644 --- a/src/world/Network/Handlers/GMCommandHandlers.cpp +++ b/src/world/Network/Handlers/GMCommandHandlers.cpp @@ -465,7 +465,7 @@ void Sapphire::Network::GameConnection::gm1Handler( FrameworkPtr pFw, case GmCommand::Teri: { auto pTeriMgr = pFw->get< TerritoryMgr >(); - if( auto instance = pTeriMgr->getInstanceZonePtr( param1 ) ) + if( auto instance = pTeriMgr->getTerritoryByGuId( param1 ) ) { player.sendDebug( "Found instance: {0}, id#{1}", instance->getName(), param1 ); From 0350b4dc229fd8d5aba7e5a8242fc1d0619c8630 Mon Sep 17 00:00:00 2001 From: NotAdam Date: Tue, 7 May 2019 22:16:18 +1000 Subject: [PATCH 039/351] remove the code restricting ic territories from being created --- src/world/Manager/TerritoryMgr.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/world/Manager/TerritoryMgr.cpp b/src/world/Manager/TerritoryMgr.cpp index 6c3d2769..fb5fd0ca 100644 --- a/src/world/Manager/TerritoryMgr.cpp +++ b/src/world/Manager/TerritoryMgr.cpp @@ -261,8 +261,9 @@ Sapphire::ZonePtr Sapphire::World::Manager::TerritoryMgr::createTerritoryInstanc if( !isValidTerritory( territoryTypeId ) ) return nullptr; - if( isInstanceContentTerritory( territoryTypeId ) ) - return nullptr; +// nb: disabled for now because there's not a real reason to have this constraint, makes testing some stuff easier too +// if( isInstanceContentTerritory( territoryTypeId ) ) +// return nullptr; auto pExdData = framework()->get< Data::ExdDataGenerated >(); auto pTeri = getTerritoryDetail( territoryTypeId ); From 3468a149f43c67980209028c1b7bc4abe8be52b0 Mon Sep 17 00:00:00 2001 From: NotAdam Date: Sat, 11 May 2019 13:16:34 +1000 Subject: [PATCH 040/351] correct autoattack potency calculation, fix attack power calc --- src/world/Actor/Chara.cpp | 9 ++++++++- src/world/Math/CalcStats.cpp | 38 ++++++++++++++++++++++++++++++++++-- src/world/Math/CalcStats.h | 5 ++++- 3 files changed, 48 insertions(+), 4 deletions(-) diff --git a/src/world/Actor/Chara.cpp b/src/world/Actor/Chara.cpp index bb328c33..445eac47 100644 --- a/src/world/Actor/Chara.cpp +++ b/src/world/Actor/Chara.cpp @@ -793,7 +793,14 @@ uint32_t Sapphire::Entity::Chara::getStatValue( Sapphire::Common::BaseParam base case Common::BaseParam::AttackPower: { - // todo: think this is right... not sure + auto primaryStat = getPrimaryStat(); + + // everything else uses str for atk power except for brd/rogue/etc who use dex + if( primaryStat == Common::BaseParam::Dexterity ) + { + return getStatValue( primaryStat ); + } + return getStatValue( Common::BaseParam::Strength ); } diff --git a/src/world/Math/CalcStats.cpp b/src/world/Math/CalcStats.cpp index 1542e2fd..b455b48a 100644 --- a/src/world/Math/CalcStats.cpp +++ b/src/world/Math/CalcStats.cpp @@ -308,6 +308,40 @@ float CalcStats::potency( uint16_t potency ) return potency / 100.f; } +float CalcStats::autoAttackPotency( const Sapphire::Entity::Chara& chara ) +{ + uint32_t aaPotency = AUTO_ATTACK_POTENCY; + + // check if ranged class + switch( chara.getClass() ) + { + case Common::ClassJob::Machinist: + case Common::ClassJob::Bard: + case Common::ClassJob::Archer: + aaPotency = RANGED_AUTO_ATTACK_POTENCY; + + default: + break; + } + + float autoAttackDelay = 2.5f; + // fetch actual auto attack delay if its a player + if( chara.isPlayer() ) + { + // todo: ew + auto pPlayer = const_cast< Entity::Chara& >( chara ).getAsPlayer(); + assert( pPlayer ); + + auto pItem = pPlayer->getEquippedWeapon(); + assert( pItem ); + + autoAttackDelay = pItem->getDelay() / 1000.f; + } + + // factors in f(PTC) in order to not lose precision + return std::floor( aaPotency / 3.f * autoAttackDelay ) / 100.f; +} + float CalcStats::weaponDamage( const Sapphire::Entity::Chara& chara, float weaponDamage ) { const auto& baseStats = chara.getStats(); @@ -491,7 +525,7 @@ float CalcStats::autoAttack( const Sapphire::Entity::Chara& chara ) auto level = chara.getLevel(); auto mainVal = static_cast< float >( levelTable[ level ][ Common::LevelTableEntry::MAIN ] ); - auto innerCalc = std::floor( ( ( mainVal * primaryStatValue( chara ) ) / 1000.f ) + weaponDamage ); + auto innerCalc = std::floor( ( mainVal * primaryStatValue( chara ) / 1000.f ) + weaponDamage ); return std::floor( innerCalc * ( autoAttackDelay / 3.f ) ); } @@ -506,7 +540,7 @@ float CalcStats::calculateAutoAttackDamage( const Sapphire::Entity::Chara& chara // D = ⌊ f(ptc) × f(aa) × f(ap) × f(det) × f(tnc) × traits ⌋ × f(ss) ⌋ × // f(chr) ⌋ × f(dhr) ⌋ × rand[ 0.95, 1.05 ] ⌋ × buff_1 ⌋ × buff... ⌋ - auto pot = potency( AUTO_ATTACK_POTENCY ); + auto pot = autoAttackPotency( chara ); auto aa = autoAttack( chara ); auto ap = getPrimaryAttackPower( chara ); auto det = determination( chara ); diff --git a/src/world/Math/CalcStats.h b/src/world/Math/CalcStats.h index 5f2b4060..92402124 100644 --- a/src/world/Math/CalcStats.h +++ b/src/world/Math/CalcStats.h @@ -10,7 +10,8 @@ namespace Sapphire::Math class CalcStats { public: - static const uint32_t AUTO_ATTACK_POTENCY = 100; + static const uint32_t AUTO_ATTACK_POTENCY = 110; + static const uint32_t RANGED_AUTO_ATTACK_POTENCY = 100; static float calculateBaseStat( const Entity::Chara& chara ); @@ -49,6 +50,8 @@ namespace Sapphire::Math */ static float potency( uint16_t potency ); + static float autoAttackPotency( const Sapphire::Entity::Chara& chara ); + /*! * @brief Weapon damage is the contribution the weapon's damage rating * From 1cab7afe0ecf5cfb36f688ef5d118b6f9e0155be Mon Sep 17 00:00:00 2001 From: NotAdam Date: Tue, 28 May 2019 22:03:55 +1000 Subject: [PATCH 041/351] fix self targeted actions failing target snapshot, fix player being unable to complete chasing shadows --- .../instances/questbattles/ChasingShadows.cpp | 15 +++++++-------- src/world/Action/Action.cpp | 7 +++---- src/world/Territory/QuestBattle.cpp | 2 +- 3 files changed, 11 insertions(+), 13 deletions(-) diff --git a/src/scripts/instances/questbattles/ChasingShadows.cpp b/src/scripts/instances/questbattles/ChasingShadows.cpp index 0c11887e..9923796c 100644 --- a/src/scripts/instances/questbattles/ChasingShadows.cpp +++ b/src/scripts/instances/questbattles/ChasingShadows.cpp @@ -67,6 +67,13 @@ public: return; } + if( instance.getCountEnemyBNpc() == 0 && successCalled == 0 ) + { + instance.setCustomVar( SUCCESS_CALLED, 1 ); + instance.success(); + return; + } + if( !boss || !ida || !papa ) return; @@ -141,14 +148,6 @@ public: a4->hateListAdd( pPlayer, 1 ); a5->hateListAdd( pPlayer, 1 ); } - - if( instance.getCountEnemyBNpc() == 0 && successCalled == 0 ) - { - instance.setCustomVar( SUCCESS_CALLED, 1 ); - instance.success(); - return; - } - } void onEnterTerritory( QuestBattle& instance, Entity::Player& player, uint32_t eventId, uint16_t param1, diff --git a/src/world/Action/Action.cpp b/src/world/Action/Action.cpp index c7c7790f..7f04a63f 100644 --- a/src/world/Action/Action.cpp +++ b/src/world/Action/Action.cpp @@ -491,7 +491,7 @@ bool Sapphire::Action::Action::consumeResources() bool Sapphire::Action::Action::snapshotAffectedActors( std::vector< Entity::CharaPtr >& actors ) { - for( const auto& actor : m_pSource->getInRangeActors() ) + for( const auto& actor : m_pSource->getInRangeActors( true ) ) { // check for initial target validity based on flags in action exd (pc/enemy/etc.) if( !preFilterActor( *actor ) ) @@ -515,9 +515,8 @@ bool Sapphire::Action::Action::snapshotAffectedActors( std::vector< Entity::Char player->sendDebug( "hit actor#{}", actor->getId() ); } } - if( actors.empty() ) - return false; - return true; + + return !actors.empty(); } void Sapphire::Action::Action::addActorFilter( World::Util::ActorFilterPtr filter ) diff --git a/src/world/Territory/QuestBattle.cpp b/src/world/Territory/QuestBattle.cpp index 39d0f821..0227bbcd 100644 --- a/src/world/Territory/QuestBattle.cpp +++ b/src/world/Territory/QuestBattle.cpp @@ -385,7 +385,7 @@ uint32_t Sapphire::QuestBattle::getQuestId() const uint32_t Sapphire::QuestBattle::getCountEnemyBNpc() { uint32_t count = 0; - for( auto bnpcIt : m_bNpcMap ) + for( const auto& bnpcIt : m_bNpcMap ) { if( bnpcIt.second->getEnemyType() == 4 && bnpcIt.second->isAlive() ) count++; From 4535c36def6ca490e8b6844d221a6b902ef423fd Mon Sep 17 00:00:00 2001 From: NotAdam Date: Tue, 28 May 2019 22:30:47 +1000 Subject: [PATCH 042/351] if the 'boss' is killed instantly, spawn all add phases instantly no mercy for //gm kill --- .../instances/questbattles/ChasingShadows.cpp | 26 +++++++++++-------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/src/scripts/instances/questbattles/ChasingShadows.cpp b/src/scripts/instances/questbattles/ChasingShadows.cpp index 9923796c..336cd0d6 100644 --- a/src/scripts/instances/questbattles/ChasingShadows.cpp +++ b/src/scripts/instances/questbattles/ChasingShadows.cpp @@ -61,23 +61,20 @@ public: auto papa = instance.getActiveBNpcByLevelId( INIT_P_POP_PAPARIMO ); auto pPlayer = instance.getPlayerPtr(); + uint32_t bossHpPercent = 0; + if( boss ) + bossHpPercent = boss->getHpPercent(); + if( pPlayer && !pPlayer->isAlive() ) { instance.fail(); return; } - if( instance.getCountEnemyBNpc() == 0 && successCalled == 0 ) - { - instance.setCustomVar( SUCCESS_CALLED, 1 ); - instance.success(); - return; - } - - if( !boss || !ida || !papa ) + if( !ida || !papa ) return; - if( pair1Spawnd == 0 && boss->getHpPercent() <= 75 ) + if( pair1Spawnd == 0 && bossHpPercent <= 75 ) { instance.setCustomVar( SET_1_SPAWNED, 1 ); auto a2 = instance.createBNpcFromLevelEntry( INIT_POP_ENEMY_B_03, 10, 0, 1440, 938, @@ -105,7 +102,7 @@ public: a5->hateListAdd( pPlayer, 1 ); } - if( pair2Spawnd == 0 && boss->getHpPercent() <= 50 ) + if( pair2Spawnd == 0 && bossHpPercent <= 50 ) { instance.setCustomVar( SET_2_SPAWNED, 1 ); auto a2 = instance.createBNpcFromLevelEntry( INIT_POP_ENEMY_B_05, 10, 0, 1440, 938, @@ -133,7 +130,7 @@ public: } - if( pair3Spawnd == 0 && boss->getHpPercent() <= 25 ) + if( pair3Spawnd == 0 && bossHpPercent <= 25 ) { instance.setCustomVar( SET_3_SPAWNED, 1 ); @@ -148,6 +145,13 @@ public: a4->hateListAdd( pPlayer, 1 ); a5->hateListAdd( pPlayer, 1 ); } + + if( instance.getCountEnemyBNpc() == 0 && successCalled == 0 ) + { + instance.setCustomVar( SUCCESS_CALLED, 1 ); + instance.success(); + return; + } } void onEnterTerritory( QuestBattle& instance, Entity::Player& player, uint32_t eventId, uint16_t param1, From 81fb7ad247828b46e62579131db8a11cc3bdda31 Mon Sep 17 00:00:00 2001 From: NotAdam Date: Thu, 30 May 2019 01:50:34 +1000 Subject: [PATCH 043/351] action_parse improvements --- src/tools/action_parse/main.cpp | 286 +++++++++++++++++++++----------- 1 file changed, 190 insertions(+), 96 deletions(-) diff --git a/src/tools/action_parse/main.cpp b/src/tools/action_parse/main.cpp index 01e759e2..30eef883 100644 --- a/src/tools/action_parse/main.cpp +++ b/src/tools/action_parse/main.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include @@ -23,16 +24,45 @@ using namespace Sapphire; const std::string datLocation( "/home/mordred/sqpack" ); //const std::string datLocation( "/mnt/c/Program Files (x86)/Steam/steamapps/common/FINAL FANTASY XIV Online/game/sqpack" ); -bool invalidChar( char c ) -{ - return !( c >= 0 && c < 128 ); -} -void stripUnicode( std::string& str ) -{ - str.erase( std::remove_if( str.begin(), str.end(), invalidChar ), str.end() ); - str.erase(std::remove_if(str.begin(), str.end(), - [](char c) { return !std::isalpha(c) && !std::isdigit(c) && !std::isspace(c) && !std::ispunct(c); }), - str.end()); +struct ActionEntry +{ + uint32_t id; + std::string name; + uint32_t potency; + uint32_t comboPotency; + uint32_t flankPotency; + uint32_t frontPotency; + uint32_t rearPotency; + uint32_t curePotency; + uint32_t restorePercentage; +}; + +bool invalidChar( char c ) +{ + return !( c >= 0 && c < 128 ); +} + +void stripUnicode( std::string& str ) +{ + str.erase( std::remove_if( str.begin(), str.end(), invalidChar ), str.end() ); + str.erase( std::remove_if( str.begin(), str.end(), + []( char c ) + { + return !std::isalpha( c ) && !std::isdigit( c ) && !std::isspace( c ) && + !std::ispunct( c ); + } ), + str.end() ); +} + +uint32_t stripNonNumerics( std::string& str ) +{ + str.erase( std::remove_if( str.begin(), str.end(), + []( char c ) + { + return !std::isdigit( c ); + }), str.end() ); + + return std::atoi( str.c_str() ); } int main() @@ -48,103 +78,167 @@ int main() } auto idList = g_exdData.getActionIdList(); + std::unordered_map< uint32_t, ActionEntry > actions; + + auto total = idList.size(); + int cursor = 0; + for( auto id : idList ) { - auto gld = g_exdData.get< Sapphire::Data::Action >( id ); - auto gld1 = g_exdData.get< Sapphire::Data::ActionTransient >( id ); - if( gld ) - { - if( gld->classJob == -1 || gld->name.empty() ) - continue; - Logger::info( "{0} - {1}", id, gld->name ); - std::string desc = gld1->description; - stripUnicode( desc );; - desc = std::regex_replace( desc, std::regex( "HI" ), "\n" ); - desc = std::regex_replace( desc, std::regex( "IH" ), "" ); + auto done = ( cursor++ / static_cast< float >( total ) ) * 100.f; + if( cursor % 50 == 0 && cursor > 0 ) + Logger::info( "Processing {} actions of {} ({:.2f}%)", cursor, total, done ); + + auto action = g_exdData.get< Sapphire::Data::Action >( id ); + auto actionTransient = g_exdData.get< Sapphire::Data::ActionTransient >( id ); + if( action ) + { + if( action->classJob == -1 || action->name.empty() ) + continue; + + if( action->isPvP ) + continue; + + auto classJob = g_exdData.get< Sapphire::Data::ClassJob >( action->classJob ); + if( !classJob ) + continue; + + // exclude dol/doh + if( classJob->classJobCategory == 32 || classJob->classJobCategory == 33 ) + continue; + + auto ac = static_cast< Common::ActionCategory >( action->actionCategory ); + if( ac != Common::ActionCategory::Ability && + ac != Common::ActionCategory::Autoattack && + ac != Common::ActionCategory::Spell && + ac != Common::ActionCategory::Weaponskill && + ac != Common::ActionCategory::LimitBreak ) + continue; + + ActionEntry entry{}; + + entry.name = action->name; + entry.id = id; + + Logger::info( " {0} - {1}", id, action->name ); + std::string desc = actionTransient->description; + stripUnicode( desc ); + desc = std::regex_replace( desc, std::regex( "HI" ), "\n" ); + desc = std::regex_replace( desc, std::regex( "IH" ), "" ); // Logger::info( "got {0}", desc ); - - std::smatch sm; - std::regex r(R"(with a potency of \d*)"); - if( std::regex_search(desc, sm, r ) ) - { - std::string potStr = sm.str(); - auto pos = potStr.find_last_of( " " ); - if( pos != std::string::npos ) - { - potStr = potStr.substr( pos + 1 ); - Logger::info( "Base Potency: {}", potStr); - } - } - - std::smatch sm1; - std::regex r1(R"(\d* when executed from a target's rear)"); - if( std::regex_search(desc, sm1, r1 ) ) - { - std::string potStr = sm1.str(); - auto pos = potStr.find_first_of( " " ); - if( pos != std::string::npos ) - { - potStr = potStr.substr( 0, pos ); - Logger::info( "Rear Potency: {}", potStr); - } - } - std::smatch sm2; - std::regex r2(R"(\d* when executed from a target's flank)"); - if( std::regex_search(desc, sm2, r2 ) ) - { - std::string potStr = sm2.str(); - auto pos = potStr.find_first_of( " " ); - if( pos != std::string::npos ) + std::smatch sm; + std::regex r( R"(with a potency of [\d,]*)" ); + if( std::regex_search( desc, sm, r ) ) { - potStr = potStr.substr( 0, pos ); - Logger::info( "Flank Potency: {}", potStr); + std::string potStr = sm.str(); + auto pos = potStr.find_last_of( " " ); + if( pos != std::string::npos ) + { + potStr = potStr.substr( pos + 1 ); +// Logger::info( "Base Potency: {}", potStr ); + entry.potency = stripNonNumerics( potStr ); + } } - } - std::smatch sm3; - std::regex r3(R"(\d* when executed in front of target)"); - if( std::regex_search(desc, sm3, r3 ) ) - { - std::string potStr = sm3.str(); - auto pos = potStr.find_first_of( " " ); - if( pos != std::string::npos ) + std::smatch sm1; + std::regex r1( R"([\d,]* when executed from a target's rear)" ); + if( std::regex_search( desc, sm1, r1 ) ) { - potStr = potStr.substr( 0, pos ); - Logger::info( "Frontal Potency: {}", potStr); + std::string potStr = sm1.str(); + auto pos = potStr.find_first_of( " " ); + if( pos != std::string::npos ) + { + potStr = potStr.substr( 0, pos ); +// Logger::info( "Rear Potency: {}", potStr ); + entry.rearPotency = stripNonNumerics( potStr ); + } } - } - - std::smatch sm4; - std::regex r4(R"(Combo Potency: \d*)"); - if( std::regex_search(desc, sm4, r4 ) ) - { - std::string potStr = sm4.str(); - auto pos = potStr.find_last_of( " " ); - if( pos != std::string::npos ) - { - potStr = potStr.substr( pos + 1 ); - Logger::info( "Combo Potency: {}", potStr); - } - } - - std::smatch sm5; - std::regex r5(R"(Cure Potency: \d*)"); - if( std::regex_search(desc, sm5, r5 ) ) - { - std::string potStr = sm5.str(); - auto pos = potStr.find_last_of( " " ); - if( pos != std::string::npos ) - { - potStr = potStr.substr( pos + 1 ); - Logger::info( "Cure Potency: {}", potStr); - } - } - Logger::info( "-" ); + std::smatch sm2; + std::regex r2( R"([\d,]* when executed from a target's flank)" ); + if( std::regex_search( desc, sm2, r2 ) ) + { + std::string potStr = sm2.str(); + auto pos = potStr.find_first_of( " " ); + if( pos != std::string::npos ) + { + potStr = potStr.substr( 0, pos ); +// Logger::info( "Flank Potency: {}", potStr ); + entry.flankPotency = stripNonNumerics( potStr ); + } + } + + std::smatch sm3; + std::regex r3( R"([\d,]* when executed in front of target)" ); + if( std::regex_search( desc, sm3, r3 ) ) + { + std::string potStr = sm3.str(); + auto pos = potStr.find_first_of( " " ); + if( pos != std::string::npos ) + { + potStr = potStr.substr( 0, pos ); +// Logger::info( "Frontal Potency: {}", potStr ); + entry.frontPotency = stripNonNumerics( potStr ); + } + } + + std::smatch sm4; + std::regex r4( R"(Combo Potency: [\d,]*)" ); + if( std::regex_search( desc, sm4, r4 ) ) + { + std::string potStr = sm4.str(); + auto pos = potStr.find_last_of( " " ); + if( pos != std::string::npos ) + { + potStr = potStr.substr( pos + 1 ); +// Logger::info( "Combo Potency: {}", potStr ); + entry.comboPotency = stripNonNumerics( potStr ); + } + } + + std::smatch sm5; + std::regex r5( R"(Cure Potency: [\d,]*)" ); + if( std::regex_search( desc, sm5, r5 ) ) + { + std::string potStr = sm5.str(); + auto pos = potStr.find_last_of( " " ); + if( pos != std::string::npos ) + { + potStr = potStr.substr( pos + 1 ); +// Logger::info( "Cure Potency: {}", potStr ); + entry.curePotency = stripNonNumerics( potStr ); + } + } + + std::smatch sm6; + std::regex r6( R"(Restores \d*%)" ); + if( std::regex_search( desc, sm6, r6 ) ) + { + std::string resStr = sm6.str(); + auto pos = resStr.find_last_of( " " ); + if( pos != std::string::npos ) + { + resStr = resStr.substr( pos + 1 ); +// Logger::info( "Cure Percentage: {}", resStr ); + entry.restorePercentage = stripNonNumerics( resStr ); + } + } + + actions[ id ] = std::move( entry ); + } + else + Logger::warn( "failed to get classjob {}", 1 ); } - else - Logger::warn( "failed to get classjob {}", 1 ); + + // dump entries + Logger::info( "Found {} player actions", actions.size() ); + for( const auto& action : actions ) + { + const auto& data = action.second; + Logger::info( " - {:<5} {:<25} pot: {:<4} flank pot: {:<4} front pot: {:<4} rear pot: {:<4} cure pot: {:<4} restore %: {:<4}", + action.first, data.name, data.potency, data.flankPotency, data.frontPotency, data.rearPotency, + data.curePotency, data.restorePercentage ); } return 0; From cd09f72a5bcc404373c7905eb9cb73b24e34c842 Mon Sep 17 00:00:00 2001 From: NotAdam Date: Thu, 30 May 2019 15:35:05 +1000 Subject: [PATCH 044/351] action lut generation --- src/tools/action_parse/ActionLut.cpp.tmpl | 8 + src/tools/action_parse/main.cpp | 35 +- src/world/Action/ActionLut.cpp | 1120 +++++++++++++++++++++ src/world/Action/ActionLut.h | 28 + 4 files changed, 1187 insertions(+), 4 deletions(-) create mode 100644 src/tools/action_parse/ActionLut.cpp.tmpl create mode 100644 src/world/Action/ActionLut.cpp create mode 100644 src/world/Action/ActionLut.h diff --git a/src/tools/action_parse/ActionLut.cpp.tmpl b/src/tools/action_parse/ActionLut.cpp.tmpl new file mode 100644 index 00000000..469b81be --- /dev/null +++ b/src/tools/action_parse/ActionLut.cpp.tmpl @@ -0,0 +1,8 @@ +#include "ActionData.h" + +using namespace Sapphire::World::Action; + +ActionData::ActionLut ActionData::m_actionLut = +{ +%INSERT_GARBAGE% +}; \ No newline at end of file diff --git a/src/tools/action_parse/main.cpp b/src/tools/action_parse/main.cpp index 30eef883..c48194d3 100644 --- a/src/tools/action_parse/main.cpp +++ b/src/tools/action_parse/main.cpp @@ -17,8 +17,12 @@ #include #include +#include + Sapphire::Data::ExdDataGenerated g_exdData; +namespace fs = std::experimental::filesystem; + using namespace Sapphire; const std::string datLocation( "/home/mordred/sqpack" ); @@ -70,6 +74,9 @@ int main() Logger::init( "action_parse" ); + if( !fs::exists( "ActionLut.cpp.tmpl" ) ) + throw std::runtime_error( "ActionLut.cpp.tmpl is missing in working directory" ); + Logger::info( "Setting up EXD data" ); if( !g_exdData.init( datLocation ) ) { @@ -78,7 +85,7 @@ int main() } auto idList = g_exdData.getActionIdList(); - std::unordered_map< uint32_t, ActionEntry > actions; + std::map< uint32_t, ActionEntry > actions; auto total = idList.size(); int cursor = 0; @@ -233,13 +240,33 @@ int main() // dump entries Logger::info( "Found {} player actions", actions.size() ); + + std::string output; for( const auto& action : actions ) { const auto& data = action.second; - Logger::info( " - {:<5} {:<25} pot: {:<4} flank pot: {:<4} front pot: {:<4} rear pot: {:<4} cure pot: {:<4} restore %: {:<4}", - action.first, data.name, data.potency, data.flankPotency, data.frontPotency, data.rearPotency, - data.curePotency, data.restorePercentage ); +// Logger::info( " - {:<5} {:<25} pot: {:<4} flank pot: {:<4} front pot: {:<4} rear pot: {:<4} cure pot: {:<4} restore %: {:<4}", +// action.first, data.name, data.potency, data.flankPotency, data.frontPotency, data.rearPotency, +// data.curePotency, data.restorePercentage ); + + auto out = fmt::format( " // {}\n {{ {}, {{ {}, {}, {}, {}, {} }} }},\n", + data.name, action.first, + data.potency, data.flankPotency, data.frontPotency, data.rearPotency, data.curePotency ); + + output += out; +// Logger::info( out ); } + std::ifstream ifs( "ActionLut.cpp.tmpl" ); + + std::string actionTmpl( ( std::istreambuf_iterator< char >( ifs ) ), + std::istreambuf_iterator< char >() ); + + auto result = std::regex_replace( actionTmpl, std::regex( "%INSERT_GARBAGE%" ), output ); + + std::ofstream outH( "ActionLut.cpp" ); + outH << result; + outH.close(); + return 0; } diff --git a/src/world/Action/ActionLut.cpp b/src/world/Action/ActionLut.cpp new file mode 100644 index 00000000..1e9c1f97 --- /dev/null +++ b/src/world/Action/ActionLut.cpp @@ -0,0 +1,1120 @@ +#include "ActionLut.h" + +using namespace Sapphire::World::Action; + +ActionLut::Lut ActionLut::m_actionLut = +{ + // attack + { 7, { 0, 0, 0, 0, 0 } }, + // Shot + { 8, { 0, 0, 0, 0, 0 } }, + // Fast Blade + { 9, { 160, 0, 0, 0, 0 } }, + // Savage Blade + { 11, { 100, 0, 0, 0, 0 } }, + // Flash + { 14, { 0, 0, 0, 0, 0 } }, + // Riot Blade + { 15, { 100, 0, 0, 0, 0 } }, + // Shield Bash + { 16, { 110, 0, 0, 0, 0 } }, + // Sentinel + { 17, { 0, 0, 0, 0, 0 } }, + // Tempered Will + { 19, { 0, 0, 0, 0, 0 } }, + // Fight or Flight + { 20, { 0, 0, 0, 0, 0 } }, + // Rage of Halone + { 21, { 100, 0, 0, 0, 0 } }, + // Bulwark + { 22, { 0, 0, 0, 0, 0 } }, + // Circle of Scorn + { 23, { 100, 0, 0, 0, 0 } }, + // Shield Lob + { 24, { 120, 0, 0, 0, 0 } }, + // Shield Swipe + { 25, { 100, 0, 0, 0, 0 } }, + // Sword Oath + { 26, { 75, 0, 0, 0, 0 } }, + // Cover + { 27, { 0, 0, 0, 0, 0 } }, + // Shield Oath + { 28, { 0, 0, 0, 0, 0 } }, + // Spirits Within + { 29, { 300, 0, 0, 0, 0 } }, + // Hallowed Ground + { 30, { 0, 0, 0, 0, 0 } }, + // Heavy Swing + { 31, { 160, 0, 0, 0, 0 } }, + // Skull Sunder + { 35, { 100, 0, 0, 0, 0 } }, + // Maim + { 37, { 100, 0, 0, 0, 0 } }, + // Berserk + { 38, { 0, 0, 0, 0, 0 } }, + // Thrill of Battle + { 40, { 0, 0, 0, 0, 0 } }, + // Overpower + { 41, { 130, 0, 0, 0, 0 } }, + // Storm's Path + { 42, { 100, 0, 0, 0, 0 } }, + // Holmgang + { 43, { 0, 0, 0, 0, 0 } }, + // Vengeance + { 44, { 55, 0, 0, 0, 0 } }, + // Storm's Eye + { 45, { 100, 0, 0, 0, 0 } }, + // Tomahawk + { 46, { 140, 0, 0, 0, 0 } }, + // Butcher's Block + { 47, { 100, 0, 0, 0, 0 } }, + // Defiance + { 48, { 0, 0, 0, 0, 0 } }, + // Inner Beast + { 49, { 350, 0, 0, 0, 0 } }, + // Unchained + { 50, { 0, 0, 0, 0, 0 } }, + // Steel Cyclone + { 51, { 200, 0, 0, 0, 0 } }, + // Infuriate + { 52, { 0, 0, 0, 0, 0 } }, + // Bootshine + { 53, { 140, 0, 0, 0, 0 } }, + // True Strike + { 54, { 160, 0, 0, 180, 0 } }, + // Snap Punch + { 56, { 150, 170, 0, 0, 0 } }, + // Internal Release + { 59, { 0, 0, 0, 0, 0 } }, + // Fists of Earth + { 60, { 0, 0, 0, 0, 0 } }, + // Twin Snakes + { 61, { 110, 130, 0, 0, 0 } }, + // Arm of the Destroyer + { 62, { 50, 0, 0, 0, 0 } }, + // Fists of Fire + { 63, { 0, 0, 0, 0, 0 } }, + // Steel Peak + { 64, { 150, 0, 0, 0, 0 } }, + // Mantra + { 65, { 0, 0, 0, 0, 0 } }, + // Demolish + { 66, { 50, 0, 0, 70, 0 } }, + // Howling Fist + { 67, { 210, 0, 0, 0, 0 } }, + // Perfect Balance + { 69, { 0, 0, 0, 0, 0 } }, + // Rockbreaker + { 70, { 130, 0, 0, 0, 0 } }, + // Shoulder Tackle + { 71, { 100, 0, 0, 0, 0 } }, + // One Ilm Punch + { 72, { 120, 0, 0, 0, 0 } }, + // Fists of Wind + { 73, { 0, 0, 0, 0, 0 } }, + // Dragon Kick + { 74, { 120, 140, 0, 0, 0 } }, + // True Thrust + { 75, { 160, 0, 0, 0, 0 } }, + // Vorpal Thrust + { 78, { 100, 0, 0, 0, 0 } }, + // Heavy Thrust + { 79, { 150, 190, 0, 0, 0 } }, + // Impulse Drive + { 81, { 200, 0, 0, 0, 0 } }, + // Life Surge + { 83, { 0, 0, 0, 0, 0 } }, + // Full Thrust + { 84, { 100, 0, 0, 0, 0 } }, + // Blood for Blood + { 85, { 0, 0, 0, 0, 0 } }, + // Doom Spike + { 86, { 140, 0, 0, 0, 0 } }, + // Disembowel + { 87, { 100, 0, 0, 0, 0 } }, + // Chaos Thrust + { 88, { 100, 0, 0, 140, 0 } }, + // Piercing Talon + { 90, { 120, 0, 0, 0, 0 } }, + // Jump + { 92, { 260, 0, 0, 0, 0 } }, + // Elusive Jump + { 94, { 0, 0, 0, 0, 0 } }, + // Spineshatter Dive + { 95, { 210, 0, 0, 0, 0 } }, + // Dragonfire Dive + { 96, { 320, 0, 0, 0, 0 } }, + // Heavy Shot + { 97, { 150, 0, 0, 0, 0 } }, + // Straight Shot + { 98, { 140, 0, 0, 0, 0 } }, + // Venomous Bite + { 100, { 100, 0, 0, 0, 0 } }, + // Raging Strikes + { 101, { 0, 0, 0, 0, 0 } }, + // Misery's End + { 103, { 190, 0, 0, 0, 0 } }, + // Quick Nock + { 106, { 110, 0, 0, 0, 0 } }, + // Barrage + { 107, { 0, 0, 0, 0, 0 } }, + // Bloodletter + { 110, { 130, 0, 0, 0, 0 } }, + // Repelling Shot + { 112, { 0, 0, 0, 0, 0 } }, + // Windbite + { 113, { 60, 0, 0, 0, 0 } }, + // Mage's Ballad + { 114, { 100, 0, 0, 0, 0 } }, + // Foe Requiem + { 115, { 0, 0, 0, 0, 0 } }, + // Army's Paeon + { 116, { 100, 0, 0, 0, 0 } }, + // Rain of Death + { 117, { 100, 0, 0, 0, 0 } }, + // Battle Voice + { 118, { 0, 0, 0, 0, 0 } }, + // Stone + { 119, { 140, 0, 0, 0, 0 } }, + // Cure + { 120, { 0, 0, 0, 0, 450 } }, + // Aero + { 121, { 50, 0, 0, 0, 0 } }, + // Medica + { 124, { 0, 0, 0, 0, 300 } }, + // Raise + { 125, { 0, 0, 0, 0, 0 } }, + // Stone II + { 127, { 200, 0, 0, 0, 0 } }, + // Repose + { 128, { 0, 0, 0, 0, 0 } }, + // Cure III + { 131, { 0, 0, 0, 0, 550 } }, + // Aero II + { 132, { 50, 0, 0, 0, 0 } }, + // Medica II + { 133, { 0, 0, 0, 0, 200 } }, + // Fluid Aura + { 134, { 0, 0, 0, 0, 0 } }, + // Cure II + { 135, { 0, 0, 0, 0, 700 } }, + // Presence of Mind + { 136, { 0, 0, 0, 0, 0 } }, + // Regen + { 137, { 0, 0, 0, 0, 150 } }, + // Holy + { 139, { 200, 0, 0, 0, 0 } }, + // Benediction + { 140, { 0, 0, 0, 0, 0 } }, + // Fire + { 141, { 180, 0, 0, 0, 0 } }, + // Blizzard + { 142, { 180, 0, 0, 0, 0 } }, + // Thunder + { 144, { 30, 0, 0, 0, 0 } }, + // Sleep + { 145, { 0, 0, 0, 0, 0 } }, + // Blizzard II + { 146, { 50, 0, 0, 0, 0 } }, + // Fire II + { 147, { 80, 0, 0, 0, 0 } }, + // Transpose + { 149, { 0, 0, 0, 0, 0 } }, + // Fire III + { 152, { 240, 0, 0, 0, 0 } }, + // Thunder III + { 153, { 70, 0, 0, 0, 0 } }, + // Blizzard III + { 154, { 240, 0, 0, 0, 0 } }, + // Aetherial Manipulation + { 155, { 0, 0, 0, 0, 0 } }, + // Scathe + { 156, { 100, 0, 0, 0, 0 } }, + // Manaward + { 157, { 0, 0, 0, 0, 0 } }, + // Convert + { 158, { 0, 0, 0, 0, 0 } }, + // Freeze + { 159, { 100, 0, 0, 0, 0 } }, + // Flare + { 162, { 260, 0, 0, 0, 0 } }, + // Ruin + { 163, { 100, 0, 0, 0, 0 } }, + // Bio + { 164, { 0, 0, 0, 0, 0 } }, + // Summon + { 165, { 0, 0, 0, 0, 0 } }, + // Aetherflow + { 166, { 0, 0, 0, 0, 0 } }, + // Energy Drain + { 167, { 150, 0, 0, 0, 0 } }, + // Miasma + { 168, { 20, 0, 0, 0, 0 } }, + // Summon II + { 170, { 0, 0, 0, 0, 0 } }, + // Sustain + { 171, { 0, 0, 0, 0, 0 } }, + // Ruin II + { 172, { 100, 0, 0, 0, 0 } }, + // Resurrection + { 173, { 0, 0, 0, 0, 0 } }, + // Bane + { 174, { 0, 0, 0, 0, 0 } }, + // Rouse + { 176, { 0, 0, 0, 0, 0 } }, + // Miasma II + { 177, { 100, 0, 0, 0, 0 } }, + // Bio II + { 178, { 0, 0, 0, 0, 0 } }, + // Shadow Flare + { 179, { 50, 0, 0, 0, 0 } }, + // Summon III + { 180, { 0, 0, 0, 0, 0 } }, + // Fester + { 181, { 150, 0, 0, 0, 0 } }, + // Tri-bind + { 182, { 30, 0, 0, 0, 0 } }, + // Enkindle + { 184, { 0, 0, 0, 0, 0 } }, + // Adloquium + { 185, { 0, 0, 0, 0, 300 } }, + // Succor + { 186, { 0, 0, 0, 0, 150 } }, + // Sacred Soil + { 188, { 0, 0, 0, 0, 0 } }, + // Lustrate + { 189, { 0, 0, 0, 0, 600 } }, + // Physick + { 190, { 0, 0, 0, 0, 400 } }, + // Shield Wall + { 197, { 0, 0, 0, 0, 0 } }, + // Stronghold + { 198, { 0, 0, 0, 0, 0 } }, + // Last Bastion + { 199, { 0, 0, 0, 0, 0 } }, + // Braver + { 200, { 2400, 0, 0, 0, 0 } }, + // Bladedance + { 201, { 5250, 0, 0, 0, 0 } }, + // Final Heaven + { 202, { 9000, 0, 0, 0, 0 } }, + // Skyshard + { 203, { 1650, 0, 0, 0, 0 } }, + // Starstorm + { 204, { 3600, 0, 0, 0, 0 } }, + // Meteor + { 205, { 6150, 0, 0, 0, 0 } }, + // Healing Wind + { 206, { 0, 0, 0, 0, 0 } }, + // Breath of the Earth + { 207, { 0, 0, 0, 0, 0 } }, + // Pulse of Life + { 208, { 0, 0, 0, 0, 0 } }, + // Magitek Cannon + { 1128, { 0, 0, 0, 0, 0 } }, + // Photon Stream + { 1129, { 0, 0, 0, 0, 0 } }, + // attack + { 1533, { 0, 0, 0, 0, 0 } }, + // Spinning Edge + { 2240, { 150, 0, 0, 0, 0 } }, + // Shade Shift + { 2241, { 0, 0, 0, 0, 0 } }, + // Gust Slash + { 2242, { 100, 0, 0, 0, 0 } }, + // Hide + { 2245, { 0, 0, 0, 0, 0 } }, + // Assassinate + { 2246, { 200, 0, 0, 0, 0 } }, + // Throwing Dagger + { 2247, { 120, 0, 0, 0, 0 } }, + // Mug + { 2248, { 140, 0, 0, 0, 0 } }, + // Hide + { 2253, { 0, 0, 0, 0, 0 } }, + // Death Blossom + { 2254, { 110, 0, 0, 0, 0 } }, + // Aeolian Edge + { 2255, { 100, 0, 0, 160, 0 } }, + // Jugulate + { 2256, { 80, 0, 0, 0, 0 } }, + // Shadow Fang + { 2257, { 100, 0, 0, 0, 0 } }, + // Trick Attack + { 2258, { 240, 0, 0, 400, 0 } }, + // Ten + { 2259, { 0, 0, 0, 0, 0 } }, + // Ninjutsu + { 2260, { 0, 0, 0, 0, 0 } }, + // Chi + { 2261, { 0, 0, 0, 0, 0 } }, + // Shukuchi + { 2262, { 0, 0, 0, 0, 0 } }, + // Jin + { 2263, { 0, 0, 0, 0, 0 } }, + // Kassatsu + { 2264, { 0, 0, 0, 0, 0 } }, + // Fuma Shuriken + { 2265, { 240, 0, 0, 0, 0 } }, + // Katon + { 2266, { 250, 0, 0, 0, 0 } }, + // Raiton + { 2267, { 360, 0, 0, 0, 0 } }, + // Hyoton + { 2268, { 140, 0, 0, 0, 0 } }, + // Huton + { 2269, { 0, 0, 0, 0, 0 } }, + // Doton + { 2270, { 45, 0, 0, 0, 0 } }, + // Suiton + { 2271, { 180, 0, 0, 0, 0 } }, + // Rabbit Medium + { 2272, { 0, 0, 0, 0, 0 } }, + // Rook Autoturret + { 2864, { 80, 0, 0, 0, 0 } }, + // Bishop Autoturret + { 2865, { 60, 0, 0, 0, 0 } }, + // Split Shot + { 2866, { 160, 0, 0, 0, 0 } }, + // Reload + { 2867, { 0, 0, 0, 0, 0 } }, + // Slug Shot + { 2868, { 100, 0, 0, 0, 0 } }, + // Spread Shot + { 2870, { 80, 0, 0, 0, 0 } }, + // Hot Shot + { 2872, { 120, 0, 0, 0, 0 } }, + // Clean Shot + { 2873, { 100, 0, 0, 0, 0 } }, + // Gauss Round + { 2874, { 210, 0, 0, 0, 0 } }, + // Heartbreak + { 2875, { 240, 0, 0, 0, 0 } }, + // Reassemble + { 2876, { 0, 0, 0, 0, 0 } }, + // Wildfire + { 2878, { 0, 0, 0, 0, 0 } }, + // Quick Reload + { 2879, { 0, 0, 0, 0, 0 } }, + // Gauss Barrel + { 2880, { 0, 0, 0, 0, 0 } }, + // Rapid Fire + { 2881, { 0, 0, 0, 0, 0 } }, + // Hypercharge + { 2885, { 0, 0, 0, 0, 0 } }, + // Dismantle + { 2887, { 0, 0, 0, 0, 0 } }, + // Blank + { 2888, { 0, 0, 0, 0, 0 } }, + // Ricochet + { 2890, { 320, 0, 0, 0, 0 } }, + // Raiton + { 3203, { 0, 0, 0, 0, 0 } }, + // Raiton + { 3204, { 0, 0, 0, 0, 0 } }, + // Kanashibari + { 3207, { 0, 0, 0, 0, 0 } }, + // Turret Retrieval + { 3487, { 0, 0, 0, 0, 0 } }, + // Goring Blade + { 3538, { 100, 0, 0, 0, 0 } }, + // Royal Authority + { 3539, { 100, 0, 0, 0, 0 } }, + // Divine Veil + { 3540, { 0, 0, 0, 0, 0 } }, + // Clemency + { 3541, { 0, 0, 0, 0, 1200 } }, + // Sheltron + { 3542, { 0, 0, 0, 0, 0 } }, + // Tornado Kick + { 3543, { 330, 0, 0, 0, 0 } }, + // Purification + { 3544, { 0, 0, 0, 0, 0 } }, + // Elixir Field + { 3545, { 220, 0, 0, 0, 0 } }, + // Meditation + { 3546, { 0, 0, 0, 0, 0 } }, + // the Forbidden Chakra + { 3547, { 250, 0, 0, 0, 0 } }, + // Deliverance + { 3548, { 0, 0, 0, 0, 0 } }, + // Fell Cleave + { 3549, { 520, 0, 0, 0, 0 } }, + // Decimate + { 3550, { 280, 0, 0, 0, 0 } }, + // Raw Intuition + { 3551, { 0, 0, 0, 0, 0 } }, + // Equilibrium + { 3552, { 0, 0, 0, 0, 1200 } }, + // Blood of the Dragon + { 3553, { 0, 0, 0, 0, 0 } }, + // Fang and Claw + { 3554, { 260, 300, 0, 0, 0 } }, + // Geirskogul + { 3555, { 230, 0, 0, 0, 0 } }, + // Wheeling Thrust + { 3556, { 260, 0, 0, 300, 0 } }, + // Battle Litany + { 3557, { 0, 0, 0, 0, 0 } }, + // Empyreal Arrow + { 3558, { 230, 0, 0, 0, 0 } }, + // the Wanderer's Minuet + { 3559, { 100, 0, 0, 0, 0 } }, + // Iron Jaws + { 3560, { 100, 0, 0, 0, 0 } }, + // the Warden's Paean + { 3561, { 0, 0, 0, 0, 0 } }, + // Sidewinder + { 3562, { 100, 0, 0, 0, 0 } }, + // Armor Crush + { 3563, { 100, 160, 0, 0, 0 } }, + // Shadewalker + { 3564, { 0, 0, 0, 0, 0 } }, + // Smoke Screen + { 3565, { 0, 0, 0, 0, 0 } }, + // Dream Within a Dream + { 3566, { 150, 0, 0, 0, 0 } }, + // Duality + { 3567, { 0, 0, 0, 0, 0 } }, + // Stone III + { 3568, { 210, 0, 0, 0, 0 } }, + // Asylum + { 3569, { 0, 0, 0, 0, 100 } }, + // Tetragrammaton + { 3570, { 0, 0, 0, 0, 700 } }, + // Assize + { 3571, { 400, 0, 0, 0, 400 } }, + // Aero III + { 3572, { 50, 0, 0, 0, 0 } }, + // Ley Lines + { 3573, { 0, 0, 0, 0, 0 } }, + // Sharpcast + { 3574, { 0, 0, 0, 0, 0 } }, + // Enochian + { 3575, { 0, 0, 0, 0, 0 } }, + // Blizzard IV + { 3576, { 260, 0, 0, 0, 0 } }, + // Fire IV + { 3577, { 300, 0, 0, 0, 0 } }, + // Painflare + { 3578, { 180, 0, 0, 0, 0 } }, + // Ruin III + { 3579, { 120, 0, 0, 0, 0 } }, + // Tri-disaster + { 3580, { 0, 0, 0, 0, 0 } }, + // Dreadwyrm Trance + { 3581, { 0, 0, 0, 0, 0 } }, + // Deathflare + { 3582, { 400, 0, 0, 0, 0 } }, + // Indomitability + { 3583, { 0, 0, 0, 0, 500 } }, + // Broil + { 3584, { 190, 0, 0, 0, 0 } }, + // Deployment Tactics + { 3585, { 0, 0, 0, 0, 0 } }, + // Emergency Tactics + { 3586, { 0, 0, 0, 0, 0 } }, + // Dissipation + { 3587, { 0, 0, 0, 0, 0 } }, + // Draw + { 3590, { 0, 0, 0, 0, 0 } }, + // Royal Road + { 3591, { 0, 0, 0, 0, 0 } }, + // Spread + { 3592, { 0, 0, 0, 0, 0 } }, + // Redraw + { 3593, { 0, 0, 0, 0, 0 } }, + // Benefic + { 3594, { 0, 0, 0, 0, 400 } }, + // Aspected Benefic + { 3595, { 0, 0, 0, 0, 200 } }, + // Malefic + { 3596, { 150, 0, 0, 0, 0 } }, + // Malefic II + { 3598, { 180, 0, 0, 0, 0 } }, + // Combust + { 3599, { 0, 0, 0, 0, 0 } }, + // Helios + { 3600, { 0, 0, 0, 0, 300 } }, + // Aspected Helios + { 3601, { 0, 0, 0, 0, 200 } }, + // Ascend + { 3603, { 0, 0, 0, 0, 0 } }, + // Diurnal Sect + { 3604, { 0, 0, 0, 0, 0 } }, + // Nocturnal Sect + { 3605, { 0, 0, 0, 0, 0 } }, + // Lightspeed + { 3606, { 0, 0, 0, 0, 0 } }, + // Combust II + { 3608, { 0, 0, 0, 0, 0 } }, + // Benefic II + { 3610, { 0, 0, 0, 0, 650 } }, + // Time Dilation + { 3611, { 0, 0, 0, 0, 0 } }, + // Synastry + { 3612, { 0, 0, 0, 0, 0 } }, + // Collective Unconscious + { 3613, { 0, 0, 0, 0, 150 } }, + // Essential Dignity + { 3614, { 0, 0, 0, 0, 400 } }, + // Gravity + { 3615, { 200, 0, 0, 0, 0 } }, + // Celestial Opposition + { 3616, { 0, 0, 0, 0, 0 } }, + // Hard Slash + { 3617, { 150, 0, 0, 0, 0 } }, + // Spinning Slash + { 3619, { 100, 0, 0, 0, 0 } }, + // Unleash + { 3621, { 50, 0, 0, 0, 0 } }, + // Syphon Strike + { 3623, { 100, 0, 0, 0, 0 } }, + // Unmend + { 3624, { 150, 0, 0, 0, 0 } }, + // Blood Weapon + { 3625, { 0, 0, 0, 0, 0 } }, + // Power Slash + { 3627, { 100, 0, 0, 0, 0 } }, + // Darkside + { 3628, { 0, 0, 0, 0, 0 } }, + // Grit + { 3629, { 0, 0, 0, 0, 0 } }, + // Blood Price + { 3631, { 0, 0, 0, 0, 0 } }, + // Souleater + { 3632, { 100, 0, 0, 0, 0 } }, + // Dark Passenger + { 3633, { 140, 0, 0, 0, 0 } }, + // Dark Mind + { 3634, { 0, 0, 0, 0, 0 } }, + // Dark Arts + { 3635, { 0, 0, 0, 0, 0 } }, + // Shadow Wall + { 3636, { 0, 0, 0, 0, 0 } }, + // Living Dead + { 3638, { 0, 0, 0, 0, 0 } }, + // Salted Earth + { 3639, { 75, 0, 0, 0, 0 } }, + // Plunge + { 3640, { 200, 0, 0, 0, 0 } }, + // Abyssal Drain + { 3641, { 120, 0, 0, 0, 0 } }, + // Sole Survivor + { 3642, { 0, 0, 0, 0, 0 } }, + // Carve and Spit + { 3643, { 100, 0, 0, 0, 0 } }, + // Big Shot + { 4238, { 0, 0, 0, 0, 0 } }, + // Desperado + { 4239, { 0, 0, 0, 0, 0 } }, + // Land Waker + { 4240, { 0, 0, 0, 0, 0 } }, + // Dark Force + { 4241, { 0, 0, 0, 0, 0 } }, + // Dragonsong Dive + { 4242, { 0, 0, 0, 0, 0 } }, + // Chimatsuri + { 4243, { 0, 0, 0, 0, 0 } }, + // Sagittarius Arrow + { 4244, { 0, 0, 0, 0, 0 } }, + // Satellite Beam + { 4245, { 0, 0, 0, 0, 0 } }, + // Teraflare + { 4246, { 0, 0, 0, 0, 0 } }, + // Angel Feathers + { 4247, { 0, 0, 0, 0, 0 } }, + // Astral Stasis + { 4248, { 0, 0, 0, 0, 0 } }, + // Form Shift + { 4262, { 0, 0, 0, 0, 0 } }, + // Cannonfire + { 4271, { 0, 0, 0, 0, 0 } }, + // the Balance + { 4401, { 0, 0, 0, 0, 0 } }, + // the Bole + { 4402, { 0, 0, 0, 0, 0 } }, + // the Arrow + { 4403, { 0, 0, 0, 0, 0 } }, + // the Spear + { 4404, { 0, 0, 0, 0, 0 } }, + // the Ewer + { 4405, { 0, 0, 0, 0, 0 } }, + // the Spire + { 4406, { 0, 0, 0, 0, 0 } }, + // the Balance + { 4407, { 0, 0, 0, 0, 0 } }, + // the Bole + { 4408, { 0, 0, 0, 0, 0 } }, + // the Arrow + { 4409, { 0, 0, 0, 0, 0 } }, + // the Spear + { 4410, { 0, 0, 0, 0, 0 } }, + // the Ewer + { 4411, { 0, 0, 0, 0, 0 } }, + // the Spire + { 4412, { 0, 0, 0, 0, 0 } }, + // the Balance + { 4413, { 0, 0, 0, 0, 0 } }, + // the Bole + { 4414, { 0, 0, 0, 0, 0 } }, + // the Arrow + { 4415, { 0, 0, 0, 0, 0 } }, + // the Spear + { 4416, { 0, 0, 0, 0, 0 } }, + // the Ewer + { 4417, { 0, 0, 0, 0, 0 } }, + // the Spire + { 4418, { 0, 0, 0, 0, 0 } }, + // the Balance + { 4419, { 0, 0, 0, 0, 0 } }, + // the Bole + { 4420, { 0, 0, 0, 0, 0 } }, + // the Arrow + { 4421, { 0, 0, 0, 0, 0 } }, + // the Spear + { 4422, { 0, 0, 0, 0, 0 } }, + // the Ewer + { 4423, { 0, 0, 0, 0, 0 } }, + // the Spire + { 4424, { 0, 0, 0, 0, 0 } }, + // Empty Road + { 4645, { 0, 0, 0, 0, 0 } }, + // Undraw Spread + { 4646, { 0, 0, 0, 0, 0 } }, + // Raiton + { 4977, { 0, 0, 0, 0, 0 } }, + // Raiton + { 5069, { 0, 0, 0, 0, 0 } }, + // attack + { 5199, { 0, 0, 0, 0, 0 } }, + // attack + { 5846, { 0, 0, 0, 0, 0 } }, + // Stickyloom + { 5874, { 0, 0, 0, 0, 0 } }, + // Void Fire II + { 6274, { 0, 0, 0, 0, 0 } }, + // Total Eclipse + { 7381, { 110, 0, 0, 0, 0 } }, + // Intervention + { 7382, { 0, 0, 0, 0, 0 } }, + // Requiescat + { 7383, { 350, 0, 0, 0, 0 } }, + // Holy Spirit + { 7384, { 380, 0, 0, 0, 0 } }, + // Passage of Arms + { 7385, { 0, 0, 0, 0, 0 } }, + // Onslaught + { 7386, { 100, 0, 0, 0, 0 } }, + // Upheaval + { 7387, { 300, 0, 0, 0, 0 } }, + // Shake It Off + { 7388, { 0, 0, 0, 0, 0 } }, + // Inner Release + { 7389, { 0, 0, 0, 0, 0 } }, + // Delirium + { 7390, { 0, 0, 0, 0, 0 } }, + // Quietus + { 7391, { 160, 0, 0, 0, 0 } }, + // Bloodspiller + { 7392, { 400, 0, 0, 0, 0 } }, + // The Blackest Night + { 7393, { 0, 0, 0, 0, 0 } }, + // Riddle of Earth + { 7394, { 0, 0, 0, 0, 0 } }, + // Riddle of Fire + { 7395, { 0, 0, 0, 0, 0 } }, + // Brotherhood + { 7396, { 0, 0, 0, 0, 0 } }, + // Sonic Thrust + { 7397, { 100, 0, 0, 0, 0 } }, + // Dragon Sight + { 7398, { 0, 0, 0, 0, 0 } }, + // Mirage Dive + { 7399, { 210, 0, 0, 0, 0 } }, + // Nastrond + { 7400, { 330, 0, 0, 0, 0 } }, + // Hellfrog Medium + { 7401, { 400, 0, 0, 0, 0 } }, + // Bhavacakra + { 7402, { 600, 0, 0, 0, 0 } }, + // Ten Chi Jin + { 7403, { 0, 0, 0, 0, 0 } }, + // Pitch Perfect + { 7404, { 100, 0, 0, 0, 0 } }, + // Troubadour + { 7405, { 0, 0, 0, 0, 0 } }, + // Caustic Bite + { 7406, { 120, 0, 0, 0, 0 } }, + // Stormbite + { 7407, { 120, 0, 0, 0, 0 } }, + // Nature's Minne + { 7408, { 0, 0, 0, 0, 0 } }, + // Refulgent Arrow + { 7409, { 300, 0, 0, 0, 0 } }, + // Cooldown + { 7410, { 150, 0, 0, 0, 0 } }, + // Heated Split Shot + { 7411, { 190, 0, 0, 0, 0 } }, + // Heated Slug Shot + { 7412, { 100, 0, 0, 0, 0 } }, + // Heated Clean Shot + { 7413, { 100, 0, 0, 0, 0 } }, + // Barrel Stabilizer + { 7414, { 0, 0, 0, 0, 0 } }, + // Rook Overdrive + { 7415, { 0, 0, 0, 0, 0 } }, + // Flamethrower + { 7418, { 0, 0, 0, 0, 0 } }, + // Between the Lines + { 7419, { 0, 0, 0, 0, 0 } }, + // Thunder IV + { 7420, { 50, 0, 0, 0, 0 } }, + // Triplecast + { 7421, { 0, 0, 0, 0, 0 } }, + // Foul + { 7422, { 650, 0, 0, 0, 0 } }, + // Aetherpact + { 7423, { 0, 0, 0, 0, 0 } }, + // Bio III + { 7424, { 0, 0, 0, 0, 0 } }, + // Miasma III + { 7425, { 50, 0, 0, 0, 0 } }, + // Ruin IV + { 7426, { 200, 0, 0, 0, 0 } }, + // Summon Bahamut + { 7427, { 0, 0, 0, 0, 0 } }, + // Enkindle Bahamut + { 7429, { 0, 0, 0, 0, 0 } }, + // Thin Air + { 7430, { 0, 0, 0, 0, 0 } }, + // Stone IV + { 7431, { 250, 0, 0, 0, 0 } }, + // Divine Benison + { 7432, { 0, 0, 0, 0, 0 } }, + // Plenary Indulgence + { 7433, { 0, 0, 0, 0, 0 } }, + // Excogitation + { 7434, { 0, 0, 0, 0, 800 } }, + // Broil II + { 7435, { 230, 0, 0, 0, 0 } }, + // Chain Stratagem + { 7436, { 0, 0, 0, 0, 0 } }, + // Aetherpact + { 7437, { 0, 0, 0, 0, 0 } }, + // Earthly Star + { 7439, { 150, 0, 0, 0, 540 } }, + // Malefic III + { 7442, { 220, 0, 0, 0, 0 } }, + // Minor Arcana + { 7443, { 0, 0, 0, 0, 0 } }, + // Lord of Crowns + { 7444, { 300, 0, 0, 0, 0 } }, + // Lady of Crowns + { 7445, { 0, 0, 0, 0, 500 } }, + // Thunder II + { 7447, { 30, 0, 0, 0, 0 } }, + // Sleeve Draw + { 7448, { 0, 0, 0, 0, 0 } }, + // Hakaze + { 7477, { 150, 0, 0, 0, 0 } }, + // Jinpu + { 7478, { 100, 0, 0, 0, 0 } }, + // Shifu + { 7479, { 100, 0, 0, 0, 0 } }, + // Yukikaze + { 7480, { 100, 0, 0, 0, 0 } }, + // Gekko + { 7481, { 100, 0, 0, 0, 0 } }, + // Kasha + { 7482, { 100, 0, 0, 0, 0 } }, + // Fuga + { 7483, { 100, 0, 0, 0, 0 } }, + // Mangetsu + { 7484, { 100, 0, 0, 0, 0 } }, + // Oka + { 7485, { 100, 0, 0, 0, 0 } }, + // Enpi + { 7486, { 100, 0, 0, 0, 0 } }, + // Midare Setsugekka + { 7487, { 720, 0, 0, 0, 0 } }, + // Tenka Goken + { 7488, { 360, 0, 0, 0, 0 } }, + // Higanbana + { 7489, { 240, 0, 0, 0, 0 } }, + // Hissatsu: Shinten + { 7490, { 300, 0, 0, 0, 0 } }, + // Hissatsu: Kyuten + { 7491, { 150, 0, 0, 0, 0 } }, + // Hissatsu: Gyoten + { 7492, { 100, 0, 0, 0, 0 } }, + // Hissatsu: Yaten + { 7493, { 100, 0, 0, 0, 0 } }, + // Hissatsu: Kaiten + { 7494, { 0, 0, 0, 0, 0 } }, + // Hagakure + { 7495, { 0, 0, 0, 0, 0 } }, + // Hissatsu: Guren + { 7496, { 800, 0, 0, 0, 0 } }, + // Meditate + { 7497, { 0, 0, 0, 0, 0 } }, + // Third Eye + { 7498, { 0, 0, 0, 0, 0 } }, + // Meikyo Shisui + { 7499, { 0, 0, 0, 0, 0 } }, + // Ageha + { 7500, { 250, 0, 0, 0, 0 } }, + // Hissatsu: Seigan + { 7501, { 200, 0, 0, 0, 0 } }, + // Merciful Eyes + { 7502, { 0, 0, 0, 0, 200 } }, + // Jolt + { 7503, { 180, 0, 0, 0, 0 } }, + // Riposte + { 7504, { 130, 0, 0, 0, 0 } }, + // Verthunder + { 7505, { 310, 0, 0, 0, 0 } }, + // Corps-a-corps + { 7506, { 130, 0, 0, 0, 0 } }, + // Veraero + { 7507, { 310, 0, 0, 0, 0 } }, + // Tether + { 7508, { 0, 0, 0, 0, 0 } }, + // Scatter + { 7509, { 100, 0, 0, 0, 0 } }, + // Verfire + { 7510, { 270, 0, 0, 0, 0 } }, + // Verstone + { 7511, { 270, 0, 0, 0, 0 } }, + // Zwerchhau + { 7512, { 100, 0, 0, 0, 0 } }, + // Moulinet + { 7513, { 60, 0, 0, 0, 0 } }, + // Vercure + { 7514, { 0, 0, 0, 0, 350 } }, + // Displacement + { 7515, { 130, 0, 0, 0, 0 } }, + // Redoublement + { 7516, { 100, 0, 0, 0, 0 } }, + // Fleche + { 7517, { 420, 0, 0, 0, 0 } }, + // Acceleration + { 7518, { 0, 0, 0, 0, 0 } }, + // Contre Sixte + { 7519, { 350, 0, 0, 0, 0 } }, + // Embolden + { 7520, { 0, 0, 0, 0, 0 } }, + // Manafication + { 7521, { 0, 0, 0, 0, 0 } }, + // Impact + { 7522, { 270, 0, 0, 0, 0 } }, + // Verraise + { 7523, { 0, 0, 0, 0, 0 } }, + // Jolt II + { 7524, { 240, 0, 0, 0, 0 } }, + // Verflare + { 7525, { 600, 0, 0, 0, 0 } }, + // Verholy + { 7526, { 600, 0, 0, 0, 0 } }, + // Enchanted Riposte + { 7527, { 210, 0, 0, 0, 0 } }, + // Enchanted Zwerchhau + { 7528, { 100, 0, 0, 0, 0 } }, + // Enchanted Redoublement + { 7529, { 100, 0, 0, 0, 0 } }, + // Enchanted Moulinet + { 7530, { 200, 0, 0, 0, 0 } }, + // Magitek Cannon + { 7619, { 0, 0, 0, 0, 0 } }, + // Photon Stream + { 7620, { 0, 0, 0, 0, 0 } }, + // Diffractive Magitek Cannon + { 7621, { 0, 0, 0, 0, 0 } }, + // High-powered Magitek Cannon + { 7622, { 0, 0, 0, 0, 0 } }, + // Doom of the Living + { 7861, { 0, 0, 0, 0, 0 } }, + // Vermillion Scourge + { 7862, { 0, 0, 0, 0, 0 } }, + // Earth Tackle + { 7864, { 100, 0, 0, 0, 0 } }, + // Wind Tackle + { 7865, { 65, 0, 0, 0, 0 } }, + // Fire Tackle + { 7866, { 130, 0, 0, 0, 0 } }, + // Iaijutsu + { 7867, { 0, 0, 0, 0, 0 } }, + // Riddle of Wind + { 7868, { 65, 0, 0, 0, 0 } }, + // Dissolve Union + { 7869, { 0, 0, 0, 0, 0 } }, + // Stellar Detonation + { 8324, { 150, 0, 0, 0, 540 } }, + // Broken Ridge + { 8395, { 0, 0, 0, 0, 0 } }, + // Magitek Pulse + { 8624, { 0, 0, 0, 0, 0 } }, + // Magitek Thunder + { 8625, { 0, 0, 0, 0, 0 } }, + // attack + { 8687, { 0, 0, 0, 0, 0 } }, + // Katon + { 9012, { 0, 0, 0, 0, 0 } }, + // Remove Barrel + { 9015, { 0, 0, 0, 0, 0 } }, + // Tenka Goken + { 9143, { 0, 0, 0, 0, 0 } }, + // Thunderous Force + { 9294, { 0, 0, 0, 0, 0 } }, + // Raiton + { 9301, { 0, 0, 0, 0, 0 } }, + // Raiton + { 9302, { 0, 0, 0, 0, 0 } }, + // Bishop Overdrive + { 9372, { 0, 0, 0, 0, 0 } }, + // Undraw + { 9629, { 0, 0, 0, 0, 0 } }, + // Self-detonate + { 9775, { 0, 0, 0, 0, 0 } }, + // Shatterstone + { 9823, { 0, 0, 0, 0, 0 } }, + // attack + { 9996, { 0, 0, 0, 0, 0 } }, + // Ungarmax + { 10001, { 0, 0, 0, 0, 0 } }, + // Starstorm + { 10894, { 0, 0, 0, 0, 0 } }, + // attack + { 10946, { 0, 0, 0, 0, 0 } }, + // attack + { 10947, { 0, 0, 0, 0, 0 } }, + // Ruin III + { 11191, { 200, 0, 0, 0, 0 } }, + // Physick + { 11192, { 0, 0, 0, 0, 400 } }, + // Starstorm + { 11193, { 3600, 0, 0, 0, 0 } }, + // Snort + { 11383, { 0, 0, 0, 0, 0 } }, + // 4-tonze Weight + { 11384, { 110, 0, 0, 0, 0 } }, + // Water Cannon + { 11385, { 120, 0, 0, 0, 0 } }, + // Song of Torment + { 11386, { 50, 0, 0, 0, 0 } }, + // High Voltage + { 11387, { 90, 0, 0, 0, 0 } }, + // Bad Breath + { 11388, { 0, 0, 0, 0, 0 } }, + // Flying Frenzy + { 11389, { 80, 0, 0, 0, 0 } }, + // Aqua Breath + { 11390, { 90, 0, 0, 0, 0 } }, + // Plaincracker + { 11391, { 130, 0, 0, 0, 0 } }, + // Acorn Bomb + { 11392, { 0, 0, 0, 0, 0 } }, + // Bristle + { 11393, { 0, 0, 0, 0, 0 } }, + // Mind Blast + { 11394, { 100, 0, 0, 0, 0 } }, + // Blood Drain + { 11395, { 20, 0, 0, 0, 0 } }, + // Bomb Toss + { 11396, { 110, 0, 0, 0, 0 } }, + // 1000 Needles + { 11397, { 0, 0, 0, 0, 0 } }, + // Drill Cannons + { 11398, { 120, 0, 0, 0, 0 } }, + // the Look + { 11399, { 130, 0, 0, 0, 0 } }, + // Sharpened Knife + { 11400, { 120, 0, 0, 0, 0 } }, + // Loom + { 11401, { 0, 0, 0, 0, 0 } }, + // Flame Thrower + { 11402, { 130, 0, 0, 0, 0 } }, + // Faze + { 11403, { 0, 0, 0, 0, 0 } }, + // Glower + { 11404, { 130, 0, 0, 0, 0 } }, + // Missile + { 11405, { 0, 0, 0, 0, 0 } }, + // White Wind + { 11406, { 0, 0, 0, 0, 0 } }, + // Final Sting + { 11407, { 1500, 0, 0, 0, 0 } }, + // Self-destruct + { 11408, { 900, 0, 0, 0, 0 } }, + // Transfusion + { 11409, { 0, 0, 0, 0, 0 } }, + // Toad Oil + { 11410, { 0, 0, 0, 0, 0 } }, + // Off-guard + { 11411, { 0, 0, 0, 0, 0 } }, + // Sticky Tongue + { 11412, { 0, 0, 0, 0, 0 } }, + // Tail Screw + { 11413, { 0, 0, 0, 0, 0 } }, + // Level 5 Petrify + { 11414, { 0, 0, 0, 0, 0 } }, + // Moon Flute + { 11415, { 0, 0, 0, 0, 0 } }, + // Doom + { 11416, { 0, 0, 0, 0, 0 } }, + // Mighty Guard + { 11417, { 0, 0, 0, 0, 0 } }, + // Ice Spikes + { 11418, { 0, 0, 0, 0, 0 } }, + // the Ram's Voice + { 11419, { 130, 0, 0, 0, 0 } }, + // the Dragon's Voice + { 11420, { 110, 0, 0, 0, 0 } }, + // Peculiar Light + { 11421, { 0, 0, 0, 0, 0 } }, + // Ink Jet + { 11422, { 120, 0, 0, 0, 0 } }, + // Flying Sardine + { 11423, { 10, 0, 0, 0, 0 } }, + // Diamondback + { 11424, { 0, 0, 0, 0, 0 } }, + // Fire Angon + { 11425, { 100, 0, 0, 0, 0 } }, + // Feather Rain + { 11426, { 180, 0, 0, 0, 0 } }, + // Eruption + { 11427, { 220, 0, 0, 0, 0 } }, + // Mountain Buster + { 11428, { 310, 0, 0, 0, 0 } }, + // Shock Strike + { 11429, { 310, 0, 0, 0, 0 } }, + // Glass Dance + { 11430, { 290, 0, 0, 0, 0 } }, + // Veil of the Whorl + { 11431, { 0, 0, 0, 0, 0 } }, + // Tri-shackle + { 11482, { 30, 0, 0, 0, 0 } }, + // attack + { 11784, { 0, 0, 0, 0, 0 } }, + // Stone of the Seventh Dawn + { 13423, { 140, 0, 0, 0, 0 } }, + // Aero of the Seventh Dawn + { 13424, { 50, 0, 0, 0, 0 } }, + // Cure of the Seventh Dawn + { 13425, { 0, 0, 0, 0, 700 } }, + // Aetherwell + { 13426, { 0, 0, 0, 0, 0 } }, + // Thunderous Force + { 14587, { 0, 0, 0, 0, 0 } }, + // Kyokufu + { 14840, { 180, 0, 0, 0, 0 } }, + // Ajisai + { 14841, { 100, 0, 0, 0, 0 } }, + // Hissatsu: Gyoten + { 14842, { 100, 0, 0, 0, 0 } }, + // 冥界恐叫打 + { 14843, { 0, 0, 0, 0, 0 } }, + // Second Wind + { 15375, { 0, 0, 0, 0, 500 } }, + +}; \ No newline at end of file diff --git a/src/world/Action/ActionLut.h b/src/world/Action/ActionLut.h new file mode 100644 index 00000000..df2e5332 --- /dev/null +++ b/src/world/Action/ActionLut.h @@ -0,0 +1,28 @@ +#ifndef SAPPHIRE_ACTIONLUT_H +#define SAPPHIRE_ACTIONLUT_H + +#include + +namespace Sapphire::World::Action +{ + struct ActionEntry + { + uint16_t potency; + uint16_t comboPotency; + uint16_t flankPotency; + uint16_t frontPotency; + uint16_t rearPotency; + uint16_t curePotency; +// uint16_t restorePercentage; + }; + + class ActionLut + { + public: + using Lut = std::unordered_map< uint16_t, ActionEntry >; + + static Lut m_actionLut; + }; +} + +#endif //SAPPHIRE_ACTIONLUT_H From 3ef207a724515bcee6472336241b8e172c9332f9 Mon Sep 17 00:00:00 2001 From: NotAdam Date: Sun, 2 Jun 2019 00:34:07 +1000 Subject: [PATCH 045/351] move the actionlut data to its own isolated cpp file --- ...ionLut.cpp.tmpl => ActionLutData.cpp.tmpl} | 0 src/world/Action/ActionLut.cpp | 1125 +---------------- src/world/Action/ActionLut.h | 2 + src/world/Action/ActionLutData.cpp | 1120 ++++++++++++++++ 4 files changed, 1133 insertions(+), 1114 deletions(-) rename src/tools/action_parse/{ActionLut.cpp.tmpl => ActionLutData.cpp.tmpl} (100%) create mode 100644 src/world/Action/ActionLutData.cpp diff --git a/src/tools/action_parse/ActionLut.cpp.tmpl b/src/tools/action_parse/ActionLutData.cpp.tmpl similarity index 100% rename from src/tools/action_parse/ActionLut.cpp.tmpl rename to src/tools/action_parse/ActionLutData.cpp.tmpl diff --git a/src/world/Action/ActionLut.cpp b/src/world/Action/ActionLut.cpp index 1e9c1f97..9c33bb96 100644 --- a/src/world/Action/ActionLut.cpp +++ b/src/world/Action/ActionLut.cpp @@ -2,1119 +2,16 @@ using namespace Sapphire::World::Action; -ActionLut::Lut ActionLut::m_actionLut = +bool ActionLut::validEntryExists( uint16_t actionId ) { - // attack - { 7, { 0, 0, 0, 0, 0 } }, - // Shot - { 8, { 0, 0, 0, 0, 0 } }, - // Fast Blade - { 9, { 160, 0, 0, 0, 0 } }, - // Savage Blade - { 11, { 100, 0, 0, 0, 0 } }, - // Flash - { 14, { 0, 0, 0, 0, 0 } }, - // Riot Blade - { 15, { 100, 0, 0, 0, 0 } }, - // Shield Bash - { 16, { 110, 0, 0, 0, 0 } }, - // Sentinel - { 17, { 0, 0, 0, 0, 0 } }, - // Tempered Will - { 19, { 0, 0, 0, 0, 0 } }, - // Fight or Flight - { 20, { 0, 0, 0, 0, 0 } }, - // Rage of Halone - { 21, { 100, 0, 0, 0, 0 } }, - // Bulwark - { 22, { 0, 0, 0, 0, 0 } }, - // Circle of Scorn - { 23, { 100, 0, 0, 0, 0 } }, - // Shield Lob - { 24, { 120, 0, 0, 0, 0 } }, - // Shield Swipe - { 25, { 100, 0, 0, 0, 0 } }, - // Sword Oath - { 26, { 75, 0, 0, 0, 0 } }, - // Cover - { 27, { 0, 0, 0, 0, 0 } }, - // Shield Oath - { 28, { 0, 0, 0, 0, 0 } }, - // Spirits Within - { 29, { 300, 0, 0, 0, 0 } }, - // Hallowed Ground - { 30, { 0, 0, 0, 0, 0 } }, - // Heavy Swing - { 31, { 160, 0, 0, 0, 0 } }, - // Skull Sunder - { 35, { 100, 0, 0, 0, 0 } }, - // Maim - { 37, { 100, 0, 0, 0, 0 } }, - // Berserk - { 38, { 0, 0, 0, 0, 0 } }, - // Thrill of Battle - { 40, { 0, 0, 0, 0, 0 } }, - // Overpower - { 41, { 130, 0, 0, 0, 0 } }, - // Storm's Path - { 42, { 100, 0, 0, 0, 0 } }, - // Holmgang - { 43, { 0, 0, 0, 0, 0 } }, - // Vengeance - { 44, { 55, 0, 0, 0, 0 } }, - // Storm's Eye - { 45, { 100, 0, 0, 0, 0 } }, - // Tomahawk - { 46, { 140, 0, 0, 0, 0 } }, - // Butcher's Block - { 47, { 100, 0, 0, 0, 0 } }, - // Defiance - { 48, { 0, 0, 0, 0, 0 } }, - // Inner Beast - { 49, { 350, 0, 0, 0, 0 } }, - // Unchained - { 50, { 0, 0, 0, 0, 0 } }, - // Steel Cyclone - { 51, { 200, 0, 0, 0, 0 } }, - // Infuriate - { 52, { 0, 0, 0, 0, 0 } }, - // Bootshine - { 53, { 140, 0, 0, 0, 0 } }, - // True Strike - { 54, { 160, 0, 0, 180, 0 } }, - // Snap Punch - { 56, { 150, 170, 0, 0, 0 } }, - // Internal Release - { 59, { 0, 0, 0, 0, 0 } }, - // Fists of Earth - { 60, { 0, 0, 0, 0, 0 } }, - // Twin Snakes - { 61, { 110, 130, 0, 0, 0 } }, - // Arm of the Destroyer - { 62, { 50, 0, 0, 0, 0 } }, - // Fists of Fire - { 63, { 0, 0, 0, 0, 0 } }, - // Steel Peak - { 64, { 150, 0, 0, 0, 0 } }, - // Mantra - { 65, { 0, 0, 0, 0, 0 } }, - // Demolish - { 66, { 50, 0, 0, 70, 0 } }, - // Howling Fist - { 67, { 210, 0, 0, 0, 0 } }, - // Perfect Balance - { 69, { 0, 0, 0, 0, 0 } }, - // Rockbreaker - { 70, { 130, 0, 0, 0, 0 } }, - // Shoulder Tackle - { 71, { 100, 0, 0, 0, 0 } }, - // One Ilm Punch - { 72, { 120, 0, 0, 0, 0 } }, - // Fists of Wind - { 73, { 0, 0, 0, 0, 0 } }, - // Dragon Kick - { 74, { 120, 140, 0, 0, 0 } }, - // True Thrust - { 75, { 160, 0, 0, 0, 0 } }, - // Vorpal Thrust - { 78, { 100, 0, 0, 0, 0 } }, - // Heavy Thrust - { 79, { 150, 190, 0, 0, 0 } }, - // Impulse Drive - { 81, { 200, 0, 0, 0, 0 } }, - // Life Surge - { 83, { 0, 0, 0, 0, 0 } }, - // Full Thrust - { 84, { 100, 0, 0, 0, 0 } }, - // Blood for Blood - { 85, { 0, 0, 0, 0, 0 } }, - // Doom Spike - { 86, { 140, 0, 0, 0, 0 } }, - // Disembowel - { 87, { 100, 0, 0, 0, 0 } }, - // Chaos Thrust - { 88, { 100, 0, 0, 140, 0 } }, - // Piercing Talon - { 90, { 120, 0, 0, 0, 0 } }, - // Jump - { 92, { 260, 0, 0, 0, 0 } }, - // Elusive Jump - { 94, { 0, 0, 0, 0, 0 } }, - // Spineshatter Dive - { 95, { 210, 0, 0, 0, 0 } }, - // Dragonfire Dive - { 96, { 320, 0, 0, 0, 0 } }, - // Heavy Shot - { 97, { 150, 0, 0, 0, 0 } }, - // Straight Shot - { 98, { 140, 0, 0, 0, 0 } }, - // Venomous Bite - { 100, { 100, 0, 0, 0, 0 } }, - // Raging Strikes - { 101, { 0, 0, 0, 0, 0 } }, - // Misery's End - { 103, { 190, 0, 0, 0, 0 } }, - // Quick Nock - { 106, { 110, 0, 0, 0, 0 } }, - // Barrage - { 107, { 0, 0, 0, 0, 0 } }, - // Bloodletter - { 110, { 130, 0, 0, 0, 0 } }, - // Repelling Shot - { 112, { 0, 0, 0, 0, 0 } }, - // Windbite - { 113, { 60, 0, 0, 0, 0 } }, - // Mage's Ballad - { 114, { 100, 0, 0, 0, 0 } }, - // Foe Requiem - { 115, { 0, 0, 0, 0, 0 } }, - // Army's Paeon - { 116, { 100, 0, 0, 0, 0 } }, - // Rain of Death - { 117, { 100, 0, 0, 0, 0 } }, - // Battle Voice - { 118, { 0, 0, 0, 0, 0 } }, - // Stone - { 119, { 140, 0, 0, 0, 0 } }, - // Cure - { 120, { 0, 0, 0, 0, 450 } }, - // Aero - { 121, { 50, 0, 0, 0, 0 } }, - // Medica - { 124, { 0, 0, 0, 0, 300 } }, - // Raise - { 125, { 0, 0, 0, 0, 0 } }, - // Stone II - { 127, { 200, 0, 0, 0, 0 } }, - // Repose - { 128, { 0, 0, 0, 0, 0 } }, - // Cure III - { 131, { 0, 0, 0, 0, 550 } }, - // Aero II - { 132, { 50, 0, 0, 0, 0 } }, - // Medica II - { 133, { 0, 0, 0, 0, 200 } }, - // Fluid Aura - { 134, { 0, 0, 0, 0, 0 } }, - // Cure II - { 135, { 0, 0, 0, 0, 700 } }, - // Presence of Mind - { 136, { 0, 0, 0, 0, 0 } }, - // Regen - { 137, { 0, 0, 0, 0, 150 } }, - // Holy - { 139, { 200, 0, 0, 0, 0 } }, - // Benediction - { 140, { 0, 0, 0, 0, 0 } }, - // Fire - { 141, { 180, 0, 0, 0, 0 } }, - // Blizzard - { 142, { 180, 0, 0, 0, 0 } }, - // Thunder - { 144, { 30, 0, 0, 0, 0 } }, - // Sleep - { 145, { 0, 0, 0, 0, 0 } }, - // Blizzard II - { 146, { 50, 0, 0, 0, 0 } }, - // Fire II - { 147, { 80, 0, 0, 0, 0 } }, - // Transpose - { 149, { 0, 0, 0, 0, 0 } }, - // Fire III - { 152, { 240, 0, 0, 0, 0 } }, - // Thunder III - { 153, { 70, 0, 0, 0, 0 } }, - // Blizzard III - { 154, { 240, 0, 0, 0, 0 } }, - // Aetherial Manipulation - { 155, { 0, 0, 0, 0, 0 } }, - // Scathe - { 156, { 100, 0, 0, 0, 0 } }, - // Manaward - { 157, { 0, 0, 0, 0, 0 } }, - // Convert - { 158, { 0, 0, 0, 0, 0 } }, - // Freeze - { 159, { 100, 0, 0, 0, 0 } }, - // Flare - { 162, { 260, 0, 0, 0, 0 } }, - // Ruin - { 163, { 100, 0, 0, 0, 0 } }, - // Bio - { 164, { 0, 0, 0, 0, 0 } }, - // Summon - { 165, { 0, 0, 0, 0, 0 } }, - // Aetherflow - { 166, { 0, 0, 0, 0, 0 } }, - // Energy Drain - { 167, { 150, 0, 0, 0, 0 } }, - // Miasma - { 168, { 20, 0, 0, 0, 0 } }, - // Summon II - { 170, { 0, 0, 0, 0, 0 } }, - // Sustain - { 171, { 0, 0, 0, 0, 0 } }, - // Ruin II - { 172, { 100, 0, 0, 0, 0 } }, - // Resurrection - { 173, { 0, 0, 0, 0, 0 } }, - // Bane - { 174, { 0, 0, 0, 0, 0 } }, - // Rouse - { 176, { 0, 0, 0, 0, 0 } }, - // Miasma II - { 177, { 100, 0, 0, 0, 0 } }, - // Bio II - { 178, { 0, 0, 0, 0, 0 } }, - // Shadow Flare - { 179, { 50, 0, 0, 0, 0 } }, - // Summon III - { 180, { 0, 0, 0, 0, 0 } }, - // Fester - { 181, { 150, 0, 0, 0, 0 } }, - // Tri-bind - { 182, { 30, 0, 0, 0, 0 } }, - // Enkindle - { 184, { 0, 0, 0, 0, 0 } }, - // Adloquium - { 185, { 0, 0, 0, 0, 300 } }, - // Succor - { 186, { 0, 0, 0, 0, 150 } }, - // Sacred Soil - { 188, { 0, 0, 0, 0, 0 } }, - // Lustrate - { 189, { 0, 0, 0, 0, 600 } }, - // Physick - { 190, { 0, 0, 0, 0, 400 } }, - // Shield Wall - { 197, { 0, 0, 0, 0, 0 } }, - // Stronghold - { 198, { 0, 0, 0, 0, 0 } }, - // Last Bastion - { 199, { 0, 0, 0, 0, 0 } }, - // Braver - { 200, { 2400, 0, 0, 0, 0 } }, - // Bladedance - { 201, { 5250, 0, 0, 0, 0 } }, - // Final Heaven - { 202, { 9000, 0, 0, 0, 0 } }, - // Skyshard - { 203, { 1650, 0, 0, 0, 0 } }, - // Starstorm - { 204, { 3600, 0, 0, 0, 0 } }, - // Meteor - { 205, { 6150, 0, 0, 0, 0 } }, - // Healing Wind - { 206, { 0, 0, 0, 0, 0 } }, - // Breath of the Earth - { 207, { 0, 0, 0, 0, 0 } }, - // Pulse of Life - { 208, { 0, 0, 0, 0, 0 } }, - // Magitek Cannon - { 1128, { 0, 0, 0, 0, 0 } }, - // Photon Stream - { 1129, { 0, 0, 0, 0, 0 } }, - // attack - { 1533, { 0, 0, 0, 0, 0 } }, - // Spinning Edge - { 2240, { 150, 0, 0, 0, 0 } }, - // Shade Shift - { 2241, { 0, 0, 0, 0, 0 } }, - // Gust Slash - { 2242, { 100, 0, 0, 0, 0 } }, - // Hide - { 2245, { 0, 0, 0, 0, 0 } }, - // Assassinate - { 2246, { 200, 0, 0, 0, 0 } }, - // Throwing Dagger - { 2247, { 120, 0, 0, 0, 0 } }, - // Mug - { 2248, { 140, 0, 0, 0, 0 } }, - // Hide - { 2253, { 0, 0, 0, 0, 0 } }, - // Death Blossom - { 2254, { 110, 0, 0, 0, 0 } }, - // Aeolian Edge - { 2255, { 100, 0, 0, 160, 0 } }, - // Jugulate - { 2256, { 80, 0, 0, 0, 0 } }, - // Shadow Fang - { 2257, { 100, 0, 0, 0, 0 } }, - // Trick Attack - { 2258, { 240, 0, 0, 400, 0 } }, - // Ten - { 2259, { 0, 0, 0, 0, 0 } }, - // Ninjutsu - { 2260, { 0, 0, 0, 0, 0 } }, - // Chi - { 2261, { 0, 0, 0, 0, 0 } }, - // Shukuchi - { 2262, { 0, 0, 0, 0, 0 } }, - // Jin - { 2263, { 0, 0, 0, 0, 0 } }, - // Kassatsu - { 2264, { 0, 0, 0, 0, 0 } }, - // Fuma Shuriken - { 2265, { 240, 0, 0, 0, 0 } }, - // Katon - { 2266, { 250, 0, 0, 0, 0 } }, - // Raiton - { 2267, { 360, 0, 0, 0, 0 } }, - // Hyoton - { 2268, { 140, 0, 0, 0, 0 } }, - // Huton - { 2269, { 0, 0, 0, 0, 0 } }, - // Doton - { 2270, { 45, 0, 0, 0, 0 } }, - // Suiton - { 2271, { 180, 0, 0, 0, 0 } }, - // Rabbit Medium - { 2272, { 0, 0, 0, 0, 0 } }, - // Rook Autoturret - { 2864, { 80, 0, 0, 0, 0 } }, - // Bishop Autoturret - { 2865, { 60, 0, 0, 0, 0 } }, - // Split Shot - { 2866, { 160, 0, 0, 0, 0 } }, - // Reload - { 2867, { 0, 0, 0, 0, 0 } }, - // Slug Shot - { 2868, { 100, 0, 0, 0, 0 } }, - // Spread Shot - { 2870, { 80, 0, 0, 0, 0 } }, - // Hot Shot - { 2872, { 120, 0, 0, 0, 0 } }, - // Clean Shot - { 2873, { 100, 0, 0, 0, 0 } }, - // Gauss Round - { 2874, { 210, 0, 0, 0, 0 } }, - // Heartbreak - { 2875, { 240, 0, 0, 0, 0 } }, - // Reassemble - { 2876, { 0, 0, 0, 0, 0 } }, - // Wildfire - { 2878, { 0, 0, 0, 0, 0 } }, - // Quick Reload - { 2879, { 0, 0, 0, 0, 0 } }, - // Gauss Barrel - { 2880, { 0, 0, 0, 0, 0 } }, - // Rapid Fire - { 2881, { 0, 0, 0, 0, 0 } }, - // Hypercharge - { 2885, { 0, 0, 0, 0, 0 } }, - // Dismantle - { 2887, { 0, 0, 0, 0, 0 } }, - // Blank - { 2888, { 0, 0, 0, 0, 0 } }, - // Ricochet - { 2890, { 320, 0, 0, 0, 0 } }, - // Raiton - { 3203, { 0, 0, 0, 0, 0 } }, - // Raiton - { 3204, { 0, 0, 0, 0, 0 } }, - // Kanashibari - { 3207, { 0, 0, 0, 0, 0 } }, - // Turret Retrieval - { 3487, { 0, 0, 0, 0, 0 } }, - // Goring Blade - { 3538, { 100, 0, 0, 0, 0 } }, - // Royal Authority - { 3539, { 100, 0, 0, 0, 0 } }, - // Divine Veil - { 3540, { 0, 0, 0, 0, 0 } }, - // Clemency - { 3541, { 0, 0, 0, 0, 1200 } }, - // Sheltron - { 3542, { 0, 0, 0, 0, 0 } }, - // Tornado Kick - { 3543, { 330, 0, 0, 0, 0 } }, - // Purification - { 3544, { 0, 0, 0, 0, 0 } }, - // Elixir Field - { 3545, { 220, 0, 0, 0, 0 } }, - // Meditation - { 3546, { 0, 0, 0, 0, 0 } }, - // the Forbidden Chakra - { 3547, { 250, 0, 0, 0, 0 } }, - // Deliverance - { 3548, { 0, 0, 0, 0, 0 } }, - // Fell Cleave - { 3549, { 520, 0, 0, 0, 0 } }, - // Decimate - { 3550, { 280, 0, 0, 0, 0 } }, - // Raw Intuition - { 3551, { 0, 0, 0, 0, 0 } }, - // Equilibrium - { 3552, { 0, 0, 0, 0, 1200 } }, - // Blood of the Dragon - { 3553, { 0, 0, 0, 0, 0 } }, - // Fang and Claw - { 3554, { 260, 300, 0, 0, 0 } }, - // Geirskogul - { 3555, { 230, 0, 0, 0, 0 } }, - // Wheeling Thrust - { 3556, { 260, 0, 0, 300, 0 } }, - // Battle Litany - { 3557, { 0, 0, 0, 0, 0 } }, - // Empyreal Arrow - { 3558, { 230, 0, 0, 0, 0 } }, - // the Wanderer's Minuet - { 3559, { 100, 0, 0, 0, 0 } }, - // Iron Jaws - { 3560, { 100, 0, 0, 0, 0 } }, - // the Warden's Paean - { 3561, { 0, 0, 0, 0, 0 } }, - // Sidewinder - { 3562, { 100, 0, 0, 0, 0 } }, - // Armor Crush - { 3563, { 100, 160, 0, 0, 0 } }, - // Shadewalker - { 3564, { 0, 0, 0, 0, 0 } }, - // Smoke Screen - { 3565, { 0, 0, 0, 0, 0 } }, - // Dream Within a Dream - { 3566, { 150, 0, 0, 0, 0 } }, - // Duality - { 3567, { 0, 0, 0, 0, 0 } }, - // Stone III - { 3568, { 210, 0, 0, 0, 0 } }, - // Asylum - { 3569, { 0, 0, 0, 0, 100 } }, - // Tetragrammaton - { 3570, { 0, 0, 0, 0, 700 } }, - // Assize - { 3571, { 400, 0, 0, 0, 400 } }, - // Aero III - { 3572, { 50, 0, 0, 0, 0 } }, - // Ley Lines - { 3573, { 0, 0, 0, 0, 0 } }, - // Sharpcast - { 3574, { 0, 0, 0, 0, 0 } }, - // Enochian - { 3575, { 0, 0, 0, 0, 0 } }, - // Blizzard IV - { 3576, { 260, 0, 0, 0, 0 } }, - // Fire IV - { 3577, { 300, 0, 0, 0, 0 } }, - // Painflare - { 3578, { 180, 0, 0, 0, 0 } }, - // Ruin III - { 3579, { 120, 0, 0, 0, 0 } }, - // Tri-disaster - { 3580, { 0, 0, 0, 0, 0 } }, - // Dreadwyrm Trance - { 3581, { 0, 0, 0, 0, 0 } }, - // Deathflare - { 3582, { 400, 0, 0, 0, 0 } }, - // Indomitability - { 3583, { 0, 0, 0, 0, 500 } }, - // Broil - { 3584, { 190, 0, 0, 0, 0 } }, - // Deployment Tactics - { 3585, { 0, 0, 0, 0, 0 } }, - // Emergency Tactics - { 3586, { 0, 0, 0, 0, 0 } }, - // Dissipation - { 3587, { 0, 0, 0, 0, 0 } }, - // Draw - { 3590, { 0, 0, 0, 0, 0 } }, - // Royal Road - { 3591, { 0, 0, 0, 0, 0 } }, - // Spread - { 3592, { 0, 0, 0, 0, 0 } }, - // Redraw - { 3593, { 0, 0, 0, 0, 0 } }, - // Benefic - { 3594, { 0, 0, 0, 0, 400 } }, - // Aspected Benefic - { 3595, { 0, 0, 0, 0, 200 } }, - // Malefic - { 3596, { 150, 0, 0, 0, 0 } }, - // Malefic II - { 3598, { 180, 0, 0, 0, 0 } }, - // Combust - { 3599, { 0, 0, 0, 0, 0 } }, - // Helios - { 3600, { 0, 0, 0, 0, 300 } }, - // Aspected Helios - { 3601, { 0, 0, 0, 0, 200 } }, - // Ascend - { 3603, { 0, 0, 0, 0, 0 } }, - // Diurnal Sect - { 3604, { 0, 0, 0, 0, 0 } }, - // Nocturnal Sect - { 3605, { 0, 0, 0, 0, 0 } }, - // Lightspeed - { 3606, { 0, 0, 0, 0, 0 } }, - // Combust II - { 3608, { 0, 0, 0, 0, 0 } }, - // Benefic II - { 3610, { 0, 0, 0, 0, 650 } }, - // Time Dilation - { 3611, { 0, 0, 0, 0, 0 } }, - // Synastry - { 3612, { 0, 0, 0, 0, 0 } }, - // Collective Unconscious - { 3613, { 0, 0, 0, 0, 150 } }, - // Essential Dignity - { 3614, { 0, 0, 0, 0, 400 } }, - // Gravity - { 3615, { 200, 0, 0, 0, 0 } }, - // Celestial Opposition - { 3616, { 0, 0, 0, 0, 0 } }, - // Hard Slash - { 3617, { 150, 0, 0, 0, 0 } }, - // Spinning Slash - { 3619, { 100, 0, 0, 0, 0 } }, - // Unleash - { 3621, { 50, 0, 0, 0, 0 } }, - // Syphon Strike - { 3623, { 100, 0, 0, 0, 0 } }, - // Unmend - { 3624, { 150, 0, 0, 0, 0 } }, - // Blood Weapon - { 3625, { 0, 0, 0, 0, 0 } }, - // Power Slash - { 3627, { 100, 0, 0, 0, 0 } }, - // Darkside - { 3628, { 0, 0, 0, 0, 0 } }, - // Grit - { 3629, { 0, 0, 0, 0, 0 } }, - // Blood Price - { 3631, { 0, 0, 0, 0, 0 } }, - // Souleater - { 3632, { 100, 0, 0, 0, 0 } }, - // Dark Passenger - { 3633, { 140, 0, 0, 0, 0 } }, - // Dark Mind - { 3634, { 0, 0, 0, 0, 0 } }, - // Dark Arts - { 3635, { 0, 0, 0, 0, 0 } }, - // Shadow Wall - { 3636, { 0, 0, 0, 0, 0 } }, - // Living Dead - { 3638, { 0, 0, 0, 0, 0 } }, - // Salted Earth - { 3639, { 75, 0, 0, 0, 0 } }, - // Plunge - { 3640, { 200, 0, 0, 0, 0 } }, - // Abyssal Drain - { 3641, { 120, 0, 0, 0, 0 } }, - // Sole Survivor - { 3642, { 0, 0, 0, 0, 0 } }, - // Carve and Spit - { 3643, { 100, 0, 0, 0, 0 } }, - // Big Shot - { 4238, { 0, 0, 0, 0, 0 } }, - // Desperado - { 4239, { 0, 0, 0, 0, 0 } }, - // Land Waker - { 4240, { 0, 0, 0, 0, 0 } }, - // Dark Force - { 4241, { 0, 0, 0, 0, 0 } }, - // Dragonsong Dive - { 4242, { 0, 0, 0, 0, 0 } }, - // Chimatsuri - { 4243, { 0, 0, 0, 0, 0 } }, - // Sagittarius Arrow - { 4244, { 0, 0, 0, 0, 0 } }, - // Satellite Beam - { 4245, { 0, 0, 0, 0, 0 } }, - // Teraflare - { 4246, { 0, 0, 0, 0, 0 } }, - // Angel Feathers - { 4247, { 0, 0, 0, 0, 0 } }, - // Astral Stasis - { 4248, { 0, 0, 0, 0, 0 } }, - // Form Shift - { 4262, { 0, 0, 0, 0, 0 } }, - // Cannonfire - { 4271, { 0, 0, 0, 0, 0 } }, - // the Balance - { 4401, { 0, 0, 0, 0, 0 } }, - // the Bole - { 4402, { 0, 0, 0, 0, 0 } }, - // the Arrow - { 4403, { 0, 0, 0, 0, 0 } }, - // the Spear - { 4404, { 0, 0, 0, 0, 0 } }, - // the Ewer - { 4405, { 0, 0, 0, 0, 0 } }, - // the Spire - { 4406, { 0, 0, 0, 0, 0 } }, - // the Balance - { 4407, { 0, 0, 0, 0, 0 } }, - // the Bole - { 4408, { 0, 0, 0, 0, 0 } }, - // the Arrow - { 4409, { 0, 0, 0, 0, 0 } }, - // the Spear - { 4410, { 0, 0, 0, 0, 0 } }, - // the Ewer - { 4411, { 0, 0, 0, 0, 0 } }, - // the Spire - { 4412, { 0, 0, 0, 0, 0 } }, - // the Balance - { 4413, { 0, 0, 0, 0, 0 } }, - // the Bole - { 4414, { 0, 0, 0, 0, 0 } }, - // the Arrow - { 4415, { 0, 0, 0, 0, 0 } }, - // the Spear - { 4416, { 0, 0, 0, 0, 0 } }, - // the Ewer - { 4417, { 0, 0, 0, 0, 0 } }, - // the Spire - { 4418, { 0, 0, 0, 0, 0 } }, - // the Balance - { 4419, { 0, 0, 0, 0, 0 } }, - // the Bole - { 4420, { 0, 0, 0, 0, 0 } }, - // the Arrow - { 4421, { 0, 0, 0, 0, 0 } }, - // the Spear - { 4422, { 0, 0, 0, 0, 0 } }, - // the Ewer - { 4423, { 0, 0, 0, 0, 0 } }, - // the Spire - { 4424, { 0, 0, 0, 0, 0 } }, - // Empty Road - { 4645, { 0, 0, 0, 0, 0 } }, - // Undraw Spread - { 4646, { 0, 0, 0, 0, 0 } }, - // Raiton - { 4977, { 0, 0, 0, 0, 0 } }, - // Raiton - { 5069, { 0, 0, 0, 0, 0 } }, - // attack - { 5199, { 0, 0, 0, 0, 0 } }, - // attack - { 5846, { 0, 0, 0, 0, 0 } }, - // Stickyloom - { 5874, { 0, 0, 0, 0, 0 } }, - // Void Fire II - { 6274, { 0, 0, 0, 0, 0 } }, - // Total Eclipse - { 7381, { 110, 0, 0, 0, 0 } }, - // Intervention - { 7382, { 0, 0, 0, 0, 0 } }, - // Requiescat - { 7383, { 350, 0, 0, 0, 0 } }, - // Holy Spirit - { 7384, { 380, 0, 0, 0, 0 } }, - // Passage of Arms - { 7385, { 0, 0, 0, 0, 0 } }, - // Onslaught - { 7386, { 100, 0, 0, 0, 0 } }, - // Upheaval - { 7387, { 300, 0, 0, 0, 0 } }, - // Shake It Off - { 7388, { 0, 0, 0, 0, 0 } }, - // Inner Release - { 7389, { 0, 0, 0, 0, 0 } }, - // Delirium - { 7390, { 0, 0, 0, 0, 0 } }, - // Quietus - { 7391, { 160, 0, 0, 0, 0 } }, - // Bloodspiller - { 7392, { 400, 0, 0, 0, 0 } }, - // The Blackest Night - { 7393, { 0, 0, 0, 0, 0 } }, - // Riddle of Earth - { 7394, { 0, 0, 0, 0, 0 } }, - // Riddle of Fire - { 7395, { 0, 0, 0, 0, 0 } }, - // Brotherhood - { 7396, { 0, 0, 0, 0, 0 } }, - // Sonic Thrust - { 7397, { 100, 0, 0, 0, 0 } }, - // Dragon Sight - { 7398, { 0, 0, 0, 0, 0 } }, - // Mirage Dive - { 7399, { 210, 0, 0, 0, 0 } }, - // Nastrond - { 7400, { 330, 0, 0, 0, 0 } }, - // Hellfrog Medium - { 7401, { 400, 0, 0, 0, 0 } }, - // Bhavacakra - { 7402, { 600, 0, 0, 0, 0 } }, - // Ten Chi Jin - { 7403, { 0, 0, 0, 0, 0 } }, - // Pitch Perfect - { 7404, { 100, 0, 0, 0, 0 } }, - // Troubadour - { 7405, { 0, 0, 0, 0, 0 } }, - // Caustic Bite - { 7406, { 120, 0, 0, 0, 0 } }, - // Stormbite - { 7407, { 120, 0, 0, 0, 0 } }, - // Nature's Minne - { 7408, { 0, 0, 0, 0, 0 } }, - // Refulgent Arrow - { 7409, { 300, 0, 0, 0, 0 } }, - // Cooldown - { 7410, { 150, 0, 0, 0, 0 } }, - // Heated Split Shot - { 7411, { 190, 0, 0, 0, 0 } }, - // Heated Slug Shot - { 7412, { 100, 0, 0, 0, 0 } }, - // Heated Clean Shot - { 7413, { 100, 0, 0, 0, 0 } }, - // Barrel Stabilizer - { 7414, { 0, 0, 0, 0, 0 } }, - // Rook Overdrive - { 7415, { 0, 0, 0, 0, 0 } }, - // Flamethrower - { 7418, { 0, 0, 0, 0, 0 } }, - // Between the Lines - { 7419, { 0, 0, 0, 0, 0 } }, - // Thunder IV - { 7420, { 50, 0, 0, 0, 0 } }, - // Triplecast - { 7421, { 0, 0, 0, 0, 0 } }, - // Foul - { 7422, { 650, 0, 0, 0, 0 } }, - // Aetherpact - { 7423, { 0, 0, 0, 0, 0 } }, - // Bio III - { 7424, { 0, 0, 0, 0, 0 } }, - // Miasma III - { 7425, { 50, 0, 0, 0, 0 } }, - // Ruin IV - { 7426, { 200, 0, 0, 0, 0 } }, - // Summon Bahamut - { 7427, { 0, 0, 0, 0, 0 } }, - // Enkindle Bahamut - { 7429, { 0, 0, 0, 0, 0 } }, - // Thin Air - { 7430, { 0, 0, 0, 0, 0 } }, - // Stone IV - { 7431, { 250, 0, 0, 0, 0 } }, - // Divine Benison - { 7432, { 0, 0, 0, 0, 0 } }, - // Plenary Indulgence - { 7433, { 0, 0, 0, 0, 0 } }, - // Excogitation - { 7434, { 0, 0, 0, 0, 800 } }, - // Broil II - { 7435, { 230, 0, 0, 0, 0 } }, - // Chain Stratagem - { 7436, { 0, 0, 0, 0, 0 } }, - // Aetherpact - { 7437, { 0, 0, 0, 0, 0 } }, - // Earthly Star - { 7439, { 150, 0, 0, 0, 540 } }, - // Malefic III - { 7442, { 220, 0, 0, 0, 0 } }, - // Minor Arcana - { 7443, { 0, 0, 0, 0, 0 } }, - // Lord of Crowns - { 7444, { 300, 0, 0, 0, 0 } }, - // Lady of Crowns - { 7445, { 0, 0, 0, 0, 500 } }, - // Thunder II - { 7447, { 30, 0, 0, 0, 0 } }, - // Sleeve Draw - { 7448, { 0, 0, 0, 0, 0 } }, - // Hakaze - { 7477, { 150, 0, 0, 0, 0 } }, - // Jinpu - { 7478, { 100, 0, 0, 0, 0 } }, - // Shifu - { 7479, { 100, 0, 0, 0, 0 } }, - // Yukikaze - { 7480, { 100, 0, 0, 0, 0 } }, - // Gekko - { 7481, { 100, 0, 0, 0, 0 } }, - // Kasha - { 7482, { 100, 0, 0, 0, 0 } }, - // Fuga - { 7483, { 100, 0, 0, 0, 0 } }, - // Mangetsu - { 7484, { 100, 0, 0, 0, 0 } }, - // Oka - { 7485, { 100, 0, 0, 0, 0 } }, - // Enpi - { 7486, { 100, 0, 0, 0, 0 } }, - // Midare Setsugekka - { 7487, { 720, 0, 0, 0, 0 } }, - // Tenka Goken - { 7488, { 360, 0, 0, 0, 0 } }, - // Higanbana - { 7489, { 240, 0, 0, 0, 0 } }, - // Hissatsu: Shinten - { 7490, { 300, 0, 0, 0, 0 } }, - // Hissatsu: Kyuten - { 7491, { 150, 0, 0, 0, 0 } }, - // Hissatsu: Gyoten - { 7492, { 100, 0, 0, 0, 0 } }, - // Hissatsu: Yaten - { 7493, { 100, 0, 0, 0, 0 } }, - // Hissatsu: Kaiten - { 7494, { 0, 0, 0, 0, 0 } }, - // Hagakure - { 7495, { 0, 0, 0, 0, 0 } }, - // Hissatsu: Guren - { 7496, { 800, 0, 0, 0, 0 } }, - // Meditate - { 7497, { 0, 0, 0, 0, 0 } }, - // Third Eye - { 7498, { 0, 0, 0, 0, 0 } }, - // Meikyo Shisui - { 7499, { 0, 0, 0, 0, 0 } }, - // Ageha - { 7500, { 250, 0, 0, 0, 0 } }, - // Hissatsu: Seigan - { 7501, { 200, 0, 0, 0, 0 } }, - // Merciful Eyes - { 7502, { 0, 0, 0, 0, 200 } }, - // Jolt - { 7503, { 180, 0, 0, 0, 0 } }, - // Riposte - { 7504, { 130, 0, 0, 0, 0 } }, - // Verthunder - { 7505, { 310, 0, 0, 0, 0 } }, - // Corps-a-corps - { 7506, { 130, 0, 0, 0, 0 } }, - // Veraero - { 7507, { 310, 0, 0, 0, 0 } }, - // Tether - { 7508, { 0, 0, 0, 0, 0 } }, - // Scatter - { 7509, { 100, 0, 0, 0, 0 } }, - // Verfire - { 7510, { 270, 0, 0, 0, 0 } }, - // Verstone - { 7511, { 270, 0, 0, 0, 0 } }, - // Zwerchhau - { 7512, { 100, 0, 0, 0, 0 } }, - // Moulinet - { 7513, { 60, 0, 0, 0, 0 } }, - // Vercure - { 7514, { 0, 0, 0, 0, 350 } }, - // Displacement - { 7515, { 130, 0, 0, 0, 0 } }, - // Redoublement - { 7516, { 100, 0, 0, 0, 0 } }, - // Fleche - { 7517, { 420, 0, 0, 0, 0 } }, - // Acceleration - { 7518, { 0, 0, 0, 0, 0 } }, - // Contre Sixte - { 7519, { 350, 0, 0, 0, 0 } }, - // Embolden - { 7520, { 0, 0, 0, 0, 0 } }, - // Manafication - { 7521, { 0, 0, 0, 0, 0 } }, - // Impact - { 7522, { 270, 0, 0, 0, 0 } }, - // Verraise - { 7523, { 0, 0, 0, 0, 0 } }, - // Jolt II - { 7524, { 240, 0, 0, 0, 0 } }, - // Verflare - { 7525, { 600, 0, 0, 0, 0 } }, - // Verholy - { 7526, { 600, 0, 0, 0, 0 } }, - // Enchanted Riposte - { 7527, { 210, 0, 0, 0, 0 } }, - // Enchanted Zwerchhau - { 7528, { 100, 0, 0, 0, 0 } }, - // Enchanted Redoublement - { 7529, { 100, 0, 0, 0, 0 } }, - // Enchanted Moulinet - { 7530, { 200, 0, 0, 0, 0 } }, - // Magitek Cannon - { 7619, { 0, 0, 0, 0, 0 } }, - // Photon Stream - { 7620, { 0, 0, 0, 0, 0 } }, - // Diffractive Magitek Cannon - { 7621, { 0, 0, 0, 0, 0 } }, - // High-powered Magitek Cannon - { 7622, { 0, 0, 0, 0, 0 } }, - // Doom of the Living - { 7861, { 0, 0, 0, 0, 0 } }, - // Vermillion Scourge - { 7862, { 0, 0, 0, 0, 0 } }, - // Earth Tackle - { 7864, { 100, 0, 0, 0, 0 } }, - // Wind Tackle - { 7865, { 65, 0, 0, 0, 0 } }, - // Fire Tackle - { 7866, { 130, 0, 0, 0, 0 } }, - // Iaijutsu - { 7867, { 0, 0, 0, 0, 0 } }, - // Riddle of Wind - { 7868, { 65, 0, 0, 0, 0 } }, - // Dissolve Union - { 7869, { 0, 0, 0, 0, 0 } }, - // Stellar Detonation - { 8324, { 150, 0, 0, 0, 540 } }, - // Broken Ridge - { 8395, { 0, 0, 0, 0, 0 } }, - // Magitek Pulse - { 8624, { 0, 0, 0, 0, 0 } }, - // Magitek Thunder - { 8625, { 0, 0, 0, 0, 0 } }, - // attack - { 8687, { 0, 0, 0, 0, 0 } }, - // Katon - { 9012, { 0, 0, 0, 0, 0 } }, - // Remove Barrel - { 9015, { 0, 0, 0, 0, 0 } }, - // Tenka Goken - { 9143, { 0, 0, 0, 0, 0 } }, - // Thunderous Force - { 9294, { 0, 0, 0, 0, 0 } }, - // Raiton - { 9301, { 0, 0, 0, 0, 0 } }, - // Raiton - { 9302, { 0, 0, 0, 0, 0 } }, - // Bishop Overdrive - { 9372, { 0, 0, 0, 0, 0 } }, - // Undraw - { 9629, { 0, 0, 0, 0, 0 } }, - // Self-detonate - { 9775, { 0, 0, 0, 0, 0 } }, - // Shatterstone - { 9823, { 0, 0, 0, 0, 0 } }, - // attack - { 9996, { 0, 0, 0, 0, 0 } }, - // Ungarmax - { 10001, { 0, 0, 0, 0, 0 } }, - // Starstorm - { 10894, { 0, 0, 0, 0, 0 } }, - // attack - { 10946, { 0, 0, 0, 0, 0 } }, - // attack - { 10947, { 0, 0, 0, 0, 0 } }, - // Ruin III - { 11191, { 200, 0, 0, 0, 0 } }, - // Physick - { 11192, { 0, 0, 0, 0, 400 } }, - // Starstorm - { 11193, { 3600, 0, 0, 0, 0 } }, - // Snort - { 11383, { 0, 0, 0, 0, 0 } }, - // 4-tonze Weight - { 11384, { 110, 0, 0, 0, 0 } }, - // Water Cannon - { 11385, { 120, 0, 0, 0, 0 } }, - // Song of Torment - { 11386, { 50, 0, 0, 0, 0 } }, - // High Voltage - { 11387, { 90, 0, 0, 0, 0 } }, - // Bad Breath - { 11388, { 0, 0, 0, 0, 0 } }, - // Flying Frenzy - { 11389, { 80, 0, 0, 0, 0 } }, - // Aqua Breath - { 11390, { 90, 0, 0, 0, 0 } }, - // Plaincracker - { 11391, { 130, 0, 0, 0, 0 } }, - // Acorn Bomb - { 11392, { 0, 0, 0, 0, 0 } }, - // Bristle - { 11393, { 0, 0, 0, 0, 0 } }, - // Mind Blast - { 11394, { 100, 0, 0, 0, 0 } }, - // Blood Drain - { 11395, { 20, 0, 0, 0, 0 } }, - // Bomb Toss - { 11396, { 110, 0, 0, 0, 0 } }, - // 1000 Needles - { 11397, { 0, 0, 0, 0, 0 } }, - // Drill Cannons - { 11398, { 120, 0, 0, 0, 0 } }, - // the Look - { 11399, { 130, 0, 0, 0, 0 } }, - // Sharpened Knife - { 11400, { 120, 0, 0, 0, 0 } }, - // Loom - { 11401, { 0, 0, 0, 0, 0 } }, - // Flame Thrower - { 11402, { 130, 0, 0, 0, 0 } }, - // Faze - { 11403, { 0, 0, 0, 0, 0 } }, - // Glower - { 11404, { 130, 0, 0, 0, 0 } }, - // Missile - { 11405, { 0, 0, 0, 0, 0 } }, - // White Wind - { 11406, { 0, 0, 0, 0, 0 } }, - // Final Sting - { 11407, { 1500, 0, 0, 0, 0 } }, - // Self-destruct - { 11408, { 900, 0, 0, 0, 0 } }, - // Transfusion - { 11409, { 0, 0, 0, 0, 0 } }, - // Toad Oil - { 11410, { 0, 0, 0, 0, 0 } }, - // Off-guard - { 11411, { 0, 0, 0, 0, 0 } }, - // Sticky Tongue - { 11412, { 0, 0, 0, 0, 0 } }, - // Tail Screw - { 11413, { 0, 0, 0, 0, 0 } }, - // Level 5 Petrify - { 11414, { 0, 0, 0, 0, 0 } }, - // Moon Flute - { 11415, { 0, 0, 0, 0, 0 } }, - // Doom - { 11416, { 0, 0, 0, 0, 0 } }, - // Mighty Guard - { 11417, { 0, 0, 0, 0, 0 } }, - // Ice Spikes - { 11418, { 0, 0, 0, 0, 0 } }, - // the Ram's Voice - { 11419, { 130, 0, 0, 0, 0 } }, - // the Dragon's Voice - { 11420, { 110, 0, 0, 0, 0 } }, - // Peculiar Light - { 11421, { 0, 0, 0, 0, 0 } }, - // Ink Jet - { 11422, { 120, 0, 0, 0, 0 } }, - // Flying Sardine - { 11423, { 10, 0, 0, 0, 0 } }, - // Diamondback - { 11424, { 0, 0, 0, 0, 0 } }, - // Fire Angon - { 11425, { 100, 0, 0, 0, 0 } }, - // Feather Rain - { 11426, { 180, 0, 0, 0, 0 } }, - // Eruption - { 11427, { 220, 0, 0, 0, 0 } }, - // Mountain Buster - { 11428, { 310, 0, 0, 0, 0 } }, - // Shock Strike - { 11429, { 310, 0, 0, 0, 0 } }, - // Glass Dance - { 11430, { 290, 0, 0, 0, 0 } }, - // Veil of the Whorl - { 11431, { 0, 0, 0, 0, 0 } }, - // Tri-shackle - { 11482, { 30, 0, 0, 0, 0 } }, - // attack - { 11784, { 0, 0, 0, 0, 0 } }, - // Stone of the Seventh Dawn - { 13423, { 140, 0, 0, 0, 0 } }, - // Aero of the Seventh Dawn - { 13424, { 50, 0, 0, 0, 0 } }, - // Cure of the Seventh Dawn - { 13425, { 0, 0, 0, 0, 700 } }, - // Aetherwell - { 13426, { 0, 0, 0, 0, 0 } }, - // Thunderous Force - { 14587, { 0, 0, 0, 0, 0 } }, - // Kyokufu - { 14840, { 180, 0, 0, 0, 0 } }, - // Ajisai - { 14841, { 100, 0, 0, 0, 0 } }, - // Hissatsu: Gyoten - { 14842, { 100, 0, 0, 0, 0 } }, - // 冥界恐叫打 - { 14843, { 0, 0, 0, 0, 0 } }, - // Second Wind - { 15375, { 0, 0, 0, 0, 500 } }, + auto it = m_actionLut.find( actionId ); -}; \ No newline at end of file + if( it == m_actionLut.end() ) + return false; + + const auto& entry = it->second; + + // if all of the fields are 0, it's not 'valid' due to parse error or no useful data in the tooltip + return entry.potency != 0 || entry.comboPotency != 0 || entry.flankPotency != 0 || entry.frontPotency != 0 || + entry.rearPotency != 0 || entry.curePotency != 0; +} \ No newline at end of file diff --git a/src/world/Action/ActionLut.h b/src/world/Action/ActionLut.h index df2e5332..36949eb5 100644 --- a/src/world/Action/ActionLut.h +++ b/src/world/Action/ActionLut.h @@ -21,6 +21,8 @@ namespace Sapphire::World::Action public: using Lut = std::unordered_map< uint16_t, ActionEntry >; + static bool validEntryExists( uint16_t actionId ); + static Lut m_actionLut; }; } diff --git a/src/world/Action/ActionLutData.cpp b/src/world/Action/ActionLutData.cpp new file mode 100644 index 00000000..1e9c1f97 --- /dev/null +++ b/src/world/Action/ActionLutData.cpp @@ -0,0 +1,1120 @@ +#include "ActionLut.h" + +using namespace Sapphire::World::Action; + +ActionLut::Lut ActionLut::m_actionLut = +{ + // attack + { 7, { 0, 0, 0, 0, 0 } }, + // Shot + { 8, { 0, 0, 0, 0, 0 } }, + // Fast Blade + { 9, { 160, 0, 0, 0, 0 } }, + // Savage Blade + { 11, { 100, 0, 0, 0, 0 } }, + // Flash + { 14, { 0, 0, 0, 0, 0 } }, + // Riot Blade + { 15, { 100, 0, 0, 0, 0 } }, + // Shield Bash + { 16, { 110, 0, 0, 0, 0 } }, + // Sentinel + { 17, { 0, 0, 0, 0, 0 } }, + // Tempered Will + { 19, { 0, 0, 0, 0, 0 } }, + // Fight or Flight + { 20, { 0, 0, 0, 0, 0 } }, + // Rage of Halone + { 21, { 100, 0, 0, 0, 0 } }, + // Bulwark + { 22, { 0, 0, 0, 0, 0 } }, + // Circle of Scorn + { 23, { 100, 0, 0, 0, 0 } }, + // Shield Lob + { 24, { 120, 0, 0, 0, 0 } }, + // Shield Swipe + { 25, { 100, 0, 0, 0, 0 } }, + // Sword Oath + { 26, { 75, 0, 0, 0, 0 } }, + // Cover + { 27, { 0, 0, 0, 0, 0 } }, + // Shield Oath + { 28, { 0, 0, 0, 0, 0 } }, + // Spirits Within + { 29, { 300, 0, 0, 0, 0 } }, + // Hallowed Ground + { 30, { 0, 0, 0, 0, 0 } }, + // Heavy Swing + { 31, { 160, 0, 0, 0, 0 } }, + // Skull Sunder + { 35, { 100, 0, 0, 0, 0 } }, + // Maim + { 37, { 100, 0, 0, 0, 0 } }, + // Berserk + { 38, { 0, 0, 0, 0, 0 } }, + // Thrill of Battle + { 40, { 0, 0, 0, 0, 0 } }, + // Overpower + { 41, { 130, 0, 0, 0, 0 } }, + // Storm's Path + { 42, { 100, 0, 0, 0, 0 } }, + // Holmgang + { 43, { 0, 0, 0, 0, 0 } }, + // Vengeance + { 44, { 55, 0, 0, 0, 0 } }, + // Storm's Eye + { 45, { 100, 0, 0, 0, 0 } }, + // Tomahawk + { 46, { 140, 0, 0, 0, 0 } }, + // Butcher's Block + { 47, { 100, 0, 0, 0, 0 } }, + // Defiance + { 48, { 0, 0, 0, 0, 0 } }, + // Inner Beast + { 49, { 350, 0, 0, 0, 0 } }, + // Unchained + { 50, { 0, 0, 0, 0, 0 } }, + // Steel Cyclone + { 51, { 200, 0, 0, 0, 0 } }, + // Infuriate + { 52, { 0, 0, 0, 0, 0 } }, + // Bootshine + { 53, { 140, 0, 0, 0, 0 } }, + // True Strike + { 54, { 160, 0, 0, 180, 0 } }, + // Snap Punch + { 56, { 150, 170, 0, 0, 0 } }, + // Internal Release + { 59, { 0, 0, 0, 0, 0 } }, + // Fists of Earth + { 60, { 0, 0, 0, 0, 0 } }, + // Twin Snakes + { 61, { 110, 130, 0, 0, 0 } }, + // Arm of the Destroyer + { 62, { 50, 0, 0, 0, 0 } }, + // Fists of Fire + { 63, { 0, 0, 0, 0, 0 } }, + // Steel Peak + { 64, { 150, 0, 0, 0, 0 } }, + // Mantra + { 65, { 0, 0, 0, 0, 0 } }, + // Demolish + { 66, { 50, 0, 0, 70, 0 } }, + // Howling Fist + { 67, { 210, 0, 0, 0, 0 } }, + // Perfect Balance + { 69, { 0, 0, 0, 0, 0 } }, + // Rockbreaker + { 70, { 130, 0, 0, 0, 0 } }, + // Shoulder Tackle + { 71, { 100, 0, 0, 0, 0 } }, + // One Ilm Punch + { 72, { 120, 0, 0, 0, 0 } }, + // Fists of Wind + { 73, { 0, 0, 0, 0, 0 } }, + // Dragon Kick + { 74, { 120, 140, 0, 0, 0 } }, + // True Thrust + { 75, { 160, 0, 0, 0, 0 } }, + // Vorpal Thrust + { 78, { 100, 0, 0, 0, 0 } }, + // Heavy Thrust + { 79, { 150, 190, 0, 0, 0 } }, + // Impulse Drive + { 81, { 200, 0, 0, 0, 0 } }, + // Life Surge + { 83, { 0, 0, 0, 0, 0 } }, + // Full Thrust + { 84, { 100, 0, 0, 0, 0 } }, + // Blood for Blood + { 85, { 0, 0, 0, 0, 0 } }, + // Doom Spike + { 86, { 140, 0, 0, 0, 0 } }, + // Disembowel + { 87, { 100, 0, 0, 0, 0 } }, + // Chaos Thrust + { 88, { 100, 0, 0, 140, 0 } }, + // Piercing Talon + { 90, { 120, 0, 0, 0, 0 } }, + // Jump + { 92, { 260, 0, 0, 0, 0 } }, + // Elusive Jump + { 94, { 0, 0, 0, 0, 0 } }, + // Spineshatter Dive + { 95, { 210, 0, 0, 0, 0 } }, + // Dragonfire Dive + { 96, { 320, 0, 0, 0, 0 } }, + // Heavy Shot + { 97, { 150, 0, 0, 0, 0 } }, + // Straight Shot + { 98, { 140, 0, 0, 0, 0 } }, + // Venomous Bite + { 100, { 100, 0, 0, 0, 0 } }, + // Raging Strikes + { 101, { 0, 0, 0, 0, 0 } }, + // Misery's End + { 103, { 190, 0, 0, 0, 0 } }, + // Quick Nock + { 106, { 110, 0, 0, 0, 0 } }, + // Barrage + { 107, { 0, 0, 0, 0, 0 } }, + // Bloodletter + { 110, { 130, 0, 0, 0, 0 } }, + // Repelling Shot + { 112, { 0, 0, 0, 0, 0 } }, + // Windbite + { 113, { 60, 0, 0, 0, 0 } }, + // Mage's Ballad + { 114, { 100, 0, 0, 0, 0 } }, + // Foe Requiem + { 115, { 0, 0, 0, 0, 0 } }, + // Army's Paeon + { 116, { 100, 0, 0, 0, 0 } }, + // Rain of Death + { 117, { 100, 0, 0, 0, 0 } }, + // Battle Voice + { 118, { 0, 0, 0, 0, 0 } }, + // Stone + { 119, { 140, 0, 0, 0, 0 } }, + // Cure + { 120, { 0, 0, 0, 0, 450 } }, + // Aero + { 121, { 50, 0, 0, 0, 0 } }, + // Medica + { 124, { 0, 0, 0, 0, 300 } }, + // Raise + { 125, { 0, 0, 0, 0, 0 } }, + // Stone II + { 127, { 200, 0, 0, 0, 0 } }, + // Repose + { 128, { 0, 0, 0, 0, 0 } }, + // Cure III + { 131, { 0, 0, 0, 0, 550 } }, + // Aero II + { 132, { 50, 0, 0, 0, 0 } }, + // Medica II + { 133, { 0, 0, 0, 0, 200 } }, + // Fluid Aura + { 134, { 0, 0, 0, 0, 0 } }, + // Cure II + { 135, { 0, 0, 0, 0, 700 } }, + // Presence of Mind + { 136, { 0, 0, 0, 0, 0 } }, + // Regen + { 137, { 0, 0, 0, 0, 150 } }, + // Holy + { 139, { 200, 0, 0, 0, 0 } }, + // Benediction + { 140, { 0, 0, 0, 0, 0 } }, + // Fire + { 141, { 180, 0, 0, 0, 0 } }, + // Blizzard + { 142, { 180, 0, 0, 0, 0 } }, + // Thunder + { 144, { 30, 0, 0, 0, 0 } }, + // Sleep + { 145, { 0, 0, 0, 0, 0 } }, + // Blizzard II + { 146, { 50, 0, 0, 0, 0 } }, + // Fire II + { 147, { 80, 0, 0, 0, 0 } }, + // Transpose + { 149, { 0, 0, 0, 0, 0 } }, + // Fire III + { 152, { 240, 0, 0, 0, 0 } }, + // Thunder III + { 153, { 70, 0, 0, 0, 0 } }, + // Blizzard III + { 154, { 240, 0, 0, 0, 0 } }, + // Aetherial Manipulation + { 155, { 0, 0, 0, 0, 0 } }, + // Scathe + { 156, { 100, 0, 0, 0, 0 } }, + // Manaward + { 157, { 0, 0, 0, 0, 0 } }, + // Convert + { 158, { 0, 0, 0, 0, 0 } }, + // Freeze + { 159, { 100, 0, 0, 0, 0 } }, + // Flare + { 162, { 260, 0, 0, 0, 0 } }, + // Ruin + { 163, { 100, 0, 0, 0, 0 } }, + // Bio + { 164, { 0, 0, 0, 0, 0 } }, + // Summon + { 165, { 0, 0, 0, 0, 0 } }, + // Aetherflow + { 166, { 0, 0, 0, 0, 0 } }, + // Energy Drain + { 167, { 150, 0, 0, 0, 0 } }, + // Miasma + { 168, { 20, 0, 0, 0, 0 } }, + // Summon II + { 170, { 0, 0, 0, 0, 0 } }, + // Sustain + { 171, { 0, 0, 0, 0, 0 } }, + // Ruin II + { 172, { 100, 0, 0, 0, 0 } }, + // Resurrection + { 173, { 0, 0, 0, 0, 0 } }, + // Bane + { 174, { 0, 0, 0, 0, 0 } }, + // Rouse + { 176, { 0, 0, 0, 0, 0 } }, + // Miasma II + { 177, { 100, 0, 0, 0, 0 } }, + // Bio II + { 178, { 0, 0, 0, 0, 0 } }, + // Shadow Flare + { 179, { 50, 0, 0, 0, 0 } }, + // Summon III + { 180, { 0, 0, 0, 0, 0 } }, + // Fester + { 181, { 150, 0, 0, 0, 0 } }, + // Tri-bind + { 182, { 30, 0, 0, 0, 0 } }, + // Enkindle + { 184, { 0, 0, 0, 0, 0 } }, + // Adloquium + { 185, { 0, 0, 0, 0, 300 } }, + // Succor + { 186, { 0, 0, 0, 0, 150 } }, + // Sacred Soil + { 188, { 0, 0, 0, 0, 0 } }, + // Lustrate + { 189, { 0, 0, 0, 0, 600 } }, + // Physick + { 190, { 0, 0, 0, 0, 400 } }, + // Shield Wall + { 197, { 0, 0, 0, 0, 0 } }, + // Stronghold + { 198, { 0, 0, 0, 0, 0 } }, + // Last Bastion + { 199, { 0, 0, 0, 0, 0 } }, + // Braver + { 200, { 2400, 0, 0, 0, 0 } }, + // Bladedance + { 201, { 5250, 0, 0, 0, 0 } }, + // Final Heaven + { 202, { 9000, 0, 0, 0, 0 } }, + // Skyshard + { 203, { 1650, 0, 0, 0, 0 } }, + // Starstorm + { 204, { 3600, 0, 0, 0, 0 } }, + // Meteor + { 205, { 6150, 0, 0, 0, 0 } }, + // Healing Wind + { 206, { 0, 0, 0, 0, 0 } }, + // Breath of the Earth + { 207, { 0, 0, 0, 0, 0 } }, + // Pulse of Life + { 208, { 0, 0, 0, 0, 0 } }, + // Magitek Cannon + { 1128, { 0, 0, 0, 0, 0 } }, + // Photon Stream + { 1129, { 0, 0, 0, 0, 0 } }, + // attack + { 1533, { 0, 0, 0, 0, 0 } }, + // Spinning Edge + { 2240, { 150, 0, 0, 0, 0 } }, + // Shade Shift + { 2241, { 0, 0, 0, 0, 0 } }, + // Gust Slash + { 2242, { 100, 0, 0, 0, 0 } }, + // Hide + { 2245, { 0, 0, 0, 0, 0 } }, + // Assassinate + { 2246, { 200, 0, 0, 0, 0 } }, + // Throwing Dagger + { 2247, { 120, 0, 0, 0, 0 } }, + // Mug + { 2248, { 140, 0, 0, 0, 0 } }, + // Hide + { 2253, { 0, 0, 0, 0, 0 } }, + // Death Blossom + { 2254, { 110, 0, 0, 0, 0 } }, + // Aeolian Edge + { 2255, { 100, 0, 0, 160, 0 } }, + // Jugulate + { 2256, { 80, 0, 0, 0, 0 } }, + // Shadow Fang + { 2257, { 100, 0, 0, 0, 0 } }, + // Trick Attack + { 2258, { 240, 0, 0, 400, 0 } }, + // Ten + { 2259, { 0, 0, 0, 0, 0 } }, + // Ninjutsu + { 2260, { 0, 0, 0, 0, 0 } }, + // Chi + { 2261, { 0, 0, 0, 0, 0 } }, + // Shukuchi + { 2262, { 0, 0, 0, 0, 0 } }, + // Jin + { 2263, { 0, 0, 0, 0, 0 } }, + // Kassatsu + { 2264, { 0, 0, 0, 0, 0 } }, + // Fuma Shuriken + { 2265, { 240, 0, 0, 0, 0 } }, + // Katon + { 2266, { 250, 0, 0, 0, 0 } }, + // Raiton + { 2267, { 360, 0, 0, 0, 0 } }, + // Hyoton + { 2268, { 140, 0, 0, 0, 0 } }, + // Huton + { 2269, { 0, 0, 0, 0, 0 } }, + // Doton + { 2270, { 45, 0, 0, 0, 0 } }, + // Suiton + { 2271, { 180, 0, 0, 0, 0 } }, + // Rabbit Medium + { 2272, { 0, 0, 0, 0, 0 } }, + // Rook Autoturret + { 2864, { 80, 0, 0, 0, 0 } }, + // Bishop Autoturret + { 2865, { 60, 0, 0, 0, 0 } }, + // Split Shot + { 2866, { 160, 0, 0, 0, 0 } }, + // Reload + { 2867, { 0, 0, 0, 0, 0 } }, + // Slug Shot + { 2868, { 100, 0, 0, 0, 0 } }, + // Spread Shot + { 2870, { 80, 0, 0, 0, 0 } }, + // Hot Shot + { 2872, { 120, 0, 0, 0, 0 } }, + // Clean Shot + { 2873, { 100, 0, 0, 0, 0 } }, + // Gauss Round + { 2874, { 210, 0, 0, 0, 0 } }, + // Heartbreak + { 2875, { 240, 0, 0, 0, 0 } }, + // Reassemble + { 2876, { 0, 0, 0, 0, 0 } }, + // Wildfire + { 2878, { 0, 0, 0, 0, 0 } }, + // Quick Reload + { 2879, { 0, 0, 0, 0, 0 } }, + // Gauss Barrel + { 2880, { 0, 0, 0, 0, 0 } }, + // Rapid Fire + { 2881, { 0, 0, 0, 0, 0 } }, + // Hypercharge + { 2885, { 0, 0, 0, 0, 0 } }, + // Dismantle + { 2887, { 0, 0, 0, 0, 0 } }, + // Blank + { 2888, { 0, 0, 0, 0, 0 } }, + // Ricochet + { 2890, { 320, 0, 0, 0, 0 } }, + // Raiton + { 3203, { 0, 0, 0, 0, 0 } }, + // Raiton + { 3204, { 0, 0, 0, 0, 0 } }, + // Kanashibari + { 3207, { 0, 0, 0, 0, 0 } }, + // Turret Retrieval + { 3487, { 0, 0, 0, 0, 0 } }, + // Goring Blade + { 3538, { 100, 0, 0, 0, 0 } }, + // Royal Authority + { 3539, { 100, 0, 0, 0, 0 } }, + // Divine Veil + { 3540, { 0, 0, 0, 0, 0 } }, + // Clemency + { 3541, { 0, 0, 0, 0, 1200 } }, + // Sheltron + { 3542, { 0, 0, 0, 0, 0 } }, + // Tornado Kick + { 3543, { 330, 0, 0, 0, 0 } }, + // Purification + { 3544, { 0, 0, 0, 0, 0 } }, + // Elixir Field + { 3545, { 220, 0, 0, 0, 0 } }, + // Meditation + { 3546, { 0, 0, 0, 0, 0 } }, + // the Forbidden Chakra + { 3547, { 250, 0, 0, 0, 0 } }, + // Deliverance + { 3548, { 0, 0, 0, 0, 0 } }, + // Fell Cleave + { 3549, { 520, 0, 0, 0, 0 } }, + // Decimate + { 3550, { 280, 0, 0, 0, 0 } }, + // Raw Intuition + { 3551, { 0, 0, 0, 0, 0 } }, + // Equilibrium + { 3552, { 0, 0, 0, 0, 1200 } }, + // Blood of the Dragon + { 3553, { 0, 0, 0, 0, 0 } }, + // Fang and Claw + { 3554, { 260, 300, 0, 0, 0 } }, + // Geirskogul + { 3555, { 230, 0, 0, 0, 0 } }, + // Wheeling Thrust + { 3556, { 260, 0, 0, 300, 0 } }, + // Battle Litany + { 3557, { 0, 0, 0, 0, 0 } }, + // Empyreal Arrow + { 3558, { 230, 0, 0, 0, 0 } }, + // the Wanderer's Minuet + { 3559, { 100, 0, 0, 0, 0 } }, + // Iron Jaws + { 3560, { 100, 0, 0, 0, 0 } }, + // the Warden's Paean + { 3561, { 0, 0, 0, 0, 0 } }, + // Sidewinder + { 3562, { 100, 0, 0, 0, 0 } }, + // Armor Crush + { 3563, { 100, 160, 0, 0, 0 } }, + // Shadewalker + { 3564, { 0, 0, 0, 0, 0 } }, + // Smoke Screen + { 3565, { 0, 0, 0, 0, 0 } }, + // Dream Within a Dream + { 3566, { 150, 0, 0, 0, 0 } }, + // Duality + { 3567, { 0, 0, 0, 0, 0 } }, + // Stone III + { 3568, { 210, 0, 0, 0, 0 } }, + // Asylum + { 3569, { 0, 0, 0, 0, 100 } }, + // Tetragrammaton + { 3570, { 0, 0, 0, 0, 700 } }, + // Assize + { 3571, { 400, 0, 0, 0, 400 } }, + // Aero III + { 3572, { 50, 0, 0, 0, 0 } }, + // Ley Lines + { 3573, { 0, 0, 0, 0, 0 } }, + // Sharpcast + { 3574, { 0, 0, 0, 0, 0 } }, + // Enochian + { 3575, { 0, 0, 0, 0, 0 } }, + // Blizzard IV + { 3576, { 260, 0, 0, 0, 0 } }, + // Fire IV + { 3577, { 300, 0, 0, 0, 0 } }, + // Painflare + { 3578, { 180, 0, 0, 0, 0 } }, + // Ruin III + { 3579, { 120, 0, 0, 0, 0 } }, + // Tri-disaster + { 3580, { 0, 0, 0, 0, 0 } }, + // Dreadwyrm Trance + { 3581, { 0, 0, 0, 0, 0 } }, + // Deathflare + { 3582, { 400, 0, 0, 0, 0 } }, + // Indomitability + { 3583, { 0, 0, 0, 0, 500 } }, + // Broil + { 3584, { 190, 0, 0, 0, 0 } }, + // Deployment Tactics + { 3585, { 0, 0, 0, 0, 0 } }, + // Emergency Tactics + { 3586, { 0, 0, 0, 0, 0 } }, + // Dissipation + { 3587, { 0, 0, 0, 0, 0 } }, + // Draw + { 3590, { 0, 0, 0, 0, 0 } }, + // Royal Road + { 3591, { 0, 0, 0, 0, 0 } }, + // Spread + { 3592, { 0, 0, 0, 0, 0 } }, + // Redraw + { 3593, { 0, 0, 0, 0, 0 } }, + // Benefic + { 3594, { 0, 0, 0, 0, 400 } }, + // Aspected Benefic + { 3595, { 0, 0, 0, 0, 200 } }, + // Malefic + { 3596, { 150, 0, 0, 0, 0 } }, + // Malefic II + { 3598, { 180, 0, 0, 0, 0 } }, + // Combust + { 3599, { 0, 0, 0, 0, 0 } }, + // Helios + { 3600, { 0, 0, 0, 0, 300 } }, + // Aspected Helios + { 3601, { 0, 0, 0, 0, 200 } }, + // Ascend + { 3603, { 0, 0, 0, 0, 0 } }, + // Diurnal Sect + { 3604, { 0, 0, 0, 0, 0 } }, + // Nocturnal Sect + { 3605, { 0, 0, 0, 0, 0 } }, + // Lightspeed + { 3606, { 0, 0, 0, 0, 0 } }, + // Combust II + { 3608, { 0, 0, 0, 0, 0 } }, + // Benefic II + { 3610, { 0, 0, 0, 0, 650 } }, + // Time Dilation + { 3611, { 0, 0, 0, 0, 0 } }, + // Synastry + { 3612, { 0, 0, 0, 0, 0 } }, + // Collective Unconscious + { 3613, { 0, 0, 0, 0, 150 } }, + // Essential Dignity + { 3614, { 0, 0, 0, 0, 400 } }, + // Gravity + { 3615, { 200, 0, 0, 0, 0 } }, + // Celestial Opposition + { 3616, { 0, 0, 0, 0, 0 } }, + // Hard Slash + { 3617, { 150, 0, 0, 0, 0 } }, + // Spinning Slash + { 3619, { 100, 0, 0, 0, 0 } }, + // Unleash + { 3621, { 50, 0, 0, 0, 0 } }, + // Syphon Strike + { 3623, { 100, 0, 0, 0, 0 } }, + // Unmend + { 3624, { 150, 0, 0, 0, 0 } }, + // Blood Weapon + { 3625, { 0, 0, 0, 0, 0 } }, + // Power Slash + { 3627, { 100, 0, 0, 0, 0 } }, + // Darkside + { 3628, { 0, 0, 0, 0, 0 } }, + // Grit + { 3629, { 0, 0, 0, 0, 0 } }, + // Blood Price + { 3631, { 0, 0, 0, 0, 0 } }, + // Souleater + { 3632, { 100, 0, 0, 0, 0 } }, + // Dark Passenger + { 3633, { 140, 0, 0, 0, 0 } }, + // Dark Mind + { 3634, { 0, 0, 0, 0, 0 } }, + // Dark Arts + { 3635, { 0, 0, 0, 0, 0 } }, + // Shadow Wall + { 3636, { 0, 0, 0, 0, 0 } }, + // Living Dead + { 3638, { 0, 0, 0, 0, 0 } }, + // Salted Earth + { 3639, { 75, 0, 0, 0, 0 } }, + // Plunge + { 3640, { 200, 0, 0, 0, 0 } }, + // Abyssal Drain + { 3641, { 120, 0, 0, 0, 0 } }, + // Sole Survivor + { 3642, { 0, 0, 0, 0, 0 } }, + // Carve and Spit + { 3643, { 100, 0, 0, 0, 0 } }, + // Big Shot + { 4238, { 0, 0, 0, 0, 0 } }, + // Desperado + { 4239, { 0, 0, 0, 0, 0 } }, + // Land Waker + { 4240, { 0, 0, 0, 0, 0 } }, + // Dark Force + { 4241, { 0, 0, 0, 0, 0 } }, + // Dragonsong Dive + { 4242, { 0, 0, 0, 0, 0 } }, + // Chimatsuri + { 4243, { 0, 0, 0, 0, 0 } }, + // Sagittarius Arrow + { 4244, { 0, 0, 0, 0, 0 } }, + // Satellite Beam + { 4245, { 0, 0, 0, 0, 0 } }, + // Teraflare + { 4246, { 0, 0, 0, 0, 0 } }, + // Angel Feathers + { 4247, { 0, 0, 0, 0, 0 } }, + // Astral Stasis + { 4248, { 0, 0, 0, 0, 0 } }, + // Form Shift + { 4262, { 0, 0, 0, 0, 0 } }, + // Cannonfire + { 4271, { 0, 0, 0, 0, 0 } }, + // the Balance + { 4401, { 0, 0, 0, 0, 0 } }, + // the Bole + { 4402, { 0, 0, 0, 0, 0 } }, + // the Arrow + { 4403, { 0, 0, 0, 0, 0 } }, + // the Spear + { 4404, { 0, 0, 0, 0, 0 } }, + // the Ewer + { 4405, { 0, 0, 0, 0, 0 } }, + // the Spire + { 4406, { 0, 0, 0, 0, 0 } }, + // the Balance + { 4407, { 0, 0, 0, 0, 0 } }, + // the Bole + { 4408, { 0, 0, 0, 0, 0 } }, + // the Arrow + { 4409, { 0, 0, 0, 0, 0 } }, + // the Spear + { 4410, { 0, 0, 0, 0, 0 } }, + // the Ewer + { 4411, { 0, 0, 0, 0, 0 } }, + // the Spire + { 4412, { 0, 0, 0, 0, 0 } }, + // the Balance + { 4413, { 0, 0, 0, 0, 0 } }, + // the Bole + { 4414, { 0, 0, 0, 0, 0 } }, + // the Arrow + { 4415, { 0, 0, 0, 0, 0 } }, + // the Spear + { 4416, { 0, 0, 0, 0, 0 } }, + // the Ewer + { 4417, { 0, 0, 0, 0, 0 } }, + // the Spire + { 4418, { 0, 0, 0, 0, 0 } }, + // the Balance + { 4419, { 0, 0, 0, 0, 0 } }, + // the Bole + { 4420, { 0, 0, 0, 0, 0 } }, + // the Arrow + { 4421, { 0, 0, 0, 0, 0 } }, + // the Spear + { 4422, { 0, 0, 0, 0, 0 } }, + // the Ewer + { 4423, { 0, 0, 0, 0, 0 } }, + // the Spire + { 4424, { 0, 0, 0, 0, 0 } }, + // Empty Road + { 4645, { 0, 0, 0, 0, 0 } }, + // Undraw Spread + { 4646, { 0, 0, 0, 0, 0 } }, + // Raiton + { 4977, { 0, 0, 0, 0, 0 } }, + // Raiton + { 5069, { 0, 0, 0, 0, 0 } }, + // attack + { 5199, { 0, 0, 0, 0, 0 } }, + // attack + { 5846, { 0, 0, 0, 0, 0 } }, + // Stickyloom + { 5874, { 0, 0, 0, 0, 0 } }, + // Void Fire II + { 6274, { 0, 0, 0, 0, 0 } }, + // Total Eclipse + { 7381, { 110, 0, 0, 0, 0 } }, + // Intervention + { 7382, { 0, 0, 0, 0, 0 } }, + // Requiescat + { 7383, { 350, 0, 0, 0, 0 } }, + // Holy Spirit + { 7384, { 380, 0, 0, 0, 0 } }, + // Passage of Arms + { 7385, { 0, 0, 0, 0, 0 } }, + // Onslaught + { 7386, { 100, 0, 0, 0, 0 } }, + // Upheaval + { 7387, { 300, 0, 0, 0, 0 } }, + // Shake It Off + { 7388, { 0, 0, 0, 0, 0 } }, + // Inner Release + { 7389, { 0, 0, 0, 0, 0 } }, + // Delirium + { 7390, { 0, 0, 0, 0, 0 } }, + // Quietus + { 7391, { 160, 0, 0, 0, 0 } }, + // Bloodspiller + { 7392, { 400, 0, 0, 0, 0 } }, + // The Blackest Night + { 7393, { 0, 0, 0, 0, 0 } }, + // Riddle of Earth + { 7394, { 0, 0, 0, 0, 0 } }, + // Riddle of Fire + { 7395, { 0, 0, 0, 0, 0 } }, + // Brotherhood + { 7396, { 0, 0, 0, 0, 0 } }, + // Sonic Thrust + { 7397, { 100, 0, 0, 0, 0 } }, + // Dragon Sight + { 7398, { 0, 0, 0, 0, 0 } }, + // Mirage Dive + { 7399, { 210, 0, 0, 0, 0 } }, + // Nastrond + { 7400, { 330, 0, 0, 0, 0 } }, + // Hellfrog Medium + { 7401, { 400, 0, 0, 0, 0 } }, + // Bhavacakra + { 7402, { 600, 0, 0, 0, 0 } }, + // Ten Chi Jin + { 7403, { 0, 0, 0, 0, 0 } }, + // Pitch Perfect + { 7404, { 100, 0, 0, 0, 0 } }, + // Troubadour + { 7405, { 0, 0, 0, 0, 0 } }, + // Caustic Bite + { 7406, { 120, 0, 0, 0, 0 } }, + // Stormbite + { 7407, { 120, 0, 0, 0, 0 } }, + // Nature's Minne + { 7408, { 0, 0, 0, 0, 0 } }, + // Refulgent Arrow + { 7409, { 300, 0, 0, 0, 0 } }, + // Cooldown + { 7410, { 150, 0, 0, 0, 0 } }, + // Heated Split Shot + { 7411, { 190, 0, 0, 0, 0 } }, + // Heated Slug Shot + { 7412, { 100, 0, 0, 0, 0 } }, + // Heated Clean Shot + { 7413, { 100, 0, 0, 0, 0 } }, + // Barrel Stabilizer + { 7414, { 0, 0, 0, 0, 0 } }, + // Rook Overdrive + { 7415, { 0, 0, 0, 0, 0 } }, + // Flamethrower + { 7418, { 0, 0, 0, 0, 0 } }, + // Between the Lines + { 7419, { 0, 0, 0, 0, 0 } }, + // Thunder IV + { 7420, { 50, 0, 0, 0, 0 } }, + // Triplecast + { 7421, { 0, 0, 0, 0, 0 } }, + // Foul + { 7422, { 650, 0, 0, 0, 0 } }, + // Aetherpact + { 7423, { 0, 0, 0, 0, 0 } }, + // Bio III + { 7424, { 0, 0, 0, 0, 0 } }, + // Miasma III + { 7425, { 50, 0, 0, 0, 0 } }, + // Ruin IV + { 7426, { 200, 0, 0, 0, 0 } }, + // Summon Bahamut + { 7427, { 0, 0, 0, 0, 0 } }, + // Enkindle Bahamut + { 7429, { 0, 0, 0, 0, 0 } }, + // Thin Air + { 7430, { 0, 0, 0, 0, 0 } }, + // Stone IV + { 7431, { 250, 0, 0, 0, 0 } }, + // Divine Benison + { 7432, { 0, 0, 0, 0, 0 } }, + // Plenary Indulgence + { 7433, { 0, 0, 0, 0, 0 } }, + // Excogitation + { 7434, { 0, 0, 0, 0, 800 } }, + // Broil II + { 7435, { 230, 0, 0, 0, 0 } }, + // Chain Stratagem + { 7436, { 0, 0, 0, 0, 0 } }, + // Aetherpact + { 7437, { 0, 0, 0, 0, 0 } }, + // Earthly Star + { 7439, { 150, 0, 0, 0, 540 } }, + // Malefic III + { 7442, { 220, 0, 0, 0, 0 } }, + // Minor Arcana + { 7443, { 0, 0, 0, 0, 0 } }, + // Lord of Crowns + { 7444, { 300, 0, 0, 0, 0 } }, + // Lady of Crowns + { 7445, { 0, 0, 0, 0, 500 } }, + // Thunder II + { 7447, { 30, 0, 0, 0, 0 } }, + // Sleeve Draw + { 7448, { 0, 0, 0, 0, 0 } }, + // Hakaze + { 7477, { 150, 0, 0, 0, 0 } }, + // Jinpu + { 7478, { 100, 0, 0, 0, 0 } }, + // Shifu + { 7479, { 100, 0, 0, 0, 0 } }, + // Yukikaze + { 7480, { 100, 0, 0, 0, 0 } }, + // Gekko + { 7481, { 100, 0, 0, 0, 0 } }, + // Kasha + { 7482, { 100, 0, 0, 0, 0 } }, + // Fuga + { 7483, { 100, 0, 0, 0, 0 } }, + // Mangetsu + { 7484, { 100, 0, 0, 0, 0 } }, + // Oka + { 7485, { 100, 0, 0, 0, 0 } }, + // Enpi + { 7486, { 100, 0, 0, 0, 0 } }, + // Midare Setsugekka + { 7487, { 720, 0, 0, 0, 0 } }, + // Tenka Goken + { 7488, { 360, 0, 0, 0, 0 } }, + // Higanbana + { 7489, { 240, 0, 0, 0, 0 } }, + // Hissatsu: Shinten + { 7490, { 300, 0, 0, 0, 0 } }, + // Hissatsu: Kyuten + { 7491, { 150, 0, 0, 0, 0 } }, + // Hissatsu: Gyoten + { 7492, { 100, 0, 0, 0, 0 } }, + // Hissatsu: Yaten + { 7493, { 100, 0, 0, 0, 0 } }, + // Hissatsu: Kaiten + { 7494, { 0, 0, 0, 0, 0 } }, + // Hagakure + { 7495, { 0, 0, 0, 0, 0 } }, + // Hissatsu: Guren + { 7496, { 800, 0, 0, 0, 0 } }, + // Meditate + { 7497, { 0, 0, 0, 0, 0 } }, + // Third Eye + { 7498, { 0, 0, 0, 0, 0 } }, + // Meikyo Shisui + { 7499, { 0, 0, 0, 0, 0 } }, + // Ageha + { 7500, { 250, 0, 0, 0, 0 } }, + // Hissatsu: Seigan + { 7501, { 200, 0, 0, 0, 0 } }, + // Merciful Eyes + { 7502, { 0, 0, 0, 0, 200 } }, + // Jolt + { 7503, { 180, 0, 0, 0, 0 } }, + // Riposte + { 7504, { 130, 0, 0, 0, 0 } }, + // Verthunder + { 7505, { 310, 0, 0, 0, 0 } }, + // Corps-a-corps + { 7506, { 130, 0, 0, 0, 0 } }, + // Veraero + { 7507, { 310, 0, 0, 0, 0 } }, + // Tether + { 7508, { 0, 0, 0, 0, 0 } }, + // Scatter + { 7509, { 100, 0, 0, 0, 0 } }, + // Verfire + { 7510, { 270, 0, 0, 0, 0 } }, + // Verstone + { 7511, { 270, 0, 0, 0, 0 } }, + // Zwerchhau + { 7512, { 100, 0, 0, 0, 0 } }, + // Moulinet + { 7513, { 60, 0, 0, 0, 0 } }, + // Vercure + { 7514, { 0, 0, 0, 0, 350 } }, + // Displacement + { 7515, { 130, 0, 0, 0, 0 } }, + // Redoublement + { 7516, { 100, 0, 0, 0, 0 } }, + // Fleche + { 7517, { 420, 0, 0, 0, 0 } }, + // Acceleration + { 7518, { 0, 0, 0, 0, 0 } }, + // Contre Sixte + { 7519, { 350, 0, 0, 0, 0 } }, + // Embolden + { 7520, { 0, 0, 0, 0, 0 } }, + // Manafication + { 7521, { 0, 0, 0, 0, 0 } }, + // Impact + { 7522, { 270, 0, 0, 0, 0 } }, + // Verraise + { 7523, { 0, 0, 0, 0, 0 } }, + // Jolt II + { 7524, { 240, 0, 0, 0, 0 } }, + // Verflare + { 7525, { 600, 0, 0, 0, 0 } }, + // Verholy + { 7526, { 600, 0, 0, 0, 0 } }, + // Enchanted Riposte + { 7527, { 210, 0, 0, 0, 0 } }, + // Enchanted Zwerchhau + { 7528, { 100, 0, 0, 0, 0 } }, + // Enchanted Redoublement + { 7529, { 100, 0, 0, 0, 0 } }, + // Enchanted Moulinet + { 7530, { 200, 0, 0, 0, 0 } }, + // Magitek Cannon + { 7619, { 0, 0, 0, 0, 0 } }, + // Photon Stream + { 7620, { 0, 0, 0, 0, 0 } }, + // Diffractive Magitek Cannon + { 7621, { 0, 0, 0, 0, 0 } }, + // High-powered Magitek Cannon + { 7622, { 0, 0, 0, 0, 0 } }, + // Doom of the Living + { 7861, { 0, 0, 0, 0, 0 } }, + // Vermillion Scourge + { 7862, { 0, 0, 0, 0, 0 } }, + // Earth Tackle + { 7864, { 100, 0, 0, 0, 0 } }, + // Wind Tackle + { 7865, { 65, 0, 0, 0, 0 } }, + // Fire Tackle + { 7866, { 130, 0, 0, 0, 0 } }, + // Iaijutsu + { 7867, { 0, 0, 0, 0, 0 } }, + // Riddle of Wind + { 7868, { 65, 0, 0, 0, 0 } }, + // Dissolve Union + { 7869, { 0, 0, 0, 0, 0 } }, + // Stellar Detonation + { 8324, { 150, 0, 0, 0, 540 } }, + // Broken Ridge + { 8395, { 0, 0, 0, 0, 0 } }, + // Magitek Pulse + { 8624, { 0, 0, 0, 0, 0 } }, + // Magitek Thunder + { 8625, { 0, 0, 0, 0, 0 } }, + // attack + { 8687, { 0, 0, 0, 0, 0 } }, + // Katon + { 9012, { 0, 0, 0, 0, 0 } }, + // Remove Barrel + { 9015, { 0, 0, 0, 0, 0 } }, + // Tenka Goken + { 9143, { 0, 0, 0, 0, 0 } }, + // Thunderous Force + { 9294, { 0, 0, 0, 0, 0 } }, + // Raiton + { 9301, { 0, 0, 0, 0, 0 } }, + // Raiton + { 9302, { 0, 0, 0, 0, 0 } }, + // Bishop Overdrive + { 9372, { 0, 0, 0, 0, 0 } }, + // Undraw + { 9629, { 0, 0, 0, 0, 0 } }, + // Self-detonate + { 9775, { 0, 0, 0, 0, 0 } }, + // Shatterstone + { 9823, { 0, 0, 0, 0, 0 } }, + // attack + { 9996, { 0, 0, 0, 0, 0 } }, + // Ungarmax + { 10001, { 0, 0, 0, 0, 0 } }, + // Starstorm + { 10894, { 0, 0, 0, 0, 0 } }, + // attack + { 10946, { 0, 0, 0, 0, 0 } }, + // attack + { 10947, { 0, 0, 0, 0, 0 } }, + // Ruin III + { 11191, { 200, 0, 0, 0, 0 } }, + // Physick + { 11192, { 0, 0, 0, 0, 400 } }, + // Starstorm + { 11193, { 3600, 0, 0, 0, 0 } }, + // Snort + { 11383, { 0, 0, 0, 0, 0 } }, + // 4-tonze Weight + { 11384, { 110, 0, 0, 0, 0 } }, + // Water Cannon + { 11385, { 120, 0, 0, 0, 0 } }, + // Song of Torment + { 11386, { 50, 0, 0, 0, 0 } }, + // High Voltage + { 11387, { 90, 0, 0, 0, 0 } }, + // Bad Breath + { 11388, { 0, 0, 0, 0, 0 } }, + // Flying Frenzy + { 11389, { 80, 0, 0, 0, 0 } }, + // Aqua Breath + { 11390, { 90, 0, 0, 0, 0 } }, + // Plaincracker + { 11391, { 130, 0, 0, 0, 0 } }, + // Acorn Bomb + { 11392, { 0, 0, 0, 0, 0 } }, + // Bristle + { 11393, { 0, 0, 0, 0, 0 } }, + // Mind Blast + { 11394, { 100, 0, 0, 0, 0 } }, + // Blood Drain + { 11395, { 20, 0, 0, 0, 0 } }, + // Bomb Toss + { 11396, { 110, 0, 0, 0, 0 } }, + // 1000 Needles + { 11397, { 0, 0, 0, 0, 0 } }, + // Drill Cannons + { 11398, { 120, 0, 0, 0, 0 } }, + // the Look + { 11399, { 130, 0, 0, 0, 0 } }, + // Sharpened Knife + { 11400, { 120, 0, 0, 0, 0 } }, + // Loom + { 11401, { 0, 0, 0, 0, 0 } }, + // Flame Thrower + { 11402, { 130, 0, 0, 0, 0 } }, + // Faze + { 11403, { 0, 0, 0, 0, 0 } }, + // Glower + { 11404, { 130, 0, 0, 0, 0 } }, + // Missile + { 11405, { 0, 0, 0, 0, 0 } }, + // White Wind + { 11406, { 0, 0, 0, 0, 0 } }, + // Final Sting + { 11407, { 1500, 0, 0, 0, 0 } }, + // Self-destruct + { 11408, { 900, 0, 0, 0, 0 } }, + // Transfusion + { 11409, { 0, 0, 0, 0, 0 } }, + // Toad Oil + { 11410, { 0, 0, 0, 0, 0 } }, + // Off-guard + { 11411, { 0, 0, 0, 0, 0 } }, + // Sticky Tongue + { 11412, { 0, 0, 0, 0, 0 } }, + // Tail Screw + { 11413, { 0, 0, 0, 0, 0 } }, + // Level 5 Petrify + { 11414, { 0, 0, 0, 0, 0 } }, + // Moon Flute + { 11415, { 0, 0, 0, 0, 0 } }, + // Doom + { 11416, { 0, 0, 0, 0, 0 } }, + // Mighty Guard + { 11417, { 0, 0, 0, 0, 0 } }, + // Ice Spikes + { 11418, { 0, 0, 0, 0, 0 } }, + // the Ram's Voice + { 11419, { 130, 0, 0, 0, 0 } }, + // the Dragon's Voice + { 11420, { 110, 0, 0, 0, 0 } }, + // Peculiar Light + { 11421, { 0, 0, 0, 0, 0 } }, + // Ink Jet + { 11422, { 120, 0, 0, 0, 0 } }, + // Flying Sardine + { 11423, { 10, 0, 0, 0, 0 } }, + // Diamondback + { 11424, { 0, 0, 0, 0, 0 } }, + // Fire Angon + { 11425, { 100, 0, 0, 0, 0 } }, + // Feather Rain + { 11426, { 180, 0, 0, 0, 0 } }, + // Eruption + { 11427, { 220, 0, 0, 0, 0 } }, + // Mountain Buster + { 11428, { 310, 0, 0, 0, 0 } }, + // Shock Strike + { 11429, { 310, 0, 0, 0, 0 } }, + // Glass Dance + { 11430, { 290, 0, 0, 0, 0 } }, + // Veil of the Whorl + { 11431, { 0, 0, 0, 0, 0 } }, + // Tri-shackle + { 11482, { 30, 0, 0, 0, 0 } }, + // attack + { 11784, { 0, 0, 0, 0, 0 } }, + // Stone of the Seventh Dawn + { 13423, { 140, 0, 0, 0, 0 } }, + // Aero of the Seventh Dawn + { 13424, { 50, 0, 0, 0, 0 } }, + // Cure of the Seventh Dawn + { 13425, { 0, 0, 0, 0, 700 } }, + // Aetherwell + { 13426, { 0, 0, 0, 0, 0 } }, + // Thunderous Force + { 14587, { 0, 0, 0, 0, 0 } }, + // Kyokufu + { 14840, { 180, 0, 0, 0, 0 } }, + // Ajisai + { 14841, { 100, 0, 0, 0, 0 } }, + // Hissatsu: Gyoten + { 14842, { 100, 0, 0, 0, 0 } }, + // 冥界恐叫打 + { 14843, { 0, 0, 0, 0, 0 } }, + // Second Wind + { 15375, { 0, 0, 0, 0, 500 } }, + +}; \ No newline at end of file From 90d1fbc3eaf3f03c0efdf54b511e741208e41da3 Mon Sep 17 00:00:00 2001 From: NotAdam Date: Sun, 2 Jun 2019 00:34:22 +1000 Subject: [PATCH 046/351] refactor Util -> Common::Util & Action to World::Action --- src/api/main.cpp | 2 +- src/api/server_http.hpp | 6 +- src/common/Database/DbConnection.cpp | 2 +- src/common/Database/DbConnection.h | 4 +- src/common/Database/DbWorker.cpp | 4 +- src/common/Database/DbWorker.h | 4 +- src/common/Database/DbWorkerPool.cpp | 2 +- src/common/Database/DbWorkerPool.h | 2 +- src/common/Database/ZoneDbConnection.cpp | 2 +- src/common/Database/ZoneDbConnection.h | 2 +- src/common/Network/GamePacket.h | 2 +- src/common/Network/PacketContainer.cpp | 2 +- src/common/Util/LockedQueue.h | 2 +- src/common/Util/LockedWaitQueue.h | 2 +- src/common/Util/SpawnIndexAllocator.h | 2 +- src/common/Util/Util.cpp | 22 ++--- src/common/Util/Util.h | 2 +- src/common/Util/UtilMath.cpp | 22 ++--- src/common/Util/UtilMath.h | 2 +- src/lobby/GameConnection.h | 4 +- src/lobby/LobbyPacketContainer.cpp | 2 +- src/lobby/client_http.hpp | 6 +- src/scripts/action/common/ActionReturn6.cpp | 2 +- src/scripts/action/common/ActionSprint3.cpp | 2 +- src/scripts/action/common/ActionTeleport5.cpp | 2 +- .../archer/ActionHeavyShot97.cpp | 2 +- .../playeractions/conjurer/ActionCure120.cpp | 2 +- .../darkknight/ActionAbyssalDrain3641.cpp | 2 +- .../darkknight/ActionHardSlash3617.cpp | 2 +- .../darkknight/ActionPowerSlash3627.cpp | 2 +- .../darkknight/ActionSpinningSlash3619.cpp | 2 +- .../darkknight/ActionSyphonStrike3623.cpp | 2 +- .../darkknight/ActionUnleash3621.cpp | 2 +- .../whitemage/ActionAsylum3569.cpp | 2 +- src/tools/action_parse/main.cpp | 4 +- src/tools/discovery_parser/main.cpp | 6 +- src/tools/event_object_parser/main.cpp | 10 +-- src/tools/exd_common_gen/main.cpp | 2 +- src/tools/mob_parse/main.cpp | 2 +- src/tools/nav_export/main.cpp | 4 +- src/tools/pcb_reader/main.cpp | 4 +- src/world/Action/Action.cpp | 82 ++++++++++--------- src/world/Action/Action.h | 2 +- src/world/Action/EventAction.cpp | 17 ++-- src/world/Action/EventAction.h | 2 +- src/world/Actor/Chara.cpp | 4 +- src/world/Actor/Chara.h | 6 +- src/world/Actor/Player.cpp | 4 +- src/world/Actor/Player.h | 12 +-- src/world/Actor/PlayerEvent.cpp | 10 +-- src/world/ForwardsZone.h | 2 +- src/world/Manager/DebugCommandMgr.cpp | 2 +- src/world/Manager/MarketMgr.cpp | 2 +- src/world/Network/GameConnection.cpp | 2 +- src/world/Network/GameConnection.h | 4 +- src/world/Network/Handlers/PacketHandlers.cpp | 2 +- .../Network/PacketWrappers/MoveActorPacket.h | 8 +- .../Network/PacketWrappers/NpcSpawnPacket.h | 4 +- .../PacketWrappers/PlayerSpawnPacket.h | 4 +- src/world/Script/NativeScriptApi.cpp | 10 +-- src/world/Script/NativeScriptApi.h | 8 +- src/world/Script/ScriptLoader.cpp | 2 +- src/world/Script/ScriptMgr.cpp | 6 +- src/world/Script/ScriptMgr.h | 6 +- src/world/ServerMgr.cpp | 4 +- src/world/Session.cpp | 16 ++-- src/world/Territory/Zone.cpp | 2 +- src/world/Util/ActorFilter.cpp | 2 +- 68 files changed, 200 insertions(+), 181 deletions(-) diff --git a/src/api/main.cpp b/src/api/main.cpp index fd68af4f..3ea413f3 100644 --- a/src/api/main.cpp +++ b/src/api/main.cpp @@ -106,7 +106,7 @@ bool loadSettings( int32_t argc, char* argv[] ) try { - arg = Sapphire::Util::toLowerCopy( std::string( args[ i ] ) ); + arg = Common::Util::toLowerCopy( std::string( args[ i ] ) ); val = std::string( args[ i + 1 ] ); // trim '-' from start of arg diff --git a/src/api/server_http.hpp b/src/api/server_http.hpp index 7c831e69..8a6d2226 100644 --- a/src/api/server_http.hpp +++ b/src/api/server_http.hpp @@ -18,7 +18,7 @@ class case_insensitive_equals { public: bool operator()(const std::string &key1, const std::string &key2) const { - return Sapphire::Util::toLowerCopy( key1 ) == Sapphire::Util::toLowerCopy( key2 ); + return Sapphire::Common::Util::toLowerCopy( key1 ) == Sapphire::Common::Util::toLowerCopy( key2 ); } }; class case_insensitive_hash { @@ -27,7 +27,7 @@ public: { std::size_t seed=0; for( auto &c : key ) - Sapphire::Util::hashCombine< char >( seed, std::tolower( c ) ); + Sapphire::Common::Util::hashCombine< char >( seed, std::tolower( c ) ); return seed; } }; @@ -388,7 +388,7 @@ namespace SimpleWeb { auto range=request->header.equal_range("Connection"); for(auto it=range.first;it!=range.second;it++) { - if( Sapphire::Util::toLowerCopy( it->second ) == "close" ) + if( Sapphire::Common::Util::toLowerCopy( it->second ) == "close" ) return; } if(http_version>1.05) diff --git a/src/common/Database/DbConnection.cpp b/src/common/Database/DbConnection.cpp index 133baa56..f03b7f9e 100644 --- a/src/common/Database/DbConnection.cpp +++ b/src/common/Database/DbConnection.cpp @@ -17,7 +17,7 @@ Sapphire::Db::DbConnection::DbConnection( ConnectionInfo& connInfo ) : } -Sapphire::Db::DbConnection::DbConnection( Sapphire::LockedWaitQueue< std::shared_ptr< Operation > >* queue, +Sapphire::Db::DbConnection::DbConnection( Common::Util::LockedWaitQueue< std::shared_ptr< Operation > >* queue, Sapphire::Db::ConnectionInfo& connInfo ) : m_reconnecting( false ), m_prepareError( false ), diff --git a/src/common/Database/DbConnection.h b/src/common/Database/DbConnection.h index a31a531d..fc84b74f 100644 --- a/src/common/Database/DbConnection.h +++ b/src/common/Database/DbConnection.h @@ -42,7 +42,7 @@ namespace Sapphire::Db DbConnection( ConnectionInfo& connInfo ); // Constructor for asynchronous connections. - DbConnection( Sapphire::LockedWaitQueue< std::shared_ptr< Operation > >* queue, ConnectionInfo& connInfo ); + DbConnection( Common::Util::LockedWaitQueue< std::shared_ptr< Operation > >* queue, ConnectionInfo& connInfo ); virtual ~DbConnection(); @@ -92,7 +92,7 @@ namespace Sapphire::Db bool m_prepareError; private: - LockedWaitQueue< std::shared_ptr< Operation > >* m_queue; + Common::Util::LockedWaitQueue< std::shared_ptr< Operation > >* m_queue; std::shared_ptr< DbWorker > m_worker; std::shared_ptr< Mysql::Connection > m_pConnection; ConnectionInfo& m_connectionInfo; diff --git a/src/common/Database/DbWorker.cpp b/src/common/Database/DbWorker.cpp index 74ee0378..d08f251f 100644 --- a/src/common/Database/DbWorker.cpp +++ b/src/common/Database/DbWorker.cpp @@ -2,7 +2,9 @@ #include "Operation.h" #include "Util/LockedWaitQueue.h" -Sapphire::Db::DbWorker::DbWorker( Sapphire::LockedWaitQueue< std::shared_ptr< Operation > >* newQueue, +using namespace Sapphire::Common; + +Sapphire::Db::DbWorker::DbWorker( Util::LockedWaitQueue< std::shared_ptr< Operation > >* newQueue, DbConnection* pConn ) { m_pConn = pConn; diff --git a/src/common/Database/DbWorker.h b/src/common/Database/DbWorker.h index 13250c19..655ef13f 100644 --- a/src/common/Database/DbWorker.h +++ b/src/common/Database/DbWorker.h @@ -14,12 +14,12 @@ namespace Sapphire::Db class DbWorker { public: - DbWorker( LockedWaitQueue< std::shared_ptr< Operation > >* newQueue, DbConnection* connection ); + DbWorker( Common::Util::LockedWaitQueue< std::shared_ptr< Operation > >* newQueue, DbConnection* connection ); ~DbWorker(); private: - LockedWaitQueue< std::shared_ptr< Operation > >* m_queue; + Common::Util::LockedWaitQueue< std::shared_ptr< Operation > >* m_queue; DbConnection* m_pConn; void workerThread(); diff --git a/src/common/Database/DbWorkerPool.cpp b/src/common/Database/DbWorkerPool.cpp index c9ef3b51..81b9d96d 100644 --- a/src/common/Database/DbWorkerPool.cpp +++ b/src/common/Database/DbWorkerPool.cpp @@ -21,7 +21,7 @@ class PingOperation : public Sapphire::Db::Operation template< class T > Sapphire::Db::DbWorkerPool< T >::DbWorkerPool() : - m_queue( new Sapphire::LockedWaitQueue< std::shared_ptr< Operation > >() ), + m_queue( new Common::Util::LockedWaitQueue< std::shared_ptr< Operation > >() ), m_asyncThreads( 0 ), m_synchThreads( 0 ) { diff --git a/src/common/Database/DbWorkerPool.h b/src/common/Database/DbWorkerPool.h index a29bd3f1..bbc02e46 100644 --- a/src/common/Database/DbWorkerPool.h +++ b/src/common/Database/DbWorkerPool.h @@ -83,7 +83,7 @@ namespace Sapphire::Db const std::string& getDatabaseName() const; - std::unique_ptr< Sapphire::LockedWaitQueue< std::shared_ptr< Operation > > > m_queue; + std::unique_ptr< Common::Util::LockedWaitQueue< std::shared_ptr< Operation > > > m_queue; std::array< std::vector< std::shared_ptr< T > >, IDX_SIZE > m_connections; ConnectionInfo m_connectionInfo; uint8_t m_asyncThreads; diff --git a/src/common/Database/ZoneDbConnection.cpp b/src/common/Database/ZoneDbConnection.cpp index cceea22f..1c4c5a82 100644 --- a/src/common/Database/ZoneDbConnection.cpp +++ b/src/common/Database/ZoneDbConnection.cpp @@ -6,7 +6,7 @@ Sapphire::Db::ZoneDbConnection::ZoneDbConnection( ConnectionInfo& connInfo ) : { } -Sapphire::Db::ZoneDbConnection::ZoneDbConnection( Sapphire::LockedWaitQueue< std::shared_ptr< Operation > >* q, +Sapphire::Db::ZoneDbConnection::ZoneDbConnection( Common::Util::LockedWaitQueue< std::shared_ptr< Operation > >* q, ConnectionInfo& connInfo ) : DbConnection( q, connInfo ) { diff --git a/src/common/Database/ZoneDbConnection.h b/src/common/Database/ZoneDbConnection.h index 93bacc23..8c74bf19 100644 --- a/src/common/Database/ZoneDbConnection.h +++ b/src/common/Database/ZoneDbConnection.h @@ -112,7 +112,7 @@ namespace Sapphire::Db ZoneDbConnection( ConnectionInfo& connInfo ); - ZoneDbConnection( Sapphire::LockedWaitQueue< std::shared_ptr< Operation > >* q, ConnectionInfo& connInfo ); + ZoneDbConnection( Common::Util::LockedWaitQueue< std::shared_ptr< Operation > >* q, ConnectionInfo& connInfo ); ~ZoneDbConnection(); diff --git a/src/common/Network/GamePacket.h b/src/common/Network/GamePacket.h index f62c08ef..c1c06b76 100644 --- a/src/common/Network/GamePacket.h +++ b/src/common/Network/GamePacket.h @@ -257,7 +257,7 @@ namespace Sapphire::Network::Packets // The IPC type itself. m_ipcHdr.type = static_cast< ServerZoneIpcType >( m_data._ServerIpcType ); - m_ipcHdr.timestamp = Util::getTimeSeconds(); + m_ipcHdr.timestamp = Common::Util::getTimeSeconds(); m_segHdr.size = sizeof( T ) + sizeof( FFXIVARR_IPC_HEADER ) + sizeof( FFXIVARR_PACKET_SEGMENT_HEADER ); }; diff --git a/src/common/Network/PacketContainer.cpp b/src/common/Network/PacketContainer.cpp index a61c38c0..d89c8df4 100644 --- a/src/common/Network/PacketContainer.cpp +++ b/src/common/Network/PacketContainer.cpp @@ -76,7 +76,7 @@ std::string Sapphire::Network::Packets::PacketContainer::toString() std::string str = "\n"; for( uint32_t i = 0; i < m_ipcHdr.size; i++ ) { - str += Util::intToHexString( static_cast< int32_t >( tmpBuffer[ i ] & 0xFF ) ) + " "; + str += Common::Util::intToHexString( static_cast< int32_t >( tmpBuffer[ i ] & 0xFF ) ) + " "; if( ( i + 1 ) % 16 == 0 ) str += "\n"; diff --git a/src/common/Util/LockedQueue.h b/src/common/Util/LockedQueue.h index 1e73f4ce..57397b59 100644 --- a/src/common/Util/LockedQueue.h +++ b/src/common/Util/LockedQueue.h @@ -7,7 +7,7 @@ #include #include -namespace Sapphire +namespace Sapphire::Common::Util { template< class T > diff --git a/src/common/Util/LockedWaitQueue.h b/src/common/Util/LockedWaitQueue.h index 122cfd1c..1a1ffdc3 100644 --- a/src/common/Util/LockedWaitQueue.h +++ b/src/common/Util/LockedWaitQueue.h @@ -8,7 +8,7 @@ #include #include -namespace Sapphire +namespace Sapphire::Common::Util { template< typename T > diff --git a/src/common/Util/SpawnIndexAllocator.h b/src/common/Util/SpawnIndexAllocator.h index f03951a3..27003e8f 100644 --- a/src/common/Util/SpawnIndexAllocator.h +++ b/src/common/Util/SpawnIndexAllocator.h @@ -5,7 +5,7 @@ #include #include -namespace Sapphire::Util +namespace Sapphire::Common::Util { template< typename T, typename ActorIdType = uint32_t > diff --git a/src/common/Util/Util.cpp b/src/common/Util/Util.cpp index f443ddf8..d653e29c 100644 --- a/src/common/Util/Util.cpp +++ b/src/common/Util/Util.cpp @@ -5,7 +5,9 @@ #include #include -std::string Sapphire::Util::binaryToHexString( uint8_t* pBinData, uint16_t size ) +using namespace Sapphire::Common; + +std::string Util::binaryToHexString( uint8_t* pBinData, uint16_t size ) { std::string outStr; @@ -17,26 +19,26 @@ std::string Sapphire::Util::binaryToHexString( uint8_t* pBinData, uint16_t size return outStr; } -std::string Sapphire::Util::toLowerCopy( const std::string& inStr ) +std::string Util::toLowerCopy( const std::string& inStr ) { std::string out = inStr; std::transform( inStr.begin(), inStr.end(), out.begin(), [](unsigned char c) -> unsigned char { return ::tolower(c); }); return out; } -void Sapphire::Util::eraseAll( std::string& inOutStr, char remove ) +void Util::eraseAll( std::string& inOutStr, char remove ) { inOutStr.erase( std::remove( inOutStr.begin(), inOutStr.end(), remove ), inOutStr.end() ); } -void Sapphire::Util::eraseAllIn( std::string& inOutStr, std::string& remove ) +void Util::eraseAllIn( std::string& inOutStr, std::string& remove ) { for( auto rem : remove ) inOutStr.erase( std::remove( inOutStr.begin(), inOutStr.end(), rem ), inOutStr.end() ); } -std::string Sapphire::Util::intToHexString( uint64_t intValue, uint8_t width ) +std::string Util::intToHexString( uint64_t intValue, uint8_t width ) { std::string hexStr; @@ -51,7 +53,7 @@ std::string Sapphire::Util::intToHexString( uint64_t intValue, uint8_t width ) return hexStr; } -std::string Sapphire::Util::binaryToHexDump( uint8_t* pBinData, uint16_t size ) +std::string Util::binaryToHexDump( uint8_t* pBinData, uint16_t size ) { int bytesPerLine = 16; constexpr char hexChars[] = "0123456789ABCDEF"; @@ -112,25 +114,25 @@ std::string Sapphire::Util::binaryToHexDump( uint8_t* pBinData, uint16_t size ) } -uint64_t Sapphire::Util::getTimeMs() +uint64_t Util::getTimeMs() { std::chrono::milliseconds epoch = std::chrono::duration_cast< std::chrono::milliseconds > ( std::chrono::system_clock::now().time_since_epoch() ); return epoch.count(); } -uint32_t Sapphire::Util::getTimeSeconds() +uint32_t Util::getTimeSeconds() { auto currClock = std::chrono::system_clock::now(); return std::chrono::time_point_cast< std::chrono::seconds >( currClock ).time_since_epoch().count(); } -uint64_t Sapphire::Util::getEorzeanTimeStamp() +uint64_t Util::getEorzeanTimeStamp() { return static_cast< uint64_t >( getTimeSeconds() * 20.571428571428573f ); } -void Sapphire::Util::valueToFlagByteIndexValue( uint32_t inVal, uint8_t& outVal, uint16_t& outIndex ) +void Util::valueToFlagByteIndexValue( uint32_t inVal, uint8_t& outVal, uint16_t& outIndex ) { uint32_t id = inVal; outIndex = id / 8; diff --git a/src/common/Util/Util.h b/src/common/Util/Util.h index 4c4a5a32..e42dd7ee 100644 --- a/src/common/Util/Util.h +++ b/src/common/Util/Util.h @@ -5,7 +5,7 @@ #include #include -namespace Sapphire::Util +namespace Sapphire::Common::Util { std::string binaryToHexString( uint8_t* pBinData, uint16_t size ); diff --git a/src/common/Util/UtilMath.cpp b/src/common/Util/UtilMath.cpp index f2e8cc2c..a1e1a01e 100644 --- a/src/common/Util/UtilMath.cpp +++ b/src/common/Util/UtilMath.cpp @@ -1,7 +1,9 @@ #include #include "UtilMath.h" -float Sapphire::Util::distanceSq( float x, float y, float z, float x1, float y1, float z1 ) +using namespace Sapphire::Common; + +float Util::distanceSq( float x, float y, float z, float x1, float y1, float z1 ) { float deltaX = x - x1; float deltaY = y - y1; @@ -10,29 +12,29 @@ float Sapphire::Util::distanceSq( float x, float y, float z, float x1, float y1, return ( deltaX * deltaX + deltaY * deltaY + deltaZ * deltaZ ); } -float Sapphire::Util::distance( float x, float y, float z, float x1, float y1, float z1 ) +float Util::distance( float x, float y, float z, float x1, float y1, float z1 ) { return sqrtf( distanceSq( x, y, z, x1, y1, z1 ) ); } -float Sapphire::Util::distance( const Common::FFXIVARR_POSITION3& pos1, const Common::FFXIVARR_POSITION3& pos2 ) +float Util::distance( const Common::FFXIVARR_POSITION3& pos1, const Common::FFXIVARR_POSITION3& pos2 ) { return sqrtf( distanceSq( pos1.x, pos1.y, pos1.z, pos2.x, pos2.y, pos2.z ) ); } -float Sapphire::Util::distance2DSq( float x, float y, float x1, float y1 ) +float Util::distance2DSq( float x, float y, float x1, float y1 ) { float deltaX = x - x1; float deltaY = y - y1; return ( deltaX * deltaX + deltaY * deltaY ); } -float Sapphire::Util::distance2D( float x, float y, float x1, float y1 ) +float Util::distance2D( float x, float y, float x1, float y1 ) { return sqrtf( distance2DSq( x, y, x1, y1 ) ); } -float Sapphire::Util::calcAngTo( float x, float y, float x1, float y1 ) +float Util::calcAngTo( float x, float y, float x1, float y1 ) { float dx = x - x1; float dy = y - y1; @@ -46,7 +48,7 @@ float Sapphire::Util::calcAngTo( float x, float y, float x1, float y1 ) } } -float Sapphire::Util::calcAngFrom( float x, float y, float x1, float y1 ) +float Util::calcAngFrom( float x, float y, float x1, float y1 ) { float dx = x - x1; float dy = y - y1; @@ -60,17 +62,17 @@ float Sapphire::Util::calcAngFrom( float x, float y, float x1, float y1 ) } } -uint16_t Sapphire::Util::floatToUInt16( float val ) +uint16_t Util::floatToUInt16( float val ) { return static_cast< uint16_t >( 0x8000 + val * 32.767f ); } -uint16_t Sapphire::Util::floatToUInt16Rot( float val ) +uint16_t Util::floatToUInt16Rot( float val ) { return static_cast< uint16_t >( 0x8000 * ( ( val + PI ) ) / PI ); } -uint8_t Sapphire::Util::floatToUInt8Rot( float val ) +uint8_t Util::floatToUInt8Rot( float val ) { return static_cast< uint8_t >( 0x80 * ( ( val + PI ) ) / PI ); } \ No newline at end of file diff --git a/src/common/Util/UtilMath.h b/src/common/Util/UtilMath.h index 5d34ee92..c35ef6be 100644 --- a/src/common/Util/UtilMath.h +++ b/src/common/Util/UtilMath.h @@ -5,7 +5,7 @@ #define PI 3.14159265358979323846f -namespace Sapphire::Util +namespace Sapphire::Common::Util { float distanceSq( float x, float y, float z, float x1, float y1, float z1 ); diff --git a/src/lobby/GameConnection.h b/src/lobby/GameConnection.h index 6bcb7122..42f0a3a2 100644 --- a/src/lobby/GameConnection.h +++ b/src/lobby/GameConnection.h @@ -36,8 +36,8 @@ namespace Sapphire::Network LobbySessionPtr m_pSession; - LockedQueue< Packets::GamePacketPtr > m_inQueue; - LockedQueue< Packets::GamePacketPtr > m_outQueue; + Common::Util::LockedQueue< Packets::GamePacketPtr > m_inQueue; + Common::Util::LockedQueue< Packets::GamePacketPtr > m_outQueue; std::vector< uint8_t > m_packets; public: diff --git a/src/lobby/LobbyPacketContainer.cpp b/src/lobby/LobbyPacketContainer.cpp index 2d217436..c1c7366c 100644 --- a/src/lobby/LobbyPacketContainer.cpp +++ b/src/lobby/LobbyPacketContainer.cpp @@ -48,7 +48,7 @@ uint8_t* Sapphire::Network::Packets::LobbyPacketContainer::getRawData( bool adds if( addstuff ) { m_header.unknown_0 = 0xff41a05252; - m_header.timestamp = Sapphire::Util::getTimeMs(); + m_header.timestamp = Common::Util::getTimeMs(); } memcpy( m_dataBuf, &m_header, sizeof( Sapphire::Network::Packets::FFXIVARR_PACKET_HEADER ) ); return m_dataBuf; diff --git a/src/lobby/client_http.hpp b/src/lobby/client_http.hpp index fc30d950..f22cb8d2 100644 --- a/src/lobby/client_http.hpp +++ b/src/lobby/client_http.hpp @@ -17,16 +17,16 @@ class case_insensitive_equals { public: bool operator()(const std::string &key1, const std::string &key2) const { - return Sapphire::Util::toLowerCopy( key1 ) == Sapphire::Util::toLowerCopy( key2 ); + return Sapphire::Common::Util::toLowerCopy( key1 ) == Sapphire::Common::Util::toLowerCopy( key2 ); } }; class case_insensitive_hash { public: - size_t operator()( const std::string &key ) const + size_t operator()( const std::string &key ) const { std::size_t seed=0; for( auto &c : key ) - Sapphire::Util::hashCombine< char >( seed, std::tolower( c ) ); + Sapphire::Common::Util::hashCombine< char >( seed, std::tolower( c ) ); return seed; } }; diff --git a/src/scripts/action/common/ActionReturn6.cpp b/src/scripts/action/common/ActionReturn6.cpp index 9831c7e3..aedb0a38 100644 --- a/src/scripts/action/common/ActionReturn6.cpp +++ b/src/scripts/action/common/ActionReturn6.cpp @@ -12,7 +12,7 @@ public: { } - void onExecute( Sapphire::Action::Action& action ) override + void onExecute( Sapphire::World::Action::Action& action ) override { if( !action.getSourceChara()->isPlayer() ) return; diff --git a/src/scripts/action/common/ActionSprint3.cpp b/src/scripts/action/common/ActionSprint3.cpp index 0067dcac..133cbb2e 100644 --- a/src/scripts/action/common/ActionSprint3.cpp +++ b/src/scripts/action/common/ActionSprint3.cpp @@ -11,7 +11,7 @@ public: { } - void onExecute( Sapphire::Action::Action& action ) override + void onExecute( Sapphire::World::Action::Action& action ) override { auto sourceChara = action.getSourceChara(); diff --git a/src/scripts/action/common/ActionTeleport5.cpp b/src/scripts/action/common/ActionTeleport5.cpp index e08afda6..1a2fcd77 100644 --- a/src/scripts/action/common/ActionTeleport5.cpp +++ b/src/scripts/action/common/ActionTeleport5.cpp @@ -14,7 +14,7 @@ public: { } - void onExecute( Sapphire::Action::Action& action ) override + void onExecute( Sapphire::World::Action::Action& action ) override { auto player = action.getSourceChara()->getAsPlayer(); diff --git a/src/scripts/action/playeractions/archer/ActionHeavyShot97.cpp b/src/scripts/action/playeractions/archer/ActionHeavyShot97.cpp index 882d4549..3c3ef16f 100644 --- a/src/scripts/action/playeractions/archer/ActionHeavyShot97.cpp +++ b/src/scripts/action/playeractions/archer/ActionHeavyShot97.cpp @@ -12,7 +12,7 @@ public: { } - void onExecute( Sapphire::Action::Action& action ) override + void onExecute( Sapphire::World::Action::Action& action ) override { if( auto player = action.getSourceChara()->getAsPlayer() ) player->sendDebug( "Imagine you just hit an enemy for 150 potency. Incredible, right?" ); diff --git a/src/scripts/action/playeractions/conjurer/ActionCure120.cpp b/src/scripts/action/playeractions/conjurer/ActionCure120.cpp index 9d6bc8a7..66284ecb 100644 --- a/src/scripts/action/playeractions/conjurer/ActionCure120.cpp +++ b/src/scripts/action/playeractions/conjurer/ActionCure120.cpp @@ -12,7 +12,7 @@ public: { } - void onExecute( Sapphire::Action::Action& action ) override + void onExecute( Sapphire::World::Action::Action& action ) override { } diff --git a/src/scripts/action/playeractions/darkknight/ActionAbyssalDrain3641.cpp b/src/scripts/action/playeractions/darkknight/ActionAbyssalDrain3641.cpp index 4d302333..3c369d1c 100644 --- a/src/scripts/action/playeractions/darkknight/ActionAbyssalDrain3641.cpp +++ b/src/scripts/action/playeractions/darkknight/ActionAbyssalDrain3641.cpp @@ -12,7 +12,7 @@ public: { } - void onExecute( Sapphire::Action::Action& action ) override + void onExecute( Sapphire::World::Action::Action& action ) override { for( auto& chara : action.getHitCharas() ) { diff --git a/src/scripts/action/playeractions/darkknight/ActionHardSlash3617.cpp b/src/scripts/action/playeractions/darkknight/ActionHardSlash3617.cpp index 6d76fdb0..1143c0f7 100644 --- a/src/scripts/action/playeractions/darkknight/ActionHardSlash3617.cpp +++ b/src/scripts/action/playeractions/darkknight/ActionHardSlash3617.cpp @@ -12,7 +12,7 @@ public: { } - void onExecute( Sapphire::Action::Action& action ) override + void onExecute( Sapphire::World::Action::Action& action ) override { auto chara = action.getHitChara(); chara->takeDamage( chara->getMaxHp() * 0.34f ); diff --git a/src/scripts/action/playeractions/darkknight/ActionPowerSlash3627.cpp b/src/scripts/action/playeractions/darkknight/ActionPowerSlash3627.cpp index 6775947d..74cd54a0 100644 --- a/src/scripts/action/playeractions/darkknight/ActionPowerSlash3627.cpp +++ b/src/scripts/action/playeractions/darkknight/ActionPowerSlash3627.cpp @@ -12,7 +12,7 @@ public: { } - void onExecute( Sapphire::Action::Action& action ) override + void onExecute( Sapphire::World::Action::Action& action ) override { } diff --git a/src/scripts/action/playeractions/darkknight/ActionSpinningSlash3619.cpp b/src/scripts/action/playeractions/darkknight/ActionSpinningSlash3619.cpp index 3eb592df..1074da11 100644 --- a/src/scripts/action/playeractions/darkknight/ActionSpinningSlash3619.cpp +++ b/src/scripts/action/playeractions/darkknight/ActionSpinningSlash3619.cpp @@ -12,7 +12,7 @@ public: { } - void onExecute( Sapphire::Action::Action& action ) override + void onExecute( Sapphire::World::Action::Action& action ) override { } diff --git a/src/scripts/action/playeractions/darkknight/ActionSyphonStrike3623.cpp b/src/scripts/action/playeractions/darkknight/ActionSyphonStrike3623.cpp index e765f8d1..a1d18a74 100644 --- a/src/scripts/action/playeractions/darkknight/ActionSyphonStrike3623.cpp +++ b/src/scripts/action/playeractions/darkknight/ActionSyphonStrike3623.cpp @@ -12,7 +12,7 @@ public: { } - void onExecute( Sapphire::Action::Action& action ) override + void onExecute( Sapphire::World::Action::Action& action ) override { } diff --git a/src/scripts/action/playeractions/darkknight/ActionUnleash3621.cpp b/src/scripts/action/playeractions/darkknight/ActionUnleash3621.cpp index 2e735af6..5af2e472 100644 --- a/src/scripts/action/playeractions/darkknight/ActionUnleash3621.cpp +++ b/src/scripts/action/playeractions/darkknight/ActionUnleash3621.cpp @@ -12,7 +12,7 @@ public: { } - void onExecute( Sapphire::Action::Action& action ) override + void onExecute( Sapphire::World::Action::Action& action ) override { for( auto& chara : action.getHitCharas() ) { diff --git a/src/scripts/action/playeractions/whitemage/ActionAsylum3569.cpp b/src/scripts/action/playeractions/whitemage/ActionAsylum3569.cpp index 1e71dd2e..6ac1c92c 100644 --- a/src/scripts/action/playeractions/whitemage/ActionAsylum3569.cpp +++ b/src/scripts/action/playeractions/whitemage/ActionAsylum3569.cpp @@ -12,7 +12,7 @@ public: { } - void onExecute( Sapphire::Action::Action& action ) override + void onExecute( Sapphire::World::Action::Action& action ) override { } diff --git a/src/tools/action_parse/main.cpp b/src/tools/action_parse/main.cpp index c48194d3..3adce507 100644 --- a/src/tools/action_parse/main.cpp +++ b/src/tools/action_parse/main.cpp @@ -257,14 +257,14 @@ int main() // Logger::info( out ); } - std::ifstream ifs( "ActionLut.cpp.tmpl" ); + std::ifstream ifs( "ActionLutData.cpp.tmpl" ); std::string actionTmpl( ( std::istreambuf_iterator< char >( ifs ) ), std::istreambuf_iterator< char >() ); auto result = std::regex_replace( actionTmpl, std::regex( "%INSERT_GARBAGE%" ), output ); - std::ofstream outH( "ActionLut.cpp" ); + std::ofstream outH( "ActionLutData.cpp" ); outH << result; outH.close(); diff --git a/src/tools/discovery_parser/main.cpp b/src/tools/discovery_parser/main.cpp index 41c833b6..0ded1f58 100644 --- a/src/tools/discovery_parser/main.cpp +++ b/src/tools/discovery_parser/main.cpp @@ -26,6 +26,8 @@ #include #include +using namespace Sapphire; + // garbage to ignore models bool ignoreModels = false; @@ -165,7 +167,7 @@ std::string zoneNameToPath( const std::string& name ) info.name = teriName; zoneInfoMap[ row.first ] = info; - if( !found && ( Sapphire::Util::toLowerCopy( name ) == Sapphire::Util::toLowerCopy( teriName ) ) ) + if( !found && ( Common::Util::toLowerCopy( name ) == Common::Util::toLowerCopy( teriName ) ) ) { found = true; path = teriPath; @@ -177,7 +179,7 @@ std::string zoneNameToPath( const std::string& name ) { for( const auto& entry : zoneInfoMap ) { - if( found = Sapphire::Util::toLowerCopy( name ) == Sapphire::Util::toLowerCopy( entry.second.name ) ) + if( found = Common::Util::toLowerCopy( name ) == Common::Util::toLowerCopy( entry.second.name ) ) { path = entry.second.path; zoneId = entry.second.id; diff --git a/src/tools/event_object_parser/main.cpp b/src/tools/event_object_parser/main.cpp index 16ab9ab6..a4d451a9 100644 --- a/src/tools/event_object_parser/main.cpp +++ b/src/tools/event_object_parser/main.cpp @@ -62,7 +62,7 @@ std::string zoneNameToPath( const std::string& name ) { std::string path; - auto it = g_nameMap.find( Sapphire::Util::toLowerCopy( name ) ); + auto it = g_nameMap.find( Common::Util::toLowerCopy( name ) ); if( it != g_nameMap.end() ) return it->second; @@ -79,7 +79,7 @@ std::string zoneNameToPath( const std::string& name ) if( teriName.empty() ) continue; - if( Sapphire::Util::toLowerCopy( name ) == Sapphire::Util::toLowerCopy( teriName ) ) + if( Common::Util::toLowerCopy( name ) == Common::Util::toLowerCopy( teriName ) ) { path = teriPath; break; @@ -90,7 +90,7 @@ std::string zoneNameToPath( const std::string& name ) { path = std::string( "bg/" ) + path.substr( 0, path.find( "/level/" ) ); Logger::debug( "Found path for {0}: {1}", name, path ); - g_nameMap[ Sapphire::Util::toLowerCopy( name ) ] = path; + g_nameMap[ Common::Util::toLowerCopy( name ) ] = path; } else { @@ -161,7 +161,7 @@ void loadAllInstanceContentEntries() name = name.replace( name.begin() + i, name.begin() + i + 1, { '_' } ); std::string remove = ",★_ '()[]-\xae\x1a\x1\x2\x1f\x1\x3.:"; - Sapphire::Util::eraseAllIn( name, remove ); + Common::Util::eraseAllIn( name, remove ); name[ 0 ] = toupper( name[ 0 ] ); contentList.push_back( { contentId, name, tt->name, type } ); } @@ -332,7 +332,7 @@ int main( int argc, char* argv[] ) { name = eobjNameMap[ id ]; std::string remove = ",★_ '()[]-\xae\x1a\x1\x2\x1f\x1\x3.:"; - Sapphire::Util::eraseAllIn( name, remove ); + Common::Util::eraseAllIn( name, remove ); name[ 0 ] = toupper( name[ 0 ] ); } if( name.empty() ) diff --git a/src/tools/exd_common_gen/main.cpp b/src/tools/exd_common_gen/main.cpp index a6c7fb60..43a27473 100644 --- a/src/tools/exd_common_gen/main.cpp +++ b/src/tools/exd_common_gen/main.cpp @@ -55,7 +55,7 @@ std::string generateEnum( const std::string& exd, int8_t nameIndex, const std::s } std::string remove = ",_-':!(){} \x02\x1f\x01\x03"; - Sapphire::Util::eraseAllIn( value, remove ); + Common::Util::eraseAllIn( value, remove ); value[ 0 ] = std::toupper( value[ 0 ] ); diff --git a/src/tools/mob_parse/main.cpp b/src/tools/mob_parse/main.cpp index 838ee51e..e8598da0 100644 --- a/src/tools/mob_parse/main.cpp +++ b/src/tools/mob_parse/main.cpp @@ -121,7 +121,7 @@ std::string binaryToHexString( uint8_t* pBinData, uint16_t size ) for( uint32_t i = 0; i < size; i++ ) { - outStr += Sapphire::Util::intToHexString( pBinData[ i ] & 0xFF ); + outStr += Common::Util::intToHexString( pBinData[ i ] & 0xFF ); } return outStr; diff --git a/src/tools/nav_export/main.cpp b/src/tools/nav_export/main.cpp index 043410a7..12e1c840 100644 --- a/src/tools/nav_export/main.cpp +++ b/src/tools/nav_export/main.cpp @@ -29,6 +29,8 @@ #include #include +using namespace Sapphire; + // garbage to ignore models bool noObj = false; @@ -121,7 +123,7 @@ std::string zoneNameToPath( const std::string& name ) if( teriName.empty() ) continue; auto teriPath = std::get< std::string >( fields.at( static_cast< size_t >( TerritoryTypeExdIndexes::Path ) ) ); - if( !found && ( Sapphire::Util::toLowerCopy( name ) == Sapphire::Util::toLowerCopy( teriName ) ) ) + if( !found && ( Common::Util::toLowerCopy( name ) == Common::Util::toLowerCopy( teriName ) ) ) { path = teriPath; found = true; diff --git a/src/tools/pcb_reader/main.cpp b/src/tools/pcb_reader/main.cpp index 7c922a12..f4d29d2a 100644 --- a/src/tools/pcb_reader/main.cpp +++ b/src/tools/pcb_reader/main.cpp @@ -29,6 +29,8 @@ #include #include +using namespace Sapphire; + // garbage to ignore models bool noObj = false; @@ -123,7 +125,7 @@ std::string zoneNameToPath( const std::string& name ) if( teriName.empty() ) continue; auto teriPath = std::get< std::string >( fields.at( static_cast< size_t >( TerritoryTypeExdIndexes::Path ) ) ); - if( !found && ( Sapphire::Util::toLowerCopy( name ) == Sapphire::Util::toLowerCopy( teriName ) ) ) + if( !found && ( Common::Util::toLowerCopy( name ) == Common::Util::toLowerCopy( teriName ) ) ) { path = teriPath; found = true; diff --git a/src/world/Action/Action.cpp b/src/world/Action/Action.cpp index 7f04a63f..3c6da8c5 100644 --- a/src/world/Action/Action.cpp +++ b/src/world/Action/Action.cpp @@ -1,4 +1,5 @@ #include "Action.h" +#include "ActionLut.h" #include #include @@ -26,16 +27,18 @@ using namespace Sapphire::Network::Packets; using namespace Sapphire::Network::Packets::Server; using namespace Sapphire::Network::ActorControl; +using namespace Sapphire::World::Action; -Sapphire::Action::Action::Action() = default; -Sapphire::Action::Action::~Action() = default; -Sapphire::Action::Action::Action( Entity::CharaPtr caster, uint32_t actionId, FrameworkPtr fw ) : +Action::Action() = default; +Action::~Action() = default; + +Action::Action( Entity::CharaPtr caster, uint32_t actionId, FrameworkPtr fw ) : Action( std::move( caster ), actionId, nullptr, std::move( fw ) ) { } -Sapphire::Action::Action::Action( Entity::CharaPtr caster, uint32_t actionId, +Action::Action( Entity::CharaPtr caster, uint32_t actionId, Data::ActionPtr actionData, FrameworkPtr fw ) : m_pSource( std::move( caster ) ), m_pFw( std::move( fw ) ), @@ -47,12 +50,12 @@ Sapphire::Action::Action::Action( Entity::CharaPtr caster, uint32_t actionId, { } -uint32_t Sapphire::Action::Action::getId() const +uint32_t Action::getId() const { return m_id; } -bool Sapphire::Action::Action::init() +bool Action::init() { if( !m_actionData ) { @@ -121,62 +124,62 @@ bool Sapphire::Action::Action::init() return true; } -void Sapphire::Action::Action::setPos( Sapphire::Common::FFXIVARR_POSITION3 pos ) +void Action::setPos( Sapphire::Common::FFXIVARR_POSITION3 pos ) { m_pos = pos; } -Sapphire::Common::FFXIVARR_POSITION3 Sapphire::Action::Action::getPos() const +Sapphire::Common::FFXIVARR_POSITION3 Action::getPos() const { return m_pos; } -void Sapphire::Action::Action::setTargetId( uint64_t targetId ) +void Action::setTargetId( uint64_t targetId ) { m_targetId = targetId; } -uint64_t Sapphire::Action::Action::getTargetId() const +uint64_t Action::getTargetId() const { return m_targetId; } -bool Sapphire::Action::Action::hasClientsideTarget() const +bool Action::hasClientsideTarget() const { return m_targetId > 0xFFFFFFFF; } -bool Sapphire::Action::Action::isInterrupted() const +bool Action::isInterrupted() const { return m_interruptType != Common::ActionInterruptType::None; } -void Sapphire::Action::Action::setInterrupted( Common::ActionInterruptType type ) +void Action::setInterrupted( Common::ActionInterruptType type ) { m_interruptType = type; } -uint32_t Sapphire::Action::Action::getCastTime() const +uint32_t Action::getCastTime() const { return m_castTimeMs; } -void Sapphire::Action::Action::setCastTime( uint32_t castTime ) +void Action::setCastTime( uint32_t castTime ) { m_castTimeMs = castTime; } -bool Sapphire::Action::Action::hasCastTime() const +bool Action::hasCastTime() const { return m_castTimeMs > 0; } -Sapphire::Entity::CharaPtr Sapphire::Action::Action::getSourceChara() const +Sapphire::Entity::CharaPtr Action::getSourceChara() const { return m_pSource; } -bool Sapphire::Action::Action::update() +bool Action::update() { // action has not been started yet if( m_startTime == 0 ) @@ -193,7 +196,7 @@ bool Sapphire::Action::Action::update() // todo: check if the target is still in range } - uint64_t tickCount = Util::getTimeMs(); + uint64_t tickCount = Common::Util::getTimeMs(); if( !hasCastTime() || std::difftime( tickCount, m_startTime ) > m_castTimeMs ) { @@ -204,11 +207,11 @@ bool Sapphire::Action::Action::update() return false; } -void Sapphire::Action::Action::start() +void Action::start() { assert( m_pSource ); - m_startTime = Util::getTimeMs(); + m_startTime = Common::Util::getTimeMs(); auto player = m_pSource->getAsPlayer(); @@ -238,6 +241,9 @@ void Sapphire::Action::Action::start() auto pScriptMgr = m_pFw->get< Scripting::ScriptMgr >(); if( !pScriptMgr->onStart( *this ) ) { + // check the lut initially and see if we have something usable, otherwise cancel the cast +// Sapphire::World::Action::ActionLut::validEntryExists( getId() ); + // script not implemented interrupt(); @@ -255,7 +261,7 @@ void Sapphire::Action::Action::start() execute(); } -void Sapphire::Action::Action::interrupt() +void Action::interrupt() { assert( m_pSource ); @@ -289,7 +295,7 @@ void Sapphire::Action::Action::interrupt() pScriptMgr->onInterrupt( *this ); } -void Sapphire::Action::Action::execute() +void Action::execute() { assert( m_pSource ); @@ -346,7 +352,7 @@ void Sapphire::Action::Action::execute() } } -bool Sapphire::Action::Action::precheck() +bool Action::precheck() { if( auto player = m_pSource->getAsPlayer() ) { @@ -357,7 +363,7 @@ bool Sapphire::Action::Action::precheck() return true; } -bool Sapphire::Action::Action::playerPrecheck( Entity::Player& player ) +bool Action::playerPrecheck( Entity::Player& player ) { // lol if( !player.isAlive() ) @@ -408,17 +414,17 @@ bool Sapphire::Action::Action::playerPrecheck( Entity::Player& player ) return true; } -uint32_t Sapphire::Action::Action::getAdditionalData() const +uint32_t Action::getAdditionalData() const { return m_additionalData; } -void Sapphire::Action::Action::setAdditionalData( uint32_t data ) +void Action::setAdditionalData( uint32_t data ) { m_additionalData = data; } -bool Sapphire::Action::Action::isComboAction() const +bool Action::isComboAction() const { auto lastActionId = m_pSource->getLastComboActionId(); @@ -430,7 +436,7 @@ bool Sapphire::Action::Action::isComboAction() const return m_actionData->actionCombo == lastActionId; } -bool Sapphire::Action::Action::primaryCostCheck( bool subtractCosts ) +bool Action::primaryCostCheck( bool subtractCosts ) { switch( m_primaryCostType ) { @@ -473,23 +479,23 @@ bool Sapphire::Action::Action::primaryCostCheck( bool subtractCosts ) } } -bool Sapphire::Action::Action::secondaryCostCheck( bool subtractCosts ) +bool Action::secondaryCostCheck( bool subtractCosts ) { // todo: these need to be mapped return true; } -bool Sapphire::Action::Action::hasResources() +bool Action::hasResources() { return primaryCostCheck( false ) && secondaryCostCheck( false ); } -bool Sapphire::Action::Action::consumeResources() +bool Action::consumeResources() { return primaryCostCheck( true ) && secondaryCostCheck( true ); } -bool Sapphire::Action::Action::snapshotAffectedActors( std::vector< Entity::CharaPtr >& actors ) +bool Action::snapshotAffectedActors( std::vector< Entity::CharaPtr >& actors ) { for( const auto& actor : m_pSource->getInRangeActors( true ) ) { @@ -519,12 +525,12 @@ bool Sapphire::Action::Action::snapshotAffectedActors( std::vector< Entity::Char return !actors.empty(); } -void Sapphire::Action::Action::addActorFilter( World::Util::ActorFilterPtr filter ) +void Action::addActorFilter( World::Util::ActorFilterPtr filter ) { m_actorFilters.push_back( std::move( filter ) ); } -void Sapphire::Action::Action::addDefaultActorFilters() +void Action::addDefaultActorFilters() { switch( m_castType ) { @@ -561,7 +567,7 @@ void Sapphire::Action::Action::addDefaultActorFilters() } } -bool Sapphire::Action::Action::preFilterActor( Sapphire::Entity::Actor& actor ) const +bool Action::preFilterActor( Sapphire::Entity::Actor& actor ) const { auto kind = actor.getObjKind(); @@ -574,12 +580,12 @@ bool Sapphire::Action::Action::preFilterActor( Sapphire::Entity::Actor& actor ) return true; } -std::vector< Sapphire::Entity::CharaPtr >& Sapphire::Action::Action::getHitCharas() +std::vector< Sapphire::Entity::CharaPtr >& Action::getHitCharas() { return m_hitActors; } -Sapphire::Entity::CharaPtr Sapphire::Action::Action::getHitChara() +Sapphire::Entity::CharaPtr Action::getHitChara() { if( !m_hitActors.empty() ) { diff --git a/src/world/Action/Action.h b/src/world/Action/Action.h index e1c57d2d..b4b12363 100644 --- a/src/world/Action/Action.h +++ b/src/world/Action/Action.h @@ -11,7 +11,7 @@ namespace Sapphire::Data using ActionPtr = std::shared_ptr< Action >; } -namespace Sapphire::Action +namespace Sapphire::World::Action { class Action diff --git a/src/world/Action/EventAction.cpp b/src/world/Action/EventAction.cpp index 349e9040..18c8d993 100644 --- a/src/world/Action/EventAction.cpp +++ b/src/world/Action/EventAction.cpp @@ -11,15 +11,16 @@ #include "EventAction.h" #include "Framework.h" +using namespace Sapphire::World; using namespace Sapphire::Common; using namespace Sapphire::Network; using namespace Sapphire::Network::Packets; using namespace Sapphire::Network::Packets::Server; using namespace Sapphire::Network::ActorControl; -Sapphire::Action::EventAction::EventAction( Entity::CharaPtr pActor, uint32_t eventId, uint16_t action, - ActionCallback finishRef, ActionCallback interruptRef, uint64_t additional, - FrameworkPtr pFw ) +Action::EventAction::EventAction( Entity::CharaPtr pActor, uint32_t eventId, uint16_t action, + ActionCallback finishRef, ActionCallback interruptRef, uint64_t additional, + FrameworkPtr pFw ) { m_additional = additional; m_eventId = eventId; @@ -33,14 +34,14 @@ Sapphire::Action::EventAction::EventAction( Entity::CharaPtr pActor, uint32_t ev m_interruptType = Common::ActionInterruptType::None; } -Sapphire::Action::EventAction::~EventAction() = default; +Action::EventAction::~EventAction() = default; -void Sapphire::Action::EventAction::start() +void Action::EventAction::start() { if( !m_pSource ) return; - m_startTime = Util::getTimeMs(); + m_startTime = Common::Util::getTimeMs(); auto control = makeActorControl142( m_pSource->getId(), ActorControlType::CastStart, 1, m_id, 0x4000004E ); @@ -54,7 +55,7 @@ void Sapphire::Action::EventAction::start() m_pSource->sendToInRangeSet( control ); } -void Sapphire::Action::EventAction::execute() +void Action::EventAction::execute() { if( !m_pSource ) return; @@ -90,7 +91,7 @@ void Sapphire::Action::EventAction::execute() } -void Sapphire::Action::EventAction::interrupt() +void Action::EventAction::interrupt() { if( !m_pSource ) return; diff --git a/src/world/Action/EventAction.h b/src/world/Action/EventAction.h index 37987634..4a9bb50a 100644 --- a/src/world/Action/EventAction.h +++ b/src/world/Action/EventAction.h @@ -6,7 +6,7 @@ #include "ForwardsZone.h" #include "Action.h" -namespace Sapphire::Action +namespace Sapphire::World::Action { class EventAction : public Action diff --git a/src/world/Actor/Chara.cpp b/src/world/Actor/Chara.cpp index d2eac841..3942f112 100644 --- a/src/world/Actor/Chara.cpp +++ b/src/world/Actor/Chara.cpp @@ -391,13 +391,13 @@ void Sapphire::Entity::Chara::sendStatusUpdate() } /*! \return ActionPtr of the currently registered action, or nullptr */ -Sapphire::Action::ActionPtr Sapphire::Entity::Chara::getCurrentAction() const +Sapphire::World::Action::ActionPtr Sapphire::Entity::Chara::getCurrentAction() const { return m_pCurrentAction; } /*! \param ActionPtr of the action to be registered */ -void Sapphire::Entity::Chara::setCurrentAction( Sapphire::Action::ActionPtr pAction ) +void Sapphire::Entity::Chara::setCurrentAction( Sapphire::World::Action::ActionPtr pAction ) { m_pCurrentAction = std::move( pAction ); } diff --git a/src/world/Actor/Chara.h b/src/world/Actor/Chara.h index 5679b2cb..83d14fb6 100644 --- a/src/world/Actor/Chara.h +++ b/src/world/Actor/Chara.h @@ -102,7 +102,7 @@ namespace Sapphire::Entity /*! Id of the currently selected target actor */ uint64_t m_targetId; /*! Ptr to a queued action */ - Action::ActionPtr m_pCurrentAction; + World::Action::ActionPtr m_pCurrentAction; /*! id of the director this chara is assigned to */ uint32_t m_directorId; @@ -265,9 +265,9 @@ namespace Sapphire::Entity virtual void update( uint64_t tickCount ); - Action::ActionPtr getCurrentAction() const; + World::Action::ActionPtr getCurrentAction() const; - void setCurrentAction( Action::ActionPtr pAction ); + void setCurrentAction( World::Action::ActionPtr pAction ); uint32_t getLastComboActionId() const; void setLastComboActionId( uint32_t actionId ); diff --git a/src/world/Actor/Player.cpp b/src/world/Actor/Player.cpp index 362dfa0e..f4abe67c 100644 --- a/src/world/Actor/Player.cpp +++ b/src/world/Actor/Player.cpp @@ -1621,7 +1621,7 @@ void Sapphire::Entity::Player::setCFPenaltyTimestamp( uint32_t timestamp ) uint32_t Sapphire::Entity::Player::getCFPenaltyMinutes() const { - auto currentTimestamp = Sapphire::Util::getTimeSeconds(); + auto currentTimestamp = Common::Util::getTimeSeconds(); auto endTimestamp = getCFPenaltyTimestamp(); // check if penalty timestamp already passed current time @@ -1634,7 +1634,7 @@ uint32_t Sapphire::Entity::Player::getCFPenaltyMinutes() const void Sapphire::Entity::Player::setCFPenaltyMinutes( uint32_t minutes ) { - auto currentTimestamp = Sapphire::Util::getTimeSeconds(); + auto currentTimestamp = Common::Util::getTimeSeconds(); setCFPenaltyTimestamp( currentTimestamp + minutes * 60 ); } diff --git a/src/world/Actor/Player.h b/src/world/Actor/Player.h index 3fbf9f88..e277738a 100644 --- a/src/world/Actor/Player.h +++ b/src/world/Actor/Player.h @@ -53,12 +53,12 @@ namespace Sapphire::Entity // EventHandlers ////////////////////////////////////////////////////////////////////////////////////////////////////// /*! start an event action */ - void eventActionStart( uint32_t eventId, uint32_t action, Action::ActionCallback finishCallback, - Action::ActionCallback interruptCallback, uint64_t additional ); + void eventActionStart( uint32_t eventId, uint32_t action, World::Action::ActionCallback finishCallback, + World::Action::ActionCallback interruptCallback, uint64_t additional ); /*! start an event item action */ - void eventItemActionStart( uint32_t eventId, uint32_t action, Action::ActionCallback finishCallback, - Action::ActionCallback interruptCallback, uint64_t additional ); + void eventItemActionStart( uint32_t eventId, uint32_t action, World::Action::ActionCallback finishCallback, + World::Action::ActionCallback interruptCallback, uint64_t additional ); /*! start/register a normal event */ void eventStart( uint64_t actorId, uint32_t eventId, Event::EventHandler::EventType eventParam, uint8_t eventParam1, @@ -1107,8 +1107,8 @@ namespace Sapphire::Entity Common::PlayerTeleportQuery m_teleportQuery; - Util::SpawnIndexAllocator< uint8_t > m_objSpawnIndexAllocator; - Util::SpawnIndexAllocator< uint8_t > m_actorSpawnIndexAllocator; + Common::Util::SpawnIndexAllocator< uint8_t > m_objSpawnIndexAllocator; + Common::Util::SpawnIndexAllocator< uint8_t > m_actorSpawnIndexAllocator; std::array< Common::HuntingLogEntry, 12 > m_huntingLogEntries; diff --git a/src/world/Actor/PlayerEvent.cpp b/src/world/Actor/PlayerEvent.cpp index f264d180..91c9060f 100644 --- a/src/world/Actor/PlayerEvent.cpp +++ b/src/world/Actor/PlayerEvent.cpp @@ -278,11 +278,11 @@ void Sapphire::Entity::Player::eventFinish( uint32_t eventId, uint32_t freePlaye void Sapphire::Entity::Player::eventActionStart( uint32_t eventId, uint32_t action, - Action::ActionCallback finishCallback, - Action::ActionCallback interruptCallback, + World::Action::ActionCallback finishCallback, + World::Action::ActionCallback interruptCallback, uint64_t additional ) { - auto pEventAction = Action::make_EventAction( getAsChara(), eventId, action, + auto pEventAction = World::Action::make_EventAction( getAsChara(), eventId, action, finishCallback, interruptCallback, additional, m_pFw ); auto pEvent = getEvent( eventId ); @@ -309,8 +309,8 @@ void Sapphire::Entity::Player::eventActionStart( uint32_t eventId, void Sapphire::Entity::Player::eventItemActionStart( uint32_t eventId, uint32_t action, - Action::ActionCallback finishCallback, - Action::ActionCallback interruptCallback, + World::Action::ActionCallback finishCallback, + World::Action::ActionCallback interruptCallback, uint64_t additional ) { // Action::ActionPtr pEventItemAction = Action::make_EventItemAction( getAsChara(), eventId, action, diff --git a/src/world/ForwardsZone.h b/src/world/ForwardsZone.h index a432cac1..08de6d59 100644 --- a/src/world/ForwardsZone.h +++ b/src/world/ForwardsZone.h @@ -82,7 +82,7 @@ TYPE_FORWARD( Director ); TYPE_FORWARD( EventHandler ); } -namespace Action +namespace World::Action { TYPE_FORWARD( Action ); TYPE_FORWARD( EventAction ); diff --git a/src/world/Manager/DebugCommandMgr.cpp b/src/world/Manager/DebugCommandMgr.cpp index f414c1bd..933b7d94 100644 --- a/src/world/Manager/DebugCommandMgr.cpp +++ b/src/world/Manager/DebugCommandMgr.cpp @@ -683,7 +683,7 @@ void Sapphire::World::Manager::DebugCommandMgr::nudge( char* data, Entity::Playe setActorPosPacket->data().x = player.getPos().x; setActorPosPacket->data().y = player.getPos().y; setActorPosPacket->data().z = player.getPos().z; - setActorPosPacket->data().r16 = Util::floatToUInt16Rot( player.getRot() ); + setActorPosPacket->data().r16 = Common::Util::floatToUInt16Rot( player.getRot() ); player.queuePacket( setActorPosPacket ); } } diff --git a/src/world/Manager/MarketMgr.cpp b/src/world/Manager/MarketMgr.cpp index 9b62e534..1ad81cf9 100644 --- a/src/world/Manager/MarketMgr.cpp +++ b/src/world/Manager/MarketMgr.cpp @@ -83,7 +83,7 @@ void Sapphire::World::Manager::MarketMgr::requestItemListingInfo( Sapphire::Enti listing.itemCatalogId = catalogId; listing.quantity = i + 1; - listing.purchaseTime = Sapphire::Util::getTimeSeconds(); + listing.purchaseTime = Common::Util::getTimeSeconds(); listing.salePrice = 69420420; listing.isHq = 1; listing.onMannequin = 1; diff --git a/src/world/Network/GameConnection.cpp b/src/world/Network/GameConnection.cpp index 799835bb..7109b2ba 100644 --- a/src/world/Network/GameConnection.cpp +++ b/src/world/Network/GameConnection.cpp @@ -424,7 +424,7 @@ void Sapphire::Network::GameConnection::handlePackets( const Sapphire::Network:: auto pe = std::make_shared< FFXIVRawPacket >( 0x07, 0x18, 0, 0 ); *( unsigned int* ) ( &pe->data()[ 0 ] ) = 0xE0037603; - *( unsigned int* ) ( &pe->data()[ 4 ] ) = Sapphire::Util::getTimeSeconds(); + *( unsigned int* ) ( &pe->data()[ 4 ] ) = Common::Util::getTimeSeconds(); sendSinglePacket( pe ); // main connection, assinging it to the session diff --git a/src/world/Network/GameConnection.h b/src/world/Network/GameConnection.h index 61be56c5..56a8fc5d 100644 --- a/src/world/Network/GameConnection.h +++ b/src/world/Network/GameConnection.h @@ -51,8 +51,8 @@ namespace Sapphire::Network World::SessionPtr m_pSession; - LockedQueue< Sapphire::Network::Packets::FFXIVARR_PACKET_RAW > m_inQueue; - LockedQueue< Packets::FFXIVPacketBasePtr > m_outQueue; + Common::Util::LockedQueue< Sapphire::Network::Packets::FFXIVARR_PACKET_RAW > m_inQueue; + Common::Util::LockedQueue< Packets::FFXIVPacketBasePtr > m_outQueue; std::vector< uint8_t > m_packets; public: diff --git a/src/world/Network/Handlers/PacketHandlers.cpp b/src/world/Network/Handlers/PacketHandlers.cpp index afb97b0b..ba97168b 100644 --- a/src/world/Network/Handlers/PacketHandlers.cpp +++ b/src/world/Network/Handlers/PacketHandlers.cpp @@ -393,7 +393,7 @@ void Sapphire::Network::GameConnection::pingHandler( FrameworkPtr pFw, queueOutPacket( std::make_shared< Server::PingPacket >( player, packet.data().timestamp ) ); - player.setLastPing( Sapphire::Util::getTimeSeconds() ); + player.setLastPing( Common::Util::getTimeSeconds() ); } diff --git a/src/world/Network/PacketWrappers/MoveActorPacket.h b/src/world/Network/PacketWrappers/MoveActorPacket.h index 78718b41..9cf724fc 100644 --- a/src/world/Network/PacketWrappers/MoveActorPacket.h +++ b/src/world/Network/PacketWrappers/MoveActorPacket.h @@ -28,15 +28,15 @@ namespace Sapphire::Network::Packets::Server void initialize( Entity::Chara& actor, uint8_t headRotation, uint8_t animationType, uint8_t state, uint16_t animationSpeed, uint8_t unknownRotation ) { - m_data.rotation = Util::floatToUInt8Rot( actor.getRot() ); + m_data.rotation = Common::Util::floatToUInt8Rot( actor.getRot() ); m_data.headRotation = headRotation; m_data.animationType = animationType; m_data.animationState = state; m_data.animationSpeed = animationSpeed; m_data.unknownRotation = unknownRotation; - m_data.posX = Util::floatToUInt16( actor.getPos().x ); - m_data.posY = Util::floatToUInt16( actor.getPos().y ); - m_data.posZ = Util::floatToUInt16( actor.getPos().z ); + m_data.posX = Common::Util::floatToUInt16( actor.getPos().x ); + m_data.posY = Common::Util::floatToUInt16( actor.getPos().y ); + m_data.posZ = Common::Util::floatToUInt16( actor.getPos().z ); }; }; diff --git a/src/world/Network/PacketWrappers/NpcSpawnPacket.h b/src/world/Network/PacketWrappers/NpcSpawnPacket.h index 8f952c77..3cc99f89 100644 --- a/src/world/Network/PacketWrappers/NpcSpawnPacket.h +++ b/src/world/Network/PacketWrappers/NpcSpawnPacket.h @@ -49,7 +49,7 @@ namespace Sapphire::Network::Packets::Server m_data.pos.x = bnpc.getPos().x; m_data.pos.y = bnpc.getPos().y; m_data.pos.z = bnpc.getPos().z; - m_data.rotation = Util::floatToUInt16Rot( bnpc.getRot() ); + m_data.rotation = Common::Util::floatToUInt16Rot( bnpc.getRot() ); m_data.levelId = bnpc.getLevelId(); m_data.enemyType = bnpc.getEnemyType(); @@ -87,7 +87,7 @@ namespace Sapphire::Network::Packets::Server m_data.targetId = static_cast< uint64_t >( bnpc.getTargetId() ); - uint64_t currentTimeMs = Sapphire::Util::getTimeMs(); + uint64_t currentTimeMs = Common::Util::getTimeMs(); for( auto const& effect : bnpc.getStatusEffectMap() ) { diff --git a/src/world/Network/PacketWrappers/PlayerSpawnPacket.h b/src/world/Network/PacketWrappers/PlayerSpawnPacket.h index 14e16754..4f384356 100644 --- a/src/world/Network/PacketWrappers/PlayerSpawnPacket.h +++ b/src/world/Network/PacketWrappers/PlayerSpawnPacket.h @@ -69,7 +69,7 @@ namespace Sapphire::Network::Packets::Server m_data.pos.x = player.getPos().x; m_data.pos.y = player.getPos().y; m_data.pos.z = player.getPos().z; - m_data.rotation = Util::floatToUInt16Rot( player.getRot() ); + m_data.rotation = Common::Util::floatToUInt16Rot( player.getRot() ); m_data.title = player.getTitle(); @@ -133,7 +133,7 @@ namespace Sapphire::Network::Packets::Server //m_data.unknown_60 = 3; //m_data.unknown_61 = 7; - uint64_t currentTimeMs = Sapphire::Util::getTimeMs(); + uint64_t currentTimeMs = Common::Util::getTimeMs(); for( auto const& effect : player.getStatusEffectMap() ) { diff --git a/src/world/Script/NativeScriptApi.cpp b/src/world/Script/NativeScriptApi.cpp index 75d63621..d6dce0f6 100644 --- a/src/world/Script/NativeScriptApi.cpp +++ b/src/world/Script/NativeScriptApi.cpp @@ -83,20 +83,20 @@ namespace Sapphire::ScriptAPI /////////////////////////////////////////////////////////////////// - ActionScript::ActionScript( uint32_t abilityId ) : - ScriptObject( abilityId, typeid( ActionScript ).hash_code() ) + ActionScript::ActionScript( uint32_t actionId ) : + ScriptObject( actionId, typeid( ActionScript ).hash_code() ) { } - void ActionScript::onStart( Sapphire::Action::Action& action ) + void ActionScript::onStart( Sapphire::World::Action::Action& action ) { } - void ActionScript::onExecute( Sapphire::Action::Action& action ) + void ActionScript::onExecute( Sapphire::World::Action::Action& action ) { } - void ActionScript::onInterrupt( Sapphire::Action::Action& action ) + void ActionScript::onInterrupt( Sapphire::World::Action::Action& action ) { } diff --git a/src/world/Script/NativeScriptApi.h b/src/world/Script/NativeScriptApi.h index 4d31b5df..d7b33d00 100644 --- a/src/world/Script/NativeScriptApi.h +++ b/src/world/Script/NativeScriptApi.h @@ -138,13 +138,13 @@ namespace Sapphire::ScriptAPI class ActionScript : public ScriptObject { public: - explicit ActionScript( uint32_t abilityId ); + explicit ActionScript( uint32_t actionId ); - virtual void onStart( Sapphire::Action::Action& action ); + virtual void onStart( Sapphire::World::Action::Action& action ); - virtual void onExecute( Sapphire::Action::Action& action ); + virtual void onExecute( Sapphire::World::Action::Action& action ); - virtual void onInterrupt( Sapphire::Action::Action& action ); + virtual void onInterrupt( Sapphire::World::Action::Action& action ); }; /*! diff --git a/src/world/Script/ScriptLoader.cpp b/src/world/Script/ScriptLoader.cpp index f670c05c..ab72f61f 100644 --- a/src/world/Script/ScriptLoader.cpp +++ b/src/world/Script/ScriptLoader.cpp @@ -154,7 +154,7 @@ bool Sapphire::Scripting::ScriptLoader::isModuleLoaded( std::string name ) for( auto it = m_scriptMap.begin(); it != m_scriptMap.end(); ++it ) { - if( Util::toLowerCopy( it->second->library_name ) == Util::toLowerCopy( name ) ) + if( Common::Util::toLowerCopy( it->second->library_name ) == Common::Util::toLowerCopy( name ) ) return true; } diff --git a/src/world/Script/ScriptMgr.cpp b/src/world/Script/ScriptMgr.cpp index bb2a86e2..4b7bd27c 100644 --- a/src/world/Script/ScriptMgr.cpp +++ b/src/world/Script/ScriptMgr.cpp @@ -329,7 +329,7 @@ bool Sapphire::Scripting::ScriptMgr::onEObjHit( Sapphire::Entity::Player& player return didCallScript; } -bool Sapphire::Scripting::ScriptMgr::onExecute( Action::Action& action ) +bool Sapphire::Scripting::ScriptMgr::onExecute( World::Action::Action& action ) { auto script = m_nativeScriptMgr->getScript< Sapphire::ScriptAPI::ActionScript >( action.getId() ); @@ -341,7 +341,7 @@ bool Sapphire::Scripting::ScriptMgr::onExecute( Action::Action& action ) return false; } -bool Sapphire::Scripting::ScriptMgr::onInterrupt( Action::Action& action ) +bool Sapphire::Scripting::ScriptMgr::onInterrupt( World::Action::Action& action ) { auto script = m_nativeScriptMgr->getScript< Sapphire::ScriptAPI::ActionScript >( action.getId() ); @@ -353,7 +353,7 @@ bool Sapphire::Scripting::ScriptMgr::onInterrupt( Action::Action& action ) return false; } -bool Sapphire::Scripting::ScriptMgr::onStart( Action::Action& action ) +bool Sapphire::Scripting::ScriptMgr::onStart( World::Action::Action& action ) { auto script = m_nativeScriptMgr->getScript< Sapphire::ScriptAPI::ActionScript >( action.getId() ); diff --git a/src/world/Script/ScriptMgr.h b/src/world/Script/ScriptMgr.h index 546ec425..94bc8067 100644 --- a/src/world/Script/ScriptMgr.h +++ b/src/world/Script/ScriptMgr.h @@ -72,11 +72,11 @@ namespace Sapphire::Scripting bool onEObjHit( Entity::Player& player, uint64_t actorId, uint32_t actionId ); - bool onStart( Action::Action& action ); + bool onStart( World::Action::Action& action ); - bool onInterrupt( Action::Action& action ); + bool onInterrupt( World::Action::Action& action ); - bool onExecute( Action::Action& action ); + bool onExecute( World::Action::Action& action ); bool onStatusReceive( Entity::CharaPtr pActor, uint32_t effectId ); diff --git a/src/world/ServerMgr.cpp b/src/world/ServerMgr.cpp index 71cef6a0..1929c765 100644 --- a/src/world/ServerMgr.cpp +++ b/src/world/ServerMgr.cpp @@ -270,8 +270,8 @@ void Sapphire::World::ServerMgr::mainLoop() { std::this_thread::sleep_for( std::chrono::milliseconds( 50 ) ); - auto currTime = Util::getTimeSeconds(); - auto tickCount = Util::getTimeMs(); + auto currTime = Common::Util::getTimeSeconds(); + auto tickCount = Common::Util::getTimeMs(); pTeriMgr->updateTerritoryInstances( tickCount ); diff --git a/src/world/Session.cpp b/src/world/Session.cpp index 6e612421..b1e2c615 100644 --- a/src/world/Session.cpp +++ b/src/world/Session.cpp @@ -14,8 +14,8 @@ namespace fs = std::experimental::filesystem; Sapphire::World::Session::Session( uint32_t sessionId, FrameworkPtr pFw ) : m_sessionId( sessionId ), - m_lastDataTime( Util::getTimeSeconds() ), - m_lastSqlTime( Util::getTimeSeconds() ), + m_lastDataTime( Common::Util::getTimeSeconds() ), + m_lastSqlTime( Common::Util::getTimeSeconds() ), m_isValid( false ), m_pFw( std::move( pFw ) ), m_isReplaying( false ) @@ -102,12 +102,12 @@ bool Sapphire::World::Session::isValid() const void Sapphire::World::Session::updateLastDataTime() { - m_lastDataTime = Util::getTimeSeconds(); + m_lastDataTime = Common::Util::getTimeSeconds(); } void Sapphire::World::Session::updateLastSqlTime() { - m_lastSqlTime = Util::getTimeSeconds(); + m_lastSqlTime = Common::Util::getTimeSeconds(); } void Sapphire::World::Session::startReplay( const std::string& path ) @@ -146,7 +146,7 @@ void Sapphire::World::Session::startReplay( const std::string& path ) for( auto set : loadedSets ) { m_replayCache.push_back( std::tuple< uint64_t, std::string >( - Util::getTimeMs() + ( std::get< 0 >( set ) - startTime ), std::get< 1 >( set ) ) ); + Common::Util::getTimeMs() + ( std::get< 0 >( set ) - startTime ), std::get< 1 >( set ) ) ); Logger::info( "Registering {0} for {1}", std::get< 1 >( set ), std::get< 0 >( set ) - startTime ); } @@ -166,7 +166,7 @@ void Sapphire::World::Session::processReplay() int at = 0; for( const auto& set : m_replayCache ) { - if( std::get< 0 >( set ) <= Util::getTimeMs() ) + if( std::get< 0 >( set ) <= Common::Util::getTimeMs() ) { m_pZoneConnection->injectPacket( std::get< 1 >( set ), *getPlayer().get() ); m_replayCache.erase( m_replayCache.begin() + at ); @@ -201,9 +201,9 @@ void Sapphire::World::Session::update() m_pZoneConnection->processInQueue(); // SESSION LOGIC - m_pPlayer->update( Util::getTimeMs() ); + m_pPlayer->update( Common::Util::getTimeMs() ); - if( Util::getTimeSeconds() - static_cast< uint32_t >( getLastSqlTime() ) > 10 ) + if( Common::Util::getTimeSeconds() - static_cast< uint32_t >( getLastSqlTime() ) > 10 ) { updateLastSqlTime(); m_pPlayer->updateSql(); diff --git a/src/world/Territory/Zone.cpp b/src/world/Territory/Zone.cpp index 339f6399..e0a159c4 100644 --- a/src/world/Territory/Zone.cpp +++ b/src/world/Territory/Zone.cpp @@ -419,7 +419,7 @@ void Sapphire::Zone::updateBNpcs( uint64_t tickCount ) return; m_lastMobUpdate = tickCount; - uint64_t currTime = Sapphire::Util::getTimeSeconds(); + uint64_t currTime = Common::Util::getTimeSeconds(); for( const auto& entry : m_bNpcMap ) { diff --git a/src/world/Util/ActorFilter.cpp b/src/world/Util/ActorFilter.cpp index 4714e1d7..f15b074e 100644 --- a/src/world/Util/ActorFilter.cpp +++ b/src/world/Util/ActorFilter.cpp @@ -13,7 +13,7 @@ Sapphire::World::Util::ActorFilterInRange::ActorFilterInRange( Common::FFXIVARR_ bool Sapphire::World::Util::ActorFilterInRange::conditionApplies( const Entity::Actor& actor ) { - return Sapphire::Util::distance( m_startPos, actor.getPos() ) <= m_range; + return Sapphire::Common::Util::distance( m_startPos, actor.getPos() ) <= m_range; } /////////////////////////////////////////////////////////////////////////////////////////////////////// From d755ea2a321d0abb6383b66731699cc9bcfb3f99 Mon Sep 17 00:00:00 2001 From: NotAdam Date: Sun, 2 Jun 2019 02:30:54 +1000 Subject: [PATCH 047/351] somewhat working action lut stuff --- .../archer/ActionHeavyShot97.cpp | 23 --------- .../playeractions/conjurer/ActionCure120.cpp | 22 -------- .../darkknight/ActionAbyssalDrain3641.cpp | 24 --------- .../darkknight/ActionHardSlash3617.cpp | 23 --------- .../darkknight/ActionPowerSlash3627.cpp | 22 -------- .../darkknight/ActionSpinningSlash3619.cpp | 22 -------- .../darkknight/ActionSyphonStrike3623.cpp | 22 -------- .../darkknight/ActionUnleash3621.cpp | 24 --------- .../whitemage/ActionAsylum3569.cpp | 22 -------- src/world/Action/Action.cpp | 50 +++++++++++-------- src/world/Action/Action.h | 4 +- src/world/Action/ActionLut.cpp | 10 ++++ src/world/Action/ActionLut.h | 1 + src/world/Manager/ActionMgr.cpp | 2 +- 14 files changed, 44 insertions(+), 227 deletions(-) delete mode 100644 src/scripts/action/playeractions/archer/ActionHeavyShot97.cpp delete mode 100644 src/scripts/action/playeractions/conjurer/ActionCure120.cpp delete mode 100644 src/scripts/action/playeractions/darkknight/ActionAbyssalDrain3641.cpp delete mode 100644 src/scripts/action/playeractions/darkknight/ActionHardSlash3617.cpp delete mode 100644 src/scripts/action/playeractions/darkknight/ActionPowerSlash3627.cpp delete mode 100644 src/scripts/action/playeractions/darkknight/ActionSpinningSlash3619.cpp delete mode 100644 src/scripts/action/playeractions/darkknight/ActionSyphonStrike3623.cpp delete mode 100644 src/scripts/action/playeractions/darkknight/ActionUnleash3621.cpp delete mode 100644 src/scripts/action/playeractions/whitemage/ActionAsylum3569.cpp diff --git a/src/scripts/action/playeractions/archer/ActionHeavyShot97.cpp b/src/scripts/action/playeractions/archer/ActionHeavyShot97.cpp deleted file mode 100644 index 3c3ef16f..00000000 --- a/src/scripts/action/playeractions/archer/ActionHeavyShot97.cpp +++ /dev/null @@ -1,23 +0,0 @@ -#include