2017-08-18 17:16:15 +02:00
|
|
|
#ifndef _PLAYERSPAWN_H
|
|
|
|
#define _PLAYERSPAWN_H
|
|
|
|
|
2018-03-06 22:22:19 +01:00
|
|
|
#include <Network/PacketDef/Zone/ServerZoneDef.h>
|
2019-03-08 15:34:38 +01:00
|
|
|
#include <Network/GamePacket.h>
|
2018-03-06 22:22:19 +01:00
|
|
|
#include <Util/Util.h>
|
2017-12-08 23:27:59 +01:00
|
|
|
#include "Actor/Player.h"
|
|
|
|
#include "Forwards.h"
|
|
|
|
#include "Inventory/Item.h"
|
|
|
|
#include "StatusEffect/StatusEffect.h"
|
2017-08-18 17:16:15 +02:00
|
|
|
|
2021-11-27 00:53:57 +01:00
|
|
|
namespace Sapphire::Network::Packets::WorldPackets::Server
|
2018-08-29 21:40:59 +02:00
|
|
|
{
|
|
|
|
|
2018-10-28 21:53:21 +01:00
|
|
|
/**
|
|
|
|
* @brief The packet sent to spawn a player.
|
|
|
|
*/
|
|
|
|
class PlayerSpawnPacket : public ZoneChannelPacket< FFXIVIpcPlayerSpawn >
|
2018-08-29 21:40:59 +02:00
|
|
|
{
|
2018-10-28 21:53:21 +01:00
|
|
|
public:
|
|
|
|
PlayerSpawnPacket( Entity::Player& player, Entity::Player& target ) :
|
|
|
|
ZoneChannelPacket< FFXIVIpcPlayerSpawn >( player.getId(), target.getId() )
|
2018-08-29 21:40:59 +02:00
|
|
|
{
|
2018-10-28 21:53:21 +01:00
|
|
|
initialize( player, target );
|
|
|
|
};
|
2018-08-29 21:40:59 +02:00
|
|
|
|
2018-10-28 21:53:21 +01:00
|
|
|
private:
|
|
|
|
void initialize( Entity::Player& player, Entity::Player& target )
|
2018-08-29 21:40:59 +02:00
|
|
|
{
|
2018-10-28 21:53:21 +01:00
|
|
|
// todo: figure out unkown offsets
|
2021-11-27 00:53:57 +01:00
|
|
|
m_data.ClassJob = static_cast< uint8_t >( player.getClass() );
|
2018-10-28 21:53:21 +01:00
|
|
|
//m_data.status = static_cast< uint8_t >( pPlayer->getStatus() );
|
|
|
|
|
2019-04-17 00:31:19 +02:00
|
|
|
// TODO: world id from server
|
2021-11-27 00:53:57 +01:00
|
|
|
m_data.WorldId = 67;
|
|
|
|
//m_data.homeWorldId = 67;
|
2019-04-17 00:31:19 +02:00
|
|
|
|
2021-11-27 00:53:57 +01:00
|
|
|
m_data.Hp = player.getHp();
|
|
|
|
m_data.Mp = player.getMp();
|
|
|
|
m_data.HpMax = player.getMaxHp();
|
|
|
|
m_data.MpMax = player.getMaxMp();
|
2018-10-28 21:53:21 +01:00
|
|
|
|
2021-11-27 00:53:57 +01:00
|
|
|
m_data.Lv = player.getLevel();
|
|
|
|
m_data.GMRank = player.getGmRank();
|
2021-12-01 01:03:36 +01:00
|
|
|
m_data.ModeArgs = player.getPersistentEmote();
|
|
|
|
m_data.PoseEmote = player.getPose();
|
2018-10-28 21:53:21 +01:00
|
|
|
|
2021-11-27 00:53:57 +01:00
|
|
|
if( player.isDirectorInitialized() )
|
|
|
|
{
|
|
|
|
m_data.ContentId = player.getDirectorId();
|
|
|
|
}
|
|
|
|
|
|
|
|
memcpy( m_data.Customize, player.getLookArray(), sizeof( m_data.Customize ) );
|
2018-10-28 21:53:21 +01:00
|
|
|
|
|
|
|
auto item = player.getItemAt( Common::GearSet0, Common::GearSetSlot::MainHand );
|
|
|
|
if( item )
|
2021-11-27 00:53:57 +01:00
|
|
|
m_data.MainWeapon = player.getModelMainWeapon();
|
|
|
|
m_data.SubWeapon = player.getModelSubWeapon();
|
|
|
|
|
|
|
|
m_data.Equipment[ Common::GearModelSlot::ModelHead ] = player.getModelForSlot( Common::GearModelSlot::ModelHead );
|
|
|
|
m_data.Equipment[ Common::GearModelSlot::ModelBody ] = player.getModelForSlot( Common::GearModelSlot::ModelBody );
|
|
|
|
m_data.Equipment[ Common::GearModelSlot::ModelHands ] = player.getModelForSlot( Common::GearModelSlot::ModelHands );
|
|
|
|
m_data.Equipment[ Common::GearModelSlot::ModelLegs ] = player.getModelForSlot( Common::GearModelSlot::ModelLegs );
|
|
|
|
m_data.Equipment[ Common::GearModelSlot::ModelFeet ] = player.getModelForSlot( Common::GearModelSlot::ModelFeet );
|
|
|
|
m_data.Equipment[ Common::GearModelSlot::ModelNeck ] = player.getModelForSlot( Common::GearModelSlot::ModelNeck );
|
|
|
|
m_data.Equipment[ Common::GearModelSlot::ModelEar ] = player.getModelForSlot( Common::GearModelSlot::ModelEar );
|
|
|
|
m_data.Equipment[ Common::GearModelSlot::ModelRing1 ] = player.getModelForSlot( Common::GearModelSlot::ModelRing1 );
|
|
|
|
m_data.Equipment[ Common::GearModelSlot::ModelRing2 ] = player.getModelForSlot( Common::GearModelSlot::ModelRing2 );
|
|
|
|
m_data.Equipment[ Common::GearModelSlot::ModelWrist ] = player.getModelForSlot( Common::GearModelSlot::ModelWrist );
|
|
|
|
|
|
|
|
strcpy( reinterpret_cast< char* >( m_data.Name ), player.getName().c_str() );
|
|
|
|
|
|
|
|
m_data.Pos[ 0 ] = player.getPos().x;
|
|
|
|
m_data.Pos[ 1 ] = player.getPos().y;
|
|
|
|
m_data.Pos[ 2 ] = player.getPos().z;
|
|
|
|
m_data.Dir = Common::Util::floatToUInt16Rot( player.getRot() );
|
|
|
|
|
|
|
|
|
|
|
|
m_data.Title = player.getTitle();
|
|
|
|
m_data.Voice = player.getVoiceId();
|
|
|
|
|
2021-11-30 16:29:21 +01:00
|
|
|
m_data.Companion = player.getCurrentCompanion();
|
|
|
|
m_data.Mount.Id = player.getCurrentMount();
|
2019-03-31 13:06:37 +02:00
|
|
|
|
2021-11-27 00:53:57 +01:00
|
|
|
m_data.OnlineStatus = static_cast< uint8_t >( player.getOnlineStatus() );
|
2018-10-28 21:53:21 +01:00
|
|
|
|
|
|
|
//m_data.u23 = 0x04;
|
|
|
|
//m_data.u24 = 256;
|
2021-11-27 00:53:57 +01:00
|
|
|
m_data.Mode = static_cast< uint8_t >( player.getStatus() );
|
|
|
|
m_data.ObjKind = player.getObjKind();
|
|
|
|
m_data.ObjType = 4;
|
2018-10-28 21:53:21 +01:00
|
|
|
if( target.getId() == player.getId() )
|
|
|
|
{
|
2021-11-30 16:29:21 +01:00
|
|
|
m_data.Index = 0;
|
2018-10-28 21:53:21 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2021-11-27 00:53:57 +01:00
|
|
|
m_data.Index = target.getSpawnIdForActorId( player.getId() );
|
2018-10-28 21:53:21 +01:00
|
|
|
|
2021-11-27 00:53:57 +01:00
|
|
|
if( !target.isActorSpawnIdValid( m_data.Index ) )
|
2018-10-28 21:53:21 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
// 0x20 == spawn hidden to be displayed by the spawneffect control
|
2021-11-27 00:53:57 +01:00
|
|
|
m_data.ActiveType = player.getStance();
|
2018-10-28 21:53:21 +01:00
|
|
|
|
|
|
|
if( player.getZoningType() != Common::ZoneingType::None || player.getGmInvis() == true )
|
|
|
|
{
|
2021-11-27 00:53:57 +01:00
|
|
|
m_data.ActiveType |= static_cast< uint16_t >( Common::DisplayFlags::Invisible );
|
2018-10-28 21:53:21 +01:00
|
|
|
}
|
|
|
|
|
2018-11-29 16:55:48 +01:00
|
|
|
if( player.getEquipDisplayFlags() & Sapphire::Common::EquipDisplayFlags::HideHead )
|
2018-10-28 21:53:21 +01:00
|
|
|
{
|
2021-11-27 00:53:57 +01:00
|
|
|
m_data.ActiveType |= static_cast< uint16_t >( Common::DisplayFlags::HideHead );
|
2018-10-28 21:53:21 +01:00
|
|
|
}
|
|
|
|
|
2018-11-29 16:55:48 +01:00
|
|
|
if( player.getEquipDisplayFlags() & Sapphire::Common::EquipDisplayFlags::HideWeapon )
|
2018-10-28 21:53:21 +01:00
|
|
|
{
|
2021-11-27 00:53:57 +01:00
|
|
|
m_data.ActiveType |= static_cast< uint16_t >( Common::DisplayFlags::HideWeapon );
|
2018-10-28 21:53:21 +01:00
|
|
|
}
|
|
|
|
|
2018-11-29 16:55:48 +01:00
|
|
|
if( player.getEquipDisplayFlags() & Sapphire::Common::EquipDisplayFlags::Visor )
|
2018-10-28 21:53:21 +01:00
|
|
|
{
|
2021-11-27 00:53:57 +01:00
|
|
|
m_data.ActiveType |= static_cast< uint16_t >( Common::DisplayFlags::Visor );
|
2018-10-28 21:53:21 +01:00
|
|
|
}
|
|
|
|
|
2018-11-29 16:55:48 +01:00
|
|
|
if( !( player.getEquipDisplayFlags() & Sapphire::Common::EquipDisplayFlags::HideLegacyMark ) )
|
2018-10-28 21:53:21 +01:00
|
|
|
{
|
2021-11-27 00:53:57 +01:00
|
|
|
m_data.Customize[ 0xC ] = m_data.Customize[ 0xC ] | 1 << 7;
|
2018-10-28 21:53:21 +01:00
|
|
|
}
|
|
|
|
|
2021-11-27 00:53:57 +01:00
|
|
|
// m_data.currentMount = player.getCurrentMount();
|
2018-10-28 21:53:21 +01:00
|
|
|
|
2021-11-27 00:53:57 +01:00
|
|
|
m_data.MainTarget = player.getTargetId();
|
2018-10-28 21:53:21 +01:00
|
|
|
//m_data.type = 1;
|
|
|
|
//m_data.unknown_33 = 4;
|
|
|
|
//m_data.unknown_38 = 0x70;
|
|
|
|
//m_data.unknown_60 = 3;
|
|
|
|
//m_data.unknown_61 = 7;
|
|
|
|
|
2019-06-02 00:34:22 +10:00
|
|
|
uint64_t currentTimeMs = Common::Util::getTimeMs();
|
2018-10-28 21:53:21 +01:00
|
|
|
|
|
|
|
for( auto const& effect : player.getStatusEffectMap() )
|
|
|
|
{
|
2021-11-27 00:53:57 +01:00
|
|
|
m_data.Status[ effect.first ].Id = effect.second->getId();
|
|
|
|
m_data.Status[ effect.first ].Time = static_cast< float >( effect.second->getDuration() -
|
2018-10-28 21:53:21 +01:00
|
|
|
( currentTimeMs -
|
|
|
|
effect.second->getStartTimeMs() ) ) / 1000;
|
2021-11-27 00:53:57 +01:00
|
|
|
m_data.Status[ effect.first ].Source = effect.second->getSrcActorId();
|
|
|
|
m_data.Status[ effect.first ].SystemParam = effect.second->getParam();
|
2018-10-28 21:53:21 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
};
|
2018-08-29 21:40:59 +02:00
|
|
|
};
|
2017-08-18 17:16:15 +02:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2017-12-05 11:21:56 +01:00
|
|
|
#endif /*_PlayerSpawn_H*/
|