public static void LoadPowers()
        {
            if (Powers == null)
            {
                string fileContents = MERUtilities.GetEmbeddedStaticFilesTextFile("powerlistme2.json");
                Powers = new List <PowerInfo>();
                var powermanifest = JsonConvert.DeserializeObject <List <PowerInfo> >(fileContents);
                foreach (var powerInfo in powermanifest)
                {
                    var powerFilePath = MERFileSystem.GetPackageFile(powerInfo.PackageFileName, false);
                    if (powerInfo.IsCorrectedPackage || (powerFilePath != null && File.Exists(powerFilePath)))
                    {
                        if (powerInfo.FileDependency != null && MERFileSystem.GetPackageFile(powerInfo.FileDependency, false) == null)
                        {
                            MERLog.Information($@"Dependency file {powerInfo.FileDependency} not found, not adding {powerInfo.PowerName} to power selection pool");
                            continue; // Dependency not met
                        }
                        MERLog.Information($@"Adding {powerInfo.PowerName} to power selection pool");
                        Powers.Add(powerInfo);
                    }

                    if (!powerInfo.IsCorrectedPackage && powerFilePath == null)
                    {
                        MERLog.Information($@"{powerInfo.PowerName} package file not found ({powerInfo.PackageFileName}), weapon not added to weapon pools");
                    }
                }
            }
        }
Exemplo n.º 2
0
        public static bool PerformRandomization(ExportEntry export, RandomizationOption option)
        {
            if (!CanRandomize(export))
            {
                return(false);
            }
            MERLog.Information($"{export.FileRef.FilePath}\t{export.FullPath}");
            var props = export.GetProperties();

            if (export.ClassName == "BioSunFlareComponent" || export.ClassName == "BioSunFlareStreakComponent")
            {
                var tint = props.GetProp <StructProperty>("FlareTint");
                if (tint != null)
                {
                    RStructs.RandomizeTint(tint, false);
                }
                RProperty.RandFloat(props, "Intensity", 0.0001f, 100f, false);
                RProperty.RandFloat(props, "BrightPercent", 0.0001f, 0.1f, false);
                RProperty.RandFloat(props, "Scale", 0.05f, 3f, false);
            }
            else if (export.ClassName == "BioSunActor")
            {
                var tint = props.GetProp <StructProperty>("SunTint");
                if (tint != null)
                {
                    RStructs.RandomizeTint(tint, false);
                }
            }

            export.WriteProperties(props);
            return(true);
        }
 private static string ExtractInternalFile(string internalResourceName, bool fullname, string destination = null, bool overwrite = false, Stream destStream = null)
 {
     MERLog.Information("Extracting file: " + internalResourceName);
     if (destStream != null || (destination != null && (!File.Exists(destination) || overwrite)))
     {
         // Todo: might need adjusted for ME3
         using Stream stream = MERUtilities.GetResourceStream(fullname ? internalResourceName : "ME2Randomizer.staticfiles." + internalResourceName);
         bool close = destStream != null;
         if (destStream == null)
         {
             destStream = new FileStream(destination, FileMode.Create, FileAccess.Write);
         }
         stream.CopyTo(destStream);
         if (close)
         {
             stream.Close();
         }
     }
     else if (destination != null && !overwrite)
     {
         MERLog.Warning("File already exists");
     }
     else
     {
         MERLog.Warning("Invalid extraction parameters!");
     }
     return(destination);
 }
 public static int GetPartitionDiskBackingType(string partitionLetter)
 {
     using (var partitionSearcher = new ManagementObjectSearcher(
                @"\\localhost\ROOT\Microsoft\Windows\Storage",
                $"SELECT DiskNumber FROM MSFT_Partition WHERE DriveLetter='{partitionLetter}'"))
     {
         try
         {
             var partition = partitionSearcher.Get().Cast <ManagementBaseObject>().Single();
             using (var physicalDiskSearcher = new ManagementObjectSearcher(
                        @"\\localhost\ROOT\Microsoft\Windows\Storage",
                        $"SELECT Size, Model, MediaType FROM MSFT_PhysicalDisk WHERE DeviceID='{ partition["DiskNumber"] }'"))
             {
                 var physicalDisk = physicalDiskSearcher.Get().Cast <ManagementBaseObject>().Single();
                 return
                     ((UInt16)physicalDisk["MediaType"]);/*||
                                                          * SSDModelSubstrings.Any(substring => result.Model.ToLower().Contains(substring)); ;*/
             }
         }
         catch (Exception e)
         {
             MERLog.Error("Error reading partition type on " + partitionLetter + ": " + e.Message);
             return(-1);
         }
     }
 }
        public static bool RandomizeExport(ExportEntry export, RandomizationOption option)
        {
            if (!CanRandomize(export))
            {
                return(false);
            }
            var settings = export.GetProperty <StructProperty>("Settings");

            if (settings != null)
            {
                MERLog.Information($@"Randomizing PostProcessingVolume settings {export.UIndex}");
                // randomize the options
                RProperty.RandBool(settings.Properties, "bEnableDOF", ThreadSafeRandom.Next(3) == 0);
                RProperty.RandBool(settings.Properties, "bEnableFilmic", ThreadSafeRandom.Next(3) == 0);
                RProperty.RandBool(settings.Properties, "bEnableBloom", ThreadSafeRandom.Next(3) == 0);
                RProperty.RandFloat(settings.Properties, "Bloom_Scale", 0, 0.4f, ThreadSafeRandom.Next(5) == 0);
                RProperty.RandFloat(settings.Properties, "DOF_BlurKernelSize", 0, 20f, ThreadSafeRandom.Next(5) == 0);
                RProperty.RandFloat(settings.Properties, "DOF_MaxNearBlurAmount", 0, 0.2f, ThreadSafeRandom.Next(5) == 0);
                RProperty.RandFloat(settings.Properties, "DOF_MaxFarBlurAmount", 0.1f, 0.5f, ThreadSafeRandom.Next(5) == 0);
                RProperty.RandFloat(settings.Properties, "DOF_InnerFocusRadius", 0, 2000f, ThreadSafeRandom.Next(5) == 0);
                RProperty.RandFloat(settings.Properties, "DOF_FocusDistance", 0, 400f, ThreadSafeRandom.Next(5) == 0);
                RProperty.RandFloat(settings.Properties, "Scene_Desaturation", 0, 0.5f, ThreadSafeRandom.Next(5) == 0);
                RProperty.RandFloat(settings.Properties, "Scene_InterpolationDuration", 0, 2f, ThreadSafeRandom.Next(5) == 0);
                RProperty.RandVector(settings.Properties, "Scene_Highlights", 0, 2, ThreadSafeRandom.Next(8) == 0);
                RProperty.RandVector(settings.Properties, "Scene_Midtones", 0, 6f, ThreadSafeRandom.Next(5) == 0);
                RProperty.RandVector(settings.Properties, "Scene_Shadows", 0, .4f, ThreadSafeRandom.Next(8) == 0);
                export.WriteProperty(settings);
                return(true);
            }
            return(false);
        }
