/// <summary> /// Create a new <see cref="Inventory"/> from supplied <see cref="CharacterCreationEntry"/>. /// </summary> public Inventory(ulong owner, CharacterCreationEntry creationEntry) { characterId = owner; foreach ((InventoryLocation location, uint defaultCapacity) in AssetManager.InventoryLocationCapacities) { bags.Add(location, new Bag(location, defaultCapacity)); } foreach (uint itemId in creationEntry.ItemIds.Where(i => i != 0u)) { Item2Entry itemEntry = GameTableManager.Item.GetEntry(itemId); if (itemEntry == null) { throw new ArgumentNullException(); } Item2TypeEntry typeEntry = GameTableManager.ItemType.GetEntry(itemEntry.Item2TypeId); if (typeEntry.ItemSlotId == 0) { ItemCreate(itemEntry, 1u); } else { ItemCreate(itemEntry); } } }
/// <summary> /// Create a new <see cref="Inventory"/> from supplied <see cref="CharacterCreationEntry"/>. /// </summary> public Inventory(ulong owner, CharacterCreationEntry creationEntry) { characterId = owner; // only need the equipped bag for character creation var pair = AssetManager.InventoryLocationCapacities .SingleOrDefault(c => c.Key == InventoryLocation.Equipped); bags.Add(pair.Key, new Bag(pair.Key, pair.Value)); foreach (uint itemId in creationEntry.ItemIds.Where(i => i != 0u)) { ItemCreate(itemId); } }
public static void HandleCharacterCreate(WorldSession session, ClientCharacterCreate characterCreate) { try { // TODO: validate name and path CharacterCreationEntry creationEntry = GameTableManager.CharacterCreation.GetEntry(characterCreate.CharacterCreationId); if (creationEntry == null) { throw new InvalidPacketValueException(); } if (creationEntry.EntitlementIdRequired != 0u) { // TODO: Aurin engineer has this } var character = new Character { AccountId = session.Account.Id, Id = AssetManager.NextCharacterId, Name = characterCreate.Name, Race = (byte)creationEntry.RaceId, Sex = (byte)creationEntry.Sex, Class = (byte)creationEntry.ClassId, Level = 1, FactionId = (ushort)creationEntry.FactionId, ActivePath = characterCreate.Path }; for (Path path = Path.Soldier; path <= Path.Explorer; path++) { character.CharacterPath.Add(new CharacterPath { Path = (byte)path, Unlocked = Convert.ToByte(characterCreate.Path == (byte)path) }); } // merge seperate label and value lists into a single dictonary Dictionary <uint, uint> customisations = characterCreate.Labels .Zip(characterCreate.Values, (l, v) => new { l, v }) .ToDictionary(p => p.l, p => p.v); foreach ((uint label, uint value) in customisations) { character.CharacterCustomisation.Add(new CharacterCustomisation { Label = label, Value = value }); CharacterCustomizationEntry entry = GetCharacterCustomisation(customisations, creationEntry.RaceId, creationEntry.Sex, label, value); if (entry == null) { continue; } character.CharacterAppearance.Add(new CharacterAppearance { Slot = (byte)entry.ItemSlotId, DisplayId = (ushort)entry.ItemDisplayId }); } for (int i = 0; i < characterCreate.Bones.Count; ++i) { character.CharacterBone.Add(new CharacterBone { BoneIndex = (byte)(i), Bone = characterCreate.Bones[i] }); } //TODO: handle starting locations per race character.LocationX = -7683.809f; character.LocationY = -942.5914f; character.LocationZ = -666.6343f; character.WorldId = 870; // create a temporary inventory to create starting gear var inventory = new Inventory(character.Id, creationEntry); var items = inventory .SelectMany(b => b) .Select(i => i); // TODO: actually error check this session.EnqueueEvent(new TaskEvent(CharacterDatabase.CreateCharacter(character, items), () => { session.Characters.Add(character); session.EnqueueMessageEncrypted(new ServerCharacterCreate { CharacterId = character.Id, WorldId = character.WorldId, Result = 3 }); })); } catch { session.EnqueueMessageEncrypted(new ServerCharacterCreate { Result = 0 }); throw; } CharacterCustomizationEntry GetCharacterCustomisation(Dictionary <uint, uint> customisations, uint race, uint sex, uint primaryLabel, uint primaryValue) { ImmutableList <CharacterCustomizationEntry> entries = AssetManager.GetPrimaryCharacterCustomisation(race, sex, primaryLabel, primaryValue); if (entries == null) { return(null); } if (entries.Count == 1) { return(entries[0]); } // customisation has multiple results, filter with secondary label and value uint secondaryLabel = entries.First(e => e.CharacterCustomizationLabelId01 != 0).CharacterCustomizationLabelId01; uint secondaryValue = customisations[secondaryLabel]; CharacterCustomizationEntry entry = entries.SingleOrDefault(e => e.CharacterCustomizationLabelId01 == secondaryLabel && e.Value01 == secondaryValue); return(entry ?? entries.Single(e => e.CharacterCustomizationLabelId01 == 0 && e.Value01 == 0)); } }
public static void HandleCharacterCreate(WorldSession session, ClientCharacterCreate characterCreate) { try { // TODO: validate name and path if (DatabaseManager.Instance.CharacterDatabase.CharacterNameExists(characterCreate.Name)) { session.EnqueueMessageEncrypted(new ServerCharacterCreate { Result = CharacterModifyResult.CreateFailed_UniqueName }); return; } CharacterCreationEntry creationEntry = GameTableManager.Instance.CharacterCreation.GetEntry(characterCreate.CharacterCreationId); if (creationEntry == null) { throw new InvalidPacketValueException(); } if (creationEntry.EntitlementIdRequired != 0u) { // TODO: Aurin engineer has this } var character = new CharacterModel { AccountId = session.Account.Id, Id = AssetManager.Instance.NextCharacterId, Name = characterCreate.Name, Race = (byte)creationEntry.RaceId, Sex = (byte)creationEntry.Sex, Class = (byte)creationEntry.ClassId, FactionId = (ushort)creationEntry.FactionId, ActivePath = characterCreate.Path }; for (Path path = Path.Soldier; path <= Path.Explorer; path++) { character.Path.Add(new CharacterPathModel { Path = (byte)path, Unlocked = Convert.ToByte(characterCreate.Path == (byte)path) }); } // merge seperate label and value lists into a single dictonary Dictionary <uint, uint> customisations = characterCreate.Labels .Zip(characterCreate.Values, (l, v) => new { l, v }) .ToDictionary(p => p.l, p => p.v); foreach ((uint label, uint value) in customisations) { character.Customisation.Add(new CharacterCustomisationModel { Label = label, Value = value }); CharacterCustomizationEntry entry = GetCharacterCustomisation(customisations, creationEntry.RaceId, creationEntry.Sex, label, value); if (entry == null) { continue; } character.Appearance.Add(new CharacterAppearanceModel { Slot = (byte)entry.ItemSlotId, DisplayId = (ushort)entry.ItemDisplayId }); } for (int i = 0; i < characterCreate.Bones.Count; ++i) { character.Bone.Add(new CharacterBoneModel { BoneIndex = (byte)(i), Bone = characterCreate.Bones[i] }); } //TODO: handle starting locations per race character.LocationX = -7683.809f; character.LocationY = -942.5914f; character.LocationZ = -666.6343f; character.WorldId = 870; character.ActiveSpec = 0; // create initial LAS abilities UILocation location = 0; foreach (SpellLevelEntry spellLevelEntry in GameTableManager.Instance.SpellLevel.Entries .Where(s => s.ClassId == character.Class && s.CharacterLevel == 1)) { Spell4Entry spell4Entry = GameTableManager.Instance.Spell4.GetEntry(spellLevelEntry.Spell4Id); if (spell4Entry == null) { continue; } character.Spell.Add(new CharacterSpellModel { Id = character.Id, Spell4BaseId = spell4Entry.Spell4BaseIdBaseSpell, Tier = 1 }); character.ActionSetShortcut.Add(new CharacterActionSetShortcutModel { Id = character.Id, SpecIndex = 0, Location = (ushort)location, ShortcutType = (byte)ShortcutType.Spell, ObjectId = spell4Entry.Spell4BaseIdBaseSpell, Tier = 1 }); location++; } // create a temporary inventory to create starting gear var inventory = new Inventory(character.Id, creationEntry); IEnumerable <Item> items = inventory .SelectMany(b => b) .Select(i => i); //TODO: handle starting stats per class/race character.Stat.Add(new CharacterStatModel { Id = character.Id, Stat = (byte)Stat.Health, Value = 800 }); character.Stat.Add(new CharacterStatModel { Id = character.Id, Stat = (byte)Stat.Shield, Value = 450 }); character.Stat.Add(new CharacterStatModel { Id = character.Id, Stat = (byte)Stat.Dash, Value = 200 }); character.Stat.Add(new CharacterStatModel { Id = character.Id, Stat = (byte)Stat.Level, Value = 1 }); character.Stat.Add(new CharacterStatModel { Id = character.Id, Stat = (byte)Stat.StandState, Value = 3 }); // TODO: actually error check this session.EnqueueEvent(new TaskEvent(DatabaseManager.Instance.CharacterDatabase.Save(c => { c.Character.Add(character); foreach (Item item in items) { item.Save(c); } }), () => { session.Characters.Add(character); session.EnqueueMessageEncrypted(new ServerCharacterCreate { CharacterId = character.Id, WorldId = character.WorldId, Result = CharacterModifyResult.CreateOk }); })); } catch { session.EnqueueMessageEncrypted(new ServerCharacterCreate { Result = CharacterModifyResult.CreateFailed }); throw; } CharacterCustomizationEntry GetCharacterCustomisation(Dictionary <uint, uint> customisations, uint race, uint sex, uint primaryLabel, uint primaryValue) { ImmutableList <CharacterCustomizationEntry> entries = AssetManager.Instance.GetPrimaryCharacterCustomisation(race, sex, primaryLabel, primaryValue); if (entries == null) { return(null); } if (entries.Count == 1) { return(entries[0]); } // customisation has multiple results, filter with secondary label and value uint secondaryLabel = entries.First(e => e.CharacterCustomizationLabelId01 != 0).CharacterCustomizationLabelId01; uint secondaryValue = customisations[secondaryLabel]; CharacterCustomizationEntry entry = entries.SingleOrDefault(e => e.CharacterCustomizationLabelId01 == secondaryLabel && e.Value01 == secondaryValue); return(entry ?? entries.Single(e => e.CharacterCustomizationLabelId01 == 0 && e.Value01 == 0)); } }