diff --git a/deps/datReader/Exd/Structs.h b/deps/datReader/Exd/Structs.h index 6d620b0f..01aa24e8 100644 --- a/deps/datReader/Exd/Structs.h +++ b/deps/datReader/Exd/Structs.h @@ -159,9 +159,15 @@ namespace Excel { uint32_t BeginnerBonusGil; uint32_t BeginnerBonusExp; + uint32_t Unknown; + uint32_t Unknown1; + uint32_t Unknown2; + uint32_t Unknown3; + uint32_t Unknown4; + uint32_t Unknown5; uint32_t TotalExp; uint32_t TotalGil; - uint32_t Unknown; + uint32_t Unknown6; uint16_t BeginnerBonusA; uint16_t ClearA; uint16_t ClearB; @@ -172,9 +178,9 @@ namespace Excel struct InstanceContent { InstanceContentTextStruct Text; + InstanceContentTextStruct Text1; InstanceContentRewardStruct Reward; uint8_t Unknown1; - uint32_t Unknown2[6]; uint32_t StartCutscene; uint32_t EntranceRect; uint32_t TerritoryType; @@ -188,24 +194,30 @@ namespace Excel uint16_t Time; uint16_t Music; uint16_t ClearMusic; + uint16_t ItemLevelMax; uint16_t Sortkey; - uint8_t Unknown4; + int16_t Unknown6; uint8_t Type; - uint8_t RandomContentType; - uint8_t RewardType; - uint8_t FinderPartyCondition; - uint8_t LevelMin; + uint8_t UnknownType; uint8_t LevelMax; - uint8_t PartyMemberCount; - uint8_t PartyCount; - uint8_t TankCount; - uint8_t HealerCount; - uint8_t AttackerCount; - uint8_t RangeCount; + uint8_t Unknown7; + uint8_t Unknown8; + }; + + struct ContentFinderCondition + { + uint16_t InstanceContentId; uint8_t ItemLevel; - uint8_t ItemLevelMax; - uint8_t ProgressMax; - int8_t TreasureObtainedFlag; + uint8_t Unknown; + uint8_t RandomContentType; + uint8_t FinderPartyCondition; + uint8_t RewardType; + uint8_t ContentMemberType; + + uint8_t Unknown1; + uint8_t Unknown2; + uint8_t LevelMin; + uint8_t Unknown3; uint8_t padding1 : 2; uint8_t DisableHalfwayProgress : 1; uint8_t Halfway : 1; @@ -213,7 +225,42 @@ namespace Excel uint8_t DifferentiateDPS : 1; uint8_t Alliance : 1; uint8_t FreeRole : 1; - uint8_t Unknown5; + uint8_t Unknown6; + uint8_t Unknown7 : 1; + uint8_t Unknown8 : 1; + uint8_t Unknown9 : 1; + uint8_t Unknown10 : 1; + uint8_t Unknown11 : 1; + uint8_t Unknown12 : 1; + uint8_t Unknown13 : 1; + uint8_t Unknown14 : 1; + uint8_t Unknown15 : 1; + uint8_t Unknown16 : 1; + uint8_t Unknown17 : 1; + uint8_t Unknown18 : 1; + uint8_t Unknown19 : 1; + uint8_t Unknown20 : 1; + uint8_t Unknown21 : 1; + uint8_t Unknown22 : 1; + + + }; + + struct ContentMemberType + { + uint8_t Unknown; + uint8_t Unknown1; + uint8_t PartyCount; + uint8_t PartyMemberCount; + uint8_t Unknown2; + uint8_t TankCount; + uint8_t HealerCount; + uint8_t AttackerCount; + uint8_t RangeCount; + uint8_t Unknown3 : 1; + uint8_t Unknown4 : 1; + uint8_t Unknown5 : 1; + uint8_t padding : 5; }; /* 63505 */ diff --git a/src/world/ContentFinder/ContentFinder.cpp b/src/world/ContentFinder/ContentFinder.cpp index 53ac5890..b34c9493 100644 --- a/src/world/ContentFinder/ContentFinder.cpp +++ b/src/world/ContentFinder/ContentFinder.cpp @@ -46,7 +46,7 @@ void Sapphire::World::ContentFinder::update() break; case MatchingComplete: { - auto contentInfo = exdData.getRow< Excel::InstanceContent >( content->getContentId() ); + auto contentInfo = exdData.getRow< Excel::InstanceContent >( content->getContentFinderId() ); for( auto& queuedPlayer : content->m_players ) { uint32_t inProgress = 0; // 0x01 - in progress @@ -72,8 +72,8 @@ void Sapphire::World::ContentFinder::update() { auto& terriMgr = Service< TerritoryMgr >::ref(); auto& warpMgr = Common::Service< WarpMgr >::ref(); - auto contentInfo = exdData.getRow< Excel::InstanceContent >( content->getContentId() ); - if( auto instance = terriMgr.createInstanceContent( content->getContentId() ) ) + auto contentFinderInfo = exdData.getRow< Excel::ContentFinderCondition >( content->getContentFinderId() ); + if( auto instance = terriMgr.createInstanceContent( content->getContentFinderId() ) ) { auto pInstanceContent = instance->getAsInstanceContent(); @@ -85,10 +85,9 @@ void Sapphire::World::ContentFinder::update() pInstanceContent->bindPlayer( queuedPlayer->getEntityId() ); warpMgr.requestMoveTerritory( *server.getPlayer( queuedPlayer->getEntityId() ), WarpType::WARP_TYPE_INSTANCE_CONTENT, pInstanceContent->getGuId(), { 0.f, 0.f, 0.f }, 0.f ); - - auto zonePacket = makeUpdateContent( queuedPlayer->getEntityId(), contentInfo->data().TerritoryType, - 0, pInstanceContent->getGuId() ); - auto zonePacket2 = makeUpdateContent( queuedPlayer->getEntityId(), contentInfo->data().TerritoryType, content->m_partyMemberCount ); + + auto zonePacket = makeUpdateContent( queuedPlayer->getEntityId(), instance->getTerritoryTypeId(), 0, pInstanceContent->getGuId() ); + auto zonePacket2 = makeUpdateContent( queuedPlayer->getEntityId(), instance->getTerritoryTypeId(), content->m_partyMemberCount ); server.queueForPlayer( queuedPlayer->getCharacterId(), zonePacket ); server.queueForPlayer( queuedPlayer->getCharacterId(), zonePacket2 ); } @@ -130,12 +129,12 @@ void Sapphire::World::ContentFinder::registerContentRequest( Sapphire::Entity::P void Sapphire::World::ContentFinder::registerRandomContentRequest( Sapphire::Entity::Player &player, uint32_t randomContentTypeId ) { auto& exdData = Service< Data::ExdData >::ref(); - auto contentListIds = exdData.getIdList< Excel::InstanceContent >(); + auto contentListIds = exdData.getIdList< Excel::ContentFinderCondition >(); std::vector< uint32_t > idList; for( auto id : contentListIds ) { - auto instanceContent = exdData.getRow< Excel::InstanceContent >( id ); + auto instanceContent = exdData.getRow< Excel::ContentFinderCondition >( id ); if( instanceContent->data().RandomContentType == randomContentTypeId ) { if( instanceContent->data().LevelMin <= player.getLevel() ) @@ -154,7 +153,7 @@ void Sapphire::World::ContentFinder::completeRegistration( const Sapphire::Entit auto queuedContent = m_queuedContent[ m_queuedPlayer[ player.getId() ]->getActiveRegisterId() ]; auto& exdData = Service< Data::ExdData >::ref(); - auto content = exdData.getRow< Excel::InstanceContent >( queuedContent->getContentId() ); + auto content = exdData.getRow< Excel::InstanceContent >( queuedContent->getContentFinderId() ); // Undersized if( flags & 0x01 ) @@ -287,18 +286,18 @@ uint32_t Sapphire::World::ContentFinder::getNextRegisterId() return ++m_nextRegisterId; } -Sapphire::World::ContentFinder::QueuedContentPtrList Sapphire::World::ContentFinder::getMatchingContentList( Sapphire::Entity::Player &player, uint32_t contentId ) +Sapphire::World::ContentFinder::QueuedContentPtrList Sapphire::World::ContentFinder::getMatchingContentList( Sapphire::Entity::Player &player, uint32_t contentFinderId ) { QueuedContentPtrList outVec; for( auto& it : m_queuedContent ) { auto& foundContent = it.second; - uint32_t leftContentId = foundContent->getContentId(); - if( leftContentId != contentId ) + uint32_t leftContentId = foundContent->getContentFinderId(); + if( leftContentId != contentFinderId ) continue; auto& exdData = Common::Service< Data::ExdData >::ref(); - auto content = exdData.getRow< Excel::InstanceContent >( contentId ); + auto content = exdData.getRow< Excel::ContentFinderCondition >( contentFinderId ); if( !content ) continue; @@ -309,34 +308,38 @@ Sapphire::World::ContentFinder::QueuedContentPtrList Sapphire::World::ContentFin if( foundContent->getState() != QueuedContentState::MatchingInProgress ) continue; + auto contentMember = exdData.getRow< Excel::ContentMemberType >( content->data().ContentMemberType ); + if( !contentMember ) + continue; + // skip if the party is already full - if( foundContent->m_partyMemberCount >= content->data().PartyMemberCount ) + if( foundContent->m_partyMemberCount >= contentMember->data().PartyMemberCount ) continue; switch( player.getRole() ) { case Role::Tank: { - if( content->data().TankCount <= foundContent->m_tankCount ) + if( contentMember->data().TankCount <= foundContent->m_tankCount ) continue; break; } case Role::Healer: { - if( content->data().HealerCount <= foundContent->m_healerCount ) + if( contentMember->data().HealerCount <= foundContent->m_healerCount ) continue; break; } case Role::RangedPhysical: case Role::RangedMagical: { - if( content->data().RangeCount <= foundContent->m_rangeCount ) + if( contentMember->data().RangeCount <= foundContent->m_rangeCount ) continue; break; } case Role::Melee: { - if( content->data().AttackerCount <= foundContent->m_attackerCount ) + if( contentMember->data().AttackerCount <= foundContent->m_attackerCount ) continue; break; } @@ -351,7 +354,7 @@ Sapphire::World::ContentFinder::QueuedContentPtrList Sapphire::World::ContentFin if( outVec.empty() ) { - auto queuedContent = std::make_shared< QueuedContent >( getNextRegisterId(), contentId ); + auto queuedContent = std::make_shared< QueuedContent >( getNextRegisterId(), contentFinderId ); outVec.push_back( queuedContent ); } return outVec; @@ -365,7 +368,7 @@ void Sapphire::World::ContentFinder::accept( Entity::Player& player ) auto queuedPlayer = m_queuedPlayer[ player.getId() ]; auto queuedContent = m_queuedContent[ queuedPlayer->getActiveRegisterId() ]; - auto content = exdData.getRow< Excel::InstanceContent >( queuedContent->getContentId() ); + auto content = exdData.getRow< Excel::InstanceContent >( queuedContent->getContentFinderId() ); // Something has gone quite wrong.. if( queuedContent->getState() != WaitingForAccept ) @@ -387,7 +390,7 @@ void Sapphire::World::ContentFinder::accept( Entity::Player& player ) } Logger::info( "[{2}][ContentFinder] Content accepted, contentId#{0} registerId#{1}", - queuedContent->getContentId(), queuedContent->getRegisterId(), player.getId() ); + queuedContent->getContentFinderId(), queuedContent->getRegisterId(), player.getId() ); auto statusPacket = makeNotifyFindContentStatus( player.getId(), content->data().TerritoryType, 4, queuedContent->m_dpsAccepted, queuedContent->m_healerAccepted, queuedContent->m_tankAccepted, 0x01 ); @@ -410,7 +413,7 @@ void Sapphire::World::ContentFinder::withdraw( Entity::Player& player ) auto& exdData = Service< Data::ExdData >::ref(); auto queuedPlayer = m_queuedPlayer[ player.getId() ]; - auto contentInfo = exdData.getRow< Excel::InstanceContent >( m_queuedContent[ queuedPlayer->getActiveRegisterId() ]->getContentId() ); + auto contentInfo = exdData.getRow< Excel::InstanceContent >( m_queuedContent[ queuedPlayer->getActiveRegisterId() ]->getContentFinderId() ); // remove the player from the global CF list m_queuedPlayer.erase( player.getId() ); @@ -426,7 +429,7 @@ void Sapphire::World::ContentFinder::withdraw( Entity::Player& player ) if( content.second->withdrawPlayer( queuedPlayer ) ) { Logger::info( "[{2}] Content withdrawn, contentId#{0} registerId#{1}", - content.second->getContentId(), content.second->getRegisterId(), player.getId() ); + content.second->getContentFinderId(), content.second->getRegisterId(), player.getId() ); updateRegisterIdSet.insert( content.second->getRegisterId() ); } } @@ -439,7 +442,7 @@ void Sapphire::World::ContentFinder::withdraw( Entity::Player& player ) if( updateRegisterIdSet.count( regId ) == 0 ) continue; - auto queuedContentInfo = exdData.getRow< Excel::InstanceContent >( content.second->getContentId() ); + auto queuedContentInfo = exdData.getRow< Excel::InstanceContent >( content.second->getContentFinderId() ); auto& playerList = content.second->m_players; for( const auto& pPlayer : playerList ) { @@ -477,9 +480,9 @@ bool Sapphire::World::ContentFinder::removeContentByRegisterId( uint32_t registe ////////////////////////////////////////////////////////////////////// -uint32_t Sapphire::World::QueuedContent::getContentId() const +uint32_t Sapphire::World::QueuedContent::getContentFinderId() const { - return m_contentId; + return m_contentFinderId; } uint32_t Sapphire::World::QueuedContent::getRegisterId() const @@ -488,13 +491,13 @@ uint32_t Sapphire::World::QueuedContent::getRegisterId() const } Sapphire::World::QueuedContent::QueuedContent( uint32_t registerId, uint32_t contentId ) : - m_registerId( registerId ), - m_contentId( contentId ), - m_state( QueuedContentState::MatchingInProgress ), - m_contentPopTime( 0 ) + m_registerId( registerId ), + m_contentFinderId( contentId ), + m_state( QueuedContentState::MatchingInProgress ), + m_contentPopTime( 0 ) { - auto& exdData = Common::Service< Data::ExdData >::ref(); - auto content = exdData.getRow< Excel::InstanceContent >( contentId ); + // auto& exdData = Common::Service< Data::ExdData >::ref(); + // auto content = exdData.getRow< Excel::InstanceContent >( contentId ); } diff --git a/src/world/ContentFinder/ContentFinder.h b/src/world/ContentFinder/ContentFinder.h index 13475500..6b9efffb 100644 --- a/src/world/ContentFinder/ContentFinder.h +++ b/src/world/ContentFinder/ContentFinder.h @@ -67,7 +67,7 @@ namespace Sapphire::World QueuedContent( uint32_t registerId, uint32_t contentId ); ~QueuedContent() = default; uint32_t getRegisterId() const; - uint32_t getContentId() const; + uint32_t getContentFinderId() const; uint8_t getRoleCount( Sapphire::Common::Role role ) const; void queuePlayer( const std::shared_ptr< QueuedPlayer >& pQPlayer ); bool withdrawPlayer( const std::shared_ptr< QueuedPlayer >& pQPlayer ); @@ -77,7 +77,7 @@ namespace Sapphire::World private: uint32_t m_registerId; - uint32_t m_contentId; + uint32_t m_contentFinderId; uint32_t m_contentPopTime; diff --git a/src/world/Manager/TerritoryMgr.cpp b/src/world/Manager/TerritoryMgr.cpp index 1b12884f..7449aa85 100644 --- a/src/world/Manager/TerritoryMgr.cpp +++ b/src/world/Manager/TerritoryMgr.cpp @@ -343,30 +343,37 @@ TerritoryPtr TerritoryMgr::createQuestBattle( uint32_t questBattleId ) return nullptr; } -TerritoryPtr TerritoryMgr::createInstanceContent( uint32_t instanceContentId ) +TerritoryPtr TerritoryMgr::createInstanceContent( uint32_t contentFinderId ) { auto& exdData = Common::Service< Data::ExdData >::ref(); - auto pInstanceContent = exdData.getRow< Excel::InstanceContent >( instanceContentId ); - if( !pInstanceContent || !isInstanceContentTerritory( pInstanceContent->data().TerritoryType ) ) + auto pContentFinderCondition = exdData.getRow< Excel::ContentFinderCondition >( contentFinderId ); + if( !pContentFinderCondition ) + return nullptr; + + auto pInstanceContent = exdData.getRow< Excel::InstanceContent >( pContentFinderCondition->data().InstanceContentId ); + if( !pInstanceContent ) return nullptr; auto& instanceContentData = pInstanceContent->data(); + if( !isInstanceContentTerritory( instanceContentData.TerritoryType ) ) + return nullptr; + auto pTeri = getTerritoryDetail( instanceContentData.TerritoryType ); - auto name = pInstanceContent->getString( instanceContentData.Text.Name ); + auto name = pContentFinderCondition->getString( instanceContentData.Text.Name ); if( !pTeri || name.empty() ) return nullptr; - Logger::debug( "Starting instance for InstanceContent id: {0} ({1})", instanceContentId, name ); + Logger::debug( "Starting instance for InstanceContent id: {0} ({1})", contentFinderId, name ); - auto pZone = make_InstanceContent( pInstanceContent, instanceContentData.TerritoryType, getNextInstanceId(), " ", name, instanceContentId ); + auto pZone = make_InstanceContent( pInstanceContent, pContentFinderCondition, instanceContentData.TerritoryType, getNextInstanceId(), " ", name, contentFinderId ); pZone->init(); - m_instanceContentIdToInstanceMap[ instanceContentId ][ pZone->getGuId() ] = pZone; + m_instanceContentIdToInstanceMap[ contentFinderId ][ pZone->getGuId() ] = pZone; m_guIdToTerritoryPtrMap[ pZone->getGuId() ] = pZone; m_instanceZoneSet.insert( pZone ); diff --git a/src/world/Manager/TerritoryMgr.h b/src/world/Manager/TerritoryMgr.h index 5cd7489f..0b54c1f4 100644 --- a/src/world/Manager/TerritoryMgr.h +++ b/src/world/Manager/TerritoryMgr.h @@ -108,7 +108,7 @@ namespace Sapphire::World::Manager /*! creates a new instance for a given territoryTypeId */ TerritoryPtr createTerritoryInstance( uint32_t territoryTypeId ); - TerritoryPtr createInstanceContent( uint32_t instanceContentId ); + TerritoryPtr createInstanceContent( uint32_t contentFinderId ); TerritoryPtr createQuestBattle( uint32_t contentFinderConditionId ); diff --git a/src/world/Territory/InstanceContent.cpp b/src/world/Territory/InstanceContent.cpp index 064f6915..09c61bfa 100644 --- a/src/world/Territory/InstanceContent.cpp +++ b/src/world/Territory/InstanceContent.cpp @@ -36,6 +36,7 @@ using namespace Sapphire::Network::ActorControl; using namespace Sapphire::World::Manager; Sapphire::InstanceContent::InstanceContent( std::shared_ptr< Excel::ExcelStruct< Excel::InstanceContent > > pInstanceConfiguration, + std::shared_ptr< Excel::ExcelStruct< Excel::ContentFinderCondition > > pContentFinderCondition, uint16_t territoryType, uint32_t guId, const std::string& internalName, @@ -44,6 +45,7 @@ Sapphire::InstanceContent::InstanceContent( std::shared_ptr< Excel::ExcelStruct< Territory( static_cast< uint16_t >( territoryType ), guId, internalName, contentName ), Director( Event::Director::InstanceContent, instanceContentId ), m_instanceConfiguration( pInstanceConfiguration ), + m_contentFinderCondition( pContentFinderCondition ), m_instanceContentId( instanceContentId ), m_state( Created ), m_pEntranceEObj( nullptr ), @@ -628,7 +630,10 @@ uint32_t Sapphire::InstanceContent::getOptionFlags() { uint32_t bitFlag = 0; - if( m_instanceConfiguration->data().PartyMemberCount == 1 ) + auto& exdData = Common::Service< Data::ExdData >::ref(); + auto contentInfo = exdData.getRow< Excel::ContentMemberType >( m_contentFinderCondition->data().ContentMemberType ); + + if( contentInfo->data().PartyMemberCount == 1 ) bitFlag |= 1; if( getVoteState() ) diff --git a/src/world/Territory/InstanceContent.h b/src/world/Territory/InstanceContent.h index 936745b7..214bd5da 100644 --- a/src/world/Territory/InstanceContent.h +++ b/src/world/Territory/InstanceContent.h @@ -81,6 +81,7 @@ namespace Sapphire }; InstanceContent( std::shared_ptr< Excel::ExcelStruct< Excel::InstanceContent > > pInstanceConfiguration, + std::shared_ptr< Excel::ExcelStruct< Excel::ContentFinderCondition > > pContentFinderCondition, uint16_t territoryType, uint32_t guId, const std::string& internalName, @@ -192,6 +193,8 @@ namespace Sapphire size_t getInstancePlayerCount() const; private: std::shared_ptr< Excel::ExcelStruct< Excel::InstanceContent > > m_instanceConfiguration; + std::shared_ptr< Excel::ExcelStruct< Excel::ContentFinderCondition > > m_contentFinderCondition; + std::shared_ptr< Excel::ExcelStruct< Excel::ContentMemberType > > m_contentMemberType; uint32_t m_instanceContentId; InstanceContentState m_state; uint16_t m_currentBgm;