Exemplo n.º 6
0
        private static void handleM3Passthrough()
        {
            if (PassthroughME1Path != null)
            {
                handlePassthrough(MEGame.ME1, PassthroughME1Path);
            }
            if (PassthroughME2Path != null)
            {
                handlePassthrough(MEGame.ME2, PassthroughME2Path);
            }
            if (PassthroughME3Path != null)
            {
                handlePassthrough(MEGame.ME3, PassthroughME3Path);
            }

            PassthroughME1Path = PassthroughME2Path = PassthroughME3Path = null;

            void handlePassthrough(MEGame game, string path)
            {
                if (path != null && Directory.Exists(path))
                {
                    GameTarget gt = new GameTarget(game, path, true, false);
                    var        passThroughValidationResult = gt.ValidateTarget(false);
                    if (passThroughValidationResult != null)
                    {
                        MERLog.Error($@"{game} path passthrough failed game target validation: {passThroughValidationResult}");
                    }
                    else
                    {
                        MERLog.Information($@"Valid passthrough for game {game}. Assigning path.");
                        Locations.SetTarget(gt, false);
                    }
                }
            }
        }
        public static void LoadGuns()
        {
            if (AllAvailableWeapons == null)
            {
                string fileContents = MERUtilities.GetEmbeddedStaticFilesTextFile("weaponloadoutrules.json");
                LoadoutSupportsVisibleMapping = JsonConvert.DeserializeObject <ConcurrentDictionary <string, bool> >(fileContents);

                fileContents = MERUtilities.GetEmbeddedStaticFilesTextFile("weaponlistme2.json");
                var allGuns = JsonConvert.DeserializeObject <List <GunInfo> >(fileContents).ToList();
                AllAvailableWeapons     = new List <GunInfo>();
                VisibleAvailableWeapons = new List <GunInfo>();
                foreach (var g in allGuns)
                {
                    var gf = MERFileSystem.GetPackageFile(g.PackageFileName, false);
                    if (g.IsCorrectedPackage || (gf != null && File.Exists(gf)))
                    {
                        MERLog.Information($@"Adding {g.GunName} to weapon selection pools");
                        AllAvailableWeapons.Add(g);
                        if (g.HasGunMesh)
                        {
                            VisibleAvailableWeapons.Add(g);
                        }
                    }

                    if (!g.IsCorrectedPackage && gf == null)
                    {
                        MERLog.Information($@"{g.GunName} package file not found ({g.PackageFileName}), weapon not added to weapon pools");
                    }
                }
                Debug.WriteLine($"Number of available weapons for randomization: {AllAvailableWeapons.Count}");
                Debug.WriteLine($"Number of visible weapons for randomization: {VisibleAvailableWeapons.Count}");
            }
        }
Exemplo n.º 8
0
        public static bool RandomizeWeapons(RandomizationOption option)
        {
            var me2rbioweapon = CoalescedHandler.GetIniFile("BIOWeapon.ini");

            // We must manually fetch game files cause MERFS will return the ini from the dlc mod instead.
            ME2Coalesced me2basegamecoalesced = new ME2Coalesced(MERFileSystem.GetSpecificFile(@"BioGame\Config\PC\Cooked\Coalesced.ini"));

            MERLog.Information("Randomizing basegame weapon ini");
            var bioweapon = me2basegamecoalesced.Inis.FirstOrDefault(x => Path.GetFileName(x.Key) == "BIOWeapon.ini").Value;

            RandomizeWeaponIni(bioweapon, me2rbioweapon);

            var weaponInis = Directory.GetFiles(MEDirectories.GetDLCPath(MERFileSystem.Game), "BIOWeapon.ini", SearchOption.AllDirectories).ToList();

            foreach (var wi in weaponInis)
            {
                if (wi.Contains($"DLC_MOD_{MERFileSystem.Game}Randomizer"))
                {
                    continue; // Skip randomizer folders
                }
                MERLog.Information($@"Randomizing weapon ini {wi}");
                //Log.Information("Randomizing weapons in ini: " + wi);
                var dlcWeapIni = DuplicatingIni.LoadIni(wi);
                RandomizeWeaponIni(dlcWeapIni, me2rbioweapon);
                //if (!MERFileSystem.UsingDLCModFS)
                //{
                //    Log.Information("Writing DLC BioWeapon: " + wi);
                //    File.WriteAllText(wi, dlcWeapIni.ToString());
                //}
            }

            return(true);
        }
Exemplo n.º 9
0
        private static void MakeKensonCool()
        {
            string[] files = new[]
            {
                "BioD_ArvLvl1.pcc",
                "BioD_ArvLvl4_300Entrance.pcc",
            };
            foreach (var f in files)
            {
                var kensonFile = MERFileSystem.GetPackageFile(f, false);
                if (kensonFile != null && File.Exists(kensonFile))
                {
                    var kensonP = MEPackageHandler.OpenMEPackage(kensonFile);
                    var ifp     = kensonP.FindExport("SFXGameContentKenson.Default__SFXPawn_Kenson_01.BioPawnSkeletalMeshComponent");
                    ifp.RemoveProperty("Materials");
                    ifp.RemoveProperty("SkeletalMesh");

                    // Remove materials used in base as they're wrong
                    kensonP.FindExport("SFXGameContentKenson.Default__SFXPawn_Kenson.BioPawnSkeletalMeshComponent").RemoveProperty("Materials");

                    MERFileSystem.SavePackage(kensonP);
                }
                else
                {
                    MERLog.Information($"Kenson file not found: {f}, skipping...");
                }
            }
        }
Exemplo n.º 10
0
        private static void PerformRAMCheck(Action <string, string> messageCallback)
        {
            var ramAmountsBytes = Utilities.GetInstalledRamAmount();
            var installedRamGB  = ramAmountsBytes * 1.0d / (2 ^ 30);

            if (ramAmountsBytes > 0 && installedRamGB < 10)
            {
                messageCallback?.Invoke("System memory is less than 10 GB", "Randomization can use significant amounts of memory (up to 6GB) in multithreaded mode. It is recommended that you disable multithreaded randomization if your system has less than 10GB of memory. This will increase randomization time but will reduce the memory required to randomize.");
            }
#if WINDOWS
            //Check pagefile
            try
            {
                //Current
                var pageFileLocations = new List <string>();
                using (var query = new ManagementObjectSearcher("SELECT Caption,AllocatedBaseSize FROM Win32_PageFileUsage"))
                {
                    foreach (ManagementBaseObject obj in query.Get())
                    {
                        string pagefileName = (string)obj.GetPropertyValue("Caption");
                        MERLog.Information("Detected pagefile: " + pagefileName);
                        pageFileLocations.Add(pagefileName.ToLower());
                    }
                }

                //Max
                using (var query = new ManagementObjectSearcher("SELECT Name,MaximumSize FROM Win32_PageFileSetting"))
                {
                    foreach (ManagementBaseObject obj in query.Get())
                    {
                        string pagefileName = (string)obj.GetPropertyValue("Name");
                        uint   max          = (uint)obj.GetPropertyValue("MaximumSize");
                        if (max > 0)
                        {
                            // Not system managed
                            pageFileLocations.RemoveAll(x => Path.GetFullPath(x).Equals(Path.GetFullPath(pagefileName)));
                            MERLog.Error($"Pagefile has been modified by the end user. The maximum page file size on {pagefileName} is {max} MB. Does this user **actually** know what capping a pagefile does?");
                        }
                    }
                }

                if (pageFileLocations.Any())
                {
                    MERLog.Information("We have a usable system managed page file - OK");
                }
                else
                {
                    MERLog.Error("We have no uncapped or available pagefiles to use! Very high chance application will run out of memory");
                    messageCallback?.Invoke($"Pagefile is off or size has been capped", $"The system pagefile (virtual memory) settings are not currently managed by Windows, or the pagefile is off. Mass Effect 2 Randomizer uses significant amounts of memory and will crash if the system runs low on memory. You should always leave page files managed by Windows.");
                }
            }
            catch (Exception e)
            {
                MERLog.Exception(e, "Unable to check pagefile settings:");
            }
#endif
        }
