using System.Buffers.Binary; namespace AcDream.Core.Net.Messages; /// /// Outbound Magic_CastSpell GameActions — targeted and untargeted /// variants. From r01 §2 + r08 §3 opcodes 0x0048 / 0x004A. /// /// /// Wire layouts (inside the 0xF7B1 GameAction envelope): /// /// /// /// Untargeted (0x0048): /// /// u32 0xF7B1 /// u32 gameActionSequence /// u32 0x0048 /// u32 spellId /// /// /// /// /// Targeted (0x004A): /// /// u32 0xF7B1 /// u32 gameActionSequence /// u32 0x004A /// u32 targetGuid /// u32 spellId /// /// /// public static class CastSpellRequest { public const uint GameActionEnvelope = 0xF7B1u; public const uint UntargetedSubOpcode = 0x0048u; public const uint TargetedSubOpcode = 0x004Au; /// Build an untargeted cast (buff self, recall, self-heal, etc). public static byte[] BuildUntargeted(uint gameActionSequence, uint spellId) { byte[] body = new byte[16]; BinaryPrimitives.WriteUInt32LittleEndian(body, GameActionEnvelope); BinaryPrimitives.WriteUInt32LittleEndian(body.AsSpan(4), gameActionSequence); BinaryPrimitives.WriteUInt32LittleEndian(body.AsSpan(8), UntargetedSubOpcode); BinaryPrimitives.WriteUInt32LittleEndian(body.AsSpan(12), spellId); return body; } /// /// Build a targeted cast (projectile attacks, target buffs, debuffs). /// public static byte[] BuildTargeted(uint gameActionSequence, uint targetGuid, uint spellId) { byte[] body = new byte[20]; BinaryPrimitives.WriteUInt32LittleEndian(body, GameActionEnvelope); BinaryPrimitives.WriteUInt32LittleEndian(body.AsSpan(4), gameActionSequence); BinaryPrimitives.WriteUInt32LittleEndian(body.AsSpan(8), TargetedSubOpcode); BinaryPrimitives.WriteUInt32LittleEndian(body.AsSpan(12), targetGuid); BinaryPrimitives.WriteUInt32LittleEndian(body.AsSpan(16), spellId); return body; } }