mirror of
https://github.com/SapphireServer/Sapphire.git
synced 2025-05-01 00:27:44 +00:00
Fixed spawning issues and navi problems in encounters
This commit is contained in:
parent
25ab437d3d
commit
c0aed54dfe
13 changed files with 75 additions and 87 deletions
|
@ -1867,6 +1867,7 @@ namespace Sapphire::Common
|
||||||
CircularAOE = 2,
|
CircularAOE = 2,
|
||||||
RectangularAOE = 3,
|
RectangularAOE = 3,
|
||||||
ConeAOE = 4,
|
ConeAOE = 4,
|
||||||
|
CircularAOESelf = 5,
|
||||||
CircularAoEPlaced = 7
|
CircularAoEPlaced = 7
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,7 @@ public:
|
||||||
{
|
{
|
||||||
instance.addEObj( "Entrance", 2000182, 4177874, 4177871, 5, { -16.000000f, 0.000000f, 0.000000f }, 1.000000f, 0.000000f, 0);
|
instance.addEObj( "Entrance", 2000182, 4177874, 4177871, 5, { -16.000000f, 0.000000f, 0.000000f }, 1.000000f, 0.000000f, 0);
|
||||||
// States -> vf_lock_on (id: 11) vf_lock_of (id: 12)
|
// States -> vf_lock_on (id: 11) vf_lock_of (id: 12)
|
||||||
instance.addEObj( "Exit", 2000139, 0, 4177870, 4, { 16.000000f, 0.000000f, 0.000000f }, 1.000000f, 0.000000f, 0);
|
// instance.addEObj( "Exit", 2000139, 0, 4177870, 4, { 16.000000f, 0.000000f, 0.000000f }, 1.000000f, 0.000000f, 0);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,8 @@ void AI::Fsm::StateCombat::onUpdate( Entity::BNpc& bnpc, uint64_t tickCount )
|
||||||
if( !pHatedActor )
|
if( !pHatedActor )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
pNaviProvider->updateAgentParameters( bnpc );
|
if( pNaviProvider && bnpc.pathingActive() )
|
||||||
|
pNaviProvider->updateAgentParameters( bnpc );
|
||||||
|
|
||||||
auto distanceOrig = Common::Util::distance( bnpc.getPos(), bnpc.getSpawnPos() );
|
auto distanceOrig = Common::Util::distance( bnpc.getPos(), bnpc.getSpawnPos() );
|
||||||
|
|
||||||
|
@ -42,7 +43,9 @@ void AI::Fsm::StateCombat::onUpdate( Entity::BNpc& bnpc, uint64_t tickCount )
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if( !hasQueuedAction && !bnpc.hasFlag( Entity::Immobile ) && distance > ( bnpc.getNaviTargetReachedDistance() + pHatedActor->getRadius() ) )
|
if( bnpc.pathingActive() && !hasQueuedAction &&
|
||||||
|
!bnpc.hasFlag( Entity::Immobile ) &&
|
||||||
|
distance > ( bnpc.getNaviTargetReachedDistance() + pHatedActor->getRadius() ) )
|
||||||
{
|
{
|
||||||
|
|
||||||
if( pNaviProvider )
|
if( pNaviProvider )
|
||||||
|
@ -53,14 +56,13 @@ void AI::Fsm::StateCombat::onUpdate( Entity::BNpc& bnpc, uint64_t tickCount )
|
||||||
|
|
||||||
pNaviProvider->syncPosToChara( bnpc );
|
pNaviProvider->syncPosToChara( bnpc );
|
||||||
|
|
||||||
if( !hasQueuedAction && distance < ( bnpc.getNaviTargetReachedDistance() + pHatedActor->getRadius() ) )
|
if( !hasQueuedAction && (distance < ( bnpc.getNaviTargetReachedDistance() + pHatedActor->getRadius() ) || !bnpc.pathingActive() ) )
|
||||||
{
|
{
|
||||||
// todo: dont turn if facing
|
// todo: dont turn if facing
|
||||||
if( !bnpc.hasFlag( Entity::TurningDisabled ) )
|
if( !bnpc.hasFlag( Entity::TurningDisabled ) )
|
||||||
bnpc.face( pHatedActor->getPos() );
|
bnpc.face( pHatedActor->getPos() );
|
||||||
|
|
||||||
if( !hasQueuedAction )
|
bnpc.processGambits( tickCount );
|
||||||
bnpc.processGambits( tickCount );
|
|
||||||
|
|
||||||
// in combat range. ATTACK!
|
// in combat range. ATTACK!
|
||||||
if( !bnpc.hasFlag( Entity::BNpcFlag::AutoAttackDisabled ) )
|
if( !bnpc.hasFlag( Entity::BNpcFlag::AutoAttackDisabled ) )
|
||||||
|
|
|
@ -15,7 +15,7 @@ void AI::Fsm::StateRoam::onUpdate( Entity::BNpc& bnpc, uint64_t tickCount )
|
||||||
auto pZone = teriMgr.getTerritoryByGuId( bnpc.getTerritoryId() );
|
auto pZone = teriMgr.getTerritoryByGuId( bnpc.getTerritoryId() );
|
||||||
auto pNaviProvider = pZone->getNaviProvider();
|
auto pNaviProvider = pZone->getNaviProvider();
|
||||||
|
|
||||||
if( bnpc.hasFlag( Entity::NoRoam ) )
|
if( bnpc.hasFlag( Entity::NoRoam ) || bnpc.hasFlag( Entity::Immobile ) || !bnpc.pathingActive() )
|
||||||
{
|
{
|
||||||
bnpc.setRoamTargetReached( true );
|
bnpc.setRoamTargetReached( true );
|
||||||
return;
|
return;
|
||||||
|
@ -38,7 +38,7 @@ void AI::Fsm::StateRoam::onEnter( Entity::BNpc& bnpc )
|
||||||
auto pZone = teriMgr.getTerritoryByGuId( bnpc.getTerritoryId() );
|
auto pZone = teriMgr.getTerritoryByGuId( bnpc.getTerritoryId() );
|
||||||
auto pNaviProvider = pZone->getNaviProvider();
|
auto pNaviProvider = pZone->getNaviProvider();
|
||||||
|
|
||||||
if( !pNaviProvider )
|
if( !pNaviProvider || bnpc.hasFlag( Entity::NoRoam ) || bnpc.hasFlag( Entity::Immobile ) )
|
||||||
{
|
{
|
||||||
bnpc.setRoamTargetReached( true );
|
bnpc.setRoamTargetReached( true );
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -88,6 +88,7 @@ BNpc::BNpc( uint32_t id, std::shared_ptr< Common::BNPCInstanceObject > pInfo, co
|
||||||
m_pos.x = pInfo->x;
|
m_pos.x = pInfo->x;
|
||||||
m_pos.y = pInfo->y;
|
m_pos.y = pInfo->y;
|
||||||
m_pos.z = pInfo->z;
|
m_pos.z = pInfo->z;
|
||||||
|
m_lastPos = m_pos;
|
||||||
m_rot = pInfo->rotation;
|
m_rot = pInfo->rotation;
|
||||||
m_level = pInfo->Level <= 0 ? 1 : pInfo->Level;
|
m_level = pInfo->Level <= 0 ? 1 : pInfo->Level;
|
||||||
m_invincibilityType = InvincibilityNone;
|
m_invincibilityType = InvincibilityNone;
|
||||||
|
@ -203,6 +204,7 @@ BNpc::BNpc( uint32_t id, std::shared_ptr< Common::BNPCInstanceObject > pInfo, co
|
||||||
m_pos.x = pInfo->x;
|
m_pos.x = pInfo->x;
|
||||||
m_pos.y = pInfo->y;
|
m_pos.y = pInfo->y;
|
||||||
m_pos.z = pInfo->z;
|
m_pos.z = pInfo->z;
|
||||||
|
m_lastPos = m_pos;
|
||||||
m_rot = pInfo->rotation;
|
m_rot = pInfo->rotation;
|
||||||
m_level = pInfo->Level <= 0 ? 1 : pInfo->Level;
|
m_level = pInfo->Level <= 0 ? 1 : pInfo->Level;
|
||||||
m_invincibilityType = InvincibilityNone;
|
m_invincibilityType = InvincibilityNone;
|
||||||
|
@ -832,7 +834,30 @@ bool BNpc::hasFlag( uint32_t flag ) const
|
||||||
|
|
||||||
void BNpc::setFlag( uint32_t flag )
|
void BNpc::setFlag( uint32_t flag )
|
||||||
{
|
{
|
||||||
|
uint32_t oldFlags = m_flags;
|
||||||
m_flags |= flag;
|
m_flags |= flag;
|
||||||
|
|
||||||
|
auto& teriMgr = Common::Service< World::Manager::TerritoryMgr >::ref();
|
||||||
|
auto pZone = teriMgr.getTerritoryByGuId( getTerritoryId() );
|
||||||
|
|
||||||
|
|
||||||
|
if( pZone && ( oldFlags & Entity::Immobile ) != Entity::Immobile &&
|
||||||
|
( m_flags & Entity::Immobile ) == Entity::Immobile )
|
||||||
|
{
|
||||||
|
auto pNaviProvider = pZone->getNaviProvider();
|
||||||
|
pNaviProvider->removeAgent( *this );
|
||||||
|
setAgentId( 0 );
|
||||||
|
setPathingActive( false );
|
||||||
|
}
|
||||||
|
else if( pZone && ( oldFlags & Entity::Immobile ) == Entity::Immobile &&
|
||||||
|
( m_flags & Entity::Immobile ) != Entity::Immobile )
|
||||||
|
{
|
||||||
|
auto pNaviProvider = pZone->getNaviProvider();
|
||||||
|
pNaviProvider->removeAgent( *this );
|
||||||
|
auto agentId = pNaviProvider->addAgent( *this );
|
||||||
|
setAgentId( agentId );
|
||||||
|
setPathingActive( true );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void BNpc::removeFlag( uint32_t flag )
|
void BNpc::removeFlag( uint32_t flag )
|
||||||
|
|
|
@ -99,7 +99,7 @@ namespace Sapphire::Entity
|
||||||
std::map< uint8_t, StatusEffect::StatusEffectPtr > m_statusEffectMap;
|
std::map< uint8_t, StatusEffect::StatusEffectPtr > m_statusEffectMap;
|
||||||
|
|
||||||
/*! Detour Crowd AgentId */
|
/*! Detour Crowd AgentId */
|
||||||
uint32_t m_agentId;
|
uint32_t m_agentId{0};
|
||||||
|
|
||||||
/*! Detour Crowd actor scale */
|
/*! Detour Crowd actor scale */
|
||||||
float m_radius;
|
float m_radius;
|
||||||
|
|
|
@ -12,3 +12,13 @@ Npc::Npc( ObjKind type ) : Chara( type )
|
||||||
Npc::~Npc()
|
Npc::~Npc()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Npc::pathingActive() const
|
||||||
|
{
|
||||||
|
return m_bPathingActive;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Npc::setPathingActive( bool pathing )
|
||||||
|
{
|
||||||
|
m_bPathingActive = pathing;
|
||||||
|
}
|
||||||
|
|
|
@ -23,6 +23,12 @@ namespace Sapphire::Entity
|
||||||
Npc( Common::ObjKind type );
|
Npc( Common::ObjKind type );
|
||||||
|
|
||||||
virtual ~Npc() override;
|
virtual ~Npc() override;
|
||||||
|
bool pathingActive() const;
|
||||||
|
void setPathingActive( bool pathing );
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool m_bPathingActive{true};
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -32,9 +32,6 @@ namespace Sapphire
|
||||||
|
|
||||||
void start() override
|
void start() override
|
||||||
{
|
{
|
||||||
auto ifritInitState = makeIfritPhaseOneState();
|
|
||||||
|
|
||||||
addState( ifritInitState );
|
|
||||||
|
|
||||||
m_status = EncounterFightStatus::ACTIVE;
|
m_status = EncounterFightStatus::ACTIVE;
|
||||||
}
|
}
|
||||||
|
@ -51,60 +48,6 @@ namespace Sapphire
|
||||||
init();
|
init();
|
||||||
}
|
}
|
||||||
|
|
||||||
EncounterStatePtr makeIfritPhaseOneState()
|
|
||||||
{
|
|
||||||
auto ifritInitState = std::make_shared< EncounterState >( shared_from_this() );
|
|
||||||
ifritInitState->setOnUpdateCallback( [ & ]( EncounterFightPtr pEncounter, EncounterState state ) {
|
|
||||||
auto timeElapsedMs = state.getElapsedTime();
|
|
||||||
|
|
||||||
auto pIfrit = pEncounter->getBNpc( NPC_IFRIT );
|
|
||||||
|
|
||||||
pIfrit->setRot( pIfrit->getRot() + .2f );
|
|
||||||
|
|
||||||
// todo: use gambits+timelines for this
|
|
||||||
if( timeElapsedMs > 10000 )
|
|
||||||
{
|
|
||||||
state.setFinishFlag();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// todo: use gambits+timelines for this
|
|
||||||
if( timeElapsedMs > 5000 )
|
|
||||||
{
|
|
||||||
auto ifritTwoState = makeIfritPhaseTwoState();
|
|
||||||
pEncounter->addState( ifritTwoState );
|
|
||||||
}
|
|
||||||
} );
|
|
||||||
|
|
||||||
ifritInitState->setOnFinishCallback( [ & ]( EncounterFightPtr pEncounter, EncounterState state ) {
|
|
||||||
Logger::info( "stage 1 finish - enrage" );
|
|
||||||
|
|
||||||
auto pIfrit = pEncounter->getBNpc( NPC_IFRIT );
|
|
||||||
pIfrit->hateListGetHighest()->die();
|
|
||||||
} );
|
|
||||||
|
|
||||||
return ifritInitState;
|
|
||||||
}
|
|
||||||
|
|
||||||
EncounterStatePtr makeIfritPhaseTwoState()
|
|
||||||
{
|
|
||||||
auto ifritTwoState = std::make_shared< EncounterState >( shared_from_this() );
|
|
||||||
ifritTwoState->setOnUpdateCallback( [ & ]( EncounterFightPtr pEncounter, EncounterState state ) {
|
|
||||||
auto timeElapsedMs = state.getElapsedTime();
|
|
||||||
|
|
||||||
auto pIfrit = pEncounter->getBNpc( NPC_IFRIT );
|
|
||||||
|
|
||||||
pIfrit->setRot( pIfrit->getRot() - .2f );
|
|
||||||
|
|
||||||
// todo: use gambits+timelines for this
|
|
||||||
if( timeElapsedMs > 5000 )
|
|
||||||
{
|
|
||||||
state.setFinishFlag();
|
|
||||||
}
|
|
||||||
} );
|
|
||||||
|
|
||||||
return ifritTwoState;
|
|
||||||
}
|
|
||||||
|
|
||||||
void update( uint64_t deltaTime ) override
|
void update( uint64_t deltaTime ) override
|
||||||
{
|
{
|
||||||
|
@ -126,19 +69,6 @@ namespace Sapphire
|
||||||
|
|
||||||
m_pInstance->getEncounterTimeline().update( getInstance(), deltaTime );
|
m_pInstance->getEncounterTimeline().update( getInstance(), deltaTime );
|
||||||
|
|
||||||
//*
|
|
||||||
if( m_stateStack; !m_stateStack->empty() )
|
|
||||||
{
|
|
||||||
if( m_stateStack->top()->shouldFinish() )
|
|
||||||
{
|
|
||||||
m_stateStack->top()->finish();
|
|
||||||
m_stateStack->pop();
|
|
||||||
}
|
|
||||||
|
|
||||||
if( !m_stateStack->empty() )
|
|
||||||
m_stateStack->top()->update( deltaTime );
|
|
||||||
}
|
|
||||||
//*/
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}// namespace Sapphire
|
}// namespace Sapphire
|
|
@ -177,7 +177,7 @@ namespace Sapphire::Encounter
|
||||||
auto pParent = pTeri->getActiveBNpcByLayoutId( m_layoutId );
|
auto pParent = pTeri->getActiveBNpcByLayoutId( m_layoutId );
|
||||||
Common::BNpcType type = pParent ? pParent->getBNpcType() : Common::BNpcType::Enemy;
|
Common::BNpcType type = pParent ? pParent->getBNpcType() : Common::BNpcType::Enemy;
|
||||||
|
|
||||||
pActor = pTeri->createBNpcFromLayoutId( m_layoutId, 1000, type );
|
pActor = pTeri->createBNpcFromLayoutIdNoPush( m_layoutId, 1000, type );
|
||||||
m_subActors[ name ] = pActor;
|
m_subActors[ name ] = pActor;
|
||||||
|
|
||||||
pActor->setInvincibilityType( Common::InvincibilityIgnoreDamage );
|
pActor->setInvincibilityType( Common::InvincibilityIgnoreDamage );
|
||||||
|
@ -189,7 +189,7 @@ namespace Sapphire::Encounter
|
||||||
auto& playerMgr = Common::Service< World::Manager::PlayerMgr >::ref();
|
auto& playerMgr = Common::Service< World::Manager::PlayerMgr >::ref();
|
||||||
for( const auto& player : pTeri->getPlayers() )
|
for( const auto& player : pTeri->getPlayers() )
|
||||||
{
|
{
|
||||||
pActor->spawn( player.second );
|
// pActor->spawn( player.second );
|
||||||
playerMgr.sendDebug( *player.second, fmt::format( "Spawned subactor {}", name ) );
|
playerMgr.sendDebug( *player.second, fmt::format( "Spawned subactor {}", name ) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -658,7 +658,7 @@ namespace Sapphire::Encounter
|
||||||
|
|
||||||
// todo: probably have this info in the timepoint data
|
// todo: probably have this info in the timepoint data
|
||||||
if( !pBNpc )
|
if( !pBNpc )
|
||||||
pBNpc = pTeri->createBNpcFromLayoutId( pSpawnData->m_layoutId, 100, Common::BNpcType::Enemy );
|
pBNpc = pTeri->createBNpcFromLayoutIdNoPush( pSpawnData->m_layoutId, 100, Common::BNpcType::Enemy );
|
||||||
|
|
||||||
if( pBNpc )
|
if( pBNpc )
|
||||||
{
|
{
|
||||||
|
@ -666,8 +666,7 @@ namespace Sapphire::Encounter
|
||||||
pBNpc->setFlag( pSpawnData->m_flags );
|
pBNpc->setFlag( pSpawnData->m_flags );
|
||||||
pBNpc->init();
|
pBNpc->init();
|
||||||
|
|
||||||
for( const auto& player : pTeri->getPlayers() )
|
pTeri->pushActor( pBNpc );
|
||||||
pBNpc->spawn( player.second );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -259,9 +259,11 @@ void Territory::pushActor( const Entity::GameObjectPtr& pActor )
|
||||||
{
|
{
|
||||||
auto pBNpc = pActor->getAsBNpc();
|
auto pBNpc = pActor->getAsBNpc();
|
||||||
|
|
||||||
if( m_pNaviProvider )
|
if( m_pNaviProvider && pBNpc->pathingActive() )
|
||||||
|
{
|
||||||
agentId = m_pNaviProvider->addAgent( *pBNpc );
|
agentId = m_pNaviProvider->addAgent( *pBNpc );
|
||||||
pBNpc->setAgentId( agentId );
|
pBNpc->setAgentId( agentId );
|
||||||
|
}
|
||||||
|
|
||||||
m_bNpcMap[ pBNpc->getId() ] = pBNpc;
|
m_bNpcMap[ pBNpc->getId() ] = pBNpc;
|
||||||
updateCellActivity( cx, cy, 1 );
|
updateCellActivity( cx, cy, 1 );
|
||||||
|
@ -854,6 +856,18 @@ Entity::BNpcPtr Territory::createBNpcFromLayoutId( uint32_t layoutId, uint32_t h
|
||||||
return pBNpc;
|
return pBNpc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Entity::BNpcPtr Territory::createBNpcFromLayoutIdNoPush( uint32_t layoutId, uint32_t hp, Common::BNpcType bnpcType, uint32_t triggerOwnerId )
|
||||||
|
{
|
||||||
|
auto infoPtr = m_bNpcBaseMap.find( layoutId );
|
||||||
|
if( infoPtr == m_bNpcBaseMap.end() )
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
auto pBNpc = std::make_shared< Entity::BNpc >( getNextActorId(), infoPtr->second, *this, hp, bnpcType );
|
||||||
|
pBNpc->init();
|
||||||
|
pBNpc->setTriggerOwnerId( triggerOwnerId );
|
||||||
|
return pBNpc;
|
||||||
|
}
|
||||||
|
|
||||||
Entity::BNpcPtr Territory::getActiveBNpcByEntityId( uint32_t entityId )
|
Entity::BNpcPtr Territory::getActiveBNpcByEntityId( uint32_t entityId )
|
||||||
{
|
{
|
||||||
auto it = m_bNpcMap.find( entityId );
|
auto it = m_bNpcMap.find( entityId );
|
||||||
|
|
|
@ -180,6 +180,7 @@ namespace Sapphire
|
||||||
void addEObj( Entity::EventObjectPtr object );
|
void addEObj( Entity::EventObjectPtr object );
|
||||||
|
|
||||||
Entity::BNpcPtr createBNpcFromLayoutId( uint32_t levelId, uint32_t hp, Common::BNpcType bnpcType, uint32_t triggerOwnerId = 0 );
|
Entity::BNpcPtr createBNpcFromLayoutId( uint32_t levelId, uint32_t hp, Common::BNpcType bnpcType, uint32_t triggerOwnerId = 0 );
|
||||||
|
Entity::BNpcPtr createBNpcFromLayoutIdNoPush( uint32_t levelId, uint32_t hp, Common::BNpcType bnpcType, uint32_t triggerOwnerId = 0 );
|
||||||
|
|
||||||
Entity::BNpcPtr getActiveBNpcByEntityId( uint32_t entityId );
|
Entity::BNpcPtr getActiveBNpcByEntityId( uint32_t entityId );
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue