public static bool UwuifyText(RandomizationOption option)
        {
            bool keepCasing   = option.HasSubOptionSelected(RTexts.SUBOPTIONKEY_UWU_KEEPCASING);
            bool addReactions = option.HasSubOptionSelected(RTexts.SUBOPTIONKEY_REACTIONS_ENABLED);

            var existingTLK = TLKHandler.GetBuildingTLK();
            var skipIDs     = existingTLK.StringRefs.Select(x => x.StringID).ToList();
            var MERTlks     = TLKHandler.GetMERTLKs();

            var nonMerTLKs = TLKHandler.GetAllTLKs().Where(x => !MERTlks.Contains(x));

            option.ProgressValue         = 0;
            option.ProgressMax           = nonMerTLKs.Where(x => x.name.EndsWith(@"INT.tlk")).Sum(x => x.StringRefs.Count(y => y.StringID > 0 && !string.IsNullOrWhiteSpace(y.Data)));
            option.ProgressMax          += MERTlks.Where(x => x.name.EndsWith(@"INT.tlk")).Sum(x => x.StringRefs.Count(y => y.StringID > 0 && !string.IsNullOrWhiteSpace(y.Data)));
            option.ProgressIndeterminate = false;


            // UwUify MER TLK first
            foreach (TalkFile tf in MERTlks)
            {
                UwuifyTalkFile(tf, keepCasing, addReactions, skipIDs, true, option);
            }

            // UwUify non MER TLK
            foreach (TalkFile tf in nonMerTLKs)
            {
                UwuifyTalkFile(tf, keepCasing, addReactions, skipIDs, false, option);
            }
            return(true);
        }
