/// <summary> /// Convert the map from a low-level object to a high-level object. /// </summary> /// <param name="savePath">The path to the folder housing the game data.</param> /// <param name="mapFileName">The name of the map file. For example, "Extinction" if you would like to load "Extinction.ark".</param> /// <param name="overrideMapData">Override the map data.</param> public ArkWorld(string savePath, string mapFileName, string configPath, ArkMapData overrideMapData = null, bool loadOnlyKnown = false) { //Read the config files configSettings = new ArkConfigSettings(); configSettings.ReadFromFile(File.ReadAllLines(configPath + "Game.ini")); configSettings.ReadFromFile(File.ReadAllLines(configPath + "GameUserSettings.ini")); //Open the .ark file now. string arkFileLocaton = Path.Combine(savePath, mapFileName + ".ark"); var arkFile = ArkSaveEditor.Deserializer.ArkSaveDeserializer.OpenDotArk(arkFileLocaton); //Loop through all .arkprofile files here and add them to the player list. string[] saveFilePaths = Directory.GetFiles(savePath); foreach (string profilePathname in saveFilePaths) { try { if (profilePathname.ToLower().EndsWith(".arkprofile")) { //This is an ARK profile. Open it. players.Add(ArkPlayerProfile.ReadFromFile(profilePathname)); } if (profilePathname.ToLower().EndsWith(".arktribe")) { //This is an ARK tribe. Open it. tribes.Add(new ArkTribeProfile(profilePathname, this)); } } catch (Exception ex) { Console.WriteLine($"Failed to load an Ark tribe or player at {profilePathname.Substring(savePath.Length)}. It will be skipped. This could result in errors!"); Console.WriteLine($"Error debug data: {ex.Message} - {ex.StackTrace}"); } } //Check to see if we have imported data. This will crash if we have not. if (ArkImports.dino_entries == null) { throw new Exception("Missing ArkImports.dino_entries! You should run ArkImports.ImportContent() to import the content."); } if (ArkImports.item_entries == null) { throw new Exception("Missing ArkImports.item_entries! You should run ArkImports.ImportContent() to import the content."); } if (ArkImports.world_settings == null) { throw new Exception("Missing ArkImports.world_settings! You should run ArkImports.ImportContent() to import the content."); } //Set our sources first sources = arkFile.gameObjects; //Do some analysis to find objects for (int i = 0; i < sources.Count; i++) { var g = sources[i]; string classname = g.classname.classname; bool known = false; //Check if this is a dinosaur by matching the classname. if (Enum.TryParse <DinoClasses>(classname, out DinoClasses dinoClass)) { //This is a dinosaur. dinos.Add(new ArkDinosaur(this, this.sources[i])); known = true; } //Check if this is a player if (classname == "PlayerPawnTest_Male_C" || classname == "PlayerPawnTest_Female_C") { //This is a player. playerCharacters.Add(new ArkPlayer(this, this.sources[i])); known = true; } //Check if this is a structure StructureDisplayMetadata metadata = ArkImports.GetStructureDisplayMetadataByClassname(classname); if (metadata != null) { //This is a structure. structures.Add(new ArkStructure(this, this.sources[i], metadata)); known = true; } } //Get the other metadata map = arkFile.meta.binaryDataNames[0]; gameTime = arkFile.gameTime; //If we got the override map data, set it. Else, auto detect if (overrideMapData == null) { //Autodetect if (ArkMapDataTable.arkmaps.ContainsKey(map)) { mapinfo = ArkMapDataTable.arkmaps[map]; } else { throw new Exception($"Ark map, '{map}', could not be found in the ArkMapDataTable. Please provide an override map data in the constructor for the ArkWorld."); } } else { mapinfo = overrideMapData; } }
/* * 0: MaxStatusValues - baseLevel * 1: AmountMaxGainedPerLevelUpValue - increasePerWildLevel * 2: AmountMaxGainedPerLevelUpValueTamed - increasePerTamedLevel * 3: TamingMaxStatAdditions - additiveTamingBonus * 4: TamingMaxStatMultipliers - multiplicativeTamingBonus */ public static ArkBreedingStat Compute(ArkDinoEntry e, DinoStatTypeIndex index, ArkConfigSettings settings) { double[] statMultipliers = new double[] { 1, 1, 1, 1 }; return(new ArkBreedingStat { BaseValue = e.baseLevel[index], AddWhenTamed = (float)e.additiveTamingBonus[index] * (e.additiveTamingBonus[index] > 0 ? (float)statMultipliers[0] : 1), MultAffinity = (float)e.multiplicativeTamingBonus[index] * (e.multiplicativeTamingBonus[index] > 0 ? (float)statMultipliers[1] : 1), IncPerTamedLevel = (float)e.increasePerTamedLevel[index] * (float)statMultipliers[2], IncPerWildLevel = (float)e.increasePerWildLevel[index] * (float)statMultipliers[3], }); }
public static double CalculateStat(ArkDinoEntry dino_entry, DinoStatTypeIndex stat, float levelWild, float tamingEff, float levelDom, float imprintingBonus, ArkWorldSettings world, ArkConfigSettings settings, bool isTamed) { // if stat is generally available but level is set to -1 (== unknown), return -1 (== unknown) if (levelWild < 0 && dino_entry != null && dino_entry.increasePerWildLevel[stat] != 0) { return(-1); } if (dino_entry != null) { Dictionary <DinoStatTypeIndex, ArkBreedingStat> stats = dino_entry.GetBreedingStats(settings); double add = 0, domMult = 1, imprintingM = 1, tamedBaseHP = 1; if (isTamed) { add = stats[stat].AddWhenTamed; double domMultAffinity = stats[stat].MultAffinity; // the multiplicative bonus is only multiplied with the TE if it is positive (i.e. negative boni won't get less bad if the TE is low) if (domMultAffinity >= 0) { domMultAffinity *= tamingEff; } domMult = (tamingEff >= 0 ? (1 + domMultAffinity) : 1) * (1 + levelDom * stats[stat].IncPerTamedLevel); if (imprintingBonus > 0 && stat != DinoStatTypeIndex.Stamina && stat != DinoStatTypeIndex.Oxygen && stat != DinoStatTypeIndex.Temperature && (stat != DinoStatTypeIndex.Speed /*|| species.NoImprintingForSpeed == false*/) && stat != DinoStatTypeIndex.TemperatureFortitude && stat != DinoStatTypeIndex.CraftingSpeed ) { imprintingM = 1 + 0.2 * imprintingBonus * settings.BabyImprintingStatScaleMultiplier; // TODO 0.2 is not always true } if (stat == 0) { tamedBaseHP = (float)dino_entry.statusComponent.tamedBaseHealthMultiplier; } } //double result = Math.Round((species.stats[stat].BaseValue * tamedBaseHP * (1 + species.stats[stat].IncPerWildLevel * levelWild) * imprintingM + add) * domMult, Utils.precision(stat), MidpointRounding.AwayFromZero); // double is too precise and results in wrong values due to rounding. float results in better values, probably ARK uses float as well. // or rounding first to a precision of 7, then use the rounding of the precision //double resultt = Math.Round((species.stats[stat].BaseValue * tamedBaseHP * (1 + species.stats[stat].IncPerWildLevel * levelWild) * imprintingM + add) * domMult, 7); //resultt = Math.Round(resultt, Utils.precision(stat), MidpointRounding.AwayFromZero); // adding an epsilon to handle rounding-errors double result = Math.Round((stats[stat].BaseValue * tamedBaseHP * (1 + stats[stat].IncPerWildLevel * levelWild) * imprintingM + add) * domMult + roundupDelta, precision(stat), MidpointRounding.AwayFromZero); return(result >= 0 ? result : 0); } return(0); }