diff --git a/sql/update.sql b/sql/update.sql index c0f2ed69..67fdb72e 100644 --- a/sql/update.sql +++ b/sql/update.sql @@ -23,5 +23,9 @@ -- ALTER TABLE `charadetail` CHANGE `OpeningSequence` `OpeningSequence` INT(3) NULL DEFAULT '0'; -- ------------------------------------------- -- update.sql Before Merge into Other SQL's 30/08/2017 +-- ------------------------------------------- +-- ALTER TABLE `charadetail` ADD `EquipDisplayFlags` int(3) DEFAULT '0' AFTER `GMRank`; +-- ------------------------------------------- +-- update.sql before titles added 09/10/2017 -ALTER TABLE `charadetail` ADD `EquipDisplayFlags` int(3) DEFAULT '0' AFTER `GMRank`; \ No newline at end of file +ALTER TABLE `charadetail` CHANGE `TitleList` `Titlelist` BINARY(48) NULL DEFAULT NULL; \ No newline at end of file diff --git a/src/servers/Server_Common/Network/PacketDef/Zone/ServerZoneDef.h b/src/servers/Server_Common/Network/PacketDef/Zone/ServerZoneDef.h index 82ae1aea..778f9a08 100644 --- a/src/servers/Server_Common/Network/PacketDef/Zone/ServerZoneDef.h +++ b/src/servers/Server_Common/Network/PacketDef/Zone/ServerZoneDef.h @@ -645,7 +645,7 @@ struct FFXIVIpcUpdateClassInfo : FFXIVIpcBasePacket */ struct FFXIVIpcPlayerTitleList : FFXIVIpcBasePacket { - uint8_t titleList[0x30]; + uint8_t titleList[48]; }; /** diff --git a/src/servers/Server_REST/PlayerMinimal.cpp b/src/servers/Server_REST/PlayerMinimal.cpp index 9643a35b..f8c7e1fe 100644 --- a/src/servers/Server_REST/PlayerMinimal.cpp +++ b/src/servers/Server_REST/PlayerMinimal.cpp @@ -175,6 +175,9 @@ namespace Core { char unlocks[64]; memset( unlocks, 0, 64 ); + char titleList[48]; + memset( titleList, 0, 48 ); + int16_t questTracking[5] = { -1, -1, -1, -1, -1 }; uint16_t size = static_cast< uint16_t >( m_lookMap.size() ); @@ -270,6 +273,7 @@ namespace Core { " unlocks, " " QuestTracking, " " Aetheryte, " + " TitleList, " " GMRank, " " UPDATE_DATE ) " " VALUES (" + std::to_string( m_iD ) + ", " @@ -285,6 +289,7 @@ namespace Core { + "UNHEX('" + std::string( Util::binaryToHexString( (uint8_t*)unlocks, 64 ) ) + "'), " + "UNHEX('" + std::string( Util::binaryToHexString( (uint8_t*)questTracking, 10 ) ) + "'), " + "UNHEX('" + std::string( Util::binaryToHexString( (uint8_t*)aetherytes, 12 ) ) + "')," + + "UNHEX('" + std::string( Util::binaryToHexString( (uint8_t*)titleList, 48 ) ) + "')," + std::to_string( m_gmRank ) + ", NOW());" ); diff --git a/src/servers/Server_Zone/Actor/Player.cpp b/src/servers/Server_Zone/Actor/Player.cpp index 6bb133c2..9630f6c3 100644 --- a/src/servers/Server_Zone/Actor/Player.cpp +++ b/src/servers/Server_Zone/Actor/Player.cpp @@ -1427,27 +1427,27 @@ uint8_t * Core::Entity::Player::getTitleList() void Core::Entity::Player::addTitle( uint16_t titleId ) { - uint8_t index = titleId / 8; // Find what index of uint8_t array this title will fit in + uint16_t index; + uint8_t value; + Util::valueToFlagByteIndexValue( titleId, value, index ); - uint8_t bitVal; - - if ( titleId < 8 ) - { - bitVal = titleId; - } - else - { - bitVal = 1 << ( titleId % ( index * 8 ) ); - } - - m_titleList[index] |= bitVal; + m_titleList[index] |= value; + setSyncFlag( PlayerSyncFlags::Title ); } void Core::Entity::Player::setTitle( uint16_t titleId ) { - // todo: add check to see if player actually has title from titlelist. packet injection n stuff + uint16_t index; + uint8_t value; + Util::valueToFlagByteIndexValue( titleId, value, index ); + + if ( ( m_titleList[index] & value ) == 0 ) // Player doesn't have title - bail + return; + m_title = titleId; + sendToInRangeSet( ActorControlPacket142( getId(), SetTitle, titleId ), true ); + setSyncFlag( PlayerSyncFlags::Title ); } void Core::Entity::Player::setEquipDisplayFlags( uint8_t state ) diff --git a/src/servers/Server_Zone/Actor/Player.h b/src/servers/Server_Zone/Actor/Player.h index 0fcd2b0d..6c84849f 100644 --- a/src/servers/Server_Zone/Actor/Player.h +++ b/src/servers/Server_Zone/Actor/Player.h @@ -576,7 +576,7 @@ private: } m_retainerInfo[8]; uint16_t m_title; - uint8_t m_titleList[30]; + uint8_t m_titleList[48]; uint8_t m_achievement[16]; uint8_t m_howTo[33]; uint8_t m_homePoint; diff --git a/src/servers/Server_Zone/Actor/PlayerSql.cpp b/src/servers/Server_Zone/Actor/PlayerSql.cpp index d8cf4194..32141d70 100644 --- a/src/servers/Server_Zone/Actor/PlayerSql.cpp +++ b/src/servers/Server_Zone/Actor/PlayerSql.cpp @@ -82,7 +82,9 @@ bool Core::Entity::Player::load( uint32_t charId, Core::SessionPtr pSession ) "cd.CFPenaltyUntil, " "cd.OpeningSequence, " "cd.GMRank, " - "cd.EquipDisplayFlags " + "cd.EquipDisplayFlags, " + "cd.ActiveTitle, " + "cd.TitleList " // 40 "FROM charabase AS c " " INNER JOIN charadetail AS cd " " ON c.CharacterId = cd.CharacterId " @@ -176,6 +178,9 @@ bool Core::Entity::Player::load( uint32_t charId, Core::SessionPtr pSession ) m_gmRank = field[37].get< uint8_t >(); m_equipDisplayFlags = field[38].get< uint8_t >(); + m_title = field[39].get< uint8_t >(); + field[40].getBinary( reinterpret_cast< char* >( m_titleList ), sizeof( m_titleList ) ); + m_pCell = nullptr; if( !loadActiveQuests() || !loadClassData() || !loadSearchInfo() ) @@ -316,6 +321,12 @@ void Core::Entity::Player::createUpdateSql() if( m_updateFlags & PlayerSyncFlags::HowTo ) charaDetailSet.insert( " HowTo = UNHEX('" + std::string( Util::binaryToHexString( static_cast< uint8_t* >( m_howTo ), sizeof( m_howTo ) ) ) + "')" ); + if ( m_updateFlags & PlayerSyncFlags::Title ) + { + charaDetailSet.insert( " ActiveTitle = " + std::to_string( m_title ) ); + charaDetailSet.insert( " TitleList = UNHEX('" + std::string( Util::binaryToHexString( reinterpret_cast< uint8_t* >( m_titleList ), sizeof( m_titleList ) ) ) + "')" ); + } + if( m_updateFlags & PlayerSyncFlags::Aetherytes ) charaDetailSet.insert( " Aetheryte = UNHEX('" + std::string( Util::binaryToHexString( reinterpret_cast< uint8_t* >( m_aetheryte ), sizeof( m_aetheryte ) ) ) + "')" ); diff --git a/src/servers/Server_Zone/Network/Handlers/ActionHandler.cpp b/src/servers/Server_Zone/Network/Handlers/ActionHandler.cpp index 54b95147..9012ef65 100644 --- a/src/servers/Server_Zone/Network/Handlers/ActionHandler.cpp +++ b/src/servers/Server_Zone/Network/Handlers/ActionHandler.cpp @@ -118,13 +118,18 @@ void Core::Network::GameConnection::actionHandler( const Packets::GamePacket& in pPlayer->getCurrentAction()->setInterrupted(); break; } + case 0x12E: // Set player title + { + pPlayer->setTitle( param1 ); + break; + } case 0x12F: // Get title list { GamePacketNew< FFXIVIpcPlayerTitleList, ServerZoneIpcType > titleListPacket( pPlayer->getId() ); memcpy( titleListPacket.data().titleList, pPlayer->getTitleList(), sizeof( titleListPacket.data().titleList ) ); pPlayer->queuePacket( titleListPacket ); - + break; } case 0x133: // Update howtos seen {