1
Fork 0
mirror of https://github.com/SapphireServer/Sapphire.git synced 2025-05-08 03:37:45 +00:00

Merge remote-tracking branch 'origin/develop' into boost_scrap

This commit is contained in:
mordred 2018-10-24 14:00:56 +02:00
commit e2598afe6d
7 changed files with 63 additions and 24 deletions

View file

@ -1000,8 +1000,8 @@ struct FFXIVIpcPlayerClassInfo :
uint16_t classId; uint16_t classId;
uint8_t unknown; uint8_t unknown;
uint8_t isSpecialist; uint8_t isSpecialist;
uint16_t level; // Locks actions, equipment, prob more uint16_t syncedLevel; // Locks actions, equipment, prob more. Player's current level (synced).
uint16_t level1; // Locks roles, prob more uint16_t classLevel; // Locks roles, prob more. Player's actual unsynced level.
uint32_t roleActions[10]; uint32_t roleActions[10];
}; };
@ -1014,7 +1014,10 @@ struct FFXIVIpcModelEquip :
{ {
/* 0000 */ uint64_t mainWeapon; /* 0000 */ uint64_t mainWeapon;
/* 0008 */ uint64_t offWeapon; /* 0008 */ uint64_t offWeapon;
/* 0010 */ uint32_t padding1; /* 0010 */ uint8_t unk1;
/* 0011 */ uint8_t classJobId;
/* 0012 */ uint8_t level;
/* 0013 */ uint8_t unk2;
/* 0014 */ uint32_t models[10]; /* 0014 */ uint32_t models[10];
/* 003C */ uint32_t padding2; /* 003C */ uint32_t padding2;
}; };

View file

@ -319,6 +319,7 @@ void PlayerMinimal::saveAsNew()
createInvDbContainer( InventoryType::ArmoryWrist ); createInvDbContainer( InventoryType::ArmoryWrist );
createInvDbContainer( InventoryType::ArmoryRing ); createInvDbContainer( InventoryType::ArmoryRing );
createInvDbContainer( InventoryType::ArmoryMain ); createInvDbContainer( InventoryType::ArmoryMain );
createInvDbContainer( InventoryType::ArmorySoulCrystal );
createInvDbContainer( InventoryType::Currency ); createInvDbContainer( InventoryType::Currency );
createInvDbContainer( InventoryType::Crystal ); createInvDbContainer( InventoryType::Crystal );

View file

@ -746,7 +746,8 @@ void Core::Entity::Player::setClassJob( Common::ClassJob classJob )
auto classInfoPacket = makeZonePacket< FFXIVIpcPlayerClassInfo >( getId() ); auto classInfoPacket = makeZonePacket< FFXIVIpcPlayerClassInfo >( getId() );
classInfoPacket->data().classId = static_cast< uint8_t >( getClass() ); classInfoPacket->data().classId = static_cast< uint8_t >( getClass() );
classInfoPacket->data().level = getLevel(); classInfoPacket->data().classLevel = getLevel();
classInfoPacket->data().syncedLevel = getLevel();
queuePacket( classInfoPacket ); queuePacket( classInfoPacket );
sendToInRangeSet( makeActorControl142( getId(), ClassJobChange, 0x04 ), true ); sendToInRangeSet( makeActorControl142( getId(), ClassJobChange, 0x04 ), true );
@ -1550,8 +1551,8 @@ void Core::Entity::Player::sendZonePackets()
auto classInfoPacket = makeZonePacket< FFXIVIpcPlayerClassInfo >( getId() ); auto classInfoPacket = makeZonePacket< FFXIVIpcPlayerClassInfo >( getId() );
classInfoPacket->data().classId = static_cast< uint8_t >( getClass() ); classInfoPacket->data().classId = static_cast< uint8_t >( getClass() );
classInfoPacket->data().unknown = 1; classInfoPacket->data().unknown = 1;
classInfoPacket->data().level = getLevel(); classInfoPacket->data().syncedLevel = getLevel();
classInfoPacket->data().level1 = getLevel(); classInfoPacket->data().classLevel = getLevel();
queuePacket( classInfoPacket ); queuePacket( classInfoPacket );
m_itemLevel = calculateEquippedGearItemLevel(); m_itemLevel = calculateEquippedGearItemLevel();
@ -1733,4 +1734,3 @@ bool Core::Entity::Player::isOnEnterEventDone() const
{ {
return m_onEnterEventDone; return m_onEnterEventDone;
} }

