private static void SetPreviewWeaponNames(FindLogic.Combo.ComboInfo info, Dictionary <ulong, ulong> weaponReplacements, STU_A0872511[] entities, int index) { if (entities == null) { return; } foreach (STU_A0872511 weaponEntity in entities) { FindLogic.Combo.Find(info, weaponEntity.m_entityDefinition, weaponReplacements); if (weaponEntity.m_loadout == 0) { continue; } Loadout loadout = Loadout.GetLoadout(weaponEntity.m_loadout); if (loadout == null) { continue; } info.SetEntityName(weaponEntity.m_entityDefinition, $"{loadout.Name}-{teResourceGUID.Index(weaponEntity.m_entityDefinition)}"); if ((weaponReplacements == null || index == 0) && info.m_entities.TryGetValue(weaponEntity.m_entityDefinition, out var entity) && info.m_models.TryGetValue(entity.m_modelGUID, out var model)) { foreach (var modellook in model.m_modelLooks) { info.SetModelLookName(modellook, $"{(STUWeaponType) index:G}-{teResourceGUID.Index(modellook):X}"); } } } }
private static void SavePreviewWeapons(FindLogic.Combo.ComboInfo info, Dictionary <ulong, ulong> weaponReplacements, STU_A0872511[] entities) { if (entities == null) { return; } foreach (STU_A0872511 weaponEntity in entities) { FindLogic.Combo.Find(info, weaponEntity.m_entityDefinition, weaponReplacements); if (weaponEntity.m_loadout == 0) { continue; } Loadout loadout = new Loadout(weaponEntity.m_loadout); info.SetEntityName(weaponEntity.m_entityDefinition, $"{loadout.Name}-{teResourceGUID.Index(weaponEntity.m_entityDefinition)}"); } }
public static void Save(ICLIFlags flags, string skinName, string basePath, STUHero hero, string rarity, STUSkinOverride skinOverride, List <ItemInfo> weaponSkins, List <STULoadout> abilities, bool quiet = true) { string heroName = GetString(hero.Name); string heroNamePath = GetValidFilename(heroName) ?? "Unknown"; heroNamePath = heroNamePath.TrimEnd(' '); string path = Path.Combine(basePath, $"{heroNamePath}\\Skins\\{rarity}\\{GetValidFilename(skinName)}"); Dictionary <uint, ItemInfo> realWeaponSkins = new Dictionary <uint, ItemInfo>(); if (weaponSkins != null) { foreach (ItemInfo weaponSkin in weaponSkins) { realWeaponSkins[((STUUnlock_Weapon)weaponSkin.Unlock).Index] = weaponSkin; } } Dictionary <ulong, ulong> replacements = skinOverride.ProperReplacements; LoudLog("\tFinding"); FindLogic.Combo.ComboInfo info = new FindLogic.Combo.ComboInfo(); FindLogic.Combo.Find(info, hero.EntityMain, replacements); FindLogic.Combo.Find(info, hero.EntityHeroSelect, replacements); FindLogic.Combo.Find(info, hero.EntityHighlightIntro, replacements); FindLogic.Combo.Find(info, hero.EntityPlayable, replacements); FindLogic.Combo.Find(info, hero.EntityThirdPerson, replacements); info.Config.DoExistingEntities = true; uint replacementIndex = 0; foreach (Common.STUGUID weaponOverrideGUID in skinOverride.Weapons) { STUHeroWeapon weaponOverride = GetInstance <STUHeroWeapon>(weaponOverrideGUID); if (weaponOverride == null) { continue; } string weaponSkinName = null; if (realWeaponSkins.ContainsKey(replacementIndex)) { weaponSkinName = GetValidFilename(GetString(realWeaponSkins[replacementIndex].Unlock.CosmeticName)); } Dictionary <ulong, ulong> weaponReplacements = weaponOverride.ProperReplacements?.ToDictionary(x => x.Key, y => y.Value) ?? new Dictionary <ulong, ulong>(); List <STUHeroWeaponEntity> weaponEntities = new List <STUHeroWeaponEntity>(); if (hero.WeaponComponents1 != null) { weaponEntities.AddRange(hero.WeaponComponents1); } if (hero.WeaponComponents2 != null) { weaponEntities.AddRange(hero.WeaponComponents2); } foreach (STUHeroWeaponEntity heroWeapon in weaponEntities) { FindLogic.Combo.Find(info, heroWeapon.Entity, weaponReplacements); STUModelComponent modelComponent = GetInstance <STUModelComponent>(heroWeapon.Entity); if (modelComponent?.Look == null || weaponSkinName == null) { continue; } ulong modelLook = FindLogic.Combo.GetReplacement(modelComponent.Look, weaponReplacements); if (!info.ModelLooks.ContainsKey(modelLook)) { continue; } FindLogic.Combo.ModelLookInfo modelLookInfo = info.ModelLooks[modelLook]; modelLookInfo.Name = weaponSkinName; } replacementIndex++; } info.Config.DoExistingEntities = false; foreach (Common.STUGUID guiImage in new[] { hero.ImageResource1, hero.ImageResource2, hero.ImageResource3, hero.ImageResource3, hero.ImageResource4, skinOverride.SkinImage, hero.SpectatorIcon }) { FindLogic.Combo.Find(info, guiImage, replacements); } Combo.SaveLooseTextures(flags, Path.Combine(path, "GUI"), info); info.SetEntityName(hero.EntityHeroSelect, $"{heroName}-HeroSelect"); info.SetEntityName(hero.EntityPlayable, $"{heroName}-Playable-ThirdPerson"); info.SetEntityName(hero.EntityThirdPerson, $"{heroName}-ThirdPerson"); info.SetEntityName(hero.EntityMain, $"{heroName}-Base"); info.SetEntityName(hero.EntityHighlightIntro, $"{heroName}-HighlightIntro"); string soundDirectory = Path.Combine(path, "Sound"); FindLogic.Combo.ComboInfo diffInfoBefore = new FindLogic.Combo.ComboInfo(); FindLogic.Combo.ComboInfo diffInfoAfter = new FindLogic.Combo.ComboInfo(); if (replacements != null) { foreach (KeyValuePair <ulong, ulong> replacement in replacements) { uint diffReplacementType = GUID.Type(replacement.Value); if (diffReplacementType != 0x2C && diffReplacementType != 0x5F && diffReplacementType != 0x3F && diffReplacementType != 0xB2) { continue; } FindLogic.Combo.Find(diffInfoAfter, replacement.Value); FindLogic.Combo.Find(diffInfoBefore, replacement.Key); } diffInfoAfter.SaveRuntimeData = new FindLogic.Combo.ComboSaveRuntimeData { Threads = false }; foreach (KeyValuePair <ulong, FindLogic.Combo.SoundFileInfo> soundFile in diffInfoAfter.SoundFiles) { if (diffInfoBefore.SoundFiles.ContainsKey(soundFile.Key)) { continue; } Combo.SaveSoundFile(flags, soundDirectory, diffInfoAfter, soundFile.Key, false); } foreach (KeyValuePair <ulong, FindLogic.Combo.SoundFileInfo> soundFile in diffInfoAfter.VoiceSoundFiles) { if (diffInfoBefore.VoiceSoundFiles.ContainsKey(soundFile.Key)) { continue; } Combo.SaveSoundFile(flags, soundDirectory, diffInfoAfter, soundFile.Key, true); } } LoudLog("\tSaving"); Combo.Save(flags, path, info); LoudLog("\tDone"); }
public static void Save(ICLIFlags flags, string directory, STUSkinBase skin, STUHero hero) { Dictionary <ulong, ulong> replacements = GetReplacements(skin); LoudLog("\t\tFinding"); FindLogic.Combo.ComboInfo info = new FindLogic.Combo.ComboInfo(); FindLogic.Combo.Find(info, hero.m_gameplayEntity, replacements); info.SetEntityName(hero.m_gameplayEntity, "Gameplay3P"); FindLogic.Combo.Find(info, hero.m_previewEmoteEntity, replacements); info.SetEntityName(hero.m_previewEmoteEntity, "PreviewEmote"); FindLogic.Combo.Find(info, hero.m_322C521A, replacements); info.SetEntityName(hero.m_322C521A, "Showcase"); FindLogic.Combo.Find(info, hero.m_26D71549, replacements); info.SetEntityName(hero.m_26D71549, "HeroGallery"); FindLogic.Combo.Find(info, hero.m_8125713E, replacements); info.SetEntityName(hero.m_8125713E, "HighlightIntro"); if (skin is STUSkinTheme skinTheme) { info.Config.DoExistingEntities = true; foreach (var weaponOverrideGUID in skinTheme.m_heroWeapons) { STUHeroWeapon heroWeapon = GetInstance <STUHeroWeapon>(weaponOverrideGUID); if (heroWeapon == null) { continue; } Dictionary <ulong, ulong> weaponReplacements = GetReplacements(heroWeapon); SavePreviewWeapons(info, weaponReplacements, hero.m_previewWeaponEntities); SavePreviewWeapons(info, weaponReplacements, hero.m_C2FE396F); } info.Config.DoExistingEntities = false; } foreach (STU_1A496D3C tex in hero.m_8203BFE1) { FindLogic.Combo.Find(info, tex.m_texture, replacements); info.SetTextureName(tex.m_texture, teResourceGUID.AsString(tex.m_id)); } Combo.SaveLooseTextures(flags, Path.Combine(directory, "GUI"), info); if (replacements != null) { string soundDirectory = Path.Combine(directory, "Sound"); FindLogic.Combo.ComboInfo diffInfoBefore = new FindLogic.Combo.ComboInfo(); FindLogic.Combo.ComboInfo diffInfoAfter = new FindLogic.Combo.ComboInfo(); foreach (KeyValuePair <ulong, ulong> replacement in replacements) { uint diffReplacementType = teResourceGUID.Type(replacement.Value); if (diffReplacementType != 0x2C && diffReplacementType != 0x3F && diffReplacementType != 0xB2) { continue; // no voice sets, use extract-hero-voice } FindLogic.Combo.Find(diffInfoAfter, replacement.Value); FindLogic.Combo.Find(diffInfoBefore, replacement.Key); } foreach (KeyValuePair <ulong, FindLogic.Combo.VoiceSetInfo> voiceSet in diffInfoAfter.VoiceSets) { if (diffInfoBefore.VoiceSets.ContainsKey(voiceSet.Key)) { continue; } Combo.SaveVoiceSet(flags, soundDirectory, diffInfoAfter, voiceSet.Key); } foreach (KeyValuePair <ulong, FindLogic.Combo.SoundFileInfo> soundFile in diffInfoAfter.SoundFiles) { if (diffInfoBefore.SoundFiles.ContainsKey(soundFile.Key)) { continue; } Combo.SaveSoundFile(flags, soundDirectory, diffInfoAfter, soundFile.Key, false); } foreach (KeyValuePair <ulong, FindLogic.Combo.SoundFileInfo> soundFile in diffInfoAfter.VoiceSoundFiles) { if (diffInfoBefore.VoiceSoundFiles.ContainsKey(soundFile.Key)) { continue; } Combo.SaveSoundFile(flags, soundDirectory, diffInfoAfter, soundFile.Key, true); } } LoudLog("\t\tSaving"); Combo.Save(flags, directory, info); LoudLog("\t\tDone"); }
public static void Save(ICLIFlags flags, string directory, STUSkinBase skin, STUHero hero) { Dictionary <ulong, ulong> replacements = GetReplacements(skin); LoudLog("\t\tFinding"); FindLogic.Combo.ComboInfo info = new FindLogic.Combo.ComboInfo(); var saveContext = new Combo.SaveContext(info); FindLogic.Combo.Find(info, hero.m_gameplayEntity, replacements); info.SetEntityName(hero.m_gameplayEntity, "Gameplay3P"); FindLogic.Combo.Find(info, hero.m_previewEmoteEntity, replacements); info.SetEntityName(hero.m_previewEmoteEntity, "PreviewEmote"); FindLogic.Combo.Find(info, hero.m_322C521A, replacements); info.SetEntityName(hero.m_322C521A, "Showcase"); FindLogic.Combo.Find(info, hero.m_26D71549, replacements); info.SetEntityName(hero.m_26D71549, "HeroGallery"); FindLogic.Combo.Find(info, hero.m_8125713E, replacements); info.SetEntityName(hero.m_8125713E, "HighlightIntro"); if (skin is STUSkinTheme skinTheme) { info.m_processExistingEntities = true; List <Dictionary <ulong, ulong> > weaponReplacementStack = new List <Dictionary <ulong, ulong> >(); for (var index = 0; index < skinTheme.m_heroWeapons.Length; index++) { var weaponOverrideGUID = skinTheme.m_heroWeapons[index]; STUHeroWeapon heroWeapon = GetInstance <STUHeroWeapon>(weaponOverrideGUID); if (heroWeapon == null) { continue; } Dictionary <ulong, ulong> weaponReplacements = GetReplacements(heroWeapon); SetPreviewWeaponNames(info, weaponReplacements, hero.m_previewWeaponEntities, index); SetPreviewWeaponNames(info, weaponReplacements, hero.m_C2FE396F, index); weaponReplacementStack.Add(weaponReplacements == null ? new Dictionary <ulong, ulong>() : weaponReplacements.Where(x => teResourceGUID.Type(x.Key) == 0x1A).ToDictionary(x => x.Key, x => x.Value)); } for (var index = 0; index < weaponReplacementStack.Count; index++) { foreach (var pair in weaponReplacementStack[index].Where(pair => pair.Key != pair.Value && info.m_modelLooks.ContainsKey(pair.Value) && info.m_modelLooks[pair.Value].m_name == null)) { info.SetModelLookName(pair.Value, $"{(STUWeaponType) index:G}-{teResourceGUID.Index(pair.Value):X}"); } } info.m_processExistingEntities = false; } foreach (STU_1A496D3C tex in hero.m_8203BFE1) // find GUI { FindLogic.Combo.Find(info, tex.m_texture, replacements); info.SetTextureName(tex.m_texture, teResourceGUID.AsString(tex.m_id)); } if (replacements != null) { string soundDirectory = Path.Combine(directory, "Sound"); FindLogic.Combo.ComboInfo diffInfoBefore = new FindLogic.Combo.ComboInfo(); FindLogic.Combo.ComboInfo diffInfoAfter = new FindLogic.Combo.ComboInfo(); var diffInfoAfterContext = new Combo.SaveContext(diffInfoAfter); // todo: remove foreach (KeyValuePair <ulong, ulong> replacement in replacements) { uint diffReplacementType = teResourceGUID.Type(replacement.Value); if (diffReplacementType != 0x2C && diffReplacementType != 0x3F && diffReplacementType != 0xB2) { continue; // no voice sets, use extract-hero-voice } FindLogic.Combo.Find(diffInfoAfter, replacement.Value); FindLogic.Combo.Find(diffInfoBefore, replacement.Key); } foreach (KeyValuePair <ulong, FindLogic.Combo.VoiceSetAsset> voiceSet in diffInfoAfter.m_voiceSets) { if (diffInfoBefore.m_voiceSets.ContainsKey(voiceSet.Key)) { continue; } Combo.SaveVoiceSet(flags, soundDirectory, diffInfoAfterContext, voiceSet.Key); } foreach (KeyValuePair <ulong, FindLogic.Combo.SoundFileAsset> soundFile in diffInfoAfter.m_soundFiles) { if (diffInfoBefore.m_soundFiles.ContainsKey(soundFile.Key)) { continue; } Combo.SaveSoundFile(flags, soundDirectory, diffInfoAfterContext, soundFile.Key, false); } foreach (KeyValuePair <ulong, FindLogic.Combo.SoundFileAsset> soundFile in diffInfoAfter.m_voiceSoundFiles) { if (diffInfoBefore.m_voiceSoundFiles.ContainsKey(soundFile.Key)) { continue; } Combo.SaveSoundFile(flags, soundDirectory, diffInfoAfterContext, soundFile.Key, true); } diffInfoAfterContext.Wait(); } LoudLog("\t\tSaving"); Combo.SaveLooseTextures(flags, Path.Combine(directory, "GUI"), saveContext); Combo.Save(flags, directory, saveContext); saveContext.Wait(); LoudLog("\t\tDone"); }