2024-09-10 01:13:20 +08:00
|
|
|
|
using PSO2SERVER.Models;
|
2024-11-29 10:01:28 +08:00
|
|
|
|
using System.Runtime.InteropServices;
|
|
|
|
|
using static PSO2SERVER.Protocol.Packets.CharacterSpawnPacket;
|
2024-09-10 00:31:40 +08:00
|
|
|
|
|
2024-11-27 18:05:53 +08:00
|
|
|
|
namespace PSO2SERVER.Protocol.Packets
|
2024-09-10 00:31:40 +08:00
|
|
|
|
{
|
|
|
|
|
public class CharacterSpawnPacket : Packet
|
|
|
|
|
{
|
2024-09-18 00:55:35 +08:00
|
|
|
|
public enum CharacterSpawnType
|
|
|
|
|
{
|
|
|
|
|
/// Spawned character is not related to the receiver.
|
|
|
|
|
Other = 0x27,
|
|
|
|
|
/// Spawned character is related to the receiver.
|
|
|
|
|
Myself = 0x2F,
|
|
|
|
|
|
|
|
|
|
Undefined = 0xFF,
|
|
|
|
|
}
|
|
|
|
|
|
2024-09-10 00:31:40 +08:00
|
|
|
|
private readonly Character _character;
|
|
|
|
|
public bool IsItMe = true;
|
|
|
|
|
public PSOLocation Position;
|
|
|
|
|
|
|
|
|
|
public CharacterSpawnPacket(Character character, PSOLocation locatiion)
|
|
|
|
|
{
|
|
|
|
|
_character = character;
|
|
|
|
|
Position = locatiion;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public CharacterSpawnPacket(Character character, PSOLocation locatiion, bool isme)
|
|
|
|
|
{
|
|
|
|
|
_character = character;
|
|
|
|
|
IsItMe = isme;
|
|
|
|
|
Position = locatiion;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#region implemented abstract members of Packet
|
|
|
|
|
|
|
|
|
|
public override byte[] Build()
|
|
|
|
|
{
|
|
|
|
|
var writer = new PacketWriter();
|
|
|
|
|
|
2024-09-20 21:58:37 +08:00
|
|
|
|
// Account header
|
2024-09-20 23:11:17 +08:00
|
|
|
|
writer.WriteAccountHeader((uint)_character.Account.AccountId);
|
2024-09-10 00:31:40 +08:00
|
|
|
|
|
|
|
|
|
// Spawn position
|
2024-09-21 09:23:14 +08:00
|
|
|
|
writer.WritePosition(Position);
|
2024-09-10 00:31:40 +08:00
|
|
|
|
|
2024-09-20 11:48:27 +08:00
|
|
|
|
writer.Write((ushort)0); // padding?
|
2024-09-10 00:31:40 +08:00
|
|
|
|
writer.WriteFixedLengthASCII("Character", 32);
|
2024-09-20 11:48:27 +08:00
|
|
|
|
writer.Write((ushort)1); // 0x44
|
|
|
|
|
writer.Write((ushort)0); // 0x46
|
|
|
|
|
writer.Write((uint)602); // 0x48
|
|
|
|
|
writer.Write((uint)1); // 0x4C
|
|
|
|
|
writer.Write((uint)53); // 0x50
|
2024-11-29 10:01:28 +08:00
|
|
|
|
writer.Write((uint)100); // 0x54
|
|
|
|
|
writer.Write((uint)(IsItMe ? CharacterSpawnType.Myself : CharacterSpawnType.Other)); // 0x58
|
2024-09-20 11:48:27 +08:00
|
|
|
|
writer.Write((ushort)559); // 0x5C
|
|
|
|
|
writer.Write((ushort)306); // 0x5E
|
2024-11-29 10:01:28 +08:00
|
|
|
|
|
|
|
|
|
// Character
|
|
|
|
|
writer.Write((uint)_character.AccountID); // player ID copy
|
|
|
|
|
writer.Write((uint)_character.CharacterID); // "char array ugggghhhhh" according to PolarisLegacy
|
2024-09-20 11:48:27 +08:00
|
|
|
|
writer.Write((uint)0); // "voiceParam_unknown4"
|
|
|
|
|
writer.Write((uint)0); // "voiceParam_unknown8"
|
2024-09-10 00:31:40 +08:00
|
|
|
|
writer.WriteFixedLengthUtf16(_character.Name, 16);
|
2024-09-18 00:55:35 +08:00
|
|
|
|
writer.Write((uint)0); // 0x90
|
2024-09-10 00:31:40 +08:00
|
|
|
|
writer.WriteStruct(_character.Looks);
|
|
|
|
|
writer.WriteStruct(_character.Jobs);
|
2024-11-29 10:01:28 +08:00
|
|
|
|
|
2024-09-10 00:31:40 +08:00
|
|
|
|
writer.WriteFixedLengthUtf16("", 32); // title?
|
2024-11-29 10:01:28 +08:00
|
|
|
|
|
2024-09-20 11:48:27 +08:00
|
|
|
|
writer.Write((uint)0); // 0x204
|
|
|
|
|
writer.Write((uint)0); // gmflag?
|
2024-11-25 23:33:41 +08:00
|
|
|
|
writer.WriteFixedLengthUtf16(_character.Account.Nickname, 16); // Nickname, maybe not 16 chars?
|
2024-09-10 00:31:40 +08:00
|
|
|
|
for (var i = 0; i < 64; i++)
|
2024-09-20 11:48:27 +08:00
|
|
|
|
writer.Write((byte)0);
|
2024-09-10 00:31:40 +08:00
|
|
|
|
|
|
|
|
|
return writer.ToArray();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override PacketHeader GetHeader()
|
|
|
|
|
{
|
2024-09-21 12:35:09 +08:00
|
|
|
|
return new PacketHeader(0x08, 0x04, PacketFlags.None);
|
2024-09-10 00:31:40 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
}
|
|
|
|
|
}
|