View file

@ -324,7 +324,13 @@ public:
void unequipItem( Common::GearSetSlot equipSlotId, ItemPtr pItem ); void unequipItem( Common::GearSetSlot equipSlotId, ItemPtr pItem );
/*! equip a weapon, possibly forcing a job change */ /*! equip a weapon, possibly forcing a job change */
void equipWeapon( ItemPtr pItem ); void equipWeapon( ItemPtr pItem, bool updateClass );
/*! equip a soul crystal, possibly forcing a job change*/
void equipSoulCrystal( ItemPtr pItem, bool updateClass );
/*! unequip a soul crystal, returning to the base class*/
void unequipSoulCrystal( ItemPtr pItem );
/*! get player ilvl */ /*! get player ilvl */
uint16_t getItemLevel() const; uint16_t getItemLevel() const;
@ -356,7 +362,7 @@ public:
/*! return the current amount of crystals of type */ /*! return the current amount of crystals of type */
uint32_t getCrystal( uint8_t type ) const; uint32_t getCrystal( uint8_t type ) const;
void updateModels( Common::GearSetSlot equipSlotId, const Core::ItemPtr& pItem ); void updateModels( Common::GearSetSlot equipSlotId, const Core::ItemPtr& pItem, bool updateClass );
Common::GearModelSlot equipSlotToModelSlot( Common::GearSetSlot slot ); Common::GearModelSlot equipSlotToModelSlot( Common::GearSetSlot slot );

View file