Exemplo n.º 11
0
        private static void RandomizeVIMaterial(ExportEntry exp)
        {
            var data = exp.Data;

            //RandomizeRGBA(data, 0x70C, false);
            RandomizeRGBA(data, 0x72C, false);
            MERLog.Information($@"Randomized VI material {exp.InstancedFullPath} in {exp.FileRef.FilePath}");
            exp.Data = data;
        }
        /// <summary>
        /// Hack to force power lists to load with only a single check
        /// </summary>
        /// <param name="option"></param>
        /// <returns></returns>
        public static bool Init(RandomizationOption option)
        {
            MERLog.Information(@"Preloading weapon data");
            LoadGuns();
            WeaponAnimsPackage        = MERFileSystem.GetStartupPackage();
            WeaponAnimationsArrayProp = WeaponAnimsPackage.FindExport("WeaponAnimData").GetProperty <ArrayProperty <StructProperty> >("WeaponAnimSpecs");

            MERLog.Information(@"Installing weapon animations startup package");
            MERFileSystem.InstallStartupPackage(); // Contains weapon animations
            return(true);
        }
Exemplo n.º 13
0
        private static void PerformOperatingSystemCheck(Action <string, string> messageCallback)
        {
            // This check is only on Windows to ensure app runs on supported Windows operating systems
#if WINDOWS
            var os = Environment.OSVersion.Version;
            if (os < ALOTInstallerCoreLib.MIN_SUPPORTED_WINDOWS_OS)
            {
                MERLog.Fatal($@"This operating system version is below the minimum supported version: {os}, minimum supported: {ALOTInstallerCoreLib.MIN_SUPPORTED_WINDOWS_OS}");
                messageCallback?.Invoke("This operating system is not supported", $"Mass Effect 2 Randomizer is not supported on this operating system. The application may not work. To ensure application compatibility or receive support from ME3Tweaks, upgrade to a version of Windows that is supported by Microsoft.");
            }
#endif
        }
Exemplo n.º 14
0
        public static long GetInstalledRamAmount()
        {
            long memKb;

            GetPhysicallyInstalledSystemMemory(out memKb);
            if (memKb == 0L)
            {
                uint   errorcode    = GetLastError();
                string errorMessage = new Win32Exception(Marshal.GetLastWin32Error()).Message;
                MERLog.Warning("Failed to get RAM amount. This may indicate a potential (or soon coming) hardware problem. The error message was: " + errorMessage);
            }
            return(memKb);
        }
Exemplo n.º 15
0
        public static void GetAntivirusInfo()
        {
            ManagementObjectSearcher   wmiData = new ManagementObjectSearcher(@"root\SecurityCenter2", "SELECT * FROM AntivirusProduct");
            ManagementObjectCollection data    = wmiData.Get();

            foreach (ManagementObject virusChecker in data)
            {
                var  virusCheckerName = virusChecker["displayName"];
                var  productState     = virusChecker["productState"];
                uint productVal       = (uint)productState;
                var  bytes            = BitConverter.GetBytes(productVal);
                MERLog.Information("Antivirus info: " + virusCheckerName + " with state " + bytes[1].ToString("X2") + " " + bytes[2].ToString("X2") + " " + bytes[3].ToString("X2"));
            }
        }
Exemplo n.º 16
0
 public static void OpenWebPage(string link)
 {
     try
     {
         ProcessStartInfo psi = new ProcessStartInfo
         {
             FileName        = link,
             UseShellExecute = true
         };
         Process.Start(psi);
     }
     catch (Exception e)
     {
         MERLog.Error("Exception trying to open web page from system (typically means browser default is incorrectly configured by Windows): " + e.Message + ". Try opening the URL manually: " + link);
     }
 }
Exemplo n.º 17
0
        private static void SetVeetorFootage()
        {
            var moviedata   = RTextureMovie.GetTextureMovieAssetBinary("Veetor.size_mer.bik");
            var veetorFiles = MERFileSystem.LoadedFiles.Keys.Where(x => x.StartsWith("BioD_ProFre_501Veetor")).ToList();

            foreach (var v in veetorFiles)
            {
                MERLog.Information($@"Setting veetor footage in {v}");
                var mpackage     = MERFileSystem.GetPackageFile(v);
                var package      = MEPackageHandler.OpenMEPackage(mpackage);
                var veetorExport = package.FindExport("BioVFX_Env_Hologram.ProFre_501_VeetorFootage");
                if (veetorExport != null)
                {
                    RTextureMovie.RandomizeExportDirect(veetorExport, null, moviedata);
                }
                MERFileSystem.SavePackage(package);
            }
        }
Exemplo n.º 18
0
        private static void initAppCenter()
        {
#if !DEBUG
            if (APIKeys.HasAppCenterKey && !telemetryStarted)
            {
                Microsoft.AppCenter.Crashes.Crashes.GetErrorAttachments = (ErrorReport report) =>
                {
                    var attachments = new List <ErrorAttachmentLog>();
                    // Attach some text.
                    string errorMessage = "ALOT Installer has crashed! This is the exception that caused the crash:\n" + report.StackTrace;
                    MERLog.Fatal(errorMessage);
                    Log.Error("Note that this exception may appear to occur in a follow up boot due to how appcenter works");
                    string log = LogCollector.CollectLatestLog(false);
                    if (log.Length < 1024 * 1024 * 7)
                    {
                        attachments.Add(ErrorAttachmentLog.AttachmentWithText(log, "crashlog.txt"));
                    }
                    else
                    {
                        //Compress log
                        var compressedLog = LZMA.CompressToLZMAFile(Encoding.UTF8.GetBytes(log));
                        attachments.Add(ErrorAttachmentLog.AttachmentWithBinary(compressedLog, "crashlog.txt.lzma", "application/x-lzma"));
                    }

                    // Attach binary data.
                    //var fakeImage = System.Text.Encoding.Default.GetBytes("Fake image");
                    //ErrorAttachmentLog binaryLog = ErrorAttachmentLog.AttachmentWithBinary(fakeImage, "ic_launcher.jpeg", "image/jpeg");

                    return(attachments);
                };
                AppCenter.Start(APIKeys.AppCenterKey, typeof(Analytics), typeof(Crashes));
            }
#else
            if (!APIKeys.HasAppCenterKey)
            {
                Debug.WriteLine(" >>> This build is missing an API key for AppCenter!");
            }
            else
            {
                Debug.WriteLine("This build has an API key for AppCenter");
            }
#endif
            telemetryStarted = true;
        }
