From bf65499e615215c86d6126750a27bce7ec92bc84 Mon Sep 17 00:00:00 2001 From: Arazati <35294320+Arazati@users.noreply.github.com> Date: Fri, 13 Mar 2020 01:59:50 -0700 Subject: [PATCH 1/4] updated opcodes -collette Was sending the player to a solo duty when trying to Examine --- src/common/Network/PacketDef/Ipcs.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/common/Network/PacketDef/Ipcs.h b/src/common/Network/PacketDef/Ipcs.h index 19651f7b..d56cc38e 100644 --- a/src/common/Network/PacketDef/Ipcs.h +++ b/src/common/Network/PacketDef/Ipcs.h @@ -291,11 +291,11 @@ namespace Sapphire::Network::Packets FinishLoadingHandler = 0x01F5, // updated 5.18 - 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 = 0x015D, // updated 5.18 CancelLogout = 0x008F, // updated 5.1 From 4c75f1fd3252cac2f3564dfed4bdb34f64b5afa6 Mon Sep 17 00:00:00 2001 From: Arazati <35294320+Arazati@users.noreply.github.com> Date: Sat, 14 Mar 2020 00:31:14 -0700 Subject: [PATCH 2/4] implement dyeing items + show dyes in examine --- src/common/Network/CommonActorControl.h | 2 +- .../Network/PacketDef/Zone/ServerZoneDef.h | 3 +- src/scripts/action/common/ActionDye2472.cpp | 27 +++++++++++++++++ src/world/Actor/Player.cpp | 30 +++++++++++++++++++ src/world/Actor/Player.h | 11 +++++++ .../Network/Handlers/ClientTriggerHandler.cpp | 5 +--- .../Network/PacketWrappers/ExaminePacket.h | 1 + .../UpdateInventorySlotPacket.h | 2 +- 8 files changed, 74 insertions(+), 7 deletions(-) create mode 100644 src/scripts/action/common/ActionDye2472.cpp 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/Zone/ServerZoneDef.h b/src/common/Network/PacketDef/Zone/ServerZoneDef.h index 6e715282..e04cb1fe 100644 --- a/src/common/Network/PacketDef/Zone/ServerZoneDef.h +++ b/src/common/Network/PacketDef/Zone/ServerZoneDef.h @@ -1203,7 +1203,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 dc616600..5eee8372 100644 --- a/src/world/Actor/Player.cpp +++ b/src/world/Actor/Player.cpp @@ -1926,6 +1926,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((Sapphire::Common::InventoryType)itemToDyeContainer, (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 26984e17..65cd334f 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; + }; PlayerDyeingInfo 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 b6decf1b..e87be3c4 100644 --- a/src/world/Network/Handlers/ClientTriggerHandler.cpp +++ b/src/world/Network/Handlers/ClientTriggerHandler.cpp @@ -279,10 +279,7 @@ void Sapphire::Network::GameConnection::clientTriggerHandler( FrameworkPtr pFw, } case ClientTriggerType::DyeItem: // Dye item { - // param11 = item to dye container - // 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..a42b11ea 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 = (uint8_t)pItem->getStain(); //NOTE: More of this packet may be dye info? //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; From 02f1bd71c5525f12a0c00babffb7d590a61a5b8f Mon Sep 17 00:00:00 2001 From: Arazati <35294320+Arazati@users.noreply.github.com> Date: Mon, 16 Mar 2020 01:35:49 -0700 Subject: [PATCH 3/4] style + cast changes --- src/world/Actor/Player.cpp | 16 ++++++++-------- src/world/Actor/Player.h | 4 ++-- .../Network/Handlers/ClientTriggerHandler.cpp | 6 +++++- src/world/Network/PacketWrappers/ExaminePacket.h | 2 +- 4 files changed, 16 insertions(+), 12 deletions(-) diff --git a/src/world/Actor/Player.cpp b/src/world/Actor/Player.cpp index 5eee8372..e98f8008 100644 --- a/src/world/Actor/Player.cpp +++ b/src/world/Actor/Player.cpp @@ -1926,7 +1926,7 @@ 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) +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; @@ -1942,18 +1942,18 @@ void Sapphire::Entity::Player::dyeItemFromDyeingInfo() 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); + auto itemToDye = getItemAt( itemToDyeContainer, itemToDyeSlot ); + auto dyeToUse = getItemAt( dyeBagContainer, dyeBagSlot ); - if (!itemToDye || !dyeToUse) return; + if ( !itemToDye || !dyeToUse ) return; uint32_t stainColorID = dyeToUse->getAdditionalData(); - itemToDye->setStain(stainColorID); + itemToDye->setStain( stainColorID ); - //TODO: subtract/remove dye used + // TODO: subtract/remove dye used - insertInventoryItem((Sapphire::Common::InventoryType)itemToDyeContainer, (uint16_t)itemToDyeSlot, itemToDye); - writeItem(itemToDye); + insertInventoryItem( static_cast < Sapphire::Common::InventoryType > ( itemToDyeContainer ), static_cast < uint16_t > ( itemToDyeSlot ), itemToDye ); + writeItem( itemToDye ); } void Sapphire::Entity::Player::resetObjSpawnIndex() diff --git a/src/world/Actor/Player.h b/src/world/Actor/Player.h index 65cd334f..f74f864b 100644 --- a/src/world/Actor/Player.h +++ b/src/world/Actor/Player.h @@ -536,7 +536,7 @@ namespace Sapphire::Entity void clearTeleportQuery(); - void setDyeingInfo(uint32_t itemToDyeContainer, uint32_t itemToDyeSlot, uint32_t dyeBagContainer, uint32_t dyeBagSlot); + void setDyeingInfo( uint32_t itemToDyeContainer, uint32_t itemToDyeSlot, uint32_t dyeBagContainer, uint32_t dyeBagSlot ); void dyeItemFromDyeingInfo(); /*! prepares zoning / fades out the screen */ @@ -1123,7 +1123,7 @@ namespace Sapphire::Entity uint32_t itemToDyeSlot; uint32_t dyeBagContainer; uint32_t dyeBagSlot; - }; PlayerDyeingInfo m_dyeingInfo; + } 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 e87be3c4..d0d56ccc 100644 --- a/src/world/Network/Handlers/ClientTriggerHandler.cpp +++ b/src/world/Network/Handlers/ClientTriggerHandler.cpp @@ -279,7 +279,11 @@ void Sapphire::Network::GameConnection::clientTriggerHandler( FrameworkPtr pFw, } case ClientTriggerType::DyeItem: // Dye item { - player.setDyeingInfo(param11, param12, param2, param4); + // param11 = item to dye container + // 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 a42b11ea..13f54726 100644 --- a/src/world/Network/PacketWrappers/ExaminePacket.h +++ b/src/world/Network/PacketWrappers/ExaminePacket.h @@ -74,7 +74,7 @@ namespace Sapphire::Network::Packets::Server auto& entry = m_data.entries[i]; entry.catalogId = pItem->getId(); entry.quality = pItem->isHq(); - entry.stain = (uint8_t)pItem->getStain(); //NOTE: More of this packet may be dye info? + entry.stain = static_cast < uint8_t > ( pItem->getStain() ); //entry.appearanceCatalogId = pItem->getGlamourId() // todo: glamour/materia etc. } From 1496999358814042c568b5cdf153f7453a94656b Mon Sep 17 00:00:00 2001 From: Arazati <35294320+Arazati@users.noreply.github.com> Date: Mon, 16 Mar 2020 02:08:35 -0700 Subject: [PATCH 4/4] more style changes --- src/world/Actor/Player.cpp | 2 +- src/world/Network/PacketWrappers/ExaminePacket.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/world/Actor/Player.cpp b/src/world/Actor/Player.cpp index e98f8008..274f336f 100644 --- a/src/world/Actor/Player.cpp +++ b/src/world/Actor/Player.cpp @@ -1952,7 +1952,7 @@ void Sapphire::Entity::Player::dyeItemFromDyeingInfo() // TODO: subtract/remove dye used - insertInventoryItem( static_cast < Sapphire::Common::InventoryType > ( itemToDyeContainer ), static_cast < uint16_t > ( itemToDyeSlot ), itemToDye ); + insertInventoryItem( static_cast< Sapphire::Common::InventoryType >( itemToDyeContainer ), static_cast< uint16_t >( itemToDyeSlot ), itemToDye ); writeItem( itemToDye ); } diff --git a/src/world/Network/PacketWrappers/ExaminePacket.h b/src/world/Network/PacketWrappers/ExaminePacket.h index 13f54726..55b16c56 100644 --- a/src/world/Network/PacketWrappers/ExaminePacket.h +++ b/src/world/Network/PacketWrappers/ExaminePacket.h @@ -74,7 +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.stain = static_cast< uint8_t >( pItem->getStain() ); //entry.appearanceCatalogId = pItem->getGlamourId() // todo: glamour/materia etc. }