public static CreateResult Create(CharacterCreateInfo characterCreateInfo, Weenie weenie, ObjectGuid guid, uint accountId, out Player player) { var cg = DatManager.PortalDat.CharGen; player = new Player(weenie, guid, accountId); player.SetProperty(PropertyInt.HeritageGroup, (int)characterCreateInfo.Heritage); player.SetProperty(PropertyString.HeritageGroup, cg.HeritageGroups[characterCreateInfo.Heritage].Name); player.SetProperty(PropertyInt.Gender, (int)characterCreateInfo.Gender); player.SetProperty(PropertyString.Sex, characterCreateInfo.Gender == 1 ? "Male" : "Female"); //player.SetProperty(PropertyDataId.Icon, cg.HeritageGroups[characterCreateInfo.Heritage].IconImage); // I don't believe this is used anywhere in the client, but it might be used by a future custom launcher // pull character data from the dat file var sex = cg.HeritageGroups[characterCreateInfo.Heritage].Genders[(int)characterCreateInfo.Gender]; player.SetProperty(PropertyDataId.MotionTable, sex.MotionTable); player.SetProperty(PropertyDataId.SoundTable, sex.SoundTable); player.SetProperty(PropertyDataId.PhysicsEffectTable, sex.PhysicsTable); player.SetProperty(PropertyDataId.Setup, sex.SetupID); player.SetProperty(PropertyDataId.PaletteBase, sex.BasePalette); player.SetProperty(PropertyDataId.CombatTable, sex.CombatTable); // Check the character scale if (sex.Scale != 100u) { player.SetProperty(PropertyFloat.DefaultScale, (sex.Scale / 100f)); // Scale is stored as a percentage } // Get the hair first, because we need to know if you're bald, and that's the name of that tune! var hairstyle = sex.HairStyleList[Convert.ToInt32(characterCreateInfo.Apperance.HairStyle)]; // Certain races (Undead, Tumeroks, Others?) have multiple body styles available. This is controlled via the "hair style". if (hairstyle.AlternateSetup > 0) { player.SetProperty(PropertyDataId.Setup, hairstyle.AlternateSetup); } player.SetProperty(PropertyDataId.EyesTexture, sex.GetEyeTexture(characterCreateInfo.Apperance.Eyes, hairstyle.Bald)); player.SetProperty(PropertyDataId.DefaultEyesTexture, sex.GetDefaultEyeTexture(characterCreateInfo.Apperance.Eyes, hairstyle.Bald)); player.SetProperty(PropertyDataId.NoseTexture, sex.GetNoseTexture(characterCreateInfo.Apperance.Nose)); player.SetProperty(PropertyDataId.DefaultNoseTexture, sex.GetDefaultNoseTexture(characterCreateInfo.Apperance.Nose)); player.SetProperty(PropertyDataId.MouthTexture, sex.GetMouthTexture(characterCreateInfo.Apperance.Mouth)); player.SetProperty(PropertyDataId.DefaultMouthTexture, sex.GetDefaultMouthTexture(characterCreateInfo.Apperance.Mouth)); player.Character.HairTexture = sex.GetHairTexture(characterCreateInfo.Apperance.HairStyle); player.Character.DefaultHairTexture = sex.GetDefaultHairTexture(characterCreateInfo.Apperance.HairStyle); player.SetProperty(PropertyDataId.HeadObject, sex.GetHeadObject(characterCreateInfo.Apperance.HairStyle)); // Skin is stored as PaletteSet (list of Palettes), so we need to read in the set to get the specific palette var skinPalSet = DatManager.PortalDat.ReadFromDat <PaletteSet>(sex.SkinPalSet); player.SetProperty(PropertyDataId.SkinPalette, skinPalSet.GetPaletteID(characterCreateInfo.Apperance.SkinHue)); player.SetProperty(PropertyFloat.Shade, characterCreateInfo.Apperance.SkinHue); // Hair is stored as PaletteSet (list of Palettes), so we need to read in the set to get the specific palette var hairPalSet = DatManager.PortalDat.ReadFromDat <PaletteSet>(sex.HairColorList[Convert.ToInt32(characterCreateInfo.Apperance.HairColor)]); player.SetProperty(PropertyDataId.HairPalette, hairPalSet.GetPaletteID(characterCreateInfo.Apperance.HairHue)); // Eye Color player.SetProperty(PropertyDataId.EyesPalette, sex.EyeColorList[Convert.ToInt32(characterCreateInfo.Apperance.EyeColor)]); if (characterCreateInfo.Apperance.HeadgearStyle < 0xFFFFFFFF) // No headgear is max UINT { var hat = GetClothingObject(sex.GetHeadgearWeenie(characterCreateInfo.Apperance.HeadgearStyle), characterCreateInfo.Apperance.HeadgearColor, characterCreateInfo.Apperance.HeadgearHue); if (hat != null) { player.TryEquipObject(hat, hat.GetProperty(PropertyInt.ValidLocations) ?? 0); } else { CreateIOU(player, sex.GetHeadgearWeenie(characterCreateInfo.Apperance.HeadgearStyle)); } } var shirt = GetClothingObject(sex.GetShirtWeenie(characterCreateInfo.Apperance.ShirtStyle), characterCreateInfo.Apperance.ShirtColor, characterCreateInfo.Apperance.ShirtHue); if (shirt != null) { player.TryEquipObject(shirt, shirt.GetProperty(PropertyInt.ValidLocations) ?? 0); } else { CreateIOU(player, sex.GetShirtWeenie(characterCreateInfo.Apperance.ShirtStyle)); } var pants = GetClothingObject(sex.GetPantsWeenie(characterCreateInfo.Apperance.PantsStyle), characterCreateInfo.Apperance.PantsColor, characterCreateInfo.Apperance.PantsHue); if (pants != null) { player.TryEquipObject(pants, pants.GetProperty(PropertyInt.ValidLocations) ?? 0); } else { CreateIOU(player, sex.GetPantsWeenie(characterCreateInfo.Apperance.PantsStyle)); } var shoes = GetClothingObject(sex.GetFootwearWeenie(characterCreateInfo.Apperance.FootwearStyle), characterCreateInfo.Apperance.FootwearColor, characterCreateInfo.Apperance.FootwearHue); if (shoes != null) { player.TryEquipObject(shoes, shoes.GetProperty(PropertyInt.ValidLocations) ?? 0); } else { CreateIOU(player, sex.GetFootwearWeenie(characterCreateInfo.Apperance.FootwearStyle)); } string templateName = cg.HeritageGroups[characterCreateInfo.Heritage].Templates[characterCreateInfo.TemplateOption].Name; //player.SetProperty(PropertyString.Title, templateName); player.SetProperty(PropertyString.Template, templateName); player.AddTitle(cg.HeritageGroups[characterCreateInfo.Heritage].Templates[characterCreateInfo.TemplateOption].Title, true); // stats uint totalAttributeCredits = cg.HeritageGroups[characterCreateInfo.Heritage].AttributeCredits; uint usedAttributeCredits = 0; player.Strength.StartingValue = ValidateAttributeCredits(characterCreateInfo.StrengthAbility, usedAttributeCredits, totalAttributeCredits); usedAttributeCredits += player.Strength.StartingValue; player.Endurance.StartingValue = ValidateAttributeCredits(characterCreateInfo.EnduranceAbility, usedAttributeCredits, totalAttributeCredits); usedAttributeCredits += player.Endurance.StartingValue; player.Coordination.StartingValue = ValidateAttributeCredits(characterCreateInfo.CoordinationAbility, usedAttributeCredits, totalAttributeCredits); usedAttributeCredits += player.Coordination.StartingValue; player.Quickness.StartingValue = ValidateAttributeCredits(characterCreateInfo.QuicknessAbility, usedAttributeCredits, totalAttributeCredits); usedAttributeCredits += player.Quickness.StartingValue; player.Focus.StartingValue = ValidateAttributeCredits(characterCreateInfo.FocusAbility, usedAttributeCredits, totalAttributeCredits); usedAttributeCredits += player.Focus.StartingValue; player.Self.StartingValue = ValidateAttributeCredits(characterCreateInfo.SelfAbility, usedAttributeCredits, totalAttributeCredits); usedAttributeCredits += player.Self.StartingValue; // Validate this is equal to actual attribute credits. 330 for all but "Olthoi", which have 60 if (usedAttributeCredits > 330 || ((characterCreateInfo.Heritage == (int)HeritageGroup.Olthoi || characterCreateInfo.Heritage == (int)HeritageGroup.OlthoiAcid) && usedAttributeCredits > 60)) { return(CreateResult.TooManySkillCreditsUsed); } // data we don't care about //characterCreateInfo.CharacterSlot; //characterCreateInfo.ClassId; // characters start with max vitals player.Health.Current = player.Health.Base; player.Stamina.Current = player.Stamina.Base; player.Mana.Current = player.Mana.Base; // set initial skill credit amount. 52 for all but "Olthoi", which have 68 player.SetProperty(PropertyInt.AvailableSkillCredits, (int)cg.HeritageGroups[characterCreateInfo.Heritage].SkillCredits); for (int i = 0; i < characterCreateInfo.SkillAdvancementClasses.Count; i++) { var skill = (Skill)i; var skillCost = skill.GetCost(); var sac = characterCreateInfo.SkillAdvancementClasses[i]; if (sac == SkillAdvancementClass.Specialized) { player.TrainSkill(skill, skillCost.TrainingCost); player.SpecializeSkill(skill, skillCost.SpecializationCost); } else if (sac == SkillAdvancementClass.Trained) { player.TrainSkill(skill, skillCost.TrainingCost); } else if (skillCost != null && sac == SkillAdvancementClass.Untrained) { player.UntrainSkill(skill, skillCost.TrainingCost); } } // grant starter items based on skills var starterGearConfig = StarterGearFactory.GetStarterGearConfiguration(); var grantedWeenies = new List <uint>(); foreach (var skillGear in starterGearConfig.Skills) { var charSkill = player.Skills[(Skill)skillGear.SkillId]; if (charSkill.AdvancementClass == SkillAdvancementClass.Trained || charSkill.AdvancementClass == SkillAdvancementClass.Specialized) { foreach (var item in skillGear.Gear) { if (grantedWeenies.Contains(item.WeenieId)) { var existingItem = player.Inventory.Values.FirstOrDefault(i => i.WeenieClassId == item.WeenieId); if (existingItem == null || (existingItem.MaxStackSize ?? 1) <= 1) { continue; } existingItem.StackSize += item.StackSize; continue; } var loot = WorldObjectFactory.CreateNewWorldObject(item.WeenieId); if (loot != null) { if (loot.StackSize.HasValue && loot.MaxStackSize.HasValue) { loot.StackSize = (item.StackSize <= loot.MaxStackSize) ? item.StackSize : loot.MaxStackSize; } } else { CreateIOU(player, item.WeenieId); continue; } if (player.TryAddToInventory(loot)) { grantedWeenies.Add(item.WeenieId); } } var heritageLoot = skillGear.Heritage.FirstOrDefault(sh => sh.HeritageId == characterCreateInfo.Heritage); if (heritageLoot != null) { foreach (var item in heritageLoot.Gear) { if (grantedWeenies.Contains(item.WeenieId)) { var existingItem = player.Inventory.Values.FirstOrDefault(i => i.WeenieClassId == item.WeenieId); if (existingItem == null || (existingItem.MaxStackSize ?? 1) <= 1) { continue; } existingItem.StackSize += item.StackSize; continue; } var loot = WorldObjectFactory.CreateNewWorldObject(item.WeenieId); if (loot != null) { if (loot.StackSize.HasValue && loot.MaxStackSize.HasValue) { loot.StackSize = (item.StackSize <= loot.MaxStackSize) ? item.StackSize : loot.MaxStackSize; } } else { CreateIOU(player, item.WeenieId); continue; } if (player.TryAddToInventory(loot)) { grantedWeenies.Add(item.WeenieId); } } } foreach (var spell in skillGear.Spells) { // Olthoi Spitter is a special case if (characterCreateInfo.Heritage == (int)HeritageGroup.OlthoiAcid) { player.AddKnownSpell(spell.SpellId); // Continue to next spell as Olthoi spells do not have the SpecializedOnly field continue; } if (charSkill.AdvancementClass == SkillAdvancementClass.Trained && spell.SpecializedOnly == false) { player.AddKnownSpell(spell.SpellId); } else if (charSkill.AdvancementClass == SkillAdvancementClass.Specialized) { player.AddKnownSpell(spell.SpellId); } } } } player.Name = characterCreateInfo.Name; player.Character.Name = player.Name; // Index used to determine the starting location var startArea = characterCreateInfo.StartArea; player.Location = new Position(cg.StarterAreas[(int)startArea].Locations[0].ObjCellID, cg.StarterAreas[(int)startArea].Locations[0].Frame.Origin.X, cg.StarterAreas[(int)startArea].Locations[0].Frame.Origin.Y, cg.StarterAreas[(int)startArea].Locations[0].Frame.Origin.Z, cg.StarterAreas[(int)startArea].Locations[0].Frame.Orientation.X, cg.StarterAreas[(int)startArea].Locations[0].Frame.Orientation.Y, cg.StarterAreas[(int)startArea].Locations[0].Frame.Orientation.Z, cg.StarterAreas[(int)startArea].Locations[0].Frame.Orientation.W); player.Instantiation = player.Location; player.Sanctuary = player.Location; CharacterCreateSetDefaultCharacterOptions(player); return(CreateResult.Success); }
public static CreateResult Create(CharacterCreateInfo characterCreateInfo, Weenie weenie, ObjectGuid guid, uint accountId, WeenieType weenieType, out Player player) { var heritageGroup = DatManager.PortalDat.CharGen.HeritageGroups[characterCreateInfo.Heritage]; if (weenieType == WeenieType.Admin) { player = new Admin(weenie, guid, accountId); } else if (weenieType == WeenieType.Sentinel) { player = new Sentinel(weenie, guid, accountId); } else { player = new Player(weenie, guid, accountId); } player.SetProperty(PropertyInt.HeritageGroup, (int)characterCreateInfo.Heritage); player.SetProperty(PropertyString.HeritageGroup, heritageGroup.Name); player.SetProperty(PropertyInt.Gender, (int)characterCreateInfo.Gender); player.SetProperty(PropertyString.Sex, characterCreateInfo.Gender == 1 ? "Male" : "Female"); //player.SetProperty(PropertyDataId.Icon, cgh.IconImage); // I don't believe this is used anywhere in the client, but it might be used by a future custom launcher // pull character data from the dat file var sex = heritageGroup.Genders[(int)characterCreateInfo.Gender]; player.SetProperty(PropertyDataId.MotionTable, sex.MotionTable); player.SetProperty(PropertyDataId.SoundTable, sex.SoundTable); player.SetProperty(PropertyDataId.PhysicsEffectTable, sex.PhysicsTable); player.SetProperty(PropertyDataId.Setup, sex.SetupID); player.SetProperty(PropertyDataId.PaletteBase, sex.BasePalette); player.SetProperty(PropertyDataId.CombatTable, sex.CombatTable); // Check the character scale if (sex.Scale != 100u) { player.SetProperty(PropertyFloat.DefaultScale, (sex.Scale / 100f)); // Scale is stored as a percentage } // Get the hair first, because we need to know if you're bald, and that's the name of that tune! var hairstyle = sex.HairStyleList[Convert.ToInt32(characterCreateInfo.Apperance.HairStyle)]; // Olthoi and Gear Knights have a "Body Style" instead of a hair style. These styles have multiple model/texture changes, instead of a single head/hairstyle. // Storing this value allows us to send the proper appearance ObjDesc if (hairstyle.ObjDesc.AnimPartChanges.Count > 1) { player.SetProperty(PropertyInt.Hairstyle, (int)characterCreateInfo.Apperance.HairStyle); } // Certain races (Undead, Tumeroks, Others?) have multiple body styles available. This is controlled via the "hair style". if (hairstyle.AlternateSetup > 0) { player.SetProperty(PropertyDataId.Setup, hairstyle.AlternateSetup); } player.SetProperty(PropertyDataId.EyesTexture, sex.GetEyeTexture(characterCreateInfo.Apperance.Eyes, hairstyle.Bald)); player.SetProperty(PropertyDataId.DefaultEyesTexture, sex.GetDefaultEyeTexture(characterCreateInfo.Apperance.Eyes, hairstyle.Bald)); player.SetProperty(PropertyDataId.NoseTexture, sex.GetNoseTexture(characterCreateInfo.Apperance.Nose)); player.SetProperty(PropertyDataId.DefaultNoseTexture, sex.GetDefaultNoseTexture(characterCreateInfo.Apperance.Nose)); player.SetProperty(PropertyDataId.MouthTexture, sex.GetMouthTexture(characterCreateInfo.Apperance.Mouth)); player.SetProperty(PropertyDataId.DefaultMouthTexture, sex.GetDefaultMouthTexture(characterCreateInfo.Apperance.Mouth)); player.Character.HairTexture = sex.GetHairTexture(characterCreateInfo.Apperance.HairStyle); player.Character.DefaultHairTexture = sex.GetDefaultHairTexture(characterCreateInfo.Apperance.HairStyle); // HeadObject can be null if we're dealing with GearKnight or Olthoi var headObject = sex.GetHeadObject(characterCreateInfo.Apperance.HairStyle); if (headObject != null) { player.SetProperty(PropertyDataId.HeadObject, (uint)headObject); } // Skin is stored as PaletteSet (list of Palettes), so we need to read in the set to get the specific palette var skinPalSet = DatManager.PortalDat.ReadFromDat <PaletteSet>(sex.SkinPalSet); player.SetProperty(PropertyDataId.SkinPalette, skinPalSet.GetPaletteID(characterCreateInfo.Apperance.SkinHue)); player.SetProperty(PropertyFloat.Shade, characterCreateInfo.Apperance.SkinHue); // Hair is stored as PaletteSet (list of Palettes), so we need to read in the set to get the specific palette var hairPalSet = DatManager.PortalDat.ReadFromDat <PaletteSet>(sex.HairColorList[Convert.ToInt32(characterCreateInfo.Apperance.HairColor)]); player.SetProperty(PropertyDataId.HairPalette, hairPalSet.GetPaletteID(characterCreateInfo.Apperance.HairHue)); // Eye Color player.SetProperty(PropertyDataId.EyesPalette, sex.EyeColorList[Convert.ToInt32(characterCreateInfo.Apperance.EyeColor)]); if (characterCreateInfo.Apperance.HeadgearStyle < 0xFFFFFFFF) // No headgear is max UINT { var hat = GetClothingObject(sex.GetHeadgearWeenie(characterCreateInfo.Apperance.HeadgearStyle), characterCreateInfo.Apperance.HeadgearColor, characterCreateInfo.Apperance.HeadgearHue); if (hat != null) { player.TryEquipObject(hat, hat.ValidLocations ?? 0); } else { player.TryAddToInventory(CreateIOU(sex.GetHeadgearWeenie(characterCreateInfo.Apperance.HeadgearStyle))); } } var shirt = GetClothingObject(sex.GetShirtWeenie(characterCreateInfo.Apperance.ShirtStyle), characterCreateInfo.Apperance.ShirtColor, characterCreateInfo.Apperance.ShirtHue); if (shirt != null) { player.TryEquipObject(shirt, shirt.ValidLocations ?? 0); } else { player.TryAddToInventory(CreateIOU(sex.GetShirtWeenie(characterCreateInfo.Apperance.ShirtStyle))); } var pants = GetClothingObject(sex.GetPantsWeenie(characterCreateInfo.Apperance.PantsStyle), characterCreateInfo.Apperance.PantsColor, characterCreateInfo.Apperance.PantsHue); if (pants != null) { player.TryEquipObject(pants, pants.ValidLocations ?? 0); } else { player.TryAddToInventory(CreateIOU(sex.GetPantsWeenie(characterCreateInfo.Apperance.PantsStyle))); } var shoes = GetClothingObject(sex.GetFootwearWeenie(characterCreateInfo.Apperance.FootwearStyle), characterCreateInfo.Apperance.FootwearColor, characterCreateInfo.Apperance.FootwearHue); if (shoes != null) { player.TryEquipObject(shoes, shoes.ValidLocations ?? 0); } else { player.TryAddToInventory(CreateIOU(sex.GetFootwearWeenie(characterCreateInfo.Apperance.FootwearStyle))); } string templateName = heritageGroup.Templates[characterCreateInfo.TemplateOption].Name; //player.SetProperty(PropertyString.Title, templateName); player.SetProperty(PropertyString.Template, templateName); player.AddTitle(heritageGroup.Templates[characterCreateInfo.TemplateOption].Title, true); // stats uint totalAttributeCredits = heritageGroup.AttributeCredits; uint usedAttributeCredits = 0; player.Strength.StartingValue = ValidateAttributeCredits(characterCreateInfo.StrengthAbility, usedAttributeCredits, totalAttributeCredits); usedAttributeCredits += player.Strength.StartingValue; player.Endurance.StartingValue = ValidateAttributeCredits(characterCreateInfo.EnduranceAbility, usedAttributeCredits, totalAttributeCredits); usedAttributeCredits += player.Endurance.StartingValue; player.Coordination.StartingValue = ValidateAttributeCredits(characterCreateInfo.CoordinationAbility, usedAttributeCredits, totalAttributeCredits); usedAttributeCredits += player.Coordination.StartingValue; player.Quickness.StartingValue = ValidateAttributeCredits(characterCreateInfo.QuicknessAbility, usedAttributeCredits, totalAttributeCredits); usedAttributeCredits += player.Quickness.StartingValue; player.Focus.StartingValue = ValidateAttributeCredits(characterCreateInfo.FocusAbility, usedAttributeCredits, totalAttributeCredits); usedAttributeCredits += player.Focus.StartingValue; player.Self.StartingValue = ValidateAttributeCredits(characterCreateInfo.SelfAbility, usedAttributeCredits, totalAttributeCredits); usedAttributeCredits += player.Self.StartingValue; if (usedAttributeCredits > heritageGroup.AttributeCredits) { return(CreateResult.TooManySkillCreditsUsed); } // data we don't care about //characterCreateInfo.CharacterSlot; //characterCreateInfo.ClassId; // characters start with max vitals player.Health.Current = player.Health.Base; player.Stamina.Current = player.Stamina.Base; player.Mana.Current = player.Mana.Base; // set initial skill credit amount. 52 for all but "Olthoi", which have 68 player.SetProperty(PropertyInt.AvailableSkillCredits, (int)heritageGroup.SkillCredits); for (int i = 0; i < characterCreateInfo.SkillAdvancementClasses.Count; i++) { var sac = characterCreateInfo.SkillAdvancementClasses[i]; if (sac == SkillAdvancementClass.Inactive) { continue; } if (!DatManager.PortalDat.SkillTable.SkillBaseHash.ContainsKey((uint)i)) { log.ErrorFormat("Character {0} tried to create with skill {1} that was not found in Portal dat.", characterCreateInfo.Name, i); return(CreateResult.InvalidSkillRequested); } var skill = DatManager.PortalDat.SkillTable.SkillBaseHash[(uint)i]; var trainedCost = skill.TrainedCost; var specializedCost = skill.UpgradeCostFromTrainedToSpecialized; foreach (var skillGroup in heritageGroup.Skills) { if (skillGroup.SkillNum == i) { trainedCost = skillGroup.NormalCost; specializedCost = skillGroup.PrimaryCost; break; } } if (sac == SkillAdvancementClass.Specialized) { if (!player.TrainSkill((Skill)i, trainedCost)) { return(CreateResult.FailedToTrainSkill); } if (!player.SpecializeSkill((Skill)i, specializedCost)) { return(CreateResult.FailedToSpecializeSkill); } } else if (sac == SkillAdvancementClass.Trained) { if (!player.TrainSkill((Skill)i, trainedCost)) { return(CreateResult.FailedToTrainSkill); } } else if (sac == SkillAdvancementClass.Untrained) { player.UntrainSkill((Skill)i, 0); } } var isDualWieldTrainedOrSpecialized = player.Skills[Skill.DualWield].AdvancementClass > SkillAdvancementClass.Untrained; // Set Heritage based Melee and Ranged Masteries GetMasteries(player.HeritageGroup, out WeaponType meleeMastery, out WeaponType rangedMastery); player.SetProperty(PropertyInt.MeleeMastery, (int)meleeMastery); player.SetProperty(PropertyInt.RangedMastery, (int)rangedMastery); // Set innate augs SetInnateAugmentations(player); // grant starter items based on skills var starterGearConfig = StarterGearFactory.GetStarterGearConfiguration(); var grantedWeenies = new List <uint>(); foreach (var skillGear in starterGearConfig.Skills) { var charSkill = player.Skills[(Skill)skillGear.SkillId]; if (charSkill.AdvancementClass == SkillAdvancementClass.Trained || charSkill.AdvancementClass == SkillAdvancementClass.Specialized) { foreach (var item in skillGear.Gear) { if (grantedWeenies.Contains(item.WeenieId)) { var existingItem = player.Inventory.Values.FirstOrDefault(i => i.WeenieClassId == item.WeenieId); if (existingItem == null || (existingItem.MaxStackSize ?? 1) <= 1) { continue; } existingItem.SetStackSize(existingItem.StackSize + item.StackSize); continue; } var loot = WorldObjectFactory.CreateNewWorldObject(item.WeenieId); if (loot != null) { if (loot.StackSize.HasValue && loot.MaxStackSize.HasValue) { loot.SetStackSize((item.StackSize <= loot.MaxStackSize) ? item.StackSize : loot.MaxStackSize); } } else { player.TryAddToInventory(CreateIOU(item.WeenieId)); } if (loot != null && player.TryAddToInventory(loot)) { grantedWeenies.Add(item.WeenieId); } if (isDualWieldTrainedOrSpecialized && loot != null) { if (loot.WeenieType == WeenieType.MeleeWeapon) { var dualloot = WorldObjectFactory.CreateNewWorldObject(item.WeenieId); if (dualloot != null) { player.TryAddToInventory(dualloot); } else { player.TryAddToInventory(CreateIOU(item.WeenieId)); } } } } var heritageLoot = skillGear.Heritage.FirstOrDefault(sh => sh.HeritageId == characterCreateInfo.Heritage); if (heritageLoot != null) { foreach (var item in heritageLoot.Gear) { if (grantedWeenies.Contains(item.WeenieId)) { var existingItem = player.Inventory.Values.FirstOrDefault(i => i.WeenieClassId == item.WeenieId); if (existingItem == null || (existingItem.MaxStackSize ?? 1) <= 1) { continue; } existingItem.SetStackSize(existingItem.StackSize + item.StackSize); continue; } var loot = WorldObjectFactory.CreateNewWorldObject(item.WeenieId); if (loot != null) { if (loot.StackSize.HasValue && loot.MaxStackSize.HasValue) { loot.SetStackSize((item.StackSize <= loot.MaxStackSize) ? item.StackSize : loot.MaxStackSize); } } else { player.TryAddToInventory(CreateIOU(item.WeenieId)); } if (loot != null && player.TryAddToInventory(loot)) { grantedWeenies.Add(item.WeenieId); } if (isDualWieldTrainedOrSpecialized && loot != null) { if (loot.WeenieType == WeenieType.MeleeWeapon) { var dualloot = WorldObjectFactory.CreateNewWorldObject(item.WeenieId); if (dualloot != null) { player.TryAddToInventory(dualloot); } else { player.TryAddToInventory(CreateIOU(item.WeenieId)); } } } } } foreach (var spell in skillGear.Spells) { // Olthoi Spitter is a special case if (characterCreateInfo.Heritage == (int)HeritageGroup.OlthoiAcid) { player.AddKnownSpell(spell.SpellId); // Continue to next spell as Olthoi spells do not have the SpecializedOnly field continue; } if (charSkill.AdvancementClass == SkillAdvancementClass.Trained && spell.SpecializedOnly == false) { player.AddKnownSpell(spell.SpellId); } else if (charSkill.AdvancementClass == SkillAdvancementClass.Specialized) { player.AddKnownSpell(spell.SpellId); } } } } player.Name = characterCreateInfo.Name; player.Character.Name = characterCreateInfo.Name; // Index used to determine the starting location var startArea = characterCreateInfo.StartArea; var starterArea = DatManager.PortalDat.CharGen.StarterAreas[(int)startArea]; player.Location = new Position(starterArea.Locations[0].ObjCellID, starterArea.Locations[0].Frame.Origin.X, starterArea.Locations[0].Frame.Origin.Y, starterArea.Locations[0].Frame.Origin.Z, starterArea.Locations[0].Frame.Orientation.X, starterArea.Locations[0].Frame.Orientation.Y, starterArea.Locations[0].Frame.Orientation.Z, starterArea.Locations[0].Frame.Orientation.W); var instantiation = new Position(0xA9B40019, 84, 7.1f, 94, 0, 0, -0.0784591f, 0.996917f); // ultimate fallback. var spellFreeRide = new Spell(); switch (starterArea.Name) { case "OlthoiLair": //todo: check this when olthoi play is allowed in ace spellFreeRide = null; // no training area for olthoi, so they start and fall back to same place. instantiation = new Position(player.Location); break; case "Shoushi": spellFreeRide = DatabaseManager.World.GetCachedSpell(3813); // Free Ride to Shoushi break; case "Yaraq": spellFreeRide = DatabaseManager.World.GetCachedSpell(3814); // Free Ride to Yaraq break; case "Sanamar": spellFreeRide = DatabaseManager.World.GetCachedSpell(3535); // Free Ride to Sanamar break; case "Holtburg": default: spellFreeRide = DatabaseManager.World.GetCachedSpell(3815); // Free Ride to Holtburg break; } if (spellFreeRide != null && spellFreeRide.Name != "") { instantiation = new Position(spellFreeRide.PositionObjCellId.Value, spellFreeRide.PositionOriginX.Value, spellFreeRide.PositionOriginY.Value, spellFreeRide.PositionOriginZ.Value, spellFreeRide.PositionAnglesX.Value, spellFreeRide.PositionAnglesY.Value, spellFreeRide.PositionAnglesZ.Value, spellFreeRide.PositionAnglesW.Value); } player.Instantiation = new Position(instantiation); player.Sanctuary = new Position(player.Location); player.SetProperty(PropertyBool.RecallsDisabled, true); if (player is Sentinel || player is Admin) { player.Character.IsPlussed = true; player.CloakStatus = CloakStatus.Off; player.ChannelsAllowed = player.ChannelsActive; } CharacterCreateSetDefaultCharacterOptions(player); return(CreateResult.Success); }
public static CreateResult Create(CharacterCreateInfo characterCreateInfo, Weenie weenie, ObjectGuid guid, uint accountId, WeenieType weenieType, out Player player) { var heritageGroup = DatManager.PortalDat.CharGen.HeritageGroups[characterCreateInfo.Heritage]; if (weenieType == WeenieType.Admin) { player = new Admin(weenie, guid, accountId); } else if (weenieType == WeenieType.Sentinel) { player = new Sentinel(weenie, guid, accountId); } else { player = new Player(weenie, guid, accountId); } player.SetProperty(PropertyInt.HeritageGroup, (int)characterCreateInfo.Heritage); player.SetProperty(PropertyString.HeritageGroup, heritageGroup.Name); player.SetProperty(PropertyInt.Gender, (int)characterCreateInfo.Gender); player.SetProperty(PropertyString.Sex, characterCreateInfo.Gender == 1 ? "Male" : "Female"); //player.SetProperty(PropertyDataId.Icon, cgh.IconImage); // I don't believe this is used anywhere in the client, but it might be used by a future custom launcher // pull character data from the dat file var sex = heritageGroup.Genders[(int)characterCreateInfo.Gender]; player.SetProperty(PropertyDataId.MotionTable, sex.MotionTable); player.SetProperty(PropertyDataId.SoundTable, sex.SoundTable); player.SetProperty(PropertyDataId.PhysicsEffectTable, sex.PhysicsTable); player.SetProperty(PropertyDataId.Setup, sex.SetupID); player.SetProperty(PropertyDataId.PaletteBase, sex.BasePalette); player.SetProperty(PropertyDataId.CombatTable, sex.CombatTable); // Check the character scale if (sex.Scale != 100u) { player.SetProperty(PropertyFloat.DefaultScale, (sex.Scale / 100f)); // Scale is stored as a percentage } // Get the hair first, because we need to know if you're bald, and that's the name of that tune! var hairstyle = sex.HairStyleList[Convert.ToInt32(characterCreateInfo.Apperance.HairStyle)]; // Olthoi and Gear Knights have a "Body Style" instead of a hair style. These styles have multiple model/texture changes, instead of a single head/hairstyle. // Storing this value allows us to send the proper appearance ObjDesc if (hairstyle.ObjDesc.AnimPartChanges.Count > 1) { player.SetProperty(PropertyInt.Hairstyle, (int)characterCreateInfo.Apperance.HairStyle); } // Certain races (Undead, Tumeroks, Others?) have multiple body styles available. This is controlled via the "hair style". if (hairstyle.AlternateSetup > 0) { player.SetProperty(PropertyDataId.Setup, hairstyle.AlternateSetup); } player.SetProperty(PropertyDataId.EyesTexture, sex.GetEyeTexture(characterCreateInfo.Apperance.Eyes, hairstyle.Bald)); player.SetProperty(PropertyDataId.DefaultEyesTexture, sex.GetDefaultEyeTexture(characterCreateInfo.Apperance.Eyes, hairstyle.Bald)); player.SetProperty(PropertyDataId.NoseTexture, sex.GetNoseTexture(characterCreateInfo.Apperance.Nose)); player.SetProperty(PropertyDataId.DefaultNoseTexture, sex.GetDefaultNoseTexture(characterCreateInfo.Apperance.Nose)); player.SetProperty(PropertyDataId.MouthTexture, sex.GetMouthTexture(characterCreateInfo.Apperance.Mouth)); player.SetProperty(PropertyDataId.DefaultMouthTexture, sex.GetDefaultMouthTexture(characterCreateInfo.Apperance.Mouth)); player.Character.HairTexture = sex.GetHairTexture(characterCreateInfo.Apperance.HairStyle); player.Character.DefaultHairTexture = sex.GetDefaultHairTexture(characterCreateInfo.Apperance.HairStyle); // HeadObject can be null if we're dealing with GearKnight or Olthoi var headObject = sex.GetHeadObject(characterCreateInfo.Apperance.HairStyle); if (headObject != null) { player.SetProperty(PropertyDataId.HeadObject, (uint)headObject); } // Skin is stored as PaletteSet (list of Palettes), so we need to read in the set to get the specific palette var skinPalSet = DatManager.PortalDat.ReadFromDat <PaletteSet>(sex.SkinPalSet); player.SetProperty(PropertyDataId.SkinPalette, skinPalSet.GetPaletteID(characterCreateInfo.Apperance.SkinHue)); player.SetProperty(PropertyFloat.Shade, characterCreateInfo.Apperance.SkinHue); // Hair is stored as PaletteSet (list of Palettes), so we need to read in the set to get the specific palette var hairPalSet = DatManager.PortalDat.ReadFromDat <PaletteSet>(sex.HairColorList[Convert.ToInt32(characterCreateInfo.Apperance.HairColor)]); player.SetProperty(PropertyDataId.HairPalette, hairPalSet.GetPaletteID(characterCreateInfo.Apperance.HairHue)); // Eye Color player.SetProperty(PropertyDataId.EyesPalette, sex.EyeColorList[Convert.ToInt32(characterCreateInfo.Apperance.EyeColor)]); if (characterCreateInfo.Apperance.HeadgearStyle < 0xFFFFFFFF) // No headgear is max UINT { var hat = GetClothingObject(sex.GetHeadgearWeenie(characterCreateInfo.Apperance.HeadgearStyle), characterCreateInfo.Apperance.HeadgearColor, characterCreateInfo.Apperance.HeadgearHue); if (hat != null) { player.TryEquipObject(hat, hat.ValidLocations ?? 0); } else { player.TryAddToInventory(CreateIOU(sex.GetHeadgearWeenie(characterCreateInfo.Apperance.HeadgearStyle))); } } var shirt = GetClothingObject(sex.GetShirtWeenie(characterCreateInfo.Apperance.ShirtStyle), characterCreateInfo.Apperance.ShirtColor, characterCreateInfo.Apperance.ShirtHue); if (shirt != null) { player.TryEquipObject(shirt, shirt.ValidLocations ?? 0); } else { player.TryAddToInventory(CreateIOU(sex.GetShirtWeenie(characterCreateInfo.Apperance.ShirtStyle))); } var pants = GetClothingObject(sex.GetPantsWeenie(characterCreateInfo.Apperance.PantsStyle), characterCreateInfo.Apperance.PantsColor, characterCreateInfo.Apperance.PantsHue); if (pants != null) { player.TryEquipObject(pants, pants.ValidLocations ?? 0); } else { player.TryAddToInventory(CreateIOU(sex.GetPantsWeenie(characterCreateInfo.Apperance.PantsStyle))); } var shoes = GetClothingObject(sex.GetFootwearWeenie(characterCreateInfo.Apperance.FootwearStyle), characterCreateInfo.Apperance.FootwearColor, characterCreateInfo.Apperance.FootwearHue); if (shoes != null) { player.TryEquipObject(shoes, shoes.ValidLocations ?? 0); } else { player.TryAddToInventory(CreateIOU(sex.GetFootwearWeenie(characterCreateInfo.Apperance.FootwearStyle))); } string templateName = heritageGroup.Templates[characterCreateInfo.TemplateOption].Name; //player.SetProperty(PropertyString.Title, templateName); player.SetProperty(PropertyString.Template, templateName); player.AddTitle(heritageGroup.Templates[characterCreateInfo.TemplateOption].Title, true); // attributes var result = ValidateAttributeCredits(characterCreateInfo, heritageGroup.AttributeCredits); if (result != CreateResult.Success) { return(result); } player.Strength.StartingValue = characterCreateInfo.StrengthAbility; player.Endurance.StartingValue = characterCreateInfo.EnduranceAbility; player.Coordination.StartingValue = characterCreateInfo.CoordinationAbility; player.Quickness.StartingValue = characterCreateInfo.QuicknessAbility; player.Focus.StartingValue = characterCreateInfo.FocusAbility; player.Self.StartingValue = characterCreateInfo.SelfAbility; // data we don't care about //characterCreateInfo.CharacterSlot; //characterCreateInfo.ClassId; // characters start with max vitals player.Health.Current = player.Health.Base; player.Stamina.Current = player.Stamina.Base; player.Mana.Current = player.Mana.Base; // set initial skill credit amount. 52 for all but "Olthoi", which have 68 player.SetProperty(PropertyInt.AvailableSkillCredits, (int)heritageGroup.SkillCredits); if (characterCreateInfo.SkillAdvancementClasses.Count != 55) { return(CreateResult.ClientServerSkillsMismatch); } for (int i = 0; i < characterCreateInfo.SkillAdvancementClasses.Count; i++) { var sac = characterCreateInfo.SkillAdvancementClasses[i]; if (sac == SkillAdvancementClass.Inactive) { continue; } if (!DatManager.PortalDat.SkillTable.SkillBaseHash.ContainsKey((uint)i)) { log.ErrorFormat("Character {0} tried to create with skill {1} that was not found in Portal dat.", characterCreateInfo.Name, i); return(CreateResult.InvalidSkillRequested); } var skill = DatManager.PortalDat.SkillTable.SkillBaseHash[(uint)i]; var trainedCost = skill.TrainedCost; var specializedCost = skill.UpgradeCostFromTrainedToSpecialized; foreach (var skillGroup in heritageGroup.Skills) { if (skillGroup.SkillNum == i) { trainedCost = skillGroup.NormalCost; specializedCost = skillGroup.PrimaryCost; break; } } if (sac == SkillAdvancementClass.Specialized) { if (!player.TrainSkill((Skill)i, trainedCost)) { return(CreateResult.FailedToTrainSkill); } if (!player.SpecializeSkill((Skill)i, specializedCost)) { return(CreateResult.FailedToSpecializeSkill); } } else if (sac == SkillAdvancementClass.Trained) { if (!player.TrainSkill((Skill)i, trainedCost, true)) { return(CreateResult.FailedToTrainSkill); } } else if (sac == SkillAdvancementClass.Untrained) { player.UntrainSkill((Skill)i, 0); } } var isDualWieldTrainedOrSpecialized = player.Skills[Skill.DualWield].AdvancementClass > SkillAdvancementClass.Untrained; // Set Heritage based Melee and Ranged Masteries GetMasteries(player.HeritageGroup, out WeaponType meleeMastery, out WeaponType rangedMastery); player.SetProperty(PropertyInt.MeleeMastery, (int)meleeMastery); player.SetProperty(PropertyInt.RangedMastery, (int)rangedMastery); // Set innate augs SetInnateAugmentations(player); // grant starter items based on skills var starterGearConfig = StarterGearFactory.GetStarterGearConfiguration(); var grantedWeenies = new List <uint>(); foreach (var skillGear in starterGearConfig.Skills) { var charSkill = player.Skills[(Skill)skillGear.SkillId]; if (charSkill.AdvancementClass == SkillAdvancementClass.Trained || charSkill.AdvancementClass == SkillAdvancementClass.Specialized) { foreach (var item in skillGear.Gear) { if (grantedWeenies.Contains(item.WeenieId)) { var existingItem = player.Inventory.Values.FirstOrDefault(i => i.WeenieClassId == item.WeenieId); if (existingItem == null || (existingItem.MaxStackSize ?? 1) <= 1) { continue; } existingItem.SetStackSize(existingItem.StackSize + item.StackSize); continue; } var loot = WorldObjectFactory.CreateNewWorldObject(item.WeenieId); if (loot != null) { if (loot.StackSize.HasValue && loot.MaxStackSize.HasValue) { loot.SetStackSize((item.StackSize <= loot.MaxStackSize) ? item.StackSize : loot.MaxStackSize); } } else { player.TryAddToInventory(CreateIOU(item.WeenieId)); } if (loot != null && player.TryAddToInventory(loot)) { grantedWeenies.Add(item.WeenieId); } if (isDualWieldTrainedOrSpecialized && loot != null) { if (loot.WeenieType == WeenieType.MeleeWeapon) { var dualloot = WorldObjectFactory.CreateNewWorldObject(item.WeenieId); if (dualloot != null) { player.TryAddToInventory(dualloot); } else { player.TryAddToInventory(CreateIOU(item.WeenieId)); } } } } var heritageLoot = skillGear.Heritage.FirstOrDefault(sh => sh.HeritageId == characterCreateInfo.Heritage); if (heritageLoot != null) { foreach (var item in heritageLoot.Gear) { if (grantedWeenies.Contains(item.WeenieId)) { var existingItem = player.Inventory.Values.FirstOrDefault(i => i.WeenieClassId == item.WeenieId); if (existingItem == null || (existingItem.MaxStackSize ?? 1) <= 1) { continue; } existingItem.SetStackSize(existingItem.StackSize + item.StackSize); continue; } var loot = WorldObjectFactory.CreateNewWorldObject(item.WeenieId); if (loot != null) { if (loot.StackSize.HasValue && loot.MaxStackSize.HasValue) { loot.SetStackSize((item.StackSize <= loot.MaxStackSize) ? item.StackSize : loot.MaxStackSize); } } else { player.TryAddToInventory(CreateIOU(item.WeenieId)); } if (loot != null && player.TryAddToInventory(loot)) { grantedWeenies.Add(item.WeenieId); } if (isDualWieldTrainedOrSpecialized && loot != null) { if (loot.WeenieType == WeenieType.MeleeWeapon) { var dualloot = WorldObjectFactory.CreateNewWorldObject(item.WeenieId); if (dualloot != null) { player.TryAddToInventory(dualloot); } else { player.TryAddToInventory(CreateIOU(item.WeenieId)); } } } } } foreach (var spell in skillGear.Spells) { // Olthoi Spitter is a special case if (characterCreateInfo.Heritage == (int)HeritageGroup.OlthoiAcid) { player.AddKnownSpell(spell.SpellId); // Continue to next spell as Olthoi spells do not have the SpecializedOnly field continue; } if (charSkill.AdvancementClass == SkillAdvancementClass.Trained && spell.SpecializedOnly == false) { player.AddKnownSpell(spell.SpellId); } else if (charSkill.AdvancementClass == SkillAdvancementClass.Specialized) { player.AddKnownSpell(spell.SpellId); } } } } player.Name = characterCreateInfo.Name; player.Character.Name = characterCreateInfo.Name; player.Instantiation = new Position(8323335, 260.085388f, -20.421343f, -59.994999f, 0.0f, -0.0f, -0.707107f, -0.707107f); player.Sanctuary = new Position(8323335, 260.085388f, -20.421343f, -59.994999f, 0.0f, -0.0f, -0.707107f, -0.707107f); player.SetProperty(PropertyBool.RecallsDisabled, false); player.AvailableSkillCredits = 50; player.AvailableExperience += 191226310247; player.TotalExperience += 191226310247; player.Level = 275; if (PropertyManager.GetBool("pk_server").Item) { player.SetProperty(PropertyInt.PlayerKillerStatus, (int)PlayerKillerStatus.PK); } else if (PropertyManager.GetBool("pkl_server").Item) { player.SetProperty(PropertyInt.PlayerKillerStatus, (int)PlayerKillerStatus.NPK); } if ((PropertyManager.GetBool("pk_server").Item || PropertyManager.GetBool("pkl_server").Item) && PropertyManager.GetBool("pk_server_safe_training_academy").Item) { player.SetProperty(PropertyFloat.MinimumTimeSincePk, -PropertyManager.GetDouble("pk_new_character_grace_period").Item); player.SetProperty(PropertyInt.PlayerKillerStatus, (int)PlayerKillerStatus.NPK); } if (player is Sentinel || player is Admin) { player.Character.IsPlussed = true; player.CloakStatus = CloakStatus.Off; player.ChannelsAllowed = player.ChannelsActive; } CharacterCreateSetDefaultCharacterOptions(player); return(CreateResult.Success); }