Exemplo n.º 19
0
        public static bool RandomizePawnSize(ExportEntry export, RandomizationOption option)
        {
            if (!CanRandomize(export))
            {
                return(false);
            }
            MERLog.Information($"[{Path.GetFileNameWithoutExtension(export.FileRef.FilePath)}] Randomizing pawn size for " + export.UIndex + ": " + export.InstancedFullPath);
            var       existingSize = export.GetProperty <StructProperty>("DrawScale3D");
            CFVector3 d3d          = existingSize == null ? new CFVector3()
            {
                X = 1, Y = 1, Z = 1
            } : CFVector3.FromStructProperty(existingSize, "X", "Y", "Z");

            d3d.X *= ThreadSafeRandom.NextFloat(1 - option.SliderValue, 1 + option.SliderValue);
            d3d.Y *= ThreadSafeRandom.NextFloat(1 - option.SliderValue, 1 + option.SliderValue);
            d3d.Z *= ThreadSafeRandom.NextFloat(1 - option.SliderValue, 1 + option.SliderValue);
            export.WriteProperty(d3d.ToStructProperty("X", "Y", "Z", "DrawScale3D", true));
            return(true);
        }
Exemplo n.º 20
0
        private static void PerformUACCheck()
        {
            bool isAdmin = Utilities.IsAdministrator();

            //Check if UAC is off
            bool   uacIsOn     = true;
            string softwareKey = @"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System";

            int?value = (int?)Registry.GetValue(softwareKey, "EnableLUA", null);

            if (value != null)
            {
                uacIsOn = value > 0;
                MERLog.Information("UAC is on: " + uacIsOn);
            }
            if (isAdmin && uacIsOn)
            {
                MERLog.Warning("This session is running as administrator.");
                //await this.ShowMessageAsync($"{Utilities.GetAppPrefixedName()} Installer should be run as standard user", $"Running {Utilities.GetAppPrefixedName()} Installer as an administrator will disable drag and drop functionality and may cause issues due to the program running in a different user context. You should restart the application without running it as an administrator unless directed by the developers.");
            }
        }
Exemplo n.º 21
0
        public static bool RandomizeExport(ExportEntry exp, RandomizationOption option)
        {
            if (!CanRandomize(exp))
            {
                return(false);
            }
            MERLog.Information($"Randomizing illusive eye color in {exp.FileRef.FilePath}");
            var props = exp.GetProperties();

            //eye color
            var emisVector = props.GetProp <ArrayProperty <StructProperty> >("VectorParameterValues").First(x => x.GetProp <NameProperty>("ParameterName").Value.Name == "Emis_Color").GetProp <StructProperty>("ParameterValue");

            //tint is float based
            RStructs.RandomizeTint(emisVector, false);

            var emisScalar = props.GetProp <ArrayProperty <StructProperty> >("ScalarParameterValues").First(x => x.GetProp <NameProperty>("ParameterName").Value.Name == "Emis_Scalar").GetProp <FloatProperty>("ParameterValue");

            emisScalar.Value = 3; //very vibrant
            exp.WriteProperties(props);
            return(true);
        }
        /// <summary>
        /// Allows loading a list of names for pawns
        /// </summary>
        public static void SetupRandomizer(RandomizationOption option)
        {
            OpenFileDialog ofd = new OpenFileDialog()
            {
                Title  = "Select text file with list of names, one per line",
                Filter = "Text files|*.txt",
            };
            var result = ofd.ShowDialog();

            if (result.HasValue && result.Value)
            {
                try
                {
                    PawnNames.ReplaceAll(File.ReadAllLines(ofd.FileName));
                    option.Description = $"{PawnNames.Count} name(s) loaded for randomization";
                }
                catch (Exception e)
                {
                    MERLog.Exception(e, "Error reading names for CharacterNames randomizer");
                }
            }
        }
Exemplo n.º 23
0
 public static int runProcessAsAdmin(string exe, string args, bool standAlone = false)
 {
     MERLog.Information("Running process as admin: " + exe + " " + args);
     using (Process p = new Process())
     {
         p.StartInfo.CreateNoWindow  = true;
         p.StartInfo.FileName        = exe;
         p.StartInfo.UseShellExecute = true;
         p.StartInfo.Arguments       = args;
         p.StartInfo.Verb            = "runas";
         try
         {
             p.Start();
             if (!standAlone)
             {
                 p.WaitForExit(60000);
                 try
                 {
                     return(p.ExitCode);
                 }
                 catch (Exception e)
                 {
                     MERLog.Error("Error getting return code from admin process. It may have timed out.\n" + FlattenException(e));
                     return(-1);
                 }
             }
             else
             {
                 return(0);
             }
         }
         catch (System.ComponentModel.Win32Exception e)
         {
             MERLog.Error("Error running elevated process: " + e.Message);
             return(WIN32_EXCEPTION_ELEVATED_CODE);
         }
     }
 }
        public bool RandomizeExport(ExportEntry export, RandomizationOption option)
        {
            if (!CanRandomize(export))
            {
                return(false);
            }
            MERLog.Information("Randomizing BioWaypointSet " + export.UIndex + " in " + Path.GetFileName(export.FileRef.FilePath));
            var waypointReferences = export.GetProperty <ArrayProperty <StructProperty> >("WaypointReferences");

            if (waypointReferences != null)
            {
                //Get list of valid targets
                var pcc       = export.FileRef;
                var waypoints = pcc.Exports.Where(x => x.ClassName == "BioPathPoint" || x.ClassName == "PathNode").ToList();
                waypoints.Shuffle();

                foreach (var waypoint in waypointReferences)
                {
                    var nav = waypoint.GetProp <ObjectProperty>("Nav");
                    if (nav != null && nav.Value > 0)
                    {
                        ExportEntry currentPoint = export.FileRef.GetUExport(nav.Value);
                        if (currentPoint.ClassName == "BioPathPoint" || currentPoint.ClassName == "PathNode")
                        {
                            nav.Value = waypoints[0].UIndex;
                            waypoints.RemoveAt(0);
                        }
                        else
                        {
                            Debug.WriteLine("SKIPPING NODE TYPE " + currentPoint.ClassName);
                        }
                    }
                }
            }

            export.WriteProperty(waypointReferences);
            return(true);
        }
