From 0a7f27ad8d3e9616878384ed03da2156ebbed608 Mon Sep 17 00:00:00 2001 From: FreezeDriedMangoes Date: Tue, 31 May 2022 20:07:58 -0400 Subject: [PATCH] added ability to specify which variation you want for each text arc --- NewHorizons/Builder/Props/NomaiTextBuilder.cs | 19 +- NewHorizons/External/Modules/PropModule.cs | 6 + .../Utility/DebugMenu/DebugMenuNomaiText.cs | 171 ++++++++++++++++++ 3 files changed, 192 insertions(+), 4 deletions(-) create mode 100644 NewHorizons/Utility/DebugMenu/DebugMenuNomaiText.cs diff --git a/NewHorizons/Builder/Props/NomaiTextBuilder.cs b/NewHorizons/Builder/Props/NomaiTextBuilder.cs index b2cc2c44..ee28ddf2 100644 --- a/NewHorizons/Builder/Props/NomaiTextBuilder.cs +++ b/NewHorizons/Builder/Props/NomaiTextBuilder.cs @@ -305,24 +305,35 @@ namespace NewHorizons.Builder.Props var i = 0; foreach (var textData in dict.Values) { + var arcInfo = info.arcInfo[i]; var textEntryID = textData.ID; var parentID = textData.ParentID; var parent = parentID == -1 ? null : arcsByID[parentID]; GameObject arc; - var type = info.arcInfo != null ? info.arcInfo[i].type : PropModule.NomaiTextArcInfo.NomaiTextArcType.Adult; + var type = info.arcInfo != null ? arcInfo.type : PropModule.NomaiTextArcInfo.NomaiTextArcType.Adult; + var variation = 0; switch (type) { case PropModule.NomaiTextArcInfo.NomaiTextArcType.Child: - arc = _childArcPrefabs[Random.Range(0, _childArcPrefabs.Count())].InstantiateInactive(); + variation = arcInfo.variation < 0 + ? Random.Range(0, _childArcPrefabs.Count()) + : (arcInfo.variation % _childArcPrefabs.Count()); + arc = _childArcPrefabs[variation].InstantiateInactive(); break; case PropModule.NomaiTextArcInfo.NomaiTextArcType.Stranger when _ghostArcPrefabs.Any(): - arc = _ghostArcPrefabs[Random.Range(0, _ghostArcPrefabs.Count())].InstantiateInactive(); + variation = arcInfo.variation < 0 + ? Random.Range(0, _ghostArcPrefabs.Count()) + : (arcInfo.variation % _ghostArcPrefabs.Count()); + arc = _ghostArcPrefabs[variation].InstantiateInactive(); break; case PropModule.NomaiTextArcInfo.NomaiTextArcType.Adult: default: - arc = _arcPrefabs[Random.Range(0, _arcPrefabs.Count())].InstantiateInactive(); + variation = arcInfo.variation < 0 + ? Random.Range(0, _arcPrefabs.Count()) + : (arcInfo.variation % _arcPrefabs.Count()); + arc = _arcPrefabs[variation].InstantiateInactive(); break; } diff --git a/NewHorizons/External/Modules/PropModule.cs b/NewHorizons/External/Modules/PropModule.cs index ca0c35e3..e104ff39 100644 --- a/NewHorizons/External/Modules/PropModule.cs +++ b/NewHorizons/External/Modules/PropModule.cs @@ -455,6 +455,7 @@ namespace NewHorizons.External.Modules [EnumMember(Value = @"stranger")] Stranger = 2 } + /// /// The local position of this object on the wall. /// @@ -465,6 +466,11 @@ namespace NewHorizons.External.Modules /// public NomaiTextArcType type = NomaiTextArcType.Adult; + /// + /// Which variation of the chosen type to place. If not specified, a random variation will be selected based on the seed provided in the parent module. + /// + [DefaultValue(-1)] public int variation = -1; + /// /// The z euler angle for this arc. /// diff --git a/NewHorizons/Utility/DebugMenu/DebugMenuNomaiText.cs b/NewHorizons/Utility/DebugMenu/DebugMenuNomaiText.cs new file mode 100644 index 00000000..dcc4701d --- /dev/null +++ b/NewHorizons/Utility/DebugMenu/DebugMenuNomaiText.cs @@ -0,0 +1,171 @@ +using NewHorizons.External.Configs; +using NewHorizons.External.Modules; +using NewHorizons.Utility.DebugUtilities; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using UnityEngine; + +namespace NewHorizons.Utility.DebugMenu +{ + + /* + * Strategy: + * load all existing nomai text and allow the user to select them from a list + * from there, allow them to edit the placement of the one selected + */ + + class DebugMenuNomaiText : DebugSubmenu + { + private Vector2 recentPropsScrollPosition = Vector2.zero; + private HashSet favoriteProps = new HashSet(); + public static readonly char separatorCharacter = '☧'; // since no chars are illegal in game object names, I picked one that's extremely unlikely to be used to be a separator + private static readonly string favoritePropsPlayerPrefKey = "FavoriteProps"; + + internal DebugPropPlacer _dpp; + internal DebugRaycaster _drc; + + internal override string SubmenuName() + { + return "Prop Placer"; + } + + internal override void OnInit(DebugMenu menu) + { + _dpp = menu.GetComponent(); + _drc = menu.GetComponent(); + } + + internal override void OnAwake(DebugMenu menu) + { + _dpp = menu.GetComponent(); + _drc = menu.GetComponent(); + LoadFavoriteProps(); + } + + internal override void OnBeginLoadMod(DebugMenu debugMenu) + { + DebugPropPlacer.active = true; + } + + internal override void LoadConfigFile(DebugMenu menu, PlanetConfig config) + { + _dpp.FindAndRegisterPropsFromConfig(config); + } + + private void LoadFavoriteProps() + { + string favoritePropsPlayerPref = PlayerPrefs.GetString(favoritePropsPlayerPrefKey); + + if (favoritePropsPlayerPref == null || favoritePropsPlayerPref == "") return; + + var favoritePropPaths = favoritePropsPlayerPref.Split(separatorCharacter); + foreach (string favoriteProp in favoritePropPaths) + { + DebugPropPlacer.RecentlyPlacedProps.Add(favoriteProp); + this.favoriteProps.Add(favoriteProp); + } + } + + internal override void OnGUI(DebugMenu menu) + { + // + // DebugPropPlacer + // + GUILayout.Label("Currently placing: "); + _dpp.SetCurrentObject(GUILayout.TextArea(_dpp.currentObject)); + + GUILayout.Space(5); + + // List of recently placed objects + GUILayout.Label("Recently placed objects"); + recentPropsScrollPosition = GUILayout.BeginScrollView(recentPropsScrollPosition, GUILayout.Width(menu.EditorMenuSize.x), GUILayout.Height(500)); + foreach (string propPath in DebugPropPlacer.RecentlyPlacedProps) + { + GUILayout.BeginHorizontal(); + + var propPathElements = propPath[propPath.Length-1] == '/' + ? propPath.Substring(0, propPath.Length-1).Split('/') + : propPath.Split('/'); + string propName = propPathElements[propPathElements.Length - 1]; + + string favoriteButtonIcon = favoriteProps.Contains(propPath) ? "★" : "☆"; + if (GUILayout.Button(favoriteButtonIcon, GUILayout.ExpandWidth(false))) + { + if (favoriteProps.Contains(propPath)) + { + favoriteProps.Remove(propPath); + } + else + { + favoriteProps.Add(propPath); + } + + string[] favoritePropsArray = favoriteProps.ToArray(); + PlayerPrefs.SetString(favoritePropsPlayerPrefKey, string.Join(separatorCharacter + "", favoritePropsArray)); + } + + if (GUILayout.Button(propName)) + { + _dpp.SetCurrentObject(propPath); + } + + GUILayout.EndHorizontal(); + } + GUILayout.EndScrollView(); + + GUILayout.Space(5); + } + + internal override void PreSave(DebugMenu menu) + { + UpdateLoadedConfigsForRecentSystem(menu); + } + + private void UpdateLoadedConfigsForRecentSystem(DebugMenu menu) + { + var newDetails = _dpp.GetPropsConfigByBody(); + + Logger.Log("Updating config files. New Details Counts by planet: " + string.Join(", ", newDetails.Keys.Select(x => x + $" ({newDetails[x].Length})"))); + + Dictionary planetToConfigPath = new Dictionary(); + + // Get all configs + foreach (var filePath in menu.loadedConfigFiles.Keys) + { + Logger.Log("potentially updating copy of config at " + filePath); + + if (menu.loadedConfigFiles[filePath].starSystem != Main.Instance.CurrentStarSystem) return; + if (menu.loadedConfigFiles[filePath].name == null || AstroObjectLocator.GetAstroObject(menu.loadedConfigFiles[filePath].name) == null) { Logger.Log("Failed to update copy of config at " + filePath); continue; } + + var astroObjectName = DebugPropPlacer.GetAstroObjectName(menu.loadedConfigFiles[filePath].name); + planetToConfigPath[astroObjectName] = filePath; + + if (!newDetails.ContainsKey(astroObjectName)) continue; + + if (menu.loadedConfigFiles[filePath].Props == null) menu.loadedConfigFiles[filePath].Props = new External.Modules.PropModule(); + menu.loadedConfigFiles[filePath].Props.details = newDetails[astroObjectName]; + + Logger.Log("successfully updated copy of config file for " + astroObjectName); + } + + // find all new planets that do not yet have config paths + var planetsThatDoNotHaveConfigFiles = newDetails.Keys.Where(x => !planetToConfigPath.ContainsKey(x)).ToList(); + foreach (var astroObjectName in planetsThatDoNotHaveConfigFiles) + { + Logger.Log("Fabricating new config file for " + astroObjectName); + + var filepath = "planets/" + Main.Instance.CurrentStarSystem + "/" + astroObjectName + ".json"; + PlanetConfig c = new PlanetConfig(); + c.starSystem = Main.Instance.CurrentStarSystem; + c.name = astroObjectName; + c.Props = new PropModule(); + c.Props.details = newDetails[astroObjectName]; + + menu.loadedConfigFiles[filepath] = c; + } + } + } +}