@ -114,7 +114,7 @@ void Core::Entity::Player::sendItemLevel()
queuePacket( makeActorControl142( getId(), SetItemLevel, getItemLevel(), 0 ) ); queuePacket( makeActorControl142( getId(), SetItemLevel, getItemLevel(), 0 ) );
} }
void Core::Entity::Player::equipWeapon( ItemPtr pItem ) void Core::Entity::Player::equipWeapon( ItemPtr pItem, bool updateClass )
{ {
auto exdData = g_fw.get< Core::Data::ExdDataGenerated >(); auto exdData = g_fw.get< Core::Data::ExdDataGenerated >();
if( !exdData ) if( !exdData )
@ -122,16 +122,31 @@ void Core::Entity::Player::equipWeapon( ItemPtr pItem )
auto itemInfo = exdData->get< Core::Data::Item >( pItem->getId() ); auto itemInfo = exdData->get< Core::Data::Item >( pItem->getId() );
auto itemClassJob = itemInfo->classJobUse; auto itemClassJob = itemInfo->classJobUse;
auto classJobInfo = exdData->get< Core::Data::ClassJob >( static_cast< uint32_t >( getClass() ) );
auto currentClass = getClass(); auto currentParentClass = static_cast< ClassJob >( classJobInfo->classJobParent );
auto newClassJob = static_cast< ClassJob >( itemClassJob ); auto newClassJob = static_cast< ClassJob >( itemClassJob );
if( isClassJobUnlocked( newClassJob ) ) if( ( isClassJobUnlocked( newClassJob ) ) && ( currentParentClass != newClassJob ) )
{
if ( updateClass )
setClassJob( newClassJob );
else
return;
}
}
void Core::Entity::Player::equipSoulCrystal( ItemPtr pItem, bool updateJob )
{
auto exdData = g_fw.get< Core::Data::ExdDataGenerated >();
if ( !exdData )
return; return;
// todo: check if soul crystal is equipped and use job instead auto itemInfo = exdData->get< Core::Data::Item >( pItem->getId() );
auto itemClassJob = itemInfo->classJobUse;
auto newClassJob = static_cast< ClassJob >( itemClassJob );
setClassJob( newClassJob ); if ( isClassJobUnlocked( newClassJob ) && updateJob )
setClassJob( newClassJob );
} }
// equip an item // equip an item
@ -139,18 +154,18 @@ void Core::Entity::Player::equipItem( Common::GearSetSlot equipSlotId, ItemPtr p
{ {
//g_framework.getLogger().debug( "Equipping into slot " + std::to_string( equipSlotId ) ); //g_framework.getLogger().debug( "Equipping into slot " + std::to_string( equipSlotId ) );
updateModels( equipSlotId, pItem );
if( sendUpdate ) if( sendUpdate )
{ {
updateModels( equipSlotId, pItem, true );
this->sendModel(); this->sendModel();
m_itemLevel = calculateEquippedGearItemLevel(); m_itemLevel = calculateEquippedGearItemLevel();
sendItemLevel(); sendItemLevel();
} }
else
updateModels( equipSlotId, pItem, false );
} }
void Core::Entity::Player::updateModels( GearSetSlot equipSlotId, const Core::ItemPtr& pItem ) void Core::Entity::Player::updateModels( GearSetSlot equipSlotId, const Core::ItemPtr& pItem, bool updateClass )
{ {
uint64_t model = pItem->getModelId1(); uint64_t model = pItem->getModelId1();
uint64_t model2 = pItem->getModelId2(); uint64_t model2 = pItem->getModelId2();
@ -160,8 +175,7 @@ void Core::Entity::Player::updateModels( GearSetSlot equipSlotId, const Core::It
case MainHand: case MainHand:
m_modelMainWeapon = model; m_modelMainWeapon = model;
m_modelSubWeapon = model2; m_modelSubWeapon = model2;
// TODO: add job change upon changing weapon if needed equipWeapon( pItem, updateClass );
// equipWeapon( pItem );
break; break;
case OffHand: case OffHand:
@ -169,8 +183,7 @@ void Core::Entity::Player::updateModels( GearSetSlot equipSlotId, const Core::It
break; break;
case SoulCrystal: case SoulCrystal:
// TODO: add Job change on equipping crystal equipSoulCrystal( pItem, updateClass );
// change job
break; break;
case Waist: case Waist:
@ -228,6 +241,20 @@ void Core::Entity::Player::unequipItem( Common::GearSetSlot equipSlotId, ItemPtr
m_itemLevel = calculateEquippedGearItemLevel(); m_itemLevel = calculateEquippedGearItemLevel();
sendItemLevel(); sendItemLevel();
if ( equipSlotId == SoulCrystal )
unequipSoulCrystal( pItem );
}
void Core::Entity::Player::unequipSoulCrystal( ItemPtr pItem )
{
auto exdData = g_fw.get< Core::Data::ExdDataGenerated >();
if ( !exdData )
return;
auto currentClassJob = exdData->get< Core::Data::ClassJob >( static_cast< uint32_t >( getClass() ) );
auto parentClass = static_cast< ClassJob >( currentClassJob->classJobParent );
setClassJob( parentClass );
} }
// TODO: these next functions are so similar that they could likely be simplified // TODO: these next functions are so similar that they could likely be simplified

View file

@ -608,7 +608,7 @@ bool Core::Entity::Player::loadInventory()
{ {
uint16_t storageId = res->getUInt16( 1 ); uint16_t storageId = res->getUInt16( 1 );
for( uint32_t i = 1; i <= 13; i++ ) for( uint32_t i = 1; i <= 14; i++ )
{ {
uint64_t uItemId = res->getUInt64( i + 1 ); uint64_t uItemId = res->getUInt64( i + 1 );
if( uItemId == 0 ) if( uItemId == 0 )

View file

@ -28,6 +28,8 @@ private:
{ {
m_data.mainWeapon = player.getModelMainWeapon(); m_data.mainWeapon = player.getModelMainWeapon();
m_data.offWeapon = player.getModelSubWeapon(); m_data.offWeapon = player.getModelSubWeapon();
m_data.classJobId = static_cast< uint8_t >( player.getClass() );
m_data.level = player.getLevel();
m_data.models[ Common::GearModelSlot::ModelHead ] = player.getModelForSlot( Common::GearModelSlot::ModelHead ); m_data.models[ Common::GearModelSlot::ModelHead ] = player.getModelForSlot( Common::GearModelSlot::ModelHead );
m_data.models[ Common::GearModelSlot::ModelBody ] = player.getModelForSlot( Common::GearModelSlot::ModelBody ); m_data.models[ Common::GearModelSlot::ModelBody ] = player.getModelForSlot( Common::GearModelSlot::ModelBody );
m_data.models[ Common::GearModelSlot::ModelHands ] = player.getModelForSlot( Common::GearModelSlot::ModelHands ); m_data.models[ Common::GearModelSlot::ModelHands ] = player.getModelForSlot( Common::GearModelSlot::ModelHands );