Exemplo n.º 25
0
        public static bool RandomizeExport(ExportEntry export, RandomizationOption option)
        {
            if (!CanRandomize(export))
            {
                return(false);
            }
            MERLog.Information($"[{Path.GetFileNameWithoutExtension(export.FileRef.FilePath)}] Randomizing movement interpolations for " + export.UIndex + ": " + export.InstancedFullPath);
            var props    = export.GetProperties();
            var posTrack = props.GetProp <StructProperty>("PosTrack");

            if (posTrack != null)
            {
                var points = posTrack.GetProp <ArrayProperty <StructProperty> >("Points");
                if (points != null)
                {
                    foreach (StructProperty s in points)
                    {
                        var outVal = s.GetProp <StructProperty>("OutVal");
                        if (outVal != null)
                        {
                            FloatProperty x = outVal.GetProp <FloatProperty>("X");
                            FloatProperty y = outVal.GetProp <FloatProperty>("Y");
                            FloatProperty z = outVal.GetProp <FloatProperty>("Z");
                            x.Value = x.Value * ThreadSafeRandom.NextFloat(1 - option.SliderValue, 1 + option.SliderValue);
                            y.Value = y.Value * ThreadSafeRandom.NextFloat(1 - option.SliderValue, 1 + option.SliderValue);
                            z.Value = z.Value * ThreadSafeRandom.NextFloat(1 - option.SliderValue, 1 + option.SliderValue);
                        }
                    }
                }
            }

            var eulerTrack = props.GetProp <StructProperty>("EulerTrack");

            if (eulerTrack != null)
            {
                var points = eulerTrack.GetProp <ArrayProperty <StructProperty> >("Points");
                if (points != null)
                {
                    foreach (StructProperty s in points)
                    {
                        var outVal = s.GetProp <StructProperty>("OutVal");
                        if (outVal != null)
                        {
                            FloatProperty x = outVal.GetProp <FloatProperty>("X");
                            FloatProperty y = outVal.GetProp <FloatProperty>("Y");
                            FloatProperty z = outVal.GetProp <FloatProperty>("Z");
                            if (x.Value != 0)
                            {
                                x.Value = x.Value * ThreadSafeRandom.NextFloat(1 - option.SliderValue, 1 + option.SliderValue);
                            }
                            else
                            {
                                x.Value = ThreadSafeRandom.NextFloat(0, ThreadSafeRandom.NextFloat(-1000 * option.SliderValue, 1000 * option.SliderValue));
                            }

                            if (y.Value != 0)
                            {
                                y.Value = y.Value * ThreadSafeRandom.NextFloat(1 - option.SliderValue, 1 + option.SliderValue);
                            }
                            else
                            {
                                y.Value = ThreadSafeRandom.NextFloat(0, ThreadSafeRandom.NextFloat(-1000 * option.SliderValue, 1000 * option.SliderValue));
                            }

                            if (z.Value != 0)
                            {
                                z.Value = z.Value * ThreadSafeRandom.NextFloat(1 - option.SliderValue, 1 + option.SliderValue);
                            }
                            else
                            {
                                z.Value = ThreadSafeRandom.NextFloat(0, ThreadSafeRandom.NextFloat(-1000 * option.SliderValue, 1000 * option.SliderValue));
                            }
                        }
                    }
                }
            }

            export.WriteProperties(props);
            return(true);
        }
