2023-02-02 02:30:31 -03:00
|
|
|
#pragma once
|
2018-09-09 23:56:22 +02:00
|
|
|
|
|
|
|
#include <Network/PacketDef/Zone/ServerZoneDef.h>
|
2019-03-08 15:34:38 +01:00
|
|
|
#include <Network/GamePacket.h>
|
2018-09-09 23:56:22 +02:00
|
|
|
#include <Util/Util.h>
|
2019-01-23 22:37:55 +01:00
|
|
|
#include <Common.h>
|
2018-09-09 23:56:22 +02:00
|
|
|
#include "Actor/Player.h"
|
|
|
|
#include "Actor/BNpc.h"
|
|
|
|
#include "Forwards.h"
|
|
|
|
#include "Inventory/Item.h"
|
|
|
|
#include "StatusEffect/StatusEffect.h"
|
|
|
|
|
2021-11-27 00:53:57 +01:00
|
|
|
namespace Sapphire::Network::Packets::WorldPackets::Server
|
2018-09-09 23:56:22 +02:00
|
|
|
{
|
|
|
|
|
2018-10-28 21:53:21 +01:00
|
|
|
/**
|
|
|
|
* @brief The packet sent to spawn a player.
|
|
|
|
*/
|
2021-11-27 00:53:57 +01:00
|
|
|
class NpcSpawnPacket : public ZoneChannelPacket< FFXIVIpcPlayerSpawn >
|
2018-09-09 23:56:22 +02:00
|
|
|
{
|
2018-10-28 21:53:21 +01:00
|
|
|
public:
|
|
|
|
NpcSpawnPacket( Entity::BNpc& bnpc, Entity::Player& target ) :
|
2021-11-27 00:53:57 +01:00
|
|
|
ZoneChannelPacket< FFXIVIpcPlayerSpawn >( bnpc.getId(), target.getId() )
|
2018-09-09 23:56:22 +02:00
|
|
|
{
|
2018-10-28 21:53:21 +01:00
|
|
|
initialize( bnpc, target );
|
|
|
|
};
|
2018-09-09 23:56:22 +02:00
|
|
|
|
2018-10-28 21:53:21 +01:00
|
|
|
private:
|
|
|
|
void initialize( Entity::BNpc& bnpc, Entity::Player& target )
|
2018-09-09 23:56:22 +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 >( bnpc.getClass() );
|
|
|
|
//m_data.ActiveType = static_cast< uint8_t >( bnpc.getStatus() );
|
|
|
|
|
2021-12-22 00:40:11 +01:00
|
|
|
m_data.LayoutId = bnpc.getLayoutId();
|
2021-11-27 00:53:57 +01:00
|
|
|
m_data.Hp = bnpc.getHp();
|
|
|
|
m_data.Mp = bnpc.getMp();
|
|
|
|
m_data.HpMax = bnpc.getMaxHp();
|
|
|
|
m_data.Lv = bnpc.getLevel();
|
|
|
|
m_data.ModeArgs = bnpc.getPose();
|
|
|
|
m_data.ContentId = bnpc.getDirectorId();
|
|
|
|
|
|
|
|
memcpy( m_data.Customize, bnpc.getLookArray(), sizeof( m_data.Customize ) );
|
|
|
|
memcpy( m_data.Equipment, bnpc.getModelArray(), sizeof( m_data.Equipment ) );
|
|
|
|
|
|
|
|
m_data.Pos[ 0 ] = bnpc.getPos().x;
|
|
|
|
m_data.Pos[ 1 ] = bnpc.getPos().y;
|
|
|
|
m_data.Pos[ 2 ] = bnpc.getPos().z;
|
|
|
|
m_data.Dir = Common::Util::floatToUInt16Rot( bnpc.getRot() );
|
|
|
|
m_data.BindId = bnpc.getBoundInstanceId();
|
|
|
|
|
|
|
|
m_data.Rank = bnpc.getRank();
|
|
|
|
m_data.MainWeapon = bnpc.getWeaponMain();
|
|
|
|
m_data.SubWeapon = bnpc.getWeaponSub();
|
|
|
|
m_data.ActiveType = bnpc.getAggressionMode() != 1 ? 2 : 1;
|
|
|
|
|
|
|
|
m_data.ClassJob = 0;
|
|
|
|
|
|
|
|
m_data.ContentId = bnpc.getDirectorId();
|
|
|
|
m_data.MainTarget = bnpc.getTargetId();
|
|
|
|
// no idea ... m_data.spawnerId = Common::INVALID_GAME_OBJECT_ID64;
|
|
|
|
m_data.ParentId = Common::INVALID_GAME_OBJECT_ID;
|
2022-01-18 08:03:49 +01:00
|
|
|
m_data.TriggerId = bnpc.getTriggerOwnerId();
|
2021-11-27 00:53:57 +01:00
|
|
|
m_data.ChannelingTarget = Common::INVALID_GAME_OBJECT_ID;
|
|
|
|
m_data.OwnerId = Common::INVALID_GAME_OBJECT_ID;
|
2019-01-23 22:37:55 +01:00
|
|
|
|
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 >( bnpc.getStatus() );
|
|
|
|
m_data.ObjKind = bnpc.getObjKind();
|
|
|
|
m_data.ObjType = 5;
|
|
|
|
// ref to bnpcbase.battalion, 0 is friendly npc rest are ???
|
|
|
|
m_data.Battalion = bnpc.getEnemyType();
|
|
|
|
|
|
|
|
m_data.ModelCharaId = bnpc.getModelChara();
|
2018-10-28 21:53:21 +01:00
|
|
|
|
2021-11-27 00:53:57 +01:00
|
|
|
m_data.NpcId = bnpc.getBNpcBaseId();
|
|
|
|
m_data.NameId = bnpc.getBNpcNameId();
|
2018-10-28 21:53:21 +01:00
|
|
|
|
2019-01-19 19:28:12 +11:00
|
|
|
assert( target.getId() != bnpc.getId() );
|
|
|
|
|
2021-11-27 00:53:57 +01:00
|
|
|
m_data.Index = target.getSpawnIdForActorId( bnpc.getId() );
|
2019-01-19 19:28:12 +11:00
|
|
|
|
2021-11-27 00:53:57 +01:00
|
|
|
if( !target.isActorSpawnIdValid( m_data.Index ) )
|
2019-01-19 19:28:12 +11:00
|
|
|
return;
|
2018-10-28 21:53:21 +01:00
|
|
|
// 0x20 == spawn hidden to be displayed by the spawneffect control
|
|
|
|
//m_data.displayFlags = bnpc.getDisplayFlags();
|
|
|
|
|
|
|
|
//m_data.currentMount = bnpc.getCurrentMount();
|
|
|
|
//m_data.persistentEmote = bnpc.getPersistentEmote();
|
|
|
|
|
2021-11-27 00:53:57 +01:00
|
|
|
m_data.MainTarget = static_cast< uint64_t >( bnpc.getTargetId() );
|
2018-10-28 21:53:21 +01:00
|
|
|
|
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 : bnpc.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-09-09 23:56:22 +02:00
|
|
|
};
|
|
|
|
|
2023-02-02 02:30:31 -03:00
|
|
|
}
|