diff --git a/src/common/Common.h b/src/common/Common.h index 72adb008..72e14d21 100644 --- a/src/common/Common.h +++ b/src/common/Common.h @@ -1381,6 +1381,7 @@ namespace Sapphire::Common enum PlayerCondition : uint8_t { + None1 = 0, HideUILockChar = 1, // as the name suggests, hides the ui and logs the char... InCombat = 2, // in Combat, locks gearchange/return/teleport Casting = 3, diff --git a/src/scripts/quest/subquest/mordhona/GaiUsc605.cpp b/src/scripts/quest/subquest/mordhona/GaiUsc605.cpp index 63253786..dcd81fb6 100644 --- a/src/scripts/quest/subquest/mordhona/GaiUsc605.cpp +++ b/src/scripts/quest/subquest/mordhona/GaiUsc605.cpp @@ -396,7 +396,7 @@ private: { eventMgr().sendEventNotice( player, getId(), 3, 0 ); quest.setSeq( Seq5 ); - playerMgr().onMountUpdate( player, Mount0 ); + player.setMount( Mount0 ); } ////////////////////////////////////////////////////////////////////// @@ -490,7 +490,7 @@ private: void Scene00017Return( World::Quest& quest, Entity::Player& player, const Event::SceneResult& result ) { - playerMgr().onMountUpdate( player, Mount0 ); + player.setMount( Mount0 ); } ////////////////////////////////////////////////////////////////////// @@ -562,7 +562,7 @@ private: void Scene00023Return( World::Quest& quest, Entity::Player& player, const Event::SceneResult& result ) { - playerMgr().onMountUpdate( player, Mount0 ); + player.setMount( Mount0 ); } ////////////////////////////////////////////////////////////////////// @@ -611,7 +611,7 @@ private: { eventMgr().sendEventNotice( player, getId(), 6, 0 ); quest.setSeq( Seq8 ); - playerMgr().onMountUpdate( player, 0 ); + player.setMount( Mount0 ); } } @@ -646,7 +646,7 @@ private: void Scene00030Return( World::Quest& quest, Entity::Player& player, const Event::SceneResult& result ) { - playerMgr().onMountUpdate( player, Mount0 ); + player.setMount( Mount0 ); } ////////////////////////////////////////////////////////////////////// diff --git a/src/world/Action/Action.cpp b/src/world/Action/Action.cpp index a9a31ffb..d78ebe2e 100644 --- a/src/world/Action/Action.cpp +++ b/src/world/Action/Action.cpp @@ -320,7 +320,6 @@ void Action::Action::start() if( player ) { player->setCondition( PlayerCondition::Casting ); - playerMgr().onConditionChanged( *player, true ); } } @@ -374,7 +373,7 @@ void Action::Action::interrupt() // reset state flag //player->unsetStateFlag( PlayerStateFlag::Occupied1 ); pPlayer->setLastActionTick( 0 ); - playerMgr().removeCondition( *pPlayer, PlayerCondition::Casting ); + pPlayer->removeCondition( PlayerCondition::Casting ); } if( hasCastTime() ) @@ -420,7 +419,7 @@ void Action::Action::execute() if( auto pPlayer = m_pSource->getAsPlayer(); pPlayer ) { pPlayer->setLastActionTick( 0 ); - playerMgr().removeCondition( *pPlayer, PlayerCondition::Casting ); + pPlayer->removeCondition( PlayerCondition::Casting ); } } diff --git a/src/world/Action/EffectResult.cpp b/src/world/Action/EffectResult.cpp index c3643a54..8ef9d68f 100644 --- a/src/world/Action/EffectResult.cpp +++ b/src/world/Action/EffectResult.cpp @@ -114,7 +114,7 @@ void EffectResult::execute() case Common::ActionEffectType::CALC_RESULT_TYPE_MOUNT: { auto pPlayer = m_target->getAsPlayer(); - Common::Service< World::Manager::PlayerMgr >::ref().onMountUpdate( *pPlayer, m_result.Value ); + pPlayer->setMount( m_result.Value ); break; } diff --git a/src/world/Action/EventAction.cpp b/src/world/Action/EventAction.cpp index 57985df5..12472525 100644 --- a/src/world/Action/EventAction.cpp +++ b/src/world/Action/EventAction.cpp @@ -62,7 +62,7 @@ void Action::EventAction::start() server().queueForPlayers( m_pSource->getInRangePlayerIds( true ), control ); if( pPlayer->hasCondition( PlayerCondition::InNpcEvent ) ) - Service< World::Manager::PlayerMgr >::ref().removeCondition( *pPlayer, PlayerCondition::InNpcEvent ); + pPlayer->removeCondition( PlayerCondition::InNpcEvent ); } else server().queueForPlayers( m_pSource->getInRangePlayerIds(), control ); diff --git a/src/world/Action/MountAction.cpp b/src/world/Action/MountAction.cpp index 2ef1d7a9..f8150a27 100644 --- a/src/world/Action/MountAction.cpp +++ b/src/world/Action/MountAction.cpp @@ -58,7 +58,7 @@ void MountAction::start() data.TargetPos[ 2 ] = Common::Util::floatToUInt16( pos.z ); data.Dir = m_pSource->getRot(); server().queueForPlayers( m_pSource->getInRangePlayerIds( true ), castPacket ); - playerMgr().setCondition( *player, Common::PlayerCondition::Casting ); + player->setCondition( Common::PlayerCondition::Casting ); auto actionStartPkt = makeActorControlSelf( m_pSource->getId(), ActorControlType::ActionStart, 1, getId(), m_recastTimeMs / 10 ); server().queueForPlayer( m_pSource->getAsPlayer()->getCharacterId(), actionStartPkt ); @@ -68,7 +68,7 @@ void MountAction::execute() { assert( m_pSource ); - Common::Service< World::Manager::PlayerMgr >::ref().removeCondition( *m_pSource->getAsPlayer(), Common::PlayerCondition::Casting ); + m_pSource->getAsPlayer()->removeCondition( Common::PlayerCondition::Casting ); m_effectBuilder->mount( m_pSource, m_mountId ); m_effectBuilder->buildAndSendPackets( { m_pSource } ); } \ No newline at end of file diff --git a/src/world/Actor/BNpc.cpp b/src/world/Actor/BNpc.cpp index 90f89489..106c5002 100644 --- a/src/world/Actor/BNpc.cpp +++ b/src/world/Actor/BNpc.cpp @@ -18,6 +18,8 @@ #include "Network/PacketWrappers/ActorControlTargetPacket.h" #include "Network/PacketWrappers/NpcSpawnPacket.h" #include "Network/PacketWrappers/MoveActorPacket.h" +#include "Network/Util/PlayerUtil.h" + #include "Navi/NaviProvider.h" #include "Math/CalcStats.h" @@ -540,7 +542,7 @@ void Sapphire::Entity::BNpc::hateListUpdate( const Sapphire::Entity::CharaPtr& p if( pChara->isPlayer() ) { auto pPlayer = pChara->getAsPlayer(); - Service< World::Manager::PlayerMgr >::ref().onHateListChanged( *pPlayer ); + Network::Util::Player::sendHateList( *pPlayer ); } } } diff --git a/src/world/Actor/Player.cpp b/src/world/Actor/Player.cpp index 2161b2f2..66a8cd9f 100644 --- a/src/world/Actor/Player.cpp +++ b/src/world/Actor/Player.cpp @@ -21,6 +21,7 @@ #include "Manager/MapMgr.h" #include "Manager/MgrUtil.h" #include "Manager/ActionMgr.h" +#include "Manager/AchievementMgr.h" #include "Territory/InstanceContent.h" @@ -716,7 +717,7 @@ void Player::setClassJob( Common::ClassJob classJob ) m_tp = 0; Network::Util::Player::sendStatusUpdate( *this ); - server().queueForPlayers( getInRangePlayerIds( true ), makeActorControl( getId(), ClassJobChange, 0x04 ) ); + Network::Util::Player::sendActorControl( getInRangePlayerIds( true ), *this, ClassJobChange, 4 ); Network::Util::Player::sendHudParam( *this ); Service< World::Manager::MapMgr >::ref().updateQuests( *this ); } @@ -738,12 +739,10 @@ void Player::setLevelForClass( uint8_t level, Common::ClassJob classjob ) m_classArray[ classJobIndex ] = level; - Service< World::Manager::PlayerMgr >::ref().onSetLevelForClass( *this, classjob ); -} + Network::Util::Player::sendActorControlSelf( *this, ClassJobUpdate, static_cast< uint8_t >( classjob ), getLevelForClass( classjob ) ); -void Player::sendModel() -{ - Service< World::Manager::PlayerMgr >::ref().onGearChanged( *this ); + auto& achvMgr = Common::Service< World::Manager::AchievementMgr >::ref(); + achvMgr.progressAchievementByType< Common::Achievement::Type::Classjob >( *this, static_cast< uint32_t >( classjob ) ); } uint32_t Player::getModelForSlot( Common::GearModelSlot slot ) @@ -877,6 +876,22 @@ void Player::setCondition( Common::PlayerCondition flag ) Util::valueToFlagByteIndexValue( iFlag, value, index ); m_condition[ index ] |= value; + Network::Util::Player::sendCondition( *this ); +} + +void Player::setConditions( const std::vector< Common::PlayerCondition >& flags ) +{ + for( auto flag : flags ) + { + auto iFlag = static_cast< int32_t >( flag ); + + uint16_t index; + uint8_t value; + Util::valueToFlagByteIndexValue( iFlag, value, index ); + + m_condition[ index ] |= value; + } + Network::Util::Player::sendCondition( *this ); } void Player::removeCondition( Common::PlayerCondition flag ) @@ -891,6 +906,7 @@ void Player::removeCondition( Common::PlayerCondition flag ) Util::valueToFlagByteIndexValue( iFlag, value, index ); m_condition[ index ] ^= value; + Network::Util::Player::sendCondition( *this ); } void Player::update( uint64_t tickCount ) @@ -919,10 +935,7 @@ void Player::freePlayerSpawnId( uint32_t actorId ) if( spawnId == m_actorSpawnIndexAllocator.getAllocFailId() ) return; - auto freeActorSpawnPacket = makeZonePacket< FFXIVIpcActorFreeSpawn >( getId() ); - freeActorSpawnPacket->data().actorId = actorId; - freeActorSpawnPacket->data().spawnId = spawnId; - server().queueForPlayer( getCharacterId(), freeActorSpawnPacket ); + Network::Util::Player::sendDeletePlayer( *this, actorId, spawnId ); } Player::AetheryteList& Player::getAetheryteArray() @@ -1090,7 +1103,7 @@ void Player::hateListAdd( const BNpc& bnpc ) uint8_t hateId = m_freeHateSlotQueue.front(); m_freeHateSlotQueue.pop(); m_actorIdTohateSlotMap[ bnpc.getId() ] = hateId; - Service< World::Manager::PlayerMgr >::ref().onHateListChanged( *this ); + Network::Util::Player::sendHateList( *this ); } } @@ -1105,8 +1118,7 @@ void Player::hateListRemove( const BNpc& bnpc ) uint8_t hateSlot = it->second; m_freeHateSlotQueue.push( hateSlot ); m_actorIdTohateSlotMap.erase( it ); - Service< World::Manager::PlayerMgr >::ref().onHateListChanged( *this ); - + Network::Util::Player::sendHateList( *this ); return; } } @@ -1126,14 +1138,14 @@ const std::map< uint32_t, uint8_t >& Player::getActorIdToHateSlotMap() void Player::onMobAggro( const BNpc& bnpc ) { hateListAdd( bnpc ); - server().queueForPlayer( getCharacterId(), makeActorControl( getId(), SetBattle, 1, 0, 0 ) ); + Network::Util::Player::sendActorControl( *this, SetBattle, 1 ); } void Player::onMobDeaggro( const BNpc& bnpc ) { hateListRemove( bnpc ); if( m_actorIdTohateSlotMap.empty() ) - server().queueForPlayer( getCharacterId(), makeActorControl( getId(), SetBattle, 0, 0, 0 ) ); + Network::Util::Player::sendActorControl( *this, SetBattle, 0 ); } bool Player::isLogin() const @@ -1175,7 +1187,7 @@ void Player::setTitle( uint16_t titleId ) return; m_activeTitle = titleId; - server().queueForPlayers( getInRangePlayerIds( true ), makeActorControl( getId(), SetTitle, titleId ) ); + Network::Util::Player::sendActorControl( getInRangePlayerIds( true ), *this, SetTitle, titleId ); } const Player::AchievementData& Player::getAchievementData() const @@ -1227,11 +1239,20 @@ uint8_t Player::getConfigFlags() const void Player::setMount( uint32_t mountId ) { m_mount = mountId; + Network::Util::Player::sendMount( *this ); } void Player::setCompanion( uint8_t id ) { + auto& exdData = Common::Service< Data::ExdData >::ref(); + + auto companion = exdData.getRow< Excel::Companion >( id ); + if( !companion ) + return; + m_companionId = id; + + Network::Util::Player::sendActorControl( getInRangePlayerIds( true ), *this, ToggleCompanion, id ); } uint8_t Player::getCurrentCompanion() const @@ -1448,8 +1469,7 @@ void Player::dyeItemFromDyeingInfo() uint32_t dyeBagContainer = m_dyeingInfo.dyeBagContainer; uint32_t dyeBagSlot = m_dyeingInfo.dyeBagSlot; - Service< World::Manager::PlayerMgr >::ref().onConditionChanged( *this, true ); // Retail sends all 0s to unlock player after a dye? Possibly not setting a flag when the action is started in the backend..? - + setCondition( Common::PlayerCondition::None1 ); auto itemToDye = getItemAt( itemToDyeContainer, itemToDyeSlot ); auto dyeToUse = getItemAt( dyeBagContainer, dyeBagSlot ); @@ -1489,7 +1509,7 @@ void Player::glamourItemFromGlamouringInfo() uint32_t glamourBagSlot = m_glamouringInfo.glamourBagSlot; bool shouldGlamour = m_glamouringInfo.shouldGlamour; - playerMgr.onConditionChanged( *this, true ); + Network::Util::Player::sendCondition( *this ); auto itemToGlamour = getItemAt( itemToGlamourContainer, itemToGlamourSlot ); auto glamourToUse = getItemAt( glamourBagContainer, glamourBagSlot ); @@ -1539,9 +1559,7 @@ void Player::freeObjSpawnIndexForActorId( uint32_t actorId ) if( spawnId == m_objSpawnIndexAllocator.getAllocFailId() ) return; - auto freeObjectSpawnPacket = makeZonePacket< FFXIVIpcDeleteObject >( getId() ); - freeObjectSpawnPacket->data().Index = spawnId; - server().queueForPlayer( getCharacterId(), freeObjectSpawnPacket ); + Network::Util::Player::sendDeleteObject( *this, spawnId ); } bool Player::isObjSpawnIndexValid( uint8_t index ) @@ -1686,12 +1704,14 @@ float Player::getRecastGroup( uint8_t index ) const return m_recast[ index ]; } -void Player::sendRecastGroups() +const std::array< float, 80 >& Player::getRecastGroups() const { - auto recastGroupPaket = makeZonePacket< FFXIVIpcRecastGroup >( getId() ); - memcpy( &recastGroupPaket->data().Recast, &m_recast, sizeof( m_recast ) ); - memcpy( &recastGroupPaket->data().RecastMax, &m_recastMax, sizeof( m_recastMax ) ); - server().queueForPlayer( getCharacterId(), recastGroupPaket ); + return m_recast; +} + +const std::array< float, 80 >& Player::getRecastGroupsMax() const +{ + return m_recastMax; } void Player::resetRecastGroups() @@ -1701,7 +1721,7 @@ void Player::resetRecastGroups() m_recast[ i ] = 0.0f; m_recastMax[ i ] = 0.0f; } - sendRecastGroups(); + Network::Util::Player::sendRecastGroups( *this ); } bool Player::checkAction() @@ -1800,8 +1820,7 @@ void Player::setFalling( bool state, const Common::FFXIVARR_POSITION3& pos, bool // no mercy on hated players takeDamage( damage ); } - - server().queueForPlayers( getInRangePlayerIds( true ), makeActorControl( getId(), SetFallDamage, damage ) ); + Network::Util::Player::sendActorControl( getInRangePlayerIds( true ), *this, SetFallDamage, damage ); } } } diff --git a/src/world/Actor/Player.h b/src/world/Actor/Player.h index a7b5fdbc..3c307f70 100644 --- a/src/world/Actor/Player.h +++ b/src/world/Actor/Player.h @@ -155,9 +155,6 @@ namespace Sapphire::Entity /*! get player ilvl */ uint16_t getItemLevel() const; - /*! send player ilvl */ - void sendItemLevel(); - /*! get the current main hand model */ uint64_t getModelMainWeapon() const; @@ -492,8 +489,8 @@ namespace Sapphire::Entity void setRecastGroup( uint8_t index, float time ); float getRecastGroup( uint8_t index ) const; - - void sendRecastGroups(); + const std::array< float, 80 >& Player::getRecastGroups() const; + const std::array< float, 80 >& Player::getRecastGroupsMax() const; void resetRecastGroups(); @@ -526,7 +523,7 @@ namespace Sapphire::Entity void setCondition( Common::PlayerCondition flag ); /* set a specified state flag */ - void setConditions( std::vector< Common::PlayerCondition > flags ); + void setConditions( const std::vector< Common::PlayerCondition >& flags ); /* check if a specified flag is set */ bool hasCondition( Common::PlayerCondition flag ) const; @@ -571,9 +568,6 @@ namespace Sapphire::Entity // Player Network Handling ////////////////////////////////////////////////////////////////////////////////////////////////////// - /*! send current models ( equipment ) */ - void sendModel(); - /*! send the entire inventory sequence */ void sendInventory(); @@ -833,8 +827,8 @@ namespace Sapphire::Entity World::Action::ActionPtr m_pQueuedAction; uint64_t m_lastActionTick; - float m_recast[80]{}; - float m_recastMax[80]{}; + std::array< float, 80 > m_recast{}; + std::array< float, 80 > m_recastMax{}; InventoryMap m_storageMap; diff --git a/src/world/Actor/PlayerInventory.cpp b/src/world/Actor/PlayerInventory.cpp index b8a848f1..ff6ff745 100644 --- a/src/world/Actor/PlayerInventory.cpp +++ b/src/world/Actor/PlayerInventory.cpp @@ -103,11 +103,6 @@ void Sapphire::Entity::Player::initInventory() calculateItemLevel(); } -void Sapphire::Entity::Player::sendItemLevel() -{ - Service< World::Manager::PlayerMgr >::ref().sendItemLevel( *this ); -} - void Sapphire::Entity::Player::equipWeapon( const Item& item ) { auto& exdData = Common::Service< Sapphire::Data::ExdData >::ref(); @@ -230,8 +225,8 @@ void Sapphire::Entity::Player::equipItem( Common::GearSetSlot equipSlotId, Item& calculateItemLevel(); if( sendUpdate ) { - sendModel(); - sendItemLevel(); + Network::Util::Player::sendEquip( *this ); + Network::Util::Player::sendActorControl( *this, SetItemLevel, getItemLevel() ); Network::Util::Player::sendBaseParams( *this ); Network::Util::Player::sendHudParam( *this ); } @@ -252,8 +247,8 @@ void Sapphire::Entity::Player::unequipItem( Common::GearSetSlot equipSlotId, Ite if( sendUpdate ) { - sendModel(); - sendItemLevel(); + Network::Util::Player::sendEquip( *this ); + Network::Util::Player::sendActorControl( *this, SetItemLevel, getItemLevel() ); Network::Util::Player::sendBaseParams( *this ); Network::Util::Player::sendHudParam( *this ); } diff --git a/src/world/Manager/DebugCommandMgr.cpp b/src/world/Manager/DebugCommandMgr.cpp index c3165361..44c7a2bc 100644 --- a/src/world/Manager/DebugCommandMgr.cpp +++ b/src/world/Manager/DebugCommandMgr.cpp @@ -260,8 +260,8 @@ void DebugCommandMgr::set( char* data, Entity::Player& player, std::shared_ptr< int32_t id; sscanf( params.c_str(), "%d", &id ); - Common::Service< World::Manager::PlayerMgr >::ref().onMountUpdate( player, 0 ); - Common::Service< World::Manager::PlayerMgr >::ref().onMountUpdate( player, id ); + player.setMount( 0 ); + player.setMount( id ); } else if( subCommand == "weatheroverride" || subCommand == "wo" ) { diff --git a/src/world/Manager/EventMgr.cpp b/src/world/Manager/EventMgr.cpp index 81ddefc4..e2b87ef4 100644 --- a/src/world/Manager/EventMgr.cpp +++ b/src/world/Manager/EventMgr.cpp @@ -551,12 +551,12 @@ void EventMgr::eventFinish( Sapphire::Entity::Player& player, uint32_t eventId, } if( player.hasCondition( Common::PlayerCondition::WatchingCutscene ) ) - Common::Service< World::Manager::PlayerMgr >::ref().removeCondition( player, Common::PlayerCondition::WatchingCutscene ); + player.removeCondition( Common::PlayerCondition::WatchingCutscene ); player.removeEvent( pEvent->getId() ); if( freePlayer == 1 ) - Common::Service< World::Manager::PlayerMgr >::ref().removeCondition( player, Common::PlayerCondition::InNpcEvent ); + player.removeCondition( Common::PlayerCondition::InNpcEvent ); } void EventMgr::eventStart( Entity::Player& player, uint64_t actorId, uint32_t eventId, Event::EventHandler::EventType eventType, uint8_t eventParam1, @@ -567,7 +567,7 @@ void EventMgr::eventStart( Entity::Player& player, uint64_t actorId, uint32_t ev newEvent->setEventFinishCallback( std::move( callback ) ); player.addEvent( newEvent ); - Common::Service< World::Manager::PlayerMgr >::ref().setCondition( player, Common::PlayerCondition::InNpcEvent ); + player.setCondition( Common::PlayerCondition::InNpcEvent ); server.queueForPlayer( player.getCharacterId(), std::make_shared< EventStartPacket >( player.getId(), actorId, eventId, eventType, eventParam1, eventParam2 ) ); @@ -838,7 +838,7 @@ Sapphire::Event::EventHandlerPtr EventMgr::bootstrapSceneEvent( Entity::Player& } if( flags & CONDITION_CUTSCENE ) - Common::Service< World::Manager::PlayerMgr >::ref().setCondition( player, Common::PlayerCondition::WatchingCutscene ); + player.setCondition( Common::PlayerCondition::WatchingCutscene ); return pEvent; } diff --git a/src/world/Manager/PlayerMgr.cpp b/src/world/Manager/PlayerMgr.cpp index ef6ba585..b60c0ffb 100644 --- a/src/world/Manager/PlayerMgr.cpp +++ b/src/world/Manager/PlayerMgr.cpp @@ -25,7 +25,6 @@ #include #include #include -#include #include #include #include @@ -215,16 +214,6 @@ Sapphire::Entity::PlayerPtr PlayerMgr::syncPlayer( uint64_t characterId ) return pPlayer; } -void PlayerMgr::onConditionChanged( Entity::Player& player, bool updateInRange ) -{ - - server().queueForPlayer( player.getCharacterId(), std::make_shared< ConditionPacket >( player ) ); - - if( updateInRange ) - server().queueForPlayers( player.getInRangePlayerIds( true ), - makeActorControl( player.getId(), SetStatusIcon, static_cast< uint8_t >( player.getOnlineStatus() ) ) ); -} - void PlayerMgr::onAchievementListChanged( Entity::Player& player ) { auto achvData = player.getAchievementData(); @@ -260,11 +249,6 @@ void PlayerMgr::onRestingTick( Entity::Player& player ) server().queueForPlayers( player.getInRangePlayerIds( true ), std::make_shared< RestingPacket >( player ) ); } -void PlayerMgr::sendItemLevel( Entity::Player& player ) -{ - server().queueForPlayer( player.getCharacterId(), makeActorControl( player.getId(), SetItemLevel, player.getItemLevel(), 0 ) ); -} - void PlayerMgr::onLevelUp( Entity::Player& player ) { player.calculateStats(); @@ -273,9 +257,8 @@ void PlayerMgr::onLevelUp( Entity::Player& player ) auto inRangePlayerIds = player.getInRangePlayerIds( true ); - server().queueForPlayers( inRangePlayerIds, makeHudParam( player ) ); - server().queueForPlayers( inRangePlayerIds, makeActorControl( player.getId(), LevelUpEffect, static_cast< uint8_t >( player.getClass() ), - player.getLevel(), player.getLevel() - 1 ) ); + Network::Util::Player::sendActorControl( inRangePlayerIds, player, LevelUpEffect, static_cast< uint8_t >( player.getClass() ), + player.getLevel(), player.getLevel() - 1 ); Network::Util::Player::sendStatusUpdate( player ); @@ -283,17 +266,6 @@ void PlayerMgr::onLevelUp( Entity::Player& player ) achvMgr.progressAchievementByType< Common::Achievement::Type::Classjob >( player, static_cast< uint32_t >( player.getClass() ) ); } -void PlayerMgr::onSetLevelForClass( Entity::Player& player, Common::ClassJob classJob ) -{ - auto& achvMgr = Common::Service< World::Manager::AchievementMgr >::ref(); - - server().queueForPlayer( player.getCharacterId(), makeActorControlSelf( player.getId(), Network::ActorControl::ClassJobUpdate, - static_cast< uint8_t >( classJob ), player.getLevelForClass( classJob ) ) ); - - achvMgr.progressAchievementByType< Common::Achievement::Type::Classjob >( player, static_cast< uint32_t >( classJob ) ); -} - - void PlayerMgr::onGainExp( Entity::Player& player, uint32_t exp ) { @@ -312,43 +284,6 @@ void PlayerMgr::onUnlockOrchestrion( Entity::Player& player, uint8_t songId, uin server().queueForPlayer( player.getCharacterId(), makeActorControlSelf( player.getId(), ToggleOrchestrionUnlock, songId, 1, itemId ) ); } -void PlayerMgr::onGearChanged( Entity::Player& player ) -{ - server().queueForPlayers( player.getInRangePlayerIds( true ), std::make_shared< ModelEquipPacket >( player ) ); -} - -void PlayerMgr::onCompanionUpdate( Entity::Player& player, uint8_t companionId ) -{ - auto& exdData = Common::Service< Data::ExdData >::ref(); - - auto companion = exdData.getRow< Excel::Companion >( companionId ); - if( !companion ) - return; - - player.setCompanion( companionId ); - Network::Util::Player::sendActorControl( player.getInRangePlayerIds( true ), player, ToggleCompanion, companionId ); -} - -void PlayerMgr::onMountUpdate( Entity::Player& player, uint32_t mountId ) -{ - - auto inRangePlayerIds = player.getInRangePlayerIds( true ); - if( mountId != 0 ) - { - Network::Util::Player::sendActorControl( inRangePlayerIds, player, SetStatus, static_cast< uint8_t >( Common::ActorStatus::Mounted ) ); - Network::Util::Player::sendActorControlSelf( inRangePlayerIds, player, 0x39e, 12 ); - } - else - { - Network::Util::Player::sendActorControl( inRangePlayerIds, player, SetStatus, static_cast< uint8_t >( Common::ActorStatus::Idle ) ); - Network::Util::Player::sendActorControlSelf( inRangePlayerIds, player, Dismount, 1 ); - } - - auto mountPacket = makeZonePacket< FFXIVIpcMount >( player.getId() ); - mountPacket->data().id = mountId; - server().queueForPlayers( inRangePlayerIds, mountPacket ); -} - void PlayerMgr::onMobKill( Entity::Player& player, Entity::BNpc& bnpc ) { auto& scriptMgr = Common::Service< Scripting::ScriptMgr >::ref(); @@ -360,46 +295,6 @@ void PlayerMgr::onMobKill( Entity::Player& player, Entity::BNpc& bnpc ) } } -void PlayerMgr::onHateListChanged( Entity::Player& player ) -{ - auto& teriMgr = Common::Service< World::Manager::TerritoryMgr >::ref(); - - auto hateListPacket = makeZonePacket< FFXIVIpcHateList >( player.getId() ); - auto hateRankPacket = makeZonePacket< FFXIVIpcHaterList >( player.getId() ); - - auto actorIdToHateSlotMap = player.getActorIdToHateSlotMap(); - - hateListPacket->data().Count = static_cast< uint8_t >( actorIdToHateSlotMap.size() ); - - hateRankPacket->data().Count = static_cast< uint8_t >( actorIdToHateSlotMap.size() ); - auto it = actorIdToHateSlotMap.begin(); - - auto zone = teriMgr.getTerritoryByGuId( player.getTerritoryId() ); - if( !zone ) - return; - - for( int32_t i = 0; it != actorIdToHateSlotMap.end(); ++it, ++i ) - { - auto pBNpc = zone->getActiveBNpcByEntityId( it->first ); - if( !pBNpc ) - continue; - - auto hateValue = pBNpc->hateListGetValue( player.getAsChara() ); - if( hateValue == 0 ) - continue; - - auto hatePercent = ( hateValue / static_cast< float >( pBNpc->hateListGetHighestValue() ) ) * 100.f; - - hateListPacket->data().List[ i ].Id = player.getId(); - hateListPacket->data().List[ i ].Value = hateValue; - - hateRankPacket->data().List[ i ].Id = it->first; - hateRankPacket->data().List[ i ].Rate = static_cast< uint8_t >( hatePercent ); - } - - server().queueForPlayer( player.getCharacterId(), { hateListPacket, hateRankPacket } ); -} - void PlayerMgr::sendLoginMessage( Entity::Player& player ) { auto motd = server().getConfig().motd; @@ -462,9 +357,9 @@ void PlayerMgr::onMoveZone( Sapphire::Entity::Player& player ) if( player.isLogin() ) server().queueForPlayer( player.getCharacterId(), makePlayerSetup( player ) ); - player.sendRecastGroups(); + Network::Util::Player::sendRecastGroups( player ); Network::Util::Player::sendBaseParams( player ); - sendItemLevel( player ); + Network::Util::Player::sendActorControl( player, SetItemLevel, player.getItemLevel() ); if( player.isLogin() ) { auto classInfo = makeZonePacket< FFXIVIpcChangeClass >( player.getId() ); @@ -561,25 +456,6 @@ void PlayerMgr::onUpdate( Entity::Player& player, uint64_t tickCount ) } } -void PlayerMgr::setCondition( Sapphire::Entity::Player& player, Common::PlayerCondition flag ) -{ - auto prevOnlineStatus = player.getOnlineStatus(); - - player.setCondition( flag ); - - auto newOnlineStatus = player.getOnlineStatus(); - onConditionChanged( player, prevOnlineStatus != newOnlineStatus ); -} - -void PlayerMgr::removeCondition( Sapphire::Entity::Player& player, Common::PlayerCondition flag ) -{ - auto prevOnlineStatus = player.getOnlineStatus(); - - player.removeCondition( flag ); - - auto newOnlineStatus = player.getOnlineStatus(); - onConditionChanged( player, prevOnlineStatus != newOnlineStatus ); -} ////////// Helper /////////// diff --git a/src/world/Manager/PlayerMgr.h b/src/world/Manager/PlayerMgr.h index d569a7cb..fd856cf0 100644 --- a/src/world/Manager/PlayerMgr.h +++ b/src/world/Manager/PlayerMgr.h @@ -27,24 +27,14 @@ namespace Sapphire::World::Manager void onRestingTick( Sapphire::Entity::Player& player ); - void sendItemLevel( Sapphire::Entity::Player& player ); - void onLevelUp( Sapphire::Entity::Player& player ); - void onSetLevelForClass( Sapphire::Entity::Player& player, Common::ClassJob classJob ); - void onGainExp( Sapphire::Entity::Player& player, uint32_t exp ); void onUnlockOrchestrion( Sapphire::Entity::Player& player, uint8_t songId, uint32_t itemId ); - void onCompanionUpdate( Entity::Player& player, uint8_t companionId ); - - void onMountUpdate( Sapphire::Entity::Player& player, uint32_t mountId ); - void onMobKill( Sapphire::Entity::Player& player, Sapphire::Entity::BNpc& bnpc ); - void onHateListChanged( Sapphire::Entity::Player& player ); - void sendLoginMessage( Sapphire::Entity::Player& player ); void onLogin( Sapphire::Entity::Player& player ); @@ -53,14 +43,8 @@ namespace Sapphire::World::Manager void onMoveZone( Sapphire::Entity::Player& player ); void onUpdate( Sapphire::Entity::Player& player, uint64_t tickCount ); - - void onConditionChanged( Sapphire::Entity::Player& player, bool updateInRange ); void onAchievementListChanged( Sapphire::Entity::Player& player ); void onAchievementProgressChanged( Sapphire::Entity::Player& player, uint32_t achievementId ); - void onGearChanged( Sapphire::Entity::Player& player ); - - void setCondition( Sapphire::Entity::Player& player, Common::PlayerCondition flag ); - void removeCondition( Sapphire::Entity::Player& player, Common::PlayerCondition flag ); //////////// Helpers diff --git a/src/world/Manager/WarpMgr.cpp b/src/world/Manager/WarpMgr.cpp index fbe9b168..2f3e1cac 100644 --- a/src/world/Manager/WarpMgr.cpp +++ b/src/world/Manager/WarpMgr.cpp @@ -136,7 +136,7 @@ void WarpMgr::finishWarp( Entity::Player& player ) server().queueForPlayer( player.getCharacterId(), zoneInPacket ); server().queueForPlayers( player.getInRangePlayerIds( true ), setStatusPacket ); - playerMgr.removeCondition( player, PlayerCondition::BetweenAreas ); + player.removeCondition( PlayerCondition::BetweenAreas ); Common::Service< MapMgr >::ref().updateAll( player ); } diff --git a/src/world/Network/Handlers/PacketCommandHandler.cpp b/src/world/Network/Handlers/PacketCommandHandler.cpp index 192c5af7..54ce1bc3 100644 --- a/src/world/Network/Handlers/PacketCommandHandler.cpp +++ b/src/world/Network/Handlers/PacketCommandHandler.cpp @@ -452,17 +452,17 @@ void Sapphire::Network::GameConnection::commandHandler( const Packets::FFXIVARR_ } case PacketCommand::CANCEL_MOUNT: { - playerMgr().onMountUpdate( player, 0 ); + player.setMount( 0 ); break; } case PacketCommand::COMPANION: { - playerMgr().onCompanionUpdate( player, static_cast< uint8_t >( data.Arg0 ) ); + player.setCompanion( static_cast< uint8_t >( data.Arg0 ) ); break; } case PacketCommand::COMPANION_CANCEL: { - playerMgr().onCompanionUpdate( player, 0 ); + player.setCompanion( 0 ); break; } case PacketCommand::REQUEST_STATUS_RESET: // Remove status (clicking it off) diff --git a/src/world/Network/Util/PlayerUtil.cpp b/src/world/Network/Util/PlayerUtil.cpp index 2ec305cd..8565e2e5 100644 --- a/src/world/Network/Util/PlayerUtil.cpp +++ b/src/world/Network/Util/PlayerUtil.cpp @@ -3,6 +3,9 @@ #include #include +#include + +#include #include #include @@ -10,6 +13,8 @@ #include #include #include +#include +#include using namespace Sapphire; using namespace Sapphire::World::Manager; @@ -157,6 +162,99 @@ void Util::Player::sendGrandCompany( Entity::Player& player ) gcAffPacket->data().MaelstromRank = player.getGcRankArray()[ 0 ]; gcAffPacket->data().TwinAdderRank = player.getGcRankArray()[ 1 ]; gcAffPacket->data().ImmortalFlamesRank = player.getGcRankArray()[ 2 ]; - server().queueForPlayer( player.getCharacterId(), gcAffPacket ); +} + +void Util::Player::sendDeletePlayer( Entity::Player& player, uint32_t actorId, uint8_t spawnIndex ) +{ + auto freeActorSpawnPacket = makeZonePacket< FFXIVIpcActorFreeSpawn >( player.getId() ); + freeActorSpawnPacket->data().actorId = actorId; + freeActorSpawnPacket->data().spawnId = spawnIndex; + server().queueForPlayer( player.getCharacterId(), freeActorSpawnPacket ); +} + +void Util::Player::sendDeleteObject( Entity::Player& player, uint8_t spawnIndex ) +{ + auto freeObjectSpawnPacket = makeZonePacket< FFXIVIpcDeleteObject >( player.getId() ); + freeObjectSpawnPacket->data().Index = spawnIndex; + server().queueForPlayer( player.getCharacterId(), freeObjectSpawnPacket ); +} + +void Util::Player::sendHateList( Entity::Player& player ) +{ + auto& teriMgr = Common::Service< World::Manager::TerritoryMgr >::ref(); + + auto hateListPacket = makeZonePacket< FFXIVIpcHateList >( player.getId() ); + auto hateRankPacket = makeZonePacket< FFXIVIpcHaterList >( player.getId() ); + + auto actorIdToHateSlotMap = player.getActorIdToHateSlotMap(); + + hateListPacket->data().Count = static_cast< uint8_t >( actorIdToHateSlotMap.size() ); + + hateRankPacket->data().Count = static_cast< uint8_t >( actorIdToHateSlotMap.size() ); + auto it = actorIdToHateSlotMap.begin(); + + auto zone = teriMgr.getTerritoryByGuId( player.getTerritoryId() ); + if( !zone ) + return; + + for( int32_t i = 0; it != actorIdToHateSlotMap.end(); ++it, ++i ) + { + auto pBNpc = zone->getActiveBNpcByEntityId( it->first ); + if( !pBNpc ) + continue; + + auto hateValue = pBNpc->hateListGetValue( player.getAsChara() ); + if( hateValue == 0 ) + continue; + + auto hatePercent = ( hateValue / static_cast< float >( pBNpc->hateListGetHighestValue() ) ) * 100.f; + + hateListPacket->data().List[ i ].Id = player.getId(); + hateListPacket->data().List[ i ].Value = hateValue; + + hateRankPacket->data().List[ i ].Id = it->first; + hateRankPacket->data().List[ i ].Rate = static_cast< uint8_t >( hatePercent ); + } + + server().queueForPlayer( player.getCharacterId(), { hateListPacket, hateRankPacket } ); +} + +void Util::Player::sendMount( Entity::Player& player ) +{ + auto mountId = player.getCurrentMount(); + auto inRangePlayerIds = player.getInRangePlayerIds( true ); + if( mountId != 0 ) + { + Network::Util::Player::sendActorControl( inRangePlayerIds, player, SetStatus, static_cast< uint8_t >( Common::ActorStatus::Mounted ) ); + Network::Util::Player::sendActorControlSelf( inRangePlayerIds, player, 0x39e, 12 ); + } + else + { + Network::Util::Player::sendActorControl( inRangePlayerIds, player, SetStatus, static_cast< uint8_t >( Common::ActorStatus::Idle ) ); + Network::Util::Player::sendActorControlSelf( inRangePlayerIds, player, Dismount, 1 ); + } + auto mountPacket = makeZonePacket< FFXIVIpcMount >( player.getId() ); + mountPacket->data().id = mountId; + server().queueForPlayers( inRangePlayerIds, mountPacket ); +} + +void Util::Player::sendEquip( Entity::Player& player ) +{ + server().queueForPlayers( player.getInRangePlayerIds( true ), std::make_shared< ModelEquipPacket >( player ) ); +} + +void Util::Player::sendCondition( Entity::Player& player ) +{ + server().queueForPlayer( player.getCharacterId(), std::make_shared< ConditionPacket >( player ) ); +} + +void Util::Player::sendRecastGroups( Entity::Player& player ) +{ + const auto& recastGroups = player.getRecastGroups(); + const auto& recastGroupsMax = player.getRecastGroupsMax(); + auto recastGroupPaket = makeZonePacket< FFXIVIpcRecastGroup >( player.getId() ); + memcpy( &recastGroupPaket->data().Recast, recastGroups.data(), recastGroups.size() * sizeof( float ) ); + memcpy( &recastGroupPaket->data().RecastMax, recastGroupsMax.data(), recastGroupsMax.size() * sizeof( float ) ); + server().queueForPlayer( player.getCharacterId(), recastGroupPaket ); } \ No newline at end of file diff --git a/src/world/Network/Util/PlayerUtil.h b/src/world/Network/Util/PlayerUtil.h index 5a8d3335..cc051c1f 100644 --- a/src/world/Network/Util/PlayerUtil.h +++ b/src/world/Network/Util/PlayerUtil.h @@ -18,6 +18,19 @@ namespace Sapphire::Network::Util::Player void sendGrandCompany( Entity::Player& player ); + void sendDeletePlayer( Entity::Player& player, uint32_t actorId, uint8_t spawnIndex ); + void sendDeleteObject( Entity::Player& player, uint8_t spawnIndex ); + + void sendHateList( Entity::Player& player ); + + void sendMount( Entity::Player& player ); + + void sendEquip( Entity::Player& player ); + + void sendCondition( Entity::Player& player ); + + void sendRecastGroups( Entity::Player& player ); + void sendActorControlSelf( Entity::Player& player, uint16_t category, uint32_t param1 = 0, uint32_t param2 = 0, uint32_t param3 = 0, uint32_t param4 = 0, uint32_t param5 = 0 ); diff --git a/src/world/Task/MoveTerritoryTask.cpp b/src/world/Task/MoveTerritoryTask.cpp index 40fb11bb..30194d9d 100644 --- a/src/world/Task/MoveTerritoryTask.cpp +++ b/src/world/Task/MoveTerritoryTask.cpp @@ -41,14 +41,13 @@ void MoveTerritoryTask::execute() if( !pPlayer ) return; - auto inRangePlayerIds = pPlayer->getInRangePlayerIds(); + auto inRangePlayerIds = pPlayer->getInRangePlayerIds( true ); auto warpStart = makeActorControlSelf( pPlayer->getId(), WarpStart, m_warpInfo.m_warpType, 1, 0, m_warpInfo.m_targetTerritoryId, 1 ); server.queueForPlayers( inRangePlayerIds, warpStart ); - server.queueForPlayer( pPlayer->getCharacterId(), warpStart ); server.queueForPlayers( inRangePlayerIds, makeActorControl( pPlayer->getId(), ActorDespawnEffect, m_warpInfo.m_warpType, m_warpInfo.m_targetTerritoryId ) ); - Common::Service< PlayerMgr >::ref().setCondition( *pPlayer, Common::PlayerCondition::BetweenAreas ); + pPlayer->setCondition( Common::PlayerCondition::BetweenAreas ); auto moveTerritoryPacket = makeZonePacket< WorldPackets::Server::FFXIVIpcMoveTerritory >( pPlayer->getId() ); moveTerritoryPacket->data().index = -1; diff --git a/src/world/Territory/InstanceContent.cpp b/src/world/Territory/InstanceContent.cpp index 1c44f9f2..d5b1b6dc 100644 --- a/src/world/Territory/InstanceContent.cpp +++ b/src/world/Territory/InstanceContent.cpp @@ -99,7 +99,7 @@ void Sapphire::InstanceContent::onPlayerZoneIn( Entity::Player& player ) } // mark player as "bound by duty" - Common::Service< World::Manager::PlayerMgr >::ref().setCondition( player, PlayerCondition::BoundByDuty ); + player.setCondition( PlayerCondition::BoundByDuty ); sendDirectorInit( player ); } @@ -614,7 +614,7 @@ void Sapphire::InstanceContent::clearDirector( Entity::Player& player ) player.setDirectorInitialized( false ); // remove "bound by duty" state - Service< World::Manager::PlayerMgr >::ref().removeCondition( player, PlayerCondition::BoundByDuty ); + player.removeCondition( PlayerCondition::BoundByDuty ); } uint32_t Sapphire::InstanceContent::getExpireValue()