Exemplo n.º 26
0
        private static bool PerformWriteCheck(Action <string, string> messageCallback)
        {
#if WINDOWS
            MERLog.Information("Performing write check on all game directories...");
            var targets = Locations.GetAllAvailableTargets();
            try
            {
                List <string> directoriesToGrant = new List <string>();
                foreach (var t in targets)
                {
                    // Check all folders are writable
                    bool isFullyWritable = true;
                    var  testDirectories = Directory.GetDirectories(t.TargetPath, "*", SearchOption.AllDirectories);
                    foreach (var d in testDirectories)
                    {
                        isFullyWritable &= Utilities.IsDirectoryWritable(d);
                    }
                }

                bool isAdmin = Utilities.IsAdministrator();

                if (directoriesToGrant.Any())
                {
                    string args = "";
                    // Some directories not writable
                    foreach (var dir in directoriesToGrant)
                    {
                        if (args != "")
                        {
                            args += " ";
                        }

                        args += $"\"{dir}\"";
                    }

                    args = $"\"{System.Security.Principal.WindowsIdentity.GetCurrent().Name}\" {args}";

                    throw new Exception("not implemented.");

                    /*
                     * var permissionsGranterExe = Path.Combine(Locations.ResourcesDir, "Binaries", "PermissionsGranter.exe");
                     *
                     * //need to run write permissions program
                     * if (isAdmin)
                     * {
                     *  int result = Utilities.RunProcess(permissionsGranterExe, args, true, true, true, true);
                     *  if (result == 0)
                     *  {
                     *      MERLog.Information("Elevated process returned code 0, directories are hopefully writable now.");
                     *      return true;
                     *  }
                     *  else
                     *  {
                     *      MERLog.Error("Elevated process returned code " + result +
                     *                ", directories probably aren't writable.");
                     *      return false;
                     *  }
                     * }
                     * else
                     * {
                     *  string message = $"The Mass Effect 2 game folder is not writeable by your user account. Mass Effect 2 Randomizer will attempt to grant access to these folders/registry with the PermissionsGranter.exe program:\n";
                     *
                     *  foreach (string str in directoriesToGrant)
                     *  {
                     *      message += "\n" + str;
                     *  }
                     *
                     *  messageCallback?.Invoke("Write permissions required for modding", message);
                     *  int result = Utilities.RunProcess(permissionsGranterExe, args, true, true, true, true);
                     *  if (result == 0)
                     *  {
                     *      MERLog.Information("Elevated process returned code 0, directories are hopefully writable now.");
                     *      return true;
                     *  }
                     *  else
                     *  {
                     *      MERLog.Error($"Elevated process returned code {result}, directories probably aren't writable.");
                     *      return false;
                     *  }
                     * }
                     */
                }
            }
            catch (Exception e)
            {
                MERLog.Exception(e, "Error checking for write privileges. This may be a significant sign that an installed game is not in a good state.");
                return(false);
            }
#endif
            return(true);
        }
        internal static bool RandomizeExport(ExportEntry export, RandomizationOption option)
        {
            if (!CanRandomize(export))
            {
                return(false);
            }
#if DEBUG
            //if (!export.ObjectName.Name.Contains("HeavyWeaponMech"))
            //    return false;
#endif

            var powers = export.GetProperty <ArrayProperty <ObjectProperty> >("Powers");

            if (powers == null)
            {
                // This loadout has no powers!
                // Randomly give them some powers.
                if (ThreadSafeRandom.Next(1) == 0)
                {
                    // unlimited power
                    List <ObjectProperty> blankPows = new List <ObjectProperty>();
                    // Add two blanks. We'll strip blanks before writing it
                    blankPows.Add(new ObjectProperty(int.MinValue));
                    blankPows.Add(new ObjectProperty(int.MinValue));
                    powers = new ArrayProperty <ObjectProperty>(blankPows, "Powers");
                }
                else
                {
                    // Sorry mate no powers for you
                    return(false);
                }
            }

            var originalPowerUIndexes = powers.Where(x => x.Value > 0).Select(x => x.Value).ToList();

            foreach (var power in powers.ToList())
            {
                if (power.Value == 0)
                {
                    return(false);                  // Null entry in weapons list
                }
                IEntry existingPowerEntry = null;
                if (power.Value != int.MinValue)
                {
                    // Husk AI kinda depends on melee or they just kinda breath on you all creepy like
                    // We'll give them a chance to change it up though
                    existingPowerEntry = power.ResolveToEntry(export.FileRef);
                    if (existingPowerEntry.ObjectName.Name.Contains("Melee", StringComparison.InvariantCultureIgnoreCase) && ThreadSafeRandom.Next(2) == 0)
                    {
                        MERLog.Information($"Not changing melee power {existingPowerEntry.ObjectName.Name}");
                        continue; // Don't randomize power
                    }
                    if (PowersToNotSwap.Contains(existingPowerEntry.ObjectName.Name))
                    {
                        MERLog.Information($"Not changing power {existingPowerEntry.ObjectName.Name}");
                        continue; // Do not change this power
                    }
                }

                // DEBUG
                PowerInfo randomNewPower = Powers.RandomElement();
                //if (option.SliderValue < 0)
                //{
                //    randomNewPower = Powers.RandomElement();
                //}
                //else
                //{
                //    randomNewPower = Powers[(int)option.SliderValue];
                //}


                // Prevent krogan from getting a death power
                while (export.ObjectName.Name.Contains("Krogan", StringComparison.InvariantCultureIgnoreCase) && randomNewPower.Type == EPowerCapabilityType.Death)
                {
                    MERLog.Information(@"Re-roll no-death-power on krogan");
                    // Reroll. Krogan AI has something weird about it
                    randomNewPower = Powers.RandomElement();
                }

                // Prevent powerful enemies from getting super stat boosters
                while (randomNewPower.Type == EPowerCapabilityType.Buff && (
                           export.ObjectName.Name.Contains("Praetorian", StringComparison.InvariantCultureIgnoreCase) ||
                           export.ObjectName.Name.Contains("ShadowBroker", StringComparison.InvariantCultureIgnoreCase)))
                {
                    MERLog.Information(@"Re-roll no-buffs for powerful enemy");
                    randomNewPower = Powers.RandomElement();
                }

                #region YMIR MECH fixes
                if (export.ObjectName.Name.Contains("HeavyWeaponMech"))
                {
                    // Heavy weapon mech chooses named death powers so we cannot change these
                    // HeavyMechDeathExplosion is checked for existence. NormalExplosion for some reason isn't
                    if ((existingPowerEntry.ObjectName.Name == "SFXPower_HeavyMechNormalExplosion"))
                    {
                        MERLog.Information($@"YMIR mech power HeavyMechNormalExplosion cannot be randomized, skipping");
                        continue;
                    }

                    // Do not add buff powers to YMIR
                    while (randomNewPower.Type == EPowerCapabilityType.Buff)
                    {
                        MERLog.Information($@"Re-roll YMIR mech power to prevent potential enemy too difficult to kill softlock. Incompatible power: {randomNewPower.PowerName}");
                        randomNewPower = Powers.RandomElement();
                    }
                }
                #endregion

                // CHANGE THE POWER
                if (existingPowerEntry == null || randomNewPower.PowerName != existingPowerEntry.ObjectName)
                {
                    if (powers.Any(x => power.Value != int.MinValue && power.ResolveToEntry(export.FileRef).ObjectName == randomNewPower.PowerName))
                    {
                        continue; // Duplicate powers crash the game. It seems this code is not bulletproof here and needs changed a bit...
                    }
                    MERLog.Information($@"Changing power {export.ObjectName} {existingPowerEntry?.ObjectName ?? "(+New Power)"} => {randomNewPower.PowerName }");
                    // It's a different power.

                    // See if we need to port this in
                    var fullName = randomNewPower.PackageName + "." + randomNewPower.PowerName; // SFXGameContent_Powers.SFXPower_Hoops
                    var existingVersionOfPower = export.FileRef.FindEntry(fullName);

                    if (existingVersionOfPower != null)
                    {
                        // Power does not need ported in
                        power.Value = existingVersionOfPower.UIndex;
                    }
                    else
                    {
                        // Power needs ported in
                        power.Value = PortPowerIntoPackage(export.FileRef, randomNewPower, out _)?.UIndex ?? int.MinValue;
                    }

                    if (existingPowerEntry != null && existingPowerEntry.UIndex > 0 && PackageTools.IsPersistentPackage(export.FileRef.FilePath))
                    {
                        // Make sure we add the original power to the list of referenced memory objects
                        // so subfiles that depend on this power existing don't crash the game!
                        var world     = export.FileRef.FindExport("TheWorld");
                        var worldBin  = ObjectBinary.From <World>(world);
                        var extraRefs = worldBin.ExtraReferencedObjects.ToList();
                        extraRefs.Add(new UIndex(existingPowerEntry.UIndex));
                        worldBin.ExtraReferencedObjects = extraRefs.Distinct().ToArray(); // Filter out duplicates that may have already been in package
                        world.WriteBinary(worldBin);
                    }

                    foreach (var addlPow in randomNewPower.AdditionalRequiredPowers)
                    {
                        var existingPow = export.FileRef.FindEntry(addlPow);
                        //if (existingPow == null && randomNewPower.ImportOnly && sourcePackage != null)
                        //{
                        //    existingPow = PackageTools.CreateImportForClass(sourcePackage.FindExport(randomNewPower.PackageName + "." + randomNewPower.PowerName), export.FileRef);
                        //}

                        if (existingPow == null)
                        {
                            Debugger.Break();
                        }
                        powers.Add(new ObjectProperty(existingPow));
                    }
                }
            }

            // Strip any blank powers we might have added, remove any duplicates
            powers.RemoveAll(x => x.Value == int.MinValue);
            powers.ReplaceAll(powers.ToList().Distinct()); //tolist prevents concurrent modification in nested linq

            // DEBUG
#if DEBUG
            var duplicates = powers
                             .GroupBy(i => i.Value)
                             .Where(g => g.Count() > 1)
                             .Select(g => g.Key).ToList();
            if (duplicates.Any())
            {
                foreach (var dup in duplicates)
                {
                    Debug.WriteLine($"DUPLICATE POWER IN LOADOUT {export.FileRef.GetEntry(dup).ObjectName}");
                }
                Debugger.Break();
            }
#endif
            export.WriteProperty(powers);

            // Our precalculated map should have accounted for imports already, so we odn't need to worry about missing imports upstream
            // If this is not a master or localization file (which are often used for imports)
            // Change the number around so it will work across packages.
            // May need disabled if game becomes unstable.

            // We check if less than 10 as it's very unlikely there will be more than 10 loadouts in a non-persistent package
            // if it's > 10 it's likely already a memory-changed item by MER
            var pName = Path.GetFileName(export.FileRef.FilePath);
            if (export.indexValue < 10 && !PackageTools.IsPersistentPackage(pName) && !PackageTools.IsLocalizationPackage(pName))
            {
                export.ObjectName = new NameReference(export.ObjectName, ThreadSafeRandom.Next(2000));
            }

            if (originalPowerUIndexes.Any())
            {
                // We should ensure the original objects are still referenced so shared objects they have (vfx?) are kept in memory
                // Dunno if this actually fixes the problems...
                PackageTools.AddReferencesToWorld(export.FileRef, originalPowerUIndexes.Select(x => export.FileRef.GetUExport(x)));
            }

            return(true);
        }
 /// <summary>
 /// Hack to force power lists to load with only a single check
 /// </summary>
 /// <param name="option"></param>
 /// <returns></returns>
 public static bool Init(RandomizationOption option)
 {
     MERLog.Information(@"Preloading power data");
     LoadPowers();
     return(true);
 }
