mirror of
https://github.com/SapphireServer/Sapphire.git
synced 2025-04-25 14:07:46 +00:00
Merge pull request #142 from goaaats/master
Initial mounts implementation, nicer debug packet printing
This commit is contained in:
commit
9df21f92eb
19 changed files with 310 additions and 21 deletions
|
@ -602,7 +602,8 @@ namespace Core {
|
||||||
MpGain = 11,
|
MpGain = 11,
|
||||||
TpLoss = 12,
|
TpLoss = 12,
|
||||||
TpGain = 13,
|
TpGain = 13,
|
||||||
GpGain = 14
|
GpGain = 14,
|
||||||
|
Mount = 38
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class ActionHitSeverityType : uint8_t
|
enum class ActionHitSeverityType : uint8_t
|
||||||
|
@ -951,7 +952,8 @@ namespace Core {
|
||||||
|
|
||||||
GearSetEquipMsg = 0x321,
|
GearSetEquipMsg = 0x321,
|
||||||
|
|
||||||
ToggleOrchestrionUnlock = 0x396
|
ToggleOrchestrionUnlock = 0x396,
|
||||||
|
Dismount = 0x3a0
|
||||||
};
|
};
|
||||||
|
|
||||||
enum struct ChatType : uint16_t
|
enum struct ChatType : uint16_t
|
||||||
|
@ -1068,6 +1070,12 @@ namespace Core {
|
||||||
Visor = 0x40,
|
Visor = 0x40,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum SkillType : uint8_t
|
||||||
|
{
|
||||||
|
Normal = 0x1,
|
||||||
|
MountSkill = 0xD,
|
||||||
|
};
|
||||||
|
|
||||||
struct ServerEntry
|
struct ServerEntry
|
||||||
{
|
{
|
||||||
uint32_t serverId;
|
uint32_t serverId;
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <boost/lexical_cast.hpp>
|
#include <boost/lexical_cast.hpp>
|
||||||
#include <boost/format.hpp>
|
#include <boost/format.hpp>
|
||||||
|
#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 )
|
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 Core::Network::Packets::GamePacket::toString() const
|
||||||
{
|
{
|
||||||
|
return Core::Util::binaryToHexDump( const_cast<uint8_t *>( &m_dataBuf[0] ), getSize() );
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -116,6 +116,7 @@ namespace Packets {
|
||||||
ActorSpawn = 0x0190, // todo: split into playerspawn/actorspawn and use opcode 0x110/0x111
|
ActorSpawn = 0x0190, // todo: split into playerspawn/actorspawn and use opcode 0x110/0x111
|
||||||
ActorFreeSpawn = 0x0191, // unchanged for sb
|
ActorFreeSpawn = 0x0191, // unchanged for sb
|
||||||
InitZone = 0x019A, // unchanged for sb
|
InitZone = 0x019A, // unchanged for sb
|
||||||
|
Mount = 0x019F,
|
||||||
WeatherChange = 0x01AF, // updated for sb
|
WeatherChange = 0x01AF, // updated for sb
|
||||||
PlayerTitleList = 0x01BD, // updated for 4.1
|
PlayerTitleList = 0x01BD, // updated for 4.1
|
||||||
Discovery = 0x01BE, // updated for 4.1
|
Discovery = 0x01BE, // updated for 4.1
|
||||||
|
|
|
@ -604,7 +604,8 @@ struct FFXIVIpcActorSetPos : FFXIVIpcBasePacket<ActorSetPos>
|
||||||
struct FFXIVIpcActorCast : FFXIVIpcBasePacket<ActorCast>
|
struct FFXIVIpcActorCast : FFXIVIpcBasePacket<ActorCast>
|
||||||
{
|
{
|
||||||
uint16_t action_id;
|
uint16_t action_id;
|
||||||
uint16_t unknown;
|
Common::SkillType skillType;
|
||||||
|
uint8_t unknown;
|
||||||
uint32_t unknown_1; // Also action id
|
uint32_t unknown_1; // Also action id
|
||||||
float cast_time;
|
float cast_time;
|
||||||
uint32_t target_id;
|
uint32_t target_id;
|
||||||
|
@ -1303,6 +1304,15 @@ struct FFXIVIpcEquipDisplayFlags : FFXIVIpcBasePacket<EquipDisplayFlags>
|
||||||
uint8_t bitmask;
|
uint8_t bitmask;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Structural representation of the packet sent by the server
|
||||||
|
* to mount a player
|
||||||
|
*/
|
||||||
|
struct FFXIVIpcMount : FFXIVIpcBasePacket<Mount>
|
||||||
|
{
|
||||||
|
uint32_t id;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
} /* Server */
|
} /* Server */
|
||||||
} /* Packets */
|
} /* Packets */
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
#include "Util.h"
|
#include "Util.h"
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
|
#include <boost/variant/detail/substitute.hpp>
|
||||||
|
|
||||||
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;
|
std::string outStr;
|
||||||
|
|
||||||
for( uint32_t i = 0; i < size; i++ )
|
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;
|
||||||
|
constexpr char 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<char>( by );
|
||||||
|
}
|
||||||
|
|
||||||
|
hexColumn += 3;
|
||||||
|
charColumn++;
|
||||||
|
}
|
||||||
|
|
||||||
|
outStr += line + "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
return outStr;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
uint64_t Core::Util::getTimeMs()
|
uint64_t Core::Util::getTimeMs()
|
||||||
{
|
{
|
||||||
std::chrono::milliseconds epoch = std::chrono::duration_cast< std::chrono::milliseconds >(std::chrono::system_clock::now().time_since_epoch());
|
std::chrono::milliseconds epoch = std::chrono::duration_cast< std::chrono::milliseconds >(std::chrono::system_clock::now().time_since_epoch());
|
||||||
|
|
|
@ -9,6 +9,8 @@ namespace Util {
|
||||||
|
|
||||||
std::string binaryToHexString( uint8_t* pBinData, uint16_t size );
|
std::string binaryToHexString( uint8_t* pBinData, uint16_t size );
|
||||||
|
|
||||||
|
std::string binaryToHexDump( uint8_t* pBinData, uint16_t size );
|
||||||
|
|
||||||
uint64_t getTimeMs();
|
uint64_t getTimeMs();
|
||||||
|
|
||||||
uint64_t getTimeSeconds();
|
uint64_t getTimeSeconds();
|
||||||
|
|
|
@ -53,7 +53,7 @@ void Core::Action::ActionCast::onStart()
|
||||||
GamePacketNew< FFXIVIpcActorCast, ServerZoneIpcType > castPacket( m_pSource->getId() );
|
GamePacketNew< FFXIVIpcActorCast, ServerZoneIpcType > castPacket( m_pSource->getId() );
|
||||||
|
|
||||||
castPacket.data().action_id = m_id;
|
castPacket.data().action_id = m_id;
|
||||||
castPacket.data().unknown = 1;
|
castPacket.data().skillType = Common::SkillType::Normal;
|
||||||
castPacket.data().unknown_1 = m_id;
|
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().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_pTarget->getId();
|
||||||
|
|
111
src/servers/Server_Zone/Action/ActionMount.cpp
Normal file
111
src/servers/Server_Zone/Action/ActionMount.cpp
Normal file
|
@ -0,0 +1,111 @@
|
||||||
|
#include "ActionMount.h"
|
||||||
|
|
||||||
|
#include <src/servers/Server_Common/Common.h>
|
||||||
|
#include <src/servers/Server_Common/Util/Util.h>
|
||||||
|
#include <src/servers/Server_Common/Util/UtilMath.h>
|
||||||
|
#include <src/servers/Server_Common/Exd/ExdData.h>
|
||||||
|
#include <src/servers/Server_Common/Logging/Logger.h>
|
||||||
|
|
||||||
|
#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, uint32_t mountId )
|
||||||
|
{
|
||||||
|
m_startTime = 0;
|
||||||
|
m_id = mountId;
|
||||||
|
m_handleActionType = HandleActionType::Spell;
|
||||||
|
m_castTime = 1000;
|
||||||
|
m_pSource = pActor;
|
||||||
|
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_pSource->getAsPlayer()->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->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 );
|
||||||
|
|
||||||
|
}
|
28
src/servers/Server_Zone/Action/ActionMount.h
Normal file
28
src/servers/Server_Zone/Action/ActionMount.h
Normal file
|
@ -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, uint32_t mountId );
|
||||||
|
|
||||||
|
void onStart() override;
|
||||||
|
void onFinish() override;
|
||||||
|
void onInterrupt() override;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -1486,6 +1486,31 @@ uint8_t Core::Entity::Player::getEquipDisplayFlags() const
|
||||||
return m_equipDisplayFlags;
|
return m_equipDisplayFlags;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 = 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 )
|
void Core::Entity::Player::autoAttack( ActorPtr pTarget )
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
|
@ -338,8 +338,14 @@ public:
|
||||||
void setTitle( uint16_t titleId );
|
void setTitle( uint16_t titleId );
|
||||||
/*! change gear param state */
|
/*! change gear param state */
|
||||||
void setEquipDisplayFlags( uint8_t state );
|
void setEquipDisplayFlags( uint8_t state );
|
||||||
/*! get gear param state and send update to inRangeSet */
|
/*! get gear param state */
|
||||||
uint8_t getEquipDisplayFlags() const;
|
uint8_t getEquipDisplayFlags() const;
|
||||||
|
/*! 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 calculateStats() override;
|
||||||
void sendStats();
|
void sendStats();
|
||||||
|
|
|
@ -85,7 +85,8 @@ bool Core::Entity::Player::load( uint32_t charId, Core::SessionPtr pSession )
|
||||||
"cd.EquipDisplayFlags, "
|
"cd.EquipDisplayFlags, "
|
||||||
"cd.ActiveTitle, "
|
"cd.ActiveTitle, "
|
||||||
"cd.TitleList, " // 40
|
"cd.TitleList, " // 40
|
||||||
"cd.Orchestrion "
|
"cd.Orchestrion, "
|
||||||
|
"c.Mount "
|
||||||
"FROM charabase AS c "
|
"FROM charabase AS c "
|
||||||
" INNER JOIN charadetail AS cd "
|
" INNER JOIN charadetail AS cd "
|
||||||
" ON c.CharacterId = cd.CharacterId "
|
" 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_equipDisplayFlags = field[38].get< uint8_t >();
|
||||||
|
|
||||||
m_title = field[39].get< uint8_t >();
|
m_title = field[39].get< uint8_t >();
|
||||||
|
|
||||||
field[40].getBinary( reinterpret_cast< char* >( m_titleList ), sizeof( m_titleList ) );
|
field[40].getBinary( reinterpret_cast< char* >( m_titleList ), sizeof( m_titleList ) );
|
||||||
|
|
||||||
field[41].getBinary( reinterpret_cast< char* >( m_orchestrion ), sizeof( m_orchestrion ) );
|
field[41].getBinary( reinterpret_cast< char* >( m_orchestrion ), sizeof( m_orchestrion ) );
|
||||||
|
|
||||||
|
m_mount = field[42].get< uint8_t >();
|
||||||
|
|
||||||
m_pCell = nullptr;
|
m_pCell = nullptr;
|
||||||
|
|
||||||
if( !loadActiveQuests() || !loadClassData() || !loadSearchInfo() )
|
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( " Class = " + std::to_string( static_cast< uint32_t >( getClass() ) ) );
|
||||||
charaDetailSet.insert( " Status = " + std::to_string( static_cast< uint8_t >( getStatus() ) ) );
|
charaDetailSet.insert( " Status = " + std::to_string( static_cast< uint8_t >( getStatus() ) ) );
|
||||||
charaDetailSet.insert( " EquipDisplayFlags = " + std::to_string( static_cast< uint8_t >( getEquipDisplayFlags() ) ) );
|
charaDetailSet.insert( " EquipDisplayFlags = " + std::to_string( static_cast< uint8_t >( getEquipDisplayFlags() ) ) );
|
||||||
|
charaBaseSet.insert( " Mount = " + std::to_string( getCurrentMount() ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
if( m_updateFlags & PlayerSyncFlags::OpeningSeq )
|
if( m_updateFlags & PlayerSyncFlags::OpeningSeq )
|
||||||
|
|
|
@ -258,6 +258,14 @@ void Core::DebugCommandHandler::set( char * data, Core::Entity::PlayerPtr pPlaye
|
||||||
pPlayer->sendModel();
|
pPlayer->sendModel();
|
||||||
pPlayer->sendDebug( "Model updated" );
|
pPlayer->sendDebug( "Model updated" );
|
||||||
}
|
}
|
||||||
|
else if ( subCommand == "mount" )
|
||||||
|
{
|
||||||
|
int32_t id;
|
||||||
|
sscanf( params.c_str(), "%d", &id );
|
||||||
|
|
||||||
|
pPlayer->dismount();
|
||||||
|
pPlayer->mount( id );
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
pPlayer->sendUrgent( subCommand + " is not a valid SET command." );
|
pPlayer->sendUrgent( subCommand + " is not a valid SET command." );
|
||||||
|
|
|
@ -44,6 +44,7 @@ namespace Core
|
||||||
TYPE_FORWARD( Action );
|
TYPE_FORWARD( Action );
|
||||||
TYPE_FORWARD( ActionTeleport );
|
TYPE_FORWARD( ActionTeleport );
|
||||||
TYPE_FORWARD( ActionCast );
|
TYPE_FORWARD( ActionCast );
|
||||||
|
TYPE_FORWARD( ActionMount );
|
||||||
TYPE_FORWARD( EventAction );
|
TYPE_FORWARD( EventAction );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -206,7 +206,7 @@ void Core::Network::GameConnection::handleZonePacket( const Packets::GamePacket&
|
||||||
g_log.debug( sessionStr + " Undefined Zone IPC : Unknown ( " +
|
g_log.debug( sessionStr + " Undefined Zone IPC : Unknown ( " +
|
||||||
boost::str( boost::format( "%|04X|" ) %
|
boost::str( boost::format( "%|04X|" ) %
|
||||||
static_cast< uint32_t >( pPacket.getSubType() & 0xFFFF ) ) + " )" );
|
static_cast< uint32_t >( pPacket.getSubType() & 0xFFFF ) ) + " )" );
|
||||||
g_log.debug( pPacket.toString() );
|
g_log.debug( "\n" + pPacket.toString() );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -106,6 +106,11 @@ void Core::Network::GameConnection::actionHandler( const Packets::GamePacket& in
|
||||||
pPlayer->changeTarget( targetId );
|
pPlayer->changeTarget( targetId );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case 0x65:
|
||||||
|
{
|
||||||
|
pPlayer->dismount();
|
||||||
|
break;
|
||||||
|
}
|
||||||
case 0x68: // Remove status (clicking it off)
|
case 0x68: // Remove status (clicking it off)
|
||||||
{
|
{
|
||||||
// todo: check if status can be removed by client from exd
|
// todo: check if status can be removed by client from exd
|
||||||
|
|
|
@ -25,9 +25,10 @@
|
||||||
#include "src/servers/Server_Zone/Forwards.h"
|
#include "src/servers/Server_Zone/Forwards.h"
|
||||||
|
|
||||||
#include "src/servers/Server_Zone/Action/Action.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/ActionCast.h"
|
||||||
|
#include "src/servers/Server_Zone/Action/ActionMount.h"
|
||||||
#include "src/servers/Server_Zone/Script/ScriptManager.h"
|
#include "src/servers/Server_Zone/Script/ScriptManager.h"
|
||||||
|
#include "Server_Zone/Network/PacketWrappers/MoveActorPacket.h"
|
||||||
|
|
||||||
|
|
||||||
extern Core::Scripting::ScriptManager g_scriptMgr;
|
extern Core::Scripting::ScriptManager g_scriptMgr;
|
||||||
|
@ -41,12 +42,19 @@ using namespace Core::Network::Packets::Server;
|
||||||
void Core::Network::GameConnection::skillHandler( const Packets::GamePacket& inPacket,
|
void Core::Network::GameConnection::skillHandler( const Packets::GamePacket& inPacket,
|
||||||
Entity::PlayerPtr pPlayer )
|
Entity::PlayerPtr pPlayer )
|
||||||
{
|
{
|
||||||
|
uint8_t type = inPacket.getValAt< uint32_t >( 0x21 );
|
||||||
|
|
||||||
uint32_t action = inPacket.getValAt< uint32_t >( 0x24 );
|
uint32_t action = inPacket.getValAt< uint32_t >( 0x24 );
|
||||||
uint32_t useCount = inPacket.getValAt< uint32_t >( 0x28 );
|
uint32_t useCount = inPacket.getValAt< uint32_t >( 0x28 );
|
||||||
|
|
||||||
uint64_t targetId = inPacket.getValAt< uint64_t >( 0x30 );
|
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
|
if( action < 1000000 ) // normal action
|
||||||
{
|
{
|
||||||
std::string actionIdStr = boost::str( boost::format( "%|04X|" ) % action );
|
std::string actionIdStr = boost::str( boost::format( "%|04X|" ) % action );
|
||||||
|
@ -104,4 +112,19 @@ void Core::Network::GameConnection::skillHandler( const Packets::GamePacket& inP
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Common::SkillType::MountSkill:
|
||||||
|
|
||||||
|
pPlayer->sendDebug( "Request mount " + std::to_string( action ) );
|
||||||
|
|
||||||
|
Action::ActionMountPtr pActionMount( new Action::ActionMount(pPlayer, action) );
|
||||||
|
pPlayer->setCurrentAction( pActionMount );
|
||||||
|
pPlayer->sendDebug("setCurrentAction()");
|
||||||
|
pPlayer->getCurrentAction()->onStart();
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -64,6 +64,9 @@ private:
|
||||||
|
|
||||||
memcpy( m_data.orchestrionMask, player->getOrchestrionBitmask(), sizeof( m_data.orchestrionMask ) );
|
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.unlockBitmask, player->getUnlockBitmask(), sizeof( m_data.unlockBitmask ) );
|
||||||
|
|
||||||
memcpy( m_data.discovery, player->getDiscoveryBitmask(), sizeof( m_data.discovery ) );
|
memcpy( m_data.discovery, player->getDiscoveryBitmask(), sizeof( m_data.discovery ) );
|
||||||
|
|
|
@ -111,6 +111,8 @@ namespace Server {
|
||||||
m_data.displayFlags |= Entity::Actor::DisplayFlags::Visor;
|
m_data.displayFlags |= Entity::Actor::DisplayFlags::Visor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_data.currentMount = pPlayer->getCurrentMount();
|
||||||
|
|
||||||
m_data.targetId = pPlayer->getTargetId();
|
m_data.targetId = pPlayer->getTargetId();
|
||||||
//m_data.type = 1;
|
//m_data.type = 1;
|
||||||
//m_data.unknown_33 = 4;
|
//m_data.unknown_33 = 4;
|
||||||
|
|
Loading…
Add table
Reference in a new issue