/// <summary> /// Creates an image with infos about the creature, using the user settings. /// </summary> /// <param name="cc">CreatureCollection for server settings.</param> public static Bitmap InfoGraphic(this Creature creature, CreatureCollection cc) { var fontName = Properties.Settings.Default.InfoGraphicFontName; if (string.IsNullOrWhiteSpace(fontName)) { fontName = "Arial"; Properties.Settings.Default.InfoGraphicFontName = fontName; } return(InfoGraphic(creature, cc, Properties.Settings.Default.InfoGraphicHeight, fontName, Properties.Settings.Default.InfoGraphicForeColor, Properties.Settings.Default.InfoGraphicBackColor, Properties.Settings.Default.InfoGraphicBorderColor, Properties.Settings.Default.InfoGraphicDisplayName, Properties.Settings.Default.InfoGraphicWithDomLevels, Properties.Settings.Default.InfoGraphicDisplayMutations, Properties.Settings.Default.InfoGraphicDisplayGeneration, Properties.Settings.Default.InfoGraphicShowStatValues, Properties.Settings.Default.InfoGraphicShowMaxWildLevel, Properties.Settings.Default.InfoGraphicExtraRegionNames, Properties.Settings.Default.InfoGraphicShowRegionNamesIfNoImage)); }
public Settings(CreatureCollection cc, int page = 0) { initStuff(); this.cc = cc; loadSettings(cc); tabControlSettings.SelectTab(page); }
public Settings(CreatureCollection cc, SettingsTabPages page) { InitializeData(); this.cc = cc; LoadSettings(cc); tabControlSettings.SelectTab((int)page); }
public Settings(CreatureCollection cc, int page = 0) { InitializeData(); this.cc = cc; LoadSettings(cc); tabControlSettings.SelectTab(page); }
/// <summary> /// Adds the mods found by CheckForMissingModFiles to the collection file. /// </summary> /// <param name="creatureCollection"></param> /// <param name="modTags">List of the mod tags. Each entry must be loaded.</param> public static void AddModsToCollection(CreatureCollection creatureCollection, List <string> modTags) { if (creatureCollection.modIDs == null) { creatureCollection.modIDs = new List <string>(); } creatureCollection.modIDs.AddRange(modTags.Select(mt => Values.V.modsManifest.modsByTag[mt].mod.id)); creatureCollection.modListHash = 0; // indicates a reload of the mod-values is needed }
/// <summary> /// Convert old libraries /// </summary> /// <param name="ccOld">CreatureCollection to be converted</param> public static CreatureCollection ConvertXml2Asb(CreatureCollectionOld ccOld, string libraryFilePath) { MessageBox.Show($"The library will be converted to the new format that supports all possible ARK-stats (e.g. the crafting speed for the Gacha).\n\nThe old library file is still available at \n{libraryFilePath}\nyou can keep it as a backup.", "Library will be converted", MessageBoxButtons.OK, MessageBoxIcon.Information); CreatureCollection ccNew = new CreatureCollection(); UpgradeFormatTo12Stats(ccOld, ccNew); TransferParameters(ccOld, ccNew); return(ccNew); }
public LibraryFilter(CreatureCollection cc) : this() { _cc = cc; _colorPicker = new MyColorPicker(); SetColorFilter(Properties.Settings.Default.FilterOnlyIfColorId); CbUseFilterInTopStatCalculation.Checked = Properties.Settings.Default.useFiltersInTopStatCalculation; CbLibraryGroupSpecies.Checked = Properties.Settings.Default.LibraryGroupBySpecies; UpdateOwnerServerTagLists(); Localization(); }
/// <summary> /// Creates infoGraphic and copies it to the clipboard. /// </summary> /// <param name="creature"></param> /// <param name="cc">CreatureCollection for server settings.</param> public static void ExportInfoGraphicToClipboard(this Creature creature, CreatureCollection cc = null) { if (creature == null) { return; } using (var bmp = creature.InfoGraphic(cc)) { if (bmp != null) { Clipboard.SetImage(bmp); } } }
public CustomStatOverridesEditor(List <Species> species, CreatureCollection cc) { InitializeComponent(); overrideEdits = new StatBaseValuesEdit[Values.STATS_COUNT]; for (int s = 0; s < Values.STATS_COUNT; s++) { var se = new StatBaseValuesEdit() { StatName = Utils.statName(s, true) }; overrideEdits[s] = se; flowLayoutPanelOverrideEdits.Controls.Add(se); flowLayoutPanelOverrideEdits.SetFlowBreak(se, true); } this.cc = cc; this.species = species; UpdateList(); }
private void InitializeStatValues() { bool setTamingFood = TamingFoodData.TryLoadDefaultFoodData(out specialFoodData); if (specialFoodData == null) { specialFoodData = new Dictionary <string, TamingData>(); } _V.specialFoodData = specialFoodData; if (setTamingFood && specialFoodData.ContainsKey("default")) { _V.defaultFoodData = specialFoodData["default"].specialFoodValues; } else { _V.defaultFoodData = new Dictionary <string, TamingFood>(); } _V.speciesNames = new List <string>(); foreach (Species sp in _V.species) { _V.speciesNames.Add(sp.name); if (setTamingFood && specialFoodData.ContainsKey(sp.name)) { sp.taming.eats = specialFoodData[sp.name].eats; sp.taming.specialFoodValues = specialFoodData[sp.name].specialFoodValues; } } OrderSpecies(); _V.LoadAliases(); _V.UpdateSpeciesBlueprintDictionaries(); _V.loadedModsHash = CreatureCollection.CalculateModListHash(new List <Mod>()); // transfer extra loaded objects from the old object to the new one _V.modsManifest = modsManifest; _V.serverMultipliersPresets = serverMultipliersPresets; }
public CustomStatOverridesEditor(List <Species> species, CreatureCollection cc) { InitializeComponent(); overrideEdits = new StatBaseValuesEdit[Values.STATS_COUNT]; for (int s = 0; s < Values.STATS_COUNT; s++) { var se = new StatBaseValuesEdit(); se.SetStatNameByIndex(s); overrideEdits[s] = se; flowLayoutPanelOverrideEdits.Controls.Add(se); flowLayoutPanelOverrideEdits.SetFlowBreak(se, true); } this.cc = cc; this.species = species; throttlingTimer = new Timer { Interval = 200 }; throttlingTimer.Tick += ThrottlingTimer_Tick; UpdateList(species); }
private void LoadSettings(CreatureCollection cc) { if (cc.serverMultipliers?.statMultipliers != null) { for (int s = 0; s < Values.STATS_COUNT; s++) { if (s < cc.serverMultipliers.statMultipliers.Length && cc.serverMultipliers.statMultipliers[s].Length > 3) { multSetter[s].Multipliers = cc.serverMultipliers.statMultipliers[s]; } else { multSetter[s].Multipliers = null; } } } cbSingleplayerSettings.Checked = cc.singlePlayerSettings; nudMaxDomLevels.ValueSave = cc.maxDomLevel; numericUpDownMaxBreedingSug.ValueSave = cc.maxBreedingSuggestions; nudMaxWildLevels.ValueSave = cc.maxWildLevel; nudMaxServerLevel.ValueSave = cc.maxServerLevel > 0 ? cc.maxServerLevel : 0; nudMaxGraphLevel.ValueSave = cc.maxChartLevel; #region Non-event multiplier nudMatingSpeed.ValueSave = (decimal)cc.serverMultipliers.MatingSpeedMultiplier; nudMatingInterval.ValueSave = (decimal)cc.serverMultipliers.MatingIntervalMultiplier; nudEggHatchSpeed.ValueSave = (decimal)cc.serverMultipliers.EggHatchSpeedMultiplier; nudBabyMatureSpeed.ValueSave = (decimal)cc.serverMultipliers.BabyMatureSpeedMultiplier; nudBabyImprintingStatScale.ValueSave = (decimal)cc.serverMultipliers.BabyImprintingStatScaleMultiplier; nudBabyCuddleInterval.ValueSave = (decimal)cc.serverMultipliers.BabyCuddleIntervalMultiplier; nudTamingSpeed.ValueSave = (decimal)cc.serverMultipliers.TamingSpeedMultiplier; nudDinoCharacterFoodDrain.ValueSave = (decimal)cc.serverMultipliers.DinoCharacterFoodDrainMultiplier; nudBabyFoodConsumptionSpeed.ValueSave = (decimal)cc.serverMultipliers.BabyFoodConsumptionSpeedMultiplier; #endregion #region event-multiplier ServerMultipliers serverMultipliersEvent = cc.serverMultipliersEvents ?? cc.serverMultipliers; nudBabyCuddleIntervalEvent.ValueSave = (decimal)serverMultipliersEvent.BabyCuddleIntervalMultiplier; nudTamingSpeedEvent.ValueSave = (decimal)serverMultipliersEvent.TamingSpeedMultiplier; nudDinoCharacterFoodDrainEvent.ValueSave = (decimal)serverMultipliersEvent.DinoCharacterFoodDrainMultiplier; nudMatingIntervalEvent.ValueSave = (decimal)serverMultipliersEvent.MatingIntervalMultiplier; nudEggHatchSpeedEvent.ValueSave = (decimal)serverMultipliersEvent.EggHatchSpeedMultiplier; nudBabyMatureSpeedEvent.ValueSave = (decimal)serverMultipliersEvent.BabyMatureSpeedMultiplier; nudBabyFoodConsumptionSpeedEvent.ValueSave = (decimal)serverMultipliersEvent.BabyFoodConsumptionSpeedMultiplier; #endregion checkBoxAutoSave.Checked = Properties.Settings.Default.autosave; numericUpDownAutosaveMinutes.ValueSave = Properties.Settings.Default.autosaveMinutes; chkbSpeechRecognition.Checked = Properties.Settings.Default.SpeechRecognition; chkCollectionSync.Checked = Properties.Settings.Default.syncCollection; if (Properties.Settings.Default.celsius) { radioButtonCelsius.Checked = true; } else { radioButtonFahrenheit.Checked = true; } cbIgnoreSexInBreedingPlan.Checked = Properties.Settings.Default.IgnoreSexInBreedingPlan; checkBoxDisplayHiddenStats.Checked = Properties.Settings.Default.oxygenForAll; tbDefaultFontName.Text = Properties.Settings.Default.DefaultFontName; nudDefaultFontSize.Value = (decimal)Properties.Settings.Default.DefaultFontSize; #region overlay nudOverlayInfoDuration.ValueSave = Properties.Settings.Default.OverlayInfoDuration; nudOverlayTimerPosX.ValueSave = Properties.Settings.Default.OverlayTimerPosition.X; nudOverlayTimerPosY.ValueSave = Properties.Settings.Default.OverlayTimerPosition.Y; nudOverlayInfoPosDFR.ValueSave = Properties.Settings.Default.OverlayInfoPosition.X; nudOverlayInfoPosY.ValueSave = Properties.Settings.Default.OverlayInfoPosition.Y; cbCustomOverlayLocation.Checked = Properties.Settings.Default.UseCustomOverlayLocation; nudCustomOverlayLocX.ValueSave = Properties.Settings.Default.CustomOverlayLocation.X; nudCustomOverlayLocY.ValueSave = Properties.Settings.Default.CustomOverlayLocation.Y; #endregion #region Timers cbTimersInOverlayAutomatically.Checked = Properties.Settings.Default.DisplayTimersInOverlayAutomatically; cbKeepExpiredTimersInOverlay.Checked = Properties.Settings.Default.KeepExpiredTimersInOverlay; cbDeleteExpiredTimersOnSaving.Checked = Properties.Settings.Default.DeleteExpiredTimersOnSaving; #endregion #region OCR cbShowOCRButton.Checked = Properties.Settings.Default.showOCRButton; nudWaitBeforeScreenCapture.ValueSave = Properties.Settings.Default.waitBeforeScreenCapture; nudWhiteThreshold.ValueSave = Properties.Settings.Default.OCRWhiteThreshold; tbOCRCaptureApp.Text = Properties.Settings.Default.OCRApp; cbOCRIgnoreImprintValue.Checked = Properties.Settings.Default.OCRIgnoresImprintValue; #endregion customSCStarving.SoundFile = Properties.Settings.Default.soundStarving; customSCWakeup.SoundFile = Properties.Settings.Default.soundWakeup; customSCBirth.SoundFile = Properties.Settings.Default.soundBirth; customSCCustom.SoundFile = Properties.Settings.Default.soundCustom; tbPlayAlarmsSeconds.Text = Properties.Settings.Default.playAlarmTimes; cbConsiderWildLevelSteps.Checked = cc.considerWildLevelSteps; nudWildLevelStep.ValueSave = cc.wildLevelStep; cbInventoryCheck.Checked = Properties.Settings.Default.inventoryCheckTimer; cbAllowMoreThanHundredImprinting.Checked = cc.allowMoreThanHundredImprinting; #region library cbCreatureColorsLibrary.Checked = Properties.Settings.Default.showColorsInLibrary; cbApplyGlobalSpeciesToLibrary.Checked = Properties.Settings.Default.ApplyGlobalSpeciesToLibrary; cbLibraryHighlightTopCreatures.Checked = Properties.Settings.Default.LibraryHighlightTopCreatures; #endregion #region import exported if (Properties.Settings.Default.ExportCreatureFolders != null) { foreach (string path in Properties.Settings.Default.ExportCreatureFolders) { aTExportFolderLocationsBindingSource.Add(ATImportExportedFolderLocation.CreateFromString(path)); } } nudWarnImportMoreThan.Value = Properties.Settings.Default.WarnWhenImportingMoreCreaturesThan; cbApplyNamePatternOnImport.Checked = Properties.Settings.Default.applyNamePatternOnImportIfEmptyName; cbCopyPatternNameToClipboard.Checked = Properties.Settings.Default.copyNameToClipboardOnImportWhenAutoNameApplied; cbAutoImportExported.Checked = Properties.Settings.Default.AutoImportExportedCreatures; cbPlaySoundOnAutomaticImport.Checked = Properties.Settings.Default.PlaySoundOnAutoImport; cbMoveImportedFileToSubFolder.Checked = Properties.Settings.Default.MoveAutoImportedFileToSubFolder; cbDeleteAutoImportedFile.Checked = Properties.Settings.Default.DeleteAutoImportedFile; nudImportLowerBoundTE.ValueSave = (decimal)Properties.Settings.Default.ImportLowerBoundTE * 100; #endregion #region import savegame if (Properties.Settings.Default.arkSavegamePaths != null) { foreach (string path in Properties.Settings.Default.arkSavegamePaths) { aTImportFileLocationBindingSource.Add(ATImportFileLocation.CreateFromString(path)); } } fileSelectorExtractedSaveFolder.Link = Properties.Settings.Default.savegameExtractionPath; cbImportUpdateCreatureStatus.Checked = cc.changeCreatureStatusOnSavegameImport; textBoxImportTribeNameFilter.Text = Properties.Settings.Default.ImportTribeNameFilter; cbIgnoreUnknownBPOnSaveImport.Checked = Properties.Settings.Default.IgnoreUnknownBlueprintsOnSaveImport; cbSaveImportCryo.Checked = Properties.Settings.Default.SaveImportCryo; #endregion cbDevTools.Checked = Properties.Settings.Default.DevTools; cbPrettifyJSON.Checked = Properties.Settings.Default.prettifyCollectionJson; cbAdminConsoleCommandWithCheat.Checked = Properties.Settings.Default.AdminConsoleCommandWithCheat; string langKey = languages.FirstOrDefault(x => x.Value == Properties.Settings.Default.language).Key ?? ""; int langI = cbbLanguage.Items.IndexOf(langKey); cbbLanguage.SelectedIndex = langI == -1 ? 0 : langI; }
/// <summary> /// Check if mod files for the missing species are available. /// </summary> /// <param name="unknownSpeciesBlueprints"></param> public static (List <string>, List <string>, List <string>) CheckForMissingModFiles(CreatureCollection creatureCollection, List <string> unknownSpeciesBlueprints) { List <string> unknownModTags = unknownSpeciesBlueprints.Select(bp => Regex.Replace(bp, @"^\/Game\/Mods\/([^\/]+)\/.*", "$1")) .Where(bp => !string.IsNullOrEmpty(bp)) .Distinct() .ToList(); if (!unknownModTags.Any()) { return(null, null, null); } // check if the needed mod-values can be downloaded automatically. List <string> locallyAvailableModFiles = new List <string>(); List <string> onlineAvailableModFiles = new List <string>(); List <string> unavailableModFiles = new List <string>(); foreach (var modTag in unknownModTags) { if (Values.V.modsManifest.modsByTag.ContainsKey(modTag)) { if (Values.V.modsManifest.modsByTag[modTag].downloaded) { locallyAvailableModFiles.Add(modTag); } else { onlineAvailableModFiles.Add(modTag); } } else { unavailableModFiles.Add(modTag); } } return(locallyAvailableModFiles, onlineAvailableModFiles, unavailableModFiles); }
private void loadSettings(CreatureCollection cc) { if (cc.multipliers.Length > 7) { for (int s = 0; s < 8; s++) { if (cc.multipliers[s].Length > 3) { multSetter[s].Multipliers = cc.multipliers[s]; } } } cbSingleplayerSettings.Checked = cc.singlePlayerSettings; numericUpDownHatching.Value = (decimal)cc.EggHatchSpeedMultiplier; numericUpDownMaturation.Value = (decimal)cc.BabyMatureSpeedMultiplier; numericUpDownDomLevelNr.Value = cc.maxDomLevel; numericUpDownMaxBreedingSug.Value = cc.maxBreedingSuggestions; numericUpDownMaxWildLevel.Value = cc.maxWildLevel; nudMaxServerLevel.Value = cc.maxServerLevel; numericUpDownMaxChartLevel.Value = cc.maxChartLevel; numericUpDownImprintingM.Value = (decimal)cc.imprintingMultiplier; numericUpDownBabyCuddleIntervalMultiplier.Value = (decimal)cc.babyCuddleIntervalMultiplier; numericUpDownTamingSpeed.Value = (decimal)cc.tamingSpeedMultiplier; numericUpDownTamingFoodRate.Value = (decimal)cc.tamingFoodRateMultiplier; nudMatingInterval.Value = (decimal)cc.MatingIntervalMultiplier; nudBabyFoodConsumptionSpeed.Value = (decimal)cc.BabyFoodConsumptionSpeedMultiplier; // event-multiplier nudCuddleIntervalEvent.Value = (decimal)cc.babyCuddleIntervalMultiplierEvent; nudTamingSpeedEvent.Value = (decimal)cc.tamingSpeedMultiplierEvent; nudTamingFoodRateEvent.Value = (decimal)cc.tamingFoodRateMultiplierEvent; nudMatingIntervalEvent.Value = (decimal)cc.MatingIntervalMultiplierEvent; nudHatchingSpeedEvent.Value = (decimal)cc.EggHatchSpeedMultiplierEvent; nudMaturationSpeedEvent.Value = (decimal)cc.BabyMatureSpeedMultiplierEvent; nudBabyFoodConsumptionEvent.Value = (decimal)cc.BabyFoodConsumptionSpeedMultiplierEvent; checkBoxAutoSave.Checked = Properties.Settings.Default.autosave; numericUpDownAutosaveMinutes.Value = Properties.Settings.Default.autosaveMinutes; nudWhiteThreshold.Value = Properties.Settings.Default.OCRWhiteThreshold; chkbSpeechRecognition.Checked = Properties.Settings.Default.SpeechRecognition; nudOverlayInfoDuration.Value = Properties.Settings.Default.OverlayInfoDuration; chkCollectionSync.Checked = Properties.Settings.Default.syncCollection; if (Properties.Settings.Default.celsius) { radioButtonCelsius.Checked = true; } else { radioButtonFahrenheit.Checked = true; } cbIgnoreSexInBreedingPlan.Checked = Properties.Settings.Default.IgnoreSexInBreedingPlan; checkBoxOxygenForAll.Checked = Properties.Settings.Default.oxygenForAll; nudWaitBeforeScreenCapture.Value = Properties.Settings.Default.waitBeforeScreenCapture; string ocrApp = Properties.Settings.Default.OCRApp; int i = cbOCRApp.Items.IndexOf(ocrApp); if (i == -1) { textBoxOCRCustom.Text = ocrApp; cbOCRApp.SelectedIndex = cbOCRApp.Items.IndexOf("Custom"); } else { cbOCRApp.SelectedIndex = i; } customSCStarving.SoundFile = Properties.Settings.Default.soundStarving; customSCWakeup.SoundFile = Properties.Settings.Default.soundWakeup; customSCBirth.SoundFile = Properties.Settings.Default.soundBirth; customSCCustom.SoundFile = Properties.Settings.Default.soundCustom; tbPlayAlarmsSeconds.Text = Properties.Settings.Default.playAlarmTimes; cbConsiderWildLevelSteps.Checked = cc.considerWildLevelSteps; nudWildLevelStep.Value = cc.wildLevelStep; cbInventoryCheck.Checked = Properties.Settings.Default.inventoryCheckTimer; cbAllowMoreThanHundredImprinting.Checked = cc.allowMoreThanHundredImprinting; cbCreatureColorsLibrary.Checked = Properties.Settings.Default.showColorsInLibrary; //ark-tools fileSelectorARKToolsExe.Link = Properties.Settings.Default.arkToolsPath; fileSelectorExtractedSaveFolder.Link = Properties.Settings.Default.savegameExtractionPath; if (Properties.Settings.Default.arkSavegamePaths != null) { foreach (string path in Properties.Settings.Default.arkSavegamePaths) { aTImportFileLocationBindingSource.Add(ATImportFileLocation.CreateFromString(path)); } } cbImportUpdateCreatureStatus.Checked = Properties.Settings.Default.importChangeCreatureStatus; fileSelectorImportExported.Link = Properties.Settings.Default.ExportCreatureFolder; cbDevTools.Checked = Properties.Settings.Default.DevTools; }
public Settings(CreatureCollection cc) { initStuff(); this.cc = cc; loadSettings(cc); }
/// <summary> /// Tries to converts the library from the 8-stats format to the 12-stats format and the species identification by the blueprintpath. /// </summary> public static void UpgradeFormatTo12Stats(CreatureCollectionOld ccOld, CreatureCollection ccNew) { if (ccOld == null) { return; } // if library has the old statMultiplier-indices, fix the order var newToOldIndices = new int[] { 0, 1, 7, 2, 3, -1, -1, 4, 5, 6, -1, -1 }; if (ccOld.multipliers != null && ccOld.multipliers.Length == 8) { /// old order was /// HP, Stam, Ox, Fo, We, Dm, Sp, To /// new order is // 0: Health // 1: Stamina / Charge Capacity // 2: Torpidity // 3: Oxygen / Charge Regeneration // 4: Food // 5: Water // 6: Temperature // 7: Weight // 8: MeleeDamageMultiplier / Charge Emission Range // 9: SpeedMultiplier // 10: TemperatureFortitude // 11: CraftingSpeedMultiplier // imprinting bonus factor default 0.2, 0, 0.2, 0, 0.2, 0.2, 0, 0.2, 0.2, 0.2, 0, 0 // i.e. stats without imprinting are by default: St, Ox, Te, TF, Cr // create new multiplierArray var newMultipliers = new double[Values.STATS_COUNT][]; for (int s = 0; s < Values.STATS_COUNT; s++) { newMultipliers[s] = new double[4]; if (newToOldIndices[s] >= 0) { for (int si = 0; si < 4; si++) { newMultipliers[s][si] = ccOld.multipliers[newToOldIndices[s]][si]; } } else { for (int si = 0; si < 4; si++) { newMultipliers[s][si] = 1; } } } ccOld.multipliers = newMultipliers; } ccNew.creatures = new List <Creature>(); foreach (CreatureOld c in ccOld.creatures) { Creature newC = new Creature() { addedToLibrary = c.addedToLibrary.Year < 2000 ? default(DateTime?) : c.addedToLibrary, ArkId = c.ArkId, ArkIdImported = c.ArkIdImported, colors = c.colors, cooldownUntil = c.cooldownUntil.Year < 2000 ? default(DateTime?) : c.cooldownUntil, domesticatedAt = c.domesticatedAt.Year < 2000 ? default(DateTime?) : c.domesticatedAt, fatherGuid = c.fatherGuid, flags = c.flags, generation = c.generation, growingLeft = c.growingLeft, growingPaused = c.growingPaused, growingUntil = c.growingUntil.Year < 2000 ? default(DateTime?) : c.growingUntil, guid = c.guid, imprinterName = c.imprinterName, imprintingBonus = c.imprintingBonus, isBred = c.isBred, motherGuid = c.motherGuid, mutationsMaternal = c.mutationsMaternal, mutationsPaternal = c.mutationsPaternal, name = c.name, note = c.note, owner = c.owner, server = c.server, sex = c.sex, Status = c.status, tags = c.tags, tamingEff = c.tamingEff, tribe = c.tribe }; ccNew.creatures.Add(newC); if (c.IsPlaceholder) { newC.flags |= CreatureFlags.Placeholder; } if (c.neutered) { newC.flags |= CreatureFlags.Neutered; } // set new species-id if (c.Species == null && !string.IsNullOrEmpty(c.speciesBlueprint)) { c.Species = Values.V.SpeciesByBlueprint(c.speciesBlueprint); } if (c.Species == null && Values.V.TryGetSpeciesByName(c.species, out Species speciesObject)) { c.Species = speciesObject; } newC.Species = c.Species; // fix statlevel-indices newC.levelsWild = Convert8To12(c.levelsWild); newC.levelsDom = Convert8To12(c.levelsDom); } ccNew.creaturesValues = new List <CreatureValues>(); foreach (var cvOld in ccOld.creaturesValues) { var cv = new CreatureValues() { ARKID = cvOld.ARKID, colorIDs = cvOld.colorIDs, cooldownUntil = cvOld.cooldownUntil.Year < 2000 ? default(DateTime?) : cvOld.cooldownUntil, domesticatedAt = cvOld.domesticatedAt.Year < 2000 ? default(DateTime?) : cvOld.domesticatedAt, fatherArkId = cvOld.fatherArkId, fatherGuid = cvOld.fatherGuid, growingUntil = cvOld.growingUntil.Year < 2000 ? default(DateTime?) : cvOld.growingUntil, guid = cvOld.guid, imprinterName = cvOld.imprinterName, imprintingBonus = cvOld.imprintingBonus, isBred = cvOld.isBred, isTamed = cvOld.isTamed, level = cvOld.level, levelsDom = cvOld.levelsDom, levelsWild = cvOld.levelsWild, motherArkId = cvOld.motherArkId, motherGuid = cvOld.motherGuid, mutationCounterFather = cvOld.mutationCounterFather, mutationCounterMother = cvOld.mutationCounterMother, name = cvOld.name, owner = cvOld.owner, server = cvOld.server, sex = cvOld.sex, speciesName = cvOld.species, statValues = cvOld.statValues, tamingEffMax = cvOld.tamingEffMax, tamingEffMin = cvOld.tamingEffMin, tribe = cvOld.tribe }; if (cvOld.neutered) { cv.flags |= CreatureFlags.Neutered; } if (Values.V.TryGetSpeciesByName(cvOld.species, out Species species)) { cv.Species = species; } ccNew.creaturesValues.Add(cv); // fix statlevel-indices cv.levelsWild = Convert8To12(cvOld.levelsWild); cv.levelsDom = Convert8To12(cvOld.levelsDom); cv.statValues = Convert8To12(cvOld.statValues); } }
public static void TransferParameters(CreatureCollectionOld ccOld, CreatureCollection ccNew) { ccNew.allowMoreThanHundredImprinting = ccOld.allowMoreThanHundredImprinting; ccNew.changeCreatureStatusOnSavegameImport = ccOld.changeCreatureStatusOnSavegameImport; ccNew.considerWildLevelSteps = ccOld.considerWildLevelSteps; ccNew.incubationListEntries = ccOld.incubationListEntries.Select(ile => new IncubationTimerEntry { fatherGuid = ile.fatherGuid, incubationDuration = ile.incubationDuration, incubationEnd = ile.incubationEnd, motherGuid = ile.motherGuid, timerIsRunning = ile.timerIsRunning, }).ToList(); ccNew.maxBreedingSuggestions = ccOld.maxBreedingSuggestions; ccNew.maxChartLevel = ccOld.maxChartLevel; ccNew.maxDomLevel = ccOld.maxDomLevel; ccNew.maxServerLevel = ccOld.maxServerLevel; ccNew.noteList = ccOld.noteList; ccNew.ownerList = ccOld.ownerList; ccNew.players = ccOld.players; ccNew.serverList = ccOld.serverList; ccNew.singlePlayerSettings = ccOld.singlePlayerSettings; ccNew.tags = ccOld.tags; ccNew.tagsExclude = ccOld.tagsExclude; ccNew.tagsInclude = ccOld.tagsInclude; ccNew.timerListEntries = ccOld.timerListEntries.Select(tle => new TimerListEntry { creatureGuid = tle.creatureGuid, group = tle.group, name = tle.name, sound = tle.sound, time = tle.time }).ToList(); ccNew.tribes = ccOld.tribes; ccNew.wildLevelStep = ccOld.wildLevelStep; // check if multiplier-conversion is possible if (ccOld?.multipliers == null) { return; } ccNew.serverMultipliers = new ServerMultipliers { BabyImprintingStatScaleMultiplier = ccOld.imprintingMultiplier, BabyCuddleIntervalMultiplier = ccOld.babyCuddleIntervalMultiplier, TamingSpeedMultiplier = ccOld.tamingSpeedMultiplier, DinoCharacterFoodDrainMultiplier = ccOld.tamingFoodRateMultiplier, MatingIntervalMultiplier = ccOld.MatingIntervalMultiplier, EggHatchSpeedMultiplier = ccOld.EggHatchSpeedMultiplier, BabyMatureSpeedMultiplier = ccOld.BabyMatureSpeedMultiplier, BabyFoodConsumptionSpeedMultiplier = ccOld.BabyFoodConsumptionSpeedMultiplier, statMultipliers = ccOld.multipliers // was converted to 12-stats before }; ccNew.serverMultipliersEvents = new ServerMultipliers { BabyImprintingStatScaleMultiplier = ccOld.imprintingMultiplier, // cannot be changed in events BabyCuddleIntervalMultiplier = ccOld.babyCuddleIntervalMultiplierEvent, TamingSpeedMultiplier = ccOld.tamingSpeedMultiplierEvent, DinoCharacterFoodDrainMultiplier = ccOld.tamingFoodRateMultiplierEvent, MatingIntervalMultiplier = ccOld.MatingIntervalMultiplierEvent, EggHatchSpeedMultiplier = ccOld.EggHatchSpeedMultiplierEvent, BabyMatureSpeedMultiplier = ccOld.BabyMatureSpeedMultiplierEvent, BabyFoodConsumptionSpeedMultiplier = ccOld.BabyFoodConsumptionSpeedMultiplierEvent }; }
/// <summary> /// Check if mod files for the missing species are available. /// </summary> /// <param name="unknownSpeciesBlueprints"></param> public static void CheckForMissingModFiles(CreatureCollection creatureCollection, List <string> unknownSpeciesBlueprints) { List <string> unknownModTags = unknownSpeciesBlueprints.Select(bp => Regex.Replace(bp, @"^\/Game\/Mods\/([^\/]+)\/.*", "$1")) .Where(bp => !string.IsNullOrEmpty(bp)) .Distinct() .ToList(); if (!unknownModTags.Any()) { return; } // check if the needed mod-values can be downloaded automatically. List <string> locallyAvailableModFiles = new List <string>(); List <string> onlineAvailableModFiles = new List <string>(); List <string> unavailableModFiles = new List <string>(); foreach (var modTag in unknownModTags) { if (Values.V.modsManifest.modsByTag.ContainsKey(modTag)) { if (Values.V.modsManifest.modsByTag[modTag].downloaded) { locallyAvailableModFiles.Add(modTag); } else { onlineAvailableModFiles.Add(modTag); } } else { unavailableModFiles.Add(modTag); } } MessageBox.Show("Some of the creatures to be imported have an unknown species, most likely because a mod is used.\n" + "To import these creatures, this application needs additional informations about these mods." + (locallyAvailableModFiles.Any() ? "\n\nThe value files for the following mods are already locally available and just need to be added to the library:\n" + string.Join("\n", locallyAvailableModFiles) : "") + (onlineAvailableModFiles.Any() ? "\n\nThe value files for the following mods can be downloaded automatically if you want:\n" + string.Join("\n", onlineAvailableModFiles) : "") + (unavailableModFiles.Any() ? "\n\nThe value files for the following mods are unknown. You probably manually need to create a mod-file to import the creatures depending on it.\n" + string.Join("\n", unavailableModFiles) : ""), "Unknown species", MessageBoxButtons.OK, MessageBoxIcon.Information); if ((onlineAvailableModFiles.Any() || locallyAvailableModFiles.Any()) && MessageBox.Show("Do you want to " + (onlineAvailableModFiles.Any() ? "download and " : "") + "add the values-files for the following mods to the library?\n\n" + string.Join("\n", onlineAvailableModFiles) + "\n" + string.Join("\n", locallyAvailableModFiles), "Add value-files?", MessageBoxButtons.YesNo, MessageBoxIcon.Question ) == DialogResult.Yes) { if (creatureCollection.modIDs == null) { creatureCollection.modIDs = new List <string>(); } creatureCollection.modIDs.AddRange(onlineAvailableModFiles.Select(mt => Values.V.modsManifest.modsByTag[mt].mod.id)); creatureCollection.modIDs.AddRange(locallyAvailableModFiles.Select(mt => Values.V.modsManifest.modsByTag[mt].mod.id)); creatureCollection.modListHash = 0; // indicates a reload of the mod-values is needed } }
private void loadSettings(CreatureCollection cc) { if (cc.multipliers.Length > 7) { for (int s = 0; s < 8; s++) { if (cc.multipliers[s].Length > 3) { multSetter[s].Multipliers = cc.multipliers[s]; } } } numericUpDownHatching.Value = (decimal)cc.EggHatchSpeedMultiplier; numericUpDownMaturation.Value = (decimal)cc.BabyMatureSpeedMultiplier; numericUpDownDomLevelNr.Value = cc.maxDomLevel; numericUpDownMaxBreedingSug.Value = cc.maxBreedingSuggestions; numericUpDownMaxWildLevel.Value = cc.maxWildLevel; numericUpDownMaxChartLevel.Value = cc.maxChartLevel; numericUpDownImprintingM.Value = (decimal)cc.imprintingMultiplier; numericUpDownBabyCuddleIntervalMultiplier.Value = (decimal)cc.babyCuddleIntervalMultiplier; numericUpDownTamingSpeed.Value = (decimal)cc.tamingSpeedMultiplier; numericUpDownTamingFoodRate.Value = (decimal)cc.tamingFoodRateMultiplier; nudMatingInterval.Value = (decimal)cc.MatingIntervalMultiplier; nudBabyFoodConsumptionSpeed.Value = (decimal)cc.BabyFoodConsumptionSpeedMultiplier; // event-multiplier nudCuddleIntervalEvent.Value = (decimal)cc.babyCuddleIntervalMultiplierEvent; nudTamingSpeedEvent.Value = (decimal)cc.tamingSpeedMultiplierEvent; nudTamingFoodRateEvent.Value = (decimal)cc.tamingFoodRateMultiplierEvent; nudMatingIntervalEvent.Value = (decimal)cc.MatingIntervalMultiplierEvent; nudHatchingSpeedEvent.Value = (decimal)cc.EggHatchSpeedMultiplierEvent; nudMaturationSpeedEvent.Value = (decimal)cc.BabyMatureSpeedMultiplierEvent; nudBabyFoodConsumptionEvent.Value = (decimal)cc.BabyFoodConsumptionSpeedMultiplierEvent; checkBoxAutoSave.Checked = Properties.Settings.Default.autosave; numericUpDownAutosaveMinutes.Value = Properties.Settings.Default.autosaveMinutes; nudWhiteThreshold.Value = Properties.Settings.Default.OCRWhiteThreshold; chkbSpeechRecognition.Checked = Properties.Settings.Default.SpeechRecognition; nudOverlayInfoDuration.Value = Properties.Settings.Default.OverlayInfoDuration; chkCollectionSync.Checked = Properties.Settings.Default.syncCollection; if (Properties.Settings.Default.celsius) { radioButtonCelsius.Checked = true; } else { radioButtonFahrenheit.Checked = true; } checkBoxOxygenForAll.Checked = Properties.Settings.Default.oxygenForAll; nudWaitBeforeScreenCapture.Value = Properties.Settings.Default.waitBeforeScreenCapture; string ocrApp = Properties.Settings.Default.OCRApp; int i = cbOCRApp.Items.IndexOf(ocrApp); if (i == -1) { textBoxOCRCustom.Text = ocrApp; cbOCRApp.SelectedIndex = cbOCRApp.Items.IndexOf("Custom"); } else { cbOCRApp.SelectedIndex = i; } customSCStarving.SoundFile = Properties.Settings.Default.soundStarving; customSCWakeup.SoundFile = Properties.Settings.Default.soundWakeup; customSCBirth.SoundFile = Properties.Settings.Default.soundBirth; tbNameGenerationPattern.Text = Properties.Settings.Default.sequentialUniqueNamePattern; cbConsiderWildLevelSteps.Checked = cc.considerWildLevelSteps; nudWildLevelStep.Value = cc.wildLevelStep; cbAdjustToPossibleImprinting.Checked = cc.adjustToPossibleImprinting; }
/// <summary> /// Creates an image with infos about the creature. /// </summary> /// <param name="creature"></param> /// <param name="cc">CreatureCollection for server settings.</param> /// <returns></returns> public static Bitmap InfoGraphic(this Creature creature, CreatureCollection cc) { if (creature == null) { return(null); } int maxGraphLevel = cc?.maxChartLevel ?? 0; if (maxGraphLevel < 1) { maxGraphLevel = 50; } int width = Properties.Settings.Default.InfoGraphicWidth; // 330 int height = width * 6 / 11; //180 int fontSize = Math.Max(1, height / 18); // 10 int fontSizeSmall = Math.Max(1, height * 2 / 45); // 8 int fontSizeHeader = Math.Max(1, height / 15); // 12 int frameThickness = Math.Max(1, height / 180); int statLineHeight = height * 5 / 59; // 15 var fontName = Properties.Settings.Default.InfoGraphicFontName; if (string.IsNullOrWhiteSpace(fontName)) { fontName = "Arial"; Properties.Settings.Default.InfoGraphicFontName = fontName; } var bmp = new Bitmap(width, height); using (var g = Graphics.FromImage(bmp)) using (var font = new Font(fontName, fontSize)) using (var fontSmall = new Font(fontName, fontSizeSmall)) using (var fontHeader = new Font(fontName, fontSizeHeader, FontStyle.Bold)) using (var fontBrush = new SolidBrush(Properties.Settings.Default.InfoGraphicForeColor)) using (var borderAroundColors = new Pen(Utils.ForeColor(Properties.Settings.Default.InfoGraphicBackColor), 1)) using (var stringFormatRight = new StringFormat { Alignment = StringAlignment.Far }) { g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias; int currentYPosition = frameThickness * 3; using (var backgroundBrush = new SolidBrush(Properties.Settings.Default.InfoGraphicBackColor)) g.FillRectangle(backgroundBrush, 0, 0, width, height); g.DrawString(creature.Species.DescriptiveNameAndMod, fontHeader, fontBrush, 3, currentYPosition); currentYPosition += height * 19 / 180; //19 string creatureInfos = $"{Loc.S("Level")} {creature.LevelHatched} | {Utils.SexSymbol(creature.sex) + (creature.flags.HasFlag(CreatureFlags.Neutered) ? $" ({Loc.S(creature.sex == Sex.Female ? "Spayed" : "Neutered")})" : string.Empty)}"; if (Properties.Settings.Default.InfoGraphicDisplayMutations) { creatureInfos += $" | {creature.Mutations} {Loc.S("Mutations")}"; } if (Properties.Settings.Default.InfoGraphicDisplayGeneration) { creatureInfos += $" | {Loc.S("generation")} {creature.generation}"; } g.DrawString(creatureInfos, font, fontBrush, width * 4 / 165, currentYPosition); currentYPosition += height * 17 / 180; //17 using (var p = new Pen(Color.FromArgb(50, Properties.Settings.Default.InfoGraphicForeColor), 1)) g.DrawLine(p, 0, currentYPosition, width, currentYPosition); currentYPosition += 2; // levels double meanLetterWidth = fontSize * 7d / 10; int xStatName = (int)meanLetterWidth; // x position of level number. torpor is the largest level number. bool showDomLevel = Properties.Settings.Default.InfoGraphicWithDomLevels; int xRightLevelValue = (int)(xStatName + ((showDomLevel ? 6 : 5) + creature.levelsWild[2].ToString().Length) * meanLetterWidth); int xRightLevelDomValue = xRightLevelValue; if (showDomLevel) { xRightLevelDomValue += (int)((creature.levelsDom.Max().ToString().Length) * meanLetterWidth); } int xRightBrValue = (int)(xRightLevelDomValue + (2 + MaxCharLength(creature.valuesBreeding)) * meanLetterWidth); int maxBoxLength = xRightBrValue - xStatName; int statBoxHeight = Math.Max(2, height / 90); g.DrawString(Loc.S("Levels"), font, fontBrush, xRightLevelDomValue, currentYPosition, stringFormatRight); g.DrawString(Loc.S("Values"), font, fontBrush, xRightBrValue, currentYPosition, stringFormatRight); int statDisplayIndex = 0; for (int si = 0; si < Values.STATS_COUNT; si++) { int statIndex = Values.statsDisplayOrder[si]; if (statIndex == (int)StatNames.Torpidity || !creature.Species.UsesStat(statIndex)) { continue; } int y = currentYPosition + (height / 9) + (statDisplayIndex++) * statLineHeight; // box // empty box to show the max possible length using (var b = new SolidBrush(Color.DarkGray)) g.FillRectangle(b, xStatName, y + statLineHeight - 1, maxBoxLength, statBoxHeight); double levelFractionOfMax = Math.Min(1, (double)creature.levelsWild[statIndex] / maxGraphLevel); if (levelFractionOfMax < 0) { levelFractionOfMax = 0; } int levelPercentageOfMax = (int)(100 * levelFractionOfMax); int statBoxLength = Math.Max((int)(maxBoxLength * levelFractionOfMax), 1); var statColor = Utils.GetColorFromPercent(levelPercentageOfMax); using (var b = new SolidBrush(statColor)) g.FillRectangle(b, xStatName, y + statLineHeight - 1, statBoxLength, statBoxHeight); using (var b = new SolidBrush(Color.FromArgb(10, statColor))) { for (int r = 4; r > 0; r--) { g.FillRectangle(b, xStatName - r, y + statLineHeight - 2 - r, statBoxLength + 2 * r, statBoxHeight + 2 * r); } } using (var p = new Pen(Utils.GetColorFromPercent(levelPercentageOfMax, -0.5), 1)) g.DrawRectangle(p, xStatName, y + statLineHeight - 1, statBoxLength, statBoxHeight); // stat name g.DrawString($"{Utils.StatName(statIndex, true, creature.Species.statNames)}", font, fontBrush, xStatName, y); // stat level number g.DrawString($"{creature.levelsWild[statIndex]}{(showDomLevel ? " +" : string.Empty)}", font, fontBrush, xRightLevelValue, y, stringFormatRight); // dom level number if (showDomLevel) { g.DrawString($"{creature.levelsDom[statIndex]}", font, fontBrush, xRightLevelDomValue, y, stringFormatRight); } // stat breeding value double displayedValue = showDomLevel ? creature.valuesDom[statIndex] : creature.valuesBreeding[statIndex]; string statValueRepresentation; if (Utils.Precision(statIndex) == 3) { statValueRepresentation = (100 * displayedValue).ToString("0.0"); g.DrawString("%", font, fontBrush, xRightBrValue, y); } else { statValueRepresentation = displayedValue.ToString("0.0"); } g.DrawString(statValueRepresentation, font, fontBrush, xRightBrValue, y, stringFormatRight); } // colors var enabledColorRegions = creature.Species.EnabledColorRegions; int xColor = (int)(xRightBrValue + meanLetterWidth * 3.5); int circleDiameter = height * 4 / 45; int colorRowHeight = circleDiameter + 2; int maxColorNameLength = (int)((width - xColor - circleDiameter) / meanLetterWidth); // max char length for the color region name if (maxColorNameLength < 0) { maxColorNameLength = 0; } bool creatureImageShown = false; bool displayMaxWild = Properties.Settings.Default.InfoGraphicShowMaxWildLevel; int extraMarginBottom = displayMaxWild ? fontSizeSmall : 0; int imageSize = (int)Math.Min(width - xColor - circleDiameter - 8 * meanLetterWidth - frameThickness * 4, height - currentYPosition - frameThickness * 4 - extraMarginBottom); if (imageSize > 5) { using (var crBmp = CreatureColored.GetColoredCreature(creature.colors, creature.Species, enabledColorRegions, imageSize, onlyImage: true, creatureSex: creature.sex)) { if (crBmp != null) { g.DrawImage(crBmp, width - imageSize - frameThickness * 4, height - imageSize - frameThickness * 4 - extraMarginBottom, imageSize, imageSize); creatureImageShown = true; } } } if (creature.colors != null) { g.DrawString(Loc.S("Colors"), font, fontBrush, xColor, currentYPosition); int colorRow = 0; for (int ci = 0; ci < Species.ColorRegionCount; ci++) { if (!enabledColorRegions[ci]) { continue; } int y = currentYPosition + (height / 9) + (colorRow++) * colorRowHeight; Color c = CreatureColors.CreatureColor(creature.colors[ci]); //Color fc = Utils.ForeColor(c); using (var b = new SolidBrush(c)) g.FillEllipse(b, xColor, y, circleDiameter, circleDiameter); g.DrawEllipse(borderAroundColors, xColor, y, circleDiameter, circleDiameter); string colorRegionName = null; //string colorName = CreatureColors.CreatureColorName(creature.colors[ci]); if (!creatureImageShown) { colorRegionName = creature.Species.colors[ci].name; int totalColorLength = colorRegionName.Length + 11; if (totalColorLength > maxColorNameLength) { // shorten color region name int lengthForRegionName = colorRegionName.Length - (totalColorLength - maxColorNameLength); colorRegionName = lengthForRegionName < 2 ? string.Empty : colorRegionName.Substring(0, lengthForRegionName - 1) + "…"; } if (!string.IsNullOrEmpty(colorRegionName)) { colorRegionName = " (" + colorRegionName + ")"; } } g.DrawString($"{creature.colors[ci]} - [{ci}]{colorRegionName}", fontSmall, fontBrush, xColor + circleDiameter + 4, y); } } // imprinting if (showDomLevel) { g.DrawString($"Imp: {creature.imprintingBonus * 100:0.0} %", font, fontBrush, xColor + (int)((Loc.S("Colors").Length + 3) * meanLetterWidth), currentYPosition); } // max wild level on server if (cc != null && displayMaxWild) { g.DrawString($"{Loc.S("max wild level")}: {cc.maxWildLevel}", fontSmall, fontBrush, width - 2 * frameThickness, height - fontSizeSmall - 4 * frameThickness, stringFormatRight); } // frame using (var p = new Pen(Properties.Settings.Default.InfoGraphicBorderColor, frameThickness)) g.DrawRectangle(p, 0, 0, width - frameThickness, height - frameThickness); } return(bmp); }
/// <summary> /// Loads the values from the default file. /// </summary> /// <returns></returns> public bool LoadValues() { try { using (FileStream file = FileService.GetJsonFileStream(Path.Combine(FileService.ValuesFolder, FileService.ValuesJson))) { DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(Values) , new DataContractJsonSerializerSettings() { UseSimpleDictionaryFormat = true } ); var tmpV = (Values)ser.ReadObject(file); if (tmpV.format != CURRENT_FORMAT_VERSION) { throw new FormatException("Unhandled format version"); } _V = tmpV; } } catch (FileNotFoundException) { if (MessageBox.Show($"Values-File {FileService.ValuesJson} not found. " + "ARK Smart Breeding will not work properly without that file.\n\n" + "Do you want to visit the releases page to redownload it?", "Error", MessageBoxButtons.YesNo, MessageBoxIcon.Error) == DialogResult.Yes) { System.Diagnostics.Process.Start(Updater.ReleasesUrl); } return(false); } catch (FormatException) { MessageBox.Show($"File {FileService.ValuesJson} is a format that is unsupported in this version of ARK Smart Breeding." + "\n\nTry updating to a newer version.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); return(false); } catch (Exception e) { if (e.GetType() == typeof(NullReferenceException)) { throw; } MessageBox.Show($"File {FileService.ValuesJson} couldn't be opened or read.\nErrormessage:\n\n" + e.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); return(false); } bool setTamingFood = TamingFoodData.TryLoadDefaultFoodData(out specialFoodData); if (specialFoodData == null) { specialFoodData = new Dictionary <string, TamingData>(); } _V.specialFoodData = specialFoodData; if (setTamingFood && specialFoodData.ContainsKey("default")) { _V.defaultFoodData = specialFoodData["default"].specialFoodValues; } else { _V.defaultFoodData = new Dictionary <string, TamingFood>(); } _V.speciesNames = new List <string>(); foreach (Species sp in _V.species) { _V.speciesNames.Add(sp.name); if (setTamingFood && specialFoodData.ContainsKey(sp.name)) { sp.taming.eats = specialFoodData[sp.name].eats; sp.taming.specialFoodValues = specialFoodData[sp.name].specialFoodValues; } } OrderSpecies(); _V.LoadAliases(); _V.UpdateSpeciesBlueprintDictionaries(); _V.loadedModsHash = CreatureCollection.CalculateModListHash(new List <Mod>()); if (_V.modsManifest == null) { if (modsManifest != null) { _V.modsManifest = modsManifest; } else { _V.LoadModsManifest(); } } if (serverMultipliersPresets != null) { _V.serverMultipliersPresets = serverMultipliersPresets; } else if (!ServerMultipliersPresets.TryLoadServerMultipliersPresets(out _V.serverMultipliersPresets)) { MessageBox.Show("The file with the server multipliers couldn't be loaded. Changed settings, e.g. for the singleplayer will be not available.\nIt's recommended to download the application again.", "Server multiplier file not loaded.", MessageBoxButtons.OK, MessageBoxIcon.Error); } return(true); }
/// <summary> /// Creates an image with infos about the creature. /// </summary> /// <param name="creature"></param> /// <param name="cc">CreatureCollection for server settings.</param> /// <returns></returns> public static Bitmap InfoGraphic(this Creature creature, CreatureCollection cc) { if (creature == null) { return(null); } int maxGraphLevel = cc?.maxChartLevel ?? 0; if (maxGraphLevel < 1) { maxGraphLevel = 50; } const int width = 330; const int height = 180; var bmp = new Bitmap(width, height); using (var g = Graphics.FromImage(bmp)) using (var font = new Font("Arial", 10)) using (var fontSmall = new Font("Arial", 8)) using (var fontHeader = new Font("Arial", 12, FontStyle.Bold)) using (var fontBrush = new SolidBrush(Color.Black)) using (var penBlack = new Pen(Color.Black, 1)) using (var stringFormatRight = new StringFormat() { Alignment = StringAlignment.Far }) { g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias; int currentYPosition = 3; using (var backgroundBrush = new SolidBrush(Color.AntiqueWhite)) g.FillRectangle(backgroundBrush, 0, 0, width, height); g.DrawString(creature.Species.DescriptiveNameAndMod, fontHeader, fontBrush, 3, currentYPosition); currentYPosition += 19; g.DrawString($"Level {creature.LevelHatched} | {Utils.SexSymbol(creature.sex) + (creature.flags.HasFlag(CreatureFlags.Neutered) ? $" ({Loc.S(creature.sex == Sex.Female ? "Spayed" : "Neutered")})" : string.Empty)} | {creature.Mutations} mutations | generation {creature.generation}", font, fontBrush, 8, currentYPosition); currentYPosition += 17; using (var p = new Pen(Color.LightGray, 1)) g.DrawLine(p, 0, currentYPosition, width, currentYPosition); currentYPosition += 2; // levels const int xStatName = 8; int xLevelValue = xStatName + 30 + (creature.levelsWild[2].ToString().Length) * 7; int xRightBrValue = xLevelValue + 14 + MaxBreedingValueLength(creature.valuesBreeding) * 7; int maxBoxLength = xRightBrValue - xStatName; const int statBoxHeight = 2; g.DrawString("Levels", font, fontBrush, xLevelValue, currentYPosition, stringFormatRight); g.DrawString("Values", font, fontBrush, xRightBrValue, currentYPosition, stringFormatRight); int statDisplayIndex = 0; for (int si = 0; si < Values.STATS_COUNT; si++) { int statIndex = Values.statsDisplayOrder[si]; if (statIndex == (int)StatNames.Torpidity || !creature.Species.UsesStat(statIndex)) { continue; } int y = currentYPosition + 20 + (statDisplayIndex++) * 15; // box // empty box to show the max possible length using (var b = new SolidBrush(Color.DarkGray)) g.FillRectangle(b, xStatName, y + 14, maxBoxLength, statBoxHeight); double levelFractionOfMax = Math.Min(1, (double)creature.levelsWild[statIndex] / maxGraphLevel); if (levelFractionOfMax < 0) { levelFractionOfMax = 0; } int levelPercentageOfMax = (int)(100 * levelFractionOfMax); int statBoxLength = Math.Max((int)(maxBoxLength * levelFractionOfMax), 1); var statColor = Utils.GetColorFromPercent(levelPercentageOfMax); using (var b = new SolidBrush(statColor)) g.FillRectangle(b, xStatName, y + 14, statBoxLength, statBoxHeight); using (var b = new SolidBrush(Color.FromArgb(10, statColor))) { for (int r = 4; r > 0; r--) { g.FillRectangle(b, xStatName - r, y + 13 - r, statBoxLength + 2 * r, statBoxHeight + 2 * r); } } using (var p = new Pen(Utils.GetColorFromPercent(levelPercentageOfMax, -0.5), 1)) g.DrawRectangle(p, xStatName, y + 14, statBoxLength, statBoxHeight); // stat name g.DrawString($"{Utils.StatName(statIndex, true, creature.Species.statNames)}", font, fontBrush, xStatName, y); // stat level number g.DrawString($"{creature.levelsWild[statIndex]}", font, fontBrush, xLevelValue, y, stringFormatRight); // stat breeding value string statValueRepresentation; if (Utils.Precision(statIndex) == 3) { statValueRepresentation = (100 * creature.valuesBreeding[statIndex]).ToString("0.0"); g.DrawString("%", font, fontBrush, xRightBrValue, y); } else { statValueRepresentation = creature.valuesBreeding[statIndex].ToString("0.0"); } g.DrawString(statValueRepresentation, font, fontBrush, xRightBrValue, y, stringFormatRight); } // colors var enabledColorRegions = creature.Species.EnabledColorRegions; bool creatureImageShown = false; const int imageSize = 125; using (var crBmp = CreatureColored.GetColoredCreature(creature.colors, creature.Species, enabledColorRegions, imageSize, onlyImage: true, creatureSex: creature.sex)) { if (crBmp != null) { g.DrawImage(crBmp, 200, 40, imageSize, imageSize); creatureImageShown = true; } } int xColor = xRightBrValue + 25; const int circleDiameter = 16; const int rowHeight = circleDiameter + 2; int maxColorNameLength = (width - xColor - circleDiameter) / 6; // max char length for the color region name if (maxColorNameLength < 0) { maxColorNameLength = 0; } g.DrawString("Colors", font, fontBrush, xColor, currentYPosition); int colorRow = 0; for (int ci = 0; ci < Species.ColorRegionCount; ci++) { if (!enabledColorRegions[ci]) { continue; } int y = currentYPosition + 20 + (colorRow++) * rowHeight; Color c = CreatureColors.CreatureColor(creature.colors[ci]); //Color fc = Utils.ForeColor(c); using (var b = new SolidBrush(c)) g.FillEllipse(b, xColor, y, circleDiameter, circleDiameter); g.DrawEllipse(penBlack, xColor, y, circleDiameter, circleDiameter); string colorRegionName = null; //string colorName = CreatureColors.CreatureColorName(creature.colors[ci]); if (!creatureImageShown) { colorRegionName = creature.Species.colors[ci].name; int totalColorLenght = colorRegionName.Length + 11; if (totalColorLenght > maxColorNameLength) { // shorten color region name int lengthForRegionName = colorRegionName.Length - (totalColorLenght - maxColorNameLength); colorRegionName = lengthForRegionName < 2 ? string.Empty : colorRegionName.Substring(0, lengthForRegionName - 1) + "…"; } if (!string.IsNullOrEmpty(colorRegionName)) { colorRegionName = " (" + colorRegionName + ")"; } } g.DrawString($"{creature.colors[ci]} - [{ci}]{colorRegionName}", fontSmall, fontBrush, xColor + circleDiameter + 4, y); } // max wild level on server if (cc != null) { g.DrawString($"max wild level: {cc.maxWildLevel}", fontSmall, fontBrush, width - 4, height - 14, stringFormatRight); } // frame using (var p = new Pen(Color.DarkRed, 1)) g.DrawRectangle(p, 0, 0, width - 1, height - 1); } return(bmp); }
/// <summary> /// Loads extra values-files that can add species values or modify existing ones /// </summary> public bool LoadModValues(List <string> modValueFileNames, bool showResults, out List <Mod> mods) { loadedModsHash = 0; List <Values> modifiedValues = new List <Values>(); mods = new List <Mod>(); if (modValueFileNames == null) { return(false); } CheckAndUpdateModFiles(modValueFileNames); foreach (string mf in modValueFileNames) { string filename = FileService.GetJsonPath(Path.Combine(FileService.ValuesFolder, mf)); if (TryLoadValuesFile(filename, setModFileName: true, out Values modValues)) { modifiedValues.Add(modValues); } } int speciesUpdated = 0; int speciesAdded = 0; // update data if existing foreach (Values modValues in modifiedValues) { // if mods are loaded multiple times, only keep the last mods.Remove(modValues.mod); mods.Add(modValues.mod); // species if (modValues.species != null) { foreach (Species sp in modValues.species) { if (string.IsNullOrWhiteSpace(sp.blueprintPath)) { continue; } Species originalSpecies = SpeciesByBlueprint(sp.blueprintPath); if (originalSpecies != null) { _V.species.Remove(originalSpecies); } _V.species.Add(sp); sp.Mod = modValues.mod; speciesAdded++; if (!blueprintToSpecies.ContainsKey(sp.blueprintPath)) { blueprintToSpecies.Add(sp.blueprintPath, sp); } } } // TODO support for mod colors } loadedModsHash = CreatureCollection.CalculateModListHash(mods); if (speciesUpdated == 0 && speciesAdded == 0) { return(true); // nothing changed } // sort new species OrderSpecies(); // mod-fooddata TODO _V.LoadAliases(); _V.UpdateSpeciesBlueprintDictionaries(); if (showResults) { MessageBox.Show($"The following mods were loaded:\n{string.Join(", ", modifiedValues.Select(m => m.mod.title).ToArray())}\n\n" + $"Species with changed stats: {speciesUpdated}\nSpecies added: {speciesAdded}", "Additional Values succesfully added", MessageBoxButtons.OK, MessageBoxIcon.Information); } return(true); }
/// <summary> /// Applies the serverMultipliers and creates precalculated species-stats values /// </summary> /// <param name="cc"></param> /// <param name="eventMultipliers"></param> /// <param name="applyStatMultipliers"></param> public void ApplyMultipliers(CreatureCollection cc, bool eventMultipliers = false, bool applyStatMultipliers = true) { currentServerMultipliers = (eventMultipliers ? cc.serverMultipliersEvents : cc.serverMultipliers)?.Copy(false); if (currentServerMultipliers == null) { currentServerMultipliers = Values.V.serverMultipliersPresets.GetPreset(ServerMultipliersPresets.OFFICIAL); } if (currentServerMultipliers == null) { MessageBox.Show("No default server multiplier values found.\nIt's recommend to redownload the application.", "No default multipliers available", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } ServerMultipliers singlePlayerServerMultipliers = null; if (cc.singlePlayerSettings) { /// The singleplayer multipliers are saved as a regular multiplierpreset, but they work differently /// in the way they are multiplied on existing multipliers and won't work on their own. /// The preset name "singleplayer" should only be used for this purpose. singlePlayerServerMultipliers = serverMultipliersPresets.GetPreset(ServerMultipliersPresets.SINGLEPLAYER); if (singlePlayerServerMultipliers == null) { MessageBox.Show("No values for the singleplayer multipliers found. The singleplayer multipliers cannot be applied.\nIt's recommend to redownload the application.", "No singleplayer data available", MessageBoxButtons.OK, MessageBoxIcon.Error); } } if (singlePlayerServerMultipliers != null) { currentServerMultipliers.MatingIntervalMultiplier *= singlePlayerServerMultipliers.MatingIntervalMultiplier; currentServerMultipliers.EggHatchSpeedMultiplier *= singlePlayerServerMultipliers.EggHatchSpeedMultiplier; currentServerMultipliers.BabyMatureSpeedMultiplier *= singlePlayerServerMultipliers.BabyMatureSpeedMultiplier; currentServerMultipliers.BabyCuddleIntervalMultiplier *= singlePlayerServerMultipliers.BabyCuddleIntervalMultiplier; currentServerMultipliers.TamingSpeedMultiplier *= singlePlayerServerMultipliers.TamingSpeedMultiplier; } currentServerMultipliers.FixZeroValues(); double[] defaultMultipliers = new double[] { 1, 1, 1, 1 }; // used if serverMultipliers don't specify non-default values foreach (Species sp in species) { if (applyStatMultipliers) { // stat-multiplier for (int s = 0; s < STATS_COUNT; s++) { double[] statMultipliers = cc.serverMultipliers?.statMultipliers?[s] ?? defaultMultipliers; sp.stats[s].BaseValue = sp.fullStatsRaw[s][0]; // don't apply the multiplier if AddWhenTamed is negative (e.g. Giganotosaurus, Griffin) sp.stats[s].AddWhenTamed = sp.fullStatsRaw[s][3] * (sp.fullStatsRaw[s][3] > 0 ? statMultipliers[0] : 1); // don't apply the multiplier if MultAffinity is negative (e.g. Aberration variants) sp.stats[s].MultAffinity = sp.fullStatsRaw[s][4] * (sp.fullStatsRaw[s][4] > 0 ? statMultipliers[1] : 1); sp.stats[s].IncPerTamedLevel = sp.fullStatsRaw[s][2] * statMultipliers[2]; sp.stats[s].IncPerWildLevel = sp.fullStatsRaw[s][1] * statMultipliers[3]; if (singlePlayerServerMultipliers?.statMultipliers?[s] == null) { continue; } // don't apply the multiplier if AddWhenTamed is negative (e.g. Giganotosaurus, Griffin) sp.stats[s].AddWhenTamed *= sp.stats[s].AddWhenTamed > 0 ? singlePlayerServerMultipliers.statMultipliers[s][0] : 1; // don't apply the multiplier if MultAffinity is negative (e.g. Aberration variants) sp.stats[s].MultAffinity *= sp.stats[s].MultAffinity > 0 ? singlePlayerServerMultipliers.statMultipliers[s][1] : 1; sp.stats[s].IncPerTamedLevel *= singlePlayerServerMultipliers.statMultipliers[s][2]; sp.stats[s].IncPerWildLevel *= singlePlayerServerMultipliers.statMultipliers[s][3]; } } // breeding multiplier if (sp.breeding == null) { continue; } if (currentServerMultipliers.EggHatchSpeedMultiplier > 0) { sp.breeding.gestationTimeAdjusted = sp.breeding.gestationTime / currentServerMultipliers.EggHatchSpeedMultiplier; sp.breeding.incubationTimeAdjusted = sp.breeding.incubationTime / currentServerMultipliers.EggHatchSpeedMultiplier; } if (currentServerMultipliers.BabyMatureSpeedMultiplier > 0) { sp.breeding.maturationTimeAdjusted = sp.breeding.maturationTime / currentServerMultipliers.BabyMatureSpeedMultiplier; } sp.breeding.matingCooldownMinAdjusted = sp.breeding.matingCooldownMin * currentServerMultipliers.MatingIntervalMultiplier; sp.breeding.matingCooldownMaxAdjusted = sp.breeding.matingCooldownMax * currentServerMultipliers.MatingIntervalMultiplier; } }
private void loadSettings(CreatureCollection cc) { for (int s = 0; s < statsCount; s++) { if (s < cc.multipliers.Length && cc.multipliers[s].Length > 3) { multSetter[s].Multipliers = cc.multipliers[s]; } else { multSetter[s].Multipliers = null; } } cbSingleplayerSettings.Checked = cc.singlePlayerSettings; nudEggHatchSpeed.ValueSave = (decimal)cc.EggHatchSpeedMultiplier; nudBabyMatureSpeed.ValueSave = (decimal)cc.BabyMatureSpeedMultiplier; numericUpDownDomLevelNr.ValueSave = cc.maxDomLevel; numericUpDownMaxBreedingSug.ValueSave = cc.maxBreedingSuggestions; numericUpDownMaxWildLevel.ValueSave = cc.maxWildLevel; nudMaxServerLevel.ValueSave = cc.maxServerLevel > 0 ? cc.maxServerLevel : 0; numericUpDownMaxChartLevel.ValueSave = cc.maxChartLevel; nudBabyImprintingStatScale.ValueSave = (decimal)cc.imprintingMultiplier; nudBabyCuddleInterval.ValueSave = (decimal)cc.babyCuddleIntervalMultiplier; nudTamingSpeed.ValueSave = (decimal)cc.tamingSpeedMultiplier; nudDinoCharacterFoodDrain.ValueSave = (decimal)cc.tamingFoodRateMultiplier; nudMatingInterval.ValueSave = (decimal)cc.MatingIntervalMultiplier; nudBabyFoodConsumptionSpeed.ValueSave = (decimal)cc.BabyFoodConsumptionSpeedMultiplier; // event-multiplier nudBabyCuddleIntervalEvent.ValueSave = (decimal)cc.babyCuddleIntervalMultiplierEvent; nudTamingSpeedEvent.ValueSave = (decimal)cc.tamingSpeedMultiplierEvent; nudDinoCharacterFoodDrainEvent.ValueSave = (decimal)cc.tamingFoodRateMultiplierEvent; nudMatingIntervalEvent.ValueSave = (decimal)cc.MatingIntervalMultiplierEvent; nudEggHatchSpeedEvent.ValueSave = (decimal)cc.EggHatchSpeedMultiplierEvent; nudBabyMatureSpeedEvent.ValueSave = (decimal)cc.BabyMatureSpeedMultiplierEvent; nudBabyFoodConsumptionSpeedEvent.ValueSave = (decimal)cc.BabyFoodConsumptionSpeedMultiplierEvent; checkBoxAutoSave.Checked = Properties.Settings.Default.autosave; numericUpDownAutosaveMinutes.ValueSave = Properties.Settings.Default.autosaveMinutes; nudWhiteThreshold.ValueSave = Properties.Settings.Default.OCRWhiteThreshold; chkbSpeechRecognition.Checked = Properties.Settings.Default.SpeechRecognition; nudOverlayInfoDuration.ValueSave = Properties.Settings.Default.OverlayInfoDuration; chkCollectionSync.Checked = Properties.Settings.Default.syncCollection; if (Properties.Settings.Default.celsius) { radioButtonCelsius.Checked = true; } else { radioButtonFahrenheit.Checked = true; } cbIgnoreSexInBreedingPlan.Checked = Properties.Settings.Default.IgnoreSexInBreedingPlan; checkBoxOxygenForAll.Checked = Properties.Settings.Default.oxygenForAll; nudWaitBeforeScreenCapture.ValueSave = Properties.Settings.Default.waitBeforeScreenCapture; cbShowOCRButton.Checked = Properties.Settings.Default.showOCRButton; string ocrApp = Properties.Settings.Default.OCRApp; int ocrI = cbOCRApp.Items.IndexOf(ocrApp); if (ocrI == -1) { textBoxOCRCustom.Text = ocrApp; cbOCRApp.SelectedIndex = cbOCRApp.Items.IndexOf("Custom"); } else { cbOCRApp.SelectedIndex = ocrI; } customSCStarving.SoundFile = Properties.Settings.Default.soundStarving; customSCWakeup.SoundFile = Properties.Settings.Default.soundWakeup; customSCBirth.SoundFile = Properties.Settings.Default.soundBirth; customSCCustom.SoundFile = Properties.Settings.Default.soundCustom; tbPlayAlarmsSeconds.Text = Properties.Settings.Default.playAlarmTimes; cbConsiderWildLevelSteps.Checked = cc.considerWildLevelSteps; nudWildLevelStep.ValueSave = cc.wildLevelStep; cbInventoryCheck.Checked = Properties.Settings.Default.inventoryCheckTimer; cbAllowMoreThanHundredImprinting.Checked = cc.allowMoreThanHundredImprinting; cbCreatureColorsLibrary.Checked = Properties.Settings.Default.showColorsInLibrary; cbApplyGlobalSpeciesToLibrary.Checked = Properties.Settings.Default.ApplyGlobalSpeciesToLibrary; // export paths if (Properties.Settings.Default.ExportCreatureFolders != null) { foreach (string path in Properties.Settings.Default.ExportCreatureFolders) { aTExportFolderLocationsBindingSource.Add(ATImportExportedFolderLocation.CreateFromString(path)); } } // savegame paths if (Properties.Settings.Default.arkSavegamePaths != null) { foreach (string path in Properties.Settings.Default.arkSavegamePaths) { aTImportFileLocationBindingSource.Add(ATImportFileLocation.CreateFromString(path)); } } fileSelectorExtractedSaveFolder.Link = Properties.Settings.Default.savegameExtractionPath; cbImportUpdateCreatureStatus.Checked = Properties.Settings.Default.importChangeCreatureStatus; textBoxImportTribeNameFilter.Text = Properties.Settings.Default.ImportTribeNameFilter; cbDevTools.Checked = Properties.Settings.Default.DevTools; string langKey = languages.FirstOrDefault(x => x.Value == Properties.Settings.Default.language).Key ?? ""; int langI = cbbLanguage.Items.IndexOf(langKey); cbbLanguage.SelectedIndex = langI == -1 ? 0 : langI; }
/// <summary> /// Creates an image with infos about the creature. /// </summary> /// <param name="creature"></param> /// <param name="cc">CreatureCollection for server settings.</param> /// <returns></returns> public static Bitmap InfoGraphic(this Creature creature, CreatureCollection cc) { if (creature == null) { return(null); } int maxGraphLevel = cc?.maxChartLevel ?? 0; if (maxGraphLevel < 1) { maxGraphLevel = 50; } const int width = 300; const int height = 180; var bmp = new Bitmap(width, height); using (var g = Graphics.FromImage(bmp)) using (var font = new Font("Arial", 10)) using (var fontSmall = new Font("Arial", 8)) using (var fontHeader = new Font("Arial", 12, FontStyle.Bold)) using (var fontBrush = new SolidBrush(Color.Black)) using (var penBlack = new Pen(Color.Black, 1)) using (var stringFormatRight = new StringFormat() { Alignment = StringAlignment.Far }) { g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias; int currentYPosition = 3; using (var backgroundBrush = new SolidBrush(Color.AntiqueWhite)) g.FillRectangle(backgroundBrush, 0, 0, width, height); g.DrawString(creature.Species.DescriptiveNameAndMod, fontHeader, fontBrush, 3, currentYPosition); currentYPosition += 19; g.DrawString($"Lvl {creature.LevelHatched} | {Utils.sexSymbol(creature.sex) + (creature.flags.HasFlag(CreatureFlags.Neutered) ? $" ({Loc.s(creature.sex == Sex.Female ? "Spayed" : "Neutered")})" : string.Empty)} | {creature.Mutations} mutations", font, fontBrush, 8, currentYPosition); currentYPosition += 17; using (var p = new Pen(Color.LightGray, 1)) g.DrawLine(p, 0, currentYPosition, width, currentYPosition); currentYPosition += 2; // levels const int xStatName = 8; int xLevelValue = xStatName + 30 + (creature.levelsWild[2].ToString().Length) * 7; int maxBoxLenght = xLevelValue - xStatName; g.DrawString("Levels", font, fontBrush, xStatName, currentYPosition); int statDisplayIndex = 0; for (int si = 0; si < Values.STATS_COUNT; si++) { int statIndex = Values.statsDisplayOrder[si]; if (statIndex == (int)StatNames.Torpidity || !creature.Species.UsesStat(statIndex)) { continue; } int y = currentYPosition + 20 + (statDisplayIndex++) * 15; // box double levelFractionOfMax = Math.Min(1, (double)creature.levelsWild[statIndex] / maxGraphLevel); if (levelFractionOfMax < 0) { levelFractionOfMax = 0; } int levelPercentageOfMax = (int)(100 * levelFractionOfMax); int statBoxLength = Math.Max((int)(maxBoxLenght * levelFractionOfMax), 1); const int statBoxHeight = 2; var statColor = Utils.getColorFromPercent(levelPercentageOfMax); using (var b = new SolidBrush(statColor)) g.FillRectangle(b, xStatName, y + 14, statBoxLength, statBoxHeight); using (var b = new SolidBrush(Color.FromArgb(10, statColor))) { for (int r = 4; r > 0; r--) { g.FillRectangle(b, xStatName - r, y + 13 - r, statBoxLength + 2 * r, statBoxHeight + 2 * r); } } using (var p = new Pen(Utils.getColorFromPercent(levelPercentageOfMax, -0.5), 1)) g.DrawRectangle(p, xStatName, y + 14, statBoxLength, statBoxHeight); // stat name g.DrawString($"{Utils.statName(statIndex, true, creature.Species.IsGlowSpecies)}", font, fontBrush, xStatName, y); // stat level number g.DrawString($"{creature.levelsWild[statIndex]}", font, fontBrush, xLevelValue, y, stringFormatRight); } // colors const int maxColorNameLength = 38; int xColor = xLevelValue + 20; g.DrawString("Colors", font, fontBrush, xColor, currentYPosition); int colorIndex = 0; for (int ci = 0; ci < Species.COLOR_REGION_COUNT; ci++) { if (!string.IsNullOrEmpty(creature.Species.colors[ci]?.name)) { const int circleDiameter = 16; const int rowHeight = circleDiameter + 2; int y = currentYPosition + 20 + (colorIndex++) * rowHeight; Color c = CreatureColors.creatureColor(creature.colors[ci]); Color fc = Utils.ForeColor(c); using (var b = new SolidBrush(c)) g.FillEllipse(b, xColor, y, circleDiameter, circleDiameter); g.DrawEllipse(penBlack, xColor, y, circleDiameter, circleDiameter); string colorRegionName = creature.Species.colors[ci].name; string colorName = CreatureColors.creatureColorName(creature.colors[ci]); int totalColorLenght = colorRegionName.Length + colorName.Length + 9; if (totalColorLenght > maxColorNameLength) { // shorten color region name int lengthForRegionName = colorRegionName.Length - (totalColorLenght - maxColorNameLength); colorRegionName = lengthForRegionName <= 0 ? string.Empty : lengthForRegionName < colorRegionName.Length ? colorRegionName.Substring(0, lengthForRegionName) : colorRegionName; } g.DrawString($"[{ci}] {colorRegionName}: [{creature.colors[ci]}] {colorName}", fontSmall, fontBrush, xColor + circleDiameter + 4, y); } } // max wild level on server if (cc != null) { g.DrawString($"max wild level: {cc.maxWildLevel}", fontSmall, fontBrush, width - 4, height - 14, stringFormatRight); } // frame using (var p = new Pen(Color.DarkRed, 1)) g.DrawRectangle(p, 0, 0, width - 1, height - 1); } return(bmp); }