Exemplo n.º 29
0
        public static async void BeginFlow(MainWindow window)
        {
            // PRE LIBRARY LOAD
            RegistryHandler.RegistrySettingsPath       = @"HKEY_CURRENT_USER\Software\MassEffect2Randomizer";
            RegistryHandler.CurrentUserRegistrySubpath = @"Software\MassEffect2Randomizer";
            LegendaryExplorerCoreLib.SetSynchronizationContext(TaskScheduler.FromCurrentSynchronizationContext());

            try
            {
                // This is in a try catch because this is a critical no-crash zone that is before launch
                window.Title = $"Mass Effect 2 Randomizer {App.AppVersion}";
            }
            catch { }

            if (Utilities.GetExecutablePath().StartsWith(Path.GetTempPath(), StringComparison.InvariantCultureIgnoreCase))
            {
                // Running from temp! This is not allowed
                await window.ShowMessageAsync("Cannot run from temp directory", $"Mass Effect 2 Randomizer cannot be run from the system's Temp directory. If this executable was run from within an archive, it needs to be extracted first.");

                Environment.Exit(1);
            }

            var pd = await window.ShowProgressAsync("Starting up", $"Mass Effect 2 Randomizer is starting up. Please wait.");

            pd.SetIndeterminate();
            NamedBackgroundWorker bw = new NamedBackgroundWorker("StartupThread");

            bw.DoWork += (a, b) =>
            {
                ALOTInstallerCoreLib.Startup(SetWrapperLogger, RunOnUIThread, startTelemetry, stopTelemetry, $"Mass Effect 2 Randomizer {App.AppVersion} starting up", false);
                // Logger is now available

                // Setup telemetry handlers
                CoreAnalytics.TrackEvent = TelemetryController.TrackEvent;
                CoreCrashes.TrackError   = TelemetryController.TrackError;
                CoreCrashes.TrackError2  = TelemetryController.TrackError2;
                CoreCrashes.TrackError3  = TelemetryController.TrackError3;

                // Setup the InteropPackage for the update check
                #region Update interop
                CancellationTokenSource ct = new CancellationTokenSource();

                AppUpdateInteropPackage interopPackage = new AppUpdateInteropPackage()
                {
                    GithubOwner              = "Mgamerz",
                    GithubReponame           = "MassEffect2Randomizer",
                    UpdateAssetPrefix        = "ME2Randomizer",
                    UpdateFilenameInArchive  = "ME2Randomizer.exe",
                    ShowUpdatePromptCallback = (title, text, updateButtonText, declineButtonText) =>
                    {
                        bool   response = false;
                        object syncObj  = new object();
                        Application.Current.Dispatcher.Invoke(async() =>
                        {
                            if (Application.Current.MainWindow is MainWindow mw)
                            {
                                var result = await mw.ShowMessageAsync(title, text, MessageDialogStyle.AffirmativeAndNegative, new MetroDialogSettings()
                                {
                                    AffirmativeButtonText = updateButtonText,
                                    NegativeButtonText    = declineButtonText,
                                    DefaultButtonFocus    = MessageDialogResult.Affirmative
                                },
                                                                       75);
                                response = result == MessageDialogResult.Affirmative;
                                lock (syncObj)
                                {
                                    Monitor.Pulse(syncObj);
                                }
                            }
                        });
                        lock (syncObj)
                        {
                            Monitor.Wait(syncObj);
                        }
                        return(response);
                    },
                    ShowUpdateProgressDialogCallback = (title, initialmessage, canCancel) =>
                    {
                        // We don't use this as we are already in a progress dialog
                        pd.SetCancelable(canCancel);
                        pd.SetMessage(initialmessage);
                        pd.SetTitle(title);
                    },
                    SetUpdateDialogTextCallback = s =>
                    {
                        pd.SetMessage(s);
                    },
                    ProgressCallback = (done, total) =>
                    {
                        pd.SetProgress(done * 1d / total);
                        pd.SetMessage($"Downloading update {FileSize.FormatSize(done)} / {FileSize.FormatSize(total)}");
                    },
                    ProgressIndeterminateCallback = () =>
                    {
                        pd.SetIndeterminate();
                    },
                    ShowMessageCallback = (title, message) =>
                    {
                        object syncObj = new object();
                        Application.Current.Dispatcher.Invoke(async() =>
                        {
                            if (Application.Current.MainWindow is MainWindow mw)
                            {
                                await mw.ShowMessageAsync(title, message);
                                lock (syncObj)
                                {
                                    Monitor.Pulse(syncObj);
                                }
                            }
                        });
                        lock (syncObj)
                        {
                            Monitor.Wait(syncObj);
                        }
                    },
                    NotifyBetaAvailable = () =>
                    {
                        App.BetaAvailable = true;
                    },
                    DownloadCompleted = () =>
                    {
                        pd.SetCancelable(false);
                    },
                    cancellationTokenSource    = ct,
                    ApplicationName            = "Mass Effect 2 Randomizer",
                    RequestHeader              = "ME2Randomizer",
                    ForcedUpgradeMaxReleaseAge = 3
                };

                #endregion



                pd.SetMessage("Checking for application updates");
                pd.Canceled += (sender, args) =>
                {
                    ct.Cancel();
                };
                AppUpdater.PerformGithubAppUpdateCheck(interopPackage);

                // If user aborts download
                pd.SetCancelable(false);
                pd.SetIndeterminate();
                pd.SetTitle("Starting up");

                void setStatus(string message)
                {
                    pd.SetIndeterminate();
                    pd.SetMessage(message);
                }

                GameTarget target = null;
                try
                {
                    pd.SetMessage("Loading Mass Effect 2 Randomizer framework");
                    ToolTipService.ShowOnDisabledProperty.OverrideMetadata(typeof(Control), new FrameworkPropertyMetadata(true));
                    ToolTipService.ShowDurationProperty.OverrideMetadata(typeof(DependencyObject), new FrameworkPropertyMetadata(int.MaxValue));

                    ALOTInstallerCoreLib.PostCriticalStartup(x => pd.SetMessage(x), RunOnUIThread, false);

#if __LE2__
                    LE2Directory.ReloadDefaultGamePath(true);
                    if (LE2Directory.DefaultGamePath != null)
                    {
                        GameTarget gt = new GameTarget(MEGame.LE2, LE2Directory.DefaultGamePath, true);
                        if (gt.ValidateTarget() == null)
                        {
                            Locations.SetTarget(gt, false);
                        }
                    }
#endif
                    MEPackageHandler.GlobalSharedCacheEnabled = false; // ME2R does not use the global shared cache.

                    handleM3Passthrough();
                    target = Locations.GetTarget(MERFileSystem.Game);
                    if (target == null)
                    {
                        var gamePath = MEDirectories.GetDefaultGamePath(MERFileSystem.Game);
                        if (Directory.Exists(gamePath))
                        {
                            target = new GameTarget(MERFileSystem.Game, gamePath, true);
                            var validationFailedReason = target.ValidateTarget();
                            if (validationFailedReason == null)
                            {
                                // CHECK NOT TEXTURE MODIFIED
                                if (target.TextureModded)
                                {
                                    MERLog.Error($@"Game target is texture modded: {target.TargetPath}. This game target is not targetable by ME2R");
                                    object o = new object();
                                    Application.Current.Dispatcher.Invoke(async() =>
                                    {
                                        if (Application.Current.MainWindow is MainWindow mw)
                                        {
                                            await mw.ShowMessageAsync("Mass Effect 2 target is texture modded", $"The game located at {target.TargetPath} has had textures modified. Mass Effect 2 Randomizer cannot randomize texture modified games, as it adds package files. If you want to texture mod your game, it must be done after randomization.", ContentWidthPercent: 75);
                                            lock (o)
                                            {
                                                Monitor.Pulse(o);
                                            }
                                        }
                                    });
                                    lock (o)
                                    {
                                        Monitor.Wait(o);
                                    }
                                }

                                // We still set target so we can restore game if necessary
                                Locations.SetTarget(target, false);
                            }
                        }
                    }


                    pd.SetMessage("Performing startup checks");
                    MERStartupCheck.PerformStartupCheck((title, message) =>
                    {
                        object o = new object();
                        Application.Current.Dispatcher.Invoke(async() =>
                        {
                            if (Application.Current.MainWindow is MainWindow mw)
                            {
                                await mw.ShowMessageAsync(title, message, ContentWidthPercent: 75);
                                lock (o)
                                {
                                    Monitor.Pulse(o);
                                }
                            }
                        });
                        lock (o)
                        {
                            Monitor.Wait(o);
                        }
                    }, x => pd.SetMessage(x));

                    // force initial refresh
                    MERPeriodicRefresh(null, null);
                }
                catch (Exception e)
                {
                    MERLog.Exception(e, @"There was an error starting up the framework!");
                }

                pd.SetMessage("Preparing interface");
                Thread.Sleep(250); // This will allow this message to show up for moment so user can see it.

                Application.Current.Dispatcher.Invoke(async() =>
                {
                    if (Application.Current.MainWindow is MainWindow mw)
                    {
                        mw.SetupTargetDescriptionText();


                        var backupStatus                = BackupService.GetBackupStatus(MERFileSystem.Game);
                        mw.BackupRestoreText            = backupStatus?.BackupActionText;
                        mw.BackupRestore_Button.ToolTip = backupStatus != null && backupStatus.BackedUp ? "Click to restore game/uninstall randomizer mod" : "Click to backup game";

                        mw.FinalizeInterfaceLoad();

                        /*
                         * if (!hasWorkingMEM)
                         * {
                         *  await mw.ShowMessageAsync("Required components are not available",
                         *      "Some components for installation are not available, likely due to network issues (blocking, no internet, etc). To install these components, folow the 'How to install the Installer Support Package' directions on any of the ALOT pages on NexusMods. The installer will not work without these files installed.",
                         *      ContentWidthPercent: 75);
                         * }*/

                        PeriodicRefresh.OnPeriodicRefresh += MERPeriodicRefresh;
                    }
                });
            };
            bw.RunWorkerCompleted += async(a, b) =>
            {
                // Post critical startup
                Random random  = new Random();
                var    preseed = random.Next();
                window.ImageCredits.ReplaceAll(ImageCredit.LoadImageCredits("imagecredits.txt", false));
                window.ContributorCredits.ReplaceAll(window.GetContributorCredits());
                window.LibraryCredits.ReplaceAll(LibraryCredit.LoadLibraryCredits("librarycredits.txt"));
#if DEBUG
                window.SeedTextBox.Text = 529572808.ToString();
#else
                window.SeedTextBox.Text = preseed.ToString();
#endif
                window.TextBlock_AssemblyVersion.Text = $"Version {App.AppVersion}";
                window.SelectedRandomizeMode          = MainWindow.RandomizationMode.ERandomizationMode_SelectAny;


                var hasFirstRun = RegistryHandler.GetRegistrySettingBool(MainWindow.SETTING_FIRSTRUN);
                if (hasFirstRun == null || !hasFirstRun.Value)
                {
                    window.FirstRunFlyoutOpen = true;
                }
                await pd.CloseAsync();
            };
            bw.RunWorkerAsync();
        }
