From 4428ad3033a25ea92c45c6f37c68cc102f0c68b6 Mon Sep 17 00:00:00 2001 From: amibu Date: Tue, 17 Oct 2017 20:13:01 +0200 Subject: [PATCH 1/9] Ported beautiful packet printing from classic --- .../Server_Common/Network/GamePacket.cpp | 14 +--- src/servers/Server_Common/Util/Util.cpp | 65 ++++++++++++++++++- src/servers/Server_Common/Util/Util.h | 2 + .../Server_Zone/Network/GameConnection.cpp | 2 +- 4 files changed, 68 insertions(+), 15 deletions(-) diff --git a/src/servers/Server_Common/Network/GamePacket.cpp b/src/servers/Server_Common/Network/GamePacket.cpp index f468e90d..e820c85e 100644 --- a/src/servers/Server_Common/Network/GamePacket.cpp +++ b/src/servers/Server_Common/Network/GamePacket.cpp @@ -5,6 +5,7 @@ #include #include #include +#include "Server_Common/Util/Util.h" Core::Network::Packets::GamePacket::GamePacket( uint16_t subType, uint16_t size, uint32_t id1, uint32_t id2, uint16_t type ) { @@ -97,16 +98,5 @@ void Core::Network::Packets::GamePacket::savePacket() std::string Core::Network::Packets::GamePacket::toString() const { - - std::string str = "\n"; - for( uint32_t i = 0; i < getSize(); i++ ) - { - str += boost::str( boost::format( "%|02X|" ) % ( int32_t ) ( m_dataBuf[i] & 0xFF ) ) + " "; - - if( ( i + 1 ) % 16 == 0 ) - str += "\n"; - } - str += "\n"; - - return str; + return Core::Util::binaryToHexDump( const_cast(&m_dataBuf[0]), getSize() ); } diff --git a/src/servers/Server_Common/Util/Util.cpp b/src/servers/Server_Common/Util/Util.cpp index 60903c30..1a505a73 100644 --- a/src/servers/Server_Common/Util/Util.cpp +++ b/src/servers/Server_Common/Util/Util.cpp @@ -1,9 +1,9 @@ #include "Util.h" #include +#include -std::string Core::Util::binaryToHexString( uint8_t* pBinData, uint16_t size ) +std::string Core::Util::binaryToHexString(uint8_t* pBinData, uint16_t size) { - std::string outStr; for( uint32_t i = 0; i < size; i++ ) @@ -15,6 +15,67 @@ std::string Core::Util::binaryToHexString( uint8_t* pBinData, uint16_t size ) } +std::string Core::Util::binaryToHexDump( uint8_t* pBinData, uint16_t size ) +{ + int bytesPerLine = 16; + std::string hexChars = "0123456789ABCDEF"; + + int offsetBlock = 8 + 3; + int byteBlock = offsetBlock + bytesPerLine * 3 + ( bytesPerLine - 1 ) / 8 + 2; + int lineLength = byteBlock + bytesPerLine + 1; + + std::string line ( lineLength, ' ' ); + int numLines = ( size + bytesPerLine - 1 ) / bytesPerLine; + + + std::string outStr; + + for( uint32_t i = 0; i < size; i += bytesPerLine ) + { + line[0] = hexChars[( i >> 28 ) & 0xF]; + line[1] = hexChars[( i >> 24 ) & 0xF]; + line[2] = hexChars[( i >> 20 ) & 0xF]; + line[3] = hexChars[( i >> 16 ) & 0xF]; + line[4] = hexChars[( i >> 12 ) & 0xF]; + line[5] = hexChars[( i >> 8 ) & 0xF]; + line[6] = hexChars[( i >> 4 ) & 0xF]; + line[7] = hexChars[( i >> 0 ) & 0xF]; + + int hexColumn = offsetBlock; + int charColumn = byteBlock; + + for( int j = 0; j < bytesPerLine; j++ ) + { + if( j > 0 && ( j & 7 ) == 0) + { + hexColumn++; + } + + if( i + j >= size ) + { + line[hexColumn] = ' '; + line[hexColumn + 1] = ' '; + line[charColumn] = ' '; + } + else + { + uint8_t by = pBinData[i + j]; + line[hexColumn] = hexChars[( by >> 4 ) & 0xF]; + line[hexColumn + 1] = hexChars[by & 0xF]; + line[charColumn] = by < 32 ? '.' : static_cast(by); + } + + hexColumn += 3; + charColumn++; + } + + outStr += line + "\n"; + } + + return outStr; + +} + uint64_t Core::Util::getTimeMs() { std::chrono::milliseconds epoch = std::chrono::duration_cast< std::chrono::milliseconds >(std::chrono::system_clock::now().time_since_epoch()); diff --git a/src/servers/Server_Common/Util/Util.h b/src/servers/Server_Common/Util/Util.h index 306b3d94..787d64a8 100644 --- a/src/servers/Server_Common/Util/Util.h +++ b/src/servers/Server_Common/Util/Util.h @@ -9,6 +9,8 @@ namespace Util { std::string binaryToHexString( uint8_t* pBinData, uint16_t size ); +std::string binaryToHexDump(uint8_t* pBinData, uint16_t size); + uint64_t getTimeMs(); uint64_t getTimeSeconds(); diff --git a/src/servers/Server_Zone/Network/GameConnection.cpp b/src/servers/Server_Zone/Network/GameConnection.cpp index a89d1bfe..a9ce9353 100644 --- a/src/servers/Server_Zone/Network/GameConnection.cpp +++ b/src/servers/Server_Zone/Network/GameConnection.cpp @@ -206,7 +206,7 @@ void Core::Network::GameConnection::handleZonePacket( const Packets::GamePacket& g_log.debug( sessionStr + " Undefined Zone IPC : Unknown ( " + boost::str( boost::format( "%|04X|" ) % static_cast< uint32_t >( pPacket.getSubType() & 0xFFFF ) ) + " )" ); - g_log.debug( pPacket.toString() ); + g_log.debug( "\n" + pPacket.toString() ); } } From e8c2fc81a5d16bdb87f4e3481b71b4440db2f16c Mon Sep 17 00:00:00 2001 From: amibu Date: Tue, 17 Oct 2017 21:31:00 +0200 Subject: [PATCH 2/9] Base for mounts, needs to be in a ActionCast; --- src/servers/Server_Common/Common.h | 9 ++++- .../Server_Common/Network/GamePacket.cpp | 2 +- .../Server_Common/Network/PacketDef/Ipcs.h | 1 + .../Network/PacketDef/Zone/ServerZoneDef.h | 9 +++++ src/servers/Server_Zone/Actor/Player.cpp | 7 ++++ src/servers/Server_Zone/Actor/Player.h | 2 + .../Network/Handlers/SkillHandler.cpp | 37 +++++++++++++++++++ .../Network/PacketWrappers/InitUIPacket.h | 3 ++ 8 files changed, 68 insertions(+), 2 deletions(-) diff --git a/src/servers/Server_Common/Common.h b/src/servers/Server_Common/Common.h index f5b72fd6..2c584f18 100644 --- a/src/servers/Server_Common/Common.h +++ b/src/servers/Server_Common/Common.h @@ -602,7 +602,8 @@ namespace Core { MpGain = 11, TpLoss = 12, TpGain = 13, - GpGain = 14 + GpGain = 14, + Mount = 38 }; enum class ActionHitSeverityType : uint8_t @@ -1068,6 +1069,12 @@ namespace Core { Visor = 0x40, }; + enum SkillType : uint8_t + { + Normal = 0x1, + MountSkill = 0xD, + }; + struct ServerEntry { uint32_t serverId; diff --git a/src/servers/Server_Common/Network/GamePacket.cpp b/src/servers/Server_Common/Network/GamePacket.cpp index e820c85e..a9e54877 100644 --- a/src/servers/Server_Common/Network/GamePacket.cpp +++ b/src/servers/Server_Common/Network/GamePacket.cpp @@ -98,5 +98,5 @@ void Core::Network::Packets::GamePacket::savePacket() std::string Core::Network::Packets::GamePacket::toString() const { - return Core::Util::binaryToHexDump( const_cast(&m_dataBuf[0]), getSize() ); + return Core::Util::binaryToHexString( const_cast(&m_dataBuf[0]), getSize() ); } diff --git a/src/servers/Server_Common/Network/PacketDef/Ipcs.h b/src/servers/Server_Common/Network/PacketDef/Ipcs.h index bf479ec8..eefd987a 100644 --- a/src/servers/Server_Common/Network/PacketDef/Ipcs.h +++ b/src/servers/Server_Common/Network/PacketDef/Ipcs.h @@ -116,6 +116,7 @@ namespace Packets { ActorSpawn = 0x0190, // todo: split into playerspawn/actorspawn and use opcode 0x110/0x111 ActorFreeSpawn = 0x0191, // unchanged for sb InitZone = 0x019A, // unchanged for sb + Mount = 0x019F, // unchanged for sb WeatherChange = 0x01AF, // updated for sb PlayerTitleList = 0x01BD, // updated for 4.1 Discovery = 0x01BE, // updated for 4.1 diff --git a/src/servers/Server_Common/Network/PacketDef/Zone/ServerZoneDef.h b/src/servers/Server_Common/Network/PacketDef/Zone/ServerZoneDef.h index 142975b4..66d4d54a 100644 --- a/src/servers/Server_Common/Network/PacketDef/Zone/ServerZoneDef.h +++ b/src/servers/Server_Common/Network/PacketDef/Zone/ServerZoneDef.h @@ -1303,6 +1303,15 @@ struct FFXIVIpcEquipDisplayFlags : FFXIVIpcBasePacket uint8_t bitmask; }; +/** +* Structural representation of the packet sent by the server +* to mount a player +*/ +struct FFXIVIpcMount : FFXIVIpcBasePacket +{ + uint32_t id; +}; + } /* Server */ } /* Packets */ diff --git a/src/servers/Server_Zone/Actor/Player.cpp b/src/servers/Server_Zone/Actor/Player.cpp index 0199f3ca..816e0edd 100644 --- a/src/servers/Server_Zone/Actor/Player.cpp +++ b/src/servers/Server_Zone/Actor/Player.cpp @@ -1486,6 +1486,13 @@ uint8_t Core::Entity::Player::getEquipDisplayFlags() const return m_equipDisplayFlags; } +void Core::Entity::Player::mount( uint32_t id ) +{ + GamePacketNew< FFXIVIpcMount, ServerZoneIpcType > mountPacket( getId() ); + mountPacket.data().id = id; + sendToInRangeSet(mountPacket, true ); +} + void Core::Entity::Player::autoAttack( ActorPtr pTarget ) { diff --git a/src/servers/Server_Zone/Actor/Player.h b/src/servers/Server_Zone/Actor/Player.h index 488065df..f9d471ea 100644 --- a/src/servers/Server_Zone/Actor/Player.h +++ b/src/servers/Server_Zone/Actor/Player.h @@ -340,6 +340,8 @@ public: void setEquipDisplayFlags( uint8_t state ); /*! get gear param state and send update to inRangeSet */ uint8_t getEquipDisplayFlags() const; + /*! mount the specified mount and send the packet */ + void mount( uint32_t id ); void calculateStats() override; void sendStats(); diff --git a/src/servers/Server_Zone/Network/Handlers/SkillHandler.cpp b/src/servers/Server_Zone/Network/Handlers/SkillHandler.cpp index 457aa855..f2e46f51 100644 --- a/src/servers/Server_Zone/Network/Handlers/SkillHandler.cpp +++ b/src/servers/Server_Zone/Network/Handlers/SkillHandler.cpp @@ -28,6 +28,7 @@ #include "src/servers/Server_Zone/Action/ActionTeleport.h" #include "src/servers/Server_Zone/Action/ActionCast.h" #include "src/servers/Server_Zone/Script/ScriptManager.h" +#include "Server_Zone/Network/PacketWrappers/MoveActorPacket.h" extern Core::Scripting::ScriptManager g_scriptMgr; @@ -42,11 +43,21 @@ void Core::Network::GameConnection::skillHandler( const Packets::GamePacket& inP Entity::PlayerPtr pPlayer ) { + g_log.debug( inPacket.toString() ); + + uint8_t type = inPacket.getValAt< uint32_t >( 0x21 ); + uint32_t action = inPacket.getValAt< uint32_t >( 0x24 ); uint32_t useCount = inPacket.getValAt< uint32_t >( 0x28 ); uint64_t targetId = inPacket.getValAt< uint64_t >( 0x30 ); + pPlayer->sendDebug( "Skill type:" + std::to_string( type ) ); + + switch( type ) + { + case Common::SkillType::Normal: + if( action < 1000000 ) // normal action { std::string actionIdStr = boost::str( boost::format( "%|04X|" ) % action ); @@ -104,4 +115,30 @@ void Core::Network::GameConnection::skillHandler( const Packets::GamePacket& inP } + break; + + case Common::SkillType::MountSkill: + + pPlayer->sendDebug( "Request mount " + std::to_string( action ) ); + + GamePacketNew< FFXIVIpcEffect, ServerZoneIpcType > effectPacket(pPlayer->getId()); + effectPacket.data().targetId = pPlayer->getId(); + effectPacket.data().actionAnimationId = action; + effectPacket.data().unknown_62 = 13; // Affects displaying action name next to number in floating text + effectPacket.data().actionTextId = 4; + effectPacket.data().numEffects = 1; + effectPacket.data().rotation = Math::Util::floatToUInt16Rot(pPlayer->getRotation()); + effectPacket.data().effectTarget = INVALID_GAME_OBJECT_ID; + effectPacket.data().effects[0].effectType = ActionEffectType::Mount; + effectPacket.data().effects[0].hitSeverity = ActionHitSeverityType::CritDamage; + effectPacket.data().effects[0].value = action; + + pPlayer->mount( action ); + pPlayer->sendToInRangeSet( effectPacket, true ); + + + break; + + } + } \ No newline at end of file diff --git a/src/servers/Server_Zone/Network/PacketWrappers/InitUIPacket.h b/src/servers/Server_Zone/Network/PacketWrappers/InitUIPacket.h index 60b69f1d..19c0f8d2 100644 --- a/src/servers/Server_Zone/Network/PacketWrappers/InitUIPacket.h +++ b/src/servers/Server_Zone/Network/PacketWrappers/InitUIPacket.h @@ -64,6 +64,9 @@ private: memcpy( m_data.orchestrionMask, player->getOrchestrionBitmask(), sizeof( m_data.orchestrionMask ) ); + memset( m_data.mountGuideMask, 0xFF, sizeof( m_data.mountGuideMask) ); + memset(m_data.fishingGuideMask, 0xFF, sizeof(m_data.fishingGuideMask)); + memcpy( m_data.unlockBitmask, player->getUnlockBitmask(), sizeof( m_data.unlockBitmask ) ); memcpy( m_data.discovery, player->getDiscoveryBitmask(), sizeof( m_data.discovery ) ); From fbae114aa02519c505d623d89c6df56ae7c06fe2 Mon Sep 17 00:00:00 2001 From: amibu Date: Tue, 17 Oct 2017 22:49:33 +0200 Subject: [PATCH 3/9] Cleanup --- src/servers/Server_Common/Network/GamePacket.cpp | 2 +- src/servers/Server_Common/Util/Util.cpp | 4 ++-- src/servers/Server_Zone/Network/Handlers/SkillHandler.cpp | 3 --- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/src/servers/Server_Common/Network/GamePacket.cpp b/src/servers/Server_Common/Network/GamePacket.cpp index a9e54877..c67f4fb6 100644 --- a/src/servers/Server_Common/Network/GamePacket.cpp +++ b/src/servers/Server_Common/Network/GamePacket.cpp @@ -98,5 +98,5 @@ void Core::Network::Packets::GamePacket::savePacket() std::string Core::Network::Packets::GamePacket::toString() const { - return Core::Util::binaryToHexString( const_cast(&m_dataBuf[0]), getSize() ); + return Core::Util::binaryToHexDump( const_cast( &m_dataBuf[0] ), getSize() ); } diff --git a/src/servers/Server_Common/Util/Util.cpp b/src/servers/Server_Common/Util/Util.cpp index 1a505a73..4e0aff5a 100644 --- a/src/servers/Server_Common/Util/Util.cpp +++ b/src/servers/Server_Common/Util/Util.cpp @@ -18,7 +18,7 @@ std::string Core::Util::binaryToHexString(uint8_t* pBinData, uint16_t size) std::string Core::Util::binaryToHexDump( uint8_t* pBinData, uint16_t size ) { int bytesPerLine = 16; - std::string hexChars = "0123456789ABCDEF"; + constexpr char hexChars[] = "0123456789ABCDEF"; int offsetBlock = 8 + 3; int byteBlock = offsetBlock + bytesPerLine * 3 + ( bytesPerLine - 1 ) / 8 + 2; @@ -62,7 +62,7 @@ std::string Core::Util::binaryToHexDump( uint8_t* pBinData, uint16_t size ) uint8_t by = pBinData[i + j]; line[hexColumn] = hexChars[( by >> 4 ) & 0xF]; line[hexColumn + 1] = hexChars[by & 0xF]; - line[charColumn] = by < 32 ? '.' : static_cast(by); + line[charColumn] = by < 32 ? '.' : static_cast( by ); } hexColumn += 3; diff --git a/src/servers/Server_Zone/Network/Handlers/SkillHandler.cpp b/src/servers/Server_Zone/Network/Handlers/SkillHandler.cpp index f2e46f51..e52948ff 100644 --- a/src/servers/Server_Zone/Network/Handlers/SkillHandler.cpp +++ b/src/servers/Server_Zone/Network/Handlers/SkillHandler.cpp @@ -42,9 +42,6 @@ using namespace Core::Network::Packets::Server; void Core::Network::GameConnection::skillHandler( const Packets::GamePacket& inPacket, Entity::PlayerPtr pPlayer ) { - - g_log.debug( inPacket.toString() ); - uint8_t type = inPacket.getValAt< uint32_t >( 0x21 ); uint32_t action = inPacket.getValAt< uint32_t >( 0x24 ); From dfde3ed8204939e90b44c56211a8c036670f2755 Mon Sep 17 00:00:00 2001 From: amibu Date: Tue, 17 Oct 2017 22:52:12 +0200 Subject: [PATCH 4/9] Formatting --- src/servers/Server_Common/Util/Util.cpp | 2 +- src/servers/Server_Common/Util/Util.h | 2 +- src/servers/Server_Zone/Actor/Player.cpp | 2 +- src/servers/Server_Zone/Network/PacketWrappers/InitUIPacket.h | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/servers/Server_Common/Util/Util.cpp b/src/servers/Server_Common/Util/Util.cpp index 4e0aff5a..99d5ceda 100644 --- a/src/servers/Server_Common/Util/Util.cpp +++ b/src/servers/Server_Common/Util/Util.cpp @@ -2,7 +2,7 @@ #include #include -std::string Core::Util::binaryToHexString(uint8_t* pBinData, uint16_t size) +std::string Core::Util::binaryToHexString( uint8_t* pBinData, uint16_t size ) { std::string outStr; diff --git a/src/servers/Server_Common/Util/Util.h b/src/servers/Server_Common/Util/Util.h index 787d64a8..2c38f55f 100644 --- a/src/servers/Server_Common/Util/Util.h +++ b/src/servers/Server_Common/Util/Util.h @@ -9,7 +9,7 @@ namespace Util { std::string binaryToHexString( uint8_t* pBinData, uint16_t size ); -std::string binaryToHexDump(uint8_t* pBinData, uint16_t size); +std::string binaryToHexDump( uint8_t* pBinData, uint16_t size ); uint64_t getTimeMs(); diff --git a/src/servers/Server_Zone/Actor/Player.cpp b/src/servers/Server_Zone/Actor/Player.cpp index 816e0edd..f9eca5b8 100644 --- a/src/servers/Server_Zone/Actor/Player.cpp +++ b/src/servers/Server_Zone/Actor/Player.cpp @@ -1490,7 +1490,7 @@ void Core::Entity::Player::mount( uint32_t id ) { GamePacketNew< FFXIVIpcMount, ServerZoneIpcType > mountPacket( getId() ); mountPacket.data().id = id; - sendToInRangeSet(mountPacket, true ); + sendToInRangeSet( mountPacket, true ); } void Core::Entity::Player::autoAttack( ActorPtr pTarget ) diff --git a/src/servers/Server_Zone/Network/PacketWrappers/InitUIPacket.h b/src/servers/Server_Zone/Network/PacketWrappers/InitUIPacket.h index 19c0f8d2..ab88e67b 100644 --- a/src/servers/Server_Zone/Network/PacketWrappers/InitUIPacket.h +++ b/src/servers/Server_Zone/Network/PacketWrappers/InitUIPacket.h @@ -65,7 +65,7 @@ private: memcpy( m_data.orchestrionMask, player->getOrchestrionBitmask(), sizeof( m_data.orchestrionMask ) ); memset( m_data.mountGuideMask, 0xFF, sizeof( m_data.mountGuideMask) ); - memset(m_data.fishingGuideMask, 0xFF, sizeof(m_data.fishingGuideMask)); + memset( m_data.fishingGuideMask, 0xFF, sizeof(m_data.fishingGuideMask) ); memcpy( m_data.unlockBitmask, player->getUnlockBitmask(), sizeof( m_data.unlockBitmask ) ); From 30aa9fe211c595b191294027d0ed2686be4ecd7e Mon Sep 17 00:00:00 2001 From: amibu Date: Tue, 17 Oct 2017 23:03:47 +0200 Subject: [PATCH 5/9] Replicating retail packet flow for testing --- src/servers/Server_Zone/Network/Handlers/ActionHandler.cpp | 5 +++++ src/servers/Server_Zone/Network/Handlers/SkillHandler.cpp | 5 +++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/servers/Server_Zone/Network/Handlers/ActionHandler.cpp b/src/servers/Server_Zone/Network/Handlers/ActionHandler.cpp index 0b30d71d..65815e95 100644 --- a/src/servers/Server_Zone/Network/Handlers/ActionHandler.cpp +++ b/src/servers/Server_Zone/Network/Handlers/ActionHandler.cpp @@ -106,6 +106,11 @@ void Core::Network::GameConnection::actionHandler( const Packets::GamePacket& in pPlayer->changeTarget( targetId ); break; } + case 0x65: + { + pPlayer->sendToInRangeSet( ActorControlPacket142(pPlayer->getId(), ActorControlType::SetStatus, 1 ), true ); //? + pPlayer->sendToInRangeSet( ActorControlPacket143( pPlayer->getId(), 0x393, 1 ), true ); //? + } case 0x68: // Remove status (clicking it off) { // todo: check if status can be removed by client from exd diff --git a/src/servers/Server_Zone/Network/Handlers/SkillHandler.cpp b/src/servers/Server_Zone/Network/Handlers/SkillHandler.cpp index e52948ff..e9405b02 100644 --- a/src/servers/Server_Zone/Network/Handlers/SkillHandler.cpp +++ b/src/servers/Server_Zone/Network/Handlers/SkillHandler.cpp @@ -130,10 +130,11 @@ void Core::Network::GameConnection::skillHandler( const Packets::GamePacket& inP effectPacket.data().effects[0].hitSeverity = ActionHitSeverityType::CritDamage; effectPacket.data().effects[0].value = action; + pPlayer->sendToInRangeSet( ActorControlPacket142( pPlayer->getId(), ActorControlType::SetStatus, 4 ), true ); //? + pPlayer->sendToInRangeSet( ActorControlPacket143( pPlayer->getId(), 0x39e, 12 ), true ); //? pPlayer->mount( action ); pPlayer->sendToInRangeSet( effectPacket, true ); - - + break; } From 240e06a63466f1fa153b3af145aeaaa4ac0448ff Mon Sep 17 00:00:00 2001 From: amibu Date: Wed, 18 Oct 2017 15:49:19 +0200 Subject: [PATCH 6/9] ActionMount; --- .../Network/PacketDef/Zone/ServerZoneDef.h | 3 +- src/servers/Server_Zone/Action/ActionCast.cpp | 2 +- .../Server_Zone/Action/ActionMount.cpp | 115 ++++++++++++++++++ src/servers/Server_Zone/Action/ActionMount.h | 28 +++++ src/servers/Server_Zone/Forwards.h | 1 + .../Network/Handlers/SkillHandler.cpp | 22 +--- 6 files changed, 152 insertions(+), 19 deletions(-) create mode 100644 src/servers/Server_Zone/Action/ActionMount.cpp create mode 100644 src/servers/Server_Zone/Action/ActionMount.h diff --git a/src/servers/Server_Common/Network/PacketDef/Zone/ServerZoneDef.h b/src/servers/Server_Common/Network/PacketDef/Zone/ServerZoneDef.h index 66d4d54a..77ee9682 100644 --- a/src/servers/Server_Common/Network/PacketDef/Zone/ServerZoneDef.h +++ b/src/servers/Server_Common/Network/PacketDef/Zone/ServerZoneDef.h @@ -604,7 +604,8 @@ struct FFXIVIpcActorSetPos : FFXIVIpcBasePacket struct FFXIVIpcActorCast : FFXIVIpcBasePacket { uint16_t action_id; - uint16_t unknown; + Common::SkillType skillType; + uint8_t unknown; uint32_t unknown_1; // Also action id float cast_time; uint32_t target_id; diff --git a/src/servers/Server_Zone/Action/ActionCast.cpp b/src/servers/Server_Zone/Action/ActionCast.cpp index a28125c7..c27b9db2 100644 --- a/src/servers/Server_Zone/Action/ActionCast.cpp +++ b/src/servers/Server_Zone/Action/ActionCast.cpp @@ -53,7 +53,7 @@ void Core::Action::ActionCast::onStart() GamePacketNew< FFXIVIpcActorCast, ServerZoneIpcType > castPacket( m_pSource->getId() ); castPacket.data().action_id = m_id; - castPacket.data().unknown = 1; + castPacket.data().skillType = Common::SkillType::Normal; castPacket.data().unknown_1 = m_id; castPacket.data().cast_time = static_cast< float >( m_castTime / 1000 ); // This is used for the cast bar above the target bar of the caster. castPacket.data().target_id = m_pTarget->getId(); diff --git a/src/servers/Server_Zone/Action/ActionMount.cpp b/src/servers/Server_Zone/Action/ActionMount.cpp new file mode 100644 index 00000000..f42c1ae5 --- /dev/null +++ b/src/servers/Server_Zone/Action/ActionMount.cpp @@ -0,0 +1,115 @@ +#include "ActionMount.h" + +#include +#include +#include +#include +#include + +#include "src/servers/Server_Zone/Network/PacketWrappers/ActorControlPacket142.h" +#include "src/servers/Server_Zone/Network/PacketWrappers/ActorControlPacket143.h" +#include "src/servers/Server_Zone/Network/PacketWrappers/ActorControlPacket144.h" +#include "src/servers/Server_Zone/Actor/Player.h" +#include "src/servers/Server_Zone/Script/ScriptManager.h" + +using namespace Core::Common; +using namespace Core::Network; +using namespace Core::Network::Packets; +using namespace Core::Network::Packets::Server; + +extern Core::Data::ExdData g_exdData; +extern Core::Logger g_log; +extern Core::Scripting::ScriptManager g_scriptMgr; + +Core::Action::ActionMount::ActionMount() +{ + m_handleActionType = Common::HandleActionType::Event; +} + +Core::Action::ActionMount::ActionMount( Entity::ActorPtr pActor, Entity::ActorPtr pTarget, uint32_t actionId ) +{ + m_startTime = 0; + m_id = actionId; + m_handleActionType = HandleActionType::Spell; + m_castTime = 1000; + m_pSource = pActor; + m_pTarget = pTarget; + m_bInterrupt = false; +} + +Core::Action::ActionMount::~ActionMount() +{ + +} + +void Core::Action::ActionMount::onStart() +{ + if( !m_pSource ) + return; + + m_pSource->getAsPlayer()->sendDebug( "ActionMount::onStart()" ); + m_startTime = Util::getTimeMs(); + + GamePacketNew< FFXIVIpcActorCast, ServerZoneIpcType > castPacket( m_pSource->getId() ); + + castPacket.data().action_id = m_id; + castPacket.data().skillType = Common::SkillType::MountSkill; + castPacket.data().unknown_1 = m_id; + castPacket.data().cast_time = static_cast< float >( m_castTime / 1000 ); // This is used for the cast bar above the target bar of the caster. + castPacket.data().target_id = m_pTarget->getId(); + + m_pSource->sendToInRangeSet( castPacket, true ); + m_pSource->getAsPlayer()->setStateFlag( PlayerStateFlag::Casting ); + m_pSource->getAsPlayer()->sendStateFlags(); + +} + +void Core::Action::ActionMount::onFinish() +{ + if( !m_pSource ) + return; + + auto pPlayer = m_pSource->getAsPlayer(); + pPlayer->sendDebug( "ActionMount::onFinish()" ); + + pPlayer->unsetStateFlag( PlayerStateFlag::Casting ); + pPlayer->sendStateFlags(); + + GamePacketNew< FFXIVIpcEffect, ServerZoneIpcType > effectPacket(pPlayer->getId()); + effectPacket.data().targetId = pPlayer->getId(); + effectPacket.data().actionAnimationId = m_id; + effectPacket.data().unknown_62 = 13; // Affects displaying action name next to number in floating text + effectPacket.data().actionTextId = 4; + effectPacket.data().numEffects = 1; + effectPacket.data().rotation = Math::Util::floatToUInt16Rot(pPlayer->getRotation()); + effectPacket.data().effectTarget = INVALID_GAME_OBJECT_ID; + effectPacket.data().effects[0].effectType = ActionEffectType::Mount; + effectPacket.data().effects[0].hitSeverity = ActionHitSeverityType::CritDamage; + effectPacket.data().effects[0].value = m_id; + + pPlayer->sendToInRangeSet(effectPacket, true); + + pPlayer->sendToInRangeSet(ActorControlPacket142(pPlayer->getId(), ActorControlType::SetStatus, 4), true); //? + pPlayer->sendToInRangeSet(ActorControlPacket143(pPlayer->getId(), 0x39e, 12), true); //? + + pPlayer->mount( m_id ); +} + +void Core::Action::ActionMount::onInterrupt() +{ + if( !m_pSource ) + return; + + m_pSource->getAsPlayer()->unsetStateFlag( PlayerStateFlag::Occupied1 ); + m_pSource->getAsPlayer()->unsetStateFlag( PlayerStateFlag::Casting ); + m_pSource->getAsPlayer()->sendStateFlags(); + + auto control = ActorControlPacket142( m_pSource->getId(), ActorControlType::CastInterrupt, + 0x219, 1, m_id, 0 ); + + // Note: When cast interrupt from taking too much damage, set the last value to 1. This enables the cast interrupt effect. Example: + // auto control = ActorControlPacket142( m_pSource->getId(), ActorControlType::CastInterrupt, 0x219, 1, m_id, 0 ); + + m_pSource->sendToInRangeSet( control, true ); + +} diff --git a/src/servers/Server_Zone/Action/ActionMount.h b/src/servers/Server_Zone/Action/ActionMount.h new file mode 100644 index 00000000..fe12bdd9 --- /dev/null +++ b/src/servers/Server_Zone/Action/ActionMount.h @@ -0,0 +1,28 @@ +#ifndef _ACTIONMOUNT_H_ +#define _ACTIONMOUNT_H_ + +#include "src/servers/Server_Zone/Forwards.h" +#include "Action.h" + +namespace Core { namespace Action { + + class ActionMount : public Action + { + private: + + public: + ActionMount(); + ~ActionMount(); + + ActionMount( Entity::ActorPtr pActor, Entity::ActorPtr pTarget, uint32_t actionId ); + + void onStart() override; + void onFinish() override; + void onInterrupt() override; + + }; + +} +} + +#endif \ No newline at end of file diff --git a/src/servers/Server_Zone/Forwards.h b/src/servers/Server_Zone/Forwards.h index c0f48782..2eaaa75e 100644 --- a/src/servers/Server_Zone/Forwards.h +++ b/src/servers/Server_Zone/Forwards.h @@ -44,6 +44,7 @@ namespace Core TYPE_FORWARD( Action ); TYPE_FORWARD( ActionTeleport ); TYPE_FORWARD( ActionCast ); + TYPE_FORWARD( ActionMount ); TYPE_FORWARD( EventAction ); } diff --git a/src/servers/Server_Zone/Network/Handlers/SkillHandler.cpp b/src/servers/Server_Zone/Network/Handlers/SkillHandler.cpp index e9405b02..e7a003ef 100644 --- a/src/servers/Server_Zone/Network/Handlers/SkillHandler.cpp +++ b/src/servers/Server_Zone/Network/Handlers/SkillHandler.cpp @@ -25,8 +25,8 @@ #include "src/servers/Server_Zone/Forwards.h" #include "src/servers/Server_Zone/Action/Action.h" -#include "src/servers/Server_Zone/Action/ActionTeleport.h" #include "src/servers/Server_Zone/Action/ActionCast.h" +#include "src/servers/Server_Zone/Action/ActionMount.h" #include "src/servers/Server_Zone/Script/ScriptManager.h" #include "Server_Zone/Network/PacketWrappers/MoveActorPacket.h" @@ -118,22 +118,10 @@ void Core::Network::GameConnection::skillHandler( const Packets::GamePacket& inP pPlayer->sendDebug( "Request mount " + std::to_string( action ) ); - GamePacketNew< FFXIVIpcEffect, ServerZoneIpcType > effectPacket(pPlayer->getId()); - effectPacket.data().targetId = pPlayer->getId(); - effectPacket.data().actionAnimationId = action; - effectPacket.data().unknown_62 = 13; // Affects displaying action name next to number in floating text - effectPacket.data().actionTextId = 4; - effectPacket.data().numEffects = 1; - effectPacket.data().rotation = Math::Util::floatToUInt16Rot(pPlayer->getRotation()); - effectPacket.data().effectTarget = INVALID_GAME_OBJECT_ID; - effectPacket.data().effects[0].effectType = ActionEffectType::Mount; - effectPacket.data().effects[0].hitSeverity = ActionHitSeverityType::CritDamage; - effectPacket.data().effects[0].value = action; - - pPlayer->sendToInRangeSet( ActorControlPacket142( pPlayer->getId(), ActorControlType::SetStatus, 4 ), true ); //? - pPlayer->sendToInRangeSet( ActorControlPacket143( pPlayer->getId(), 0x39e, 12 ), true ); //? - pPlayer->mount( action ); - pPlayer->sendToInRangeSet( effectPacket, true ); + Action::ActionMountPtr pActionMount(new Action::ActionMount(pPlayer, pPlayer, action)); + pPlayer->setCurrentAction(pActionMount); + pPlayer->sendDebug("setCurrentAction()"); + pPlayer->getCurrentAction()->onStart(); break; From 77717d29f345d29b231b1b3cbf30f27461cb7560 Mon Sep 17 00:00:00 2001 From: amibu Date: Wed, 18 Oct 2017 17:54:17 +0200 Subject: [PATCH 7/9] Cleanup, mount DB saving; --- src/servers/Server_Common/Common.h | 3 ++- .../Server_Zone/Action/ActionMount.cpp | 10 +++------- src/servers/Server_Zone/Action/ActionMount.h | 2 +- src/servers/Server_Zone/Actor/Player.cpp | 20 ++++++++++++++++++- src/servers/Server_Zone/Actor/Player.h | 8 ++++++-- src/servers/Server_Zone/Actor/PlayerSql.cpp | 7 ++++++- .../Network/Handlers/ActionHandler.cpp | 4 ++-- .../Network/Handlers/SkillHandler.cpp | 4 ++-- .../PacketWrappers/PlayerSpawnPacket.h | 2 ++ 9 files changed, 43 insertions(+), 17 deletions(-) diff --git a/src/servers/Server_Common/Common.h b/src/servers/Server_Common/Common.h index 2c584f18..1675c443 100644 --- a/src/servers/Server_Common/Common.h +++ b/src/servers/Server_Common/Common.h @@ -952,7 +952,8 @@ namespace Core { GearSetEquipMsg = 0x321, - ToggleOrchestrionUnlock = 0x396 + ToggleOrchestrionUnlock = 0x396, + Dismount = 0x3a0 }; enum struct ChatType : uint16_t diff --git a/src/servers/Server_Zone/Action/ActionMount.cpp b/src/servers/Server_Zone/Action/ActionMount.cpp index f42c1ae5..50462d19 100644 --- a/src/servers/Server_Zone/Action/ActionMount.cpp +++ b/src/servers/Server_Zone/Action/ActionMount.cpp @@ -26,14 +26,13 @@ Core::Action::ActionMount::ActionMount() m_handleActionType = Common::HandleActionType::Event; } -Core::Action::ActionMount::ActionMount( Entity::ActorPtr pActor, Entity::ActorPtr pTarget, uint32_t actionId ) +Core::Action::ActionMount::ActionMount( Entity::ActorPtr pActor, uint32_t mountId ) { m_startTime = 0; - m_id = actionId; + m_id = mountId; m_handleActionType = HandleActionType::Spell; m_castTime = 1000; m_pSource = pActor; - m_pTarget = pTarget; m_bInterrupt = false; } @@ -56,7 +55,7 @@ void Core::Action::ActionMount::onStart() castPacket.data().skillType = Common::SkillType::MountSkill; castPacket.data().unknown_1 = m_id; castPacket.data().cast_time = static_cast< float >( m_castTime / 1000 ); // This is used for the cast bar above the target bar of the caster. - castPacket.data().target_id = m_pTarget->getId(); + castPacket.data().target_id = m_pSource->getAsPlayer()->getId(); m_pSource->sendToInRangeSet( castPacket, true ); m_pSource->getAsPlayer()->setStateFlag( PlayerStateFlag::Casting ); @@ -89,9 +88,6 @@ void Core::Action::ActionMount::onFinish() pPlayer->sendToInRangeSet(effectPacket, true); - pPlayer->sendToInRangeSet(ActorControlPacket142(pPlayer->getId(), ActorControlType::SetStatus, 4), true); //? - pPlayer->sendToInRangeSet(ActorControlPacket143(pPlayer->getId(), 0x39e, 12), true); //? - pPlayer->mount( m_id ); } diff --git a/src/servers/Server_Zone/Action/ActionMount.h b/src/servers/Server_Zone/Action/ActionMount.h index fe12bdd9..cdd68e3d 100644 --- a/src/servers/Server_Zone/Action/ActionMount.h +++ b/src/servers/Server_Zone/Action/ActionMount.h @@ -14,7 +14,7 @@ namespace Core { namespace Action { ActionMount(); ~ActionMount(); - ActionMount( Entity::ActorPtr pActor, Entity::ActorPtr pTarget, uint32_t actionId ); + ActionMount( Entity::ActorPtr pActor, uint32_t mountId ); void onStart() override; void onFinish() override; diff --git a/src/servers/Server_Zone/Actor/Player.cpp b/src/servers/Server_Zone/Actor/Player.cpp index f9eca5b8..39d5d709 100644 --- a/src/servers/Server_Zone/Actor/Player.cpp +++ b/src/servers/Server_Zone/Actor/Player.cpp @@ -1488,9 +1488,27 @@ uint8_t Core::Entity::Player::getEquipDisplayFlags() const void Core::Entity::Player::mount( uint32_t id ) { + m_mount = id; + sendToInRangeSet( ActorControlPacket142( getId(), ActorControlType::SetStatus, static_cast< uint8_t >( Entity::Actor::ActorStatus::Mounted )), true ); + sendToInRangeSet( ActorControlPacket143( getId(), 0x39e, 12 ), true ); //? + GamePacketNew< FFXIVIpcMount, ServerZoneIpcType > mountPacket( getId() ); - mountPacket.data().id = id; + mountPacket.data().id = m_mount; sendToInRangeSet( mountPacket, true ); + setSyncFlag( PlayerSyncFlags::Status ); +} + +void Core::Entity::Player::dismount() +{ + sendToInRangeSet( ActorControlPacket142( getId(), ActorControlType::SetStatus, static_cast< uint8_t >( Entity::Actor::ActorStatus::Idle )), true ); + sendToInRangeSet( ActorControlPacket143( getId(), ActorControlType::Dismount, 1 ), true ); + m_mount = 0; + setSyncFlag( PlayerSyncFlags::Status ); +} + +uint8_t Core::Entity::Player::getCurrentMount() const +{ + return m_mount; } void Core::Entity::Player::autoAttack( ActorPtr pTarget ) diff --git a/src/servers/Server_Zone/Actor/Player.h b/src/servers/Server_Zone/Actor/Player.h index f9d471ea..95fd1b89 100644 --- a/src/servers/Server_Zone/Actor/Player.h +++ b/src/servers/Server_Zone/Actor/Player.h @@ -338,10 +338,14 @@ public: void setTitle( uint16_t titleId ); /*! change gear param state */ void setEquipDisplayFlags( uint8_t state ); - /*! get gear param state and send update to inRangeSet */ + /*! get gear param state */ uint8_t getEquipDisplayFlags() const; - /*! mount the specified mount and send the packet */ + /*! mount the specified mount and send the packets */ void mount( uint32_t id ); + /*! dismount the current mount and send the packets */ + void dismount(); + /*! get the current mount */ + uint8_t getCurrentMount() const; void calculateStats() override; void sendStats(); diff --git a/src/servers/Server_Zone/Actor/PlayerSql.cpp b/src/servers/Server_Zone/Actor/PlayerSql.cpp index 4ff24919..23ed16f0 100644 --- a/src/servers/Server_Zone/Actor/PlayerSql.cpp +++ b/src/servers/Server_Zone/Actor/PlayerSql.cpp @@ -85,7 +85,8 @@ bool Core::Entity::Player::load( uint32_t charId, Core::SessionPtr pSession ) "cd.EquipDisplayFlags, " "cd.ActiveTitle, " "cd.TitleList, " // 40 - "cd.Orchestrion " + "cd.Orchestrion, " + "c.Mount " "FROM charabase AS c " " INNER JOIN charadetail AS cd " " ON c.CharacterId = cd.CharacterId " @@ -180,10 +181,13 @@ bool Core::Entity::Player::load( uint32_t charId, Core::SessionPtr pSession ) 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 ) ); field[41].getBinary( reinterpret_cast< char* >( m_orchestrion ), sizeof( m_orchestrion ) ); + m_mount = field[42].get< uint8_t >(); + m_pCell = nullptr; if( !loadActiveQuests() || !loadClassData() || !loadSearchInfo() ) @@ -371,6 +375,7 @@ void Core::Entity::Player::createUpdateSql() charaDetailSet.insert( " Class = " + std::to_string( static_cast< uint32_t >( getClass() ) ) ); charaDetailSet.insert( " Status = " + std::to_string( static_cast< uint8_t >( getStatus() ) ) ); charaDetailSet.insert( " EquipDisplayFlags = " + std::to_string( static_cast< uint8_t >( getEquipDisplayFlags() ) ) ); + charaBaseSet.insert( " Mount = " + std::to_string( getCurrentMount() ) ); } if( m_updateFlags & PlayerSyncFlags::OpeningSeq ) diff --git a/src/servers/Server_Zone/Network/Handlers/ActionHandler.cpp b/src/servers/Server_Zone/Network/Handlers/ActionHandler.cpp index 65815e95..9a6dcd6a 100644 --- a/src/servers/Server_Zone/Network/Handlers/ActionHandler.cpp +++ b/src/servers/Server_Zone/Network/Handlers/ActionHandler.cpp @@ -108,8 +108,8 @@ void Core::Network::GameConnection::actionHandler( const Packets::GamePacket& in } case 0x65: { - pPlayer->sendToInRangeSet( ActorControlPacket142(pPlayer->getId(), ActorControlType::SetStatus, 1 ), true ); //? - pPlayer->sendToInRangeSet( ActorControlPacket143( pPlayer->getId(), 0x393, 1 ), true ); //? + pPlayer->dismount(); + break; } case 0x68: // Remove status (clicking it off) { diff --git a/src/servers/Server_Zone/Network/Handlers/SkillHandler.cpp b/src/servers/Server_Zone/Network/Handlers/SkillHandler.cpp index e7a003ef..e83219f0 100644 --- a/src/servers/Server_Zone/Network/Handlers/SkillHandler.cpp +++ b/src/servers/Server_Zone/Network/Handlers/SkillHandler.cpp @@ -118,8 +118,8 @@ void Core::Network::GameConnection::skillHandler( const Packets::GamePacket& inP pPlayer->sendDebug( "Request mount " + std::to_string( action ) ); - Action::ActionMountPtr pActionMount(new Action::ActionMount(pPlayer, pPlayer, action)); - pPlayer->setCurrentAction(pActionMount); + Action::ActionMountPtr pActionMount( new Action::ActionMount(pPlayer, action) ); + pPlayer->setCurrentAction( pActionMount ); pPlayer->sendDebug("setCurrentAction()"); pPlayer->getCurrentAction()->onStart(); diff --git a/src/servers/Server_Zone/Network/PacketWrappers/PlayerSpawnPacket.h b/src/servers/Server_Zone/Network/PacketWrappers/PlayerSpawnPacket.h index f96160f6..1c3e8eed 100644 --- a/src/servers/Server_Zone/Network/PacketWrappers/PlayerSpawnPacket.h +++ b/src/servers/Server_Zone/Network/PacketWrappers/PlayerSpawnPacket.h @@ -111,6 +111,8 @@ namespace Server { m_data.displayFlags |= Entity::Actor::DisplayFlags::Visor; } + m_data.currentMount = pPlayer->getCurrentMount(); + m_data.targetId = pPlayer->getTargetId(); //m_data.type = 1; //m_data.unknown_33 = 4; From 1f3d0112a5e533a2d246e4e82346db7faee4936b Mon Sep 17 00:00:00 2001 From: amibu Date: Wed, 18 Oct 2017 18:06:25 +0200 Subject: [PATCH 8/9] Mount debug command; --- .../Server_Zone/DebugCommand/DebugCommandHandler.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/servers/Server_Zone/DebugCommand/DebugCommandHandler.cpp b/src/servers/Server_Zone/DebugCommand/DebugCommandHandler.cpp index 3a8805ed..c1f8f2f7 100644 --- a/src/servers/Server_Zone/DebugCommand/DebugCommandHandler.cpp +++ b/src/servers/Server_Zone/DebugCommand/DebugCommandHandler.cpp @@ -258,6 +258,14 @@ void Core::DebugCommandHandler::set( char * data, Core::Entity::PlayerPtr pPlaye pPlayer->sendModel(); pPlayer->sendDebug( "Model updated" ); } + else if ( subCommand == "mount" ) + { + int32_t id; + sscanf( params.c_str(), "%d", &id ); + + pPlayer->dismount(); + pPlayer->mount( id ); + } else { pPlayer->sendUrgent( subCommand + " is not a valid SET command." ); From 19ca1394131d7f3eb39faf65d5e07bea2d5359fa Mon Sep 17 00:00:00 2001 From: amibu Date: Wed, 18 Oct 2017 18:08:51 +0200 Subject: [PATCH 9/9] Formatting --- src/servers/Server_Common/Network/PacketDef/Ipcs.h | 2 +- src/servers/Server_Zone/Network/PacketWrappers/InitUIPacket.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/servers/Server_Common/Network/PacketDef/Ipcs.h b/src/servers/Server_Common/Network/PacketDef/Ipcs.h index eefd987a..be752a6c 100644 --- a/src/servers/Server_Common/Network/PacketDef/Ipcs.h +++ b/src/servers/Server_Common/Network/PacketDef/Ipcs.h @@ -116,7 +116,7 @@ namespace Packets { ActorSpawn = 0x0190, // todo: split into playerspawn/actorspawn and use opcode 0x110/0x111 ActorFreeSpawn = 0x0191, // unchanged for sb InitZone = 0x019A, // unchanged for sb - Mount = 0x019F, // unchanged for sb + Mount = 0x019F, WeatherChange = 0x01AF, // updated for sb PlayerTitleList = 0x01BD, // updated for 4.1 Discovery = 0x01BE, // updated for 4.1 diff --git a/src/servers/Server_Zone/Network/PacketWrappers/InitUIPacket.h b/src/servers/Server_Zone/Network/PacketWrappers/InitUIPacket.h index ab88e67b..e28f87e1 100644 --- a/src/servers/Server_Zone/Network/PacketWrappers/InitUIPacket.h +++ b/src/servers/Server_Zone/Network/PacketWrappers/InitUIPacket.h @@ -65,7 +65,7 @@ private: memcpy( m_data.orchestrionMask, player->getOrchestrionBitmask(), sizeof( m_data.orchestrionMask ) ); memset( m_data.mountGuideMask, 0xFF, sizeof( m_data.mountGuideMask) ); - memset( m_data.fishingGuideMask, 0xFF, sizeof(m_data.fishingGuideMask) ); + memset( m_data.fishingGuideMask, 0xFF, sizeof( m_data.fishingGuideMask ) ); memcpy( m_data.unlockBitmask, player->getUnlockBitmask(), sizeof( m_data.unlockBitmask ) );