/// <summary> /// Validates character creation attribute info /// </summary> private static CreateResult ValidateAttributeCredits(CharacterCreateInfo info, uint maxAttributes) { var attributeValues = new List <uint>() { info.StrengthAbility, info.EnduranceAbility, info.CoordinationAbility, info.QuicknessAbility, info.FocusAbility, info.SelfAbility }; uint total = 0; foreach (var attributeValue in attributeValues) { if (attributeValue < 10 || attributeValue > 100) { return(CreateResult.InvalidSkillRequested); } total += attributeValue; } if (total > maxAttributes) { return(CreateResult.TooManySkillCreditsUsed); } return(CreateResult.Success); }
/// <summary> /// Creates a fully leveled/augmented 275 Heavy Weapons character player /// </summary> public static Player Create275HeavyWeapons(Weenie weenie, ObjectGuid guid, uint accountId, string name) { var characterCreateInfo = new CharacterCreateInfo(); using (var memoryStream = new MemoryStream(baseGearKnight1)) using (var binaryReader = new BinaryReader(memoryStream)) characterCreateInfo.Unpack(binaryReader); characterCreateInfo.Name = name; Create(characterCreateInfo, weenie, guid, accountId, WeenieType.Creature, out var player); LevelUpPlayer(player); // todo add the creature/item/life skills here and remove them from the above base array once we have augmentations added in LevelUpPlayer() // Specialize Heavy Weapon specific skills player.TrainSkill(Skill.HeavyWeapons, 6); player.SpecializeSkill(Skill.HeavyWeapons, 6); player.TrainSkill(Skill.Healing, 6); player.SpecializeSkill(Skill.Healing, 4); player.TrainSkill(Skill.Shield, 2); player.SpecializeSkill(Skill.Shield, 2); // Raise base skills player.TrainSkill(Skill.MissileDefense, 6); player.SpecializeSkill(Skill.MeleeDefense, 10); player.SpecializeSkill(Skill.MagicDefense, 12); // todo 0 skill points. When we add the 4 skill points in LevelUpPlayer, we can spend them here // todo aug endurance SpendAllXp(player); AddCommonEquipment(player); AddCommonInventory(player); // todo Give the character skill appropriate weapons AddAllSpells(player); return(player); }
private static void CharacterCreateEx(ClientMessage message, Session session) { var characterCreateInfo = new CharacterCreateInfo(); characterCreateInfo.Unpack(message.Payload); // TODO: Check for Banned Name Here //DatabaseManager.Shard.IsCharacterNameBanned(characterCreateInfo.Name, isBanned => //{ // if (!isBanned) // { // SendCharacterCreateResponse(session, CharacterGenerationVerificationResponse.NameBanned); // return; // } //}); // Disable OlthoiPlay characters for now. They're not implemented yet. // FIXME: Restore OlthoiPlay characters when properly handled. if (characterCreateInfo.Heritage == (int)HeritageGroup.Olthoi || characterCreateInfo.Heritage == (int)HeritageGroup.OlthoiAcid) { SendCharacterCreateResponse(session, CharacterGenerationVerificationResponse.Pending); return; } Weenie weenie; if (ConfigManager.Config.Server.Accounts.OverrideCharacterPermissions) { if (session.AccessLevel >= AccessLevel.Developer && session.AccessLevel <= AccessLevel.Admin) { weenie = DatabaseManager.World.GetCachedWeenie("admin"); } else if (session.AccessLevel >= AccessLevel.Sentinel && session.AccessLevel <= AccessLevel.Envoy) { weenie = DatabaseManager.World.GetCachedWeenie("sentinel"); } else { weenie = DatabaseManager.World.GetCachedWeenie("human"); } if (characterCreateInfo.Heritage == (int)HeritageGroup.Olthoi && weenie.Type == (int)WeenieType.Admin) { weenie = DatabaseManager.World.GetCachedWeenie("olthoiadmin"); } if (characterCreateInfo.Heritage == (int)HeritageGroup.OlthoiAcid && weenie.Type == (int)WeenieType.Admin) { weenie = DatabaseManager.World.GetCachedWeenie("olthoiacidadmin"); } } else { weenie = DatabaseManager.World.GetCachedWeenie("human"); } if (characterCreateInfo.Heritage == (int)HeritageGroup.Olthoi && weenie.Type == (int)WeenieType.Creature) { weenie = DatabaseManager.World.GetCachedWeenie("olthoiplayer"); } if (characterCreateInfo.Heritage == (int)HeritageGroup.OlthoiAcid && weenie.Type == (int)WeenieType.Creature) { weenie = DatabaseManager.World.GetCachedWeenie("olthoiacidplayer"); } if (characterCreateInfo.IsSentinel && session.AccessLevel >= AccessLevel.Sentinel) { weenie = DatabaseManager.World.GetCachedWeenie("sentinel"); } if (characterCreateInfo.IsAdmin && session.AccessLevel >= AccessLevel.Developer) { weenie = DatabaseManager.World.GetCachedWeenie("admin"); } if (weenie == null) { weenie = DatabaseManager.World.GetCachedWeenie("human"); // Default catch-all } if (weenie == null) // If it is STILL null after the above catchall, the database is missing critical data and cannot continue with character creation. { SendCharacterCreateResponse(session, CharacterGenerationVerificationResponse.DatabaseDown); log.Error("Database does not contain the weenie for human (1). Characters cannot be created until the missing weenie is restored."); return; } // Removes the generic knife and buckler, hidden Javelin, 30 stack of arrows, and 5 stack of coins that are given to all characters // Starter Gear from the JSON file are added to the character later in the CharacterCreateEx() process weenie.WeeniePropertiesCreateList.Clear(); var guid = GuidManager.NewPlayerGuid(); var weenieType = (WeenieType)weenie.Type; // If Database didn't have Sentinel/Admin weenies, alter the weenietype coming in. if (ConfigManager.Config.Server.Accounts.OverrideCharacterPermissions) { if (session.AccessLevel >= AccessLevel.Developer && session.AccessLevel <= AccessLevel.Admin && weenieType != WeenieType.Admin) { weenieType = WeenieType.Admin; } else if (session.AccessLevel >= AccessLevel.Sentinel && session.AccessLevel <= AccessLevel.Envoy && weenieType != WeenieType.Sentinel) { weenieType = WeenieType.Sentinel; } } var result = PlayerFactory.Create(characterCreateInfo, weenie, guid, session.AccountId, weenieType, out var player); if (result != PlayerFactory.CreateResult.Success || player == null) { SendCharacterCreateResponse(session, CharacterGenerationVerificationResponse.Corrupt); return; } DatabaseManager.Shard.IsCharacterNameAvailable(characterCreateInfo.Name, isAvailable => { if (!isAvailable) { SendCharacterCreateResponse(session, CharacterGenerationVerificationResponse.NameInUse); return; } var possessions = player.GetAllPossessions(); var possessedBiotas = new Collection <(Biota biota, ReaderWriterLockSlim rwLock)>(); foreach (var possession in possessions) { possessedBiotas.Add((possession.Biota, possession.BiotaDatabaseLock)); }
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); }
private static void CharacterCreateEx(ClientMessage message, Session session) { var characterCreateInfo = new CharacterCreateInfo(); characterCreateInfo.Unpack(message.Payload); if (PropertyManager.GetBool("taboo_table").Item&& DatManager.PortalDat.TabooTable.ContainsBadWord(characterCreateInfo.Name.ToLowerInvariant())) { SendCharacterCreateResponse(session, CharacterGenerationVerificationResponse.NameBanned); return; } if (PropertyManager.GetBool("creature_name_check").Item&& DatabaseManager.World.IsCreatureNameInWorldDatabase(characterCreateInfo.Name)) { SendCharacterCreateResponse(session, CharacterGenerationVerificationResponse.NameBanned); return; } DatabaseManager.Shard.IsCharacterNameAvailable(characterCreateInfo.Name, isAvailable => { if (!isAvailable) { SendCharacterCreateResponse(session, CharacterGenerationVerificationResponse.NameInUse); return; } }); // Disable OlthoiPlay characters for now. They're not implemented yet. // FIXME: Restore OlthoiPlay characters when properly handled. if ((characterCreateInfo.Heritage == HeritageGroup.Olthoi || characterCreateInfo.Heritage == HeritageGroup.OlthoiAcid) && !PropertyManager.GetBool("olthoi_play_enabled").Item) { SendCharacterCreateResponse(session, CharacterGenerationVerificationResponse.Pending); return; } Weenie weenie; if (ConfigManager.Config.Server.Accounts.OverrideCharacterPermissions) { if (session.AccessLevel >= AccessLevel.Developer && session.AccessLevel <= AccessLevel.Admin) { weenie = DatabaseManager.World.GetCachedWeenie("admin"); } else if (session.AccessLevel >= AccessLevel.Sentinel && session.AccessLevel <= AccessLevel.Envoy) { weenie = DatabaseManager.World.GetCachedWeenie("sentinel"); } else { weenie = DatabaseManager.World.GetCachedWeenie("human"); } if (characterCreateInfo.Heritage == HeritageGroup.Olthoi && weenie.WeenieType == WeenieType.Admin) { weenie = DatabaseManager.World.GetCachedWeenie("olthoiadmin"); } if (characterCreateInfo.Heritage == HeritageGroup.OlthoiAcid && weenie.WeenieType == WeenieType.Admin) { weenie = DatabaseManager.World.GetCachedWeenie("olthoiacidadmin"); } } else { weenie = DatabaseManager.World.GetCachedWeenie("human"); } if (characterCreateInfo.Heritage == HeritageGroup.Olthoi && weenie.WeenieType == WeenieType.Creature) { weenie = DatabaseManager.World.GetCachedWeenie("olthoiplayer"); } if (characterCreateInfo.Heritage == HeritageGroup.OlthoiAcid && weenie.WeenieType == WeenieType.Creature) { weenie = DatabaseManager.World.GetCachedWeenie("olthoiacidplayer"); } if (characterCreateInfo.IsSentinel && session.AccessLevel >= AccessLevel.Sentinel) { weenie = DatabaseManager.World.GetCachedWeenie("sentinel"); } if (characterCreateInfo.IsAdmin && session.AccessLevel >= AccessLevel.Developer) { weenie = DatabaseManager.World.GetCachedWeenie("admin"); } if (weenie == null) { weenie = DatabaseManager.World.GetCachedWeenie("human"); // Default catch-all } if (weenie == null) // If it is STILL null after the above catchall, the database is missing critical data and cannot continue with character creation. { SendCharacterCreateResponse(session, CharacterGenerationVerificationResponse.DatabaseDown); log.Error("Database does not contain the weenie for human (1). Characters cannot be created until the missing weenie is restored."); return; } var guid = GuidManager.NewPlayerGuid(); var weenieType = weenie.WeenieType; // If Database didn't have Sentinel/Admin weenies, alter the weenietype coming in. if (ConfigManager.Config.Server.Accounts.OverrideCharacterPermissions) { if (session.AccessLevel >= AccessLevel.Developer && session.AccessLevel <= AccessLevel.Admin && weenieType != WeenieType.Admin) { weenieType = WeenieType.Admin; } else if (session.AccessLevel >= AccessLevel.Sentinel && session.AccessLevel <= AccessLevel.Envoy && weenieType != WeenieType.Sentinel) { weenieType = WeenieType.Sentinel; } } var result = PlayerFactory.Create(characterCreateInfo, weenie, guid, session.AccountId, weenieType, out var player); if (result != PlayerFactory.CreateResult.Success || player == null) { if (result == PlayerFactory.CreateResult.ClientServerSkillsMismatch) { session.Terminate(SessionTerminationReason.ClientOutOfDate, new GameMessageBootAccount(" because your client is not the correct version for this server. Please visit http://play.emu.ac/ to update to latest client")); return; } SendCharacterCreateResponse(session, CharacterGenerationVerificationResponse.Corrupt); return; } DatabaseManager.Shard.IsCharacterNameAvailable(characterCreateInfo.Name, isAvailable => { if (!isAvailable) { SendCharacterCreateResponse(session, CharacterGenerationVerificationResponse.NameInUse); return; } var possessions = player.GetAllPossessions(); var possessedBiotas = new Collection <(Biota biota, ReaderWriterLockSlim rwLock)>(); foreach (var possession in possessions) { possessedBiotas.Add((possession.Biota, possession.BiotaDatabaseLock)); }
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); }
private static void CharacterCreateEx(ClientMessage message, Session session) { var characterCreateInfo = new CharacterCreateInfo(); characterCreateInfo.Unpack(message.Payload); // TODO: Check for Banned Name Here //DatabaseManager.Shard.IsCharacterNameBanned(characterCreateInfo.Name, isBanned => //{ // if (!isBanned) // { // SendCharacterCreateResponse(session, CharacterGenerationVerificationResponse.NameBanned); // return; // } //}); // Disable OlthoiPlay characters for now. They're not implemented yet. // FIXME: Restore OlthoiPlay characters when properly handled. if (characterCreateInfo.Heritage == (int)HeritageGroup.Olthoi || characterCreateInfo.Heritage == (int)HeritageGroup.OlthoiAcid) { SendCharacterCreateResponse(session, CharacterGenerationVerificationResponse.Pending); return; } var cg = DatManager.PortalDat.CharGen; var isAdmin = characterCreateInfo.IsAdmin && (session.AccessLevel >= AccessLevel.Developer); var isEnvoy = characterCreateInfo.IsEnvoy && (session.AccessLevel >= AccessLevel.Sentinel); Weenie weenie; if (ConfigManager.Config.Server.Accounts.OverrideCharacterPermissions) { if (session.AccessLevel >= AccessLevel.Developer && session.AccessLevel <= AccessLevel.Admin) { weenie = DatabaseManager.World.GetCachedWeenie("admin"); } else if (session.AccessLevel >= AccessLevel.Sentinel && session.AccessLevel <= AccessLevel.Envoy) { weenie = DatabaseManager.World.GetCachedWeenie("sentinel"); } else { weenie = DatabaseManager.World.GetCachedWeenie("human"); } if (characterCreateInfo.Heritage == (int)HeritageGroup.Olthoi && weenie.Type == (int)WeenieType.Admin) { weenie = DatabaseManager.World.GetCachedWeenie("olthoiadmin"); } if (characterCreateInfo.Heritage == (int)HeritageGroup.OlthoiAcid && weenie.Type == (int)WeenieType.Admin) { weenie = DatabaseManager.World.GetCachedWeenie("olthoiacidadmin"); } } else { weenie = DatabaseManager.World.GetCachedWeenie("human"); } if (characterCreateInfo.Heritage == (int)HeritageGroup.Olthoi && weenie.Type == (int)WeenieType.Creature) { weenie = DatabaseManager.World.GetCachedWeenie("olthoiplayer"); } if (characterCreateInfo.Heritage == (int)HeritageGroup.OlthoiAcid && weenie.Type == (int)WeenieType.Creature) { weenie = DatabaseManager.World.GetCachedWeenie("olthoiacidplayer"); } if (isEnvoy) { weenie = DatabaseManager.World.GetCachedWeenie("sentinel"); } if (isAdmin) { weenie = DatabaseManager.World.GetCachedWeenie("admin"); } if (weenie == null) { weenie = DatabaseManager.World.GetCachedWeenie("human"); // Default catch-all } if (weenie == null) // If it is STILL null after the above catchall, the database is missing critical data and cannot continue with character creation. { SendCharacterCreateResponse(session, CharacterGenerationVerificationResponse.DatabaseDown); log.Error($"Database does not contain the weenie for human (1). Characters cannot be created until the missing weenie is restored."); return; } var guid = GuidManager.NewPlayerGuid(); // If Database didn't have Sentinel/Admin weenies, alter the weenietype coming in. if (ConfigManager.Config.Server.Accounts.OverrideCharacterPermissions) { if (session.AccessLevel >= AccessLevel.Developer && session.AccessLevel <= AccessLevel.Admin && weenie.Type != (int)WeenieType.Admin) { weenie.Type = (int)WeenieType.Admin; } else if (session.AccessLevel >= AccessLevel.Sentinel && session.AccessLevel <= AccessLevel.Envoy && weenie.Type != (int)WeenieType.Sentinel) { weenie.Type = (int)WeenieType.Sentinel; } } var player = new Player(weenie, guid, session); 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.SetProperty(PropertyDataId.HairTexture, sex.GetHairTexture(characterCreateInfo.Apperance.HairStyle)); player.SetProperty(PropertyDataId.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)) { SendCharacterCreateResponse(session, CharacterGenerationVerificationResponse.Corrupt); return; } // 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.SkillStatuses.Count; i++) { var skill = (Skill)i; var skillCost = skill.GetCost(); var skillStatus = characterCreateInfo.SkillStatuses[i]; if (skillStatus == SkillStatus.Specialized) { player.TrainSkill(skill, skillCost.TrainingCost); player.SpecializeSkill(skill, skillCost.SpecializationCost); player.GetCreatureSkill(skill).InitLevel = 10; } else if (skillStatus == SkillStatus.Trained) { player.TrainSkill(skill, skillCost.TrainingCost); player.GetCreatureSkill(skill).InitLevel = 5; } else if (skillCost != null && skillStatus == SkillStatus.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.Status == SkillStatus.Trained || charSkill.Status == SkillStatus.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; } } if (loot == null) { 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; } } if (loot == null) { 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.Status == SkillStatus.Trained && spell.SpecializedOnly == false) { player.AddKnownSpell(spell.SpellId); } else if (charSkill.Status == SkillStatus.Specialized) { player.AddKnownSpell(spell.SpellId); } } } } player.Name = characterCreateInfo.Name; //player.SetProperty(PropertyString.DisplayName, characterCreateInfo.Name); // unsure // Index used to determine the starting location uint startArea = characterCreateInfo.StartArea; player.SetProperty(PropertyBool.Attackable, true); player.SetProperty(PropertyFloat.CreationTimestamp, Time.GetTimestamp()); player.SetProperty(PropertyInt.CreationTimestamp, (int)player.GetProperty(PropertyFloat.CreationTimestamp)); player.SetProperty(PropertyString.DateOfBirth, $"{DateTime.UtcNow:dd MMMM yyyy}"); DatabaseManager.Shard.IsCharacterNameAvailable(characterCreateInfo.Name, isAvailable => { if (!isAvailable) { SendCharacterCreateResponse(session, CharacterGenerationVerificationResponse.NameInUse); return; } // player.SetProperty(PropertyInstanceId.Account, (int)session.Id); var character = new Character(); character.AccountId = session.Id; character.Name = player.GetProperty(PropertyString.Name); character.BiotaId = player.Guid.Full; character.IsDeleted = false; CharacterCreateSetDefaultCharacterOptions(player); 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; var possessions = player.GetAllPossessions(); var possessedBiotas = new Collection <Biota>(); foreach (var possession in possessions) { possessedBiotas.Add(possession.Biota); } // We must await here -- DatabaseManager.Shard.AddCharacter(character, player.Biota, possessedBiotas, saveSuccess => { if (!saveSuccess) { SendCharacterCreateResponse(session, CharacterGenerationVerificationResponse.DatabaseDown); return; } session.AccountCharacters.Add(character); SendCharacterCreateResponse(session, CharacterGenerationVerificationResponse.Ok, player.Guid, characterCreateInfo.Name); }); }); }
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)]); 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); // set player attributes to 10/100/10/10/100/100 player.Strength.StartingValue = 10; player.Endurance.StartingValue = 100; player.Coordination.StartingValue = 10; player.Quickness.StartingValue = 60; player.Focus.StartingValue = 100; player.Self.StartingValue = 100; //unspecialize and untrain all skills //retrain/specialize appropriate war mage skills player.AvailableSkillCredits = 80; player.UnspecializeSkill(Skill.WarMagic, 0); player.UnspecializeSkill(Skill.Alchemy, 0); player.UnspecializeSkill(Skill.ArcaneLore, 0); player.UnspecializeSkill(Skill.ArmorTinkering, 0); player.UnspecializeSkill(Skill.AssessCreature, 0); player.UnspecializeSkill(Skill.Cooking, 0); player.UnspecializeSkill(Skill.CreatureEnchantment, 0); player.UnspecializeSkill(Skill.Deception, 0); player.UnspecializeSkill(Skill.DirtyFighting, 0); player.UnspecializeSkill(Skill.DualWield, 0); player.UnspecializeSkill(Skill.FinesseWeapons, 0); player.UnspecializeSkill(Skill.Fletching, 0); player.UnspecializeSkill(Skill.Healing, 0); player.UnspecializeSkill(Skill.HeavyWeapons, 0); player.UnspecializeSkill(Skill.ItemEnchantment, 0); player.UnspecializeSkill(Skill.ItemTinkering, 0); player.UnspecializeSkill(Skill.Jump, 0); player.UnspecializeSkill(Skill.Leadership, 0); player.UnspecializeSkill(Skill.LifeMagic, 0); player.UnspecializeSkill(Skill.LightWeapons, 0); player.UnspecializeSkill(Skill.Lockpick, 0); player.UnspecializeSkill(Skill.Loyalty, 0); player.UnspecializeSkill(Skill.MagicDefense, 0); player.UnspecializeSkill(Skill.MagicItemTinkering, 0); player.UnspecializeSkill(Skill.ManaConversion, 0); player.UnspecializeSkill(Skill.MeleeDefense, 0); player.UnspecializeSkill(Skill.MissileDefense, 0); player.UnspecializeSkill(Skill.MissileWeapons, 0); player.UnspecializeSkill(Skill.Recklessness, 0); player.UnspecializeSkill(Skill.Run, 0); player.UnspecializeSkill(Skill.Salvaging, 0); player.UnspecializeSkill(Skill.Shield, 0); player.UnspecializeSkill(Skill.SneakAttack, 0); player.UnspecializeSkill(Skill.Summoning, 0); player.UnspecializeSkill(Skill.TwoHandedCombat, 0); player.UnspecializeSkill(Skill.VoidMagic, 0); player.UnspecializeSkill(Skill.WeaponTinkering, 0); player.UntrainSkill(Skill.WarMagic, 0); player.UntrainSkill(Skill.Alchemy, 0); player.UntrainSkill(Skill.ArcaneLore, 0); player.UntrainSkill(Skill.ArmorTinkering, 0); player.UntrainSkill(Skill.AssessCreature, 0); player.UntrainSkill(Skill.Cooking, 0); player.UntrainSkill(Skill.CreatureEnchantment, 0); player.UntrainSkill(Skill.Deception, 0); player.UntrainSkill(Skill.DirtyFighting, 0); player.UntrainSkill(Skill.DualWield, 0); player.UntrainSkill(Skill.FinesseWeapons, 0); player.UntrainSkill(Skill.Fletching, 0); player.UntrainSkill(Skill.Healing, 0); player.UntrainSkill(Skill.HeavyWeapons, 0); player.UntrainSkill(Skill.ItemEnchantment, 0); player.UntrainSkill(Skill.ItemTinkering, 0); player.UntrainSkill(Skill.Jump, 0); player.UntrainSkill(Skill.Leadership, 0); player.UntrainSkill(Skill.LifeMagic, 0); player.UntrainSkill(Skill.LightWeapons, 0); player.UntrainSkill(Skill.Lockpick, 0); player.UntrainSkill(Skill.Loyalty, 0); player.UntrainSkill(Skill.MagicDefense, 0); player.UntrainSkill(Skill.MagicItemTinkering, 0); player.UntrainSkill(Skill.ManaConversion, 0); player.UntrainSkill(Skill.MeleeDefense, 0); player.UntrainSkill(Skill.MissileDefense, 0); player.UntrainSkill(Skill.MissileWeapons, 0); player.UntrainSkill(Skill.Recklessness, 0); player.UntrainSkill(Skill.Run, 0); player.UntrainSkill(Skill.Salvaging, 0); player.UntrainSkill(Skill.Shield, 0); player.UntrainSkill(Skill.SneakAttack, 0); player.UntrainSkill(Skill.Summoning, 0); player.UntrainSkill(Skill.TwoHandedCombat, 0); player.UntrainSkill(Skill.VoidMagic, 0); player.UntrainSkill(Skill.WeaponTinkering, 0); player.TrainSkill(Skill.ArcaneLore, 0); player.TrainSkill(Skill.Jump, 0); player.TrainSkill(Skill.MagicDefense, 0); player.TrainSkill(Skill.Run, 0); player.TrainSkill(Skill.WarMagic, 0); player.TrainSkill(Skill.ManaConversion, 0); player.TrainSkill(Skill.LifeMagic, 0); player.SpecializeSkill(Skill.WarMagic, 0); player.SpecializeSkill(Skill.MagicDefense, 0); player.SpecializeSkill(Skill.ManaConversion, 0); player.SpecializeSkill(Skill.LifeMagic, 0); // 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 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); SetInnateAugmentations(player); AddWeeniesToInventoryX(player, new HashSet <uint> { 15271, 6799, 6801, 1000036, 25702, 1000030, 24207, 1000031 }); 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 = 0; player.AvailableExperience += 191226310247; player.TotalExperience += 191226310247; player.Level = 275; SpendAllXpX(player); 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); }
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); }