Exemplo n.º 30
0
        /// <summary>
        /// Swap the vowels around. Optional hard mode allows swapping 2 consonants to make it extra difficult to read
        /// </summary>
        /// <param name="Tlks"></param>
        public static bool RandomizeVowels(RandomizationOption option)
        {
            // Map of what letter maps to what other letter
            MERLog.Information("Randomizing vowels in words");
            var hardMode = option.HasSubOptionSelected(RTexts.SUBOPTIONKEY_VOWELS_HARDMODE);


            var existingTLK = TLKHandler.GetBuildingTLK();
            var skipIDs     = existingTLK.StringRefs.Select(x => x.StringID).ToList();
            var MERTLKs     = TLKHandler.GetMERTLKs();
            Dictionary <char, char> vowels      = null;
            List <char>             vowelValues = null;

            bool retryMapping = true;

            while (retryMapping)
            {
                bool failed = false;
                vowels      = GetVowelMap();
                vowelValues = vowels.Values.ToList();

                int numAttemptsRemaining = 10;

                foreach (var sourceVowel in vowels.Keys)
                {
                    var value = vowelValues.RandomElement();
                    while (hardMode && value == sourceVowel && numAttemptsRemaining > 0)
                    {
                        value = vowelValues.RandomElement();
                        numAttemptsRemaining--;
                    }

                    if (numAttemptsRemaining == 0 && hardMode && value == sourceVowel)
                    {
                        // This attempt has failed
                        MERLog.Warning(@"Hard mode vowel randomization failed, retrying");
                        failed = true;
                        break;
                    }

                    vowelValues.Remove(value); // Do not allow reassignment of same vowel
                    Debug.WriteLine($"Vowel Randomizer: {sourceVowel} -> {value}");
                    vowels[sourceVowel] = value;
                }

                if (!failed)
                {
                    retryMapping = false;
                }
            }

            var consonants = GetConsonantMap();

            if (hardMode)
            {
                // Swap some consontants around
                var numConsonantsToRandomize = 2;
                var consonantValues          = consonants.Values.ToList();
                while (numConsonantsToRandomize > 0)
                {
                    var sourceValue = consonantValues.RandomElement();
                    var value       = consonantValues.RandomElement();
                    while (sourceValue == value)
                    {
                        value = consonantValues.RandomElement();
                    }
                    consonantValues.Remove(value);       // Do not allow reassignment of same vowel
                    consonantValues.Remove(sourceValue); // Do not allow reassignment of same vowel

                    Debug.WriteLine($"Vowel Randomizer Hard Mode: {sourceValue} -> {value}");

                    consonants[sourceValue] = value;
                    consonants[value]       = sourceValue;
                    numConsonantsToRandomize--;
                }
            }

            // Build full translation map (uppercase)
            var translationMapUC = new[] { vowels, consonants }.SelectMany(dict => dict)
            .ToDictionary(pair => pair.Key, pair => pair.Value);

            // Add lowercase translation
            var lowerCaseMap = translationMapUC.ToDictionary(x => char.ToLowerInvariant(x.Key), x => char.ToLowerInvariant(x.Value));

            // Build a full translation
            var translationMap = new[] { translationMapUC, lowerCaseMap }.SelectMany(dict => dict)
            .ToDictionary(pair => pair.Key, pair => pair.Value);

            var nonMERTLKs = TLKHandler.GetAllTLKs().Where(x => !MERTLKs.Contains(x)).ToList();

            // MER

            option.ProgressValue         = 0;
            option.ProgressMax           = nonMERTLKs.Sum(x => x.StringRefs.Count(y => y.StringID > 0 && !string.IsNullOrWhiteSpace(y.Data)));
            option.ProgressMax          += MERTLKs.Sum(x => x.StringRefs.Count(y => y.StringID > 0 && !string.IsNullOrWhiteSpace(y.Data)));
            option.ProgressIndeterminate = false;

            foreach (var merTLK in MERTLKs)
            {
                RandomizeVowelsInternal(merTLK, skipIDs, translationMap, true, option);
            }

            // Non MER
            Parallel.ForEach(nonMERTLKs, tf =>
            {
                RandomizeVowelsInternal(tf, skipIDs, translationMap, false, option);
            });
            return(true);
        }