Example #2
0
        public static bool TurnOnFriendlyFire(RandomizationOption option)
        {
            var sfxgame = MEPackageHandler.OpenMEPackage(MERFileSystem.GetPackageFile("SFXGame.pcc"));
            var md      = sfxgame.GetUExport(21353);
            var patched = md.Data;

            for (int i = 0x0285; i < 0x0317; i++)
            {
                patched[i] = 0x0B; // nop
            }
            md.Data = patched;

            if (option.HasSubOptionSelected(SUBOPTIONKEY_CARELESSFF))
            {
                // Copy a 'return false' over the top of IsFriendlyBlockingSightline
                var fExport = sfxgame.GetUExport(5723);
                var fObjBin = ObjectBinary.From <UFunction>(fExport);

                var friendlyBlockingFunc = sfxgame.GetUExport(1203);
                var fbObjBin             = ObjectBinary.From <UFunction>(friendlyBlockingFunc);

                fbObjBin.ScriptBytecodeSize = fObjBin.ScriptBytecodeSize;
                fbObjBin.ScriptStorageSize  = fObjBin.ScriptStorageSize;
                fbObjBin.ScriptBytes        = fObjBin.ScriptBytes;
                friendlyBlockingFunc.WriteBinary(fbObjBin);
            }
            MERFileSystem.SavePackage(sfxgame);
            return(true);
        }
        public static bool RandomizeIconicMaleShep(RandomizationOption option)
        {
            var sfxgame = MERFileSystem.GetPackageFile("SFXGame.pcc");

            if (sfxgame != null && File.Exists(sfxgame))
            {
                var sfxgameP = MEPackageHandler.OpenMEPackage(sfxgame);
                var shepMDL  = sfxgameP.GetUExport(42539);
                var objBin   = RSkeletalMesh.FuzzSkeleton(shepMDL, option);

                if (option.HasSubOptionSelected(CharacterCreator.SUBOPTIONKEY_MALESHEP_COLORS))
                {
                    Dictionary <string, CFVector4> vectors = new();
                    Dictionary <string, float>     scalars = new();
                    var materials = objBin.Materials;
                    foreach (var mat in materials.Select(x => sfxgameP.GetUExport(x)))
                    {
                        RMaterialInstance.RandomizeSubMatInst(mat, vectors, scalars);
                    }
                }

                MERFileSystem.SavePackage(sfxgameP);
                return(true);
            }

            return(false);
        }
        /// <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);
        }
        public static bool RandomizeGalaxyMap(RandomizationOption option)
        {
            // Make the ship faster because otherwise it takes ages to do stuff
            // And can also consume more fuel

            var sfxgame = MERFileSystem.GetPackageFile("SFXGame.pcc");

            if (sfxgame != null && File.Exists(sfxgame))
            {
                var sfxgameP             = MEPackageHandler.OpenMEPackage(sfxgame);
                var galaxyModCamDefaults = sfxgameP.GetUExport(3899);
                var props = galaxyModCamDefaults.GetProperties();

                props.AddOrReplaceProp(new FloatProperty(150, "m_fMovementScalarGalaxy")); // is this used?
                props.AddOrReplaceProp(new FloatProperty(75, "m_fMovementScalarCluster"));
                props.AddOrReplaceProp(new FloatProperty(125, "m_fMovementScalarSystem"));

                galaxyModCamDefaults.WriteProperties(props);

                // Make it so you can't run out of a gas.
                if (option.HasSubOptionSelected(SUBOPTIONKEY_INFINITEGAS))
                {
                    var BurnFuel = sfxgameP.GetUExport(3877);
                    if (BurnFuel.ObjectName == "BurnFuel")
                    {
                        var bfData = BurnFuel.Data;
                        bfData.OverwriteRange(0x9C, BitConverter.GetBytes(50f)); // Make it so we don't run out of gas
                        BurnFuel.Data = bfData;
                    }
                }


                MERFileSystem.SavePackage(sfxgameP);
            }

            // Give a bit more starting gas
            // IDK why it's in Weapon
            // This doesn't seem to actually do anything. But i'll leave it here anyways
            var weaponini = CoalescedHandler.GetIniFile("BIOWeapon.ini");
            var sfxinvmgr = weaponini.GetOrAddSection("SFXGame.SFXInventoryManager");

            sfxinvmgr.SetSingleEntry("FuelEfficiency", 5);

            // Make faster deceleration cause its hard to stop right
            var biogameini = CoalescedHandler.GetIniFile("BIOGame.ini");
            var camgalaxy  = biogameini.GetOrAddSection("SFXGame.BioCameraBehaviorGalaxy");

            camgalaxy.SetSingleEntry("m_fShipSystemDeccel", 25);
            camgalaxy.SetSingleEntry("m_fShipClusterDeccel", .7f);

            var packageF = MERFileSystem.GetPackageFile(@"BioD_Nor_103aGalaxyMap.pcc");
            var package  = MEPackageHandler.OpenMEPackage(packageF);

            foreach (ExportEntry export in package.Exports)
            {
                switch (export.ClassName)
                {
                case "SFXCluster":
                {
                    var props     = export.GetProperties();
                    var starColor = props.GetProp <StructProperty>("StarColor");
                    if (starColor != null)
                    {
                        RStructs.RandomizeTint(starColor, false);
                    }
                    starColor = props.GetProp <StructProperty>("StarColor2");
                    if (starColor != null)
                    {
                        RStructs.RandomizeTint(starColor, false);
                    }

                    props.GetProp <IntProperty>("PosX").Value = ThreadSafeRandom.Next(800);
                    props.GetProp <IntProperty>("PosY").Value = ThreadSafeRandom.Next(800);


                    var intensity = props.GetProp <FloatProperty>("SphereIntensity");
                    if (intensity != null)
                    {
                        intensity.Value = ThreadSafeRandom.NextFloat(0, 6);
                    }
                    intensity = props.GetProp <FloatProperty>("NebularDensity");
                    if (intensity != null)
                    {
                        intensity.Value = ThreadSafeRandom.NextFloat(0, 6);
                    }
                    intensity = props.GetProp <FloatProperty>("SphereSize");
                    if (intensity != null)
                    {
                        intensity.Value = ThreadSafeRandom.NextFloat(0, 6);
                    }

                    export.WriteProperties(props);
                }
                    //RandomizeClustersXY(export);

                    break;

                case "SFXSystem":
                {
                    var props     = export.GetProperties();
                    var starColor = props.GetProp <StructProperty>("StarColor");
                    if (starColor != null)
                    {
                        RStructs.RandomizeTint(starColor, false);
                    }

                    starColor = props.GetProp <StructProperty>("FlareTint");
                    if (starColor != null)
                    {
                        RStructs.RandomizeTint(starColor, false);
                    }


                    starColor = props.GetProp <StructProperty>("SunColor");
                    if (starColor != null)
                    {
                        RStructs.RandomizeTint(starColor, false);
                    }

                    props.GetProp <IntProperty>("PosX").Value = ThreadSafeRandom.Next(1000);
                    props.GetProp <IntProperty>("PosY").Value = ThreadSafeRandom.Next(1000);


                    var scale = props.GetProp <FloatProperty>("Scale");
                    if (scale != null)
                    {
                        scale.Value = ThreadSafeRandom.NextFloat(.1, 2);
                    }


                    export.WriteProperties(props);
                }
                break;

                case "BioPlanet":
                {
                    var props     = export.GetProperties();
                    var starColor = props.GetProp <StructProperty>("SunColor");
                    if (starColor != null)
                    {
                        RStructs.RandomizeTint(starColor, false);
                    }

                    starColor = props.GetProp <StructProperty>("FlareTint");
                    if (starColor != null)
                    {
                        RStructs.RandomizeTint(starColor, false);
                    }


                    starColor = props.GetProp <StructProperty>("CloudColor");
                    if (starColor != null)
                    {
                        RStructs.RandomizeTint(starColor, false);
                    }

                    var resourceRichness = props.GetProp <FloatProperty>("ResourceRichness");
                    if (resourceRichness != null)
                    {
                        resourceRichness.Value = ThreadSafeRandom.NextFloat(0, 1.2);
                    }
                    else
                    {
                        props.AddOrReplaceProp(new FloatProperty(ThreadSafeRandom.NextFloat(0, .6), "ResourceRichness"));
                    }

                    props.GetProp <IntProperty>("PosX").Value = ThreadSafeRandom.Next(1000);
                    props.GetProp <IntProperty>("PosY").Value = ThreadSafeRandom.Next(1000);


                    var scale = props.GetProp <FloatProperty>("Scale");
                    if (scale != null)
                    {
                        scale.Value = ThreadSafeRandom.NextFloat(.1, 6);
                    }


                    export.WriteProperties(props);
                }
                break;

                case "MaterialInstanceConstant":
                    RMaterialInstance.RandomizeExport(export, null);
                    break;
                }
            }
            MERFileSystem.SavePackage(package);
            return(true);
        }
        public static bool RandomizeCharacterCreator(RandomizationOption option)
        {
            var biop_charF         = MERFileSystem.GetPackageFile(@"BioP_Char.pcc");
            var biop_char          = MEPackageHandler.OpenMEPackage(biop_charF);
            var maleFrontEndData   = biop_char.GetUExport(18753);
            var femaleFrontEndData = biop_char.GetUExport(18754);

            var codeMapMale   = CalculateCodeMap(maleFrontEndData);
            var codeMapFemale = CalculateCodeMap(femaleFrontEndData);

            var bioUI                  = CoalescedHandler.GetIniFile("BIOUI.ini");
            var bgr                    = CoalescedHandler.GetIniFile("BIOGuiResources.ini");
            var charCreatorPCS         = bgr.GetOrAddSection("SFXGame.BioSFHandler_PCNewCharacter");
            var charCreatorControllerS = bioUI.GetOrAddSection("SFXGame.BioSFHandler_NewCharacter");

            charCreatorPCS.Entries.Add(new DuplicatingIni.IniEntry("!MalePregeneratedHeadCodes", "CLEAR"));
            charCreatorControllerS.Entries.Add(new DuplicatingIni.IniEntry("!MalePregeneratedHeadCodes", "CLEAR"));

            int numToMake = 20;
            int i         = 0;

            // Male: 34 chars
            while (i < numToMake)
            {
                i++;
                charCreatorPCS.Entries.Add(GenerateHeadCode(codeMapMale, false));
                charCreatorControllerS.Entries.Add(GenerateHeadCode(codeMapMale, false));
            }



            // Female: 36 chars
            charCreatorPCS.Entries.Add(new DuplicatingIni.IniEntry(""));         //blank line
            charCreatorControllerS.Entries.Add(new DuplicatingIni.IniEntry("")); //blank line
            charCreatorPCS.Entries.Add(new DuplicatingIni.IniEntry("!FemalePregeneratedHeadCodes", "CLEAR"));
            charCreatorControllerS.Entries.Add(new DuplicatingIni.IniEntry("!FemalePregeneratedHeadCodes", "CLEAR"));
            charCreatorPCS.Entries.Add(new DuplicatingIni.IniEntry("!FemalePregeneratedHeadCodes", "CLEAR"));

            i = 0;
            while (i < numToMake)
            {
                i++;
                charCreatorPCS.Entries.Add(GenerateHeadCode(codeMapFemale, true));
                charCreatorControllerS.Entries.Add(GenerateHeadCode(codeMapFemale, true));
            }


            randomizeFrontEnd(maleFrontEndData);
            randomizeFrontEnd(femaleFrontEndData);


            //Copy the final skeleton from female into male.
            var femBase  = biop_char.GetUExport(3480);
            var maleBase = biop_char.GetUExport(3481);

            maleBase.WriteProperty(femBase.GetProperty <ArrayProperty <StructProperty> >("m_aFinalSkeleton"));

            var randomizeColors = !option.HasSubOptionSelected(CharacterCreator.SUBOPTIONKEY_CHARCREATOR_NO_COLORS);

            foreach (var export in biop_char.Exports)
            {
                if (export.ClassName == "BioMorphFace" && !export.ObjectName.Name.Contains("Iconic"))
                {
                    RBioMorphFace.RandomizeExportNonHench(export, SuperRandomOption); //.3 default
                }
                else if (export.ClassName == "MorphTarget")
                {
                    if (
                        export.ObjectName.Name.StartsWith("jaw") || export.ObjectName.Name.StartsWith("mouth") ||
                        export.ObjectName.Name.StartsWith("eye") ||
                        export.ObjectName.Name.StartsWith("cheek") ||
                        export.ObjectName.Name.StartsWith("nose") ||
                        export.ObjectName.Name.StartsWith("teeth")
                        )
                    {
                        RMorphTarget.RandomizeExport(export, option);
                    }
                }
                else if (export.ClassName == "BioMorphFaceFESliderColour" && randomizeColors)
                {
                    var colors = export.GetProperty <ArrayProperty <StructProperty> >("m_acColours");
                    foreach (var color in colors)
                    {
                        RStructs.RandomizeColor(color, true, .5, 1.5);
                    }
                    export.WriteProperty(colors);
                }
                else if (export.ClassName == "BioMorphFaceFESliderMorph")
                {
                    // These don't work becuase of the limits in the morph system
                    // So all this does is change how much the values change, not the max/min
                }
                else if (export.ClassName == "BioMorphFaceFESliderScalar" || export.ClassName == "BioMorphFaceFESliderSetMorph")
                {
                    //no idea how to randomize this lol
                    var floats   = export.GetProperty <ArrayProperty <FloatProperty> >("m_afValues");
                    var minfloat = floats.Min();
                    var maxfloat = floats.Max();
                    if (minfloat == maxfloat)
                    {
                        if (minfloat == 0)
                        {
                            maxfloat = 1;
                        }
                        else
                        {
                            var vari = minfloat / 2;
                            maxfloat = ThreadSafeRandom.NextFloat(-vari, vari) + minfloat; //+/- 50%
                        }
                    }
                    foreach (var floatval in floats)
                    {
                        floatval.Value = ThreadSafeRandom.NextFloat(minfloat, maxfloat);
                    }
                    export.WriteProperty(floats);
                }
                else if (export.ClassName == "BioMorphFaceFESliderTexture")
                {
                }
            }
            MERFileSystem.SavePackage(biop_char);
            return(true);
        }