using PSO2SERVER.Database; using PSO2SERVER.Models; using PSO2SERVER.Zone; using System.Runtime.InteropServices; using static PSO2SERVER.Models.CharacterStruct; using static PSO2SERVER.Protocol.Packets.CharacterSpawnPacket; namespace PSO2SERVER.Protocol.Packets { public class CharacterSpawnPacket : Packet { public enum CharacterSpawnType : byte { /// Spawned character is not related to the receiver. Other = 0x27, /// Spawned character is related to the receiver. Myself = 0x2F, Undefined = 0xFF, } //private readonly Character _character; //public byte IsItMe = (byte)CharacterSpawnType.Myself; //public uint IsGM = 0; /// /// CharacterSpawnPacket Struct /// /// Spawned character's player object. public ObjectHeader ObjHeader { get; set; } = new ObjectHeader(); public PSOLocation ObjPosition { get; set; } = new PSOLocation(); public ushort Unk1 { get; set; } = 0; /// Always `Character`. (?) public string ObjName { get; set; } = "Character";//0x20 public ushort Unk3 { get; set; } = 1; public ushort Unk4 { get; set; } public uint Unk5 { get; set; } public uint Unk6 { get; set; } public uint Unk7 { get; set; } public uint Unk8 { get; set; } public CharacterSpawnType SpawnType { get; set; } public byte Unk9 { get; set; } public ushort Unk10 { get; set; } public Character Character { get; set; } public uint Unk11 { get; set; } /// Set to `1` if the player is a GM. public uint GmFlag { get; set; } public string Nickname { get; set; } //#[SeekAfter(0x60)] public byte[] Unk12 { get; set; } = new byte[0x40]; public CharacterSpawnPacket(Character character, PSOLocation locatiion) { ObjHeader = new ObjectHeader((uint)character.Account.AccountId, ObjectType.Player); Character = character; ObjPosition = locatiion; } public CharacterSpawnPacket(Character character, PSOLocation locatiion, bool isme, bool isgm) { ObjHeader = new ObjectHeader((uint)character.Account.AccountId, ObjectType.Player); Character = character; SpawnType = isme ? CharacterSpawnType.Myself : CharacterSpawnType.Other; ObjPosition = locatiion; GmFlag = isgm ? (uint)1 : 0; } #region implemented abstract members of Packet public override byte[] Build() { var pkt = new PacketWriter(); // Accounts header pkt.WriteStruct(ObjHeader); // Spawn position pkt.WritePosition(ObjPosition); pkt.Write(Unk1); pkt.WriteFixedLengthASCII(ObjName, 0x20); pkt.Write(Unk3); // 0x44 pkt.Write(Unk4); pkt.Write(Unk5); pkt.Write(Unk6); pkt.Write(Unk7); pkt.Write(Unk8); pkt.Write((byte)SpawnType); pkt.Write(Unk9); pkt.Write(Unk10); // Character data. pkt.Write(Character.BuildCharacterByteArray()); pkt.Write(Unk11); pkt.Write(GmFlag); pkt.WriteFixedLengthUtf16(Character.Account.Nickname, 0x10); //for (var i = 0; i < 0x60; i++) // pkt.Write((byte)0); //pkt.Write(unk12); //pkt.Write((ushort)0); // 0x46 //pkt.Write((uint)602); // 0x48 //pkt.Write((uint)1); // 0x4C //pkt.Write((uint)53); // 0x50 //pkt.Write((uint)0); // 0x54 //// Character spawn type. //pkt.Write(IsItMe); // 0x58 //pkt.Write((byte)0x00); //pkt.Write((ushort)0x00); //////writer.write((ushort)0x022f); // 0x5c ////writer.write((byte)0x2f); // 0x5c ////writer.write((byte)0x02); //////writer.write((ushort)0x0132); // 0x5e ////writer.write((byte)0x32); ////writer.write((byte)0x01); ////JobParam jobParam = _character.Jobs; ////jobParam.mainClass = ClassType.Luster; ////jobParam.subClass = ClassType.Phantom; ////jobParam.entries.Luster.level = 100; //// Character data. //pkt.Write((uint)_character.AccountID); //pkt.Write((uint)_character.CharacterID); //pkt.Write((uint)_character.Unk1);//4 //pkt.Write((uint)_character.VoiceType);//4 //pkt.Write((ushort)_character.Unk2);//2 //pkt.Write(_character.VoicePitch);//2 //pkt.WriteFixedLengthUtf16(_character.Name, 16); //pkt.Write((uint)_character.Unk3); // 0x90 //pkt.WriteStruct(_character.Looks); //pkt.WriteStruct(_character.Jobs); //pkt.WriteFixedLengthUtf16(_character.Account.Nickname, 16); //pkt.WriteBytes(0, 116); //pkt.Write((uint)0); // 0x204 //pkt.Write(IsGM); // gmflag? //for (var i = 0; i < 0x60; i++) // pkt.Write((byte)0); //for (var i = 0; i < 0x40; i++) // writer.Write((byte)0); return pkt.ToArray(); } public override PacketHeader GetHeader() { return new PacketHeader(0x08, 0x04, PacketFlags.None); } #endregion } }