/// <summary> /// Creates a placeholder creature with the given ArkId, which have to be imported /// </summary> /// <param name="arkId">ArkId from an imported source (no user input)</param> public Creature(long arkId) { ArkId = arkId; ArkIdImported = true; guid = Utils.ConvertArkIdToGuid(arkId); levelsWild = new[] { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }; // unknown wild levels IsPlaceholder = true; }
private Creature ConvertGameObject(GameObject creatureObject, int?levelStep) { if (!Values.V.TryGetSpeciesByClassName(creatureObject.ClassString, out Species species)) { // species is unknown, creature cannot be imported. // use name-field to temporarily save the unknown classString to display in a messagebox return(new Creature { name = creatureObject.ClassString }); } GameObject statusObject = creatureObject.CharacterStatusComponent(); // error while deserializing that creature if (statusObject == null) { return(null); } string imprinterName = creatureObject.GetPropertyValue <string>("ImprinterName"); string owner = string.IsNullOrWhiteSpace(imprinterName) ? creatureObject.GetPropertyValue <string>("TamerString") : imprinterName; int[] wildLevels = Enumerable.Repeat(-1, Values.STATS_COUNT).ToArray(); // -1 is unknown int[] tamedLevels = new int[Values.STATS_COUNT]; for (int i = 0; i < Values.STATS_COUNT; i++) { wildLevels[i] = statusObject.GetPropertyValue <ArkByteValue>("NumberOfLevelUpPointsApplied", i)?.ByteValue ?? 0; } wildLevels[(int)StatNames.Torpidity] = statusObject.GetPropertyValue <int>("BaseCharacterLevel", defaultValue: 1) - 1; // torpor for (int i = 0; i < Values.STATS_COUNT; i++) { tamedLevels[i] = statusObject.GetPropertyValue <ArkByteValue>("NumberOfLevelUpPointsAppliedTamed", i)?.ByteValue ?? 0; } float ti = statusObject.GetPropertyValue <float>("TamedIneffectivenessModifier", defaultValue: float.NaN); double te = 1f / (1 + (!float.IsNaN(ti) ? ti : creatureObject.GetPropertyValue <float>("TameIneffectivenessModifier"))); Creature creature = new Creature(species, creatureObject.GetPropertyValue <string>("TamedName"), owner, creatureObject.GetPropertyValue <string>("TribeName"), creatureObject.IsFemale() ? Sex.Female : Sex.Male, wildLevels, tamedLevels, te, !string.IsNullOrWhiteSpace(creatureObject.GetPropertyValue <string>("ImprinterName")), statusObject.GetPropertyValue <float>("DinoImprintingQuality"), levelStep ) { imprinterName = creatureObject.GetPropertyValue <string>("ImprinterName"), guid = Utils.ConvertArkIdToGuid(creatureObject.GetDinoId()), ArkId = creatureObject.GetDinoId(), ArkIdImported = true, domesticatedAt = DateTime.Now, // TODO: possible to convert ingame-time to realtime? addedToLibrary = DateTime.Now, mutationsMaternal = creatureObject.GetPropertyValue <int>("RandomMutationsFemale"), mutationsPaternal = creatureObject.GetPropertyValue <int>("RandomMutationsMale"), flags = creatureObject.GetPropertyValue <bool>("bNeutered") ? CreatureFlags.Neutered : CreatureFlags.None }; // If it's a baby and still growing, work out growingUntil if (creatureObject.GetPropertyValue <bool>("bIsBaby") || !creatureObject.GetPropertyValue <bool>("bIsBaby") && !string.IsNullOrWhiteSpace(imprinterName)) { double maturationTime = species.breeding?.maturationTimeAdjusted ?? 0; float tamedTime = _gameTime - (float)creatureObject.GetPropertyValue <double>("TamedAtTime"); if (tamedTime < maturationTime - 120) // there seems to be a slight offset of one of these saved values, so don't display a creature as being in cooldown if it is about to leave it in the next 2 minutes { creature.growingUntil = DateTime.Now + TimeSpan.FromSeconds(maturationTime - tamedTime); } } // Ancestor linking is done later after entire collection is formed - here we just set the guids ArkArrayStruct femaleAncestors = creatureObject.GetPropertyValue <IArkArray, ArkArrayStruct>("DinoAncestors"); StructPropertyList femaleAncestor = (StructPropertyList)femaleAncestors?.LastOrDefault(); if (femaleAncestor != null) { creature.motherGuid = Utils.ConvertArkIdToGuid(Utils.ConvertArkIdsToLongArkId( femaleAncestor.GetPropertyValue <int>("FemaleDinoID1"), femaleAncestor.GetPropertyValue <int>("FemaleDinoID2"))); creature.motherName = femaleAncestor.GetPropertyValue <string>("FemaleName"); creature.isBred = true; } ArkArrayStruct maleAncestors = creatureObject.GetPropertyValue <IArkArray, ArkArrayStruct>("DinoAncestorsMale"); StructPropertyList maleAncestor = (StructPropertyList)maleAncestors?.LastOrDefault(); if (maleAncestor != null) { creature.fatherGuid = Utils.ConvertArkIdToGuid(GameObjectExtensions.CreateDinoId( maleAncestor.GetPropertyValue <int>("MaleDinoID1"), maleAncestor.GetPropertyValue <int>("MaleDinoID2"))); creature.fatherName = maleAncestor.GetPropertyValue <string>("MaleName"); creature.isBred = true; } creature.colors = new int[6]; for (int i = 0; i < 6; i++) { creature.colors[i] = creatureObject.GetPropertyValue <ArkByteValue>("ColorSetIndices", i)?.ByteValue ?? 0; } bool isDead = creatureObject.GetPropertyValue <bool>("bIsDead"); if (isDead) { creature.Status = CreatureStatus.Dead; // dead is always dead } if (creatureObject.IsCryo) { creature.Status = CreatureStatus.Cryopod; } creature.RecalculateCreatureValues(levelStep); return(creature); }
private Creature convertGameObject(GameObject creatureObject, int?levelStep) { GameObject statusObject = creatureObject.CharacterStatusComponent(); string imprinterName = creatureObject.GetPropertyValue <string>("ImprinterName"); string owner = string.IsNullOrWhiteSpace(imprinterName) ? creatureObject.GetPropertyValue <string>("TamerString") : imprinterName; int[] wildLevels = Enumerable.Repeat(-1, statsCount).ToArray(); // -1 is unknown int[] tamedLevels = new int[statsCount]; for (int i = 0; i < statsCount; i++) { wildLevels[i] = statusObject.GetPropertyValue <ArkByteValue>("NumberOfLevelUpPointsApplied", i)?.ByteValue ?? 0; } wildLevels[(int)StatNames.Torpidity] = statusObject.GetPropertyValue <int>("BaseCharacterLevel", defaultValue: 1) - 1; // torpor for (int i = 0; i < statsCount; i++) { tamedLevels[i] = statusObject.GetPropertyValue <ArkByteValue>("NumberOfLevelUpPointsAppliedTamed", i)?.ByteValue ?? 0; } string convertedSpeciesName = convertSpecies(creatureObject.GetNameForCreature(arkData) ?? creatureObject.ClassString); float ti = statusObject.GetPropertyValue <float>("TamedIneffectivenessModifier", defaultValue: float.NaN); double te = 1f / (1 + (!float.IsNaN(ti) ? ti : creatureObject.GetPropertyValue <float>("TameIneffectivenessModifier"))); Creature creature = new Creature(convertedSpeciesName, creatureObject.GetPropertyValue <string>("TamedName"), owner, creatureObject.GetPropertyValue <string>("TribeName"), creatureObject.IsFemale() ? Sex.Female : Sex.Male, wildLevels, tamedLevels, te, !string.IsNullOrWhiteSpace(creatureObject.GetPropertyValue <string>("ImprinterName")), statusObject.GetPropertyValue <float>("DinoImprintingQuality"), levelStep ) { imprinterName = creatureObject.GetPropertyValue <string>("ImprinterName"), guid = Utils.ConvertArkIdToGuid(creatureObject.GetDinoId()), ArkId = creatureObject.GetDinoId(), ArkIdImported = true, domesticatedAt = DateTime.Now, // TODO: possible to convert ingame-time to realtime? addedToLibrary = DateTime.Now, mutationsMaternal = creatureObject.GetPropertyValue <int>("RandomMutationsFemale"), mutationsPaternal = creatureObject.GetPropertyValue <int>("RandomMutationsMale") }; // If it's a baby and still growing, work out growingUntil if (creatureObject.GetPropertyValue <bool>("bIsBaby") || !creatureObject.GetPropertyValue <bool>("bIsBaby") && !string.IsNullOrWhiteSpace(imprinterName)) { int i = Values.V.speciesNames.IndexOf(convertedSpeciesName); double maturationTime = Values.V.species[i].breeding?.maturationTimeAdjusted ?? 0; float tamedTime = gameTime - (float)creatureObject.GetPropertyValue <double>("TamedAtTime"); if (tamedTime < maturationTime) { creature.growingUntil = DateTime.Now + TimeSpan.FromSeconds(maturationTime - tamedTime); } } // Ancestor linking is done later after entire collection is formed - here we just set the guids ArkArrayStruct femaleAncestors = creatureObject.GetPropertyValue <IArkArray, ArkArrayStruct>("DinoAncestors"); StructPropertyList femaleAncestor = (StructPropertyList)femaleAncestors?.LastOrDefault(); if (femaleAncestor != null) { creature.motherGuid = Utils.ConvertArkIdToGuid(GameObjectExtensions.CreateDinoId( femaleAncestor.GetPropertyValue <int>("FemaleDinoID1"), femaleAncestor.GetPropertyValue <int>("FemaleDinoID2"))); creature.motherName = femaleAncestor.GetPropertyValue <string>("FemaleName"); creature.isBred = true; } ArkArrayStruct maleAncestors = creatureObject.GetPropertyValue <IArkArray, ArkArrayStruct>("DinoAncestorsMale"); StructPropertyList maleAncestor = (StructPropertyList)maleAncestors?.LastOrDefault(); if (maleAncestor != null) { creature.fatherGuid = Utils.ConvertArkIdToGuid(GameObjectExtensions.CreateDinoId( maleAncestor.GetPropertyValue <int>("MaleDinoID1"), maleAncestor.GetPropertyValue <int>("MaleDinoID2"))); creature.fatherName = maleAncestor.GetPropertyValue <string>("MaleName"); creature.isBred = true; } creature.colors = new int[6]; for (int i = 0; i < 6; i++) { creature.colors[i] = colorModulo(creatureObject.GetPropertyValue <ArkByteValue>("ColorSetIndices", i)?.ByteValue ?? 0); } bool isDead = creatureObject.GetPropertyValue <bool>("bIsDead"); if (isDead) { creature.status = CreatureStatus.Dead; // dead is always dead } if (!isDead && creature.status == CreatureStatus.Dead) { creature.status = CreatureStatus.Unavailable; // if found alive when marked dead, mark as unavailable } creature.recalculateAncestorGenerations(); creature.recalculateCreatureValues(levelStep); return(creature); }
public static CreatureValues importExportedCreature(string filePath) { CreatureValues cv = new CreatureValues { domesticatedAt = File.GetLastWriteTime(filePath), isTamed = true, tamingEffMax = 1 }; string[] iniLines = File.ReadAllLines(filePath); string id = ""; int statIndexIngame = -1; // this is the order how the stats appear in the ini-file; field names in the file are localized string[] statIndices = { "Health", "Stamina", "Torpidity", "Oxygen", "Food", "Water" /*ignored*/, "Temperature" /*ignored*/, "Weight", "Melee Damage", "Movement Speed", "Fortitude" /*ignored*/, "Crafting Skill" /*ignored*/ }; bool inStatSection = false; foreach (string line in iniLines) { if (line.Contains("=")) { string parameterName; int i = line.IndexOf("="); string text = line.Substring(i + 1); double.TryParse(text, System.Globalization.NumberStyles.AllowDecimalPoint | System.Globalization.NumberStyles.AllowLeadingSign, System.Globalization.CultureInfo.GetCultureInfo("en-US"), out double value); if (inStatSection) { statIndexIngame++; if (statIndexIngame > 11) { inStatSection = false; } } if (inStatSection) { parameterName = statIndices[statIndexIngame]; } else { parameterName = line.Substring(0, i); if (parameterName.Contains("DinoAncestorsMale")) { parameterName = "DinoAncestorsMale"; // only the last entry contains the parents } } if (parameterName.Length <= 0) { continue; } switch (parameterName) { case "DinoID1": if (string.IsNullOrEmpty(id)) { id = text; } else { cv.ARKID = buildARKID(text, id); cv.guid = Utils.ConvertArkIdToGuid(cv.ARKID); } break; case "DinoID2": if (string.IsNullOrEmpty(id)) { id = text; } else { cv.ARKID = buildARKID(id, text); cv.guid = Utils.ConvertArkIdToGuid(cv.ARKID); } break; case "DinoClass": if (text.Length > 2 && text.Substring(text.Length - 2) == "_C") { text = text.Substring(0, text.Length - 2); // the last two characters are "_C" } cv.species = Values.V.speciesNameFromBP(text); break; case "bIsFemale": cv.sex = text == "True" ? Sex.Female : Sex.Male; break; case "bIsNeutered": cv.neutered = text != "False"; break; case "TamerString": cv.owner = text; break; case "TamedName": cv.name = text; break; case "ImprinterName": cv.imprinterName = text; if (string.IsNullOrEmpty(cv.owner)) { cv.owner = text; } if (!string.IsNullOrWhiteSpace(text)) { cv.isBred = true; // TODO is this a correct assumption? } break; // todo mutations for mother and father case "RandomMutationsMale": cv.mutationCounterFather = (int)value; break; case "RandomMutationsFemale": cv.mutationCounterMother = (int)value; break; case "BabyAge": int speciesIndex = Values.V.speciesIndex(cv.species); if (speciesIndex >= 0 && value >= 0 && value <= 1 && Values.V.species[speciesIndex].breeding != null) { cv.growingUntil = DateTime.Now.AddSeconds((int)(Values.V.species[speciesIndex].breeding.maturationTimeAdjusted * (1 - value))); } break; case "CharacterLevel": cv.level = (int)value; break; case "DinoImprintingQuality": cv.imprintingBonus = value; if (value > 0) { cv.isBred = true; } break; // Colorization case "ColorSet[0]": cv.colorIDs[0] = parseColor(text); break; case "ColorSet[1]": cv.colorIDs[1] = parseColor(text); break; case "ColorSet[2]": cv.colorIDs[2] = parseColor(text); break; case "ColorSet[3]": cv.colorIDs[3] = parseColor(text); break; case "ColorSet[4]": cv.colorIDs[4] = parseColor(text); break; case "ColorSet[5]": cv.colorIDs[5] = parseColor(text); break; case "Health": cv.statValues[0] = value; break; case "Stamina": cv.statValues[1] = value; break; case "Torpidity": cv.statValues[7] = value; break; case "Oxygen": cv.statValues[2] = value; break; case "Food": cv.statValues[3] = value; break; case "Weight": cv.statValues[4] = value; break; case "Melee Damage": cv.statValues[5] = 1 + value; break; case "Movement Speed": cv.statValues[6] = 1 + value; break; case "DinoAncestorsMale": Regex r = new Regex(@"MaleName=([^;]+);MaleDinoID1=([^;]+);MaleDinoID2=([^;]+);FemaleName=([^;]+);FemaleDinoID1=([^;]+);FemaleDinoID2=([^;]+)"); Match m = r.Match(text); if (m.Success) { cv.motherArkId = buildARKID(m.Groups[5].Value, m.Groups[6].Value); cv.fatherArkId = buildARKID(m.Groups[2].Value, m.Groups[3].Value); cv.isBred = true; } break; } } else if (line.Contains("[Max Character Status Values]")) { inStatSection = true; } } // if parent ArkIds are set, create creature placeholder if (cv.motherArkId != 0) { cv.Mother = new Creature(cv.motherArkId) { species = cv.species }; } if (cv.fatherArkId != 0) { cv.Father = new Creature(cv.fatherArkId) { species = cv.species }; } return(cv); }