mirror of
https://github.com/SapphireServer/Sapphire.git
synced 2025-04-26 14:37:44 +00:00
Merge pull request #511 from NotAdam/develop
fixed bnpc movement speed tick rate inconsistency
This commit is contained in:
commit
ab9de4bed8
11 changed files with 98 additions and 33 deletions
|
@ -15,6 +15,11 @@ float Sapphire::Util::distance( float x, float y, float z, float x1, float y1, f
|
||||||
return sqrtf( distanceSq( x, y, z, x1, y1, z1 ) );
|
return sqrtf( distanceSq( x, y, z, x1, y1, z1 ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float Sapphire::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 Sapphire::Util::distance2DSq( float x, float y, float x1, float y1 )
|
||||||
{
|
{
|
||||||
float deltaX = x - x1;
|
float deltaX = x - x1;
|
||||||
|
|
|
@ -11,6 +11,7 @@ namespace Sapphire::Util
|
||||||
float distanceSq( float x, float y, float z, float x1, float y1, float z1 );
|
float distanceSq( float x, float y, float z, float x1, float y1, float z1 );
|
||||||
|
|
||||||
float distance( float x, float y, float z, float x1, float y1, float z1 );
|
float distance( float x, float y, float z, float x1, float y1, float z1 );
|
||||||
|
float distance( const Common::FFXIVARR_POSITION3& pos1, const Common::FFXIVARR_POSITION3& pos2 );
|
||||||
|
|
||||||
float distance2DSq( float x, float y, float x1, float y1 );
|
float distance2DSq( float x, float y, float x1, float y1 );
|
||||||
|
|
||||||
|
|
|
@ -88,6 +88,7 @@ Sapphire::Entity::BNpc::BNpc( uint32_t id, BNpcTemplatePtr pTemplate, float posX
|
||||||
memcpy( m_customize, pTemplate->getCustomize(), sizeof( m_customize ) );
|
memcpy( m_customize, pTemplate->getCustomize(), sizeof( m_customize ) );
|
||||||
memcpy( m_modelEquip, pTemplate->getModelEquip(), sizeof( m_modelEquip ) );
|
memcpy( m_modelEquip, pTemplate->getModelEquip(), sizeof( m_modelEquip ) );
|
||||||
|
|
||||||
|
m_lastTickTime = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
Sapphire::Entity::BNpc::~BNpc()
|
Sapphire::Entity::BNpc::~BNpc()
|
||||||
|
@ -162,11 +163,9 @@ void Sapphire::Entity::BNpc::step()
|
||||||
return;
|
return;
|
||||||
|
|
||||||
auto stepPos = m_naviLastPath[ m_naviPathStep ];
|
auto stepPos = m_naviLastPath[ m_naviPathStep ];
|
||||||
auto distanceToStep = Util::distance( getPos().x, getPos().y, getPos().z,
|
|
||||||
stepPos.x, stepPos.y, stepPos.z );
|
|
||||||
|
|
||||||
auto distanceToDest = Util::distance( getPos().x, getPos().y, getPos().z,
|
auto distanceToStep = Util::distance( getPos(), stepPos );
|
||||||
m_naviTarget.x, m_naviTarget.y, m_naviTarget.z );
|
auto distanceToDest = Util::distance( getPos(), m_naviTarget );
|
||||||
|
|
||||||
if( distanceToStep <= 4 && m_naviPathStep < m_naviLastPath.size() - 1 )
|
if( distanceToStep <= 4 && m_naviPathStep < m_naviLastPath.size() - 1 )
|
||||||
{
|
{
|
||||||
|
@ -178,15 +177,16 @@ void Sapphire::Entity::BNpc::step()
|
||||||
// This is probably not a good way to do it but works fine for now
|
// 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;
|
float angle = Util::calcAngFrom( getPos().x, getPos().z, stepPos.x, stepPos.z ) + PI;
|
||||||
|
|
||||||
float speed = 1.7f;
|
auto delta = static_cast< float >( Util::getTimeMs() - m_lastUpdate ) / 1000.f;
|
||||||
|
|
||||||
|
float speed = 7.5f * delta;
|
||||||
|
|
||||||
if( m_state == BNpcState::Roaming )
|
if( m_state == BNpcState::Roaming )
|
||||||
speed *= 0.5f;
|
speed *= 0.27f;
|
||||||
|
|
||||||
if( distanceToDest <= distanceToStep + speed )
|
// this seems to fix it but i don't know why :(
|
||||||
{
|
if( speed > distanceToDest )
|
||||||
speed = distanceToDest;
|
speed = distanceToDest / delta;
|
||||||
}
|
|
||||||
|
|
||||||
auto x = ( cosf( angle ) * speed );
|
auto x = ( cosf( angle ) * speed );
|
||||||
auto y = stepPos.y;
|
auto y = stepPos.y;
|
||||||
|
@ -201,7 +201,7 @@ void Sapphire::Entity::BNpc::step()
|
||||||
|
|
||||||
bool Sapphire::Entity::BNpc::moveTo( const FFXIVARR_POSITION3& pos )
|
bool Sapphire::Entity::BNpc::moveTo( const FFXIVARR_POSITION3& pos )
|
||||||
{
|
{
|
||||||
if( Util::distance( getPos().x, getPos().y, getPos().z, pos.x, pos.y, pos.z ) <= 4 )
|
if( Util::distance( getPos(), pos ) <= 4 )
|
||||||
{
|
{
|
||||||
// Reached destination
|
// Reached destination
|
||||||
m_naviLastPath.clear();
|
m_naviLastPath.clear();
|
||||||
|
@ -233,7 +233,27 @@ bool Sapphire::Entity::BNpc::moveTo( const FFXIVARR_POSITION3& pos )
|
||||||
Logger::debug( "No path found from x{0} y{1} z{2} to x{3} y{4} z{5} in {6}",
|
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() );
|
getPos().x, getPos().y, getPos().z, pos.x, pos.y, pos.z, m_pCurrentZone->getInternalName() );
|
||||||
|
|
||||||
|
|
||||||
hateListClear();
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -368,6 +388,14 @@ void Sapphire::Entity::BNpc::deaggro( Sapphire::Entity::CharaPtr pChara )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Sapphire::Entity::BNpc::onTick()
|
||||||
|
{
|
||||||
|
if( m_state == BNpcState::Retreat )
|
||||||
|
{
|
||||||
|
regainHp();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Sapphire::Entity::BNpc::update( int64_t currTime )
|
void Sapphire::Entity::BNpc::update( int64_t currTime )
|
||||||
{
|
{
|
||||||
const uint8_t minActorDistance = 4;
|
const uint8_t minActorDistance = 4;
|
||||||
|
@ -386,10 +414,6 @@ void Sapphire::Entity::BNpc::update( int64_t currTime )
|
||||||
{
|
{
|
||||||
setInvincibilityType( InvincibilityType::InvincibilityIgnoreDamage );
|
setInvincibilityType( InvincibilityType::InvincibilityIgnoreDamage );
|
||||||
|
|
||||||
if( std::difftime( currTime, m_lastTickTime ) > 3000 )
|
|
||||||
regainHp( currTime );
|
|
||||||
|
|
||||||
// slowly restore hp every tick
|
|
||||||
if( moveTo( m_spawnPos ) )
|
if( moveTo( m_spawnPos ) )
|
||||||
{
|
{
|
||||||
setInvincibilityType( InvincibilityType::InvincibilityNone );
|
setInvincibilityType( InvincibilityType::InvincibilityNone );
|
||||||
|
@ -491,12 +515,13 @@ void Sapphire::Entity::BNpc::update( int64_t currTime )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Chara::update( currTime );
|
||||||
}
|
}
|
||||||
|
|
||||||
void Sapphire::Entity::BNpc::regainHp( int64_t currTime )
|
void Sapphire::Entity::BNpc::regainHp()
|
||||||
{
|
{
|
||||||
this->m_lastTickTime = currTime;
|
|
||||||
|
|
||||||
if( this->m_hp < this->getMaxHp() )
|
if( this->m_hp < this->getMaxHp() )
|
||||||
{
|
{
|
||||||
auto addHp = static_cast< uint32_t >( this->getMaxHp() * 0.1f + 1 );
|
auto addHp = static_cast< uint32_t >( this->getMaxHp() * 0.1f + 1 );
|
||||||
|
|
|
@ -82,6 +82,7 @@ namespace Sapphire::Entity
|
||||||
void deaggro( CharaPtr pChara );
|
void deaggro( CharaPtr pChara );
|
||||||
|
|
||||||
void update( int64_t currTime ) override;
|
void update( int64_t currTime ) override;
|
||||||
|
void onTick() override;
|
||||||
|
|
||||||
void onActionHostile( CharaPtr pSource ) override;
|
void onActionHostile( CharaPtr pSource ) override;
|
||||||
|
|
||||||
|
@ -90,7 +91,7 @@ namespace Sapphire::Entity
|
||||||
uint32_t getTimeOfDeath() const;
|
uint32_t getTimeOfDeath() const;
|
||||||
void setTimeOfDeath( uint32_t timeOfDeath );
|
void setTimeOfDeath( uint32_t timeOfDeath );
|
||||||
|
|
||||||
void regainHp( int64_t currTime );
|
void regainHp();
|
||||||
|
|
||||||
void checkAggro( uint32_t range );
|
void checkAggro( uint32_t range );
|
||||||
|
|
||||||
|
|
|
@ -280,6 +280,18 @@ bool Sapphire::Entity::Chara::checkAction()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Sapphire::Entity::Chara::update( int64_t currTime )
|
||||||
|
{
|
||||||
|
if( std::difftime( currTime, m_lastTickTime ) > 3000 )
|
||||||
|
{
|
||||||
|
onTick();
|
||||||
|
|
||||||
|
m_lastTickTime = currTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_lastUpdate = currTime;
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
Change the current target and propagate to in range players
|
Change the current target and propagate to in range players
|
||||||
|
|
||||||
|
|
|
@ -68,11 +68,11 @@ namespace Sapphire::Entity
|
||||||
protected:
|
protected:
|
||||||
char m_name[34];
|
char m_name[34];
|
||||||
/*! Last tick time for the actor ( in ms ) */
|
/*! Last tick time for the actor ( in ms ) */
|
||||||
uint64_t m_lastTickTime;
|
int64_t m_lastTickTime;
|
||||||
/*! Last time the actor performed an autoAttack ( in ms ) */
|
/*! Last time the actor performed an autoAttack ( in ms ) */
|
||||||
uint64_t m_lastAttack;
|
uint64_t m_lastAttack;
|
||||||
/*! Last time the actor was updated ( in ms ) */
|
/*! Last time the actor was updated ( in ms ) */
|
||||||
uint64_t m_lastUpdate;
|
int64_t m_lastUpdate;
|
||||||
/*! Current stance of the actor */
|
/*! Current stance of the actor */
|
||||||
Common::Stance m_currentStance;
|
Common::Stance m_currentStance;
|
||||||
/*! Current staus of the actor */
|
/*! Current staus of the actor */
|
||||||
|
@ -237,7 +237,7 @@ namespace Sapphire::Entity
|
||||||
|
|
||||||
virtual bool checkAction();
|
virtual bool checkAction();
|
||||||
|
|
||||||
virtual void update( int64_t currTime ) {};
|
virtual void update( int64_t currTime );
|
||||||
|
|
||||||
Action::ActionPtr getCurrentAction() const;
|
Action::ActionPtr getCurrentAction() const;
|
||||||
|
|
||||||
|
|
|
@ -1043,7 +1043,6 @@ void Sapphire::Entity::Player::unsetStateFlag( Common::PlayerStateFlag flag )
|
||||||
|
|
||||||
void Sapphire::Entity::Player::update( int64_t currTime )
|
void Sapphire::Entity::Player::update( int64_t currTime )
|
||||||
{
|
{
|
||||||
|
|
||||||
// a zoning is pending, lets do it
|
// a zoning is pending, lets do it
|
||||||
if( m_queuedZoneing && ( currTime - m_queuedZoneing->m_queueTime ) > 800 )
|
if( m_queuedZoneing && ( currTime - m_queuedZoneing->m_queueTime ) > 800 )
|
||||||
{
|
{
|
||||||
|
@ -1115,13 +1114,7 @@ void Sapphire::Entity::Player::update( int64_t currTime )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if( ( currTime - m_lastTickTime ) > 3000 )
|
Chara::update( currTime );
|
||||||
{
|
|
||||||
// add 3 seconds to total play time
|
|
||||||
m_playTime += 3;
|
|
||||||
m_lastTickTime = currTime;
|
|
||||||
onTick();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Sapphire::Entity::Player::onMobKill( uint16_t nameId )
|
void Sapphire::Entity::Player::onMobKill( uint16_t nameId )
|
||||||
|
|
|
@ -355,6 +355,9 @@ void Sapphire::Entity::Player::onDeath()
|
||||||
void Sapphire::Entity::Player::onTick()
|
void Sapphire::Entity::Player::onTick()
|
||||||
{
|
{
|
||||||
|
|
||||||
|
// add 3 seconds to total play time
|
||||||
|
m_playTime += 3;
|
||||||
|
|
||||||
bool sendUpdate = false;
|
bool sendUpdate = false;
|
||||||
|
|
||||||
if( !isAlive() || !isLoadingComplete() )
|
if( !isAlive() || !isLoadingComplete() )
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
|
|
||||||
namespace Sapphire::World::Navi
|
namespace Sapphire::World::Navi
|
||||||
{
|
{
|
||||||
const int32_t MAX_POLYS = 8;
|
const int32_t MAX_POLYS = 32;
|
||||||
const int32_t MAX_SMOOTH = 2048;
|
const int32_t MAX_SMOOTH = 2048;
|
||||||
|
|
||||||
const int32_t NAVMESHSET_MAGIC = 'M' << 24 | 'S' << 16 | 'E' << 8 | 'T'; //'MSET'
|
const int32_t NAVMESHSET_MAGIC = 'M' << 24 | 'S' << 16 | 'E' << 8 | 'T'; //'MSET'
|
||||||
|
|
|
@ -399,13 +399,38 @@ void Sapphire::Network::GameConnection::gm1Handler( FrameworkPtr pFw,
|
||||||
}
|
}
|
||||||
case GmCommand::GC:
|
case GmCommand::GC:
|
||||||
{
|
{
|
||||||
|
if( param1 > 3 )
|
||||||
|
{
|
||||||
|
player.sendUrgent( "Invalid Grand Company ID: {0}", param1 );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
targetPlayer->setGc( param1 );
|
targetPlayer->setGc( param1 );
|
||||||
|
|
||||||
|
// if we're changing them to a GC, check if they have a rank and if not, set it to the lowest rank
|
||||||
|
if( param1 > 0 )
|
||||||
|
{
|
||||||
|
auto gcRankIdx = static_cast< uint8_t >( param1 ) - 1;
|
||||||
|
if( targetPlayer->getGcRankArray()[ gcRankIdx ] == 0 )
|
||||||
|
{
|
||||||
|
player.setGcRankAt( gcRankIdx, 1 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
player.sendNotice( "GC for {0} was set to {1}", targetPlayer->getName(), targetPlayer->getGc() );
|
player.sendNotice( "GC for {0} was set to {1}", targetPlayer->getName(), targetPlayer->getGc() );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case GmCommand::GCRank:
|
case GmCommand::GCRank:
|
||||||
{
|
{
|
||||||
targetPlayer->setGcRankAt( targetPlayer->getGc() - 1, param1 );
|
auto gcId = targetPlayer->getGc() - 1;
|
||||||
|
|
||||||
|
if( gcId > 2 )
|
||||||
|
{
|
||||||
|
player.sendUrgent( "{0} has an invalid Grand Company ID: {0}", targetPlayer->getName(), gcId );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
targetPlayer->setGcRankAt( gcId, param1 );
|
||||||
player.sendNotice( "GC Rank for {0} for GC {1} was set to {2}", targetPlayer->getName(), targetPlayer->getGc(),
|
player.sendNotice( "GC Rank for {0} for GC {1} was set to {2}", targetPlayer->getName(), targetPlayer->getGc(),
|
||||||
targetPlayer->getGcRankArray()[ targetPlayer->getGc() - 1 ] );
|
targetPlayer->getGcRankArray()[ targetPlayer->getGc() - 1 ] );
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -393,7 +393,7 @@ void Sapphire::Zone::updateBNpcs( int64_t tickCount )
|
||||||
m_lastMobUpdate = tickCount;
|
m_lastMobUpdate = tickCount;
|
||||||
uint32_t currTime = Sapphire::Util::getTimeSeconds();
|
uint32_t currTime = Sapphire::Util::getTimeSeconds();
|
||||||
|
|
||||||
for( auto entry : m_bNpcMap )
|
for( const auto& entry : m_bNpcMap )
|
||||||
{
|
{
|
||||||
Entity::BNpcPtr pBNpc = entry.second;
|
Entity::BNpcPtr pBNpc = entry.second;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue