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); }
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); }