diff --git a/src/common/Network/CommonActorControl.h b/src/common/Network/CommonActorControl.h index c5a32413..d144e83c 100644 --- a/src/common/Network/CommonActorControl.h +++ b/src/common/Network/CommonActorControl.h @@ -372,7 +372,7 @@ namespace Sapphire::Network::ActorControl Timers = 0x1AB, - DyeItem = 0x1B5, + DyeItem = 0x1B0, // updated 5.21 RequestChocoboInventory = 0x1C4, diff --git a/src/common/Network/PacketDef/Ipcs.h b/src/common/Network/PacketDef/Ipcs.h index 8e9c9879..06b9e40a 100644 --- a/src/common/Network/PacketDef/Ipcs.h +++ b/src/common/Network/PacketDef/Ipcs.h @@ -289,11 +289,11 @@ namespace Sapphire::Network::Packets FinishLoadingHandler = 0x007D, // updated 5.21 - CFCommenceHandler = 0x006F, + CFCommenceHandler = 0x0201, // updated 5.21 - CFRegisterDuty = 0x0071, - CFRegisterRoulette = 0xFF72, + CFRegisterDuty = 0x00C4, // updated 5.21 + CFRegisterRoulette = 0x030F, // updated 5.21 PlayTimeHandler = 0x0276, // updated 5.1 LogoutHandler = 0x0365, // updated 5.21 CancelLogout = 0x008F, // updated 5.1 diff --git a/src/common/Network/PacketDef/Zone/ServerZoneDef.h b/src/common/Network/PacketDef/Zone/ServerZoneDef.h index 5e4c2db2..5ac08ff6 100644 --- a/src/common/Network/PacketDef/Zone/ServerZoneDef.h +++ b/src/common/Network/PacketDef/Zone/ServerZoneDef.h @@ -1201,7 +1201,8 @@ namespace Sapphire::Network::Packets::Server uint32_t appearanceCatalogId; uint64_t crafterId; uint8_t quality; - uint8_t unknown[3]; + uint8_t stain; + uint8_t unknown[2]; struct Materia { uint16_t materiaId; diff --git a/src/scripts/action/common/ActionDye2472.cpp b/src/scripts/action/common/ActionDye2472.cpp new file mode 100644 index 00000000..b1049a8d --- /dev/null +++ b/src/scripts/action/common/ActionDye2472.cpp @@ -0,0 +1,27 @@ +#include +#include +#include +#include + +class ActionDye2472 : + public Sapphire::ScriptAPI::ActionScript +{ +public: + ActionDye2472() : + Sapphire::ScriptAPI::ActionScript( 2472 ) + { + } + + void onExecute( Sapphire::World::Action::Action& action ) override + { + auto sourceChara = action.getSourceChara(); + + if( !sourceChara->isPlayer() ) + return; + + //TODO: Effect + sourceChara->getAsPlayer()->dyeItemFromDyeingInfo(); + } +}; + +EXPOSE_SCRIPT(ActionDye2472); \ No newline at end of file diff --git a/src/world/Actor/Player.cpp b/src/world/Actor/Player.cpp index 8559955a..b88873b5 100644 --- a/src/world/Actor/Player.cpp +++ b/src/world/Actor/Player.cpp @@ -1961,6 +1961,36 @@ uint8_t Sapphire::Entity::Player::getNextObjSpawnIndexForActorId( uint32_t actor return index; } +void Sapphire::Entity::Player::setDyeingInfo( uint32_t itemToDyeContainer, uint32_t itemToDyeSlot, uint32_t dyeBagContainer, uint32_t dyeBagSlot ) +{ + m_dyeingInfo.itemToDyeContainer = itemToDyeContainer; + m_dyeingInfo.itemToDyeSlot = itemToDyeSlot; + m_dyeingInfo.dyeBagContainer = dyeBagContainer; + m_dyeingInfo.dyeBagSlot = dyeBagSlot; +} + +void Sapphire::Entity::Player::dyeItemFromDyeingInfo() +{ + uint32_t itemToDyeContainer = m_dyeingInfo.itemToDyeContainer; + uint32_t itemToDyeSlot = m_dyeingInfo.itemToDyeSlot; + uint32_t dyeBagContainer = m_dyeingInfo.dyeBagContainer; + uint32_t dyeBagSlot = m_dyeingInfo.dyeBagSlot; + + sendStateFlags(); // Retail sends all 0s to unlock player after a dye? Possibly not setting a flag when the action is started in the backend..? + auto itemToDye = getItemAt( itemToDyeContainer, itemToDyeSlot ); + auto dyeToUse = getItemAt( dyeBagContainer, dyeBagSlot ); + + if ( !itemToDye || !dyeToUse ) return; + + uint32_t stainColorID = dyeToUse->getAdditionalData(); + itemToDye->setStain( stainColorID ); + + // TODO: subtract/remove dye used + + insertInventoryItem( static_cast< Sapphire::Common::InventoryType >( itemToDyeContainer ), static_cast< uint16_t >( itemToDyeSlot ), itemToDye ); + writeItem( itemToDye ); +} + void Sapphire::Entity::Player::resetObjSpawnIndex() { m_objSpawnIndexAllocator.freeAllSpawnIndexes(); diff --git a/src/world/Actor/Player.h b/src/world/Actor/Player.h index 003c85d0..cd8fb307 100644 --- a/src/world/Actor/Player.h +++ b/src/world/Actor/Player.h @@ -536,6 +536,9 @@ namespace Sapphire::Entity void clearTeleportQuery(); + void setDyeingInfo( uint32_t itemToDyeContainer, uint32_t itemToDyeSlot, uint32_t dyeBagContainer, uint32_t dyeBagSlot ); + void dyeItemFromDyeingInfo(); + /*! prepares zoning / fades out the screen */ void prepareZoning( uint16_t targetZone, bool fadeOut, uint8_t fadeOutTime = 0, uint16_t animation = 0 ); @@ -1114,6 +1117,14 @@ namespace Sapphire::Entity Common::PlayerTeleportQuery m_teleportQuery; + struct PlayerDyeingInfo + { + uint32_t itemToDyeContainer; + uint32_t itemToDyeSlot; + uint32_t dyeBagContainer; + uint32_t dyeBagSlot; + } m_dyeingInfo; + Common::Util::SpawnIndexAllocator< uint8_t > m_objSpawnIndexAllocator; Common::Util::SpawnIndexAllocator< uint8_t > m_actorSpawnIndexAllocator; diff --git a/src/world/Network/Handlers/ClientTriggerHandler.cpp b/src/world/Network/Handlers/ClientTriggerHandler.cpp index e8ca0481..a1dd3815 100644 --- a/src/world/Network/Handlers/ClientTriggerHandler.cpp +++ b/src/world/Network/Handlers/ClientTriggerHandler.cpp @@ -282,6 +282,7 @@ void Sapphire::Network::GameConnection::clientTriggerHandler( const Packets::FFX // param12 = item to dye slot // param2 = dye bag container // param4 = dye bag slot + player.setDyeingInfo( param11, param12, param2, param4 ); break; } case ClientTriggerType::DirectorInitFinish: // Director init finish diff --git a/src/world/Network/PacketWrappers/ExaminePacket.h b/src/world/Network/PacketWrappers/ExaminePacket.h index 37baee37..55b16c56 100644 --- a/src/world/Network/PacketWrappers/ExaminePacket.h +++ b/src/world/Network/PacketWrappers/ExaminePacket.h @@ -74,6 +74,7 @@ namespace Sapphire::Network::Packets::Server auto& entry = m_data.entries[i]; entry.catalogId = pItem->getId(); entry.quality = pItem->isHq(); + entry.stain = static_cast< uint8_t >( pItem->getStain() ); //entry.appearanceCatalogId = pItem->getGlamourId() // todo: glamour/materia etc. } diff --git a/src/world/Network/PacketWrappers/UpdateInventorySlotPacket.h b/src/world/Network/PacketWrappers/UpdateInventorySlotPacket.h index 3c6e8c1c..c16042d2 100644 --- a/src/world/Network/PacketWrappers/UpdateInventorySlotPacket.h +++ b/src/world/Network/PacketWrappers/UpdateInventorySlotPacket.h @@ -34,7 +34,7 @@ namespace Sapphire::Network::Packets::Server m_data.hqFlag = item.isHq() ? 1 : 0; m_data.condition = 60000; // 200% m_data.spiritBond = item.getSpiritbond(); - m_data.color = 0; + m_data.color = item.getStain(); m_data.glamourCatalogId = 0; m_data.materia1 = 0; m_data.materia2 = 0;