diff --git a/src/StudioCore/AssetLocator.cs b/src/StudioCore/AssetLocator.cs
index e0f66de56..88e20c28b 100644
--- a/src/StudioCore/AssetLocator.cs
+++ b/src/StudioCore/AssetLocator.cs
@@ -1,18 +1,15 @@
using Octokit;
using SoulsFormats;
using StudioCore.Editor;
-using System;
using System.Collections.Generic;
-using System.Globalization;
using System.IO;
-using System.Linq;
-using System.Text.RegularExpressions;
namespace StudioCore;
public static class Locator
{
public static AssetLocator AssetLocator { get; set; }
+ public static Project ActiveProject { get; set; }
}
///
@@ -83,2211 +80,131 @@ public override bool Equals(object obj)
///
public class AssetLocator
{
- public static readonly string GameExecutableFilter;
- public static readonly string ProjectJsonFilter;
- public static readonly string RegulationBinFilter;
- public static readonly string Data0Filter;
- public static readonly string ParamBndDcxFilter;
- public static readonly string ParamBndFilter;
- public static readonly string EncRegulationFilter;
- public static readonly string ParamLooseFilter;
- public static readonly string CsvFilter;
- public static readonly string TxtFilter;
- public static readonly string FmgJsonFilter;
-
- private List FullMapList;
-
- static AssetLocator()
- {
- // These patterns are meant to be passed directly into PlatformUtils.
- // Everything about their handling should be done there.
-
- // Game Executable (.EXE, EBOOT.BIN)|*.EXE*;*EBOOT.BIN*
- // Windows executable (*.EXE)|*.EXE*
- // Playstation executable (*.BIN)|*.BIN*
- GameExecutableFilter = "exe,bin";
- // Project file (project.json)|PROJECT.JSON
- ProjectJsonFilter = "json";
- // Regulation file (regulation.bin)|REGULATION.BIN
- RegulationBinFilter = "bin";
- // Data file (Data0.bdt)|DATA0.BDT
- Data0Filter = "bdt";
- // ParamBndDcx (gameparam.parambnd.dcx)|GAMEPARAM.PARAMBND.DCX
- ParamBndDcxFilter = "parambnd.dcx";
- // ParamBnd (gameparam.parambnd)|GAMEPARAM.PARAMBND
- ParamBndFilter = "parambnd";
- // Enc_RegBndDcx (enc_regulation.bnd.dcx)|ENC_REGULATION.BND.DCX
- EncRegulationFilter = "bnd.dcx";
- // Loose Param file (*.Param)|*.Param
- ParamLooseFilter = "param";
- // CSV file (*.csv)|*.csv
- CsvFilter = "csv";
- // Text file (*.txt)|*.txt
- TxtFilter = "txt";
- // Exported FMGs (*.fmg.json)|*.fmg.json
- FmgJsonFilter = "fmg.json";
- // All file filter is implicitly added by NFD. Ideally this is used explicitly.
- // All files|*.*
- }
-
- public GameType Type { get; private set; } = GameType.Undefined;
+ public GameType Type => Locator.ActiveProject != null ? Locator.ActiveProject.Type : GameType.Undefined;
///
/// The game interroot where all the game assets are
///
- public string GameRootDirectory { get; private set; }
+ public string GameRootDirectory => Locator.ActiveProject.ParentProject.AssetLocator.RootDirectory;
///
/// An optional override mod directory where modded files are stored
///
- public string GameModDirectory { get; private set; }
-
- ///
- /// Directory where misc DSMapStudio files associated with a project are stored.
- ///
- public string ProjectMiscDir => @$"{GameModDirectory}\DSMapStudio";
-
- public string GetAssetPath(string relpath)
- {
- if (GameModDirectory != null)
- {
- var modpath = $@"{GameModDirectory}\{relpath}";
- if (File.Exists(modpath))
- {
- return modpath;
- }
- }
-
- return $@"{GameRootDirectory}\{relpath}";
- }
-
- public GameType GetGameTypeForExePath(string exePath)
- {
- var type = GameType.Undefined;
- if (exePath.ToLower().Contains("darksouls.exe"))
- {
- type = GameType.DarkSoulsPTDE;
- }
- else if (exePath.ToLower().Contains("darksoulsremastered.exe"))
- {
- type = GameType.DarkSoulsRemastered;
- }
- else if (exePath.ToLower().Contains("darksoulsii.exe"))
- {
- type = GameType.DarkSoulsIISOTFS;
- }
- else if (exePath.ToLower().Contains("darksoulsiii.exe"))
- {
- type = GameType.DarkSoulsIII;
- }
- else if (exePath.ToLower().Contains("eboot.bin"))
- {
- var path = Path.GetDirectoryName(exePath);
- if (Directory.Exists($@"{path}\dvdroot_ps4"))
- {
- type = GameType.Bloodborne;
- }
- else
- {
- type = GameType.DemonsSouls;
- }
- }
- else if (exePath.ToLower().Contains("sekiro.exe"))
- {
- type = GameType.Sekiro;
- }
- else if (exePath.ToLower().Contains("eldenring.exe"))
- {
- type = GameType.EldenRing;
- }
- else if (exePath.ToLower().Contains("armoredcore6.exe"))
- {
- type = GameType.ArmoredCoreVI;
- }
-
- return type;
- }
-
- public bool CheckFilesExpanded(string gamepath, GameType game)
- {
- if (game == GameType.EldenRing)
- {
- if (!Directory.Exists($@"{gamepath}\map"))
- {
- return false;
- }
-
- if (!Directory.Exists($@"{gamepath}\asset"))
- {
- return false;
- }
- }
-
- if (game is GameType.DarkSoulsPTDE or GameType.DarkSoulsIII or GameType.Sekiro)
- {
- if (!Directory.Exists($@"{gamepath}\map"))
- {
- return false;
- }
-
- if (!Directory.Exists($@"{gamepath}\obj"))
- {
- return false;
- }
- }
-
- if (game == GameType.DarkSoulsIISOTFS)
- {
- if (!Directory.Exists($@"{gamepath}\map"))
- {
- return false;
- }
-
- if (!Directory.Exists($@"{gamepath}\model\obj"))
- {
- return false;
- }
- }
-
- if (game == GameType.ArmoredCoreVI)
- {
- if (!Directory.Exists($@"{gamepath}\map"))
- {
- return false;
- }
-
- if (!Directory.Exists($@"{gamepath}\asset"))
- {
- return false;
- }
- }
-
- return true;
- }
-
- public void SetModProjectDirectory(string dir)
- {
- GameModDirectory = dir;
- }
-
- public void SetFromProjectSettings(ProjectSettings settings, string moddir)
- {
- Type = settings.GameType;
- GameRootDirectory = settings.GameRoot;
- GameModDirectory = moddir;
- FullMapList = null;
- }
+ public string GameModDirectory => Locator.ActiveProject.AssetLocator.RootDirectory;
- public bool CreateRecoveryProject()
- {
- if (GameRootDirectory == null || GameModDirectory == null)
- {
- return false;
- }
+ public string GetAssetPath(string relpath) => Locator.ActiveProject.AssetLocator.GetAssetPath(relpath);
- try
- {
- var time = DateTime.Now.ToString("dd-MM-yyyy-(hh-mm-ss)", CultureInfo.InvariantCulture);
- GameModDirectory = GameModDirectory + $@"\recovery\{time}";
- if (!Directory.Exists(GameModDirectory))
- {
- Directory.CreateDirectory(GameModDirectory);
- }
+ public bool CreateRecoveryProject() => Locator.ActiveProject.CreateRecoveryProject() != null;
- return true;
- }
- catch (Exception e)
- {
- return false;
- }
- }
+ ///
+ /// Gets the full list of maps in the game (excluding chalice dungeons). Basically if there's an msb for it,
+ /// it will be in this list.
+ ///
+ ///
+ public List GetFullMapList() => Locator.ActiveProject.AssetLocator.GetFullMapList();
- public bool FileExists(string relpath)
- {
- if (GameModDirectory != null && File.Exists($@"{GameModDirectory}\{relpath}"))
- {
- return true;
- }
+ public AssetDescription GetMapMSB(string mapid, bool writemode = false) => Locator.ActiveProject.AssetLocator.GetMapMSB(mapid, writemode);
- if (File.Exists($@"{GameRootDirectory}\{relpath}"))
- {
- return true;
- }
+ public List GetMapBTLs(string mapid, bool writemode = false) => Locator.ActiveProject.AssetLocator.GetMapBTLs(mapid, writemode);
- return false;
- }
+ public AssetDescription GetMapNVA(string mapid, bool writemode = false) => Locator.ActiveProject.AssetLocator.GetMapNVA(mapid, writemode);
- public string GetOverridenFilePath(string relpath)
- {
- if (GameModDirectory != null && File.Exists($@"{GameModDirectory}\{relpath}"))
- {
- return $@"{GameModDirectory}\{relpath}";
- }
+ public AssetDescription GetWorldLoadListList(bool writemode = false) => Locator.ActiveProject.AssetLocator.GetWorldLoadListList(writemode);
- if (File.Exists($@"{GameRootDirectory}\{relpath}"))
- {
- return $@"{GameRootDirectory}\{relpath}";
- }
+ ///
+ /// Get folders with msgbnds used in-game
+ ///
+ /// Dictionary with language name and path
+ public Dictionary GetMsgLanguages() => Locator.ActiveProject.AssetLocator.GetMsgLanguages();
- return null;
- }
+ ///
+ /// Get path of item.msgbnd (english by default)
+ ///
+ public AssetDescription GetItemMsgbnd(string langFolder, bool writemode = false) => Locator.ActiveProject.AssetLocator.GetItemMsgbnd(langFolder, writemode);
///
- /// Gets the full list of maps in the game (excluding chalice dungeons). Basically if there's an msb for it,
- /// it will be in this list.
+ /// Get path of menu.msgbnd (english by default)
///
- ///
- public List GetFullMapList()
- {
- if (GameRootDirectory == null)
- {
- return null;
- }
+ public AssetDescription GetMenuMsgbnd(string langFolder, bool writemode = false) => Locator.ActiveProject.AssetLocator.GetMenuMsgbnd(langFolder, writemode);
- if (FullMapList != null)
- {
- return FullMapList;
- }
+ public AssetDescription GetMsgbnd(string msgBndType, string langFolder, bool writemode = false) => Locator.ActiveProject.AssetLocator.GetMsgbnd(msgBndType, langFolder, writemode);
- try
- {
- HashSet mapSet = new();
+ public string GetGameIDForDir() => AssetUtils.GetGameIDForDir(Locator.ActiveProject.AssetLocator.Type);
- // DS2 has its own structure for msbs, where they are all inside individual folders
- if (Type == GameType.DarkSoulsIISOTFS)
- {
- List maps = Directory.GetFileSystemEntries(GameRootDirectory + @"\map", @"m*").ToList();
- if (GameModDirectory != null)
- {
- if (Directory.Exists(GameModDirectory + @"\map"))
- {
- maps.AddRange(Directory.GetFileSystemEntries(GameModDirectory + @"\map", @"m*").ToList());
- }
- }
+ public string GetScriptAssetsCommonDir() => Locator.ActiveProject.AssetLocator.GetScriptAssetsCommonDir();
- foreach (var map in maps)
- {
- mapSet.Add(Path.GetFileNameWithoutExtension($@"{map}.blah"));
- }
- }
- else
- {
- List msbFiles = Directory
- .GetFileSystemEntries(GameRootDirectory + @"\map\MapStudio\", @"*.msb")
- .Select(Path.GetFileNameWithoutExtension).ToList();
- msbFiles.AddRange(Directory
- .GetFileSystemEntries(GameRootDirectory + @"\map\MapStudio\", @"*.msb.dcx")
- .Select(Path.GetFileNameWithoutExtension).Select(Path.GetFileNameWithoutExtension).ToList());
- if (GameModDirectory != null && Directory.Exists(GameModDirectory + @"\map\MapStudio\"))
- {
- msbFiles.AddRange(Directory
- .GetFileSystemEntries(GameModDirectory + @"\map\MapStudio\", @"*.msb")
- .Select(Path.GetFileNameWithoutExtension).ToList());
- msbFiles.AddRange(Directory
- .GetFileSystemEntries(GameModDirectory + @"\map\MapStudio\", @"*.msb.dcx")
- .Select(Path.GetFileNameWithoutExtension).Select(Path.GetFileNameWithoutExtension)
- .ToList());
- }
+ public string GetScriptAssetsDir() => Locator.ActiveProject.AssetLocator.GetScriptAssetsDir();
- foreach (var msb in msbFiles)
- {
- mapSet.Add(msb);
- }
- }
+ public string GetUpgraderAssetsDir() => Locator.ActiveProject.AssetLocator.GetUpgraderAssetsDir();
- Regex mapRegex = new(@"^m\d{2}_\d{2}_\d{2}_\d{2}$");
- List mapList = mapSet.Where(x => mapRegex.IsMatch(x)).ToList();
- mapList.Sort();
- FullMapList = mapList;
- return FullMapList;
- }
- catch (DirectoryNotFoundException e)
- {
- // Game is likely not UXM unpacked
- return new List();
- }
- }
+ public string GetGameOffsetsAssetsDir() => Locator.ActiveProject.AssetLocator.GetGameOffsetsAssetsDir();
- public AssetDescription GetMapMSB(string mapid, bool writemode = false)
- {
- AssetDescription ad = new();
- ad.AssetPath = null;
- if (mapid.Length != 12)
- {
- return ad;
- }
+ public string GetStrippedRowNamesPath(string paramName) => Locator.ActiveProject.AssetLocator.GetStrippedRowNamesPath(paramName);
- string preferredPath;
- string backupPath;
- // SOFTS
- if (Type == GameType.DarkSoulsIISOTFS)
- {
- preferredPath = $@"map\{mapid}\{mapid}.msb";
- backupPath = $@"map\{mapid}\{mapid}.msb";
- }
- // BB chalice maps
- else if (Type == GameType.Bloodborne && mapid.StartsWith("m29"))
- {
- preferredPath = $@"\map\MapStudio\{mapid.Substring(0, 9)}_00\{mapid}.msb.dcx";
- backupPath = $@"\map\MapStudio\{mapid.Substring(0, 9)}_00\{mapid}.msb";
- }
- // DeS, DS1, DS1R
- else if (Type == GameType.DarkSoulsPTDE || Type == GameType.DarkSoulsRemastered ||
- Type == GameType.DemonsSouls)
- {
- preferredPath = $@"\map\MapStudio\{mapid}.msb";
- backupPath = $@"\map\MapStudio\{mapid}.msb.dcx";
- }
- // BB, DS3, ER, SSDT
- else if (Type == GameType.Bloodborne || Type == GameType.DarkSoulsIII || Type == GameType.EldenRing ||
- Type == GameType.Sekiro)
- {
- preferredPath = $@"\map\MapStudio\{mapid}.msb.dcx";
- backupPath = $@"\map\MapStudio\{mapid}.msb";
- }
- else
- {
- preferredPath = $@"\map\MapStudio\{mapid}.msb.dcx";
- backupPath = $@"\map\MapStudio\{mapid}.msb";
- }
+ public PARAMDEF GetParamdefForParam(string paramType) => Locator.ActiveProject.AssetLocator.GetParamdefForParam(paramType);
- if ((GameModDirectory != null && File.Exists($@"{GameModDirectory}\{preferredPath}")) ||
- (writemode && GameModDirectory != null))
- {
- ad.AssetPath = $@"{GameModDirectory}\{preferredPath}";
- }
- else if ((GameModDirectory != null && File.Exists($@"{GameModDirectory}\{backupPath}")) ||
- (writemode && GameModDirectory != null))
- {
- ad.AssetPath = $@"{GameModDirectory}\{backupPath}";
- }
- else if (File.Exists($@"{GameRootDirectory}\{preferredPath}"))
- {
- ad.AssetPath = $@"{GameRootDirectory}\{preferredPath}";
- }
- else if (File.Exists($@"{GameRootDirectory}\{backupPath}"))
- {
- ad.AssetPath = $@"{GameRootDirectory}\{backupPath}";
- }
+ public AssetDescription GetDS2GeneratorParam(string mapid, bool writemode = false) => Locator.ActiveProject.AssetLocator.GetDS2GeneratorParam(mapid, writemode);
- ad.AssetName = mapid;
- return ad;
- }
+ public AssetDescription GetDS2GeneratorLocationParam(string mapid, bool writemode = false) => Locator.ActiveProject.AssetLocator.GetDS2GeneratorLocationParam(mapid, writemode);
+ public AssetDescription GetDS2GeneratorRegistParam(string mapid, bool writemode = false) => Locator.ActiveProject.AssetLocator.GetDS2GeneratorRegistParam(mapid, writemode);
- public List GetMapBTLs(string mapid, bool writemode = false)
- {
- List adList = new();
- if (mapid.Length != 12)
- {
- return adList;
- }
+ public AssetDescription GetDS2EventParam(string mapid, bool writemode = false) => Locator.ActiveProject.AssetLocator.GetDS2EventParam(mapid, writemode);
- if (Type is GameType.DarkSoulsIISOTFS)
- {
- // DS2 BTL is located inside map's .gibdt file
- AssetDescription ad = new();
- var path = $@"model\map\g{mapid[1..]}.gibhd";
+ public AssetDescription GetDS2EventLocationParam(string mapid, bool writemode = false) => Locator.ActiveProject.AssetLocator.GetDS2EventLocationParam(mapid, writemode);
- if ((GameModDirectory != null && File.Exists($@"{GameModDirectory}\{path}")) ||
- (writemode && GameModDirectory != null))
- {
- ad.AssetPath = $@"{GameModDirectory}\{path}";
- }
- else if (File.Exists($@"{GameRootDirectory}\{path}"))
- {
- ad.AssetPath = $@"{GameRootDirectory}\{path}";
- }
+ public AssetDescription GetDS2ObjInstanceParam(string mapid, bool writemode = false) => Locator.ActiveProject.AssetLocator.GetDS2ObjInstanceParam(mapid, writemode);
- if (ad.AssetPath != null)
- {
- ad.AssetName = $@"g{mapid[1..]}";
- ad.AssetVirtualPath = $@"{mapid}\light.btl.dcx";
- adList.Add(ad);
- }
+ public List GetMapModelsFromBXF(string mapid) => Locator.ActiveProject.AssetLocator.GetMapModelsFromBXF(mapid);
+ public List GetMapModels(string mapid) => Locator.ActiveProject.AssetLocator.GetMapModels(mapid);
+ public string MapModelNameToAssetName(string mapid, string modelname) => Locator.ActiveProject.AssetLocator.MapModelNameToAssetName(mapid, modelname);
- AssetDescription ad2 = new();
- path = $@"model_lq\map\g{mapid[1..]}.gibhd";
+ ///
+ /// Gets the adjusted map ID that contains all the map assets
+ ///
+ /// The msb map ID to adjust
+ /// The map ID for the purpose of asset storage
+ public string GetAssetMapID(string mapid) => Locator.ActiveProject.AssetLocator.GetAssetMapID(mapid);
- if ((GameModDirectory != null && File.Exists($@"{GameModDirectory}\{path}")) ||
- (writemode && GameModDirectory != null))
- {
- ad2.AssetPath = $@"{GameModDirectory}\{path}";
- }
- else if (File.Exists($@"{GameRootDirectory}\{path}"))
- {
- ad2.AssetPath = $@"{GameRootDirectory}\{path}";
- }
+ public AssetDescription GetMapModel(string mapid, string model) => Locator.ActiveProject.AssetLocator.GetMapModel(mapid, model);
- if (ad2.AssetPath != null)
- {
- ad2.AssetName = $@"g{mapid[1..]}_lq";
- ad2.AssetVirtualPath = $@"{mapid}\light.btl.dcx";
- adList.Add(ad2);
- }
- }
- else if (Type is GameType.Bloodborne or GameType.DarkSoulsIII or GameType.Sekiro or GameType.EldenRing or GameType.ArmoredCoreVI)
- {
- string path;
- if (Type is GameType.EldenRing or GameType.ArmoredCoreVI)
- {
- path = $@"map\{mapid[..3]}\{mapid}";
- }
- else
- {
- path = $@"map\{mapid}";
- }
+ public AssetDescription GetMapCollisionModel(string mapid, string model, bool hi = true) => Locator.ActiveProject.AssetLocator.GetMapCollisionModel(mapid, model, hi);
- List files = new();
+ public List GetMapTextures(string mapid) => Locator.ActiveProject.AssetLocator.GetMapTextures(mapid);
- if (Directory.Exists($@"{GameRootDirectory}\{path}"))
- {
- files.AddRange(Directory.GetFiles($@"{GameRootDirectory}\{path}", "*.btl").ToList());
- files.AddRange(Directory.GetFiles($@"{GameRootDirectory}\{path}", "*.btl.dcx").ToList());
- }
+ public List GetEnvMapTextureNames(string mapid) => Locator.ActiveProject.AssetLocator.GetEnvMapTextureNames(mapid);
- if (Directory.Exists($@"{GameModDirectory}\{path}"))
- {
- // Check for additional BTLs the user has created.
- files.AddRange(Directory.GetFiles($@"{GameModDirectory}\{path}", "*.btl").ToList());
- files.AddRange(Directory.GetFiles($@"{GameModDirectory}\{path}", "*.btl.dcx").ToList());
- files = files.DistinctBy(f => f.Split("\\").Last()).ToList();
- }
+ public AssetDescription GetChrTextures(string chrid) => Locator.ActiveProject.AssetLocator.GetChrTextures(chrid);
- foreach (var file in files)
- {
- AssetDescription ad = new();
- var fileName = file.Split("\\").Last();
- if ((GameModDirectory != null && File.Exists($@"{GameModDirectory}\{path}\{fileName}")) ||
- (writemode && GameModDirectory != null))
- {
- ad.AssetPath = $@"{GameModDirectory}\{path}\{fileName}";
- }
- else if (File.Exists($@"{GameRootDirectory}\{path}\{fileName}"))
- {
- ad.AssetPath = $@"{GameRootDirectory}\{path}\{fileName}";
- }
+ public AssetDescription GetMapNVMModel(string mapid, string model) => Locator.ActiveProject.AssetLocator.GetMapNVMModel(mapid, model);
- if (ad.AssetPath != null)
- {
- ad.AssetName = fileName;
- adList.Add(ad);
- }
- }
- }
+ public AssetDescription GetHavokNavmeshes(string mapid) => Locator.ActiveProject.AssetLocator.GetHavokNavmeshes(mapid);
- return adList;
- }
+ public AssetDescription GetHavokNavmeshModel(string mapid, string model) => Locator.ActiveProject.AssetLocator.GetHavokNavmeshModel(mapid, model);
- public AssetDescription GetMapNVA(string mapid, bool writemode = false)
- {
- AssetDescription ad = new();
- ad.AssetPath = null;
- if (mapid.Length != 12)
- {
- return ad;
- }
- // BB chalice maps
+ public List GetChrModels() => Locator.ActiveProject.AssetLocator.GetChrModels();
- if (Type == GameType.Bloodborne && mapid.StartsWith("m29"))
- {
- var path = $@"\map\{mapid.Substring(0, 9)}_00\{mapid}";
- if ((GameModDirectory != null && File.Exists($@"{GameModDirectory}\{path}.nva.dcx")) ||
- (writemode && GameModDirectory != null && Type != GameType.DarkSoulsPTDE))
- {
- ad.AssetPath = $@"{GameModDirectory}\{path}.nva.dcx";
- }
- else if (File.Exists($@"{GameRootDirectory}\{path}.nva.dcx"))
- {
- ad.AssetPath = $@"{GameRootDirectory}\{path}.nva.dcx";
- }
- }
- else
- {
- var path = $@"\map\{mapid}\{mapid}";
- if ((GameModDirectory != null && File.Exists($@"{GameModDirectory}\{path}.nva.dcx")) ||
- (writemode && GameModDirectory != null && Type != GameType.DarkSoulsPTDE))
- {
- ad.AssetPath = $@"{GameModDirectory}\{path}.nva.dcx";
- }
- else if (File.Exists($@"{GameRootDirectory}\{path}.nva.dcx"))
- {
- ad.AssetPath = $@"{GameRootDirectory}\{path}.nva.dcx";
- }
- else if ((GameModDirectory != null && File.Exists($@"{GameModDirectory}\{path}.nva")) ||
- (writemode && GameModDirectory != null))
- {
- ad.AssetPath = $@"{GameModDirectory}\{path}.nva";
- }
- else if (File.Exists($@"{GameRootDirectory}\{path}.nva"))
- {
- ad.AssetPath = $@"{GameRootDirectory}\{path}.nva";
- }
- }
+ public AssetDescription GetChrModel(string chr) => Locator.ActiveProject.AssetLocator.GetChrModel(chr);
- ad.AssetName = mapid;
- return ad;
- }
+ public List GetObjModels() => Locator.ActiveProject.AssetLocator.GetObjModels();
- public AssetDescription GetWorldLoadListList(bool writemode = false)
- {
- AssetDescription ad = new();
+ public AssetDescription GetObjModel(string obj) => Locator.ActiveProject.AssetLocator.GetObjModel(obj);
- if (writemode || (GameModDirectory != null && File.Exists($@"{GameModDirectory}\map\worldmsblist.worldloadlistlist.dcx")))
- {
- ad.AssetPath = $@"{GameModDirectory}\map\worldmsblist.worldloadlistlist.dcx";
- } else
- {
- ad.AssetPath = $@"{GameRootDirectory}\map\worldmsblist.worldloadlistlist.dcx";
- }
-
- return ad;
- }
+ public AssetDescription GetObjTexture(string obj) => Locator.ActiveProject.AssetLocator.GetObjTexture(obj);
- ///
- /// Get folders with msgbnds used in-game
- ///
- /// Dictionary with language name and path
- public Dictionary GetMsgLanguages()
- {
- Dictionary dict = new();
- List folders = new();
- try
- {
- if (Type == GameType.DemonsSouls)
- {
- folders = Directory.GetDirectories(GameRootDirectory + @"\msg").ToList();
- // Japanese uses root directory
- if (File.Exists(GameRootDirectory + @"\msg\menu.msgbnd.dcx") ||
- File.Exists(GameRootDirectory + @"\msg\item.msgbnd.dcx"))
- {
- dict.Add("Japanese", "");
- }
- }
- else if (Type == GameType.DarkSoulsIISOTFS)
- {
- folders = Directory.GetDirectories(GameRootDirectory + @"\menu\text").ToList();
- }
- else
- {
- // Exclude folders that don't have typical msgbnds
- folders = Directory.GetDirectories(GameRootDirectory + @"\msg")
- .Where(x => !"common,as,eu,jp,na,uk,japanese".Contains(x.Split("\\").Last())).ToList();
- }
+ public AssetDescription GetAetTexture(string aetid) => Locator.ActiveProject.AssetLocator.GetAetTexture(aetid);
- foreach (var path in folders)
- {
- dict.Add(path.Split("\\").Last(), path);
- }
- }
- catch (Exception e) when (e is DirectoryNotFoundException or FileNotFoundException)
- {
- }
+ public List GetPartsModels() => Locator.ActiveProject.AssetLocator.GetPartsModels();
- return dict;
- }
+ public AssetDescription GetPartsModel(string part) => Locator.ActiveProject.AssetLocator.GetPartsModel(part);
- ///
- /// Get path of item.msgbnd (english by default)
- ///
- public AssetDescription GetItemMsgbnd(string langFolder, bool writemode = false)
- {
- return GetMsgbnd("item", langFolder, writemode);
- }
+ public AssetDescription GetPartTextures(string partsId) => Locator.ActiveProject.AssetLocator.GetPartTextures(partsId);
///
- /// Get path of menu.msgbnd (english by default)
- ///
- public AssetDescription GetMenuMsgbnd(string langFolder, bool writemode = false)
- {
- return GetMsgbnd("menu", langFolder, writemode);
- }
-
- public AssetDescription GetMsgbnd(string msgBndType, string langFolder, bool writemode = false)
- {
- AssetDescription ad = new();
- var path = $@"msg\{langFolder}\{msgBndType}.msgbnd.dcx";
- if (Type == GameType.DemonsSouls)
- {
- path = $@"msg\{langFolder}\{msgBndType}.msgbnd.dcx";
- // Demon's Souls has msgbnds directly in the msg folder
- if (!File.Exists($@"{GameRootDirectory}\{path}"))
- {
- path = $@"msg\{msgBndType}.msgbnd.dcx";
- }
- }
- else if (Type == GameType.DarkSoulsPTDE)
- {
- path = $@"msg\{langFolder}\{msgBndType}.msgbnd";
- }
- else if (Type == GameType.DarkSoulsRemastered)
- {
- path = $@"msg\{langFolder}\{msgBndType}.msgbnd.dcx";
- }
- else if (Type == GameType.DarkSoulsIISOTFS)
- {
- // DS2 does not have an msgbnd but loose fmg files instead
- path = $@"menu\text\{langFolder}";
- AssetDescription ad2 = new();
- ad2.AssetPath = writemode ? path : $@"{GameRootDirectory}\{path}";
- //TODO: doesn't support project files
- return ad2;
- }
- else if (Type == GameType.DarkSoulsIII)
- {
- path = $@"msg\{langFolder}\{msgBndType}_dlc2.msgbnd.dcx";
- }
-
- if (writemode)
- {
- ad.AssetPath = path;
- return ad;
- }
-
- if ((GameModDirectory != null && File.Exists($@"{GameModDirectory}\{path}")) ||
- (writemode && GameModDirectory != null))
- {
- ad.AssetPath = $@"{GameModDirectory}\{path}";
- }
- else if (File.Exists($@"{GameRootDirectory}\{path}"))
- {
- ad.AssetPath = $@"{GameRootDirectory}\{path}";
- }
-
- return ad;
- }
-
- public string GetGameIDForDir()
- {
- switch (Type)
- {
- case GameType.DemonsSouls:
- return "DES";
- case GameType.DarkSoulsPTDE:
- return "DS1";
- case GameType.DarkSoulsRemastered:
- return "DS1R";
- case GameType.DarkSoulsIISOTFS:
- return "DS2S";
- case GameType.Bloodborne:
- return "BB";
- case GameType.DarkSoulsIII:
- return "DS3";
- case GameType.Sekiro:
- return "SDT";
- case GameType.EldenRing:
- return "ER";
- case GameType.ArmoredCoreVI:
- return "AC6";
- default:
- throw new Exception("Game type not set");
- }
- }
-
- public string GetAliasAssetsDir()
- {
- return $@"Assets\Aliases\{GetGameIDForDir()}";
- }
-
-
- public string GetScriptAssetsCommonDir()
- {
- return @"Assets\MassEditScripts\Common";
- }
-
- public string GetScriptAssetsDir()
- {
- return $@"Assets\MassEditScripts\{GetGameIDForDir()}";
- }
-
- public string GetUpgraderAssetsDir()
- {
- return $@"{GetParamAssetsDir()}\Upgrader";
- }
-
- public string GetGameOffsetsAssetsDir()
- {
- return $@"Assets\GameOffsets\{GetGameIDForDir()}";
- }
-
- public string GetParamAssetsDir()
- {
- return $@"Assets\Paramdex\{GetGameIDForDir()}";
- }
-
- public string GetParamdefDir()
- {
- return $@"{GetParamAssetsDir()}\Defs";
- }
-
- public string GetTentativeParamTypePath()
- {
- return $@"{GetParamAssetsDir()}\Defs\TentativeParamType.csv";
- }
-
- public ulong[] GetParamdefPatches()
- {
- if (Directory.Exists($@"{GetParamAssetsDir()}\DefsPatch"))
- {
- var entries = Directory.GetFileSystemEntries($@"{GetParamAssetsDir()}\DefsPatch");
- return entries.Select(e => ulong.Parse(Path.GetFileNameWithoutExtension(e))).ToArray();
- }
-
- return new ulong[] { };
- }
-
- public string GetParamdefPatchDir(ulong patch)
- {
- return $@"{GetParamAssetsDir()}\DefsPatch\{patch}";
- }
-
- public string GetParammetaDir()
- {
- return $@"{GetParamAssetsDir()}\Meta";
- }
-
- public string GetParamNamesDir()
- {
- return $@"{GetParamAssetsDir()}\Names";
- }
-
- public string GetStrippedRowNamesPath(string paramName)
- {
- var dir = $@"{ProjectMiscDir}\Stripped Row Names";
- return $@"{dir}\{paramName}.txt";
- }
-
- public PARAMDEF GetParamdefForParam(string paramType)
- {
- PARAMDEF pd = PARAMDEF.XmlDeserialize($@"{GetParamdefDir()}\{paramType}.xml");
- return pd;
- }
-
- public AssetDescription GetDS2GeneratorParam(string mapid, bool writemode = false)
- {
- AssetDescription ad = new();
- var path = $@"Param\generatorparam_{mapid}";
- if ((GameModDirectory != null && File.Exists($@"{GameModDirectory}\{path}.param")) ||
- (writemode && GameModDirectory != null))
- {
- ad.AssetPath = $@"{GameModDirectory}\{path}.param";
- }
- else if (File.Exists($@"{GameRootDirectory}\{path}.param"))
- {
- ad.AssetPath = $@"{GameRootDirectory}\{path}.param";
- }
-
- ad.AssetName = mapid + "_generators";
- return ad;
- }
-
- public AssetDescription GetDS2GeneratorLocationParam(string mapid, bool writemode = false)
- {
- AssetDescription ad = new();
- var path = $@"Param\generatorlocation_{mapid}";
- if ((GameModDirectory != null && File.Exists($@"{GameModDirectory}\{path}.param")) ||
- (writemode && GameModDirectory != null))
- {
- ad.AssetPath = $@"{GameModDirectory}\{path}.param";
- }
- else if (File.Exists($@"{GameRootDirectory}\{path}.param"))
- {
- ad.AssetPath = $@"{GameRootDirectory}\{path}.param";
- }
-
- ad.AssetName = mapid + "_generator_locations";
- return ad;
- }
-
- public AssetDescription GetDS2GeneratorRegistParam(string mapid, bool writemode = false)
- {
- AssetDescription ad = new();
- var path = $@"Param\generatorregistparam_{mapid}";
- if ((GameModDirectory != null && File.Exists($@"{GameModDirectory}\{path}.param")) ||
- (writemode && GameModDirectory != null))
- {
- ad.AssetPath = $@"{GameModDirectory}\{path}.param";
- }
- else if (File.Exists($@"{GameRootDirectory}\{path}.param"))
- {
- ad.AssetPath = $@"{GameRootDirectory}\{path}.param";
- }
-
- ad.AssetName = mapid + "_generator_registrations";
- return ad;
- }
-
- public AssetDescription GetDS2EventParam(string mapid, bool writemode = false)
- {
- AssetDescription ad = new();
- var path = $@"Param\eventparam_{mapid}";
- if ((GameModDirectory != null && File.Exists($@"{GameModDirectory}\{path}.param")) ||
- (writemode && GameModDirectory != null))
- {
- ad.AssetPath = $@"{GameModDirectory}\{path}.param";
- }
- else if (File.Exists($@"{GameRootDirectory}\{path}.param"))
- {
- ad.AssetPath = $@"{GameRootDirectory}\{path}.param";
- }
-
- ad.AssetName = mapid + "_event_params";
- return ad;
- }
-
- public AssetDescription GetDS2EventLocationParam(string mapid, bool writemode = false)
- {
- AssetDescription ad = new();
- var path = $@"Param\eventlocation_{mapid}";
- if ((GameModDirectory != null && File.Exists($@"{GameModDirectory}\{path}.param")) ||
- (writemode && GameModDirectory != null))
- {
- ad.AssetPath = $@"{GameModDirectory}\{path}.param";
- }
- else if (File.Exists($@"{GameRootDirectory}\{path}.param"))
- {
- ad.AssetPath = $@"{GameRootDirectory}\{path}.param";
- }
-
- ad.AssetName = mapid + "_event_locations";
- return ad;
- }
-
- public AssetDescription GetDS2ObjInstanceParam(string mapid, bool writemode = false)
- {
- AssetDescription ad = new();
- var path = $@"Param\mapobjectinstanceparam_{mapid}";
- if ((GameModDirectory != null && File.Exists($@"{GameModDirectory}\{path}.param")) ||
- (writemode && GameModDirectory != null))
- {
- ad.AssetPath = $@"{GameModDirectory}\{path}.param";
- }
- else if (File.Exists($@"{GameRootDirectory}\{path}.param"))
- {
- ad.AssetPath = $@"{GameRootDirectory}\{path}.param";
- }
-
- ad.AssetName = mapid + "_object_instance_params";
- return ad;
- }
-
- // Used to get the map model list from within the mapbhd/bdt
- public List GetMapModelsFromBXF(string mapid)
- {
- List ret = new();
-
- if (Locator.AssetLocator.Type is GameType.DarkSoulsIISOTFS)
- {
- var path = $@"{Locator.AssetLocator.GameModDirectory}/model/map/{mapid}.mapbdt";
-
- if (!File.Exists(path))
- {
- path = $@"{Locator.AssetLocator.GameRootDirectory}/model/map/{mapid}.mapbdt";
- }
-
- if (File.Exists(path))
- {
- var bdtPath = path;
- var bhdPath = path.Replace("bdt", "bhd");
-
- var bxf = BXF4.Read(bhdPath, bdtPath);
-
- if (bxf != null)
- {
- foreach (var file in bxf.Files)
- {
- if (file.Name.Contains(".flv"))
- {
- var name = Path.GetFileNameWithoutExtension(Path.GetFileNameWithoutExtension(file.Name));
-
- AssetDescription ad = new();
- ad.AssetName = name;
- ad.AssetArchiveVirtualPath = $@"map/{name}/model/";
-
- ret.Add(ad);
- }
- }
- }
- }
- }
-
- return ret;
- }
- public List GetMapModels(string mapid)
- {
- List ret = new();
- if (Type == GameType.DarkSoulsIII || Type == GameType.Sekiro)
- {
- if (!Directory.Exists(GameRootDirectory + $@"\map\{mapid}\"))
- {
- return ret;
- }
-
- List mapfiles = Directory
- .GetFileSystemEntries(GameRootDirectory + $@"\map\{mapid}\", @"*.mapbnd.dcx").ToList();
- foreach (var f in mapfiles)
- {
- AssetDescription ad = new();
- ad.AssetPath = f;
- var name = Path.GetFileNameWithoutExtension(Path.GetFileNameWithoutExtension(f));
- ad.AssetName = name;
- ad.AssetArchiveVirtualPath = $@"map/{mapid}/model/{name}";
- ad.AssetVirtualPath = $@"map/{mapid}/model/{name}/{name}.flver";
- ret.Add(ad);
- }
- }
- else if (Type == GameType.DarkSoulsIISOTFS)
- {
- AssetDescription ad = new();
- var name = mapid;
- ad.AssetName = name;
- ad.AssetArchiveVirtualPath = $@"map/{mapid}/model";
- ret.Add(ad);
- }
- else if (Type == GameType.EldenRing)
- {
- var mapPath = GameRootDirectory + $@"\map\{mapid[..3]}\{mapid}";
- if (!Directory.Exists(mapPath))
- {
- return ret;
- }
-
- List mapfiles = Directory.GetFileSystemEntries(mapPath, @"*.mapbnd.dcx").ToList();
- foreach (var f in mapfiles)
- {
- AssetDescription ad = new();
- ad.AssetPath = f;
- var name = Path.GetFileNameWithoutExtension(Path.GetFileNameWithoutExtension(f));
- ad.AssetName = name;
- ad.AssetArchiveVirtualPath = $@"map/{mapid}/model/{name}";
- ad.AssetVirtualPath = $@"map/{mapid}/model/{name}/{name}.flver";
- ret.Add(ad);
- }
- }
- else if (Type == GameType.ArmoredCoreVI)
- {
- var mapPath = GameRootDirectory + $@"\map\{mapid[..3]}\{mapid}";
- if (!Directory.Exists(mapPath))
- {
- return ret;
- }
-
- List mapfiles = Directory.GetFileSystemEntries(mapPath, @"*.mapbnd.dcx").ToList();
- foreach (var f in mapfiles)
- {
- AssetDescription ad = new();
- ad.AssetPath = f;
- var name = Path.GetFileNameWithoutExtension(Path.GetFileNameWithoutExtension(f));
- ad.AssetName = name;
- ad.AssetArchiveVirtualPath = $@"map/{mapid}/model/{name}";
- ad.AssetVirtualPath = $@"map/{mapid}/model/{name}/{name}.flver";
- ret.Add(ad);
- }
- }
- else
- {
- if (!Directory.Exists(GameRootDirectory + $@"\map\{mapid}\"))
- {
- return ret;
- }
-
- var ext = Type == GameType.DarkSoulsPTDE ? @"*.flver" : @"*.flver.dcx";
- List mapfiles = Directory.GetFileSystemEntries(GameRootDirectory + $@"\map\{mapid}\", ext)
- .ToList();
- foreach (var f in mapfiles)
- {
- AssetDescription ad = new();
- ad.AssetPath = f;
- var name = Path.GetFileNameWithoutExtension(Path.GetFileNameWithoutExtension(f));
- ad.AssetName = name;
- // ad.AssetArchiveVirtualPath = $@"map/{mapid}/model/{name}";
- ad.AssetVirtualPath = $@"map/{mapid}/model/{name}/{name}.flver";
- ret.Add(ad);
- }
- }
-
- return ret;
- }
-
- public string MapModelNameToAssetName(string mapid, string modelname)
- {
- if (Type == GameType.DarkSoulsPTDE || Type == GameType.DarkSoulsRemastered)
- {
- return $@"{modelname}A{mapid.Substring(1, 2)}";
- }
-
- if (Type == GameType.DemonsSouls)
- {
- return $@"{modelname}";
- }
-
- if (Type == GameType.DarkSoulsIISOTFS)
- {
- return modelname;
- }
-
- return $@"{mapid}_{modelname.Substring(1)}";
- }
-
- ///
- /// Gets the adjusted map ID that contains all the map assets
- ///
- /// The msb map ID to adjust
- /// The map ID for the purpose of asset storage
- public string GetAssetMapID(string mapid)
- {
- if (Type is GameType.EldenRing or GameType.ArmoredCoreVI)
- {
- return mapid;
- }
-
- if (Type is GameType.DarkSoulsRemastered)
- {
- if (mapid.StartsWith("m99"))
- {
- // DSR m99 maps contain their own assets
- return mapid;
- }
- }
- else if (Type is GameType.DemonsSouls)
- {
- return mapid;
- }
- else if (Type is GameType.Bloodborne)
- {
- if (mapid.StartsWith("m29"))
- {
- // Special case for chalice dungeon assets
- return "m29_00_00_00";
- }
- }
-
- // Default
- return mapid.Substring(0, 6) + "_00_00";
- }
-
- public AssetDescription GetMapModel(string mapid, string model)
- {
- AssetDescription ret = new();
- if (Type == GameType.DarkSoulsPTDE || Type == GameType.Bloodborne || Type == GameType.DemonsSouls)
- {
- ret.AssetPath = GetAssetPath($@"map\{mapid}\{model}.flver");
- }
- else if (Type == GameType.DarkSoulsRemastered)
- {
- ret.AssetPath = GetAssetPath($@"map\{mapid}\{model}.flver.dcx");
- }
- else if (Type == GameType.DarkSoulsIISOTFS)
- {
- ret.AssetPath = GetAssetPath($@"model\map\{mapid}.mapbhd");
- }
- else if (Type == GameType.EldenRing)
- {
- ret.AssetPath = GetAssetPath($@"map\{mapid[..3]}\{mapid}\{model}.mapbnd.dcx");
- }
- else if (Type == GameType.ArmoredCoreVI)
- {
- ret.AssetPath = GetAssetPath($@"map\{mapid[..3]}\{mapid}\{model}.mapbnd.dcx");
- }
- else
- {
- ret.AssetPath = GetAssetPath($@"map\{mapid}\{model}.mapbnd.dcx");
- }
-
- ret.AssetName = model;
- if (Type == GameType.DarkSoulsIISOTFS)
- {
- ret.AssetArchiveVirtualPath = $@"map/{mapid}/model";
- ret.AssetVirtualPath = $@"map/{mapid}/model/{model}.flv.dcx";
- }
- else
- {
- if (Type is not GameType.DemonsSouls
- and not GameType.DarkSoulsPTDE
- and not GameType.DarkSoulsRemastered
- and not GameType.Bloodborne)
- {
- ret.AssetArchiveVirtualPath = $@"map/{mapid}/model/{model}";
- }
-
- ret.AssetVirtualPath = $@"map/{mapid}/model/{model}/{model}.flver";
- }
-
- return ret;
- }
-
- public AssetDescription GetMapCollisionModel(string mapid, string model, bool hi = true)
- {
- AssetDescription ret = new();
- if (Type == GameType.DarkSoulsPTDE || Type == GameType.DemonsSouls)
- {
- if (hi)
- {
- ret.AssetPath = GetAssetPath($@"map\{mapid}\{model}.hkx");
- ret.AssetName = model;
- ret.AssetVirtualPath = $@"map/{mapid}/hit/hi/{model}.hkx";
- }
- else
- {
- ret.AssetPath = GetAssetPath($@"map\{mapid}\l{model.Substring(1)}.hkx");
- ret.AssetName = model;
- ret.AssetVirtualPath = $@"map/{mapid}/hit/lo/l{model.Substring(1)}.hkx";
- }
- }
- else if (Type == GameType.DarkSoulsIISOTFS)
- {
- ret.AssetPath = GetAssetPath($@"model\map\h{mapid.Substring(1)}.hkxbhd");
- ret.AssetName = model;
- ret.AssetVirtualPath = $@"map/{mapid}/hit/hi/{model}.hkx.dcx";
- ret.AssetArchiveVirtualPath = $@"map/{mapid}/hit/hi";
- }
- else if (Type == GameType.DarkSoulsIII || Type == GameType.Bloodborne)
- {
- if (hi)
- {
- ret.AssetPath = GetAssetPath($@"map\{mapid}\h{mapid.Substring(1)}.hkxbhd");
- ret.AssetName = model;
- ret.AssetVirtualPath = $@"map/{mapid}/hit/hi/h{model.Substring(1)}.hkx.dcx";
- ret.AssetArchiveVirtualPath = $@"map/{mapid}/hit/hi";
- }
- else
- {
- ret.AssetPath = GetAssetPath($@"map\{mapid}\l{mapid.Substring(1)}.hkxbhd");
- ret.AssetName = model;
- ret.AssetVirtualPath = $@"map/{mapid}/hit/lo/l{model.Substring(1)}.hkx.dcx";
- ret.AssetArchiveVirtualPath = $@"map/{mapid}/hit/lo";
- }
- }
- else
- {
- return GetNullAsset();
- }
-
- return ret;
- }
-
- public List GetMapTextures(string mapid)
- {
- List ads = new();
-
- if (Type == GameType.DarkSoulsIISOTFS)
- {
- AssetDescription t = new();
- t.AssetPath = GetAssetPath($@"model\map\t{mapid.Substring(1)}.tpfbhd");
- t.AssetArchiveVirtualPath = $@"map/tex/{mapid}/tex";
- ads.Add(t);
- }
- else if (Type == GameType.DarkSoulsPTDE)
- {
- // TODO
- }
- else if (Type == GameType.EldenRing)
- {
- // TODO ER
- }
- else if (Type == GameType.ArmoredCoreVI)
- {
- // TODO AC6
- }
- else if (Type == GameType.DemonsSouls)
- {
- var mid = mapid.Substring(0, 3);
- var paths = Directory.GetFileSystemEntries($@"{GameRootDirectory}\map\{mid}\", "*.tpf.dcx");
- foreach (var path in paths)
- {
- AssetDescription ad = new();
- ad.AssetPath = path;
- var tid = Path.GetFileNameWithoutExtension(path).Substring(4, 4);
- ad.AssetVirtualPath = $@"map/tex/{mid}/{tid}";
- ads.Add(ad);
- }
- }
- else
- {
- // Clean this up. Even if it's common code having something like "!=Sekiro" can lead to future issues
- var mid = mapid.Substring(0, 3);
-
- AssetDescription t0000 = new();
- t0000.AssetPath = GetAssetPath($@"map\{mid}\{mid}_0000.tpfbhd");
- t0000.AssetArchiveVirtualPath = $@"map/tex/{mid}/0000";
- ads.Add(t0000);
-
- AssetDescription t0001 = new();
- t0001.AssetPath = GetAssetPath($@"map\{mid}\{mid}_0001.tpfbhd");
- t0001.AssetArchiveVirtualPath = $@"map/tex/{mid}/0001";
- ads.Add(t0001);
-
- AssetDescription t0002 = new();
- t0002.AssetPath = GetAssetPath($@"map\{mid}\{mid}_0002.tpfbhd");
- t0002.AssetArchiveVirtualPath = $@"map/tex/{mid}/0002";
- ads.Add(t0002);
-
- AssetDescription t0003 = new();
- t0003.AssetPath = GetAssetPath($@"map\{mid}\{mid}_0003.tpfbhd");
- t0003.AssetArchiveVirtualPath = $@"map/tex/{mid}/0003";
- ads.Add(t0003);
-
- if (Type == GameType.DarkSoulsRemastered)
- {
- AssetDescription env = new();
- env.AssetPath = GetAssetPath($@"map\{mid}\GI_EnvM_{mid}.tpfbhd");
- env.AssetArchiveVirtualPath = $@"map/tex/{mid}/env";
- ads.Add(env);
- }
- else if (Type == GameType.Bloodborne || Type == GameType.DarkSoulsIII)
- {
- AssetDescription env = new();
- env.AssetPath = GetAssetPath($@"map\{mid}\{mid}_envmap.tpf.dcx");
- env.AssetVirtualPath = $@"map/tex/{mid}/env";
- ads.Add(env);
- }
- else if (Type == GameType.Sekiro)
- {
- //TODO SDT
- }
- }
-
- return ads;
- }
-
- public List GetEnvMapTextureNames(string mapid)
- {
- List l = new();
- if (Type == GameType.DarkSoulsIII)
- {
- var mid = mapid.Substring(0, 3);
- if (File.Exists(GetAssetPath($@"map\{mid}\{mid}_envmap.tpf.dcx")))
- {
- TPF t = TPF.Read(GetAssetPath($@"map\{mid}\{mid}_envmap.tpf.dcx"));
- foreach (TPF.Texture tex in t.Textures)
- {
- l.Add(tex.Name);
- }
- }
- }
-
- return l;
- }
-
- private string GetChrTexturePath(string chrid)
- {
- if (Type is GameType.DemonsSouls)
- {
- return GetOverridenFilePath($@"chr\{chrid}\{chrid}.tpf");
- }
-
- if (Type is GameType.DarkSoulsPTDE)
- {
- var path = GetOverridenFilePath($@"chr\{chrid}\{chrid}.tpf");
- if (path != null)
- {
- return path;
- }
-
- return GetOverridenFilePath($@"chr\{chrid}.chrbnd");
- }
-
- if (Type is GameType.DarkSoulsIISOTFS)
- {
- return GetOverridenFilePath($@"model\chr\{chrid}.texbnd");
- }
-
- if (Type is GameType.DarkSoulsRemastered)
- {
- // TODO: Some textures require getting chrtpfbhd from chrbnd, then using it with chrtpfbdt in chr folder.
- return GetOverridenFilePath($@"chr\{chrid}.chrbnd");
- }
-
- if (Type is GameType.Bloodborne)
- {
- return GetOverridenFilePath($@"chr\{chrid}_2.tpf.dcx");
- }
-
- if (Type is GameType.DarkSoulsIII or GameType.Sekiro)
- {
- return GetOverridenFilePath($@"chr\{chrid}.texbnd.dcx");
- }
-
- if (Type is GameType.EldenRing)
- {
- // TODO: Maybe add an option down the line to load lower quality
- return GetOverridenFilePath($@"chr\{chrid}_h.texbnd.dcx");
- }
-
- if (Type is GameType.ArmoredCoreVI)
- {
- return GetOverridenFilePath($@"chr\{chrid}.texbnd.dcx");
- }
-
- return null;
- }
-
- public AssetDescription GetChrTextures(string chrid)
- {
- AssetDescription ad = new();
- ad.AssetArchiveVirtualPath = null;
- ad.AssetPath = null;
- if (Type is GameType.DemonsSouls)
- {
- var path = GetChrTexturePath(chrid);
- if (path != null)
- {
- ad.AssetPath = path;
- ad.AssetVirtualPath = $@"chr/{chrid}/tex";
- }
- }
- else if (Type is GameType.DarkSoulsPTDE)
- {
- var path = GetChrTexturePath(chrid);
- if (path != null)
- {
- ad.AssetPath = path;
- if (path.EndsWith(".chrbnd"))
- {
- ad.AssetArchiveVirtualPath = $@"chr/{chrid}/tex";
- }
- else
- {
- ad.AssetVirtualPath = $@"chr/{chrid}/tex";
- }
- }
- }
- else if (Type is GameType.DarkSoulsRemastered)
- {
- // TODO: Some textures require getting chrtpfbhd from chrbnd, then using it with chrtpfbdt in chr folder.
- var path = GetChrTexturePath(chrid);
- if (path != null)
- {
- ad = new AssetDescription();
- ad.AssetPath = path;
- ad.AssetVirtualPath = $@"chr/{chrid}/tex";
- }
- }
- else if (Type is GameType.DarkSoulsIISOTFS)
- {
- var path = GetChrTexturePath(chrid);
- if (path != null)
- {
- ad = new AssetDescription();
- ad.AssetPath = path;
- ad.AssetVirtualPath = $@"chr/{chrid}/tex";
- }
- }
- else if (Type is GameType.Bloodborne)
- {
- var path = GetChrTexturePath(chrid);
- if (path != null)
- {
- ad.AssetPath = path;
- ad.AssetVirtualPath = $@"chr/{chrid}/tex";
- }
- }
- else if (Type is GameType.DarkSoulsIII or GameType.Sekiro)
- {
- var path = GetChrTexturePath(chrid);
- if (path != null)
- {
- ad.AssetPath = path;
- ad.AssetArchiveVirtualPath = $@"chr/{chrid}/tex";
- }
- }
- else if (Type is GameType.EldenRing or GameType.ArmoredCoreVI)
- {
- var path = GetChrTexturePath(chrid);
- if (path != null)
- {
- ad.AssetPath = path;
- ad.AssetArchiveVirtualPath = $@"chr/{chrid}/tex";
- }
- }
-
- return ad;
- }
-
- public AssetDescription GetMapNVMModel(string mapid, string model)
- {
- AssetDescription ret = new();
- if (Type == GameType.DarkSoulsPTDE || Type == GameType.DarkSoulsRemastered || Type == GameType.DemonsSouls)
- {
- ret.AssetPath = GetAssetPath($@"map\{mapid}\{model}.nvm");
- ret.AssetName = model;
- ret.AssetArchiveVirtualPath = $@"map/{mapid}/nav";
- ret.AssetVirtualPath = $@"map/{mapid}/nav/{model}.nvm";
- }
- else
- {
- return GetNullAsset();
- }
-
- return ret;
- }
-
- public AssetDescription GetHavokNavmeshes(string mapid)
- {
- AssetDescription ret = new();
- ret.AssetPath = GetAssetPath($@"map\{mapid}\{mapid}.nvmhktbnd.dcx");
- ret.AssetName = mapid;
- ret.AssetArchiveVirtualPath = $@"map/{mapid}/nav";
- return ret;
- }
-
- public AssetDescription GetHavokNavmeshModel(string mapid, string model)
- {
- AssetDescription ret = new();
- ret.AssetPath = GetAssetPath($@"map\{mapid}\{mapid}.nvmhktbnd.dcx");
- ret.AssetName = model;
- ret.AssetArchiveVirtualPath = $@"map/{mapid}/nav";
- ret.AssetVirtualPath = $@"map/{mapid}/nav/{model}.hkx";
-
- return ret;
- }
-
- public List GetChrModels()
- {
- try
- {
- HashSet chrs = new();
- List ret = new();
-
- var modelDir = @"\chr";
- var modelExt = @".chrbnd.dcx";
- if (Type == GameType.DarkSoulsPTDE)
- {
- modelExt = ".chrbnd";
- }
- else if (Type == GameType.DarkSoulsIISOTFS)
- {
- modelDir = @"\model\chr";
- modelExt = ".bnd";
- }
-
- if (Type == GameType.DemonsSouls)
- {
- var chrdirs = Directory.GetDirectories(GameRootDirectory + modelDir);
- foreach (var f in chrdirs)
- {
- var name = Path.GetFileNameWithoutExtension(f + ".dummy");
- if (name.StartsWith("c"))
- {
- ret.Add(name);
- }
- }
-
- return ret;
- }
-
- List chrfiles = Directory.GetFileSystemEntries(GameRootDirectory + modelDir, $@"*{modelExt}")
- .ToList();
- foreach (var f in chrfiles)
- {
- var name = Path.GetFileNameWithoutExtension(Path.GetFileNameWithoutExtension(f));
- ret.Add(name);
- chrs.Add(name);
- }
-
- if (GameModDirectory != null && Directory.Exists(GameModDirectory + modelDir))
- {
- chrfiles = Directory.GetFileSystemEntries(GameModDirectory + modelDir, $@"*{modelExt}").ToList();
- foreach (var f in chrfiles)
- {
- var name = Path.GetFileNameWithoutExtension(Path.GetFileNameWithoutExtension(f));
- if (!chrs.Contains(name))
- {
- ret.Add(name);
- chrs.Add(name);
- }
- }
- }
-
- return ret;
- }
- catch (DirectoryNotFoundException e)
- {
- // Game likely isn't UXM unpacked
- return new List();
- }
- }
-
- public AssetDescription GetChrModel(string chr)
- {
- AssetDescription ret = new();
- ret.AssetName = chr;
- ret.AssetArchiveVirtualPath = $@"chr/{chr}/model";
- if (Type == GameType.DarkSoulsIISOTFS)
- {
- ret.AssetVirtualPath = $@"chr/{chr}/model/{chr}.flv";
- }
- else
- {
- ret.AssetVirtualPath = $@"chr/{chr}/model/{chr}.flver";
- }
-
- return ret;
- }
-
- public List GetObjModels()
- {
- try
- {
- HashSet objs = new();
- List ret = new();
-
- var modelDir = @"\obj";
- var modelExt = @".objbnd.dcx";
- if (Type == GameType.DarkSoulsPTDE)
- {
- modelExt = ".objbnd";
- }
- else if (Type == GameType.DarkSoulsIISOTFS)
- {
- modelDir = @"\model\obj";
- modelExt = ".bnd";
- }
- else if (Type == GameType.EldenRing)
- {
- // AEGs are objs in my heart :(
- modelDir = @"\asset\aeg";
- modelExt = ".geombnd.dcx";
- }
- else if (Type == GameType.ArmoredCoreVI)
- {
- // AEGs are objs in my heart :(
- modelDir = @"\asset\environment\geometry";
- modelExt = ".geombnd.dcx";
- }
-
- // Directories to search for obj models
- List searchDirs = new();
- if (Type == GameType.EldenRing)
- {
- searchDirs = Directory.GetFileSystemEntries(GameRootDirectory + modelDir, @"aeg*").ToList();
- }
- else
- {
- searchDirs.Add(GameRootDirectory + modelDir);
- }
-
- foreach (var searchDir in searchDirs)
- {
- List objfiles = Directory.GetFileSystemEntries(searchDir, $@"*{modelExt}").ToList();
- foreach (var f in objfiles)
- {
- var name = Path.GetFileNameWithoutExtension(Path.GetFileNameWithoutExtension(f));
- ret.Add(name);
- objs.Add(name);
- }
-
- if (GameModDirectory != null && Directory.Exists(searchDir))
- {
- objfiles = Directory.GetFileSystemEntries(searchDir, $@"*{modelExt}").ToList();
- foreach (var f in objfiles)
- {
- var name = Path.GetFileNameWithoutExtension(Path.GetFileNameWithoutExtension(f));
- if (!objs.Contains(name))
- {
- ret.Add(name);
- objs.Add(name);
- }
- }
- }
- }
-
- return ret;
- }
- catch (DirectoryNotFoundException e)
- {
- // Game likely isn't UXM unpacked
- return new List();
- }
- }
-
- public AssetDescription GetObjModel(string obj)
- {
- AssetDescription ret = new();
- ret.AssetName = obj;
- ret.AssetArchiveVirtualPath = $@"obj/{obj}/model";
- if (Type == GameType.DarkSoulsIISOTFS)
- {
- ret.AssetVirtualPath = $@"obj/{obj}/model/{obj}.flv";
- }
- else if (Type is GameType.EldenRing or GameType.ArmoredCoreVI)
- {
- ret.AssetVirtualPath = $@"obj/{obj}/model/{obj.ToUpper()}.flver";
- }
- else
- {
- ret.AssetVirtualPath = $@"obj/{obj}/model/{obj}.flver";
- }
-
- return ret;
- }
-
- public AssetDescription GetObjTexture(string obj)
- {
- AssetDescription ad = new();
- ad.AssetPath = null;
- ad.AssetArchiveVirtualPath = null;
- string path = null;
- if (Type == GameType.DarkSoulsPTDE)
- {
- path = GetOverridenFilePath($@"obj\{obj}.objbnd");
- }
- else if (Type is GameType.DemonsSouls or GameType.DarkSoulsRemastered or GameType.Bloodborne
- or GameType.DarkSoulsIII or GameType.Sekiro)
- {
- path = GetOverridenFilePath($@"obj\{obj}.objbnd.dcx");
- }
-
- if (path != null)
- {
- ad.AssetPath = path;
- ad.AssetArchiveVirtualPath = $@"obj/{obj}/tex";
- }
-
- return ad;
- }
-
- public AssetDescription GetAetTexture(string aetid)
- {
- AssetDescription ad = new();
- ad.AssetPath = null;
- ad.AssetArchiveVirtualPath = null;
- string path;
- if (Type == GameType.EldenRing)
- {
- path = GetOverridenFilePath($@"asset\aet\{aetid.Substring(0, 6)}\{aetid}.tpf.dcx");
- }
- else if (Type is GameType.ArmoredCoreVI)
- {
- path = GetOverridenFilePath($@"\asset\environment\texture\{aetid}.tpf.dcx");
- }
- else
- {
- throw new NotSupportedException();
- }
-
- if (path != null)
- {
- ad.AssetPath = path;
- ad.AssetArchiveVirtualPath = $@"aet/{aetid}/tex";
- }
-
- return ad;
- }
-
- public List GetPartsModels()
- {
- try
- {
- HashSet parts = new();
- List ret = new();
-
- var modelDir = @"\parts";
- var modelExt = @".partsbnd.dcx";
- if (Type == GameType.DarkSoulsPTDE)
- {
- modelExt = ".partsbnd";
- }
- else if (Type == GameType.DarkSoulsIISOTFS)
- {
- modelDir = @"\model\parts";
- modelExt = ".bnd";
- var partsGatheredFiles =
- Directory.GetFiles(GameRootDirectory + modelDir, "*", SearchOption.AllDirectories);
- foreach (var f in partsGatheredFiles)
- {
- if (!f.EndsWith("common.commonbnd.dcx") && !f.EndsWith("common_cloth.commonbnd.dcx") &&
- !f.EndsWith("facepreset.bnd"))
- {
- ret.Add(Path.GetFileNameWithoutExtension(f));
- }
- }
-
- return ret;
- }
-
- List partsFiles = Directory.GetFileSystemEntries(GameRootDirectory + modelDir, $@"*{modelExt}")
- .ToList();
- foreach (var f in partsFiles)
- {
- var name = Path.GetFileNameWithoutExtension(Path.GetFileNameWithoutExtension(f));
- ret.Add(name);
- parts.Add(name);
- }
-
- if (GameModDirectory != null && Directory.Exists(GameModDirectory + modelDir))
- {
- partsFiles = Directory.GetFileSystemEntries(GameModDirectory + modelDir, $@"*{modelExt}").ToList();
- foreach (var f in partsFiles)
- {
- var name = Path.GetFileNameWithoutExtension(Path.GetFileNameWithoutExtension(f));
- if (!parts.Contains(name))
- {
- ret.Add(name);
- parts.Add(name);
- }
- }
- }
-
- return ret;
- }
- catch (DirectoryNotFoundException e)
- {
- // Game likely isn't UXM unpacked
- return new List();
- }
- }
-
- public AssetDescription GetPartsModel(string part)
- {
- AssetDescription ret = new();
- ret.AssetName = part;
- ret.AssetArchiveVirtualPath = $@"parts/{part}/model";
- if (Type == GameType.DarkSoulsIISOTFS)
- {
- ret.AssetVirtualPath = $@"parts/{part}/model/{part}.flv";
- }
- else if (Type is GameType.DarkSoulsPTDE)
- {
- ret.AssetVirtualPath = $@"parts/{part}/model/{part.ToUpper()}.flver";
- }
- else
- {
- ret.AssetVirtualPath = $@"parts/{part}/model/{part}.flver";
- }
-
- return ret;
- }
-
- public AssetDescription GetPartTextures(string partsId)
- {
- AssetDescription ad = new();
- ad.AssetArchiveVirtualPath = null;
- ad.AssetPath = null;
- if (Type == GameType.ArmoredCoreVI)
- {
- string path;
- if (partsId.Substring(0, 2) == "wp")
- {
- string id;
- if (partsId.EndsWith("_l"))
- {
- id = partsId[..^2].Split("_").Last();
- path = GetOverridenFilePath($@"parts\wp_{id}_l.tpf.dcx");
- }
- else
- {
- id = partsId.Split("_").Last();
- path = GetOverridenFilePath($@"parts\wp_{id}.tpf.dcx");
- }
- }
- else
- {
- path = GetOverridenFilePath($@"parts\{partsId}_u.tpf.dcx");
- }
-
- if (path != null)
- {
- ad.AssetPath = path;
- ad.AssetVirtualPath = $@"parts/{partsId}/tex";
- }
- }
- else if (Type == GameType.EldenRing)
- {
- // Maybe add an option down the line to load lower quality
- var path = GetOverridenFilePath($@"parts\{partsId}.partsbnd.dcx");
- if (path != null)
- {
- ad.AssetPath = path;
- ad.AssetArchiveVirtualPath = $@"parts/{partsId}/tex";
- }
- }
- else if (Type == GameType.DarkSoulsIII || Type == GameType.Sekiro)
- {
- var path = GetOverridenFilePath($@"parts\{partsId}.partsbnd.dcx");
- if (path != null)
- {
- ad.AssetPath = path;
- ad.AssetArchiveVirtualPath = $@"parts/{partsId}/tex";
- }
- }
- else if (Type == GameType.Bloodborne)
- {
- var path = GetOverridenFilePath($@"parts\{partsId}.partsbnd.dcx");
- if (path != null)
- {
- ad.AssetPath = path;
- ad.AssetVirtualPath = $@"parts/{partsId}/tex";
- }
- }
- else if (Type == GameType.DarkSoulsPTDE)
- {
- var path = GetOverridenFilePath($@"parts\{partsId}.partsbnd");
- if (path != null)
- {
- ad.AssetPath = path;
- ad.AssetArchiveVirtualPath = $@"parts/{partsId}/tex";
- }
- }
- else if (Type == GameType.DemonsSouls)
- {
- var path = GetOverridenFilePath($@"parts\{partsId}.partsbnd.dcx");
- if (path != null)
- {
- ad.AssetPath = path;
- ad.AssetArchiveVirtualPath = $@"parts/{partsId}/tex";
- }
- }
-
- return ad;
- }
-
- public AssetDescription GetNullAsset()
- {
- AssetDescription ret = new();
- ret.AssetPath = "null";
- ret.AssetName = "null";
- ret.AssetArchiveVirtualPath = "null";
- ret.AssetVirtualPath = "null";
- return ret;
- }
-
- ///
- /// Converts a virtual path to an actual filesystem path. Only resolves virtual paths up to the bnd level,
- /// which the remaining string is output for additional handling
+ /// Converts a virtual path to an actual filesystem path. Only resolves virtual paths up to the bnd level,
+ /// which the remaining string is output for additional handling
///
///
///
- public string VirtualToRealPath(string virtualPath, out string bndpath)
- {
- var pathElements = virtualPath.Split('/');
- Regex mapRegex = new(@"^m\d{2}_\d{2}_\d{2}_\d{2}$");
- var ret = "";
-
- // Parse the virtual path with a DFA and convert it to a game path
- var i = 0;
- if (pathElements[i].Equals("map"))
- {
- i++;
- if (pathElements[i].Equals("tex"))
- {
- i++;
- if (Type == GameType.DarkSoulsIISOTFS)
- {
- var mid = pathElements[i];
- i++;
- var id = pathElements[i];
- if (id == "tex")
- {
- bndpath = "";
- return GetAssetPath($@"model\map\t{mid.Substring(1)}.tpfbhd");
- }
- }
- else if (Type == GameType.DemonsSouls)
- {
- var mid = pathElements[i];
- i++;
- bndpath = "";
- return GetAssetPath($@"map\{mid}\{mid}_{pathElements[i]}.tpf.dcx");
- }
- else
- {
- var mid = pathElements[i];
- i++;
- bndpath = "";
- if (pathElements[i] == "env")
- {
- if (Type == GameType.DarkSoulsRemastered)
- {
- return GetAssetPath($@"map\{mid}\GI_EnvM_{mid}.tpf.dcx");
- }
-
- return GetAssetPath($@"map\{mid}\{mid}_envmap.tpf.dcx");
- }
-
- return GetAssetPath($@"map\{mid}\{mid}_{pathElements[i]}.tpfbhd");
- }
- }
- else if (mapRegex.IsMatch(pathElements[i]))
- {
- var mapid = pathElements[i];
- i++;
- if (pathElements[i].Equals("model"))
- {
- i++;
- bndpath = "";
- if (Type == GameType.DarkSoulsPTDE)
- {
- return GetAssetPath($@"map\{mapid}\{pathElements[i]}.flver");
- }
-
- if (Type == GameType.DarkSoulsRemastered)
- {
- return GetAssetPath($@"map\{mapid}\{pathElements[i]}.flver.dcx");
- }
-
- if (Type == GameType.DarkSoulsIISOTFS)
- {
- return GetAssetPath($@"model\map\{mapid}.mapbhd");
- }
-
- if (Type == GameType.Bloodborne || Type == GameType.DemonsSouls)
- {
- return GetAssetPath($@"map\{mapid}\{pathElements[i]}.flver.dcx");
- }
-
- if (Type == GameType.EldenRing)
- {
- return GetAssetPath($@"map\{mapid.Substring(0, 3)}\{mapid}\{pathElements[i]}.mapbnd.dcx");
- }
-
- if (Type == GameType.ArmoredCoreVI)
- {
- return GetAssetPath($@"map\{mapid.Substring(0, 3)}\{mapid}\{pathElements[i]}.mapbnd.dcx");
- }
-
- return GetAssetPath($@"map\{mapid}\{pathElements[i]}.mapbnd.dcx");
- }
-
- if (pathElements[i].Equals("hit"))
- {
- i++;
- var hittype = pathElements[i];
- i++;
- if (Type == GameType.DarkSoulsPTDE || Type == GameType.DemonsSouls)
- {
- bndpath = "";
- return GetAssetPath($@"map\{mapid}\{pathElements[i]}");
- }
-
- if (Type == GameType.DarkSoulsIISOTFS)
- {
- bndpath = "";
- return GetAssetPath($@"model\map\h{mapid.Substring(1)}.hkxbhd");
- }
-
- if (Type == GameType.DarkSoulsIII || Type == GameType.Bloodborne)
- {
- bndpath = "";
- if (hittype == "lo")
- {
- return GetAssetPath($@"map\{mapid}\l{mapid.Substring(1)}.hkxbhd");
- }
-
- return GetAssetPath($@"map\{mapid}\h{mapid.Substring(1)}.hkxbhd");
- }
-
- bndpath = "";
- return null;
- }
-
- if (pathElements[i].Equals("nav"))
- {
- i++;
- if (Type == GameType.DarkSoulsPTDE || Type == GameType.DemonsSouls ||
- Type == GameType.DarkSoulsRemastered)
- {
- if (i < pathElements.Length)
- {
- bndpath = $@"{pathElements[i]}";
- }
- else
- {
- bndpath = "";
- }
-
- if (Type == GameType.DarkSoulsRemastered)
- {
- return GetAssetPath($@"map\{mapid}\{mapid}.nvmbnd.dcx");
- }
-
- return GetAssetPath($@"map\{mapid}\{mapid}.nvmbnd");
- }
-
- if (Type == GameType.DarkSoulsIII)
- {
- bndpath = "";
- return GetAssetPath($@"map\{mapid}\{mapid}.nvmhktbnd.dcx");
- }
-
- bndpath = "";
- return null;
- }
- }
- }
- else if (pathElements[i].Equals("chr"))
- {
- i++;
- var chrid = pathElements[i];
- i++;
- if (pathElements[i].Equals("model"))
- {
- bndpath = "";
- if (Type == GameType.DarkSoulsPTDE)
- {
- return GetOverridenFilePath($@"chr\{chrid}.chrbnd");
- }
-
- if (Type == GameType.DarkSoulsIISOTFS)
- {
- return GetOverridenFilePath($@"model\chr\{chrid}.bnd");
- }
-
- if (Type == GameType.DemonsSouls)
- {
- return GetOverridenFilePath($@"chr\{chrid}\{chrid}.chrbnd.dcx");
- }
-
- return GetOverridenFilePath($@"chr\{chrid}.chrbnd.dcx");
- }
-
- if (pathElements[i].Equals("tex"))
- {
- bndpath = "";
- return GetChrTexturePath(chrid);
- }
- }
- else if (pathElements[i].Equals("obj"))
- {
- i++;
- var objid = pathElements[i];
- i++;
- if (pathElements[i].Equals("model") || pathElements[i].Equals("tex"))
- {
- bndpath = "";
- if (Type == GameType.DarkSoulsPTDE)
- {
- return GetOverridenFilePath($@"obj\{objid}.objbnd");
- }
-
- if (Type == GameType.DarkSoulsIISOTFS)
- {
- return GetOverridenFilePath($@"model\obj\{objid}.bnd");
- }
-
- if (Type == GameType.EldenRing)
- {
- // Derive subfolder path from model name (all vanilla AEG are within subfolders)
- if (objid.Length >= 6)
- {
- return GetOverridenFilePath($@"asset\aeg\{objid.Substring(0, 6)}\{objid}.geombnd.dcx");
- }
-
- return null;
- }
-
- if (Type == GameType.ArmoredCoreVI)
- {
- if (objid.Length >= 6)
- {
- return GetOverridenFilePath($@"asset\environment\geometry\{objid}.geombnd.dcx");
- }
-
- return null;
- }
-
- return GetOverridenFilePath($@"obj\{objid}.objbnd.dcx");
- }
- }
- else if (pathElements[i].Equals("parts"))
- {
- i++;
- var partsId = pathElements[i];
- i++;
- if (pathElements[i].Equals("model") || pathElements[i].Equals("tex"))
- {
- bndpath = "";
- if (Type == GameType.DarkSoulsPTDE || Type == GameType.DarkSoulsRemastered)
- {
- return GetOverridenFilePath($@"parts\{partsId}.partsbnd");
- }
-
- if (Type == GameType.DarkSoulsIISOTFS)
- {
- var partType = "";
- switch (partsId.Substring(0, 2))
- {
- case "as":
- partType = "accessories";
- break;
- case "am":
- partType = "arm";
- break;
- case "bd":
- partType = "body";
- break;
- case "fa":
- case "fc":
- case "fg":
- partType = "face";
- break;
- case "hd":
- partType = "head";
- break;
- case "leg":
- partType = "leg";
- break;
- case "sd":
- partType = "shield";
- break;
- case "wp":
- partType = "weapon";
- break;
- }
-
- return GetOverridenFilePath($@"model\parts\{partType}\{partsId}.bnd");
- }
-
- if (Type == GameType.EldenRing)
- {
- return GetOverridenFilePath($@"parts\{partsId}\{partsId}.partsbnd.dcx");
- }
-
- if (Type == GameType.ArmoredCoreVI && pathElements[i].Equals("tex"))
- {
- string path;
- if (partsId.Substring(0, 2) == "wp")
- {
- string id;
- if (partsId.EndsWith("_l"))
- {
- id = partsId[..^2].Split("_").Last();
- path = GetOverridenFilePath($@"parts\wp_{id}_l.tpf.dcx");
- }
- else
- {
- id = partsId.Split("_").Last();
- path = GetOverridenFilePath($@"parts\wp_{id}.tpf.dcx");
- }
- }
- else
- {
- path = GetOverridenFilePath($@"parts\{partsId}_u.tpf.dcx");
- }
-
- return path;
- }
-
- return GetOverridenFilePath($@"parts\{partsId}.partsbnd.dcx");
- }
- }
-
- bndpath = virtualPath;
- return null;
- }
-
- public string GetBinderVirtualPath(string virtualPathToBinder, string binderFilePath)
- {
- var filename = Path.GetFileNameWithoutExtension($@"{binderFilePath}.blah");
- if (filename.Length > 0)
- {
- filename = $@"{virtualPathToBinder}/{filename}";
- }
- else
- {
- filename = virtualPathToBinder;
- }
-
- return filename;
- }
+ public string VirtualToRealPath(string virtualPath, out string bndpath) => Locator.ActiveProject.AssetLocator.VirtualToRealPath(virtualPath, out bndpath);
}
diff --git a/src/StudioCore/AssetUtils.cs b/src/StudioCore/AssetUtils.cs
new file mode 100644
index 000000000..356da967f
--- /dev/null
+++ b/src/StudioCore/AssetUtils.cs
@@ -0,0 +1,216 @@
+using SoulsFormats;
+using StudioCore.Editor;
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.IO;
+using System.Linq;
+using System.Text.RegularExpressions;
+
+namespace StudioCore;
+
+///
+/// Helper functions and statics for Project/Assetlocator
+///
+public class AssetUtils
+{
+ public static readonly string GameExecutableFilter;
+ public static readonly string ProjectJsonFilter;
+ public static readonly string RegulationBinFilter;
+ public static readonly string Data0Filter;
+ public static readonly string ParamBndDcxFilter;
+ public static readonly string ParamBndFilter;
+ public static readonly string EncRegulationFilter;
+ public static readonly string ParamLooseFilter;
+ public static readonly string CsvFilter;
+ public static readonly string TxtFilter;
+ public static readonly string FmgJsonFilter;
+
+ static AssetUtils()
+ {
+ // These patterns are meant to be passed directly into PlatformUtils.
+ // Everything about their handling should be done there.
+
+ // Game Executable (.EXE, EBOOT.BIN)|*.EXE*;*EBOOT.BIN*
+ // Windows executable (*.EXE)|*.EXE*
+ // Playstation executable (*.BIN)|*.BIN*
+ GameExecutableFilter = "exe,bin";
+ // Project file (project.json)|PROJECT.JSON
+ ProjectJsonFilter = "json";
+ // Regulation file (regulation.bin)|REGULATION.BIN
+ RegulationBinFilter = "bin";
+ // Data file (Data0.bdt)|DATA0.BDT
+ Data0Filter = "bdt";
+ // ParamBndDcx (gameparam.parambnd.dcx)|GAMEPARAM.PARAMBND.DCX
+ ParamBndDcxFilter = "parambnd.dcx";
+ // ParamBnd (gameparam.parambnd)|GAMEPARAM.PARAMBND
+ ParamBndFilter = "parambnd";
+ // Enc_RegBndDcx (enc_regulation.bnd.dcx)|ENC_REGULATION.BND.DCX
+ EncRegulationFilter = "bnd.dcx";
+ // Loose Param file (*.Param)|*.Param
+ ParamLooseFilter = "param";
+ // CSV file (*.csv)|*.csv
+ CsvFilter = "csv";
+ // Text file (*.txt)|*.txt
+ TxtFilter = "txt";
+ // Exported FMGs (*.fmg.json)|*.fmg.json
+ FmgJsonFilter = "fmg.json";
+ // All file filter is implicitly added by NFD. Ideally this is used explicitly.
+ // All files|*.*
+ }
+ public static GameType GetGameTypeForExePath(string exePath)
+ {
+ var type = GameType.Undefined;
+ if (exePath.ToLower().Contains("darksouls.exe"))
+ {
+ type = GameType.DarkSoulsPTDE;
+ }
+ else if (exePath.ToLower().Contains("darksoulsremastered.exe"))
+ {
+ type = GameType.DarkSoulsRemastered;
+ }
+ else if (exePath.ToLower().Contains("darksoulsii.exe"))
+ {
+ type = GameType.DarkSoulsIISOTFS;
+ }
+ else if (exePath.ToLower().Contains("darksoulsiii.exe"))
+ {
+ type = GameType.DarkSoulsIII;
+ }
+ else if (exePath.ToLower().Contains("eboot.bin"))
+ {
+ var path = Path.GetDirectoryName(exePath);
+ if (Directory.Exists($@"{path}\dvdroot_ps4"))
+ {
+ type = GameType.Bloodborne;
+ }
+ else
+ {
+ type = GameType.DemonsSouls;
+ }
+ }
+ else if (exePath.ToLower().Contains("sekiro.exe"))
+ {
+ type = GameType.Sekiro;
+ }
+ else if (exePath.ToLower().Contains("eldenring.exe"))
+ {
+ type = GameType.EldenRing;
+ }
+ else if (exePath.ToLower().Contains("armoredcore6.exe"))
+ {
+ type = GameType.ArmoredCoreVI;
+ }
+
+ return type;
+ }
+
+ public static bool CheckFilesExpanded(string gamepath, GameType game)
+ {
+ if (game == GameType.EldenRing)
+ {
+ if (!Directory.Exists($@"{gamepath}\map"))
+ {
+ return false;
+ }
+
+ if (!Directory.Exists($@"{gamepath}\asset"))
+ {
+ return false;
+ }
+ }
+
+ if (game is GameType.DarkSoulsPTDE or GameType.DarkSoulsIII or GameType.Sekiro)
+ {
+ if (!Directory.Exists($@"{gamepath}\map"))
+ {
+ return false;
+ }
+
+ if (!Directory.Exists($@"{gamepath}\obj"))
+ {
+ return false;
+ }
+ }
+
+ if (game == GameType.DarkSoulsIISOTFS)
+ {
+ if (!Directory.Exists($@"{gamepath}\map"))
+ {
+ return false;
+ }
+
+ if (!Directory.Exists($@"{gamepath}\model\obj"))
+ {
+ return false;
+ }
+ }
+
+ if (game == GameType.ArmoredCoreVI)
+ {
+ if (!Directory.Exists($@"{gamepath}\map"))
+ {
+ return false;
+ }
+
+ if (!Directory.Exists($@"{gamepath}\asset"))
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ public static string GetGameIDForDir(GameType Type)
+ {
+ switch (Type)
+ {
+ case GameType.DemonsSouls:
+ return "DES";
+ case GameType.DarkSoulsPTDE:
+ return "DS1";
+ case GameType.DarkSoulsRemastered:
+ return "DS1R";
+ case GameType.DarkSoulsIISOTFS:
+ return "DS2S";
+ case GameType.Bloodborne:
+ return "BB";
+ case GameType.DarkSoulsIII:
+ return "DS3";
+ case GameType.Sekiro:
+ return "SDT";
+ case GameType.EldenRing:
+ return "ER";
+ case GameType.ArmoredCoreVI:
+ return "AC6";
+ default:
+ throw new Exception("Game type not set");
+ }
+ }
+
+ public static AssetDescription GetNullAsset()
+ {
+ AssetDescription ret = new();
+ ret.AssetPath = "null";
+ ret.AssetName = "null";
+ ret.AssetArchiveVirtualPath = "null";
+ ret.AssetVirtualPath = "null";
+ return ret;
+ }
+
+ public static string GetBinderVirtualPath(string virtualPathToBinder, string binderFilePath)
+ {
+ var filename = Path.GetFileNameWithoutExtension($@"{binderFilePath}.blah");
+ if (filename.Length > 0)
+ {
+ filename = $@"{virtualPathToBinder}/{filename}";
+ }
+ else
+ {
+ filename = virtualPathToBinder;
+ }
+
+ return filename;
+ }
+}
diff --git a/src/StudioCore/Editor/Action.cs b/src/StudioCore/Editor/Action.cs
index f3762df93..466095945 100644
--- a/src/StudioCore/Editor/Action.cs
+++ b/src/StudioCore/Editor/Action.cs
@@ -309,10 +309,10 @@ public override ActionEvent Undo()
public class DuplicateFMGEntryAction : EditorAction
{
- private readonly FMGBank.EntryGroup EntryGroup;
- private FMGBank.EntryGroup NewEntryGroup;
+ private readonly FMGEntryGroup EntryGroup;
+ private FMGEntryGroup NewEntryGroup;
- public DuplicateFMGEntryAction(FMGBank.EntryGroup entryGroup)
+ public DuplicateFMGEntryAction(FMGEntryGroup entryGroup)
{
EntryGroup = entryGroup;
}
@@ -333,10 +333,10 @@ public override ActionEvent Undo()
public class DeleteFMGEntryAction : EditorAction
{
- private FMGBank.EntryGroup BackupEntryGroup = new();
- private FMGBank.EntryGroup EntryGroup;
+ private FMGEntryGroup BackupEntryGroup = new();
+ private FMGEntryGroup EntryGroup;
- public DeleteFMGEntryAction(FMGBank.EntryGroup entryGroup)
+ public DeleteFMGEntryAction(FMGEntryGroup entryGroup)
{
EntryGroup = entryGroup;
}
diff --git a/src/StudioCore/Editor/EditorDecorations.cs b/src/StudioCore/Editor/EditorDecorations.cs
index 46c1b3f9a..5c8c06dd1 100644
--- a/src/StudioCore/Editor/EditorDecorations.cs
+++ b/src/StudioCore/Editor/EditorDecorations.cs
@@ -259,21 +259,21 @@ public static void ParamRefsSelectables(ParamBank bank, List paramRefs
return rows;
}
- private static List<(string, FMGBank.EntryGroup)> resolveFMGRefs(List fmgRefs, Param.Row context,
+ private static List<(string, FMGEntryGroup)> resolveFMGRefs(List fmgRefs, Param.Row context,
dynamic oldval)
{
- if (!FMGBank.IsLoaded)
+ if (!Locator.ActiveProject.FMGBank.IsLoaded)
{
- return new List<(string, FMGBank.EntryGroup)>();
+ return new List<(string, FMGEntryGroup)>();
}
return fmgRefs.Where(rf =>
{
Param.Cell? c = context?[rf.conditionField];
return context == null || c == null || Convert.ToInt32(c.Value.Value) == rf.conditionValue;
- }).Select(rf => FMGBank.FmgInfoBank.Find(x => x.Name == rf.fmg))
+ }).Select(rf => Locator.ActiveProject.FMGBank.FmgInfoBank.FirstOrDefault(x => x.Name == rf.fmg))
.Where(fmgi => fmgi != null)
- .Select(fmgi => (fmgi.Name, FMGBank.GenerateEntryGroup((int)oldval, fmgi)))
+ .Select(fmgi => (fmgi.Name, Locator.ActiveProject.FMGBank.GenerateEntryGroup((int)oldval, fmgi)))
.ToList();
}
@@ -282,11 +282,11 @@ public static void FmgRefSelectable(EditorScreen ownerScreen, List fmgNa
{
List textsToPrint = UICache.GetCached(ownerScreen, (int)oldval, "PARAM META FMGREF", () =>
{
- List<(string, FMGBank.EntryGroup)> refs = resolveFMGRefs(fmgNames, context, oldval);
+ List<(string, FMGEntryGroup)> refs = resolveFMGRefs(fmgNames, context, oldval);
return refs.Where(x => x.Item2 != null)
.Select(x =>
{
- FMGBank.EntryGroup group = x.Item2;
+ FMGEntryGroup group = x.Item2;
var toPrint = "";
if (!string.IsNullOrWhiteSpace(group.Title?.Text))
{
@@ -379,7 +379,7 @@ public static void VirtualParamRefSelectables(ParamBank bank, string virtualRefN
{
List matchedExtRefPath =
currentRef.paths.Select(x => string.Format(x, searchValue)).ToList();
- AssetLocator al = ParamBank.PrimaryBank.AssetLocator;
+ AssetLocator al = Locator.AssetLocator;
ExtRefItem(context, fieldName, $"modded {currentRef.name}", matchedExtRefPath, al.GameModDirectory,
cacheOwner);
ExtRefItem(context, fieldName, $"vanilla {currentRef.name}", matchedExtRefPath,
@@ -464,7 +464,7 @@ public static void ParamRefEnumQuickLink(ParamBank bank, object oldval, List reftypes, Param.R
ActionManager executor)
{
// Add Goto statements
- List<(string, FMGBank.EntryGroup)> refs = resolveFMGRefs(reftypes, context, oldval);
+ List<(string, FMGEntryGroup)> refs = resolveFMGRefs(reftypes, context, oldval);
var ctrlDown = InputTracker.GetKey(Key.ControlLeft) || InputTracker.GetKey(Key.ControlRight);
- foreach ((var name, FMGBank.EntryGroup group) in refs)
+ foreach ((var name, FMGEntryGroup group) in refs)
{
if (ImGui.Selectable($@"Goto {name} Text"))
{
diff --git a/src/StudioCore/Editor/ProjectSettings.cs b/src/StudioCore/Editor/ProjectSettings.cs
index c0689984c..495fe6974 100644
--- a/src/StudioCore/Editor/ProjectSettings.cs
+++ b/src/StudioCore/Editor/ProjectSettings.cs
@@ -1,4 +1,5 @@
-using StudioCore.Platform;
+using Silk.NET.Core;
+using StudioCore.Platform;
using System;
using System.Collections.Generic;
using System.IO;
@@ -39,8 +40,6 @@ public class ProjectSettings
///
public bool UseLooseParams { get; set; } = false;
- public bool PartialParams { get; set; } = false;
-
// FMG editor
public string LastFmgLanguageUsed { get; set; } = "";
@@ -79,6 +78,24 @@ public static ProjectSettings Deserialize(string path)
return null;
}
}
+
+ internal ProjectSettings CopyAndAssumeFromModDir(string moddir)
+ {
+ ProjectSettings newProj = new();
+ newProj.ProjectName = Path.GetFileName(Path.GetDirectoryName(moddir));
+ newProj.GameRoot = GameRoot;
+ newProj.GameType = GameType;
+ switch (newProj.GameType)
+ {
+ case GameType.DarkSoulsIISOTFS:
+ newProj.UseLooseParams = File.Exists($@"{moddir}\Param\AreaParam.param");
+ break;
+ case GameType.DarkSoulsIII:
+ newProj.UseLooseParams = File.Exists($@"{moddir}\param\gameparam\gameparam_dlc2.parambnd.dcx");
+ break;
+ }
+ return newProj;
+ }
}
public class NewProjectOptions
diff --git a/src/StudioCore/Interface/AliasUtils.cs b/src/StudioCore/Interface/AliasUtils.cs
index 886038d0c..01906485d 100644
--- a/src/StudioCore/Interface/AliasUtils.cs
+++ b/src/StudioCore/Interface/AliasUtils.cs
@@ -231,9 +231,9 @@ public static string FindPlayerCharacterName(Entity e, string modelName)
var term = c.Value.ToParamEditorString();
var result = term;
- if (FMGBank.IsLoaded)
+ if (Locator.ActiveProject.FMGBank.IsLoaded)
{
- var matchingFmgInfo = FMGBank.FmgInfoBank.Find(x => x.Name.Contains("Character"));
+ var matchingFmgInfo = Locator.ActiveProject.FMGBank.FmgInfoBank.First(x => x.Name.Contains("Character"));
if (matchingFmgInfo != null)
{
diff --git a/src/StudioCore/MapStudioNew.cs b/src/StudioCore/MapStudioNew.cs
index 113a3cbd6..23ed73aac 100644
--- a/src/StudioCore/MapStudioNew.cs
+++ b/src/StudioCore/MapStudioNew.cs
@@ -41,8 +41,6 @@ public class MapStudioNew
public static bool LowRequirementsMode;
- private readonly AssetLocator _assetLocator;
-
private readonly IGraphicsContext _context;
private readonly List _editors;
@@ -91,21 +89,20 @@ public unsafe MapStudioNew(IGraphicsContext context, string version)
_context.Window.Title = _programTitle;
PlatformUtils.InitializeWindows(context.Window.SdlWindowHandle);
- _assetLocator = new AssetLocator();
- Locator.AssetLocator = _assetLocator; // Yeah, I'm not passing this as a parameter anymore :P
+ Locator.AssetLocator = new AssetLocator();
// Banks
ModelAliasBank.Bank = new AliasBank(AliasType.Model);
MapAliasBank.Bank = new AliasBank(AliasType.Map);
- MsbEditorScreen msbEditor = new(_context.Window, _context.Device, _assetLocator);
- ModelEditorScreen modelEditor = new(_context.Window, _context.Device, _assetLocator);
- ParamEditorScreen paramEditor = new(_context.Window, _context.Device, _assetLocator);
- TextEditorScreen textEditor = new(_context.Window, _context.Device, _assetLocator);
+ MsbEditorScreen msbEditor = new(_context.Window, _context.Device);
+ ModelEditorScreen modelEditor = new(_context.Window, _context.Device);
+ ParamEditorScreen paramEditor = new(_context.Window, _context.Device);
+ TextEditorScreen textEditor = new(_context.Window, _context.Device);
_editors = new List { msbEditor, modelEditor, paramEditor, textEditor };
_focusedEditor = msbEditor;
- _soapstoneService = new SoapstoneService(_version, _assetLocator, msbEditor);
+ _soapstoneService = new SoapstoneService(_version, msbEditor);
_settingsMenu.MsbEditor = msbEditor;
_settingsMenu.ModelEditor = modelEditor;
@@ -114,11 +111,6 @@ public unsafe MapStudioNew(IGraphicsContext context, string version)
HelpWindow = new HelpWindow();
- ParamBank.PrimaryBank.SetAssetLocator(_assetLocator);
- ParamBank.VanillaBank.SetAssetLocator(_assetLocator);
- FMGBank.SetAssetLocator(_assetLocator);
- MtdBank.LoadMtds(_assetLocator);
-
ImGui.GetIO()->ConfigFlags |= ImGuiConfigFlags.NavEnableKeyboard;
SetupFonts();
_context.ImguiRenderer.OnSetupDone();
@@ -403,7 +395,7 @@ public void CrashShutdown()
private void ChangeProjectSettings(ProjectSettings newsettings, string moddir, NewProjectOptions options)
{
_projectSettings = newsettings;
- _assetLocator.SetFromProjectSettings(newsettings, moddir);
+ Locator.ActiveProject = new Project(newsettings, moddir);
_settingsMenu.ProjSettings = _projectSettings;
// Banks
@@ -412,6 +404,7 @@ private void ChangeProjectSettings(ProjectSettings newsettings, string moddir, N
ParamBank.ReloadParams(newsettings, options);
MtdBank.ReloadMtds();
+ FMGBank.ReloadFMGs();
foreach (EditorScreen editor in _editors)
{
@@ -477,7 +470,7 @@ public void UnapplyStyle()
private void DumpFlverLayouts()
{
- if (PlatformUtils.Instance.SaveFileDialog("Save Flver layout dump", new[] { AssetLocator.TxtFilter },
+ if (PlatformUtils.Instance.SaveFileDialog("Save Flver layout dump", new[] { AssetUtils.TxtFilter },
out var path))
{
using (StreamWriter file = new(path))
@@ -528,11 +521,11 @@ private bool AttemptLoadProject(ProjectSettings settings, string filename, NewPr
{
if (PlatformUtils.Instance.OpenFileDialog(
$"Select executable for {settings.GameType}...",
- new[] { AssetLocator.GameExecutableFilter },
+ new[] { AssetUtils.GameExecutableFilter },
out var path))
{
settings.GameRoot = path;
- GameType gametype = _assetLocator.GetGameTypeForExePath(settings.GameRoot);
+ GameType gametype = AssetUtils.GetGameTypeForExePath(settings.GameRoot);
if (gametype == settings.GameType)
{
success = true;
@@ -560,7 +553,7 @@ private bool AttemptLoadProject(ProjectSettings settings, string filename, NewPr
if (success)
{
- if (!_assetLocator.CheckFilesExpanded(settings.GameRoot, settings.GameType))
+ if (!AssetUtils.CheckFilesExpanded(settings.GameRoot, settings.GameType))
{
if (!GameNotUnpackedWarning(settings.GameType))
{
@@ -660,12 +653,12 @@ public void AttemptSaveOnCrash()
}
}
- var success = _assetLocator.CreateRecoveryProject();
+ var success = Locator.AssetLocator.CreateRecoveryProject();
if (success)
{
SaveAll();
PlatformUtils.Instance.MessageBox(
- $"Attempted to save project files to {_assetLocator.GameModDirectory} for manual recovery.\n" +
+ $"Attempted to save project files to {Locator.AssetLocator.GameModDirectory} for manual recovery.\n" +
"You must manually replace your project files with these recovery files should you wish to restore them.\n" +
"Given the program has crashed, these files may be corrupt and you should backup your last good saved\n" +
"files before attempting to use these.",
@@ -807,7 +800,7 @@ private unsafe void Update(float deltaseconds)
{
if (PlatformUtils.Instance.OpenFileDialog(
"Choose the project json file",
- new[] { AssetLocator.ProjectJsonFilter },
+ new[] { AssetUtils.ProjectJsonFilter },
out var path))
{
ProjectSettings settings = ProjectSettings.Deserialize(path);
@@ -872,13 +865,13 @@ private unsafe void Update(float deltaseconds)
{
if (ImGui.MenuItem("Open Project Folder", "", false, !TaskManager.AnyActiveTasks()))
{
- var projectPath = _assetLocator.GameModDirectory;
+ var projectPath = Locator.AssetLocator.GameModDirectory;
Process.Start("explorer.exe", projectPath);
}
if (ImGui.MenuItem("Open Game Folder", "", false, !TaskManager.AnyActiveTasks()))
{
- var gamePath = _assetLocator.GameRootDirectory;
+ var gamePath = Locator.AssetLocator.GameRootDirectory;
Process.Start("explorer.exe", gamePath);
}
@@ -939,17 +932,17 @@ private unsafe void Update(float deltaseconds)
if (ImGui.MenuItem("MSBE read/write test"))
{
- MSBReadWrite.Run(_assetLocator);
+ MSBReadWrite.Run(Locator.AssetLocator);
}
if (ImGui.MenuItem("MSB_AC6 Read/Write Test"))
{
- MSB_AC6_Read_Write.Run(_assetLocator);
+ MSB_AC6_Read_Write.Run(Locator.AssetLocator);
}
if (ImGui.MenuItem("BTL read/write test"))
{
- BTLReadWrite.Run(_assetLocator);
+ BTLReadWrite.Run(Locator.AssetLocator);
}
if (ImGui.MenuItem("Insert unique rows IDs into params"))
@@ -1089,7 +1082,7 @@ private unsafe void Update(float deltaseconds)
_newProjectOptions.settings.GameRoot = gname;
}
- _newProjectOptions.settings.GameType = _assetLocator.GetGameTypeForExePath(gname);
+ _newProjectOptions.settings.GameType = AssetUtils.GetGameTypeForExePath(gname);
if (_newProjectOptions.settings.GameType == GameType.Bloodborne)
{
@@ -1102,11 +1095,11 @@ private unsafe void Update(float deltaseconds)
{
if (PlatformUtils.Instance.OpenFileDialog(
"Select executable for the game you want to mod...",
- new[] { AssetLocator.GameExecutableFilter },
+ new[] { AssetUtils.GameExecutableFilter },
out var path))
{
_newProjectOptions.settings.GameRoot = Path.GetDirectoryName(path);
- _newProjectOptions.settings.GameType = _assetLocator.GetGameTypeForExePath(path);
+ _newProjectOptions.settings.GameType = AssetUtils.GetGameTypeForExePath(path);
if (_newProjectOptions.settings.GameType == GameType.Bloodborne)
{
@@ -1175,25 +1168,6 @@ private unsafe void Update(float deltaseconds)
_newProjectOptions.settings.UseLooseParams = looseparams;
}
}
- else if (FeatureFlags.EnablePartialParam && _newProjectOptions.settings.GameType == GameType.EldenRing)
- {
- ImGui.NewLine();
- ImGui.AlignTextToFramePadding();
- ImGui.Text(@"Save partial regulation: ");
- ImGui.SameLine();
- Utils.ImGuiGenericHelpPopup("TODO (disbababled)", "##Help_PartialParam",
- "TODO: why does this setting exist separately from loose params?");
- ImGui.SameLine();
- var partialReg = _newProjectOptions.settings.PartialParams;
- if (ImGui.Checkbox("##partialparams", ref partialReg))
- {
- _newProjectOptions.settings.PartialParams = partialReg;
- }
-
- ImGui.SameLine();
- ImGui.TextUnformatted(
- "Warning: partial params require merging before use in game.\nRow names on unchanged rows will be forgotten between saves");
- }
else if (_newProjectOptions.settings.GameType is GameType.ArmoredCoreVI)
{
//TODO AC6
@@ -1276,7 +1250,7 @@ private unsafe void Update(float deltaseconds)
}
var gameroot = _newProjectOptions.settings.GameRoot;
- if (!_assetLocator.CheckFilesExpanded(gameroot, _newProjectOptions.settings.GameType))
+ if (!AssetUtils.CheckFilesExpanded(gameroot, _newProjectOptions.settings.GameType))
{
if (!GameNotUnpackedWarning(_newProjectOptions.settings.GameType))
{
diff --git a/src/StudioCore/MsbEditor/ModelEditorScreen.cs b/src/StudioCore/MsbEditor/ModelEditorScreen.cs
index 3045bd8e5..0b0ee6cdc 100644
--- a/src/StudioCore/MsbEditor/ModelEditorScreen.cs
+++ b/src/StudioCore/MsbEditor/ModelEditorScreen.cs
@@ -33,8 +33,6 @@ public class ModelEditorScreen : EditorScreen, AssetBrowserEventHandler, SceneTr
private Task _loadingTask;
private MeshRenderableProxy _renderMesh;
-
- public AssetLocator AssetLocator;
public ActionManager EditorActionManager = new();
public Rectangle Rect;
public RenderScene RenderScene;
@@ -43,11 +41,9 @@ public class ModelEditorScreen : EditorScreen, AssetBrowserEventHandler, SceneTr
private bool ViewportUsingKeyboard;
private Sdl2Window Window;
- public ModelEditorScreen(Sdl2Window window, GraphicsDevice device, AssetLocator locator)
+ public ModelEditorScreen(Sdl2Window window, GraphicsDevice device)
{
Rect = window.Bounds;
- AssetLocator = locator;
- ResourceManager.Locator = AssetLocator;
Window = window;
if (device != null)
@@ -61,10 +57,10 @@ public ModelEditorScreen(Sdl2Window window, GraphicsDevice device, AssetLocator
Viewport = new NullViewport("Modeleditvp", EditorActionManager, _selection, Rect.Width, Rect.Height);
}
- _universe = new Universe(AssetLocator, RenderScene, _selection);
+ _universe = new Universe(RenderScene, _selection);
_sceneTree = new SceneTree(SceneTree.Configuration.ModelEditor, this, "modeledittree", _universe,
- _selection, EditorActionManager, Viewport, AssetLocator);
+ _selection, EditorActionManager, Viewport);
_propEditor = new PropertyEditor(EditorActionManager, _propCache);
ModelAssetBrowser = new AssetBrowserScreen(AssetBrowserSource.ModelEditor, _universe, RenderScene, _selection, EditorActionManager, this, Viewport);
@@ -240,7 +236,7 @@ public bool InputCaptured()
public void OnProjectChanged(ProjectSettings newSettings)
{
- if (AssetLocator.Type != GameType.Undefined)
+ if (Locator.AssetLocator.Type != GameType.Undefined)
{
ModelAssetBrowser.OnProjectChanged();
}
@@ -306,25 +302,25 @@ public void LoadModel(string modelid, ModelEditorModelType modelType, string map
switch (modelType)
{
case ModelEditorModelType.Character:
- asset = AssetLocator.GetChrModel(modelid);
- assettex = AssetLocator.GetChrTextures(modelid);
+ asset = Locator.AssetLocator.GetChrModel(modelid);
+ assettex = Locator.AssetLocator.GetChrTextures(modelid);
break;
case ModelEditorModelType.Object:
- asset = AssetLocator.GetObjModel(modelid);
- assettex = AssetLocator.GetObjTexture(modelid);
+ asset = Locator.AssetLocator.GetObjModel(modelid);
+ assettex = Locator.AssetLocator.GetObjTexture(modelid);
break;
case ModelEditorModelType.Parts:
- asset = AssetLocator.GetPartsModel(modelid);
- assettex = AssetLocator.GetPartTextures(modelid);
+ asset = Locator.AssetLocator.GetPartsModel(modelid);
+ assettex = Locator.AssetLocator.GetPartTextures(modelid);
break;
case ModelEditorModelType.MapPiece:
- asset = AssetLocator.GetMapModel(mapid, modelid);
- assettex = AssetLocator.GetNullAsset();
+ asset = Locator.AssetLocator.GetMapModel(mapid, modelid);
+ assettex = AssetUtils.GetNullAsset();
break;
default:
//Uh oh
- asset = AssetLocator.GetNullAsset();
- assettex = AssetLocator.GetNullAsset();
+ asset = AssetUtils.GetNullAsset();
+ assettex = AssetUtils.GetNullAsset();
break;
}
diff --git a/src/StudioCore/MsbEditor/MsbEditorScreen.cs b/src/StudioCore/MsbEditor/MsbEditorScreen.cs
index ac2a435a6..d9d6f6150 100644
--- a/src/StudioCore/MsbEditor/MsbEditorScreen.cs
+++ b/src/StudioCore/MsbEditor/MsbEditorScreen.cs
@@ -28,8 +28,6 @@ public class MsbEditorScreen : EditorScreen, SceneTreeEventHandler
private static readonly object _lock_PauseUpdate = new();
public Selection _selection = new Selection();
- public readonly AssetLocator AssetLocator;
-
private IModal _activeModal;
private int _createEntityMapIndex;
@@ -73,11 +71,9 @@ public class MsbEditorScreen : EditorScreen, SceneTreeEventHandler
private Sdl2Window Window;
- public MsbEditorScreen(Sdl2Window window, GraphicsDevice device, AssetLocator locator)
+ public MsbEditorScreen(Sdl2Window window, GraphicsDevice device)
{
Rect = window.Bounds;
- AssetLocator = locator;
- ResourceManager.Locator = AssetLocator;
Window = window;
if (device != null)
@@ -92,14 +88,14 @@ public MsbEditorScreen(Sdl2Window window, GraphicsDevice device, AssetLocator lo
Viewport = new NullViewport("Mapeditvp", EditorActionManager, _selection, Rect.Width, Rect.Height);
}
- Universe = new Universe(AssetLocator, RenderScene, _selection);
+ Universe = new Universe(RenderScene, _selection);
SceneTree = new SceneTree(SceneTree.Configuration.MapEditor, this, "mapedittree", Universe, _selection,
- EditorActionManager, Viewport, AssetLocator);
+ EditorActionManager, Viewport);
PropEditor = new PropertyEditor(EditorActionManager, _propCache);
DispGroupEditor = new DisplayGroupsEditor(RenderScene, _selection, EditorActionManager);
PropSearch = new SearchProperties(Universe, _propCache);
- NavMeshEditor = new NavmeshEditor(locator, RenderScene, _selection);
+ NavMeshEditor = new NavmeshEditor(RenderScene, _selection);
MapAssetBrowser = new AssetBrowserScreen(AssetBrowserSource.MapEditor, Universe, RenderScene, _selection, EditorActionManager, this, Viewport);
EditorActionManager.AddEventHandler(SceneTree);
@@ -529,7 +525,7 @@ public void DrawEditorMenu()
if (ImGui.BeginMenu("Create"))
{
- if (AssetLocator.Type is GameType.EldenRing)
+ if (Locator.ActiveProject.Type is GameType.EldenRing)
{
if (ImGui.Selectable("New Map"))
{
@@ -641,7 +637,7 @@ public void DrawEditorMenu()
ImGui.EndMenu();
}
- if (AssetLocator.Type is GameType.EldenRing)
+ if (Locator.ActiveProject.AssetLocator.Type is GameType.EldenRing)
{
if (ImGui.BeginMenu("Asset Prefabs"))
{
@@ -858,7 +854,7 @@ public void DrawEditorMenu()
{
var loadedMaps = Universe.LoadedObjectContainers.Values.Where(x => x != null);
- if (AssetLocator.Type is not GameType.DarkSoulsIISOTFS)
+ if (Locator.AssetLocator.Type is not GameType.DarkSoulsIISOTFS)
{
if (ImGui.BeginMenu("Render enemy patrol routes"))
{
@@ -910,7 +906,7 @@ public void DrawEditorMenu()
}
}
- if (AssetLocator.Type is GameType.DemonsSouls or
+ if (Locator.AssetLocator.Type is GameType.DemonsSouls or
GameType.DarkSoulsPTDE or GameType.DarkSoulsRemastered)
{
if (ImGui.BeginMenu("Regenerate MCP and MCG"))
@@ -1090,7 +1086,7 @@ public unsafe void OnGUI(string[] initcmd)
PatrolDrawManager.Generate(Universe);
}
- if (AssetLocator.Type is GameType.EldenRing)
+ if (Locator.ActiveProject != null && Locator.ActiveProject.AssetLocator.Type is GameType.EldenRing)
{
if (InputTracker.GetKeyDown(KeyBindings.Current.Map_AssetPrefabExport))
{
@@ -1253,7 +1249,7 @@ public unsafe void OnGUI(string[] initcmd)
// Not usable yet
if (FeatureFlags.EnableNavmeshBuilder)
{
- NavMeshEditor.OnGui(AssetLocator.Type);
+ NavMeshEditor.OnGui(Locator.AssetLocator.Type);
}
ResourceManager.OnGuiDrawTasks(Viewport.Width, Viewport.Height);
@@ -1396,7 +1392,7 @@ public void SetObjectModelForSelection(string modelName, string assetType, strin
if (assetType == "Chr")
{
- switch (AssetLocator.Type)
+ switch (Locator.AssetLocator.Type)
{
case GameType.DemonsSouls:
if (s.WrappedObject is MSBD.Part.Enemy)
@@ -1435,7 +1431,7 @@ public void SetObjectModelForSelection(string modelName, string assetType, strin
}
if (assetType == "Obj")
{
- switch (AssetLocator.Type)
+ switch (Locator.AssetLocator.Type)
{
case GameType.DemonsSouls:
if (s.WrappedObject is MSBD.Part.Object)
@@ -1476,7 +1472,7 @@ public void SetObjectModelForSelection(string modelName, string assetType, strin
}
if (assetType == "MapPiece")
{
- switch (AssetLocator.Type)
+ switch (Locator.AssetLocator.Type)
{
case GameType.DemonsSouls:
if (s.WrappedObject is MSBD.Part.MapPiece)
@@ -1838,7 +1834,7 @@ private void UnDummySelection()
private void DummyUndummySelection(string[] sourceTypes, string[] targetTypes)
{
Type msbclass;
- switch (AssetLocator.Type)
+ switch (Locator.AssetLocator.Type)
{
case GameType.DemonsSouls:
msbclass = typeof(MSBD);
@@ -2011,9 +2007,9 @@ public void ReloadUniverse()
GC.Collect();
Universe.PopulateMapList();
- if (AssetLocator.Type != GameType.Undefined)
+ if (Locator.AssetLocator.Type != GameType.Undefined)
{
- PopulateClassNames(AssetLocator.Type);
+ PopulateClassNames(Locator.AssetLocator.Type);
}
}
@@ -2064,7 +2060,7 @@ private void GenerateMCGMCP(Dictionary orderedMaps)
foreach (var map in orderedMaps)
{
string mapid = map.Key;
- if (AssetLocator.Type is GameType.DemonsSouls)
+ if (Locator.AssetLocator.Type is GameType.DemonsSouls)
{
if (mapid != "m03_01_00_99" && !mapid.StartsWith("m99"))
{
@@ -2080,10 +2076,10 @@ private void GenerateMCGMCP(Dictionary orderedMaps)
{
if (orderMap.Key.StartsWith(areaId) && orderMap.Key != "m03_01_00_99")
{
- areaDirectories.Add(Path.Combine(AssetLocator.GameRootDirectory, "map", orderMap.Key));
+ areaDirectories.Add(Path.Combine(Locator.AssetLocator.GameRootDirectory, "map", orderMap.Key));
}
}
- SoulsMapMetadataGenerator.GenerateMCGMCP(areaDirectories, AssetLocator, toBigEndian: true);
+ SoulsMapMetadataGenerator.GenerateMCGMCP(areaDirectories, Locator.AssetLocator, toBigEndian: true);
}
}
else
@@ -2092,21 +2088,21 @@ private void GenerateMCGMCP(Dictionary orderedMaps)
{
List areaDirectories = new List
{
- Path.Combine(AssetLocator.GameRootDirectory, "map", mapid)
+ Path.Combine(Locator.AssetLocator.GameRootDirectory, "map", mapid)
};
- SoulsMapMetadataGenerator.GenerateMCGMCP(areaDirectories, AssetLocator, toBigEndian: true);
+ SoulsMapMetadataGenerator.GenerateMCGMCP(areaDirectories, Locator.AssetLocator, toBigEndian: true);
}
}
}
- else if (AssetLocator.Type is GameType.DarkSoulsPTDE or GameType.DarkSoulsRemastered)
+ else if (Locator.AssetLocator.Type is GameType.DarkSoulsPTDE or GameType.DarkSoulsRemastered)
{
if (ImGui.Selectable($"{mapid}"))
{
List areaDirectories = new List
{
- Path.Combine(AssetLocator.GameRootDirectory, "map", mapid)
+ Path.Combine(Locator.AssetLocator.GameRootDirectory, "map", mapid)
};
- SoulsMapMetadataGenerator.GenerateMCGMCP(areaDirectories, AssetLocator, toBigEndian: false);
+ SoulsMapMetadataGenerator.GenerateMCGMCP(areaDirectories, Locator.AssetLocator, toBigEndian: false);
}
}
}
diff --git a/src/StudioCore/MsbEditor/MtdBank.cs b/src/StudioCore/MsbEditor/MtdBank.cs
index b4a737baf..91d7e3c94 100644
--- a/src/StudioCore/MsbEditor/MtdBank.cs
+++ b/src/StudioCore/MsbEditor/MtdBank.cs
@@ -8,8 +8,6 @@ namespace StudioCore.MsbEditor;
public class MtdBank
{
- private static AssetLocator AssetLocator;
-
private static Dictionary _mtds = new();
private static Dictionary _matbins = new();
@@ -27,14 +25,14 @@ public static void ReloadMtds()
try
{
IBinder mtdBinder = null;
- if (AssetLocator.Type == GameType.DarkSoulsIII || AssetLocator.Type == GameType.Sekiro)
+ if (Locator.AssetLocator.Type == GameType.DarkSoulsIII || Locator.AssetLocator.Type == GameType.Sekiro)
{
- mtdBinder = BND4.Read(AssetLocator.GetAssetPath(@"mtd\allmaterialbnd.mtdbnd.dcx"));
+ mtdBinder = BND4.Read(Locator.AssetLocator.GetAssetPath(@"mtd\allmaterialbnd.mtdbnd.dcx"));
IsMatbin = false;
}
- else if (AssetLocator.Type is GameType.EldenRing or GameType.ArmoredCoreVI)
+ else if (Locator.AssetLocator.Type is GameType.EldenRing or GameType.ArmoredCoreVI)
{
- mtdBinder = BND4.Read(AssetLocator.GetAssetPath(@"material\allmaterial.matbinbnd.dcx"));
+ mtdBinder = BND4.Read(Locator.AssetLocator.GetAssetPath(@"material\allmaterial.matbinbnd.dcx"));
IsMatbin = true;
}
@@ -80,16 +78,4 @@ public static void ReloadMtds()
}
}));
}
-
- public static void LoadMtds(AssetLocator l)
- {
- AssetLocator = l;
-
- if (AssetLocator.Type == GameType.Undefined)
- {
- return;
- }
-
- ReloadMtds();
- }
}
diff --git a/src/StudioCore/MsbEditor/NavmeshEditor.cs b/src/StudioCore/MsbEditor/NavmeshEditor.cs
index fbc2c33d6..f70485fef 100644
--- a/src/StudioCore/MsbEditor/NavmeshEditor.cs
+++ b/src/StudioCore/MsbEditor/NavmeshEditor.cs
@@ -15,7 +15,6 @@ namespace StudioCore.MsbEditor;
///
public class NavmeshEditor
{
- private readonly AssetLocator _locator;
private readonly MeshRenderableProxy _previewMesh = null;
private readonly Selection _selection;
private readonly int icount = 0;
@@ -34,9 +33,8 @@ public class NavmeshEditor
private int MinRegionArea = 3;
private float SlopeAngle = 30.0f;
- public NavmeshEditor(AssetLocator locator, RenderScene scene, Selection sel)
+ public NavmeshEditor(RenderScene scene, Selection sel)
{
- _locator = locator;
_scene = scene;
_selection = sel;
}
@@ -121,7 +119,7 @@ public unsafe void OnGui(GameType game)
_previewMesh.World = mrp.World;
// Do a test save
- var path = $@"{_locator.GameModDirectory}\navout\test.hkx";
+ var path = $@"{Locator.AssetLocator.GameModDirectory}\navout\test.hkx";
using (FileStream s2 = File.Create(path))
{
BinaryWriterEx bw = new(false, s2);
diff --git a/src/StudioCore/MsbEditor/SceneTree.cs b/src/StudioCore/MsbEditor/SceneTree.cs
index 36db75535..04dae0f4c 100644
--- a/src/StudioCore/MsbEditor/SceneTree.cs
+++ b/src/StudioCore/MsbEditor/SceneTree.cs
@@ -47,9 +47,6 @@ public enum ViewMode
Flat,
ObjectType
}
-
- private readonly AssetLocator _assetLocator;
-
private readonly Configuration _configuration;
private readonly List _dragDropDestObjects = new();
private readonly List _dragDropDests = new();
@@ -94,7 +91,7 @@ private ulong
private ViewMode _viewMode = ViewMode.ObjectType;
public SceneTree(Configuration configuration, SceneTreeEventHandler handler, string id, Universe universe,
- Selection sel, ActionManager aman, IViewport vp, AssetLocator al)
+ Selection sel, ActionManager aman, IViewport vp)
{
_handler = handler;
_id = id;
@@ -102,7 +99,6 @@ public SceneTree(Configuration configuration, SceneTreeEventHandler handler, str
_selection = sel;
_editorActionManager = aman;
_viewport = vp;
- _assetLocator = al;
_configuration = configuration;
if (_configuration == Configuration.ModelEditor)
@@ -131,12 +127,12 @@ private void RebuildTypeViewCache(Map map)
mapcache.Add(MapEntity.MapEntityType.Part, new Dictionary>());
mapcache.Add(MapEntity.MapEntityType.Region, new Dictionary>());
mapcache.Add(MapEntity.MapEntityType.Event, new Dictionary>());
- if (_assetLocator.Type is GameType.Bloodborne or GameType.DarkSoulsIII or GameType.Sekiro
+ if (Locator.AssetLocator.Type is GameType.Bloodborne or GameType.DarkSoulsIII or GameType.Sekiro
or GameType.EldenRing or GameType.ArmoredCoreVI)
{
mapcache.Add(MapEntity.MapEntityType.Light, new Dictionary>());
}
- else if (_assetLocator.Type is GameType.DarkSoulsIISOTFS)
+ else if (Locator.AssetLocator.Type is GameType.DarkSoulsIISOTFS)
{
mapcache.Add(MapEntity.MapEntityType.Light, new Dictionary>());
mapcache.Add(MapEntity.MapEntityType.DS2Event, new Dictionary>());
@@ -487,7 +483,7 @@ private void TypeView(Map map)
{
// Regions don't have multiple types in certain games
if (cats.Key == MapEntity.MapEntityType.Region &&
- _assetLocator.Type is GameType.DemonsSouls
+ Locator.AssetLocator.Type is GameType.DemonsSouls
or GameType.DarkSoulsPTDE
or GameType.DarkSoulsRemastered
or GameType.Bloodborne)
@@ -617,7 +613,7 @@ public unsafe void OnGui()
if (_configuration == Configuration.MapEditor)
{
- if (_assetLocator.Type is GameType.DarkSoulsIISOTFS)
+ if (Locator.AssetLocator.Type is GameType.DarkSoulsIISOTFS)
{
if (ParamBank.PrimaryBank.IsLoadingParams)
{
@@ -905,7 +901,7 @@ public unsafe void OnGui()
}
}
- if (/*_assetLocator.Type == GameType.Bloodborne &&*/ _configuration == Configuration.MapEditor)
+ if (Locator.AssetLocator.Type == GameType.Bloodborne && _configuration == Configuration.MapEditor)
{
ChaliceDungeonImportButton();
}
diff --git a/src/StudioCore/MsbEditor/Universe.cs b/src/StudioCore/MsbEditor/Universe.cs
index 4f6af99d6..23a060c56 100644
--- a/src/StudioCore/MsbEditor/Universe.cs
+++ b/src/StudioCore/MsbEditor/Universe.cs
@@ -30,7 +30,6 @@ internal partial class BtlLightSerializerContext : JsonSerializerContext
///
public class Universe
{
- private readonly AssetLocator _assetLocator;
private readonly RenderScene _renderScene;
public int _dispGroupCount = 8;
@@ -38,9 +37,8 @@ public class Universe
public bool postLoad;
- public Universe(AssetLocator al, RenderScene scene, Selection sel)
+ public Universe(RenderScene scene, Selection sel)
{
- _assetLocator = al;
_renderScene = scene;
Selection = sel;
}
@@ -50,7 +48,7 @@ public Universe(AssetLocator al, RenderScene scene, Selection sel)
public List EnvMapTextures { get; private set; } = new();
- public GameType GameType => _assetLocator.Type;
+ public GameType GameType => Locator.AssetLocator.Type;
public Map GetLoadedMap(string id)
{
@@ -316,43 +314,43 @@ public RenderableProxy GetModelDrawable(Map map, Entity obj, string modelname, b
var loadflver = false;
var filt = RenderFilter.All;
- var amapid = _assetLocator.GetAssetMapID(map.Name);
+ var amapid = Locator.AssetLocator.GetAssetMapID(map.Name);
ResourceManager.ResourceJobBuilder job = ResourceManager.CreateNewJob(@"Loading mesh");
if (modelname.ToLower().StartsWith("m"))
{
loadflver = true;
- asset = _assetLocator.GetMapModel(amapid, _assetLocator.MapModelNameToAssetName(amapid, modelname));
+ asset = Locator.AssetLocator.GetMapModel(amapid, Locator.AssetLocator.MapModelNameToAssetName(amapid, modelname));
filt = RenderFilter.MapPiece;
}
else if (modelname.ToLower().StartsWith("c"))
{
loadflver = true;
- asset = _assetLocator.GetChrModel(modelname);
+ asset = Locator.AssetLocator.GetChrModel(modelname);
filt = RenderFilter.Character;
}
else if (modelname.ToLower().StartsWith("o") || modelname.StartsWith("AEG"))
{
loadflver = true;
- asset = _assetLocator.GetObjModel(modelname);
+ asset = Locator.AssetLocator.GetObjModel(modelname);
filt = RenderFilter.Object;
}
else if (modelname.ToLower().StartsWith("h"))
{
loadcol = true;
- asset = _assetLocator.GetMapCollisionModel(amapid,
- _assetLocator.MapModelNameToAssetName(amapid, modelname), false);
+ asset = Locator.AssetLocator.GetMapCollisionModel(amapid,
+ Locator.AssetLocator.MapModelNameToAssetName(amapid, modelname), false);
filt = RenderFilter.Collision;
}
else if (modelname.ToLower().StartsWith("n"))
{
loadnav = true;
- asset = _assetLocator.GetMapNVMModel(amapid, _assetLocator.MapModelNameToAssetName(amapid, modelname));
+ asset = Locator.AssetLocator.GetMapNVMModel(amapid, Locator.AssetLocator.MapModelNameToAssetName(amapid, modelname));
filt = RenderFilter.Navmesh;
}
else
{
- asset = _assetLocator.GetNullAsset();
+ asset = AssetUtils.GetNullAsset();
}
ModelMarkerType modelMarkerType =
@@ -389,7 +387,7 @@ public RenderableProxy GetModelDrawable(Map map, Entity obj, string modelname, b
return mesh;
}
- if (loadnav && _assetLocator.Type != GameType.DarkSoulsIISOTFS)
+ if (loadnav && Locator.AssetLocator.Type != GameType.DarkSoulsIISOTFS)
{
MeshRenderableProxy mesh = MeshRenderableProxy.MeshRenderableFromNVMResource(
_renderScene, asset.AssetVirtualPath, modelMarkerType);
@@ -420,7 +418,7 @@ public RenderableProxy GetModelDrawable(Map map, Entity obj, string modelname, b
return mesh;
}
- else if (loadnav && _assetLocator.Type == GameType.DarkSoulsIISOTFS)
+ else if (loadnav && Locator.AssetLocator.Type == GameType.DarkSoulsIISOTFS)
{
}
else if (loadflver)
@@ -531,14 +529,14 @@ public void LoadDS2Generators(string mapid, Map map)
(int)regist.GetCellHandleOrThrow("EnemyParamID").Value);
if (chrid != null)
{
- AssetDescription asset = _assetLocator.GetChrModel($@"c{chrid}");
+ AssetDescription asset = Locator.AssetLocator.GetChrModel($@"c{chrid}");
MeshRenderableProxy model = MeshRenderableProxy.MeshRenderableFromFlverResource(
_renderScene, asset.AssetVirtualPath, ModelMarkerType.Enemy);
model.DrawFilter = RenderFilter.Character;
generatorObjs[row.ID].RenderSceneMesh = model;
model.SetSelectable(generatorObjs[row.ID]);
chrsToLoad.Add(asset);
- AssetDescription tasset = _assetLocator.GetChrTextures($@"c{chrid}");
+ AssetDescription tasset = Locator.AssetLocator.GetChrTextures($@"c{chrid}");
if (tasset.AssetVirtualPath != null || tasset.AssetArchiveVirtualPath != null)
{
chrsToLoad.Add(tasset);
@@ -617,7 +615,7 @@ public void LoadDS2Generators(string mapid, Map map)
public void PopulateMapList()
{
LoadedObjectContainers.Clear();
- foreach (var m in _assetLocator.GetFullMapList())
+ foreach (var m in Locator.AssetLocator.GetFullMapList())
{
LoadedObjectContainers.Add(m, null);
}
@@ -635,7 +633,7 @@ public void LoadRelatedMapsER(string mapid, Dictionary
public bool LoadMap(string mapid, bool selectOnLoad = false)
{
- if (_assetLocator.Type == GameType.DarkSoulsIISOTFS
+ if (Locator.AssetLocator.Type == GameType.DarkSoulsIISOTFS
&& ParamBank.PrimaryBank.Params == null)
{
// ParamBank must be loaded for DS2 maps
@@ -644,7 +642,7 @@ public bool LoadMap(string mapid, bool selectOnLoad = false)
return false;
}
- AssetDescription ad = _assetLocator.GetMapMSB(mapid);
+ AssetDescription ad = Locator.AssetLocator.GetMapMSB(mapid);
if (ad.AssetPath == null)
{
return false;
@@ -660,7 +658,7 @@ public BTL ReturnBTL(AssetDescription ad)
{
BTL btl;
- if (_assetLocator.Type == GameType.DarkSoulsIISOTFS)
+ if (Locator.AssetLocator.Type == GameType.DarkSoulsIISOTFS)
{
using BXF4 bdt = BXF4.Read(ad.AssetPath, ad.AssetPath[..^3] + "bdt");
BinderFile file = bdt.Files.Find(f => f.Name.EndsWith("light.btl.dcx"));
@@ -710,7 +708,7 @@ public async void LoadMapAsync(string mapid, bool selectOnLoad = false)
HashSet navsToLoad = new();
//drawgroup count
- switch (_assetLocator.Type)
+ switch (Locator.AssetLocator.Type)
{
// imgui checkbox click seems to break at some point after 8 (8*32) checkboxes, so let's just hope that never happens, yeah?
case GameType.DemonsSouls:
@@ -729,42 +727,42 @@ public async void LoadMapAsync(string mapid, bool selectOnLoad = false)
_dispGroupCount = 8; //?
break;
default:
- throw new Exception($"Error: Did not expect Gametype {_assetLocator.Type}");
+ throw new Exception($"Error: Did not expect Gametype {Locator.AssetLocator.Type}");
//break;
}
- AssetDescription ad = _assetLocator.GetMapMSB(mapid);
+ AssetDescription ad = Locator.AssetLocator.GetMapMSB(mapid);
if (ad.AssetPath == null)
{
return;
}
IMsb msb;
- if (_assetLocator.Type == GameType.DarkSoulsIII)
+ if (Locator.AssetLocator.Type == GameType.DarkSoulsIII)
{
msb = MSB3.Read(ad.AssetPath);
}
- else if (_assetLocator.Type == GameType.Sekiro)
+ else if (Locator.AssetLocator.Type == GameType.Sekiro)
{
msb = MSBS.Read(ad.AssetPath);
}
- else if (_assetLocator.Type == GameType.EldenRing)
+ else if (Locator.AssetLocator.Type == GameType.EldenRing)
{
msb = MSBE.Read(ad.AssetPath);
}
- else if (_assetLocator.Type == GameType.ArmoredCoreVI)
+ else if (Locator.AssetLocator.Type == GameType.ArmoredCoreVI)
{
msb = MSB_AC6.Read(ad.AssetPath);
}
- else if (_assetLocator.Type == GameType.DarkSoulsIISOTFS)
+ else if (Locator.AssetLocator.Type == GameType.DarkSoulsIISOTFS)
{
msb = MSB2.Read(ad.AssetPath);
}
- else if (_assetLocator.Type == GameType.Bloodborne)
+ else if (Locator.AssetLocator.Type == GameType.Bloodborne)
{
msb = MSBB.Read(ad.AssetPath);
}
- else if (_assetLocator.Type == GameType.DemonsSouls)
+ else if (Locator.AssetLocator.Type == GameType.DemonsSouls)
{
msb = MSBD.Read(ad.AssetPath);
}
@@ -775,21 +773,21 @@ public async void LoadMapAsync(string mapid, bool selectOnLoad = false)
map.LoadMSB(msb);
- var amapid = _assetLocator.GetAssetMapID(mapid);
+ var amapid = Locator.AssetLocator.GetAssetMapID(mapid);
foreach (IMsbModel model in msb.Models.GetEntries())
{
AssetDescription asset;
if (model.Name.StartsWith("m"))
{
- asset = _assetLocator.GetMapModel(amapid,
- _assetLocator.MapModelNameToAssetName(amapid, model.Name));
+ asset = Locator.AssetLocator.GetMapModel(amapid,
+ Locator.AssetLocator.MapModelNameToAssetName(amapid, model.Name));
mappiecesToLoad.Add(asset);
}
else if (model.Name.StartsWith("c"))
{
- asset = _assetLocator.GetChrModel(model.Name);
+ asset = Locator.AssetLocator.GetChrModel(model.Name);
chrsToLoad.Add(asset);
- AssetDescription tasset = _assetLocator.GetChrTextures(model.Name);
+ AssetDescription tasset = Locator.AssetLocator.GetChrTextures(model.Name);
if (tasset.AssetVirtualPath != null || tasset.AssetArchiveVirtualPath != null)
{
chrsToLoad.Add(tasset);
@@ -797,9 +795,9 @@ public async void LoadMapAsync(string mapid, bool selectOnLoad = false)
}
else if (model.Name.StartsWith("o"))
{
- asset = _assetLocator.GetObjModel(model.Name);
+ asset = Locator.AssetLocator.GetObjModel(model.Name);
objsToLoad.Add(asset);
- AssetDescription tasset = _assetLocator.GetObjTexture(model.Name);
+ AssetDescription tasset = Locator.AssetLocator.GetObjTexture(model.Name);
if (tasset.AssetVirtualPath != null || tasset.AssetArchiveVirtualPath != null)
{
objsToLoad.Add(tasset);
@@ -807,20 +805,20 @@ public async void LoadMapAsync(string mapid, bool selectOnLoad = false)
}
else if (model.Name.StartsWith("AEG"))
{
- asset = _assetLocator.GetObjModel(model.Name);
+ asset = Locator.AssetLocator.GetObjModel(model.Name);
objsToLoad.Add(asset);
}
else if (model.Name.StartsWith("h"))
{
- asset = _assetLocator.GetMapCollisionModel(amapid,
- _assetLocator.MapModelNameToAssetName(amapid, model.Name), false);
+ asset = Locator.AssetLocator.GetMapCollisionModel(amapid,
+ Locator.AssetLocator.MapModelNameToAssetName(amapid, model.Name), false);
colsToLoad.Add(asset);
}
- else if (model.Name.StartsWith("n") && _assetLocator.Type != GameType.DarkSoulsIISOTFS &&
- _assetLocator.Type != GameType.Bloodborne)
+ else if (model.Name.StartsWith("n") && Locator.AssetLocator.Type != GameType.DarkSoulsIISOTFS &&
+ Locator.AssetLocator.Type != GameType.Bloodborne)
{
- asset = _assetLocator.GetMapNVMModel(amapid,
- _assetLocator.MapModelNameToAssetName(amapid, model.Name));
+ asset = Locator.AssetLocator.GetMapNVMModel(amapid,
+ Locator.AssetLocator.MapModelNameToAssetName(amapid, model.Name));
navsToLoad.Add(asset);
}
}
@@ -835,7 +833,7 @@ public async void LoadMapAsync(string mapid, bool selectOnLoad = false)
}
// Load BTLs (must be done after MapOffset is set)
- List BTLs = _assetLocator.GetMapBTLs(mapid);
+ List BTLs = Locator.AssetLocator.GetMapBTLs(mapid);
foreach (AssetDescription btl_ad in BTLs)
{
BTL btl = ReturnBTL(btl_ad);
@@ -845,7 +843,7 @@ public async void LoadMapAsync(string mapid, bool selectOnLoad = false)
}
}
- if (_assetLocator.Type == GameType.EldenRing && CFG.Current.EnableEldenRingAutoMapOffset)
+ if (Locator.AssetLocator.Type == GameType.EldenRing && CFG.Current.EnableEldenRingAutoMapOffset)
{
if (SpecialMapConnections.GetEldenMapTransform(mapid, LoadedObjectContainers) is Transform
loadTransform)
@@ -871,15 +869,15 @@ public async void LoadMapAsync(string mapid, bool selectOnLoad = false)
Selection.AddSelection(map.RootObject);
}
- if (_assetLocator.Type == GameType.DarkSoulsIISOTFS)
+ if (Locator.AssetLocator.Type == GameType.DarkSoulsIISOTFS)
{
LoadDS2Generators(amapid, map);
}
// Temporary DS3 navmesh loading
- if (FeatureFlags.LoadDS3Navmeshes && _assetLocator.Type == GameType.DarkSoulsIII)
+ if (FeatureFlags.LoadDS3Navmeshes && Locator.AssetLocator.Type == GameType.DarkSoulsIII)
{
- AssetDescription nvaasset = _assetLocator.GetMapNVA(amapid);
+ AssetDescription nvaasset = Locator.AssetLocator.GetMapNVA(amapid);
if (nvaasset.AssetPath != null)
{
NVA nva = NVA.Read(nvaasset.AssetPath);
@@ -889,8 +887,8 @@ public async void LoadMapAsync(string mapid, bool selectOnLoad = false)
MapEntity n = new(map, nav, MapEntity.MapEntityType.Editor);
map.AddObject(n);
var navid = $@"n{nav.ModelID:D6}";
- var navname = "n" + _assetLocator.MapModelNameToAssetName(amapid, navid).Substring(1);
- AssetDescription nasset = _assetLocator.GetHavokNavmeshModel(amapid, navname);
+ var navname = "n" + Locator.AssetLocator.MapModelNameToAssetName(amapid, navid).Substring(1);
+ AssetDescription nasset = Locator.AssetLocator.GetHavokNavmeshModel(amapid, navname);
MeshRenderableProxy mesh = MeshRenderableProxy.MeshRenderableFromHavokNavmeshResource(
_renderScene, nasset.AssetVirtualPath, ModelMarkerType.Other);
@@ -922,7 +920,7 @@ public async void LoadMapAsync(string mapid, bool selectOnLoad = false)
if (CFG.Current.EnableTexturing)
{
job = ResourceManager.CreateNewJob($@"Loading {amapid} textures");
- foreach (AssetDescription asset in _assetLocator.GetMapTextures(amapid))
+ foreach (AssetDescription asset in Locator.AssetLocator.GetMapTextures(amapid))
{
if (asset.AssetArchiveVirtualPath != null)
{
@@ -1001,9 +999,9 @@ public async void LoadMapAsync(string mapid, bool selectOnLoad = false)
if (FeatureFlags.LoadNavmeshes)
{
job = ResourceManager.CreateNewJob(@"Loading Navmeshes");
- if (_assetLocator.Type == GameType.DarkSoulsIII && FeatureFlags.LoadDS3Navmeshes)
+ if (Locator.AssetLocator.Type == GameType.DarkSoulsIII && FeatureFlags.LoadDS3Navmeshes)
{
- AssetDescription nav = _assetLocator.GetHavokNavmeshes(amapid);
+ AssetDescription nav = Locator.AssetLocator.GetHavokNavmeshes(amapid);
job.AddLoadArchiveTask(nav.AssetArchiveVirtualPath, AccessLevel.AccessGPUOptimizedOnly, false,
ResourceManager.ResourceType.NavmeshHKX);
}
@@ -1028,7 +1026,7 @@ public async void LoadMapAsync(string mapid, bool selectOnLoad = false)
}
// Real bad hack
- EnvMapTextures = _assetLocator.GetEnvMapTextureNames(amapid);
+ EnvMapTextures = Locator.AssetLocator.GetEnvMapTextureNames(amapid);
ScheduleTextureRefresh();
@@ -1131,40 +1129,40 @@ public void LoadFlver(FLVER2 flver, MeshRenderableProxy proxy, string name)
private void SaveDS2Generators(Map map)
{
// Load all the params
- AssetDescription regparamad = _assetLocator.GetDS2GeneratorRegistParam(map.Name);
- AssetDescription regparamadw = _assetLocator.GetDS2GeneratorRegistParam(map.Name, true);
+ AssetDescription regparamad = Locator.AssetLocator.GetDS2GeneratorRegistParam(map.Name);
+ AssetDescription regparamadw = Locator.AssetLocator.GetDS2GeneratorRegistParam(map.Name, true);
Param regparam = Param.Read(regparamad.AssetPath);
- PARAMDEF reglayout = _assetLocator.GetParamdefForParam(regparam.ParamType);
+ PARAMDEF reglayout = Locator.AssetLocator.GetParamdefForParam(regparam.ParamType);
regparam.ApplyParamdef(reglayout);
- AssetDescription locparamad = _assetLocator.GetDS2GeneratorLocationParam(map.Name);
- AssetDescription locparamadw = _assetLocator.GetDS2GeneratorLocationParam(map.Name, true);
+ AssetDescription locparamad = Locator.AssetLocator.GetDS2GeneratorLocationParam(map.Name);
+ AssetDescription locparamadw = Locator.AssetLocator.GetDS2GeneratorLocationParam(map.Name, true);
Param locparam = Param.Read(locparamad.AssetPath);
- PARAMDEF loclayout = _assetLocator.GetParamdefForParam(locparam.ParamType);
+ PARAMDEF loclayout = Locator.AssetLocator.GetParamdefForParam(locparam.ParamType);
locparam.ApplyParamdef(loclayout);
- AssetDescription genparamad = _assetLocator.GetDS2GeneratorParam(map.Name);
- AssetDescription genparamadw = _assetLocator.GetDS2GeneratorParam(map.Name, true);
+ AssetDescription genparamad = Locator.AssetLocator.GetDS2GeneratorParam(map.Name);
+ AssetDescription genparamadw = Locator.AssetLocator.GetDS2GeneratorParam(map.Name, true);
Param genparam = Param.Read(genparamad.AssetPath);
- PARAMDEF genlayout = _assetLocator.GetParamdefForParam(genparam.ParamType);
+ PARAMDEF genlayout = Locator.AssetLocator.GetParamdefForParam(genparam.ParamType);
genparam.ApplyParamdef(genlayout);
- AssetDescription evtparamad = _assetLocator.GetDS2EventParam(map.Name);
- AssetDescription evtparamadw = _assetLocator.GetDS2EventParam(map.Name, true);
+ AssetDescription evtparamad = Locator.AssetLocator.GetDS2EventParam(map.Name);
+ AssetDescription evtparamadw = Locator.AssetLocator.GetDS2EventParam(map.Name, true);
Param evtparam = Param.Read(evtparamad.AssetPath);
- PARAMDEF evtlayout = _assetLocator.GetParamdefForParam(evtparam.ParamType);
+ PARAMDEF evtlayout = Locator.AssetLocator.GetParamdefForParam(evtparam.ParamType);
evtparam.ApplyParamdef(evtlayout);
- AssetDescription evtlparamad = _assetLocator.GetDS2EventLocationParam(map.Name);
- AssetDescription evtlparamadw = _assetLocator.GetDS2EventLocationParam(map.Name, true);
+ AssetDescription evtlparamad = Locator.AssetLocator.GetDS2EventLocationParam(map.Name);
+ AssetDescription evtlparamadw = Locator.AssetLocator.GetDS2EventLocationParam(map.Name, true);
Param evtlparam = Param.Read(evtlparamad.AssetPath);
- PARAMDEF evtllayout = _assetLocator.GetParamdefForParam(evtlparam.ParamType);
+ PARAMDEF evtllayout = Locator.AssetLocator.GetParamdefForParam(evtlparam.ParamType);
evtlparam.ApplyParamdef(evtllayout);
- AssetDescription objparamad = _assetLocator.GetDS2ObjInstanceParam(map.Name);
- AssetDescription objparamadw = _assetLocator.GetDS2ObjInstanceParam(map.Name, true);
+ AssetDescription objparamad = Locator.AssetLocator.GetDS2ObjInstanceParam(map.Name);
+ AssetDescription objparamadw = Locator.AssetLocator.GetDS2ObjInstanceParam(map.Name, true);
Param objparam = Param.Read(objparamad.AssetPath);
- PARAMDEF objlayout = _assetLocator.GetParamdefForParam(objparam.ParamType);
+ PARAMDEF objlayout = Locator.AssetLocator.GetParamdefForParam(objparam.ParamType);
objparam.ApplyParamdef(objlayout);
// Clear them out
@@ -1328,33 +1326,33 @@ private void SaveDS2Generators(Map map)
private DCX.Type GetCompressionType()
{
- if (_assetLocator.Type == GameType.DarkSoulsIII)
+ if (Locator.AssetLocator.Type == GameType.DarkSoulsIII)
{
return DCX.Type.DCX_DFLT_10000_44_9;
}
- if (_assetLocator.Type == GameType.EldenRing)
+ if (Locator.AssetLocator.Type == GameType.EldenRing)
{
return DCX.Type.DCX_DFLT_10000_44_9;
}
- if (_assetLocator.Type == GameType.ArmoredCoreVI)
+ if (Locator.AssetLocator.Type == GameType.ArmoredCoreVI)
{
return DCX.Type.DCX_DFLT_10000_44_9;
}
- else if (_assetLocator.Type == GameType.DarkSoulsIISOTFS)
+ else if (Locator.AssetLocator.Type == GameType.DarkSoulsIISOTFS)
{
return DCX.Type.None;
}
- else if (_assetLocator.Type == GameType.Sekiro)
+ else if (Locator.AssetLocator.Type == GameType.Sekiro)
{
return DCX.Type.DCX_DFLT_10000_44_9;
}
- else if (_assetLocator.Type == GameType.Bloodborne)
+ else if (Locator.AssetLocator.Type == GameType.Bloodborne)
{
return DCX.Type.DCX_DFLT_10000_44_9;
}
- else if (_assetLocator.Type == GameType.DemonsSouls)
+ else if (Locator.AssetLocator.Type == GameType.DemonsSouls)
{
return DCX.Type.None;
}
@@ -1367,10 +1365,10 @@ private DCX.Type GetCompressionType()
///
public void SaveBTL(Map map)
{
- List BTLs = _assetLocator.GetMapBTLs(map.Name);
- List BTLs_w = _assetLocator.GetMapBTLs(map.Name, true);
+ List BTLs = Locator.AssetLocator.GetMapBTLs(map.Name);
+ List BTLs_w = Locator.AssetLocator.GetMapBTLs(map.Name, true);
DCX.Type compressionType = GetCompressionType();
- if (_assetLocator.Type == GameType.DarkSoulsIISOTFS)
+ if (Locator.AssetLocator.Type == GameType.DarkSoulsIISOTFS)
{
for (var i = 0; i < BTLs.Count; i++)
{
@@ -1389,8 +1387,8 @@ public void SaveBTL(Map map)
file.Bytes = btl.Write(DCX.Type.DCX_DFLT_10000_24_9);
var bdtPath = BTLs_w[i].AssetPath[..^3] + "bdt";
- Utils.WriteWithBackup(_assetLocator, Utils.GetLocalAssetPath(_assetLocator, bdtPath), bdt,
- Utils.GetLocalAssetPath(_assetLocator, BTLs_w[i].AssetPath));
+ Utils.WriteWithBackup(Locator.AssetLocator, Utils.GetLocalAssetPath(Locator.AssetLocator, bdtPath), bdt,
+ Utils.GetLocalAssetPath(Locator.AssetLocator, BTLs_w[i].AssetPath));
}
}
}
@@ -1410,8 +1408,8 @@ public void SaveBTL(Map map)
{
btl.Lights = newLights;
- Utils.WriteWithBackup(_assetLocator,
- Utils.GetLocalAssetPath(_assetLocator, BTLs_w[i].AssetPath), btl);
+ Utils.WriteWithBackup(Locator.AssetLocator,
+ Utils.GetLocalAssetPath(Locator.AssetLocator, BTLs_w[i].AssetPath), btl);
}
}
}
@@ -1423,11 +1421,11 @@ public void SaveMap(Map map)
SaveBTL(map);
try
{
- AssetDescription ad = _assetLocator.GetMapMSB(map.Name);
- AssetDescription adw = _assetLocator.GetMapMSB(map.Name, true);
+ AssetDescription ad = Locator.AssetLocator.GetMapMSB(map.Name);
+ AssetDescription adw = Locator.AssetLocator.GetMapMSB(map.Name, true);
IMsb msb;
DCX.Type compressionType = GetCompressionType();
- if (_assetLocator.Type == GameType.DarkSoulsIII)
+ if (Locator.AssetLocator.Type == GameType.DarkSoulsIII)
{
MSB3 prev = MSB3.Read(ad.AssetPath);
MSB3 n = new();
@@ -1436,7 +1434,7 @@ public void SaveMap(Map map)
n.Routes = prev.Routes;
msb = n;
}
- else if (_assetLocator.Type == GameType.EldenRing)
+ else if (Locator.AssetLocator.Type == GameType.EldenRing)
{
MSBE n = new();
//Asset path may be null if this is a newly created map
@@ -1448,7 +1446,7 @@ public void SaveMap(Map map)
}
msb = n;
}
- else if (_assetLocator.Type == GameType.ArmoredCoreVI)
+ else if (Locator.AssetLocator.Type == GameType.ArmoredCoreVI)
{
MSB_AC6 prev = MSB_AC6.Read(ad.AssetPath);
MSB_AC6 n = new();
@@ -1456,14 +1454,14 @@ public void SaveMap(Map map)
n.Routes = prev.Routes;
msb = n;
}
- else if (_assetLocator.Type == GameType.DarkSoulsIISOTFS)
+ else if (Locator.AssetLocator.Type == GameType.DarkSoulsIISOTFS)
{
MSB2 prev = MSB2.Read(ad.AssetPath);
MSB2 n = new();
n.PartPoses = prev.PartPoses;
msb = n;
}
- else if (_assetLocator.Type == GameType.Sekiro)
+ else if (Locator.AssetLocator.Type == GameType.Sekiro)
{
MSBS prev = MSBS.Read(ad.AssetPath);
MSBS n = new();
@@ -1472,11 +1470,11 @@ public void SaveMap(Map map)
n.Routes = prev.Routes;
msb = n;
}
- else if (_assetLocator.Type == GameType.Bloodborne)
+ else if (Locator.AssetLocator.Type == GameType.Bloodborne)
{
msb = new MSBB();
}
- else if (_assetLocator.Type == GameType.DemonsSouls)
+ else if (Locator.AssetLocator.Type == GameType.DemonsSouls)
{
MSBD prev = MSBD.Read(ad.AssetPath);
MSBD n = new();
@@ -1490,7 +1488,7 @@ public void SaveMap(Map map)
//((MSB1)msb).Models = t.Models;
}
- map.SerializeToMSB(msb, _assetLocator.Type);
+ map.SerializeToMSB(msb, Locator.AssetLocator.Type);
// Create the map directory if it doesn't exist
if (!Directory.Exists(Path.GetDirectoryName(adw.AssetPath)))
@@ -1532,7 +1530,7 @@ public void SaveMap(Map map)
File.Move(mapPath + ".temp", mapPath);
- if (_assetLocator.Type == GameType.DarkSoulsIISOTFS)
+ if (Locator.AssetLocator.Type == GameType.DarkSoulsIISOTFS)
{
SaveDS2Generators(map);
}
@@ -1565,10 +1563,11 @@ public void UpdateWorldMsbList()
{
try
{
- if (_assetLocator.Type == GameType.EldenRing)
+ var assetLocator = Locator.ActiveProject.AssetLocator;
+ if (assetLocator.Type == GameType.EldenRing)
{
- AssetDescription ad = _assetLocator.GetWorldLoadListList();
- AssetDescription adw = _assetLocator.GetWorldLoadListList(true);
+ AssetDescription ad = assetLocator.GetWorldLoadListList();
+ AssetDescription adw = assetLocator.GetWorldLoadListList(true);
if (!Directory.Exists(Path.GetDirectoryName(adw.AssetPath)))
{
@@ -1587,7 +1586,7 @@ public void UpdateWorldMsbList()
}
}
- Utils.WriteWithBackup(_assetLocator.GameRootDirectory, _assetLocator.GameModDirectory, @"\map\worldmsblist.worldloadlistlist.dcx", loadList);
+ Utils.WriteWithBackup(Locator.ActiveProject.ParentProject.AssetLocator.RootDirectory, assetLocator.RootDirectory, @"\map\worldmsblist.worldloadlistlist.dcx", loadList);
TaskLogs.AddLog($"Saved WorldMsbList");
}
diff --git a/src/StudioCore/ParamEditor/MassEditScript.cs b/src/StudioCore/ParamEditor/MassEditScript.cs
index 1ad38de2b..aa59de4d6 100644
--- a/src/StudioCore/ParamEditor/MassEditScript.cs
+++ b/src/StudioCore/ParamEditor/MassEditScript.cs
@@ -51,8 +51,8 @@ private MassEditScript(string path, string name)
public static void ReloadScripts()
{
- var cdir = ParamBank.PrimaryBank.AssetLocator.GetScriptAssetsCommonDir();
- var dir = ParamBank.PrimaryBank.AssetLocator.GetScriptAssetsDir();
+ var cdir = Locator.AssetLocator.GetScriptAssetsCommonDir();
+ var dir = Locator.AssetLocator.GetScriptAssetsDir();
scriptList = new List();
LoadScriptsFromDir(cdir);
LoadScriptsFromDir(dir);
diff --git a/src/StudioCore/ParamEditor/ParamBank.cs b/src/StudioCore/ParamEditor/ParamBank.cs
index 4ba179d64..721620f69 100644
--- a/src/StudioCore/ParamEditor/ParamBank.cs
+++ b/src/StudioCore/ParamEditor/ParamBank.cs
@@ -33,10 +33,15 @@ public enum RowGetType
SelectedRows = 2
}
- public static ParamBank PrimaryBank = new();
- public static ParamBank VanillaBank = new();
+ public static ParamBank PrimaryBank => Locator.ActiveProject.ParamBank;
+ public static ParamBank VanillaBank => Locator.ActiveProject.ParentProject.ParamBank;
public static Dictionary AuxBanks = new();
+ ///
+ /// Mapping from path -> PARAMDEF for cache and and comparison purposes. TODO: check for paramdef comparisons and evaluate if the file/paramdef was actually the same.
+ ///
+ private static readonly Dictionary _paramdefsCache = new();
+
public static string ClipboardParam = null;
public static List ClipboardRows = new();
@@ -44,14 +49,18 @@ public enum RowGetType
///
/// Mapping from ParamType -> PARAMDEF.
///
- private static Dictionary _paramdefs;
+ private Dictionary _paramdefs = new();
+
+ //TODO private this
+ public Dictionary ParamMetas = new();
+
///
/// Mapping from Param filename -> Manual ParamType.
/// This is for params with no usable ParamType at some particular game version.
/// By convention, ParamTypes ending in "_TENTATIVE" do not have official data to reference.
///
- private static Dictionary _tentativeParamType;
+ private Dictionary _tentativeParamType;
///
/// Map related params.
@@ -96,6 +105,8 @@ public enum RowGetType
private static readonly HashSet EMPTYSET = new();
+ public Project Project;
+
private Dictionary _params;
private ulong _paramVersion;
@@ -111,11 +122,10 @@ public enum RowGetType
private Dictionary _usedTentativeParamTypes;
private Dictionary> _vanillaDiffCache; //If param != vanillaparam
- internal AssetLocator AssetLocator;
- private Param EnemyParam;
+ private Param EnemyParam => _params["EnemyParam"];
- public static bool IsDefsLoaded { get; private set; }
+ public bool IsDefsLoaded { get; private set; }
public static bool IsMetaLoaded { get; private set; }
public bool IsLoadingParams { get; private set; }
@@ -172,6 +182,11 @@ public IReadOnlyDictionary> PrimaryDiffCache
}
}
+ public ParamBank(Project owner)
+ {
+ Project = owner;
+ }
+
private static FileNotFoundException CreateParamMissingException(GameType type)
{
if (type is GameType.DarkSoulsPTDE or GameType.Sekiro)
@@ -190,21 +205,23 @@ private static FileNotFoundException CreateParamMissingException(GameType type)
$"Cannot locate param files for {type}.\nYour game folder may be missing game files, please verify game files through steam to restore them.");
}
- private static List<(string, PARAMDEF)> LoadParamdefs(AssetLocator assetLocator)
+ private List<(string, PARAMDEF)> LoadParamdefs()
{
_paramdefs = new Dictionary();
_tentativeParamType = new Dictionary();
- var dir = assetLocator.GetParamdefDir();
- var files = Directory.GetFiles(dir, "*.xml");
+ var files = Project.AssetLocator.GetAllProjectFiles($@"Paramdex\{AssetUtils.GetGameIDForDir(Locator.ActiveProject.Type)}\Defs", ["*.xml"], true, false);
List<(string, PARAMDEF)> defPairs = new();
foreach (var f in files)
{
- PARAMDEF pdef = PARAMDEF.XmlDeserialize(f, true);
+ if (!_paramdefsCache.TryGetValue(f, out PARAMDEF pdef))
+ {
+ pdef = PARAMDEF.XmlDeserialize(f, true);
+ }
_paramdefs.Add(pdef.ParamType, pdef);
defPairs.Add((f, pdef));
}
- var tentativeMappingPath = assetLocator.GetTentativeParamTypePath();
+ var tentativeMappingPath = Project.AssetLocator.GetProjectFilePath($@"{Project.AssetLocator.GetParamdexDir()}\Defs\TentativeParamType.csv");
if (File.Exists(tentativeMappingPath))
{
// No proper CSV library is used currently, and all CSV parsing is in the context of param files.
@@ -223,23 +240,23 @@ private static FileNotFoundException CreateParamMissingException(GameType type)
return defPairs;
}
-
- public static void LoadParamMeta(List<(string, PARAMDEF)> defPairs, AssetLocator assetLocator)
+ public void LoadParamMeta(List<(string, PARAMDEF)> defPairs)
{
- var mdir = assetLocator.GetParammetaDir();
+ //This way of tying stuff together still sucks
+ var mdir = Project.AssetLocator.GetProjectFilePath($@"{Locator.ActiveProject.AssetLocator.GetParamdexDir()}\Meta");
foreach ((var f, PARAMDEF pdef) in defPairs)
{
var fName = f.Substring(f.LastIndexOf('\\') + 1);
- ParamMetaData.XmlDeserialize($@"{mdir}\{fName}", pdef);
+ var md = ParamMetaData.XmlDeserialize($@"{mdir}\{fName}", pdef);
+ ParamMetas.Add(pdef, md);
}
}
public CompoundAction LoadParamDefaultNames(string param = null, bool onlyAffectEmptyNames = false, bool onlyAffectVanillaNames = false)
{
- var dir = AssetLocator.GetParamNamesDir();
var files = param == null
- ? Directory.GetFiles(dir, "*.txt")
- : new[] { Path.Combine(dir, $"{param}.txt") };
+ ? Project.AssetLocator.GetAllProjectFiles($@"{Project.AssetLocator.GetParamdexDir()}\Names", ["*.txt"], true)
+ : new[] { Project.AssetLocator.GetProjectFilePath($@"{Project.AssetLocator.GetParamdexDir()}\Names\{param}.txt") };
List actions = new();
foreach (var f in files)
{
@@ -299,7 +316,7 @@ private void LoadParamFromBinder(IBinder parambnd, ref Dictionary
Param p;
- if (AssetLocator.Type == GameType.ArmoredCoreVI)
+ if (Project.Type == GameType.ArmoredCoreVI)
{
_usedTentativeParamTypes = new Dictionary();
p = Param.ReadIgnoreCompression(f.Bytes);
@@ -357,7 +374,7 @@ private void LoadParamFromBinder(IBinder parambnd, ref Dictionary
// Try to fixup Elden Ring ChrModelParam for ER 1.06 because many have been saving botched params and
// it's an easy fixup
- if (AssetLocator.Type == GameType.EldenRing &&
+ if (Project.Type == GameType.EldenRing &&
p.ParamType == "CHR_MODEL_PARAM_ST" &&
version == 10601000)
{
@@ -380,7 +397,7 @@ private void LoadParamFromBinder(IBinder parambnd, ref Dictionary
var name = f.Name.Split("\\").Last();
var message = $"Could not apply ParamDef for {name}";
- if (AssetLocator.Type == GameType.DarkSoulsRemastered &&
+ if (Project.Type == GameType.DarkSoulsRemastered &&
name is "m99_ToneMapBank.param" or "m99_ToneCorrectBank.param"
or "default_ToneCorrectBank.param")
{
@@ -396,101 +413,19 @@ name is "m99_ToneMapBank.param" or "m99_ToneCorrectBank.param"
}
}
}
-
- ///
- /// Checks for DeS paramBNDs and returns the name of the parambnd with the highest priority.
- ///
- private string GetDesGameparamName(string rootDirectory)
- {
- var name = "";
- name = "gameparamna.parambnd.dcx";
- if (File.Exists($@"{rootDirectory}\param\gameparam\{name}"))
- {
- return name;
- }
-
- name = "gameparamna.parambnd";
- if (File.Exists($@"{rootDirectory}\param\gameparam\{name}"))
- {
- return name;
- }
-
- name = "gameparam.parambnd.dcx";
- if (File.Exists($@"{rootDirectory}\param\gameparam\{name}"))
- {
- return name;
- }
-
- name = "gameparam.parambnd";
- if (File.Exists($@"{rootDirectory}\param\gameparam\{name}"))
- {
- return name;
- }
-
- return "";
- }
-
private void LoadParamsDES()
{
- var dir = AssetLocator.GameRootDirectory;
- var mod = AssetLocator.GameModDirectory;
-
- var paramBinderName = GetDesGameparamName(mod);
- if (paramBinderName == "")
- {
- paramBinderName = GetDesGameparamName(dir);
- }
-
- // Load params
- var param = $@"{mod}\param\gameparam\{paramBinderName}";
- if (!File.Exists(param))
- {
- param = $@"{dir}\param\gameparam\{paramBinderName}";
- }
-
- if (!File.Exists(param))
+ var param = Project.AssetLocator.GetAssetPathFromOptions([@$"\param\gameparam\gameparamna.parambnd.dcx", @$"\param\gameparam\gameparamna.parambnd", @$"\param\gameparam\gameparam.parambnd.dcx", @$"\param\gameparam\gameparam.parambnd"]).Item2;
+ if (param == null)
{
- throw CreateParamMissingException(AssetLocator.Type);
+ throw CreateParamMissingException(Project.Type);
}
-
LoadParamsDESFromFile(param);
- //DrawParam
- Dictionary drawparams = new();
- if (Directory.Exists($@"{dir}\param\drawparam"))
+ var drawparams = Project.AssetLocator.GetAllAssets($@"\param\drawparam", ["*.parambnd.dcx", "*.parambnd"]);
+ foreach (string drawparam in drawparams)
{
- foreach (var p in Directory.GetFiles($@"{dir}\param\drawparam", "*.parambnd.dcx"))
- {
- drawparams[Path.GetFileNameWithoutExtension(p)] = p;
- }
- }
-
- if (Directory.Exists($@"{mod}\param\drawparam"))
- {
- foreach (var p in Directory.GetFiles($@"{mod}\param\drawparam", "*.parambnd.dcx"))
- {
- drawparams[Path.GetFileNameWithoutExtension(p)] = p;
- }
- }
-
- foreach (KeyValuePair drawparam in drawparams)
- {
- LoadParamsDESFromFile(drawparam.Value);
- }
- }
-
- private void LoadVParamsDES()
- {
- var paramBinderName = GetDesGameparamName(AssetLocator.GameRootDirectory);
-
- LoadParamsDESFromFile($@"{AssetLocator.GameRootDirectory}\param\gameparam\{paramBinderName}");
- if (Directory.Exists($@"{AssetLocator.GameRootDirectory}\param\drawparam"))
- {
- foreach (var p in Directory.GetFiles($@"{AssetLocator.GameRootDirectory}\param\drawparam",
- "*.parambnd.dcx"))
- {
- LoadParamsDS1FromFile(p);
- }
+ LoadParamsDESFromFile(drawparam);
}
}
@@ -502,56 +437,17 @@ private void LoadParamsDESFromFile(string path)
private void LoadParamsDS1()
{
- var dir = AssetLocator.GameRootDirectory;
- var mod = AssetLocator.GameModDirectory;
- if (!File.Exists($@"{dir}\\param\GameParam\GameParam.parambnd"))
- {
- throw CreateParamMissingException(AssetLocator.Type);
- }
-
- // Load params
- var param = $@"{mod}\param\GameParam\GameParam.parambnd";
- if (!File.Exists(param))
+ var param = Project.AssetLocator.GetAssetPath($@"param\GameParam\GameParam.parambnd");
+ if (param == null)
{
- param = $@"{dir}\param\GameParam\GameParam.parambnd";
+ throw CreateParamMissingException(Project.Type);
}
-
LoadParamsDS1FromFile(param);
- //DrawParam
- Dictionary drawparams = new();
- if (Directory.Exists($@"{dir}\param\DrawParam"))
+ var drawparams = Project.AssetLocator.GetAllAssets($@"param\DrawParam", ["*.parambnd"]);
+ foreach (string drawparam in drawparams)
{
- foreach (var p in Directory.GetFiles($@"{dir}\param\DrawParam", "*.parambnd"))
- {
- drawparams[Path.GetFileNameWithoutExtension(p)] = p;
- }
- }
-
- if (Directory.Exists($@"{mod}\param\DrawParam"))
- {
- foreach (var p in Directory.GetFiles($@"{mod}\param\DrawParam", "*.parambnd"))
- {
- drawparams[Path.GetFileNameWithoutExtension(p)] = p;
- }
- }
-
- foreach (KeyValuePair drawparam in drawparams)
- {
- LoadParamsDS1FromFile(drawparam.Value);
- }
- }
-
- private void LoadVParamsDS1()
- {
- LoadParamsDS1FromFile($@"{AssetLocator.GameRootDirectory}\param\GameParam\GameParam.parambnd");
- if (Directory.Exists($@"{AssetLocator.GameRootDirectory}\param\DrawParam"))
- {
- foreach (var p in Directory.GetFiles($@"{AssetLocator.GameRootDirectory}\param\DrawParam",
- "*.parambnd"))
- {
- LoadParamsDS1FromFile(p);
- }
+ LoadParamsDS1FromFile(drawparam);
}
}
@@ -563,56 +459,17 @@ private void LoadParamsDS1FromFile(string path)
private void LoadParamsDS1R()
{
- var dir = AssetLocator.GameRootDirectory;
- var mod = AssetLocator.GameModDirectory;
- if (!File.Exists($@"{dir}\\param\GameParam\GameParam.parambnd.dcx"))
- {
- throw CreateParamMissingException(AssetLocator.Type);
- }
-
- // Load params
- var param = $@"{mod}\param\GameParam\GameParam.parambnd.dcx";
- if (!File.Exists(param))
+ var param = Project.AssetLocator.GetAssetPath($@"param\GameParam\GameParam.parambnd.dcx");
+ if (param == null)
{
- param = $@"{dir}\param\GameParam\GameParam.parambnd.dcx";
+ throw CreateParamMissingException(Project.Type);
}
-
LoadParamsDS1RFromFile(param);
- //DrawParam
- Dictionary drawparams = new();
- if (Directory.Exists($@"{dir}\param\DrawParam"))
- {
- foreach (var p in Directory.GetFiles($@"{dir}\param\DrawParam", "*.parambnd.dcx"))
- {
- drawparams[Path.GetFileNameWithoutExtension(p)] = p;
- }
- }
-
- if (Directory.Exists($@"{mod}\param\DrawParam"))
- {
- foreach (var p in Directory.GetFiles($@"{mod}\param\DrawParam", "*.parambnd.dcx"))
- {
- drawparams[Path.GetFileNameWithoutExtension(p)] = p;
- }
- }
-
- foreach (KeyValuePair drawparam in drawparams)
+ var drawparams = Project.AssetLocator.GetAllAssets($@"param\DrawParam", ["*.parambnd.dcx"]);
+ foreach (string drawparam in drawparams)
{
- LoadParamsDS1RFromFile(drawparam.Value);
- }
- }
-
- private void LoadVParamsDS1R()
- {
- LoadParamsDS1RFromFile($@"{AssetLocator.GameRootDirectory}\param\GameParam\GameParam.parambnd.dcx");
- if (Directory.Exists($@"{AssetLocator.GameRootDirectory}\param\DrawParam"))
- {
- foreach (var p in Directory.GetFiles($@"{AssetLocator.GameRootDirectory}\param\DrawParam",
- "*.parambnd.dcx"))
- {
- LoadParamsDS1FromFile(p);
- }
+ LoadParamsDS1RFromFile(drawparam);
}
}
@@ -624,28 +481,14 @@ private void LoadParamsDS1RFromFile(string path)
private void LoadParamsBBSekiro()
{
- var dir = AssetLocator.GameRootDirectory;
- var mod = AssetLocator.GameModDirectory;
- if (!File.Exists($@"{dir}\\param\gameparam\gameparam.parambnd.dcx"))
- {
- throw CreateParamMissingException(AssetLocator.Type);
- }
-
- // Load params
- var param = $@"{mod}\param\gameparam\gameparam.parambnd.dcx";
- if (!File.Exists(param))
+ var param = Project.AssetLocator.GetAssetPath($@"param\gameparam\gameparam.parambnd.dcx");
+ if (param == null)
{
- param = $@"{dir}\param\gameparam\gameparam.parambnd.dcx";
+ throw CreateParamMissingException(Project.Type);
}
-
LoadParamsBBSekiroFromFile(param);
}
- private void LoadVParamsBBSekiro()
- {
- LoadParamsBBSekiroFromFile($@"{AssetLocator.GameRootDirectory}\param\gameparam\gameparam.parambnd.dcx");
- }
-
private void LoadParamsBBSekiroFromFile(string path)
{
using BND4 bnd = BND4.Read(path);
@@ -665,75 +508,17 @@ private static List GetLooseParamsInDir(string dir)
private void LoadParamsDS2(bool loose)
{
- var dir = AssetLocator.GameRootDirectory;
- var mod = AssetLocator.GameModDirectory;
- if (!File.Exists($@"{dir}\enc_regulation.bnd.dcx"))
- {
- throw CreateParamMissingException(AssetLocator.Type);
- }
-
- if (!BND4.Is($@"{dir}\enc_regulation.bnd.dcx"))
- {
- PlatformUtils.Instance.MessageBox(
- "Attempting to decrypt DS2 regulation file, else functionality will be limited.", "",
- MessageBoxButtons.OK, MessageBoxIcon.Error);
- //return;
- }
-
- // Load loose params (prioritizing ones in mod folder)
- List looseParams = GetLooseParamsInDir(mod);
- if (Directory.Exists($@"{dir}\Param"))
- {
- // Include any params in game folder that are not in mod folder
- foreach (var path in Directory.GetFileSystemEntries($@"{dir}\Param", @"*.param"))
- {
- if (looseParams.Find(e => Path.GetFileName(e) == Path.GetFileName(path)) == null)
- {
- // Project folder does not contain this loose param
- looseParams.Add(path);
- }
- }
- }
-
- // Load reg params
- var param = $@"{mod}\enc_regulation.bnd.dcx";
- if (!File.Exists(param))
- {
- param = $@"{dir}\enc_regulation.bnd.dcx";
- }
-
- var enemyFile = $@"{mod}\Param\EnemyParam.param";
- if (!File.Exists(enemyFile))
+ var param = Project.AssetLocator.GetAssetPath($@"enc_regulation.bnd.dcx");
+ if (param == null)
{
- enemyFile = $@"{dir}\Param\EnemyParam.param";
+ throw CreateParamMissingException(Project.Type);
}
-
- LoadParamsDS2FromFile(looseParams, param, enemyFile, loose);
+ var looseParams = Project.AssetLocator.GetAllAssets($@"Param", [$@"*.param"]);
+ LoadParamsDS2FromFile(looseParams, param, loose);
LoadExternalRowNames();
}
- private void LoadVParamsDS2(bool loose)
- {
- if (!File.Exists($@"{AssetLocator.GameRootDirectory}\enc_regulation.bnd.dcx"))
- {
- throw CreateParamMissingException(AssetLocator.Type);
- }
-
- if (!BND4.Is($@"{AssetLocator.GameRootDirectory}\enc_regulation.bnd.dcx"))
- {
- PlatformUtils.Instance.MessageBox(
- "Attempting to decrypt DS2 regulation file, else functionality will be limited.", "",
- MessageBoxButtons.OK, MessageBoxIcon.Error);
- }
-
- // Load loose params
- List looseParams = GetLooseParamsInDir(AssetLocator.GameRootDirectory);
-
- LoadParamsDS2FromFile(looseParams, $@"{AssetLocator.GameRootDirectory}\enc_regulation.bnd.dcx",
- $@"{AssetLocator.GameRootDirectory}\Param\EnemyParam.param", loose);
- }
-
- private void LoadParamsDS2FromFile(List looseParams, string path, string enemypath, bool loose)
+ private void LoadParamsDS2FromFile(IEnumerable looseParams, string path, bool loose)
{
BND4 paramBnd;
if (!BND4.Is(path))
@@ -746,32 +531,6 @@ private void LoadParamsDS2FromFile(List looseParams, string path, string
paramBnd = BND4.Read(path);
}
- BinderFile bndfile = paramBnd.Files.Find(x => Path.GetFileName(x.Name) == "EnemyParam.param");
- if (bndfile != null)
- {
- EnemyParam = Param.Read(bndfile.Bytes);
- }
-
- // Otherwise the param is a loose param
- if (File.Exists(enemypath))
- {
- EnemyParam = Param.Read(enemypath);
- }
-
- if (EnemyParam is { ParamType: not null })
- {
- try
- {
- PARAMDEF def = _paramdefs[EnemyParam.ParamType];
- EnemyParam.ApplyParamdef(def);
- }
- catch (Exception e)
- {
- TaskLogs.AddLog($"Could not apply ParamDef for {EnemyParam.ParamType}",
- LogLevel.Warning, TaskLogs.LogPriority.Normal, e);
- }
- }
-
LoadParamFromBinder(paramBnd, ref _params, out _paramVersion);
foreach (var p in looseParams)
@@ -803,7 +562,7 @@ private void LoadParamsDS2FromFile(List looseParams, string path, string
catch (Exception e)
{
var message = $"Could not apply ParamDef for {fname}";
- if (AssetLocator.Type == GameType.DarkSoulsIISOTFS &&
+ if (Project.Type == GameType.DarkSoulsIISOTFS &&
fname is "GENERATOR_DBG_LOCATION_PARAM")
{
// Known cases that don't affect standard modmaking
@@ -823,34 +582,25 @@ private void LoadParamsDS2FromFile(List looseParams, string path, string
private void LoadParamsDS3(bool loose)
{
- var dir = AssetLocator.GameRootDirectory;
- var mod = AssetLocator.GameModDirectory;
- if (!File.Exists($@"{dir}\Data0.bdt"))
+ string param;
+ bool looseFile;
+ if (loose)
{
- throw CreateParamMissingException(AssetLocator.Type);
+ var p = Project.AssetLocator.GetAssetPathFromOptions([$@"param\gameparam\gameparam_dlc2.parambnd.dcx", $@"Data0.bdt"]);
+ looseFile = p.Item1 == 0;
+ param = p.Item2;
}
-
- var vparam = $@"{dir}\Data0.bdt";
- // Load loose params if they exist
- if (loose && File.Exists($@"{mod}\\param\gameparam\gameparam_dlc2.parambnd.dcx"))
+ else
{
- LoadParamsDS3FromFile($@"{mod}\param\gameparam\gameparam_dlc2.parambnd.dcx", true);
+ var p = Project.AssetLocator.GetAssetPathFromOptions([$@"Data0.bdt", $@"param\gameparam\gameparam_dlc2.parambnd.dcx"]);
+ looseFile = p.Item1 == 1;
+ param = p.Item2;
}
- else
+ if (param == null)
{
- var param = $@"{mod}\Data0.bdt";
- if (!File.Exists(param))
- {
- param = vparam;
- }
-
- LoadParamsDS3FromFile(param, false);
+ throw CreateParamMissingException(Project.Type);
}
- }
-
- private void LoadVParamsDS3()
- {
- LoadParamsDS3FromFile($@"{AssetLocator.GameRootDirectory}\Data0.bdt", false);
+ LoadParamsDS3FromFile(param, looseFile);
}
private void LoadParamsDS3FromFile(string path, bool isLoose)
@@ -859,55 +609,16 @@ private void LoadParamsDS3FromFile(string path, bool isLoose)
LoadParamFromBinder(lparamBnd, ref _params, out _paramVersion);
}
- private void LoadParamsER(bool partial)
+ private void LoadParamsER()
{
- var dir = AssetLocator.GameRootDirectory;
- var mod = AssetLocator.GameModDirectory;
- if (!File.Exists($@"{dir}\\regulation.bin"))
- {
- throw CreateParamMissingException(AssetLocator.Type);
- }
-
- // Load params
- var param = $@"{mod}\regulation.bin";
- if (!File.Exists(param) || partial)
+ var param = Project.AssetLocator.GetAssetPath($@"regulation.bin");
+ if (param == null)
{
- param = $@"{dir}\regulation.bin";
+ throw CreateParamMissingException(Project.Type);
}
-
LoadParamsERFromFile(param);
- param = $@"{mod}\regulation.bin";
- if (partial && File.Exists(param))
- {
- using BND4 pParamBnd = SFUtil.DecryptERRegulation(param);
- Dictionary cParamBank = new();
- ulong v;
- LoadParamFromBinder(pParamBnd, ref cParamBank, out v, true);
- foreach (KeyValuePair pair in cParamBank)
- {
- Param baseParam = _params[pair.Key];
- foreach (Param.Row row in pair.Value.Rows)
- {
- Param.Row bRow = baseParam[row.ID];
- if (bRow == null)
- {
- baseParam.AddRow(row);
- }
- else
- {
- bRow.Name = row.Name;
- foreach (Param.Column field in bRow.Columns)
- {
- Param.Cell cell = bRow[field];
- cell.Value = row[field].Value;
- }
- }
- }
- }
- }
-
- string sysParam = AssetLocator.GetAssetPath(@"param\systemparam\systemparam.parambnd.dcx");
+ string sysParam = Project.AssetLocator.GetAssetPath(@"param\systemparam\systemparam.parambnd.dcx");
if (File.Exists(sysParam))
{
LoadParamsERFromFile(sysParam, false);
@@ -917,7 +628,7 @@ private void LoadParamsER(bool partial)
TaskLogs.AddLog("Systemparam could not be found. These require an unpacked game to modify.", LogLevel.Information, TaskLogs.LogPriority.Normal);
}
- var eventParam = AssetLocator.GetAssetPath(@"param\eventparam\eventparam.parambnd.dcx");
+ var eventParam = Project.AssetLocator.GetAssetPath(@"param\eventparam\eventparam.parambnd.dcx");
if (File.Exists(eventParam))
{
LoadParamsERFromFile(eventParam, false);
@@ -928,23 +639,6 @@ private void LoadParamsER(bool partial)
}
}
- private void LoadVParamsER()
- {
- LoadParamsERFromFile($@"{AssetLocator.GameRootDirectory}\regulation.bin");
-
- var sysParam = $@"{AssetLocator.GameRootDirectory}\param\systemparam\systemparam.parambnd.dcx";
- if (File.Exists(sysParam))
- {
- LoadParamsERFromFile(sysParam, false);
- }
-
- var eventParam = $@"{AssetLocator.GameRootDirectory}\param\eventparam\eventparam.parambnd.dcx";
- if (File.Exists(eventParam))
- {
- LoadParamsERFromFile(eventParam, false);
- }
- }
-
private void LoadParamsERFromFile(string path, bool encrypted = true)
{
if (encrypted)
@@ -961,24 +655,15 @@ private void LoadParamsERFromFile(string path, bool encrypted = true)
private void LoadParamsAC6()
{
- var dir = AssetLocator.GameRootDirectory;
- var mod = AssetLocator.GameModDirectory;
- if (!File.Exists($@"{dir}\\regulation.bin"))
- {
- throw CreateParamMissingException(AssetLocator.Type);
- }
-
- // Load params
- var param = $@"{mod}\regulation.bin";
- if (!File.Exists(param))
+ var param = Project.AssetLocator.GetAssetPath($@"regulation.bin");
+ if (param == null)
{
- param = $@"{dir}\regulation.bin";
+ throw CreateParamMissingException(Project.Type);
}
-
LoadParamsAC6FromFile(param, true);
- string sysParam = AssetLocator.GetAssetPath(@"param\systemparam\systemparam.parambnd.dcx");
- if (File.Exists(sysParam))
+ string sysParam = Project.AssetLocator.GetAssetPath(@"param\systemparam\systemparam.parambnd.dcx");
+ if (sysParam != null)
{
LoadParamsAC6FromFile(sysParam, false);
}
@@ -987,8 +672,8 @@ private void LoadParamsAC6()
TaskLogs.AddLog("Systemparam could not be found. These require an unpacked game to modify.", LogLevel.Information, TaskLogs.LogPriority.Normal);
}
- string graphicsConfigParam = AssetLocator.GetAssetPath(@"param\graphicsconfig\graphicsconfig.parambnd.dcx");
- if (File.Exists(graphicsConfigParam))
+ string graphicsConfigParam = Project.AssetLocator.GetAssetPath(@"param\graphicsconfig\graphicsconfig.parambnd.dcx");
+ if (graphicsConfigParam != null)
{
LoadParamsAC6FromFile(graphicsConfigParam, false);
}
@@ -997,8 +682,8 @@ private void LoadParamsAC6()
TaskLogs.AddLog("Graphicsconfig could not be found. These require an unpacked game to modify.", LogLevel.Information, TaskLogs.LogPriority.Normal);
}
- string eventParam = AssetLocator.GetAssetPath(@"param\eventparam\eventparam.parambnd.dcx");
- if (File.Exists(eventParam))
+ string eventParam = Project.AssetLocator.GetAssetPath(@"param\eventparam\eventparam.parambnd.dcx");
+ if (eventParam != null)
{
LoadParamsAC6FromFile(eventParam, false);
}
@@ -1008,29 +693,6 @@ private void LoadParamsAC6()
}
}
- private void LoadVParamsAC6()
- {
- LoadParamsAC6FromFile($@"{AssetLocator.GameRootDirectory}\regulation.bin");
-
- var sysParam = $@"{AssetLocator.GameRootDirectory}\param\systemparam\systemparam.parambnd.dcx";
- if (File.Exists(sysParam))
- {
- LoadParamsAC6FromFile(sysParam, false);
- }
-
- var graphicsConfigParam = $@"{AssetLocator.GameRootDirectory}\param\graphicsconfig\graphicsconfig.parambnd.dcx";
- if (File.Exists(graphicsConfigParam))
- {
- LoadParamsAC6FromFile(graphicsConfigParam, false);
- }
-
- var eventParam = $@"{AssetLocator.GameRootDirectory}\param\eventparam\eventparam.parambnd.dcx";
- if (File.Exists(eventParam))
- {
- LoadParamsAC6FromFile(eventParam, false);
- }
- }
-
private void LoadParamsAC6FromFile(string path, bool encrypted = true)
{
if (encrypted)
@@ -1045,131 +707,94 @@ private void LoadParamsAC6FromFile(string path, bool encrypted = true)
}
}
- //Some returns and repetition, but it keeps all threading and loading-flags visible inside this method
- public static void ReloadParams(ProjectSettings settings, NewProjectOptions options)
+ private void LoadParams()
{
- // Steal assetlocator from PrimaryBank.
- AssetLocator locator = PrimaryBank.AssetLocator;
- _paramdefs = new Dictionary();
IsDefsLoaded = false;
- IsMetaLoaded = false;
-
- AuxBanks = new Dictionary();
-
- PrimaryBank._params = new Dictionary();
- PrimaryBank.IsLoadingParams = true;
-
- UICache.ClearCaches();
-
- TaskManager.Run(new TaskManager.LiveTask("Param - Load Params", TaskManager.RequeueType.WaitThenRequeue,
- false, () =>
- {
- if (PrimaryBank.AssetLocator.Type != GameType.Undefined)
- {
- List<(string, PARAMDEF)> defPairs = LoadParamdefs(locator);
- IsDefsLoaded = true;
- TaskManager.Run(new TaskManager.LiveTask("Param - Load Meta",
- TaskManager.RequeueType.WaitThenRequeue, false, () =>
- {
- LoadParamMeta(defPairs, locator);
- IsMetaLoaded = true;
- }));
- }
-
- if (locator.Type == GameType.DemonsSouls)
- {
- PrimaryBank.LoadParamsDES();
- }
+ IsLoadingParams = true;
- if (locator.Type == GameType.DarkSoulsPTDE)
- {
- PrimaryBank.LoadParamsDS1();
- }
+ _params = new Dictionary();
- if (locator.Type == GameType.DarkSoulsRemastered)
+ if (Project.Type != GameType.Undefined)
+ {
+ List<(string, PARAMDEF)> defPairs = LoadParamdefs();
+ IsDefsLoaded = true;
+ TaskManager.Run(new TaskManager.LiveTask("Param - Load Meta",
+ TaskManager.RequeueType.WaitThenRequeue, false, () =>
{
- PrimaryBank.LoadParamsDS1R();
- }
+ LoadParamMeta(defPairs);
+ IsMetaLoaded = true;
+ }));
+ }
- if (locator.Type == GameType.DarkSoulsIISOTFS)
- {
- PrimaryBank.LoadParamsDS2(settings.UseLooseParams);
- }
+ if (Project.Type == GameType.DemonsSouls)
+ {
+ LoadParamsDES();
+ }
- if (locator.Type == GameType.DarkSoulsIII)
- {
- PrimaryBank.LoadParamsDS3(settings.UseLooseParams);
- }
+ if (Project.Type == GameType.DarkSoulsPTDE)
+ {
+ LoadParamsDS1();
+ }
- if (locator.Type == GameType.Bloodborne || locator.Type == GameType.Sekiro)
- {
- PrimaryBank.LoadParamsBBSekiro();
- }
+ if (Project.Type == GameType.DarkSoulsRemastered)
+ {
+ LoadParamsDS1R();
+ }
- if (locator.Type == GameType.EldenRing)
- {
- PrimaryBank.LoadParamsER(settings.PartialParams);
- }
+ if (Project.Type == GameType.DarkSoulsIISOTFS)
+ {
+ LoadParamsDS2(Project.Settings.UseLooseParams);
+ }
- if (locator.Type == GameType.ArmoredCoreVI)
- {
- PrimaryBank.LoadParamsAC6();
- }
+ if (Project.Type == GameType.DarkSoulsIII)
+ {
+ LoadParamsDS3(Project.Settings.UseLooseParams);
+ }
- PrimaryBank.ClearParamDiffCaches();
- PrimaryBank.IsLoadingParams = false;
+ if (Project.Type == GameType.Bloodborne || Project.Type == GameType.Sekiro)
+ {
+ LoadParamsBBSekiro();
+ }
- VanillaBank.IsLoadingParams = true;
- VanillaBank._params = new Dictionary();
- TaskManager.Run(new TaskManager.LiveTask("Param - Load Vanilla Params",
- TaskManager.RequeueType.WaitThenRequeue, false, () =>
- {
- if (locator.Type == GameType.DemonsSouls)
- {
- VanillaBank.LoadVParamsDES();
- }
+ if (Project.Type == GameType.EldenRing)
+ {
+ LoadParamsER();
+ }
- if (locator.Type == GameType.DarkSoulsPTDE)
- {
- VanillaBank.LoadVParamsDS1();
- }
+ if (Project.Type == GameType.ArmoredCoreVI)
+ {
+ LoadParamsAC6();
+ }
- if (locator.Type == GameType.DarkSoulsRemastered)
- {
- VanillaBank.LoadVParamsDS1R();
- }
+ ClearParamDiffCaches();
- if (locator.Type == GameType.DarkSoulsIISOTFS)
- {
- VanillaBank.LoadVParamsDS2(settings.UseLooseParams);
- }
+ IsLoadingParams = false;
+ }
- if (locator.Type == GameType.DarkSoulsIII)
- {
- VanillaBank.LoadVParamsDS3();
- }
+ //Some returns and repetition, but it keeps all threading and loading-flags visible inside this method
+ public static void ReloadParams(ProjectSettings settings, NewProjectOptions options)
+ {
+ IsMetaLoaded = false;
- if (locator.Type == GameType.Bloodborne || locator.Type == GameType.Sekiro)
- {
- VanillaBank.LoadVParamsBBSekiro();
- }
+ AuxBanks = new Dictionary();
- if (locator.Type == GameType.EldenRing)
- {
- VanillaBank.LoadVParamsER();
- }
+ UICache.ClearCaches();
- if (locator.Type == GameType.ArmoredCoreVI)
- {
- VanillaBank.LoadVParamsAC6();
- }
+ TaskManager.Run(new TaskManager.LiveTask("Param - Load Params", TaskManager.RequeueType.WaitThenRequeue,
+ false, () =>
+ {
+ PrimaryBank.LoadParams();
- VanillaBank.IsLoadingParams = false;
+ TaskManager.Run(new TaskManager.LiveTask("Param - Load Vanilla Params",
+ TaskManager.RequeueType.WaitThenRequeue, false, () =>
+ {
+ VanillaBank.LoadParams();
TaskManager.Run(new TaskManager.LiveTask("Param - Check Differences",
TaskManager.RequeueType.WaitThenRequeue, false,
() => RefreshAllParamDiffCaches(true)));
+ UICache.ClearCaches();
}));
if (options != null)
@@ -1188,59 +813,20 @@ public static void ReloadParams(ProjectSettings settings, NewProjectOptions opti
}
}
}
+ UICache.ClearCaches();
}));
}
- public static void LoadAuxBank(string path, string looseDir, string enemyPath, ProjectSettings settings)
+ public static void LoadAuxBank(string dir, ProjectSettings settings = null)
{
- // Steal assetlocator
- AssetLocator locator = PrimaryBank.AssetLocator;
- ParamBank newBank = new();
- newBank.SetAssetLocator(locator);
- newBank._params = new Dictionary();
- newBank.IsLoadingParams = true;
- if (locator.Type == GameType.ArmoredCoreVI)
- {
- newBank.LoadParamsAC6FromFile(path);
- }
- else if (locator.Type == GameType.EldenRing)
- {
- newBank.LoadParamsERFromFile(path);
- }
- else if (locator.Type == GameType.Sekiro)
- {
- newBank.LoadParamsBBSekiroFromFile(path);
- }
- else if (locator.Type == GameType.DarkSoulsIII)
- {
- newBank.LoadParamsDS3FromFile(path, path.Trim().ToLower().EndsWith(".dcx"));
- }
- else if (locator.Type == GameType.Bloodborne)
- {
- newBank.LoadParamsBBSekiroFromFile(path);
- }
- else if (locator.Type == GameType.DarkSoulsIISOTFS)
- {
- List looseParams = GetLooseParamsInDir(looseDir);
- newBank.LoadParamsDS2FromFile(looseParams, path, enemyPath, settings.UseLooseParams);
- }
- else if (locator.Type == GameType.DarkSoulsRemastered)
- {
- newBank.LoadParamsDS1RFromFile(path);
- }
- else if (locator.Type == GameType.DarkSoulsPTDE)
- {
- newBank.LoadParamsDS1FromFile(path);
- }
- else if (locator.Type == GameType.DemonsSouls)
- {
- newBank.LoadParamsDESFromFile(path);
- }
+ // skip the meme and just treat as project
+ Project siblingVirtualProject = new Project(dir, Locator.ActiveProject.ParentProject, settings);
+ ParamBank newBank = siblingVirtualProject.ParamBank;
+
+ newBank.LoadParams();
- newBank.ClearParamDiffCaches();
- newBank.IsLoadingParams = false;
newBank.RefreshParamDiffCaches(true);
- AuxBanks[Path.GetFileName(Path.GetDirectoryName(path)).Replace(' ', '_')] = newBank;
+ AuxBanks[Path.GetFileName(dir).Replace(' ', '_')] = newBank;
}
@@ -1411,31 +997,17 @@ private static bool IsChanged(Param.Row row, ReadOnlySpan vanillaRows
return true;
}
-
- public void SetAssetLocator(AssetLocator l)
- {
- AssetLocator = l;
- //ReloadParams();
- }
-
private void SaveParamsDS1()
{
- var dir = AssetLocator.GameRootDirectory;
- var mod = AssetLocator.GameModDirectory;
- if (!File.Exists($@"{dir}\\param\GameParam\GameParam.parambnd"))
+ var dir = Project.ParentProject.AssetLocator.RootDirectory;
+ var mod = Project.AssetLocator.RootDirectory;
+ var param = Project.AssetLocator.GetAssetPath($@"param\GameParam\GameParam.parambnd");
+ if (param == null)
{
TaskLogs.AddLog("Cannot locate param files. Save failed.",
LogLevel.Error, TaskLogs.LogPriority.High);
return;
}
-
- // Load params
- var param = $@"{mod}\param\GameParam\GameParam.parambnd";
- if (!File.Exists(param))
- {
- param = $@"{dir}\param\GameParam\GameParam.parambnd";
- }
-
using BND3 paramBnd = BND3.Read(param);
// Replace params with edited ones
@@ -1450,43 +1022,32 @@ private void SaveParamsDS1()
Utils.WriteWithBackup(dir, mod, @"param\GameParam\GameParam.parambnd", paramBnd);
// Drawparam
- if (Directory.Exists($@"{AssetLocator.GameRootDirectory}\param\DrawParam"))
+ foreach (var bnd in Project.AssetLocator.GetAllAssets($@"param\DrawParam", [$@"*.parambnd"]))
{
- foreach (var bnd in Directory.GetFiles($@"{AssetLocator.GameRootDirectory}\param\DrawParam",
- "*.parambnd"))
+ using BND3 drawParamBnd = BND3.Read(bnd);
+ foreach (BinderFile p in drawParamBnd.Files)
{
- using BND3 drawParamBnd = BND3.Read(bnd);
- foreach (BinderFile p in drawParamBnd.Files)
+ if (_params.ContainsKey(Path.GetFileNameWithoutExtension(p.Name)))
{
- if (_params.ContainsKey(Path.GetFileNameWithoutExtension(p.Name)))
- {
- p.Bytes = _params[Path.GetFileNameWithoutExtension(p.Name)].Write();
- }
+ p.Bytes = _params[Path.GetFileNameWithoutExtension(p.Name)].Write();
}
-
- Utils.WriteWithBackup(dir, mod, @$"param\DrawParam\{Path.GetFileName(bnd)}", drawParamBnd);
}
+
+ Utils.WriteWithBackup(dir, mod, @$"param\DrawParam\{Path.GetFileName(bnd)}", drawParamBnd);
}
}
private void SaveParamsDS1R()
{
- var dir = AssetLocator.GameRootDirectory;
- var mod = AssetLocator.GameModDirectory;
- if (!File.Exists($@"{dir}\\param\GameParam\GameParam.parambnd.dcx"))
+ var dir = Project.ParentProject.AssetLocator.RootDirectory;
+ var mod = Project.AssetLocator.RootDirectory;
+ var param = Project.AssetLocator.GetAssetPath($@"param\GameParam\GameParam.parambnd.dcx");
+ if (param == null)
{
TaskLogs.AddLog("Cannot locate param files. Save failed.",
LogLevel.Error, TaskLogs.LogPriority.High);
return;
}
-
- // Load params
- var param = $@"{mod}\param\GameParam\GameParam.parambnd.dcx";
- if (!File.Exists(param))
- {
- param = $@"{dir}\param\GameParam\GameParam.parambnd.dcx";
- }
-
using BND3 paramBnd = BND3.Read(param);
// Replace params with edited ones
@@ -1501,30 +1062,27 @@ private void SaveParamsDS1R()
Utils.WriteWithBackup(dir, mod, @"param\GameParam\GameParam.parambnd.dcx", paramBnd);
// Drawparam
- if (Directory.Exists($@"{AssetLocator.GameRootDirectory}\param\DrawParam"))
+ foreach (var bnd in Project.AssetLocator.GetAllAssets($@"param\DrawParam", ["*.parambnd.dcx"]))
{
- foreach (var bnd in Directory.GetFiles($@"{AssetLocator.GameRootDirectory}\param\DrawParam",
- "*.parambnd.dcx"))
+ using BND3 drawParamBnd = BND3.Read(bnd);
+ foreach (BinderFile p in drawParamBnd.Files)
{
- using BND3 drawParamBnd = BND3.Read(bnd);
- foreach (BinderFile p in drawParamBnd.Files)
+ if (_params.ContainsKey(Path.GetFileNameWithoutExtension(p.Name)))
{
- if (_params.ContainsKey(Path.GetFileNameWithoutExtension(p.Name)))
- {
- p.Bytes = _params[Path.GetFileNameWithoutExtension(p.Name)].Write();
- }
+ p.Bytes = _params[Path.GetFileNameWithoutExtension(p.Name)].Write();
}
-
- Utils.WriteWithBackup(dir, mod, @$"param\DrawParam\{Path.GetFileName(bnd)}", drawParamBnd);
}
+
+ Utils.WriteWithBackup(dir, mod, @$"param\DrawParam\{Path.GetFileName(bnd)}", drawParamBnd);
}
}
private void SaveParamsDS2(bool loose)
{
- var dir = AssetLocator.GameRootDirectory;
- var mod = AssetLocator.GameModDirectory;
- if (!File.Exists($@"{dir}\enc_regulation.bnd.dcx"))
+ var dir = Project.ParentProject.AssetLocator.RootDirectory;
+ var mod = Project.AssetLocator.RootDirectory;
+ var param = Project.AssetLocator.GetAssetPath($@"enc_regulation.bnd.dcx");
+ if (param == null)
{
TaskLogs.AddLog("Cannot locate param files. Save failed.",
LogLevel.Error, TaskLogs.LogPriority.High);
@@ -1532,31 +1090,20 @@ private void SaveParamsDS2(bool loose)
}
// Load params
- var param = $@"{mod}\enc_regulation.bnd.dcx";
BND4 paramBnd;
- if (!File.Exists(param))
+ if (!BND4.Is(param))
{
- // If there is no mod file, check the base file. Decrypt it if you have to.
- param = $@"{dir}\enc_regulation.bnd.dcx";
- if (!BND4.Is($@"{dir}\enc_regulation.bnd.dcx"))
- {
- // Decrypt the file
- paramBnd = SFUtil.DecryptDS2Regulation(param);
+ // Decrypt the file
+ paramBnd = SFUtil.DecryptDS2Regulation(param);
- // Since the file is encrypted, check for a backup. If it has none, then make one and write a decrypted one.
- if (!File.Exists($@"{param}.bak"))
- {
- File.Copy(param, $@"{param}.bak", true);
- paramBnd.Write(param);
- }
- }
- // No need to decrypt
- else
+ // Since the file is encrypted, check for a backup. If it has none, then make one and write a decrypted one.
+ if (!File.Exists($@"{param}.bak"))
{
- paramBnd = BND4.Read(param);
+ File.Copy(param, $@"{param}.bak", true);
+ paramBnd.Write(param);
}
}
- // Mod file exists, use that.
+ // No need to decrypt
else
{
paramBnd = BND4.Read(param);
@@ -1665,22 +1212,28 @@ private void SaveParamsDS2(bool loose)
private void SaveParamsDS3(bool loose)
{
- var dir = AssetLocator.GameRootDirectory;
- var mod = AssetLocator.GameModDirectory;
- if (!File.Exists($@"{dir}\Data0.bdt"))
+ var dir = Project.ParentProject.AssetLocator.RootDirectory;
+ var mod = Project.AssetLocator.RootDirectory;
+ string param;
+ bool looseFile;
+ if (loose)
+ {
+ var p = Project.AssetLocator.GetAssetPathFromOptions([$@"param\gameparam\gameparam_dlc2.parambnd.dcx", $@"Data0.bdt"]);
+ looseFile = p.Item1 == 0;
+ param = p.Item2;
+ }
+ else
+ {
+ var p = Project.AssetLocator.GetAssetPathFromOptions([$@"Data0.bdt", $@"param\gameparam\gameparam_dlc2.parambnd.dcx"]);
+ looseFile = p.Item1 != 1;
+ param = p.Item2;
+ }
+ if (param == null)
{
TaskLogs.AddLog("Cannot locate param files. Save failed.",
LogLevel.Error, TaskLogs.LogPriority.High);
return;
}
-
- // Load params
- var param = $@"{mod}\Data0.bdt";
- if (!File.Exists(param))
- {
- param = $@"{dir}\Data0.bdt";
- }
-
BND4 paramBnd = SFUtil.DecryptDS3Regulation(param);
// Replace params with edited ones
@@ -1712,42 +1265,21 @@ private void SaveParamsDS3(bool loose)
Unicode = true,
Files = paramBnd.Files.Where(f => f.Name.EndsWith(".param")).ToList()
};
-
- /*BND4 stayBND = new BND4
- {
- BigEndian = false,
- Compression = DCX.Type.DCX_DFLT_10000_44_9,
- Extended = 0x04,
- Unk04 = false,
- Unk05 = false,
- Format = Binder.Format.Compression | Binder.Format.Flag6 | Binder.Format.LongOffsets | Binder.Format.Names1,
- Unicode = true,
- Files = paramBnd.Files.Where(f => f.Name.EndsWith(".stayparam")).ToList()
- };*/
-
Utils.WriteWithBackup(dir, mod, @"param\gameparam\gameparam_dlc2.parambnd.dcx", paramBND);
- //Utils.WriteWithBackup(dir, mod, @"param\stayparam\stayparam.parambnd.dcx", stayBND);
}
}
private void SaveParamsBBSekiro()
{
- var dir = AssetLocator.GameRootDirectory;
- var mod = AssetLocator.GameModDirectory;
- if (!File.Exists($@"{dir}\\param\gameparam\gameparam.parambnd.dcx"))
+ var dir = Project.ParentProject.AssetLocator.RootDirectory;
+ var mod = Project.AssetLocator.RootDirectory;
+ var param = Project.AssetLocator.GetAssetPath($@"param\gameparam\gameparam.parambnd.dcx");
+ if (param == null)
{
TaskLogs.AddLog("Cannot locate param files. Save failed.",
LogLevel.Error, TaskLogs.LogPriority.High);
return;
}
-
- // Load params
- var param = $@"{mod}\param\gameparam\gameparam.parambnd.dcx";
- if (!File.Exists(param))
- {
- param = $@"{dir}\param\gameparam\gameparam.parambnd.dcx";
- }
-
BND4 paramBnd = BND4.Read(param);
// Replace params with edited ones
@@ -1764,23 +1296,11 @@ private void SaveParamsBBSekiro()
private void SaveParamsDES()
{
- var dir = AssetLocator.GameRootDirectory;
- var mod = AssetLocator.GameModDirectory;
+ var dir = Project.ParentProject.AssetLocator.RootDirectory;
+ var mod = Project.AssetLocator.RootDirectory;
+ var param = Project.ParentProject.AssetLocator.GetAssetPathFromOptions([@$"\param\gameparam\gameparamna.parambnd.dcx", @$"\param\gameparam\gameparamna.parambnd", @$"\param\gameparam\gameparam.parambnd.dcx", @$"\param\gameparam\gameparam.parambnd"]).Item2;
- var paramBinderName = GetDesGameparamName(mod);
- if (paramBinderName == "")
- {
- paramBinderName = GetDesGameparamName(dir);
- }
-
- // Load params
- var param = $@"{mod}\param\gameparam\{paramBinderName}";
- if (!File.Exists(param))
- {
- param = $@"{dir}\param\gameparam\{paramBinderName}";
- }
-
- if (!File.Exists(param))
+ if (param == null)
{
TaskLogs.AddLog("Cannot locate param files. Save failed.",
LogLevel.Error, TaskLogs.LogPriority.High);
@@ -1820,39 +1340,23 @@ private void SaveParamsDES()
Utils.WriteWithBackup(dir, mod, @"param\gameparam\gameparam.parambnd", paramBnd);
// Drawparam
- List drawParambndPaths = new();
- if (Directory.Exists($@"{AssetLocator.GameRootDirectory}\param\drawparam"))
+ var drawparambnds = Project.AssetLocator.GetAllAssets($@"param\drawparam", ["*.parambnd.dcx", "*.parambnd"]);
+ foreach (var bnd in drawparambnds)
{
- foreach (var bnd in Directory.GetFiles($@"{AssetLocator.GameRootDirectory}\param\drawparam",
- "*.parambnd.dcx"))
- {
- drawParambndPaths.Add(bnd);
- }
-
- // Also save decompressed parambnds because DeS debug uses them.
- foreach (var bnd in Directory.GetFiles($@"{AssetLocator.GameRootDirectory}\param\drawparam",
- "*.parambnd"))
+ using BND3 drawParamBnd = BND3.Read(bnd);
+ foreach (BinderFile p in drawParamBnd.Files)
{
- drawParambndPaths.Add(bnd);
- }
-
- foreach (var bnd in drawParambndPaths)
- {
- using BND3 drawParamBnd = BND3.Read(bnd);
- foreach (BinderFile p in drawParamBnd.Files)
+ if (_params.ContainsKey(Path.GetFileNameWithoutExtension(p.Name)))
{
- if (_params.ContainsKey(Path.GetFileNameWithoutExtension(p.Name)))
- {
- p.Bytes = _params[Path.GetFileNameWithoutExtension(p.Name)].Write();
- }
+ p.Bytes = _params[Path.GetFileNameWithoutExtension(p.Name)].Write();
}
-
- Utils.WriteWithBackup(dir, mod, @$"param\drawparam\{Path.GetFileName(bnd)}", drawParamBnd);
}
+
+ Utils.WriteWithBackup(dir, mod, @$"param\drawparam\{Path.GetFileName(bnd)}", drawParamBnd);
}
}
- private void SaveParamsER(bool partial)
+ private void SaveParamsER()
{
void OverwriteParamsER(BND4 paramBnd)
{
@@ -1862,59 +1366,34 @@ void OverwriteParamsER(BND4 paramBnd)
if (_params.ContainsKey(Path.GetFileNameWithoutExtension(p.Name)))
{
Param paramFile = _params[Path.GetFileNameWithoutExtension(p.Name)];
- IReadOnlyList backup = paramFile.Rows;
- List changed = new();
- if (partial)
- {
- TaskManager.WaitAll(); //wait on dirtycache update
- HashSet dirtyCache = _vanillaDiffCache[Path.GetFileNameWithoutExtension(p.Name)];
- foreach (Param.Row row in paramFile.Rows)
- {
- if (dirtyCache.Contains(row.ID))
- {
- changed.Add(row);
- }
- }
-
- paramFile.Rows = changed;
- }
-
p.Bytes = paramFile.Write();
- paramFile.Rows = backup;
}
}
}
- var dir = AssetLocator.GameRootDirectory;
- var mod = AssetLocator.GameModDirectory;
- if (!File.Exists($@"{dir}\\regulation.bin"))
+ var dir = Project.ParentProject.AssetLocator.RootDirectory;
+ var mod = Project.AssetLocator.RootDirectory;
+ var param = Project.AssetLocator.GetAssetPath($@"regulation.bin");
+ if (param == null)
{
TaskLogs.AddLog("Cannot locate param files. Save failed.",
LogLevel.Error, TaskLogs.LogPriority.High);
return;
}
-
- // Load params
- var param = $@"{mod}\regulation.bin";
- if (!File.Exists(param) || _pendingUpgrade)
- {
- param = $@"{dir}\regulation.bin";
- }
-
BND4 regParams = SFUtil.DecryptERRegulation(param);
OverwriteParamsER(regParams);
Utils.WriteWithBackup(dir, mod, @"regulation.bin", regParams, GameType.EldenRing);
- string sysParam = AssetLocator.GetAssetPath(@"param\systemparam\systemparam.parambnd.dcx");
- if (File.Exists(sysParam))
+ string sysParam = Project.AssetLocator.GetAssetPath(@"param\systemparam\systemparam.parambnd.dcx");
+ if (sysParam != null)
{
using BND4 sysParams = BND4.Read(sysParam);
OverwriteParamsER(sysParams);
Utils.WriteWithBackup(dir, mod, @"param\systemparam\systemparam.parambnd.dcx", sysParams);
}
- var eventParam = AssetLocator.GetAssetPath(@"param\eventparam\eventparam.parambnd.dcx");
- if (File.Exists(eventParam))
+ var eventParam = Project.AssetLocator.GetAssetPath(@"param\eventparam\eventparam.parambnd.dcx");
+ if (sysParam != null)
{
using var eventParams = BND4.Read(eventParam);
OverwriteParamsER(eventParams);
@@ -1935,7 +1414,7 @@ void OverwriteParamsAC6(BND4 paramBnd)
if (_params.TryGetValue(paramName, out Param paramFile))
{
IReadOnlyList backup = paramFile.Rows;
- if (AssetLocator.Type is GameType.ArmoredCoreVI)
+ if (Project.Type is GameType.ArmoredCoreVI)
{
if (_usedTentativeParamTypes.TryGetValue(paramName, out var oldParamType))
{
@@ -1957,44 +1436,37 @@ void OverwriteParamsAC6(BND4 paramBnd)
}
}
- var dir = AssetLocator.GameRootDirectory;
- var mod = AssetLocator.GameModDirectory;
- if (!File.Exists($@"{dir}\\regulation.bin"))
+ var dir = Project.ParentProject.AssetLocator.RootDirectory;
+ var mod = Project.AssetLocator.RootDirectory;
+ var param = Project.AssetLocator.GetAssetPath($@"regulation.bin");
+ if (param == null)
{
TaskLogs.AddLog("Cannot locate param files. Save failed.",
LogLevel.Error, TaskLogs.LogPriority.High);
return;
}
-
- // Load params
- var param = $@"{mod}\regulation.bin";
- if (!File.Exists(param) || _pendingUpgrade)
- {
- param = $@"{dir}\regulation.bin";
- }
-
BND4 regParams = SFUtil.DecryptAC6Regulation(param);
OverwriteParamsAC6(regParams);
Utils.WriteWithBackup(dir, mod, @"regulation.bin", regParams, GameType.ArmoredCoreVI);
- string sysParam = AssetLocator.GetAssetPath(@"param\systemparam\systemparam.parambnd.dcx");
- if (File.Exists(sysParam))
+ string sysParam = Project.AssetLocator.GetAssetPath(@"param\systemparam\systemparam.parambnd.dcx");
+ if (sysParam != null)
{
using BND4 sysParams = BND4.Read(sysParam);
OverwriteParamsAC6(sysParams);
Utils.WriteWithBackup(dir, mod, @"param\systemparam\systemparam.parambnd.dcx", sysParams);
}
- string graphicsConfigParam = AssetLocator.GetAssetPath(@"param\graphicsconfig\graphicsconfig.parambnd.dcx");
- if (File.Exists(graphicsConfigParam))
+ string graphicsConfigParam = Project.AssetLocator.GetAssetPath(@"param\graphicsconfig\graphicsconfig.parambnd.dcx");
+ if (graphicsConfigParam != null)
{
using BND4 graphicsConfigParams = BND4.Read(graphicsConfigParam);
OverwriteParamsAC6(graphicsConfigParams);
Utils.WriteWithBackup(dir, mod, @"param\graphicsconfig\graphicsconfig.parambnd.dcx", graphicsConfigParams);
}
- string eventParam = AssetLocator.GetAssetPath(@"param\eventparam\eventparam.parambnd.dcx");
- if (File.Exists(eventParam))
+ string eventParam = Project.AssetLocator.GetAssetPath(@"param\eventparam\eventparam.parambnd.dcx");
+ if (eventParam != null)
{
using BND4 eventParams = BND4.Read(eventParam);
OverwriteParamsAC6(eventParams);
@@ -2004,49 +1476,49 @@ void OverwriteParamsAC6(BND4 paramBnd)
_pendingUpgrade = false;
}
- public void SaveParams(bool loose = false, bool partialParams = false)
+ public void SaveParams(bool loose = false)
{
if (_params == null)
{
return;
}
- if (AssetLocator.Type == GameType.DarkSoulsPTDE)
+ if (Project.Type == GameType.DarkSoulsPTDE)
{
SaveParamsDS1();
}
- if (AssetLocator.Type == GameType.DarkSoulsRemastered)
+ if (Project.Type == GameType.DarkSoulsRemastered)
{
SaveParamsDS1R();
}
- if (AssetLocator.Type == GameType.DemonsSouls)
+ if (Project.Type == GameType.DemonsSouls)
{
SaveParamsDES();
}
- if (AssetLocator.Type == GameType.DarkSoulsIISOTFS)
+ if (Project.Type == GameType.DarkSoulsIISOTFS)
{
SaveParamsDS2(loose);
}
- if (AssetLocator.Type == GameType.DarkSoulsIII)
+ if (Project.Type == GameType.DarkSoulsIII)
{
SaveParamsDS3(loose);
}
- if (AssetLocator.Type == GameType.Bloodborne || AssetLocator.Type == GameType.Sekiro)
+ if (Project.Type == GameType.Bloodborne || Project.Type == GameType.Sekiro)
{
SaveParamsBBSekiro();
}
- if (AssetLocator.Type == GameType.EldenRing)
+ if (Project.Type == GameType.EldenRing)
{
- SaveParamsER(partialParams);
+ SaveParamsER();
}
- if (AssetLocator.Type == GameType.ArmoredCoreVI)
+ if (Project.Type == GameType.ArmoredCoreVI)
{
SaveParamsAC6();
}
@@ -2319,23 +1791,23 @@ public ParamUpgradeResult UpgradeRegulation(ParamBank vanillaBank, string oldVan
}
// Backup modded params
- string modRegulationPath = $@"{AssetLocator.GameModDirectory}\regulation.bin";
+ string modRegulationPath = $@"{Project.AssetLocator.RootDirectory}\regulation.bin";
File.Copy(modRegulationPath, $@"{modRegulationPath}.upgrade.bak", true);
// Load old vanilla regulation
BND4 oldVanillaParamBnd;
- if (AssetLocator.Type == GameType.EldenRing)
+ if (Project.Type == GameType.EldenRing)
{
oldVanillaParamBnd = SFUtil.DecryptERRegulation(oldVanillaParamPath);
}
- else if (AssetLocator.Type == GameType.ArmoredCoreVI)
+ else if (Project.Type == GameType.ArmoredCoreVI)
{
oldVanillaParamBnd = SFUtil.DecryptAC6Regulation(oldVanillaParamPath);
}
else
{
throw new NotImplementedException(
- $"Param upgrading for game type {AssetLocator.Type} is not supported.");
+ $"Param upgrading for game type {Project.Type} is not supported.");
}
Dictionary oldVanillaParams = new();
@@ -2466,7 +1938,7 @@ private void LoadExternalRowNames()
var failCount = 0;
foreach (KeyValuePair p in _params)
{
- var path = AssetLocator.GetStrippedRowNamesPath(p.Key);
+ var path = Project.AssetLocator.GetStrippedRowNamesPath(p.Key);
if (File.Exists(path))
{
var names = File.ReadAllLines(path);
@@ -2510,7 +1982,7 @@ private void StripRowNames()
r.Name = "";
}
- var path = AssetLocator.GetStrippedRowNamesPath(p.Key);
+ var path = Project.AssetLocator.GetStrippedRowNamesPath(p.Key);
Directory.CreateDirectory(Path.GetDirectoryName(path));
File.WriteAllLines(path, list);
}
diff --git a/src/StudioCore/ParamEditor/ParamEditorScreen.cs b/src/StudioCore/ParamEditor/ParamEditorScreen.cs
index 3b5bb6775..5a727b97b 100644
--- a/src/StudioCore/ParamEditor/ParamEditorScreen.cs
+++ b/src/StudioCore/ParamEditor/ParamEditorScreen.cs
@@ -153,9 +153,9 @@ public void DecorateContextMenuItems(Param.Row row)
private void PopulateDecorator()
{
- if (_entryCache.Count == 0 && FMGBank.IsLoaded)
+ if (_entryCache.Count == 0 && Locator.ActiveProject.FMGBank.IsLoaded)
{
- List fmgEntries = FMGBank.GetFmgEntriesByCategory(_category, false);
+ List fmgEntries = Locator.ActiveProject.FMGBank.GetFmgEntriesByCategory(_category, false);
foreach (FMG.Entry fmgEntry in fmgEntries)
{
_entryCache[fmgEntry.ID] = fmgEntry;
@@ -168,8 +168,6 @@ public class ParamEditorScreen : EditorScreen
{
public static bool EditorMode;
- public readonly AssetLocator AssetLocator;
-
///
/// Whitelist of games and maximum param version to allow param upgrading.
/// Used to restrict upgrading before DSMS properly supports it.
@@ -216,9 +214,8 @@ public class ParamEditorScreen : EditorScreen
public List<(ulong, string, string)> ParamUpgradeEdits;
public ulong ParamUpgradeVersionSoftWhitelist;
- public ParamEditorScreen(Sdl2Window window, GraphicsDevice device, AssetLocator locator)
+ public ParamEditorScreen(Sdl2Window window, GraphicsDevice device)
{
- AssetLocator = locator;
_views = new List();
_views.Add(new ParamEditorView(this, 0));
_activeView = _views[0];
@@ -286,7 +283,7 @@ public void DrawEditorMenu()
{
if (ImGui.Selectable("Open Scripts Folder"))
{
- Process.Start("explorer.exe", AssetLocator.GetScriptAssetsDir());
+ Process.Start("explorer.exe", Locator.AssetLocator.GetScriptAssetsDir());
}
if (ImGui.Selectable("Reload Scripts"))
@@ -625,23 +622,23 @@ void ImportRowNames(bool currentParamOnly, string title)
if (ImGui.MenuItem("Current Param", KeyBindings.Current.Param_HotReload.HintText, false,
canHotReload && _activeView._selection.GetActiveParam() != null))
{
- ParamReloader.ReloadMemoryParam(ParamBank.PrimaryBank, ParamBank.PrimaryBank.AssetLocator,
+ ParamReloader.ReloadMemoryParam(ParamBank.PrimaryBank, Locator.AssetLocator,
_activeView._selection.GetActiveParam());
}
if (ImGui.MenuItem("All Params", KeyBindings.Current.Param_HotReloadAll.HintText, false,
canHotReload))
{
- ParamReloader.ReloadMemoryParams(ParamBank.PrimaryBank, ParamBank.PrimaryBank.AssetLocator,
+ ParamReloader.ReloadMemoryParams(ParamBank.PrimaryBank, Locator.AssetLocator,
ParamBank.PrimaryBank.Params.Keys.ToArray());
}
- foreach (var param in ParamReloader.GetReloadableParams(ParamBank.PrimaryBank.AssetLocator))
+ foreach (var param in ParamReloader.GetReloadableParams(Locator.AssetLocator))
{
if (ImGui.MenuItem(param, "", false, canHotReload))
{
ParamReloader.ReloadMemoryParams(ParamBank.PrimaryBank,
- ParamBank.PrimaryBank.AssetLocator, new[] { param });
+ Locator.AssetLocator, new[] { param });
}
}
}
@@ -652,7 +649,7 @@ void ImportRowNames(bool currentParamOnly, string title)
var activeParam = _activeView._selection.GetActiveParam();
if (activeParam != null && _projectSettings.GameType == GameType.DarkSoulsIII)
{
- ParamReloader.GiveItemMenu(ParamBank.PrimaryBank.AssetLocator,
+ ParamReloader.GiveItemMenu(Locator.AssetLocator,
_activeView._selection.GetSelectedRows(), _activeView._selection.GetActiveParam());
}
@@ -683,55 +680,30 @@ void ImportRowNames(bool currentParamOnly, string title)
// Only support ER for now
if (ImGui.MenuItem("Load Params for comparison...", null, false))
{
- string[] allParamTypes =
- {
- AssetLocator.RegulationBinFilter, AssetLocator.Data0Filter, AssetLocator.ParamBndDcxFilter,
- AssetLocator.ParamBndFilter, AssetLocator.EncRegulationFilter
- };
try
{
- if (_projectSettings.GameType != GameType.DarkSoulsIISOTFS)
+ // NativeFileDialog doesn't show the title currently, so manual dialogs are required for now.
+ var res = PlatformUtils.Instance.MessageBox(
+ "To compare params, you can select the mod/project folder containing them, or the project.json in that folder.\n" +
+ "If you load from folder, Project settings such as usage of looseParams will be inferred from your current project.\n" +
+ "If you are selecting a folder and have loose params, ensure you select the mod/project folder that CONTAINS the param folder.\n\n" +
+ "Would you like to select a folder?",
+ "Select folder?",
+ MessageBoxButtons.YesNo,
+ MessageBoxIcon.Information);
+ if (res == DialogResult.Yes)
{
- if (PlatformUtils.Instance.OpenFileDialog("Select file containing params", allParamTypes,
- out var path))
+ if (PlatformUtils.Instance.OpenFolderDialog("Select mod or project folder",
+ out var folder))
{
- ParamBank.LoadAuxBank(path, null, null, _projectSettings);
+ ParamBank.LoadAuxBank(folder);
}
}
- else
+ else if (res == DialogResult.No)
{
- // NativeFileDialog doesn't show the title currently, so manual dialogs are required for now.
- PlatformUtils.Instance.MessageBox(
- "To compare DS2 params, select the file locations of alternative params, including\n" +
- "the loose params folder, the non-loose parambnd or regulation, and the loose enemy param.\n\n" +
- "First, select the loose params folder.",
- "Select loose params",
- MessageBoxButtons.OK,
- MessageBoxIcon.Information);
- if (PlatformUtils.Instance.OpenFolderDialog("Select folder for looseparams",
- out var folder))
+ if (PlatformUtils.Instance.OpenFileDialog("Select project.json", [AssetUtils.ProjectJsonFilter], out var file))
{
- PlatformUtils.Instance.MessageBox(
- "Second, select the non-loose parambnd or regulation",
- "Select regulation",
- MessageBoxButtons.OK,
- MessageBoxIcon.Information);
- if (PlatformUtils.Instance.OpenFileDialog(
- "Select file containing remaining, non-loose params", allParamTypes,
- out var path))
- {
- PlatformUtils.Instance.MessageBox(
- "Finally, select the file containing enemyparam",
- "Select enemyparam",
- MessageBoxButtons.OK,
- MessageBoxIcon.Information);
- if (PlatformUtils.Instance.OpenFileDialog(
- "Select file containing enemyparam",
- new[] { AssetLocator.ParamLooseFilter }, out var enemyPath))
- {
- ParamBank.LoadAuxBank(path, folder, enemyPath, _projectSettings);
- }
- }
+ ParamBank.LoadAuxBank(Path.GetDirectoryName(file), ProjectSettings.Deserialize(file));
}
}
}
@@ -910,13 +882,13 @@ public unsafe void OnGUI(string[] initcmd)
{
if (InputTracker.GetKeyDown(KeyBindings.Current.Param_HotReloadAll))
{
- ParamReloader.ReloadMemoryParams(ParamBank.PrimaryBank, ParamBank.PrimaryBank.AssetLocator,
+ ParamReloader.ReloadMemoryParams(ParamBank.PrimaryBank, Locator.AssetLocator,
ParamBank.PrimaryBank.Params.Keys.ToArray());
}
else if (InputTracker.GetKeyDown(KeyBindings.Current.Param_HotReload) &&
_activeView._selection.GetActiveParam() != null)
{
- ParamReloader.ReloadMemoryParam(ParamBank.PrimaryBank, ParamBank.PrimaryBank.AssetLocator,
+ ParamReloader.ReloadMemoryParam(ParamBank.PrimaryBank, Locator.AssetLocator,
_activeView._selection.GetActiveParam());
}
}
@@ -1153,7 +1125,7 @@ public void Save()
{
if (_projectSettings != null)
{
- ParamBank.PrimaryBank.SaveParams(_projectSettings.UseLooseParams, _projectSettings.PartialParams);
+ ParamBank.PrimaryBank.SaveParams(_projectSettings.UseLooseParams);
TaskLogs.AddLog("Saved params");
}
}
@@ -1175,7 +1147,7 @@ public void SaveAll()
{
if (_projectSettings != null)
{
- ParamBank.PrimaryBank.SaveParams(_projectSettings.UseLooseParams, _projectSettings.PartialParams);
+ ParamBank.PrimaryBank.SaveParams(_projectSettings.UseLooseParams);
TaskLogs.AddLog("Saved params");
}
}
@@ -1208,9 +1180,9 @@ private void LoadUpgraderData()
ParamUpgradeEdits = null;
try
{
- var baseDir = AssetLocator.GetUpgraderAssetsDir();
- var wlFile = Path.Join(AssetLocator.GetUpgraderAssetsDir(), "version.txt");
- var massEditFile = Path.Join(AssetLocator.GetUpgraderAssetsDir(), "massedit.txt");
+ var baseDir = Locator.AssetLocator.GetUpgraderAssetsDir();
+ var wlFile = Path.Join(Locator.AssetLocator.GetUpgraderAssetsDir(), "version.txt");
+ var massEditFile = Path.Join(Locator.AssetLocator.GetUpgraderAssetsDir(), "massedit.txt");
if (!File.Exists(wlFile) || !File.Exists(massEditFile))
{
return;
@@ -1244,10 +1216,10 @@ private void LoadUpgraderData()
private void ParamUpgradeDisplay()
{
- if (ParamBank.IsDefsLoaded
+ if (Locator.ActiveProject != null && Locator.ActiveProject.ParamBank.IsDefsLoaded
&& ParamBank.PrimaryBank.Params != null
&& ParamBank.VanillaBank.Params != null
- && ParamUpgrade_SupportedGames.Contains(ParamBank.PrimaryBank.AssetLocator.Type)
+ && ParamUpgrade_SupportedGames.Contains(Locator.AssetLocator.Type)
&& !ParamBank.PrimaryBank.IsLoadingParams
&& !ParamBank.VanillaBank.IsLoadingParams
&& ParamBank.PrimaryBank.ParamVersion < ParamBank.VanillaBank.ParamVersion)
@@ -1284,7 +1256,7 @@ private void ParamUpgradeDisplay()
{
if (PlatformUtils.Instance.OpenFileDialog(
$"Select regulation.bin for game version {ParamBank.PrimaryBank.ParamVersion}...",
- new[] { AssetLocator.RegulationBinFilter },
+ new[] { AssetUtils.RegulationBinFilter },
out var path))
{
UpgradeRegulation(ParamBank.PrimaryBank, ParamBank.VanillaBank, path);
@@ -1352,7 +1324,7 @@ public void UpgradeRegulation(ParamBank bank, ParamBank vanillaBank, string oldR
if (result == ParamBank.ParamUpgradeResult.RowConflictsFound)
{
// If there's row conflicts write a conflict log
- var logPath = $@"{bank.AssetLocator.GameModDirectory}\regulationUpgradeLog.txt";
+ var logPath = $@"{Locator.AssetLocator.GameModDirectory}\regulationUpgradeLog.txt";
if (File.Exists(logPath))
{
File.Delete(logPath);
@@ -2069,7 +2041,7 @@ public int CountViews()
private static bool SaveCsvDialog(out string path)
{
var result = PlatformUtils.Instance.SaveFileDialog(
- "Choose CSV file", new[] { AssetLocator.CsvFilter, AssetLocator.TxtFilter }, out path);
+ "Choose CSV file", new[] { AssetUtils.CsvFilter, AssetUtils.TxtFilter }, out path);
if (result && !path.ToLower().EndsWith(".csv"))
path += ".csv";
@@ -2080,7 +2052,7 @@ private static bool SaveCsvDialog(out string path)
private static bool OpenCsvDialog(out string path)
{
return PlatformUtils.Instance.OpenFileDialog(
- "Choose CSV file", new[] { AssetLocator.CsvFilter, AssetLocator.TxtFilter }, out path);
+ "Choose CSV file", new[] { AssetUtils.CsvFilter, AssetUtils.TxtFilter }, out path);
}
private static bool ReadCsvDialog(out string csv)
diff --git a/src/StudioCore/ParamEditor/ParamEditorView.cs b/src/StudioCore/ParamEditor/ParamEditorView.cs
index 67e9d7066..41f3d559b 100644
--- a/src/StudioCore/ParamEditor/ParamEditorView.cs
+++ b/src/StudioCore/ParamEditor/ParamEditorView.cs
@@ -84,7 +84,7 @@ private void ParamView_ParamList_Header(bool isActiveView)
lastParamSearch = _selection.currentParamSearchString;
}
- if (ParamBank.PrimaryBank.AssetLocator.Type is GameType.DemonsSouls
+ if (Locator.AssetLocator.Type is GameType.DemonsSouls
or GameType.DarkSoulsPTDE
or GameType.DarkSoulsRemastered)
{
@@ -96,7 +96,7 @@ or GameType.DarkSoulsPTDE
ImGui.Separator();
}
- else if (ParamBank.PrimaryBank.AssetLocator.Type is GameType.DarkSoulsIISOTFS)
+ else if (Locator.AssetLocator.Type is GameType.DarkSoulsIISOTFS)
{
// DS2 has map params, add UI element to toggle viewing map params and GameParams.
if (ImGui.Checkbox("Edit Map Params", ref _mapParamView))
@@ -106,7 +106,7 @@ or GameType.DarkSoulsPTDE
ImGui.Separator();
}
- else if (ParamBank.PrimaryBank.AssetLocator.Type is GameType.EldenRing || ParamBank.PrimaryBank.AssetLocator.Type is GameType.ArmoredCoreVI)
+ else if (Locator.AssetLocator.Type is GameType.EldenRing || Locator.AssetLocator.Type is GameType.ArmoredCoreVI)
{
if (ImGui.Checkbox("Edit Event Params", ref _eventParamView))
{
@@ -182,7 +182,7 @@ private void ParamView_ParamList_Main(bool doFocus, float scale, float scrollTo)
List keyList = list.Where(param => param.Item1 == ParamBank.PrimaryBank)
.Select(param => ParamBank.PrimaryBank.GetKeyForParam(param.Item2)).ToList();
- if (ParamBank.PrimaryBank.AssetLocator.Type is GameType.DemonsSouls
+ if (Locator.AssetLocator.Type is GameType.DemonsSouls
or GameType.DarkSoulsPTDE
or GameType.DarkSoulsRemastered)
{
@@ -195,7 +195,7 @@ or GameType.DarkSoulsPTDE
keyList = keyList.FindAll(p => !p.EndsWith("Bank"));
}
}
- else if (ParamBank.PrimaryBank.AssetLocator.Type is GameType.DarkSoulsIISOTFS)
+ else if (Locator.AssetLocator.Type is GameType.DarkSoulsIISOTFS)
{
if (_mapParamView)
{
@@ -206,7 +206,7 @@ or GameType.DarkSoulsPTDE
keyList = keyList.FindAll(p => !ParamBank.DS2MapParamlist.Contains(p.Split('_')[0]));
}
}
- else if (ParamBank.PrimaryBank.AssetLocator.Type is GameType.EldenRing)
+ else if (Locator.AssetLocator.Type is GameType.EldenRing)
{
if (_eventParamView)
{
@@ -226,7 +226,7 @@ or GameType.DarkSoulsPTDE
keyList = keyList.FindAll(p => !p.StartsWith("Gconfig"));
}
}
- else if (ParamBank.PrimaryBank.AssetLocator.Type is GameType.ArmoredCoreVI)
+ else if (Locator.AssetLocator.Type is GameType.ArmoredCoreVI)
{
if (_eventParamView)
{
diff --git a/src/StudioCore/ParamEditor/ParamMeta.cs b/src/StudioCore/ParamEditor/ParamMeta.cs
index fc84eae12..363597b4f 100644
--- a/src/StudioCore/ParamEditor/ParamMeta.cs
+++ b/src/StudioCore/ParamEditor/ParamMeta.cs
@@ -13,7 +13,6 @@ namespace StudioCore.ParamEditor;
public class ParamMetaData
{
private const int XML_VERSION = 0;
- private static readonly Dictionary _ParamMetas = new();
private readonly string _path;
internal XmlDocument _xml;
@@ -21,7 +20,6 @@ public class ParamMetaData
private ParamMetaData(PARAMDEF def, string path)
{
- Add(def, this);
foreach (PARAMDEF.Field f in def.Fields)
{
new FieldMetaData(this, f);
@@ -61,8 +59,6 @@ private ParamMetaData(XmlDocument xml, string path, PARAMDEF def)
$"Mismatched XML version; current version: {XML_VERSION}, file version: {xmlVersion}");
}
- Add(def, this);
-
XmlNode self = root.SelectSingleNode("Self");
if (self != null)
{
@@ -222,14 +218,8 @@ public static ParamMetaData Get(PARAMDEF def)
return null;
}
- return _ParamMetas[def];
+ return Locator.ActiveProject.ParamBank.ParamMetas[def];
}
-
- private static void Add(PARAMDEF key, ParamMetaData meta)
- {
- _ParamMetas.Add(key, meta);
- }
-
internal static XmlNode GetXmlNode(XmlDocument xml, XmlNode parent, string child)
{
XmlNode node = parent.SelectSingleNode(child);
@@ -382,7 +372,7 @@ public static void SaveAll()
field.Value.Commit(FixName(field.Key.InternalName)); //does not handle shared names
}
- foreach (ParamMetaData param in _ParamMetas.Values)
+ foreach (ParamMetaData param in Locator.ActiveProject.ParamBank.ParamMetas.Values)
{
param.Commit();
param.Save();
diff --git a/src/StudioCore/ParamEditor/SearchEngine.cs b/src/StudioCore/ParamEditor/SearchEngine.cs
index 594d5844e..184a1cde5 100644
--- a/src/StudioCore/ParamEditor/SearchEngine.cs
+++ b/src/StudioCore/ParamEditor/SearchEngine.cs
@@ -275,13 +275,8 @@ internal enum MassEditRowSource
internal class ParamSearchEngine : SearchEngine
{
- public static ParamSearchEngine pse = new(ParamBank.PrimaryBank);
- private readonly ParamBank bank;
-
- private ParamSearchEngine(ParamBank bank)
- {
- this.bank = bank;
- }
+ public static ParamSearchEngine pse = new();
+ private ParamBank bank => ParamBank.PrimaryBank;
internal override void Setup()
{
@@ -340,13 +335,8 @@ internal override void Setup()
internal class RowSearchEngine : SearchEngine<(ParamBank, Param), Param.Row>
{
- public static RowSearchEngine rse = new(ParamBank.PrimaryBank);
- private readonly ParamBank bank;
-
- private RowSearchEngine(ParamBank bank)
- {
- this.bank = bank;
- }
+ public static RowSearchEngine rse = new();
+ private ParamBank bank => ParamBank.PrimaryBank;
internal override void Setup()
{
@@ -535,7 +525,7 @@ internal override void Setup()
throw new Exception();
}
- List fmgEntries = FMGBank.GetFmgEntriesByCategory(category, false);
+ List fmgEntries = Locator.ActiveProject.FMGBank.GetFmgEntriesByCategory(category, false);
Dictionary _cache = new();
foreach (FMG.Entry fmgEntry in fmgEntries)
{
@@ -766,12 +756,12 @@ internal override void Setup()
category = cat;
}
- if (category == FmgEntryCategory.None || !FMGBank.IsLoaded)
+ if (category == FmgEntryCategory.None || !Locator.ActiveProject.FMGBank.IsLoaded)
{
return row => rx.IsMatch(row.Name ?? "") || rx.IsMatch(row.ID.ToString());
}
- List fmgEntries = FMGBank.GetFmgEntriesByCategory(category, false);
+ List fmgEntries = Locator.ActiveProject.FMGBank.GetFmgEntriesByCategory(category, false);
Dictionary _cache = new();
foreach (FMG.Entry fmgEntry in fmgEntries)
{
diff --git a/src/StudioCore/Project.cs b/src/StudioCore/Project.cs
new file mode 100644
index 000000000..a5660aa9f
--- /dev/null
+++ b/src/StudioCore/Project.cs
@@ -0,0 +1,103 @@
+using SoulsFormats;
+using StudioCore.Editor;
+using StudioCore.ParamEditor;
+using StudioCore.TextEditor;
+using System;
+using System.Globalization;
+using System.IO;
+using System.Linq;
+
+namespace StudioCore;
+
+///
+/// Holds asset locator, data banks, etc
+///
+public class Project
+{
+ public readonly ProjectSettings Settings;
+
+ public readonly Project ParentProject;
+
+ public readonly ProjectAssetLocator AssetLocator;
+
+ public readonly ParamBank ParamBank;
+
+ public readonly FMGBank FMGBank;
+
+
+ public GameType Type => Settings.GameType;
+
+ ///
+ /// Creates a project based in a single folder with no parent. This is for Game or DSMS files.
+ ///
+ public Project(ProjectSettings settings)
+ {
+ Settings = settings;
+ AssetLocator = new(this, settings.GameRoot);
+ ParentProject = null;
+
+ ParamBank = new(this);
+ FMGBank = new(this);
+ }
+ ///
+ /// Creates a project based in a folder with no explicit parent project, with a new ParentProject for the game directory. This is for a mod.
+ ///
+ public Project(ProjectSettings settings, string moddir)
+ {
+ Settings = settings;
+ AssetLocator = new(this, moddir);
+ ParentProject = new Project(settings);
+
+ ParamBank = new(this);
+ FMGBank = new(this);
+ }
+ ///
+ /// Creates a project based in a folder with an explicit parent project. This is for an addon or fork of a mod.
+ ///
+ public Project(string moddir, Project parent, ProjectSettings settings = null)
+ {
+ if (settings == null)
+ {
+ Settings = parent.Settings.CopyAndAssumeFromModDir(moddir);
+ }
+ else
+ {
+ Settings = settings;
+ }
+ AssetLocator = new(this, moddir);
+ ParentProject = parent;
+
+ ParamBank = new(this);
+ FMGBank = new(this);
+ }
+
+ ///
+ /// Creates a project based on an existing one for recovery purposes. Shares resources with the original project.
+ ///
+ public Project(Project parent)
+ {
+ var time = DateTime.Now.ToString("dd-MM-yyyy-(hh-mm-ss)", CultureInfo.InvariantCulture);
+ Settings = parent.Settings;
+ AssetLocator = new(this, parent.AssetLocator.RootDirectory + $@"\recovery\{time}");
+ ParentProject = parent.ParentProject;
+ if (!Directory.Exists(AssetLocator.RootDirectory))
+ {
+ Directory.CreateDirectory(AssetLocator.RootDirectory);
+ }
+
+ ParamBank = parent.ParamBank;
+ FMGBank = parent.FMGBank;
+ }
+
+ public Project CreateRecoveryProject()
+ {
+ try
+ {
+ return new Project(this);
+ }
+ catch (Exception e)
+ {
+ return this;
+ }
+ }
+}
diff --git a/src/StudioCore/ProjectAssetLocator.cs b/src/StudioCore/ProjectAssetLocator.cs
new file mode 100644
index 000000000..97ee2c398
--- /dev/null
+++ b/src/StudioCore/ProjectAssetLocator.cs
@@ -0,0 +1,1937 @@
+using SoulsFormats;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text.RegularExpressions;
+
+namespace StudioCore;
+
+///
+/// Exposes an interface to retrieve game assets from the various souls games.
+///
+public class ProjectAssetLocator
+{
+ public readonly Project Project;
+
+ public GameType Type => Project.Type;
+ public ProjectAssetLocator ParentAssetLocator => Project.ParentProject?.AssetLocator;
+
+ ///
+ /// The root directory where all the assets are
+ ///
+ public readonly string RootDirectory;
+
+ ///
+ /// Directory where misc DSMapStudio files associated with a project are stored.
+ ///
+ public string ProjectMiscDir => @$"{RootDirectory}\DSMapStudio";
+
+ private List MapList;
+
+ public ProjectAssetLocator(Project owner, string dir)
+ {
+ Project = owner;
+ RootDirectory = dir;
+ }
+
+ private string GetFileNameWithoutExtensions(string path)
+ {
+ return Path.GetFileNameWithoutExtension(Path.GetFileNameWithoutExtension(path));
+ }
+
+ public string GetAssetPath(string relpath)
+ {
+ if (File.Exists($@"{RootDirectory}\{relpath}"))
+ {
+ return $@"{RootDirectory}\{relpath}";
+ }
+ if (ParentAssetLocator != null)
+ {
+ return ParentAssetLocator.GetAssetPath(relpath);
+ }
+ return null;
+ }
+ public string GetProjectFilePath(string relpath)
+ {
+ if (ParentAssetLocator == null)
+ {
+ return $@"Assets\{relpath}";
+ }
+ string path = $@"{ProjectMiscDir}\{relpath}";
+ if (File.Exists(path))
+ {
+ return path;
+ }
+ else
+ {
+ return ParentAssetLocator.GetProjectFilePath(relpath);
+ }
+ }
+
+ public IEnumerable GetProjectFileAllPaths(string relpath, List paths = null)
+ {
+ if (paths == null)
+ {
+ paths = new();
+ }
+ if (ParentAssetLocator == null)
+ {
+ paths.Add($@"Assets\{relpath}");
+ return paths;
+ }
+ string path = $@"{ProjectMiscDir}\{relpath}";
+ if (File.Exists(path))
+ {
+ paths.Add(path);
+ }
+ return ParentAssetLocator.GetProjectFileAllPaths(relpath, paths);;
+ }
+
+ public (int, string) GetAssetPathFromOptions(IEnumerable relpaths)
+ {
+ int i = 0;
+ foreach (string relpath in relpaths)
+ {
+ var path = $@"{RootDirectory}\{relpath}";
+ if (File.Exists(path))
+ {
+ return (i, path);
+ }
+ i++;
+ }
+ if (ParentAssetLocator != null)
+ {
+ return ParentAssetLocator.GetAssetPathFromOptions(relpaths);
+ }
+ return (-1, null);
+ }
+
+ public bool FileExists(string relpath)
+ {
+ if (ParentAssetLocator != null && ParentAssetLocator.FileExists(relpath))
+ {
+ return true;
+ }
+
+ if (File.Exists($@"{RootDirectory}\{relpath}"))
+ {
+ return true;
+ }
+
+ return false;
+ }
+ public IEnumerable GetAllAssets(string relpath, string[] extensionPatterns, bool distinct = true, bool subDirectories = false)
+ {
+ List files = new();
+ string rpath = $@"{RootDirectory}\{relpath}";
+ if (Directory.Exists(rpath))
+ {
+ foreach (string pattern in extensionPatterns)
+ {
+ files.AddRange(Directory.GetFiles(rpath, pattern, subDirectories ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly));
+ }
+ }
+ if (ParentAssetLocator != null)
+ {
+ files.AddRange(ParentAssetLocator.GetAllAssets(relpath, extensionPatterns, distinct, subDirectories));
+ }
+ if (distinct)
+ {
+ // WARNING DistinctBy doesn't guarantee preference by order, though implementations do
+ return files.DistinctBy(GetFileNameWithoutExtensions);
+ }
+ else
+ {
+ return files;
+ }
+ }
+ public IEnumerable GetAllProjectFiles(string relpath, string[] extensionPatterns, bool distinct = true, bool subDirectories = false)
+ {
+ List files = new();
+ string rpath;
+ if (ParentAssetLocator == null)
+ {
+ rpath = $@"Assets\{relpath}";
+ foreach (string pattern in extensionPatterns)
+ {
+ files.AddRange(Directory.GetFiles(rpath, pattern, subDirectories ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly));
+ }
+ return files;
+ }
+ rpath = $@"{RootDirectory}\{ProjectMiscDir}\{relpath}";
+ if (Directory.Exists(rpath))
+ {
+ foreach (string pattern in extensionPatterns)
+ {
+ files.AddRange(Directory.GetFiles(rpath, pattern, subDirectories ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly));
+ }
+ }
+ if (ParentAssetLocator != null)
+ {
+ files.AddRange(ParentAssetLocator.GetAllProjectFiles(relpath, extensionPatterns, distinct, subDirectories));
+ }
+ if (distinct)
+ {
+ // WARNING DistinctBy doesn't guarantee preference by order, though implementations do
+ return files.DistinctBy(GetFileNameWithoutExtensions);
+ }
+ else
+ {
+ return files;
+ }
+ }
+ public IEnumerable GetAllSubDirs(string relpath, bool distinct = true, bool subDirectories = false)
+ {
+ List dirs = new();
+ string rpath = $@"{RootDirectory}\{relpath}";
+ if (Directory.Exists(rpath))
+ {
+ dirs.AddRange(Directory.GetDirectories(rpath, "*", subDirectories ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly));
+ }
+ if (ParentAssetLocator != null)
+ {
+ dirs.AddRange(ParentAssetLocator.GetAllSubDirs(relpath, subDirectories));
+ }
+ if (distinct)
+ {
+ // WARNING DistinctBy doesn't guarantee preference by order, though implementations do
+ return dirs.DistinctBy(Path.GetFileName);
+ }
+ else
+ {
+ return dirs;
+ }
+ }
+
+ ///
+ /// Gets the full list of maps in the game (excluding chalice dungeons). Basically if there's an msb for it,
+ /// it will be in this list.
+ ///
+ ///
+ public List GetFullMapList()
+ {
+
+ if (MapList != null)
+ {
+ return MapList;
+ }
+
+ try
+ {
+ HashSet mapSet = new();
+
+ // DS2 has its own structure for msbs, where they are all inside individual folders
+ if (Type == GameType.DarkSoulsIISOTFS)
+ {
+ foreach (var map in GetAllAssets(@"map", [@"*.msb"], true, true))
+ {
+ mapSet.Add(Path.GetFileNameWithoutExtension(map));
+ }
+ }
+ else
+ {
+ foreach (var msb in GetAllAssets(@"map\MapStudio\", [@"*.msb", @"*.msb.dcx"]))
+ {
+ mapSet.Add(GetFileNameWithoutExtensions(msb));
+ }
+ }
+ Regex mapRegex = new(@"^m\d{2}_\d{2}_\d{2}_\d{2}$");
+ List mapList = mapSet.Where(x => mapRegex.IsMatch(x)).ToList();
+ mapList.Sort();
+ MapList = mapList;
+ return MapList;
+ }
+ catch (DirectoryNotFoundException e)
+ {
+ // Game is likely not UXM unpacked
+ if (ParentAssetLocator != null)
+ {
+ MapList = ParentAssetLocator.GetFullMapList();
+ return MapList;
+ }
+ return new List();
+ }
+ }
+
+ public AssetDescription GetMapMSB(string mapid, bool writemode = false)
+ {
+ AssetDescription ad = new();
+ ad.AssetPath = null;
+ if (mapid.Length != 12)
+ {
+ return ad;
+ }
+
+ string preferredPath;
+ string backupPath;
+ // SOFTS
+ if (Type == GameType.DarkSoulsIISOTFS)
+ {
+ preferredPath = $@"map\{mapid}\{mapid}.msb";
+ backupPath = $@"map\{mapid}\{mapid}.msb";
+ }
+ // BB chalice maps
+ else if (Type == GameType.Bloodborne && mapid.StartsWith("m29"))
+ {
+ preferredPath = $@"\map\MapStudio\{mapid.Substring(0, 9)}_00\{mapid}.msb.dcx";
+ backupPath = $@"\map\MapStudio\{mapid.Substring(0, 9)}_00\{mapid}.msb";
+ }
+ // DeS, DS1, DS1R
+ else if (Type == GameType.DarkSoulsPTDE || Type == GameType.DarkSoulsRemastered ||
+ Type == GameType.DemonsSouls)
+ {
+ preferredPath = $@"\map\MapStudio\{mapid}.msb";
+ backupPath = $@"\map\MapStudio\{mapid}.msb.dcx";
+ }
+ // BB, DS3, ER, SSDT
+ else if (Type == GameType.Bloodborne || Type == GameType.DarkSoulsIII || Type == GameType.EldenRing ||
+ Type == GameType.Sekiro)
+ {
+ preferredPath = $@"\map\MapStudio\{mapid}.msb.dcx";
+ backupPath = $@"\map\MapStudio\{mapid}.msb";
+ }
+ else
+ {
+ preferredPath = $@"\map\MapStudio\{mapid}.msb.dcx";
+ backupPath = $@"\map\MapStudio\{mapid}.msb";
+ }
+
+ if (writemode)
+ {
+ ad.AssetPath = $@"{RootDirectory}\{preferredPath}";
+ }
+ else
+ {
+ ad.AssetPath = GetAssetPathFromOptions([preferredPath, backupPath]).Item2;
+ }
+
+ ad.AssetName = mapid;
+ return ad;
+ }
+
+ public List GetMapBTLs(string mapid, bool writemode = false)
+ {
+ List adList = new();
+ if (mapid.Length != 12)
+ {
+ return adList;
+ }
+
+ if (Type is GameType.DarkSoulsIISOTFS)
+ {
+ // DS2 BTL is located inside map's .gibdt file
+ AssetDescription ad = new();
+ var path = $@"model\map\g{mapid[1..]}.gibhd";
+
+ if (writemode)
+ {
+ ad.AssetPath = $@"{RootDirectory}\{path}";
+ }
+ else
+ {
+ ad.AssetPath = GetAssetPath(path);
+ }
+
+ if (ad.AssetPath != null)
+ {
+ ad.AssetName = $@"g{mapid[1..]}";
+ ad.AssetVirtualPath = $@"{mapid}\light.btl.dcx";
+ adList.Add(ad);
+ }
+
+ AssetDescription ad2 = new();
+ path = $@"model_lq\map\g{mapid[1..]}.gibhd";
+
+ if (writemode)
+ {
+ ad2.AssetPath = $@"{RootDirectory}\{path}";
+ }
+ else
+ {
+ ad2.AssetPath = GetAssetPath(path);
+ }
+
+ if (ad2.AssetPath != null)
+ {
+ ad2.AssetName = $@"g{mapid[1..]}_lq";
+ ad2.AssetVirtualPath = $@"{mapid}\light.btl.dcx";
+ adList.Add(ad2);
+ }
+ }
+ else if (Type is GameType.Bloodborne or GameType.DarkSoulsIII or GameType.Sekiro or GameType.EldenRing or GameType.ArmoredCoreVI)
+ {
+ string path;
+ if (Type is GameType.EldenRing or GameType.ArmoredCoreVI)
+ {
+ path = $@"map\{mapid[..3]}\{mapid}";
+ }
+ else
+ {
+ path = $@"map\{mapid}";
+ }
+
+ List files = new();
+
+ files = GetAllAssets(path, ["*.btl", "*.btl.dcx"]).ToList();
+
+ foreach (var file in files)
+ {
+ AssetDescription ad = new();
+ var fileName = file.Split("\\").Last();
+ if (writemode)
+ {
+ ad.AssetPath = $@"{RootDirectory}\{path}\{fileName}";
+ }
+ else
+ {
+ ad.AssetPath = GetAssetPath($@"{path}\{fileName}");
+ }
+
+ if (ad.AssetPath != null)
+ {
+ ad.AssetName = fileName;
+ adList.Add(ad);
+ }
+ }
+ }
+
+ return adList;
+ }
+ public AssetDescription GetMapNVA(string mapid, bool writemode = false)
+ {
+ AssetDescription ad = new();
+ ad.AssetPath = null;
+ if (mapid.Length != 12)
+ {
+ return ad;
+ }
+ // BB chalice maps
+
+ if (Type == GameType.Bloodborne && mapid.StartsWith("m29"))
+ {
+ var path = $@"\map\{mapid.Substring(0, 9)}_00\{mapid}";
+ if (writemode)
+ {
+ ad.AssetPath = $@"{RootDirectory}\{path}.nva.dcx";
+ }
+ else
+ {
+ ad.AssetPath = GetAssetPath($@"{path}.nva.dcx");
+ }
+ }
+ else if (Type == GameType.DarkSoulsPTDE)
+ {
+ var path = $@"\map\{mapid}\{mapid}";
+ if (writemode)
+ {
+ ad.AssetPath = $@"{RootDirectory}\{path}.nva";
+ }
+ else
+ {
+ ad.AssetPath = GetAssetPathFromOptions([$@"{path}.nva", $@"{path}.nva.dcx"]).Item2;
+ }
+ }
+ else
+ {
+ var path = $@"\map\{mapid}\{mapid}";
+ if (writemode)
+ {
+ ad.AssetPath = $@"{RootDirectory}\{path}.nva.dcx";
+ }
+ else
+ {
+ ad.AssetPath = GetAssetPathFromOptions([$@"{path}.nva.dcx", $@"{path}.nva"]).Item2;
+ }
+ }
+
+ ad.AssetName = mapid;
+ return ad;
+ }
+
+ public AssetDescription GetWorldLoadListList(bool writemode = false)
+ {
+ AssetDescription ad = new();
+
+ if (writemode)
+ {
+ ad.AssetPath = $@"{RootDirectory}\map\worldmsblist.worldloadlistlist.dcx";
+ }
+ else
+ {
+ ad.AssetPath = GetAssetPath($@"map\worldmsblist.worldloadlistlist.dcx");
+ }
+
+ return ad;
+ }
+
+ ///
+ /// Get folders with msgbnds used in-game
+ ///
+ /// Dictionary with language name and path
+ public Dictionary GetMsgLanguages()
+ {
+ Dictionary dict = new();
+ List folders = new();
+ try
+ {
+ if (Type == GameType.DemonsSouls)
+ {
+ folders = GetAllSubDirs(@"\msg").ToList();
+ // Japanese uses root directory
+ if (FileExists(@"\msg\menu.msgbnd.dcx") || FileExists(@"\msg\item.msgbnd.dcx"))
+ {
+ dict.Add("Japanese", "");
+ }
+ }
+ else if (Type == GameType.DarkSoulsIISOTFS)
+ {
+ folders = GetAllSubDirs(@"\menu\text").ToList();
+ }
+ else
+ {
+ // Exclude folders that don't have typical msgbnds
+ folders = GetAllSubDirs(@"\msg")
+ .Where(x => !"common,as,eu,jp,na,uk,japanese".Contains(Path.GetFileName(x))).ToList();
+ }
+
+ foreach (var path in folders)
+ {
+ dict.Add(path.Split("\\").Last(), path);
+ }
+ }
+ catch (Exception e) when (e is DirectoryNotFoundException or FileNotFoundException)
+ {
+ }
+
+ return dict;
+ }
+
+ ///
+ /// Get path of item.msgbnd (english by default)
+ ///
+ public AssetDescription GetItemMsgbnd(string langFolder, bool writemode = false)
+ {
+ return GetMsgbnd("item", langFolder, writemode);
+ }
+
+ ///
+ /// Get path of menu.msgbnd (english by default)
+ ///
+ public AssetDescription GetMenuMsgbnd(string langFolder, bool writemode = false)
+ {
+ return GetMsgbnd("menu", langFolder, writemode);
+ }
+
+ public AssetDescription GetMsgbnd(string msgBndType, string langFolder, bool writemode = false)
+ {
+ AssetDescription ad = new();
+ IEnumerable path;
+ if (Project.Type == GameType.DemonsSouls)
+ {
+ // Demon's Souls has msgbnds directly in the msg folder
+ path = [$@"msg\{langFolder}\{msgBndType}.msgbnd.dcx", $@"msg\{msgBndType}.msgbnd.dcx"];
+ }
+ else if (Project.Type == GameType.DarkSoulsPTDE)
+ {
+ path = [$@"msg\{langFolder}\{msgBndType}.msgbnd"];
+ }
+ else if (Project.Type == GameType.DarkSoulsRemastered)
+ {
+ path = [$@"msg\{langFolder}\{msgBndType}.msgbnd.dcx"];
+ }
+ else if (Project.Type == GameType.DarkSoulsIISOTFS)
+ {
+ // DS2 does not have an msgbnd but loose fmg files instead
+ path = [$@"menu\text\{langFolder}"];
+ }
+ else if (Project.Type == GameType.DarkSoulsIII)
+ {
+ path = [$@"msg\{langFolder}\{msgBndType}_dlc2.msgbnd.dcx"];
+ }
+ else
+ {
+ path = [$@"msg\{langFolder}\{msgBndType}.msgbnd.dcx"];
+ }
+
+ if (writemode)
+ {
+ ad.AssetPath = $@"{Project.AssetLocator.RootDirectory}\{path.First()}";
+ }
+ else
+ {
+ ad.AssetPath = Project.AssetLocator.GetAssetPathFromOptions(path).Item2;
+ }
+
+ return ad;
+ }
+
+ public string GetAliasAssetsDir()
+ {
+ return GetProjectFilePath($@"Aliases");
+ }
+
+ public string GetParamdexDir()
+ {
+ return $@"Paramdex\{AssetUtils.GetGameIDForDir(Type)}";
+ }
+
+ public string GetStrippedRowNamesPath(string paramName)
+ {
+ return GetProjectFilePath($@"Stripped Row Names\{paramName}.txt");
+ }
+
+ public string GetScriptAssetsCommonDir()
+ {
+ return GetProjectFilePath($@"MassEditScripts\Common");
+ }
+
+ public string GetScriptAssetsDir()
+ {
+ return GetProjectFilePath($@"MassEditScripts\{AssetUtils.GetGameIDForDir(Type)}");
+ }
+
+ public string GetUpgraderAssetsDir()
+ {
+ return GetProjectFilePath($@"{GetParamdexDir()}\Upgrader");
+ }
+
+ public string GetGameOffsetsAssetsDir()
+ {
+ return GetProjectFilePath($@"GameOffsets\{AssetUtils.GetGameIDForDir(Type)}");
+ }
+
+ public PARAMDEF GetParamdefForParam(string paramType)
+ {
+ //This is ds2 only and really ds2 should be using parambank params not its own copies
+ PARAMDEF pd = PARAMDEF.XmlDeserialize($@"{GetParamdexDir()}\{AssetUtils.GetGameIDForDir(Type)}\Defs\{paramType}.xml");
+ return pd;
+ }
+
+ public AssetDescription GetDS2GeneratorParam(string mapid, bool writemode = false)
+ {
+ AssetDescription ad = new();
+ var path = $@"Param\generatorparam_{mapid}";
+ if (writemode)
+ {
+ ad.AssetPath = $@"{RootDirectory}\{path}.param";
+ }
+ else
+ {
+ ad.AssetPath = GetAssetPath($@"{path}.param");
+ }
+
+ ad.AssetName = mapid + "_generators";
+ return ad;
+ }
+
+ public AssetDescription GetDS2GeneratorLocationParam(string mapid, bool writemode = false)
+ {
+ AssetDescription ad = new();
+ var path = $@"Param\generatorlocation_{mapid}";
+ if (writemode)
+ {
+ ad.AssetPath = $@"{RootDirectory}\{path}.param";
+ }
+ else
+ {
+ ad.AssetPath = GetAssetPath($@"{path}.param");
+ }
+
+ ad.AssetName = mapid + "_generator_locations";
+ return ad;
+ }
+
+ public AssetDescription GetDS2GeneratorRegistParam(string mapid, bool writemode = false)
+ {
+ AssetDescription ad = new();
+ var path = $@"Param\generatorregistparam_{mapid}";
+ if (writemode)
+ {
+ ad.AssetPath = $@"{RootDirectory}\{path}.param";
+ }
+ else
+ {
+ ad.AssetPath = GetAssetPath($@"{path}.param");
+ }
+
+ ad.AssetName = mapid + "_generator_registrations";
+ return ad;
+ }
+
+ public AssetDescription GetDS2EventParam(string mapid, bool writemode = false)
+ {
+ AssetDescription ad = new();
+ var path = $@"Param\eventparam_{mapid}";
+ if (writemode)
+ {
+ ad.AssetPath = $@"{RootDirectory}\{path}.param";
+ }
+ else
+ {
+ ad.AssetPath = GetAssetPath($@"{path}.param");
+ }
+
+ ad.AssetName = mapid + "_event_params";
+ return ad;
+ }
+
+ public AssetDescription GetDS2EventLocationParam(string mapid, bool writemode = false)
+ {
+ AssetDescription ad = new();
+ var path = $@"Param\eventlocation_{mapid}";
+ if (writemode)
+ {
+ ad.AssetPath = $@"{RootDirectory}\{path}.param";
+ }
+ else
+ {
+ ad.AssetPath = GetAssetPath($@"{path}.param");
+ }
+
+ ad.AssetName = mapid + "_event_locations";
+ return ad;
+ }
+
+ public AssetDescription GetDS2ObjInstanceParam(string mapid, bool writemode = false)
+ {
+ AssetDescription ad = new();
+ var path = $@"Param\mapobjectinstanceparam_{mapid}";
+ if (writemode)
+ {
+ ad.AssetPath = $@"{RootDirectory}\{path}.param";
+ }
+ else
+ {
+ ad.AssetPath = GetAssetPath($@"{path}.param");
+ }
+
+ ad.AssetName = mapid + "_object_instance_params";
+ return ad;
+ }
+
+ // Used to get the map model list from within the mapbhd/bdt
+ public List GetMapModelsFromBXF(string mapid)
+ {
+ List ret = new();
+
+ if (Locator.AssetLocator.Type is GameType.DarkSoulsIISOTFS)
+ {
+ var path = GetAssetPath($@"model/map/{mapid}.mapbdt");
+
+ if (path != null)
+ {
+ var bdtPath = path;
+ var bhdPath = path.Replace("bdt", "bhd");
+
+ var bxf = BXF4.Read(bhdPath, bdtPath);
+
+ if (bxf != null)
+ {
+ foreach (var file in bxf.Files)
+ {
+ if (file.Name.Contains(".flv"))
+ {
+ var name = GetFileNameWithoutExtensions(file.Name);
+
+ AssetDescription ad = new();
+ ad.AssetName = name;
+ ad.AssetArchiveVirtualPath = $@"map/{name}/model/";
+
+ ret.Add(ad);
+ }
+ }
+ }
+ }
+ }
+
+ return ret;
+ }
+
+ public List GetMapModels(string mapid)
+ {
+ List ret = new();
+ if (Type == GameType.DarkSoulsIII || Type == GameType.Sekiro)
+ {
+ foreach (var f in GetAllAssets($@"\map\{mapid}\", [@"*.mapbnd.dcx"]))
+ {
+ AssetDescription ad = new();
+ ad.AssetPath = f;
+ var name = GetFileNameWithoutExtensions(f);
+ ad.AssetName = name;
+ ad.AssetArchiveVirtualPath = $@"map/{mapid}/model/{name}";
+ ad.AssetVirtualPath = $@"map/{mapid}/model/{name}/{name}.flver";
+ ret.Add(ad);
+ }
+ }
+ else if (Type == GameType.DarkSoulsIISOTFS)
+ {
+ AssetDescription ad = new();
+ var name = mapid;
+ ad.AssetName = name;
+ ad.AssetArchiveVirtualPath = $@"map/{mapid}/model";
+ ret.Add(ad);
+ }
+ else if (Type == GameType.EldenRing)
+ {
+ var mapPath = RootDirectory + $@"\map\{mapid[..3]}\{mapid}";
+ foreach (var f in GetAllAssets(mapPath, [@"*.mapbnd.dcx"]))
+ {
+ AssetDescription ad = new();
+ ad.AssetPath = f;
+ var name = GetFileNameWithoutExtensions(f);
+ ad.AssetName = name;
+ ad.AssetArchiveVirtualPath = $@"map/{mapid}/model/{name}";
+ ad.AssetVirtualPath = $@"map/{mapid}/model/{name}/{name}.flver";
+ ret.Add(ad);
+ }
+ }
+ else if (Type == GameType.ArmoredCoreVI)
+ {
+ var mapPath = RootDirectory + $@"\map\{mapid[..3]}\{mapid}";
+ foreach (var f in GetAllAssets(mapPath, [@"*.mapbnd.dcx"]))
+ {
+ AssetDescription ad = new();
+ ad.AssetPath = f;
+ var name = GetFileNameWithoutExtensions(f);
+ ad.AssetName = name;
+ ad.AssetArchiveVirtualPath = $@"map/{mapid}/model/{name}";
+ ad.AssetVirtualPath = $@"map/{mapid}/model/{name}/{name}.flver";
+ ret.Add(ad);
+ }
+ }
+ else
+ {
+ if (!Directory.Exists(RootDirectory + $@"\map\{mapid}\"))
+ {
+ return ret;
+ }
+
+ var ext = Type == GameType.DarkSoulsPTDE ? @"*.flver" : @"*.flver.dcx";
+ List mapfiles = Directory.GetFileSystemEntries(RootDirectory + $@"\map\{mapid}\", ext)
+ .ToList();
+ foreach (var f in mapfiles)
+ {
+ AssetDescription ad = new();
+ ad.AssetPath = f;
+ var name = GetFileNameWithoutExtensions(f);
+ ad.AssetName = name;
+ // ad.AssetArchiveVirtualPath = $@"map/{mapid}/model/{name}";
+ ad.AssetVirtualPath = $@"map/{mapid}/model/{name}/{name}.flver";
+ ret.Add(ad);
+ }
+ }
+
+ return ret;
+ }
+ public string MapModelNameToAssetName(string mapid, string modelname)
+ {
+ if (Type == GameType.DarkSoulsPTDE || Type == GameType.DarkSoulsRemastered)
+ {
+ return $@"{modelname}A{mapid.Substring(1, 2)}";
+ }
+
+ if (Type == GameType.DemonsSouls)
+ {
+ return $@"{modelname}";
+ }
+
+ if (Type == GameType.DarkSoulsIISOTFS)
+ {
+ return modelname;
+ }
+
+ return $@"{mapid}_{modelname.Substring(1)}";
+ }
+
+ ///
+ /// Gets the adjusted map ID that contains all the map assets
+ ///
+ /// The msb map ID to adjust
+ /// The map ID for the purpose of asset storage
+ public string GetAssetMapID(string mapid)
+ {
+ if (Type is GameType.EldenRing or GameType.ArmoredCoreVI)
+ {
+ return mapid;
+ }
+
+ if (Type is GameType.DarkSoulsRemastered)
+ {
+ if (mapid.StartsWith("m99"))
+ {
+ // DSR m99 maps contain their own assets
+ return mapid;
+ }
+ }
+ else if (Type is GameType.DemonsSouls)
+ {
+ return mapid;
+ }
+ else if (Type is GameType.Bloodborne)
+ {
+ if (mapid.StartsWith("m29"))
+ {
+ // Special case for chalice dungeon assets
+ return "m29_00_00_00";
+ }
+ }
+
+ // Default
+ return mapid.Substring(0, 6) + "_00_00";
+ }
+ public AssetDescription GetMapModel(string mapid, string model)
+ {
+ AssetDescription ret = new();
+ if (Type == GameType.DarkSoulsPTDE || Type == GameType.Bloodborne || Type == GameType.DemonsSouls)
+ {
+ ret.AssetPath = GetAssetPath($@"map\{mapid}\{model}.flver");
+ }
+ else if (Type == GameType.DarkSoulsRemastered)
+ {
+ ret.AssetPath = GetAssetPath($@"map\{mapid}\{model}.flver.dcx");
+ }
+ else if (Type == GameType.DarkSoulsIISOTFS)
+ {
+ ret.AssetPath = GetAssetPath($@"model\map\{mapid}.mapbhd");
+ }
+ else if (Type == GameType.EldenRing)
+ {
+ ret.AssetPath = GetAssetPath($@"map\{mapid[..3]}\{mapid}\{model}.mapbnd.dcx");
+ }
+ else if (Type == GameType.ArmoredCoreVI)
+ {
+ ret.AssetPath = GetAssetPath($@"map\{mapid[..3]}\{mapid}\{model}.mapbnd.dcx");
+ }
+ else
+ {
+ ret.AssetPath = GetAssetPath($@"map\{mapid}\{model}.mapbnd.dcx");
+ }
+
+ ret.AssetName = model;
+ if (Type == GameType.DarkSoulsIISOTFS)
+ {
+ ret.AssetArchiveVirtualPath = $@"map/{mapid}/model";
+ ret.AssetVirtualPath = $@"map/{mapid}/model/{model}.flv.dcx";
+ }
+ else
+ {
+ if (Type is not GameType.DemonsSouls
+ and not GameType.DarkSoulsPTDE
+ and not GameType.DarkSoulsRemastered
+ and not GameType.Bloodborne)
+ {
+ ret.AssetArchiveVirtualPath = $@"map/{mapid}/model/{model}";
+ }
+
+ ret.AssetVirtualPath = $@"map/{mapid}/model/{model}/{model}.flver";
+ }
+
+ return ret;
+ }
+
+ public AssetDescription GetMapCollisionModel(string mapid, string model, bool hi = true)
+ {
+ AssetDescription ret = new();
+ if (Type == GameType.DarkSoulsPTDE || Type == GameType.DemonsSouls)
+ {
+ if (hi)
+ {
+ ret.AssetPath = GetAssetPath($@"map\{mapid}\{model}.hkx");
+ ret.AssetName = model;
+ ret.AssetVirtualPath = $@"map/{mapid}/hit/hi/{model}.hkx";
+ }
+ else
+ {
+ ret.AssetPath = GetAssetPath($@"map\{mapid}\l{model.Substring(1)}.hkx");
+ ret.AssetName = model;
+ ret.AssetVirtualPath = $@"map/{mapid}/hit/lo/l{model.Substring(1)}.hkx";
+ }
+ }
+ else if (Type == GameType.DarkSoulsIISOTFS)
+ {
+ ret.AssetPath = GetAssetPath($@"model\map\h{mapid.Substring(1)}.hkxbhd");
+ ret.AssetName = model;
+ ret.AssetVirtualPath = $@"map/{mapid}/hit/hi/{model}.hkx.dcx";
+ ret.AssetArchiveVirtualPath = $@"map/{mapid}/hit/hi";
+ }
+ else if (Type == GameType.DarkSoulsIII || Type == GameType.Bloodborne)
+ {
+ if (hi)
+ {
+ ret.AssetPath = GetAssetPath($@"map\{mapid}\h{mapid.Substring(1)}.hkxbhd");
+ ret.AssetName = model;
+ ret.AssetVirtualPath = $@"map/{mapid}/hit/hi/h{model.Substring(1)}.hkx.dcx";
+ ret.AssetArchiveVirtualPath = $@"map/{mapid}/hit/hi";
+ }
+ else
+ {
+ ret.AssetPath = GetAssetPath($@"map\{mapid}\l{mapid.Substring(1)}.hkxbhd");
+ ret.AssetName = model;
+ ret.AssetVirtualPath = $@"map/{mapid}/hit/lo/l{model.Substring(1)}.hkx.dcx";
+ ret.AssetArchiveVirtualPath = $@"map/{mapid}/hit/lo";
+ }
+ }
+ else
+ {
+ return AssetUtils.GetNullAsset();
+ }
+
+ return ret;
+ }
+
+ public List GetMapTextures(string mapid)
+ {
+ List ads = new();
+
+ if (Type == GameType.DarkSoulsIISOTFS)
+ {
+ AssetDescription t = new();
+ t.AssetPath = GetAssetPath($@"model\map\t{mapid.Substring(1)}.tpfbhd");
+ t.AssetArchiveVirtualPath = $@"map/tex/{mapid}/tex";
+ ads.Add(t);
+ }
+ else if (Type == GameType.DarkSoulsPTDE)
+ {
+ // TODO
+ }
+ else if (Type == GameType.EldenRing)
+ {
+ // TODO ER
+ }
+ else if (Type == GameType.ArmoredCoreVI)
+ {
+ // TODO AC6
+ }
+ else if (Type == GameType.DemonsSouls)
+ {
+ var mid = mapid.Substring(0, 3);
+ var paths = Directory.GetFileSystemEntries($@"{RootDirectory}\map\{mid}\", "*.tpf.dcx");
+ foreach (var path in paths)
+ {
+ AssetDescription ad = new();
+ ad.AssetPath = path;
+ var tid = Path.GetFileNameWithoutExtension(path).Substring(4, 4);
+ ad.AssetVirtualPath = $@"map/tex/{mid}/{tid}";
+ ads.Add(ad);
+ }
+ }
+ else
+ {
+ // Clean this up. Even if it's common code having something like "!=Sekiro" can lead to future issues
+ var mid = mapid.Substring(0, 3);
+
+ AssetDescription t0000 = new();
+ t0000.AssetPath = GetAssetPath($@"map\{mid}\{mid}_0000.tpfbhd");
+ t0000.AssetArchiveVirtualPath = $@"map/tex/{mid}/0000";
+ ads.Add(t0000);
+
+ AssetDescription t0001 = new();
+ t0001.AssetPath = GetAssetPath($@"map\{mid}\{mid}_0001.tpfbhd");
+ t0001.AssetArchiveVirtualPath = $@"map/tex/{mid}/0001";
+ ads.Add(t0001);
+
+ AssetDescription t0002 = new();
+ t0002.AssetPath = GetAssetPath($@"map\{mid}\{mid}_0002.tpfbhd");
+ t0002.AssetArchiveVirtualPath = $@"map/tex/{mid}/0002";
+ ads.Add(t0002);
+
+ AssetDescription t0003 = new();
+ t0003.AssetPath = GetAssetPath($@"map\{mid}\{mid}_0003.tpfbhd");
+ t0003.AssetArchiveVirtualPath = $@"map/tex/{mid}/0003";
+ ads.Add(t0003);
+
+ if (Type == GameType.DarkSoulsRemastered)
+ {
+ AssetDescription env = new();
+ env.AssetPath = GetAssetPath($@"map\{mid}\GI_EnvM_{mid}.tpfbhd");
+ env.AssetArchiveVirtualPath = $@"map/tex/{mid}/env";
+ ads.Add(env);
+ }
+ else if (Type == GameType.Bloodborne || Type == GameType.DarkSoulsIII)
+ {
+ AssetDescription env = new();
+ env.AssetPath = GetAssetPath($@"map\{mid}\{mid}_envmap.tpf.dcx");
+ env.AssetVirtualPath = $@"map/tex/{mid}/env";
+ ads.Add(env);
+ }
+ else if (Type == GameType.Sekiro)
+ {
+ //TODO SDT
+ }
+ }
+
+ return ads;
+ }
+ public List GetEnvMapTextureNames(string mapid)
+ {
+ List l = new();
+ if (Type == GameType.DarkSoulsIII)
+ {
+ var mid = mapid.Substring(0, 3);
+ if (File.Exists(GetAssetPath($@"map\{mid}\{mid}_envmap.tpf.dcx")))
+ {
+ TPF t = TPF.Read(GetAssetPath($@"map\{mid}\{mid}_envmap.tpf.dcx"));
+ foreach (TPF.Texture tex in t.Textures)
+ {
+ l.Add(tex.Name);
+ }
+ }
+ }
+
+ return l;
+ }
+
+ private string GetChrTexturePath(string chrid)
+ {
+ if (Type is GameType.DemonsSouls)
+ {
+ return GetAssetPath($@"chr\{chrid}\{chrid}.tpf");
+ }
+
+ if (Type is GameType.DarkSoulsPTDE)
+ {
+ var path = GetAssetPath($@"chr\{chrid}\{chrid}.tpf");
+ if (path != null)
+ {
+ return path;
+ }
+
+ return GetAssetPath($@"chr\{chrid}.chrbnd");
+ }
+
+ if (Type is GameType.DarkSoulsIISOTFS)
+ {
+ return GetAssetPath($@"model\chr\{chrid}.texbnd");
+ }
+
+ if (Type is GameType.DarkSoulsRemastered)
+ {
+ // TODO: Some textures require getting chrtpfbhd from chrbnd, then using it with chrtpfbdt in chr folder.
+ return GetAssetPath($@"chr\{chrid}.chrbnd");
+ }
+
+ if (Type is GameType.Bloodborne)
+ {
+ return GetAssetPath($@"chr\{chrid}_2.tpf.dcx");
+ }
+
+ if (Type is GameType.DarkSoulsIII or GameType.Sekiro)
+ {
+ return GetAssetPath($@"chr\{chrid}.texbnd.dcx");
+ }
+
+ if (Type is GameType.EldenRing)
+ {
+ // TODO: Maybe add an option down the line to load lower quality
+ return GetAssetPath($@"chr\{chrid}_h.texbnd.dcx");
+ }
+
+ if (Type is GameType.ArmoredCoreVI)
+ {
+ return GetAssetPath($@"chr\{chrid}.texbnd.dcx");
+ }
+
+ return null;
+ }
+
+ public AssetDescription GetChrTextures(string chrid)
+ {
+ AssetDescription ad = new();
+ ad.AssetArchiveVirtualPath = null;
+ ad.AssetPath = null;
+ if (Type is GameType.DemonsSouls)
+ {
+ var path = GetChrTexturePath(chrid);
+ if (path != null)
+ {
+ ad.AssetPath = path;
+ ad.AssetVirtualPath = $@"chr/{chrid}/tex";
+ }
+ }
+ else if (Type is GameType.DarkSoulsPTDE)
+ {
+ var path = GetChrTexturePath(chrid);
+ if (path != null)
+ {
+ ad.AssetPath = path;
+ if (path.EndsWith(".chrbnd"))
+ {
+ ad.AssetArchiveVirtualPath = $@"chr/{chrid}/tex";
+ }
+ else
+ {
+ ad.AssetVirtualPath = $@"chr/{chrid}/tex";
+ }
+ }
+ }
+ else if (Type is GameType.DarkSoulsRemastered)
+ {
+ // TODO: Some textures require getting chrtpfbhd from chrbnd, then using it with chrtpfbdt in chr folder.
+ var path = GetChrTexturePath(chrid);
+ if (path != null)
+ {
+ ad = new AssetDescription();
+ ad.AssetPath = path;
+ ad.AssetVirtualPath = $@"chr/{chrid}/tex";
+ }
+ }
+ else if (Type is GameType.DarkSoulsIISOTFS)
+ {
+ var path = GetChrTexturePath(chrid);
+ if (path != null)
+ {
+ ad = new AssetDescription();
+ ad.AssetPath = path;
+ ad.AssetVirtualPath = $@"chr/{chrid}/tex";
+ }
+ }
+ else if (Type is GameType.Bloodborne)
+ {
+ var path = GetChrTexturePath(chrid);
+ if (path != null)
+ {
+ ad.AssetPath = path;
+ ad.AssetVirtualPath = $@"chr/{chrid}/tex";
+ }
+ }
+ else if (Type is GameType.DarkSoulsIII or GameType.Sekiro)
+ {
+ var path = GetChrTexturePath(chrid);
+ if (path != null)
+ {
+ ad.AssetPath = path;
+ ad.AssetArchiveVirtualPath = $@"chr/{chrid}/tex";
+ }
+ }
+ else if (Type is GameType.EldenRing or GameType.ArmoredCoreVI)
+ {
+ var path = GetChrTexturePath(chrid);
+ if (path != null)
+ {
+ ad.AssetPath = path;
+ ad.AssetArchiveVirtualPath = $@"chr/{chrid}/tex";
+ }
+ }
+
+ return ad;
+ }
+ public AssetDescription GetMapNVMModel(string mapid, string model)
+ {
+ AssetDescription ret = new();
+ if (Type == GameType.DarkSoulsPTDE || Type == GameType.DarkSoulsRemastered || Type == GameType.DemonsSouls)
+ {
+ ret.AssetPath = GetAssetPath($@"map\{mapid}\{model}.nvm");
+ ret.AssetName = model;
+ ret.AssetArchiveVirtualPath = $@"map/{mapid}/nav";
+ ret.AssetVirtualPath = $@"map/{mapid}/nav/{model}.nvm";
+ }
+ else
+ {
+ return AssetUtils.GetNullAsset();
+ }
+
+ return ret;
+ }
+
+ public AssetDescription GetHavokNavmeshes(string mapid)
+ {
+ AssetDescription ret = new();
+ ret.AssetPath = GetAssetPath($@"map\{mapid}\{mapid}.nvmhktbnd.dcx");
+ ret.AssetName = mapid;
+ ret.AssetArchiveVirtualPath = $@"map/{mapid}/nav";
+ return ret;
+ }
+
+ public AssetDescription GetHavokNavmeshModel(string mapid, string model)
+ {
+ AssetDescription ret = new();
+ ret.AssetPath = GetAssetPath($@"map\{mapid}\{mapid}.nvmhktbnd.dcx");
+ ret.AssetName = model;
+ ret.AssetArchiveVirtualPath = $@"map/{mapid}/nav";
+ ret.AssetVirtualPath = $@"map/{mapid}/nav/{model}.hkx";
+
+ return ret;
+ }
+
+ public List GetChrModels()
+ {
+ try
+ {
+ HashSet chrs = new();
+ List ret = new();
+
+ var modelDir = @"\chr";
+ var modelExt = @".chrbnd.dcx";
+ if (Type == GameType.DarkSoulsPTDE)
+ {
+ modelExt = ".chrbnd";
+ }
+ else if (Type == GameType.DarkSoulsIISOTFS)
+ {
+ modelDir = @"\model\chr";
+ modelExt = ".bnd";
+ }
+
+ if (Type == GameType.DemonsSouls)
+ {
+ foreach (var f in GetAllSubDirs(modelDir).Select(Path.GetFileName).Where(x => x.StartsWith("c")))
+ {
+ ret.Add(f);
+ }
+
+ return ret;
+ }
+
+ foreach (var f in GetAllAssets(modelDir, [$@"*{modelExt}"]))
+ {
+ var name = GetFileNameWithoutExtensions(f);
+ ret.Add(name);
+ chrs.Add(name);
+ }
+
+ return ret;
+ }
+ catch (DirectoryNotFoundException e)
+ {
+ // Game likely isn't UXM unpacked
+ return new List();
+ }
+ }
+ public AssetDescription GetChrModel(string chr)
+ {
+ AssetDescription ret = new();
+ ret.AssetName = chr;
+ ret.AssetArchiveVirtualPath = $@"chr/{chr}/model";
+ if (Type == GameType.DarkSoulsIISOTFS)
+ {
+ ret.AssetVirtualPath = $@"chr/{chr}/model/{chr}.flv";
+ }
+ else
+ {
+ ret.AssetVirtualPath = $@"chr/{chr}/model/{chr}.flver";
+ }
+
+ return ret;
+ }
+
+ public List GetObjModels()
+ {
+ try
+ {
+ HashSet objs = new();
+ List ret = new();
+
+ var modelDir = @"\obj";
+ var modelExt = @".objbnd.dcx";
+ if (Type == GameType.DarkSoulsPTDE)
+ {
+ modelExt = ".objbnd";
+ }
+ else if (Type == GameType.DarkSoulsIISOTFS)
+ {
+ modelDir = @"\model\obj";
+ modelExt = ".bnd";
+ }
+ else if (Type == GameType.EldenRing)
+ {
+ // AEGs are objs in my heart :(
+ modelDir = @"\asset\aeg";
+ modelExt = ".geombnd.dcx";
+ }
+ else if (Type == GameType.ArmoredCoreVI)
+ {
+ // AEGs are objs in my heart :(
+ modelDir = @"\asset\environment\geometry";
+ modelExt = ".geombnd.dcx";
+ }
+
+ // Directories to search for obj models
+ List searchDirs = new();
+ if (Type == GameType.EldenRing)
+ {
+ searchDirs = GetAllSubDirs(modelDir).Where(x => GetFileNameWithoutExtensions(x).StartsWith("aeg")).ToList();
+ }
+ else
+ {
+ searchDirs.Add(GetAssetPath(modelDir));
+ }
+
+ foreach (var searchDir in searchDirs)
+ {
+ foreach (var f in GetAllAssets(searchDir, [$@"*{modelExt}"]))
+ {
+ var name = GetFileNameWithoutExtensions(f);
+ ret.Add(name);
+ objs.Add(name);
+ }
+ }
+
+ return ret;
+ }
+ catch (DirectoryNotFoundException e)
+ {
+ // Game likely isn't UXM unpacked
+ return new List();
+ }
+ }
+
+ public AssetDescription GetObjModel(string obj)
+ {
+ AssetDescription ret = new();
+ ret.AssetName = obj;
+ ret.AssetArchiveVirtualPath = $@"obj/{obj}/model";
+ if (Type == GameType.DarkSoulsIISOTFS)
+ {
+ ret.AssetVirtualPath = $@"obj/{obj}/model/{obj}.flv";
+ }
+ else if (Type is GameType.EldenRing or GameType.ArmoredCoreVI)
+ {
+ ret.AssetVirtualPath = $@"obj/{obj}/model/{obj.ToUpper()}.flver";
+ }
+ else
+ {
+ ret.AssetVirtualPath = $@"obj/{obj}/model/{obj}.flver";
+ }
+
+ return ret;
+ }
+
+ public AssetDescription GetObjTexture(string obj)
+ {
+ AssetDescription ad = new();
+ ad.AssetPath = null;
+ ad.AssetArchiveVirtualPath = null;
+ string path = null;
+ if (Type == GameType.DarkSoulsPTDE)
+ {
+ path = GetAssetPath($@"obj\{obj}.objbnd");
+ }
+ else if (Type is GameType.DemonsSouls or GameType.DarkSoulsRemastered or GameType.Bloodborne
+ or GameType.DarkSoulsIII or GameType.Sekiro)
+ {
+ path = GetAssetPath($@"obj\{obj}.objbnd.dcx");
+ }
+
+ if (path != null)
+ {
+ ad.AssetPath = path;
+ ad.AssetArchiveVirtualPath = $@"obj/{obj}/tex";
+ }
+
+ return ad;
+ }
+
+ public AssetDescription GetAetTexture(string aetid)
+ {
+ AssetDescription ad = new();
+ ad.AssetPath = null;
+ ad.AssetArchiveVirtualPath = null;
+ string path;
+ if (Type == GameType.EldenRing)
+ {
+ path = GetAssetPath($@"asset\aet\{aetid.Substring(0, 6)}\{aetid}.tpf.dcx");
+ }
+ else if (Type is GameType.ArmoredCoreVI)
+ {
+ path = GetAssetPath($@"\asset\environment\texture\{aetid}.tpf.dcx");
+ }
+ else
+ {
+ throw new NotSupportedException();
+ }
+
+ if (path != null)
+ {
+ ad.AssetPath = path;
+ ad.AssetArchiveVirtualPath = $@"aet/{aetid}/tex";
+ }
+
+ return ad;
+ }
+ public List GetPartsModels()
+ {
+ try
+ {
+ HashSet parts = new();
+ List ret = new();
+
+ var modelDir = @"\parts";
+ var modelExt = @".partsbnd.dcx";
+ if (Type == GameType.DarkSoulsPTDE)
+ {
+ modelExt = ".partsbnd";
+ }
+ else if (Type == GameType.DarkSoulsIISOTFS)
+ {
+ modelDir = @"\model\parts";
+ modelExt = ".bnd";
+ var partsGatheredFiles = GetAllAssets(modelDir, ["*"], true, true);
+ Directory.GetFiles(RootDirectory + modelDir, "*", SearchOption.AllDirectories);
+ foreach (var f in partsGatheredFiles)
+ {
+ if (!f.EndsWith("common.commonbnd.dcx") && !f.EndsWith("common_cloth.commonbnd.dcx") &&
+ !f.EndsWith("facepreset.bnd"))
+ {
+ ret.Add(GetFileNameWithoutExtensions(f));
+ }
+ }
+
+ return ret;
+ }
+
+ List partsFiles = GetAllAssets(modelDir, [$@"*{modelExt}"]).ToList();
+ foreach (var f in partsFiles)
+ {
+ var name = GetFileNameWithoutExtensions(f);
+ ret.Add(name);
+ parts.Add(name);
+ }
+
+ return ret;
+ }
+ catch (DirectoryNotFoundException e)
+ {
+ // Game likely isn't UXM unpacked
+ return new List();
+ }
+ }
+
+ public AssetDescription GetPartsModel(string part)
+ {
+ AssetDescription ret = new();
+ ret.AssetName = part;
+ ret.AssetArchiveVirtualPath = $@"parts/{part}/model";
+ if (Type == GameType.DarkSoulsIISOTFS)
+ {
+ ret.AssetVirtualPath = $@"parts/{part}/model/{part}.flv";
+ }
+ else if (Type is GameType.DarkSoulsPTDE)
+ {
+ ret.AssetVirtualPath = $@"parts/{part}/model/{part.ToUpper()}.flver";
+ }
+ else
+ {
+ ret.AssetVirtualPath = $@"parts/{part}/model/{part}.flver";
+ }
+
+ return ret;
+ }
+
+ public AssetDescription GetPartTextures(string partsId)
+ {
+ AssetDescription ad = new();
+ ad.AssetArchiveVirtualPath = null;
+ ad.AssetPath = null;
+ if (Type == GameType.ArmoredCoreVI)
+ {
+ string path;
+ if (partsId.Substring(0, 2) == "wp")
+ {
+ string id;
+ if (partsId.EndsWith("_l"))
+ {
+ id = partsId[..^2].Split("_").Last();
+ path = GetAssetPath($@"parts\wp_{id}_l.tpf.dcx");
+ }
+ else
+ {
+ id = partsId.Split("_").Last();
+ path = GetAssetPath($@"parts\wp_{id}.tpf.dcx");
+ }
+ }
+ else
+ {
+ path = GetAssetPath($@"parts\{partsId}_u.tpf.dcx");
+ }
+
+ if (path != null)
+ {
+ ad.AssetPath = path;
+ ad.AssetVirtualPath = $@"parts/{partsId}/tex";
+ }
+ }
+ else if (Type == GameType.EldenRing)
+ {
+ // Maybe add an option down the line to load lower quality
+ var path = GetAssetPath($@"parts\{partsId}.partsbnd.dcx");
+ if (path != null)
+ {
+ ad.AssetPath = path;
+ ad.AssetArchiveVirtualPath = $@"parts/{partsId}/tex";
+ }
+ }
+ else if (Type == GameType.DarkSoulsIII || Type == GameType.Sekiro)
+ {
+ var path = GetAssetPath($@"parts\{partsId}.partsbnd.dcx");
+ if (path != null)
+ {
+ ad.AssetPath = path;
+ ad.AssetArchiveVirtualPath = $@"parts/{partsId}/tex";
+ }
+ }
+ else if (Type == GameType.Bloodborne)
+ {
+ var path = GetAssetPath($@"parts\{partsId}.partsbnd.dcx");
+ if (path != null)
+ {
+ ad.AssetPath = path;
+ ad.AssetVirtualPath = $@"parts/{partsId}/tex";
+ }
+ }
+ else if (Type == GameType.DarkSoulsPTDE)
+ {
+ var path = GetAssetPath($@"parts\{partsId}.partsbnd");
+ if (path != null)
+ {
+ ad.AssetPath = path;
+ ad.AssetArchiveVirtualPath = $@"parts/{partsId}/tex";
+ }
+ }
+ else if (Type == GameType.DemonsSouls)
+ {
+ var path = GetAssetPath($@"parts\{partsId}.partsbnd.dcx");
+ if (path != null)
+ {
+ ad.AssetPath = path;
+ ad.AssetArchiveVirtualPath = $@"parts/{partsId}/tex";
+ }
+ }
+
+ return ad;
+ }
+
+ public AssetDescription GetNullAsset()
+ {
+ AssetDescription ret = new();
+ ret.AssetPath = "null";
+ ret.AssetName = "null";
+ ret.AssetArchiveVirtualPath = "null";
+ ret.AssetVirtualPath = "null";
+ return ret;
+ }
+
+ ///
+ /// Converts a virtual path to an actual filesystem path. Only resolves virtual paths up to the bnd level,
+ /// which the remaining string is output for additional handling
+ ///
+ ///
+ ///
+ public string VirtualToRealPath(string virtualPath, out string bndpath)
+ {
+ var pathElements = virtualPath.Split('/');
+ Regex mapRegex = new(@"^m\d{2}_\d{2}_\d{2}_\d{2}$");
+ var ret = "";
+
+ // Parse the virtual path with a DFA and convert it to a game path
+ var i = 0;
+ if (pathElements[i].Equals("map"))
+ {
+ i++;
+ if (pathElements[i].Equals("tex"))
+ {
+ i++;
+ if (Type == GameType.DarkSoulsIISOTFS)
+ {
+ var mid = pathElements[i];
+ i++;
+ var id = pathElements[i];
+ if (id == "tex")
+ {
+ bndpath = "";
+ return GetAssetPath($@"model\map\t{mid.Substring(1)}.tpfbhd");
+ }
+ }
+ else if (Type == GameType.DemonsSouls)
+ {
+ var mid = pathElements[i];
+ i++;
+ bndpath = "";
+ return GetAssetPath($@"map\{mid}\{mid}_{pathElements[i]}.tpf.dcx");
+ }
+ else
+ {
+ var mid = pathElements[i];
+ i++;
+ bndpath = "";
+ if (pathElements[i] == "env")
+ {
+ if (Type == GameType.DarkSoulsRemastered)
+ {
+ return GetAssetPath($@"map\{mid}\GI_EnvM_{mid}.tpf.dcx");
+ }
+
+ return GetAssetPath($@"map\{mid}\{mid}_envmap.tpf.dcx");
+ }
+
+ return GetAssetPath($@"map\{mid}\{mid}_{pathElements[i]}.tpfbhd");
+ }
+ }
+ else if (mapRegex.IsMatch(pathElements[i]))
+ {
+ var mapid = pathElements[i];
+ i++;
+ if (pathElements[i].Equals("model"))
+ {
+ i++;
+ bndpath = "";
+ if (Type == GameType.DarkSoulsPTDE)
+ {
+ return GetAssetPath($@"map\{mapid}\{pathElements[i]}.flver");
+ }
+
+ if (Type == GameType.DarkSoulsRemastered)
+ {
+ return GetAssetPath($@"map\{mapid}\{pathElements[i]}.flver.dcx");
+ }
+
+ if (Type == GameType.DarkSoulsIISOTFS)
+ {
+ return GetAssetPath($@"model\map\{mapid}.mapbhd");
+ }
+
+ if (Type == GameType.Bloodborne || Type == GameType.DemonsSouls)
+ {
+ return GetAssetPath($@"map\{mapid}\{pathElements[i]}.flver.dcx");
+ }
+
+ if (Type == GameType.EldenRing)
+ {
+ return GetAssetPath($@"map\{mapid.Substring(0, 3)}\{mapid}\{pathElements[i]}.mapbnd.dcx");
+ }
+
+ if (Type == GameType.ArmoredCoreVI)
+ {
+ return GetAssetPath($@"map\{mapid.Substring(0, 3)}\{mapid}\{pathElements[i]}.mapbnd.dcx");
+ }
+
+ return GetAssetPath($@"map\{mapid}\{pathElements[i]}.mapbnd.dcx");
+ }
+
+ if (pathElements[i].Equals("hit"))
+ {
+ i++;
+ var hittype = pathElements[i];
+ i++;
+ if (Type == GameType.DarkSoulsPTDE || Type == GameType.DemonsSouls)
+ {
+ bndpath = "";
+ return GetAssetPath($@"map\{mapid}\{pathElements[i]}");
+ }
+
+ if (Type == GameType.DarkSoulsIISOTFS)
+ {
+ bndpath = "";
+ return GetAssetPath($@"model\map\h{mapid.Substring(1)}.hkxbhd");
+ }
+
+ if (Type == GameType.DarkSoulsIII || Type == GameType.Bloodborne)
+ {
+ bndpath = "";
+ if (hittype == "lo")
+ {
+ return GetAssetPath($@"map\{mapid}\l{mapid.Substring(1)}.hkxbhd");
+ }
+
+ return GetAssetPath($@"map\{mapid}\h{mapid.Substring(1)}.hkxbhd");
+ }
+
+ bndpath = "";
+ return null;
+ }
+
+ if (pathElements[i].Equals("nav"))
+ {
+ i++;
+ if (Type == GameType.DarkSoulsPTDE || Type == GameType.DemonsSouls ||
+ Type == GameType.DarkSoulsRemastered)
+ {
+ if (i < pathElements.Length)
+ {
+ bndpath = $@"{pathElements[i]}";
+ }
+ else
+ {
+ bndpath = "";
+ }
+
+ if (Type == GameType.DarkSoulsRemastered)
+ {
+ return GetAssetPath($@"map\{mapid}\{mapid}.nvmbnd.dcx");
+ }
+
+ return GetAssetPath($@"map\{mapid}\{mapid}.nvmbnd");
+ }
+
+ if (Type == GameType.DarkSoulsIII)
+ {
+ bndpath = "";
+ return GetAssetPath($@"map\{mapid}\{mapid}.nvmhktbnd.dcx");
+ }
+
+ bndpath = "";
+ return null;
+ }
+ }
+ }
+ else if (pathElements[i].Equals("chr"))
+ {
+ i++;
+ var chrid = pathElements[i];
+ i++;
+ if (pathElements[i].Equals("model"))
+ {
+ bndpath = "";
+ if (Type == GameType.DarkSoulsPTDE)
+ {
+ return GetAssetPath($@"chr\{chrid}.chrbnd");
+ }
+
+ if (Type == GameType.DarkSoulsIISOTFS)
+ {
+ return GetAssetPath($@"model\chr\{chrid}.bnd");
+ }
+
+ if (Type == GameType.DemonsSouls)
+ {
+ return GetAssetPath($@"chr\{chrid}\{chrid}.chrbnd.dcx");
+ }
+
+ return GetAssetPath($@"chr\{chrid}.chrbnd.dcx");
+ }
+
+ if (pathElements[i].Equals("tex"))
+ {
+ bndpath = "";
+ return GetChrTexturePath(chrid);
+ }
+ }
+ else if (pathElements[i].Equals("obj"))
+ {
+ i++;
+ var objid = pathElements[i];
+ i++;
+ if (pathElements[i].Equals("model") || pathElements[i].Equals("tex"))
+ {
+ bndpath = "";
+ if (Type == GameType.DarkSoulsPTDE)
+ {
+ return GetAssetPath($@"obj\{objid}.objbnd");
+ }
+
+ if (Type == GameType.DarkSoulsIISOTFS)
+ {
+ return GetAssetPath($@"model\obj\{objid}.bnd");
+ }
+
+ if (Type == GameType.EldenRing)
+ {
+ // Derive subfolder path from model name (all vanilla AEG are within subfolders)
+ if (objid.Length >= 6)
+ {
+ return GetAssetPath($@"asset\aeg\{objid.Substring(0, 6)}\{objid}.geombnd.dcx");
+ }
+
+ return null;
+ }
+
+ if (Type == GameType.ArmoredCoreVI)
+ {
+ if (objid.Length >= 6)
+ {
+ return GetAssetPath($@"asset\environment\geometry\{objid}.geombnd.dcx");
+ }
+
+ return null;
+ }
+
+ return GetAssetPath($@"obj\{objid}.objbnd.dcx");
+ }
+ }
+ else if (pathElements[i].Equals("parts"))
+ {
+ i++;
+ var partsId = pathElements[i];
+ i++;
+ if (pathElements[i].Equals("model") || pathElements[i].Equals("tex"))
+ {
+ bndpath = "";
+ if (Type == GameType.DarkSoulsPTDE || Type == GameType.DarkSoulsRemastered)
+ {
+ return GetAssetPath($@"parts\{partsId}.partsbnd");
+ }
+
+ if (Type == GameType.DarkSoulsIISOTFS)
+ {
+ var partType = "";
+ switch (partsId.Substring(0, 2))
+ {
+ case "as":
+ partType = "accessories";
+ break;
+ case "am":
+ partType = "arm";
+ break;
+ case "bd":
+ partType = "body";
+ break;
+ case "fa":
+ case "fc":
+ case "fg":
+ partType = "face";
+ break;
+ case "hd":
+ partType = "head";
+ break;
+ case "leg":
+ partType = "leg";
+ break;
+ case "sd":
+ partType = "shield";
+ break;
+ case "wp":
+ partType = "weapon";
+ break;
+ }
+
+ return GetAssetPath($@"model\parts\{partType}\{partsId}.bnd");
+ }
+
+ if (Type == GameType.EldenRing)
+ {
+ return GetAssetPath($@"parts\{partsId}\{partsId}.partsbnd.dcx");
+ }
+
+ if (Type == GameType.ArmoredCoreVI && pathElements[i].Equals("tex"))
+ {
+ string path;
+ if (partsId.Substring(0, 2) == "wp")
+ {
+ string id;
+ if (partsId.EndsWith("_l"))
+ {
+ id = partsId[..^2].Split("_").Last();
+ path = GetAssetPath($@"parts\wp_{id}_l.tpf.dcx");
+ }
+ else
+ {
+ id = partsId.Split("_").Last();
+ path = GetAssetPath($@"parts\wp_{id}.tpf.dcx");
+ }
+ }
+ else
+ {
+ path = GetAssetPath($@"parts\{partsId}_u.tpf.dcx");
+ }
+
+ return path;
+ }
+
+ return GetAssetPath($@"parts\{partsId}.partsbnd.dcx");
+ }
+ }
+
+ bndpath = virtualPath;
+ return null;
+ }
+}
diff --git a/src/StudioCore/Resource/ResourceManager.cs b/src/StudioCore/Resource/ResourceManager.cs
index ac39ebcbd..50efba09c 100644
--- a/src/StudioCore/Resource/ResourceManager.cs
+++ b/src/StudioCore/Resource/ResourceManager.cs
@@ -37,8 +37,6 @@ public enum ResourceType
private static QueuedTaskScheduler JobScheduler = new(4, "JobMaster");
private static readonly TaskFactory JobTaskFactory = new(JobScheduler);
- public static AssetLocator Locator;
-
private static readonly Dictionary ResourceDatabase = new();
private static readonly ConcurrentDictionary ActiveJobProgress = new();
private static readonly HashSet InFlightFiles = new();
@@ -125,7 +123,7 @@ private static void LoadBinderResources(LoadBinderResourcesAction action)
{
Memory f = action.Binder.ReadFile(p.Item3);
p.Item1.LoadByteResourceBlock.Post(new LoadByteResourceRequest(p.Item2, f, action.AccessLevel,
- Locator.Type));
+ Locator.AssetLocator.Type));
action._job.IncrementEstimateTaskSize(1);
i++;
}
@@ -136,7 +134,7 @@ private static void LoadBinderResources(LoadBinderResourcesAction action)
{
TPF f = TPF.Read(action.Binder.ReadFile(t.Item2));
action._job.AddLoadTPFResources(new LoadTPFResourcesAction(action._job, t.Item1, f,
- action.AccessLevel, Locator.Type));
+ action.AccessLevel, Locator.AssetLocator.Type));
}
catch (Exception e)
{
@@ -541,8 +539,8 @@ public void ProcessBinder()
if (Binder == null)
{
string o;
- var path = Locator.VirtualToRealPath(BinderVirtualPath, out o);
- Binder = InstantiateBinderReaderForFile(path, Locator.Type);
+ var path = Locator.AssetLocator.VirtualToRealPath(BinderVirtualPath, out o);
+ Binder = InstantiateBinderReaderForFile(path, Locator.AssetLocator.Type);
if (Binder == null)
{
return;
@@ -558,7 +556,7 @@ public void ProcessBinder()
}
var binderpath = f.Name;
- var filevirtpath = Locator.GetBinderVirtualPath(BinderVirtualPath, binderpath);
+ var filevirtpath = AssetUtils.GetBinderVirtualPath(BinderVirtualPath, binderpath);
if (AssetWhitelist != null && !AssetWhitelist.Contains(filevirtpath))
{
continue;
@@ -812,7 +810,7 @@ public void AddLoadFileTask(string virtualPath, AccessLevel al)
InFlightFiles.Add(virtualPath);
string bndout;
- var path = Locator.VirtualToRealPath(virtualPath, out bndout);
+ var path = Locator.AssetLocator.VirtualToRealPath(virtualPath, out bndout);
IResourceLoadPipeline pipeline;
if (path == null || virtualPath == "null")
@@ -840,7 +838,7 @@ public void AddLoadFileTask(string virtualPath, AccessLevel al)
}
}
- _job.AddLoadTPFResources(new LoadTPFResourcesAction(_job, virt, path, al, Locator.Type));
+ _job.AddLoadTPFResources(new LoadTPFResourcesAction(_job, virt, path, al, Locator.AssetLocator.Type));
return;
}
else
@@ -848,7 +846,7 @@ public void AddLoadFileTask(string virtualPath, AccessLevel al)
pipeline = _job.FlverLoadPipeline;
}
- pipeline.LoadFileResourceRequest.Post(new LoadFileResourceRequest(virtualPath, path, al, Locator.Type));
+ pipeline.LoadFileResourceRequest.Post(new LoadFileResourceRequest(virtualPath, path, al, Locator.AssetLocator.Type));
}
///
@@ -864,14 +862,14 @@ public void AddLoadUDSFMTexturesTask()
string path = null;
if (texpath.StartsWith("map/tex"))
{
- path = $@"{Locator.GameRootDirectory}\map\tx\{Path.GetFileName(texpath)}.tpf";
+ path = $@"{Locator.AssetLocator.GameRootDirectory}\map\tx\{Path.GetFileName(texpath)}.tpf";
}
if (path != null && File.Exists(path))
{
_job.AddLoadTPFResources(new LoadTPFResourcesAction(_job,
Path.GetDirectoryName(r.Key).Replace('\\', '/'),
- path, AccessLevel.AccessGPUOptimizedOnly, Locator.Type));
+ path, AccessLevel.AccessGPUOptimizedOnly, Locator.AssetLocator.Type));
}
}
}
@@ -901,7 +899,7 @@ public void AddLoadUnloadedTextures()
continue;
}
- path = Locator.GetAetTexture(fullaetid).AssetPath;
+ path = Locator.AssetLocator.GetAetTexture(fullaetid).AssetPath;
assetTpfs.Add(fullaetid);
}
@@ -910,7 +908,7 @@ public void AddLoadUnloadedTextures()
{
_job.AddLoadTPFResources(new LoadTPFResourcesAction(_job,
Path.GetDirectoryName(r.Key).Replace('\\', '/'), path,
- AccessLevel.AccessGPUOptimizedOnly, Locator.Type));
+ AccessLevel.AccessGPUOptimizedOnly, Locator.AssetLocator.Type));
}
}
}
diff --git a/src/StudioCore/SettingsMenu.cs b/src/StudioCore/SettingsMenu.cs
index 24e5f085e..faaff4815 100644
--- a/src/StudioCore/SettingsMenu.cs
+++ b/src/StudioCore/SettingsMenu.cs
@@ -196,22 +196,6 @@ private void DisplaySettings_System()
ProjSettings.UseLooseParams = useLoose;
}
}
-
- var usepartial = ProjSettings.PartialParams;
- if ((FeatureFlags.EnablePartialParam || usepartial))
- {
- if (CFG.Current.ShowUITooltips)
- {
- ShowHelpMarker("Partial params.");
- ImGui.SameLine();
- }
-
- if (ProjSettings.GameType == GameType.EldenRing &&
- ImGui.Checkbox("Partial params", ref usepartial))
- {
- ProjSettings.PartialParams = usepartial;
- }
- }
}
}
}
diff --git a/src/StudioCore/SoapstoneService.cs b/src/StudioCore/SoapstoneService.cs
index a9b007db6..659d3842e 100644
--- a/src/StudioCore/SoapstoneService.cs
+++ b/src/StudioCore/SoapstoneService.cs
@@ -45,16 +45,13 @@ public class SoapstoneService : SoapstoneServiceV1
private static readonly Dictionary revMapNamespaces =
mapNamespaces.ToDictionary(e => e.Value, e => e.Key);
-
- private readonly AssetLocator assetLocator;
private readonly MsbEditorScreen msbEditor;
private readonly string version;
- public SoapstoneService(string version, AssetLocator assetLocator, MsbEditorScreen msbEditor)
+ public SoapstoneService(string version, MsbEditorScreen msbEditor)
{
this.version = version;
- this.assetLocator = assetLocator;
this.msbEditor = msbEditor;
}
@@ -65,13 +62,13 @@ public override async Task GetServerInfo(ServerCallContext c
Id = "DSMapStudio", Version = version, ServerPath = Process.GetCurrentProcess().MainModule?.FileName
};
- if (assetLocator.GameModDirectory != null
- && gameMapping.TryGetValue(assetLocator.Type, out FromSoftGame gameType))
+ if (Locator.AssetLocator.GameModDirectory != null
+ && gameMapping.TryGetValue(Locator.AssetLocator.Type, out FromSoftGame gameType))
{
EditorResource projectResource = new()
{
Type = EditorResourceType.Project,
- ProjectJsonPath = Path.Combine(assetLocator.GameModDirectory, "project.json"),
+ ProjectJsonPath = Path.Combine(Locator.AssetLocator.GameModDirectory, "project.json"),
Game = gameType
};
response.Resources.Add(projectResource);
@@ -124,9 +121,9 @@ public override async Task GetServerInfo(ServerCallContext c
private static bool FMGBankLoaded(FromSoftGame game, out SoulsFmg.FmgLanguage lang)
{
lang = default;
- return FMGBank.IsLoaded
- && !string.IsNullOrEmpty(FMGBank.LanguageFolder)
- && SoulsFmg.TryGetFmgLanguageEnum(game, FMGBank.LanguageFolder, out lang);
+ return Locator.ActiveProject.FMGBank.IsLoaded
+ && !string.IsNullOrEmpty(Locator.ActiveProject.FMGBank.LanguageFolder)
+ && SoulsFmg.TryGetFmgLanguageEnum(game, Locator.ActiveProject.FMGBank.LanguageFolder, out lang);
}
private static object AccessParamFile(SoulsKey.GameParamKey p, string key)
@@ -234,11 +231,11 @@ private static object AccessFmgProperty(SoulsKey.FmgKey fmgKey, SoulsFmg.FmgKeyI
private static bool GetFmgKey(
FromSoftGame game,
SoulsFmg.FmgLanguage lang,
- FMGBank.FMGInfo info,
+ FMGInfo info,
out SoulsKey.FmgKey key)
{
- // UICategory is used to distinguish between name-keyed FMGs (DS2) and binder-keyed FMGs (item/menu bnds)
- if (info.UICategory == FmgUICategory.Text)
+ // FileCategory is used to distinguish between name-keyed FMGs (DS2) and binder-keyed FMGs (item/menu bnds)
+ if (info.FileCategory == FmgFileCategory.Loose)
{
if (SoulsFmg.TryGetFmgNameType(game, info.Name, out List types))
{
@@ -271,7 +268,7 @@ public override async Task> GetObjects(
RequestedProperties properties)
{
List results = new();
- if (!gameMapping.TryGetValue(assetLocator.Type, out FromSoftGame game) || resource.Game != game)
+ if (!gameMapping.TryGetValue(Locator.AssetLocator.Type, out FromSoftGame game) || resource.Game != game)
{
return results;
}
@@ -308,9 +305,9 @@ public override async Task> GetObjects(
}
if (resource.Type == EditorResourceType.Fmg
- && FMGBank.IsLoaded
- && !string.IsNullOrEmpty(FMGBank.LanguageFolder)
- && SoulsFmg.TryGetFmgLanguageEnum(game, FMGBank.LanguageFolder, out SoulsFmg.FmgLanguage lang)
+ && Locator.ActiveProject.FMGBank.IsLoaded
+ && !string.IsNullOrEmpty(Locator.ActiveProject.FMGBank.LanguageFolder)
+ && SoulsFmg.TryGetFmgLanguageEnum(game, Locator.ActiveProject.FMGBank.LanguageFolder, out SoulsFmg.FmgLanguage lang)
&& MatchesResource(resource, lang.ToString()))
{
foreach (SoulsKey getKey in keys)
@@ -321,8 +318,8 @@ public override async Task> GetObjects(
continue;
}
- FMGBank.FMGInfo info = FMGBank.FmgInfoBank
- .Find(info =>
+ FMGInfo info = Locator.ActiveProject.FMGBank.FmgInfoBank
+ .FirstOrDefault(info =>
GetFmgKey(game, lang, info, out SoulsKey.FmgKey infoKey) && infoKey.Equals(fileKey));
if (info == null)
{
@@ -397,7 +394,7 @@ public override async Task> SearchObjects(
SearchOptions options)
{
List results = new();
- if (!gameMapping.TryGetValue(assetLocator.Type, out FromSoftGame game) || resource.Game != game)
+ if (!gameMapping.TryGetValue(Locator.AssetLocator.Type, out FromSoftGame game) || resource.Game != game)
{
return results;
}
@@ -457,9 +454,9 @@ bool addResult(SoulsObject obj)
}
if (resource.Type == EditorResourceType.Fmg
- && FMGBank.IsLoaded
- && !string.IsNullOrEmpty(FMGBank.LanguageFolder)
- && SoulsFmg.TryGetFmgLanguageEnum(game, FMGBank.LanguageFolder, out SoulsFmg.FmgLanguage lang)
+ && Locator.ActiveProject.FMGBank.IsLoaded
+ && !string.IsNullOrEmpty(Locator.ActiveProject.FMGBank.LanguageFolder)
+ && SoulsFmg.TryGetFmgLanguageEnum(game, Locator.ActiveProject.FMGBank.LanguageFolder, out SoulsFmg.FmgLanguage lang)
// Language applies to all FMGs at once currently, so filter it here if requested
&& MatchesResource(resource, lang.ToString())
&& search.GetKeyFilter("Language")(lang.ToString()))
@@ -467,7 +464,7 @@ bool addResult(SoulsObject obj)
Predicate
/// List of patched entries if found; empty list otherwise.
- public static List GetFmgEntriesByFmgIDType(FmgIDType fmgID, bool sort = true)
+ public List GetFmgEntriesByFmgIDType(FmgIDType fmgID, bool sort = true)
{
foreach (FMGInfo info in FmgInfoBank)
{
@@ -1055,9 +740,9 @@ private static void ApplyGameDifferences(FMGInfo info)
/// Generate a new EntryGroup using a given ID and FMGInfo.
/// Data is updated using FMGInfo PatchChildren.
///
- public static EntryGroup GenerateEntryGroup(int id, FMGInfo fmgInfo)
+ public FMGEntryGroup GenerateEntryGroup(int id, FMGInfo fmgInfo)
{
- EntryGroup eGroup = new() { ID = id };
+ FMGEntryGroup eGroup = new() { ID = id };
if (fmgInfo.EntryCategory == FmgEntryCategory.None || CFG.Current.FMG_NoGroupedFmgEntries)
{
@@ -1110,224 +795,80 @@ public static EntryGroup GenerateEntryGroup(int id, FMGInfo fmgInfo)
return eGroup;
}
+}
- private static void HandleDuplicateEntries()
- {
- var askedAboutDupes = false;
- var ignoreDupes = true;
- foreach (FMGInfo info in FmgInfoBank)
- {
- IEnumerable dupes = info.Fmg.Entries.GroupBy(e => e.ID).SelectMany(g => g.SkipLast(1));
- if (dupes.Any())
- {
- var dupeList = string.Join(", ", dupes.Select(dupe => dupe.ID));
- if (!askedAboutDupes && PlatformUtils.Instance.MessageBox(
- $"Duplicate text entries have been found in FMG {Path.GetFileNameWithoutExtension(info.FileName)} for the following row IDs:\n\n{dupeList}\n\nRemove all duplicates? (Latest entries are kept)",
- "Duplicate Text Entries", MessageBoxButtons.YesNo) == DialogResult.Yes)
- {
- ignoreDupes = false;
- }
-
- askedAboutDupes = true;
-
- if (!ignoreDupes)
- {
- foreach (FMG.Entry dupe in dupes)
- {
- info.Fmg.Entries.Remove(dupe);
- }
- }
- }
- }
- }
-
- private static string FormatJson(string json)
- {
- json = json.Replace("{\"ID\"", "\r\n{\"ID\"");
- json = json.Replace("],", "\r\n],");
- return json;
- }
-
- private static void SaveFMGsDS2()
+///
+/// Value pair with an entry and the FMG it belongs to.
+///
+public class EntryFMGInfoPair
+{
+ public EntryFMGInfoPair(FMGInfo fmgInfo, FMG.Entry entry)
{
- foreach (FMGInfo info in FmgInfoBank)
- {
- Utils.WriteWithBackup(AssetLocator.GameRootDirectory, AssetLocator.GameModDirectory,
- $@"menu\text\{LanguageFolder}\{info.Name}.fmg", info.Fmg);
- }
+ FmgInfo = fmgInfo;
+ Entry = entry;
}
- public static void SaveFMGs()
- {
- try
- {
- if (!IsLoaded)
- {
- return;
- }
-
- if (AssetLocator.Type == GameType.Undefined)
- {
- return;
- }
-
- if (AssetLocator.Type == GameType.DarkSoulsIISOTFS)
- {
- SaveFMGsDS2();
- TaskLogs.AddLog("Saved FMG text");
- return;
- }
+ public FMGInfo FmgInfo { get; set; }
+ public FMG.Entry Entry { get; set; }
+}
- // Load the fmg bnd, replace fmgs, and save
- IBinder fmgBinderItem;
- IBinder fmgBinderMenu;
- AssetDescription itemMsgPath = AssetLocator.GetItemMsgbnd(LanguageFolder);
- AssetDescription menuMsgPath = AssetLocator.GetMenuMsgbnd(LanguageFolder);
- if (AssetLocator.Type == GameType.DemonsSouls || AssetLocator.Type == GameType.DarkSoulsPTDE ||
- AssetLocator.Type == GameType.DarkSoulsRemastered)
- {
- fmgBinderItem = BND3.Read(itemMsgPath.AssetPath);
- fmgBinderMenu = BND3.Read(menuMsgPath.AssetPath);
- }
- else
- {
- fmgBinderItem = BND4.Read(itemMsgPath.AssetPath);
- fmgBinderMenu = BND4.Read(menuMsgPath.AssetPath);
- }
+///
+/// Base object that stores an FMG and information regarding it.
+///
+public class FMGInfo
+{
+ public FMGFileSet FileSet;
- foreach (BinderFile file in fmgBinderItem.Files)
- {
- FMGInfo info = FmgInfoBank.Find(e => e.FmgID == (FmgIDType)file.ID);
- if (info != null)
- {
- file.Bytes = info.Fmg.Write();
- }
- }
+ public FmgEntryCategory EntryCategory;
+ public FmgEntryTextType EntryType;
+ public string FileName;
+ public FMG Fmg;
+ public FmgIDType FmgID;
+ public string Name;
- foreach (BinderFile file in fmgBinderMenu.Files)
- {
- FMGInfo info = FmgInfoBank.Find(e => e.FmgID == (FmgIDType)file.ID);
- if (info != null)
- {
- file.Bytes = info.Fmg.Write();
- }
- }
+ ///
+ /// List of associated children to this FMGInfo used to get patch entry data.
+ ///
+ public List PatchChildren = new();
- AssetDescription itemMsgPathDest = AssetLocator.GetItemMsgbnd(LanguageFolder, true);
- AssetDescription menuMsgPathDest = AssetLocator.GetMenuMsgbnd(LanguageFolder, true);
- if (fmgBinderItem is BND3 bnd3)
- {
- Utils.WriteWithBackup(AssetLocator.GameRootDirectory,
- AssetLocator.GameModDirectory, itemMsgPathDest.AssetPath, bnd3);
- Utils.WriteWithBackup(AssetLocator.GameRootDirectory,
- AssetLocator.GameModDirectory, menuMsgPathDest.AssetPath, (BND3)fmgBinderMenu);
- if (AssetLocator.Type is GameType.DemonsSouls)
- {
- bnd3.Compression = DCX.Type.None;
- ((BND3)fmgBinderMenu).Compression = DCX.Type.None;
- Utils.WriteWithBackup(AssetLocator.GameRootDirectory,
- AssetLocator.GameModDirectory, itemMsgPathDest.AssetPath[..^4], bnd3);
- Utils.WriteWithBackup(AssetLocator.GameRootDirectory,
- AssetLocator.GameModDirectory, menuMsgPathDest.AssetPath[..^4], (BND3)fmgBinderMenu);
- }
- }
- else if (fmgBinderItem is BND4 bnd4)
- {
- Utils.WriteWithBackup(AssetLocator.GameRootDirectory,
- AssetLocator.GameModDirectory, itemMsgPathDest.AssetPath, bnd4);
- Utils.WriteWithBackup(AssetLocator.GameRootDirectory,
- AssetLocator.GameModDirectory, menuMsgPathDest.AssetPath, (BND4)fmgBinderMenu);
- }
+ public FMGInfo PatchParent;
+ public FmgFileCategory FileCategory;
- fmgBinderItem.Dispose();
- fmgBinderMenu.Dispose();
- TaskLogs.AddLog("Saved FMG text");
- }
- catch (SavingFailedException e)
+ private string _patchPrefix = null;
+ public string PatchPrefix
+ {
+ get
{
- TaskLogs.AddLog(e.Wrapped.Message,
- LogLevel.Error, TaskLogs.LogPriority.High, e.Wrapped);
+ _patchPrefix ??= Name.Replace(FMGBank.RemovePatchStrings(Name), "");
+ return _patchPrefix;
}
}
- public static void SetAssetLocator(AssetLocator l)
+ public void AddParent(FMGInfo parent)
{
- AssetLocator = l;
+ PatchParent = parent;
+ parent.PatchChildren.Add(this);
}
///
- /// Value pair with an entry and the FMG it belongs to.
+ /// Returns a patched list of Entry & FMGInfo value pairs from this FMGInfo and its children.
+ /// If a PatchParent exists, it will be checked instead.
///
- public class EntryFMGInfoPair
+ public List GetPatchedEntryFMGPairs(bool sort = true)
{
- public EntryFMGInfoPair(FMGInfo fmgInfo, FMG.Entry entry)
+ if (PatchParent != null && !CFG.Current.FMG_NoFmgPatching)
{
- FmgInfo = fmgInfo;
- Entry = entry;
+ return PatchParent.GetPatchedEntryFMGPairs(sort);
}
- public FMGInfo FmgInfo { get; set; }
- public FMG.Entry Entry { get; set; }
- }
-
- ///
- /// Base object that stores an FMG and information regarding it.
- ///
- public class FMGInfo
- {
- public FmgEntryCategory EntryCategory;
- public FmgEntryTextType EntryType;
- public string FileName;
- public FMG Fmg;
- public FmgIDType FmgID;
- public string Name;
-
- ///
- /// List of associated children to this FMGInfo used to get patch entry data.
- ///
- public List PatchChildren = new();
-
- public FMGInfo PatchParent;
- public FmgUICategory UICategory;
-
- private string _patchPrefix = null;
- public string PatchPrefix
+ List list = new();
+ foreach (FMG.Entry entry in Fmg.Entries)
{
- get
- {
- _patchPrefix ??= Name.Replace(RemovePatchStrings(Name), "");
- return _patchPrefix;
- }
+ list.Add(new EntryFMGInfoPair(this, entry));
}
- public void AddParent(FMGInfo parent)
- {
- if (CFG.Current.FMG_NoFmgPatching)
- {
- return;
- }
-
- PatchParent = parent;
- parent.PatchChildren.Add(this);
- }
-
- ///
- /// Returns a patched list of Entry & FMGInfo value pairs from this FMGInfo and its children.
- /// If a PatchParent exists, it will be checked instead.
- ///
- public List GetPatchedEntryFMGPairs(bool sort = true)
+ if (!CFG.Current.FMG_NoFmgPatching)
{
- if (PatchParent != null)
- {
- return PatchParent.GetPatchedEntryFMGPairs(sort);
- }
-
- List list = new();
- foreach (FMG.Entry entry in Fmg.Entries)
- {
- list.Add(new EntryFMGInfoPair(this, entry));
- }
-
// Check and apply patch entries
foreach (FMGInfo child in PatchChildren.OrderBy(e => (int)e.FmgID))
{
@@ -1350,29 +891,32 @@ public List GetPatchedEntryFMGPairs(bool sort = true)
}
}
}
+ }
- if (sort)
- {
- list = list.OrderBy(e => e.Entry.ID).ToList();
- }
-
- return list;
+ if (sort)
+ {
+ list = list.OrderBy(e => e.Entry.ID).ToList();
}
- ///
- /// Returns a patched list of entries in this FMGInfo and its children.
- /// If a PatchParent exists, it will be checked instead.
- ///
- public List GetPatchedEntries(bool sort = true)
+ return list;
+ }
+
+ ///
+ /// Returns a patched list of entries in this FMGInfo and its children.
+ /// If a PatchParent exists, it will be checked instead.
+ ///
+ public List GetPatchedEntries(bool sort = true)
+ {
+ if (PatchParent != null && !CFG.Current.FMG_NoFmgPatching)
{
- if (PatchParent != null)
- {
- return PatchParent.GetPatchedEntries(sort);
- }
+ return PatchParent.GetPatchedEntries(sort);
+ }
- List list = new();
- list.AddRange(Fmg.Entries);
+ List list = new();
+ list.AddRange(Fmg.Entries);
+ if (!CFG.Current.FMG_NoFmgPatching)
+ {
// Check and apply patch entries
foreach (FMGInfo child in PatchChildren.OrderBy(e => (int)e.FmgID))
{
@@ -1395,314 +939,313 @@ public List GetPatchedEntryFMGPairs(bool sort = true)
}
}
}
-
- if (sort)
- {
- list = list.OrderBy(e => e.ID).ToList();
- }
-
- return list;
- }
-
- ///
- /// Returns title FMGInfo that shares this FMGInfo's EntryCategory.
- /// If none are found, an exception will be thrown.
- ///
- public FMGInfo GetTitleFmgInfo()
- {
- foreach (var info in FMGBank.FmgInfoBank)
- {
- if (info.EntryCategory == EntryCategory && info.EntryType == FmgEntryTextType.Title && info.PatchPrefix == PatchPrefix)
- {
- return info;
- }
- }
- throw new InvalidOperationException($"Couldn't find title FMGInfo for {this.Name}");
}
- ///
- /// Adds an entry to the end of the FMG.
- ///
- public void AddEntry(FMG.Entry entry)
+ if (sort)
{
- Fmg.Entries.Add(entry);
+ list = list.OrderBy(e => e.ID).ToList();
}
- ///
- /// Clones an FMG entry.
- ///
- /// Cloned entry
- public FMG.Entry CloneEntry(FMG.Entry entry)
- {
- FMG.Entry newEntry = new(entry.ID, entry.Text);
- return newEntry;
- }
-
- ///
- /// Removes an entry from FMGInfo's FMG.
- ///
- public void DeleteEntry(FMG.Entry entry)
- {
- Fmg.Entries.Remove(entry);
- }
+ return list;
}
-
///
- /// A group of entries that may be associated (such as title, summary, description) along with respective FMGs.
+ /// Returns title FMGInfo that shares this FMGInfo's EntryCategory.
+ /// If none are found, an exception will be thrown.
///
- public class EntryGroup
+ public FMGInfo GetTitleFmgInfo()
{
- private int _ID = -1;
- public FMG.Entry Description;
- public FMGInfo DescriptionInfo;
- public FMG.Entry ExtraText;
- public FMGInfo ExtraTextInfo;
- public FMG.Entry Summary;
- public FMGInfo SummaryInfo;
- public FMG.Entry TextBody;
- public FMGInfo TextBodyInfo;
- public FMG.Entry Title;
- public FMGInfo TitleInfo;
-
- public int ID
- {
- set
+ foreach (var info in FileSet.FmgInfos)
+ {
+ if (info.EntryCategory == EntryCategory && info.EntryType == FmgEntryTextType.Title && info.PatchPrefix == PatchPrefix)
{
- _ID = value;
- if (TextBody != null)
- {
- TextBody.ID = _ID;
- }
-
- if (Title != null)
- {
- Title.ID = _ID;
- }
-
- if (Summary != null)
- {
- Summary.ID = _ID;
- }
-
- if (Description != null)
- {
- Description.ID = _ID;
- }
-
- if (ExtraText != null)
- {
- ExtraText.ID = _ID;
- }
+ return info;
}
- get => _ID;
}
+ throw new InvalidOperationException($"Couldn't find title FMGInfo for {this.Name}");
+ }
- ///
- /// Gets next unused entry ID.
- ///
- public int GetNextUnusedID()
- {
- var id = ID;
- if (TextBody != null)
- {
- List entries = TextBodyInfo.GetPatchedEntries();
- do
- {
- id++;
- } while (entries.Find(e => e.ID == id) != null);
- }
- else if (Title != null)
- {
- List entries = TitleInfo.GetPatchedEntries();
- do
- {
- id++;
- } while (entries.Find(e => e.ID == id) != null);
- }
- else if (Summary != null)
- {
- List entries = SummaryInfo.GetPatchedEntries();
- do
- {
- id++;
- } while (entries.Find(e => e.ID == id) != null);
- }
- else if (Description != null)
- {
- List entries = DescriptionInfo.GetPatchedEntries();
- do
- {
- id++;
- } while (entries.Find(e => e.ID == id) != null);
- }
- else if (ExtraText != null)
- {
- List entries = ExtraTextInfo.GetPatchedEntries();
- do
- {
- id++;
- } while (entries.Find(e => e.ID == id) != null);
- }
+ ///
+ /// Adds an entry to the end of the FMG.
+ ///
+ public void AddEntry(FMG.Entry entry)
+ {
+ Fmg.Entries.Add(entry);
+ }
- return id;
- }
+ ///
+ /// Clones an FMG entry.
+ ///
+ /// Cloned entry
+ public FMG.Entry CloneEntry(FMG.Entry entry)
+ {
+ FMG.Entry newEntry = new(entry.ID, entry.Text);
+ return newEntry;
+ }
- ///
- /// Sets ID of all entries to the next unused entry ID.
- ///
- public void SetNextUnusedID()
- {
- ID = GetNextUnusedID();
- }
+ ///
+ /// Removes an entry from FMGInfo's FMG.
+ ///
+ public void DeleteEntry(FMG.Entry entry)
+ {
+ Fmg.Entries.Remove(entry);
+ }
+}
- ///
- /// Places all entries within this EntryGroup into their assigned FMGs.
- ///
- public void ImplementEntryGroup()
+///
+/// A group of entries that may be associated (such as title, summary, description) along with respective FMGs.
+///
+public class FMGEntryGroup
+{
+ private int _ID = -1;
+ public FMG.Entry Description;
+ public FMGInfo DescriptionInfo;
+ public FMG.Entry ExtraText;
+ public FMGInfo ExtraTextInfo;
+ public FMG.Entry Summary;
+ public FMGInfo SummaryInfo;
+ public FMG.Entry TextBody;
+ public FMGInfo TextBodyInfo;
+ public FMG.Entry Title;
+ public FMGInfo TitleInfo;
+
+ public int ID
+ {
+ set
{
+ _ID = value;
if (TextBody != null)
{
- TextBodyInfo.AddEntry(TextBody);
+ TextBody.ID = _ID;
}
if (Title != null)
{
- TitleInfo.AddEntry(Title);
+ Title.ID = _ID;
}
if (Summary != null)
{
- SummaryInfo.AddEntry(Summary);
+ Summary.ID = _ID;
}
if (Description != null)
{
- DescriptionInfo.AddEntry(Description);
+ Description.ID = _ID;
}
if (ExtraText != null)
{
- ExtraTextInfo.AddEntry(ExtraText);
+ ExtraText.ID = _ID;
}
}
+ get => _ID;
+ }
- ///
- /// Duplicates all entries within their assigned FMGs.
- /// New entries are inserted into their assigned FMGs.
- ///
- /// New EntryGroup.
- public EntryGroup DuplicateFMGEntries()
+ ///
+ /// Gets next unused entry ID.
+ ///
+ public int GetNextUnusedID()
+ {
+ var id = ID;
+ if (TextBody != null)
{
- EntryGroup newGroup = new();
- if (TextBody != null)
+ List entries = TextBodyInfo.GetPatchedEntries();
+ do
{
- newGroup.TextBodyInfo = TextBodyInfo;
- newGroup.TextBody = TextBodyInfo.CloneEntry(TextBody);
- TextBodyInfo.AddEntry(newGroup.TextBody);
- }
-
- if (Title != null)
+ id++;
+ } while (entries.Find(e => e.ID == id) != null);
+ }
+ else if (Title != null)
+ {
+ List entries = TitleInfo.GetPatchedEntries();
+ do
{
- newGroup.TitleInfo = TitleInfo;
- newGroup.Title = TitleInfo.CloneEntry(Title);
- TitleInfo.AddEntry(newGroup.Title);
- }
-
- if (Summary != null)
+ id++;
+ } while (entries.Find(e => e.ID == id) != null);
+ }
+ else if (Summary != null)
+ {
+ List entries = SummaryInfo.GetPatchedEntries();
+ do
{
- newGroup.SummaryInfo = SummaryInfo;
- newGroup.Summary = SummaryInfo.CloneEntry(Summary);
- SummaryInfo.AddEntry(newGroup.Summary);
- }
-
- if (Description != null)
+ id++;
+ } while (entries.Find(e => e.ID == id) != null);
+ }
+ else if (Description != null)
+ {
+ List entries = DescriptionInfo.GetPatchedEntries();
+ do
{
- newGroup.DescriptionInfo = DescriptionInfo;
- newGroup.Description = DescriptionInfo.CloneEntry(Description);
- DescriptionInfo.AddEntry(newGroup.Description);
- }
-
- if (ExtraText != null)
+ id++;
+ } while (entries.Find(e => e.ID == id) != null);
+ }
+ else if (ExtraText != null)
+ {
+ List entries = ExtraTextInfo.GetPatchedEntries();
+ do
{
- newGroup.ExtraTextInfo = ExtraTextInfo;
- newGroup.ExtraText = ExtraTextInfo.CloneEntry(ExtraText);
- ExtraTextInfo.AddEntry(newGroup.ExtraText);
- }
+ id++;
+ } while (entries.Find(e => e.ID == id) != null);
+ }
+
+ return id;
+ }
- newGroup.ID = ID;
- return newGroup;
+ ///
+ /// Sets ID of all entries to the next unused entry ID.
+ ///
+ public void SetNextUnusedID()
+ {
+ ID = GetNextUnusedID();
+ }
+
+ ///
+ /// Places all entries within this EntryGroup into their assigned FMGs.
+ ///
+ public void ImplementEntryGroup()
+ {
+ if (TextBody != null)
+ {
+ TextBodyInfo.AddEntry(TextBody);
}
- ///
- /// Clones this EntryGroup and returns a duplicate.
- ///
- /// Cloned EntryGroup.
- public EntryGroup CloneEntryGroup()
+ if (Title != null)
{
- EntryGroup newGroup = new();
- if (TextBody != null)
- {
- newGroup.TextBodyInfo = TextBodyInfo;
- newGroup.TextBody = TextBodyInfo.CloneEntry(TextBody);
- }
+ TitleInfo.AddEntry(Title);
+ }
- if (Title != null)
- {
- newGroup.TitleInfo = TitleInfo;
- newGroup.Title = TitleInfo.CloneEntry(Title);
- }
+ if (Summary != null)
+ {
+ SummaryInfo.AddEntry(Summary);
+ }
- if (Summary != null)
- {
- newGroup.SummaryInfo = SummaryInfo;
- newGroup.Summary = SummaryInfo.CloneEntry(Summary);
- }
+ if (Description != null)
+ {
+ DescriptionInfo.AddEntry(Description);
+ }
- if (Description != null)
- {
- newGroup.DescriptionInfo = DescriptionInfo;
- newGroup.Description = DescriptionInfo.CloneEntry(Description);
- }
+ if (ExtraText != null)
+ {
+ ExtraTextInfo.AddEntry(ExtraText);
+ }
+ }
- if (ExtraText != null)
- {
- newGroup.ExtraTextInfo = ExtraTextInfo;
- newGroup.ExtraText = ExtraTextInfo.CloneEntry(ExtraText);
- }
+ ///
+ /// Duplicates all entries within their assigned FMGs.
+ /// New entries are inserted into their assigned FMGs.
+ ///
+ /// New EntryGroup.
+ public FMGEntryGroup DuplicateFMGEntries()
+ {
+ FMGEntryGroup newGroup = new();
+ if (TextBody != null)
+ {
+ newGroup.TextBodyInfo = TextBodyInfo;
+ newGroup.TextBody = TextBodyInfo.CloneEntry(TextBody);
+ TextBodyInfo.AddEntry(newGroup.TextBody);
+ }
- return newGroup;
+ if (Title != null)
+ {
+ newGroup.TitleInfo = TitleInfo;
+ newGroup.Title = TitleInfo.CloneEntry(Title);
+ TitleInfo.AddEntry(newGroup.Title);
}
- ///
- /// Removes all entries from their assigned FMGs.
- ///
- public void DeleteEntries()
+ if (Summary != null)
{
- if (TextBody != null)
- {
- TextBodyInfo.DeleteEntry(TextBody);
- }
+ newGroup.SummaryInfo = SummaryInfo;
+ newGroup.Summary = SummaryInfo.CloneEntry(Summary);
+ SummaryInfo.AddEntry(newGroup.Summary);
+ }
- if (Title != null)
- {
- TitleInfo.DeleteEntry(Title);
- }
+ if (Description != null)
+ {
+ newGroup.DescriptionInfo = DescriptionInfo;
+ newGroup.Description = DescriptionInfo.CloneEntry(Description);
+ DescriptionInfo.AddEntry(newGroup.Description);
+ }
- if (Summary != null)
- {
- SummaryInfo.DeleteEntry(Summary);
- }
+ if (ExtraText != null)
+ {
+ newGroup.ExtraTextInfo = ExtraTextInfo;
+ newGroup.ExtraText = ExtraTextInfo.CloneEntry(ExtraText);
+ ExtraTextInfo.AddEntry(newGroup.ExtraText);
+ }
- if (Description != null)
- {
- DescriptionInfo.DeleteEntry(Description);
- }
+ newGroup.ID = ID;
+ return newGroup;
+ }
- if (ExtraText != null)
- {
- ExtraTextInfo.DeleteEntry(ExtraText);
- }
+ ///
+ /// Clones this EntryGroup and returns a duplicate.
+ ///
+ /// Cloned EntryGroup.
+ public FMGEntryGroup CloneEntryGroup()
+ {
+ FMGEntryGroup newGroup = new();
+ if (TextBody != null)
+ {
+ newGroup.TextBodyInfo = TextBodyInfo;
+ newGroup.TextBody = TextBodyInfo.CloneEntry(TextBody);
+ }
+
+ if (Title != null)
+ {
+ newGroup.TitleInfo = TitleInfo;
+ newGroup.Title = TitleInfo.CloneEntry(Title);
+ }
+
+ if (Summary != null)
+ {
+ newGroup.SummaryInfo = SummaryInfo;
+ newGroup.Summary = SummaryInfo.CloneEntry(Summary);
+ }
+
+ if (Description != null)
+ {
+ newGroup.DescriptionInfo = DescriptionInfo;
+ newGroup.Description = DescriptionInfo.CloneEntry(Description);
+ }
+
+ if (ExtraText != null)
+ {
+ newGroup.ExtraTextInfo = ExtraTextInfo;
+ newGroup.ExtraText = ExtraTextInfo.CloneEntry(ExtraText);
+ }
+
+ return newGroup;
+ }
+
+ ///
+ /// Removes all entries from their assigned FMGs.
+ ///
+ public void DeleteEntries()
+ {
+ if (TextBody != null)
+ {
+ TextBodyInfo.DeleteEntry(TextBody);
+ }
+
+ if (Title != null)
+ {
+ TitleInfo.DeleteEntry(Title);
+ }
+
+ if (Summary != null)
+ {
+ SummaryInfo.DeleteEntry(Summary);
+ }
+
+ if (Description != null)
+ {
+ DescriptionInfo.DeleteEntry(Description);
+ }
+
+ if (ExtraText != null)
+ {
+ ExtraTextInfo.DeleteEntry(ExtraText);
}
}
}
diff --git a/src/StudioCore/TextEditor/FMGEditor.cs b/src/StudioCore/TextEditor/FMGEditor.cs
index fb1eff176..4eb7a7ed5 100644
--- a/src/StudioCore/TextEditor/FMGEditor.cs
+++ b/src/StudioCore/TextEditor/FMGEditor.cs
@@ -10,7 +10,7 @@ namespace StudioCore.TextEditor;
public class PropertyEditor
{
- private FMGBank.EntryGroup _eGroupCache;
+ private FMGEntryGroup _eGroupCache;
private FMG.Entry _entryCache;
private int _fmgID;
@@ -265,7 +265,7 @@ public unsafe void PropEditorFMG(FMG.Entry entry, string name)
_fmgID++;
}
- public void PropIDFMG(FMGBank.EntryGroup eGroup, List entryCache)
+ public void PropIDFMG(FMGEntryGroup eGroup, List entryCache)
{
var oldID = eGroup.ID;
var id = oldID;
diff --git a/src/StudioCore/TextEditor/FMGEnums.cs b/src/StudioCore/TextEditor/FMGEnums.cs
new file mode 100644
index 000000000..9c122bc62
--- /dev/null
+++ b/src/StudioCore/TextEditor/FMGEnums.cs
@@ -0,0 +1,517 @@
+namespace StudioCore.TextEditor;
+
+///
+/// FMG sections in UI
+///
+public enum FmgFileCategory
+{
+ Loose = 0,
+ Item = 1,
+ Menu = 2
+}
+
+///
+/// Entry type for Title, Summary, Description, or other.
+///
+public enum FmgEntryTextType
+{
+ TextBody = 0,
+ Title = 1,
+ Summary = 2,
+ Description = 3,
+ ExtraText = 4
+}
+
+///
+/// Text categories used for grouping multiple FMGs or broad identification
+///
+public enum FmgEntryCategory
+{
+ None = -1,
+ Goods,
+ Weapons,
+ Armor,
+ Rings,
+ Spells,
+ Characters,
+ Locations,
+ Gem,
+ Message,
+ SwordArts,
+ Effect,
+ ActionButtonText,
+ Tutorial,
+ LoadingScreen,
+ Generator,
+ Booster,
+ FCS,
+ Mission,
+ Archive,
+
+ ItemFmgDummy = 200 // Anything with this will be sorted into the item section of the editor.
+}
+
+///
+/// BND IDs for FMG files used for identification
+///
+public enum FmgIDType
+{
+ // Note: Matching names with _DLC and _PATCH are used as identifiers for patch FMGs. This is a little dumb and patch fmg handling should probably be redone.
+ None = -1,
+
+ TitleGoods = 10,
+ TitleWeapons = 11,
+ TitleArmor = 12,
+ TitleRings = 13,
+ TitleSpells = 14,
+ TitleTest = 15,
+ TitleTest2 = 16,
+ TitleTest3 = 17,
+ TitleCharacters = 18,
+ TitleLocations = 19,
+ SummaryGoods = 20,
+ SummaryWeapons = 21,
+ SummaryArmor = 22,
+ SummaryRings = 23,
+ DescriptionGoods = 24,
+ DescriptionWeapons = 25,
+ DescriptionArmor = 26,
+ DescriptionRings = 27,
+ SummarySpells = 28,
+ DescriptionSpells = 29,
+
+ //
+ TalkMsg = 1,
+ BloodMsg = 2,
+ MovieSubtitle = 3,
+ Event = 30,
+ MenuInGame = 70,
+ MenuCommon = 76,
+ MenuOther = 77,
+ MenuDialog = 78,
+ MenuKeyGuide = 79,
+ MenuLineHelp = 80,
+ MenuContext = 81,
+ MenuTags = 90,
+ Win32Tags = 91,
+ Win32Messages = 92,
+ Event_Patch = 101,
+ MenuDialog_Patch = 102,
+ Win32Messages_Patch = 103,
+ TalkMsg_Patch = 104,
+ BloodMsg_Patch = 107,
+ MenuLineHelp_Patch = 121,
+ MenuKeyGuide_Patch = 122,
+ MenuOther_Patch = 123,
+ MenuCommon_Patch = 124,
+
+ // DS1 _DLC
+ DescriptionGoods_Patch = 100,
+ DescriptionSpells_Patch = 105,
+ DescriptionWeapons_Patch = 106,
+ DescriptionArmor_Patch = 108,
+ DescriptionRings_Patch = 109,
+ SummaryGoods_Patch = 110,
+ TitleGoods_Patch = 111,
+ SummaryRings_Patch = 112,
+ TitleRings_Patch = 113,
+ SummaryWeapons_Patch = 114,
+ TitleWeapons_Patch = 115,
+ SummaryArmor_Patch = 116,
+ TitleArmor_Patch = 117,
+ TitleSpells_Patch = 118,
+ TitleCharacters_Patch = 119,
+ TitleLocations_Patch = 120,
+
+ // DS3 _DLC1
+ TitleWeapons_DLC1 = 211,
+ TitleArmor_DLC1 = 212,
+ TitleRings_DLC1 = 213,
+ TitleSpells_DLC1 = 214,
+ TitleCharacters_DLC1 = 215,
+ TitleLocations_DLC1 = 216,
+ SummaryGoods_DLC1 = 217,
+ SummaryRings_DLC1 = 220,
+ DescriptionGoods_DLC1 = 221,
+ DescriptionWeapons_DLC1 = 222,
+ DescriptionArmor_DLC1 = 223,
+ DescriptionRings_DLC1 = 224,
+ SummarySpells_DLC1 = 225,
+ DescriptionSpells_DLC1 = 226,
+
+ //
+ Modern_MenuText = 200,
+ Modern_LineHelp = 201,
+ Modern_KeyGuide = 202,
+ Modern_SystemMessage_win64 = 203,
+ Modern_Dialogues = 204,
+ TalkMsg_DLC1 = 230,
+ Event_DLC1 = 231,
+ Modern_MenuText_DLC1 = 232,
+ Modern_LineHelp_DLC1 = 233,
+ Modern_SystemMessage_win64_DLC1 = 235,
+ Modern_Dialogues_DLC1 = 236,
+ SystemMessage_PS4_DLC1 = 237,
+ SystemMessage_XboxOne_DLC1 = 238,
+ BloodMsg_DLC1 = 239,
+
+ // DS3 _DLC2
+ TitleGoods_DLC2 = 250,
+ TitleWeapons_DLC2 = 251,
+ TitleArmor_DLC2 = 252,
+ TitleRings_DLC2 = 253,
+ TitleSpells_DLC2 = 254,
+ TitleCharacters_DLC2 = 255,
+ TitleLocations_DLC2 = 256,
+ SummaryGoods_DLC2 = 257,
+ SummaryRings_DLC2 = 260,
+ DescriptionGoods_DLC2 = 261,
+ DescriptionWeapons_DLC2 = 262,
+ DescriptionArmor_DLC2 = 263,
+ DescriptionRings_DLC2 = 264,
+ SummarySpells_DLC2 = 265,
+ DescriptionSpells_DLC2 = 266,
+
+ //
+ TalkMsg_DLC2 = 270,
+ Event_DLC2 = 271,
+ Modern_MenuText_DLC2 = 272,
+ Modern_LineHelp_DLC2 = 273,
+ Modern_SystemMessage_win64_DLC2 = 275,
+ Modern_Dialogues_DLC2 = 276,
+ SystemMessage_PS4_DLC2 = 277,
+ SystemMessage_XboxOne_DLC2 = 278,
+ BloodMsg_DLC2 = 279,
+
+ // SDT
+ Skills = 40,
+
+ // ER
+ DescriptionGem = 37,
+ SummarySwordArts = 43,
+ WeaponEffect = 44,
+ ERUnk45 = 45,
+ GoodsInfo2 = 46,
+
+ //
+ TalkMsg_FemalePC_Alt = 4,
+ NetworkMessage = 31,
+ EventTextForTalk = 33,
+ EventTextForMap = 34,
+ TutorialTitle = 207,
+ TutorialBody = 208,
+ TextEmbedImageName_win64 = 209,
+
+ // AC6
+ TitleBooster = 38,
+ DescriptionBooster = 39,
+
+ //
+ RankerProfile = 50,
+ TitleMission = 60,
+ SummaryMission = 61,
+ DescriptionMission = 62,
+ MissionLocation = 63,
+ TitleArchive = 65,
+ DescriptionArchive = 66,
+ TutorialTitle2023 = 73,
+ TutorialBody2023 = 74,
+
+ // Multiple use cases. Differences are applied in ApplyGameDifferences();
+ ReusedFMG_32 = 32,
+
+ // FMG 32
+ // BB: GemExtraInfo
+ // DS3: ActionButtonText
+ // SDT: ActionButtonText
+ // ER: ActionButtonText
+ ReusedFMG_35 = 35,
+
+ // FMG 35
+ // Most: TitleGem
+ // AC6: TitleGenerator
+ ReusedFMG_36 = 36,
+
+ // FMG 36
+ // Most: SummaryGem
+ // AC6: DescriptionGenerator
+ ReusedFMG_41 = 41,
+
+ // FMG 41
+ // Most: TitleMessage
+ // AC6: TitleFCS
+ ReusedFMG_42 = 42,
+
+ // FMG 42
+ // Most: TitleSwordArts
+ // AC6: DescriptionFCS
+ ReusedFMG_210 = 210,
+
+ // FMG 210
+ // DS3: TitleGoods_DLC1
+ // SDT: ?
+ // ER: ToS_win64
+ // AC6: TextEmbeddedImageNames
+ ReusedFMG_205 = 205,
+
+ // FMG 205
+ // DS3: SystemMessage_PS4
+ // SDT: TutorialText
+ // ER: LoadingTitle
+ // AC6: MenuContext
+ ReusedFMG_206 = 206
+ // FMG 206
+ // DS3: SystemMessage_XboxOne
+ // SDT: TutorialTitle
+ // ER: LoadingText
+}
+
+public static class FMGEnums
+{
+ ///
+ /// Get category for grouped entries (Goods, Weapons, etc)
+ ///
+ public static FmgEntryCategory GetFmgCategory(int id)
+ {
+ switch ((FmgIDType)id)
+ {
+ case FmgIDType.TitleTest:
+ case FmgIDType.TitleTest2:
+ case FmgIDType.TitleTest3:
+ case FmgIDType.ERUnk45:
+ return FmgEntryCategory.None;
+
+ case FmgIDType.DescriptionGoods:
+ case FmgIDType.DescriptionGoods_Patch:
+ case FmgIDType.DescriptionGoods_DLC1:
+ case FmgIDType.DescriptionGoods_DLC2:
+ case FmgIDType.SummaryGoods:
+ case FmgIDType.SummaryGoods_Patch:
+ case FmgIDType.SummaryGoods_DLC1:
+ case FmgIDType.SummaryGoods_DLC2:
+ case FmgIDType.TitleGoods:
+ case FmgIDType.TitleGoods_Patch:
+ case FmgIDType.TitleGoods_DLC2:
+ case FmgIDType.GoodsInfo2:
+ return FmgEntryCategory.Goods;
+
+ case FmgIDType.DescriptionWeapons:
+ case FmgIDType.DescriptionWeapons_DLC1:
+ case FmgIDType.DescriptionWeapons_DLC2:
+ case FmgIDType.SummaryWeapons:
+ case FmgIDType.TitleWeapons:
+ case FmgIDType.TitleWeapons_DLC1:
+ case FmgIDType.TitleWeapons_DLC2:
+ case FmgIDType.DescriptionWeapons_Patch:
+ case FmgIDType.SummaryWeapons_Patch:
+ case FmgIDType.TitleWeapons_Patch:
+ return FmgEntryCategory.Weapons;
+
+ case FmgIDType.DescriptionArmor:
+ case FmgIDType.DescriptionArmor_DLC1:
+ case FmgIDType.DescriptionArmor_DLC2:
+ case FmgIDType.SummaryArmor:
+ case FmgIDType.TitleArmor:
+ case FmgIDType.TitleArmor_DLC1:
+ case FmgIDType.TitleArmor_DLC2:
+ case FmgIDType.DescriptionArmor_Patch:
+ case FmgIDType.SummaryArmor_Patch:
+ case FmgIDType.TitleArmor_Patch:
+ return FmgEntryCategory.Armor;
+
+ case FmgIDType.DescriptionRings:
+ case FmgIDType.DescriptionRings_DLC1:
+ case FmgIDType.DescriptionRings_DLC2:
+ case FmgIDType.SummaryRings:
+ case FmgIDType.SummaryRings_DLC1:
+ case FmgIDType.SummaryRings_DLC2:
+ case FmgIDType.TitleRings:
+ case FmgIDType.TitleRings_DLC1:
+ case FmgIDType.TitleRings_DLC2:
+ case FmgIDType.DescriptionRings_Patch:
+ case FmgIDType.SummaryRings_Patch:
+ case FmgIDType.TitleRings_Patch:
+ return FmgEntryCategory.Rings;
+
+ case FmgIDType.DescriptionSpells:
+ case FmgIDType.DescriptionSpells_DLC1:
+ case FmgIDType.DescriptionSpells_DLC2:
+ case FmgIDType.SummarySpells:
+ case FmgIDType.SummarySpells_DLC1:
+ case FmgIDType.SummarySpells_DLC2:
+ case FmgIDType.TitleSpells:
+ case FmgIDType.TitleSpells_DLC1:
+ case FmgIDType.TitleSpells_DLC2:
+ case FmgIDType.DescriptionSpells_Patch:
+ case FmgIDType.TitleSpells_Patch:
+ return FmgEntryCategory.Spells;
+
+ case FmgIDType.TitleCharacters:
+ case FmgIDType.TitleCharacters_DLC1:
+ case FmgIDType.TitleCharacters_DLC2:
+ case FmgIDType.TitleCharacters_Patch:
+ return FmgEntryCategory.Characters;
+
+ case FmgIDType.TitleLocations:
+ case FmgIDType.TitleLocations_DLC1:
+ case FmgIDType.TitleLocations_DLC2:
+ case FmgIDType.TitleLocations_Patch:
+ return FmgEntryCategory.Locations;
+
+ case FmgIDType.DescriptionGem:
+ return FmgEntryCategory.Gem;
+
+ case FmgIDType.SummarySwordArts:
+ return FmgEntryCategory.SwordArts;
+
+ case FmgIDType.TutorialTitle:
+ case FmgIDType.TutorialBody:
+ case FmgIDType.TutorialTitle2023:
+ case FmgIDType.TutorialBody2023:
+ return FmgEntryCategory.Tutorial;
+
+ case FmgIDType.WeaponEffect:
+ return FmgEntryCategory.ItemFmgDummy;
+
+ case FmgIDType.TitleMission:
+ case FmgIDType.SummaryMission:
+ case FmgIDType.DescriptionMission:
+ case FmgIDType.MissionLocation:
+ return FmgEntryCategory.Mission;
+
+ case FmgIDType.TitleBooster:
+ case FmgIDType.DescriptionBooster:
+ return FmgEntryCategory.Booster;
+
+ case FmgIDType.TitleArchive:
+ case FmgIDType.DescriptionArchive:
+ return FmgEntryCategory.Archive;
+
+ default:
+ return FmgEntryCategory.None;
+ }
+ }
+
+ ///
+ /// Get entry text type (such as weapon Title, Summary, Description)
+ ///
+ public static FmgEntryTextType GetFmgTextType(int id)
+ {
+ switch ((FmgIDType)id)
+ {
+ case FmgIDType.DescriptionGoods:
+ case FmgIDType.DescriptionGoods_DLC1:
+ case FmgIDType.DescriptionGoods_DLC2:
+ case FmgIDType.DescriptionWeapons:
+ case FmgIDType.DescriptionWeapons_DLC1:
+ case FmgIDType.DescriptionWeapons_DLC2:
+ case FmgIDType.DescriptionArmor:
+ case FmgIDType.DescriptionArmor_DLC1:
+ case FmgIDType.DescriptionArmor_DLC2:
+ case FmgIDType.DescriptionRings:
+ case FmgIDType.DescriptionRings_DLC1:
+ case FmgIDType.DescriptionRings_DLC2:
+ case FmgIDType.DescriptionSpells:
+ case FmgIDType.DescriptionSpells_DLC1:
+ case FmgIDType.DescriptionSpells_DLC2:
+ case FmgIDType.DescriptionArmor_Patch:
+ case FmgIDType.DescriptionGoods_Patch:
+ case FmgIDType.DescriptionRings_Patch:
+ case FmgIDType.DescriptionSpells_Patch:
+ case FmgIDType.DescriptionWeapons_Patch:
+ case FmgIDType.DescriptionGem:
+ case FmgIDType.SummarySwordArts: // Include as Description (for text box size)
+ case FmgIDType.DescriptionBooster:
+ case FmgIDType.DescriptionMission:
+ case FmgIDType.DescriptionArchive:
+ return FmgEntryTextType.Description;
+
+ case FmgIDType.SummaryGoods:
+ case FmgIDType.SummaryGoods_DLC1:
+ case FmgIDType.SummaryGoods_DLC2:
+ case FmgIDType.SummaryWeapons:
+ case FmgIDType.SummaryArmor:
+ case FmgIDType.SummaryRings:
+ case FmgIDType.SummaryRings_DLC1:
+ case FmgIDType.SummaryRings_DLC2:
+ case FmgIDType.SummarySpells:
+ case FmgIDType.SummarySpells_DLC1:
+ case FmgIDType.SummarySpells_DLC2:
+ case FmgIDType.SummaryArmor_Patch:
+ case FmgIDType.SummaryGoods_Patch:
+ case FmgIDType.SummaryRings_Patch:
+ case FmgIDType.SummaryWeapons_Patch:
+ case FmgIDType.SummaryMission:
+ case FmgIDType.TutorialTitle: // Include as summary (not all TutorialBody's have a title)
+ case FmgIDType.TutorialTitle2023:
+ return FmgEntryTextType.Summary;
+
+ case FmgIDType.TitleGoods:
+ case FmgIDType.TitleGoods_DLC2:
+ case FmgIDType.TitleWeapons:
+ case FmgIDType.TitleWeapons_DLC1:
+ case FmgIDType.TitleWeapons_DLC2:
+ case FmgIDType.TitleArmor:
+ case FmgIDType.TitleArmor_DLC1:
+ case FmgIDType.TitleArmor_DLC2:
+ case FmgIDType.TitleRings:
+ case FmgIDType.TitleRings_DLC1:
+ case FmgIDType.TitleRings_DLC2:
+ case FmgIDType.TitleSpells:
+ case FmgIDType.TitleSpells_DLC1:
+ case FmgIDType.TitleSpells_DLC2:
+ case FmgIDType.TitleCharacters:
+ case FmgIDType.TitleCharacters_DLC1:
+ case FmgIDType.TitleCharacters_DLC2:
+ case FmgIDType.TitleLocations:
+ case FmgIDType.TitleLocations_DLC1:
+ case FmgIDType.TitleLocations_DLC2:
+ case FmgIDType.TitleTest:
+ case FmgIDType.TitleTest2:
+ case FmgIDType.TitleTest3:
+ case FmgIDType.TitleArmor_Patch:
+ case FmgIDType.TitleCharacters_Patch:
+ case FmgIDType.TitleGoods_Patch:
+ case FmgIDType.TitleLocations_Patch:
+ case FmgIDType.TitleRings_Patch:
+ case FmgIDType.TitleSpells_Patch:
+ case FmgIDType.TitleWeapons_Patch:
+ case FmgIDType.TitleBooster:
+ case FmgIDType.TitleMission:
+ case FmgIDType.TitleArchive:
+ return FmgEntryTextType.Title;
+
+ case FmgIDType.GoodsInfo2:
+ case FmgIDType.MissionLocation:
+ return FmgEntryTextType.ExtraText;
+
+ case FmgIDType.WeaponEffect:
+ case FmgIDType.TutorialBody: // Include as TextBody to make it display foremost.
+ case FmgIDType.TutorialBody2023:
+ return FmgEntryTextType.TextBody;
+
+ default:
+ return FmgEntryTextType.TextBody;
+ }
+ }
+
+ public static FmgFileCategory GetFMGUICategory(FmgEntryCategory entryCategory)
+ {
+ switch (entryCategory)
+ {
+ case FmgEntryCategory.Goods:
+ case FmgEntryCategory.Weapons:
+ case FmgEntryCategory.Armor:
+ case FmgEntryCategory.Rings:
+ case FmgEntryCategory.Gem:
+ case FmgEntryCategory.SwordArts:
+ case FmgEntryCategory.Generator:
+ case FmgEntryCategory.Booster:
+ case FmgEntryCategory.FCS:
+ case FmgEntryCategory.Archive:
+ return FmgFileCategory.Item;
+ default:
+ return FmgFileCategory.Menu;
+ }
+ }
+}
diff --git a/src/StudioCore/TextEditor/FmgExporter.cs b/src/StudioCore/TextEditor/FmgExporter.cs
index 7b1010f11..520371557 100644
--- a/src/StudioCore/TextEditor/FmgExporter.cs
+++ b/src/StudioCore/TextEditor/FmgExporter.cs
@@ -36,426 +36,437 @@ public JsonFMG(FmgIDType fmg_id, FMG fmg)
}
}
-public static partial class FMGBank
+///
+/// Imports and exports FMGs using external formats.
+///
+public static class FmgExporter
{
- ///
- /// Imports and exports FMGs using external formats.
- ///
- public static class FmgExporter
- {
- private const string _entrySeparator = "###";
+ private const string _entrySeparator = "###";
- private static Dictionary GetFmgs(string msgBndPath)
+ private static Dictionary GetFmgs(FMGBank bank, string msgBndPath)
+ {
+ Dictionary fmgs = new();
+ IBinder fmgBinder;
+ if (bank.Project.Type is GameType.DemonsSouls or GameType.DarkSoulsPTDE
+ or GameType.DarkSoulsRemastered)
{
- Dictionary fmgs = new();
- IBinder fmgBinder;
- if (AssetLocator.Type is GameType.DemonsSouls or GameType.DarkSoulsPTDE
- or GameType.DarkSoulsRemastered)
- {
- fmgBinder = BND3.Read(msgBndPath);
- }
- else
- {
- fmgBinder = BND4.Read(msgBndPath);
- }
- foreach (var file in fmgBinder.Files)
- {
- var fmg = FMG.Read(file.Bytes);
- fmgs.Add((FmgIDType)file.ID, fmg);
- }
+ fmgBinder = BND3.Read(msgBndPath);
+ }
+ else
+ {
+ fmgBinder = BND4.Read(msgBndPath);
+ }
+ foreach (var file in fmgBinder.Files)
+ {
+ var fmg = FMG.Read(file.Bytes);
+ fmgs.Add((FmgIDType)file.ID, fmg);
+ }
+
+ fmgBinder.Dispose();
+
+ return fmgs;
+ }
- fmgBinder.Dispose();
+ private static string FormatJson(string json)
+ {
+ json = json.Replace("{\"ID\"", "\r\n{\"ID\"");
+ json = json.Replace("],", "\r\n],");
+ return json;
+ }
- return fmgs;
+ ///
+ /// Exports jsons that only contains entries that differ between game and mod directories.
+ ///
+ public static void ExportFmgTxt(FMGLanguage lang, bool moddedOnly)
+ {
+ if (!PlatformUtils.Instance.OpenFolderDialog("Choose Export Folder", out var path))
+ {
+ return;
}
- ///
- /// Exports jsons that only contains entries that differ between game and mod directories.
- ///
- public static void ExportFmgTxt(bool moddedOnly)
+ if (lang.Owner.Project.ParentProject == null)
{
- if (!PlatformUtils.Instance.OpenFolderDialog("Choose Export Folder", out var path))
- {
- return;
- }
+ TaskLogs.AddLog("Error: Project has no parent to compare to. Cannot export modded files without vanilla FMGs to compare to.",
+ LogLevel.Warning, TaskLogs.LogPriority.High);
+ return;
+ }
- if (moddedOnly && AssetLocator.GameModDirectory == AssetLocator.GameRootDirectory)
- {
- TaskLogs.AddLog("Error: Game directory is identical to mod directory. Cannot export modded files without vanilla FMGs to compare to.",
- LogLevel.Warning, TaskLogs.LogPriority.High);
- return;
- }
+ if (moddedOnly && lang.Owner.Project.AssetLocator.RootDirectory == lang.Owner.Project.ParentProject.AssetLocator.RootDirectory)
+ {
+ TaskLogs.AddLog("Error: Game directory is identical to mod directory or project has no parent. Cannot export modded files without vanilla FMGs to compare to.",
+ LogLevel.Warning, TaskLogs.LogPriority.High);
+ return;
+ }
- var itemPath = AssetLocator.GetItemMsgbnd(LanguageFolder).AssetPath;
- var menuPath = AssetLocator.GetMenuMsgbnd(LanguageFolder).AssetPath;
- var itemPath_Vanilla = itemPath.Replace(AssetLocator.GameModDirectory, AssetLocator.GameRootDirectory);
- var menuPath_Vanilla = menuPath.Replace(AssetLocator.GameModDirectory, AssetLocator.GameRootDirectory);
+ var itemPath = Locator.AssetLocator.GetItemMsgbnd(lang.LanguageFolder).AssetPath;
+ var menuPath = Locator.AssetLocator.GetMenuMsgbnd(lang.LanguageFolder).AssetPath;
+ var itemPath_Vanilla = itemPath.Replace(lang.Owner.Project.AssetLocator.RootDirectory, lang.Owner.Project.ParentProject.AssetLocator.RootDirectory);
+ var menuPath_Vanilla = menuPath.Replace(lang.Owner.Project.AssetLocator.RootDirectory, lang.Owner.Project.ParentProject.AssetLocator.RootDirectory);
- Dictionary fmgs_vanilla = new();
- fmgs_vanilla.AddAll(GetFmgs(itemPath_Vanilla));
- fmgs_vanilla.AddAll(GetFmgs(menuPath_Vanilla));
+ Dictionary fmgs_vanilla = new();
+ fmgs_vanilla.AddAll(GetFmgs(lang.Owner, itemPath_Vanilla));
+ fmgs_vanilla.AddAll(GetFmgs(lang.Owner, menuPath_Vanilla));
- Dictionary fmgs_mod = new();
- foreach (var info in FmgInfoBank)
- {
- fmgs_mod.Add(info.FmgID, info.Fmg);
- }
+ Dictionary fmgs_mod = new();
+ foreach (var info in lang._FmgInfoBanks.SelectMany((x) => x.Value.FmgInfos))
+ {
+ fmgs_mod.Add(info.FmgID, info.Fmg);
+ }
- Dictionary fmgs_out;
+ Dictionary fmgs_out;
- if (!moddedOnly)
- {
- // Export all entries
- fmgs_out = fmgs_mod;
- }
- else
+ if (!moddedOnly)
+ {
+ // Export all entries
+ fmgs_out = fmgs_mod;
+ }
+ else
+ {
+ // Export modded entries only
+ fmgs_out = new();
+ foreach (var kvp in fmgs_mod)
{
- // Export modded entries only
- fmgs_out = new();
- foreach (var kvp in fmgs_mod)
- {
- var fmg_mod = kvp.Value;
- var entries_vanilla = fmgs_vanilla[kvp.Key].Entries.ToList();
- FMG entries_out = new(fmg_mod.Version);
+ var fmg_mod = kvp.Value;
+ var entries_vanilla = fmgs_vanilla[kvp.Key].Entries.ToList();
+ FMG entries_out = new(fmg_mod.Version);
- foreach (var entry in fmg_mod.Entries)
+ foreach (var entry in fmg_mod.Entries)
+ {
+ FMG.Entry entry_vanilla = null;
+ for (var i = 0; i < entries_vanilla.Count; i++)
{
- FMG.Entry entry_vanilla = null;
- for (var i = 0; i < entries_vanilla.Count; i++)
+ if (entries_vanilla[i].ID == entry.ID)
{
- if (entries_vanilla[i].ID == entry.ID)
- {
- entry_vanilla = entries_vanilla[i];
- entries_vanilla.RemoveAt(i);
- break;
- }
- }
-
- if (entry_vanilla != null && entry.Text == entry_vanilla.Text)
- {
- continue;
+ entry_vanilla = entries_vanilla[i];
+ entries_vanilla.RemoveAt(i);
+ break;
}
-
- entries_out.Entries.Add(entry);
}
- if (entries_out.Entries.Count > 0)
+ if (entry_vanilla != null && entry.Text == entry_vanilla.Text)
{
- fmgs_out.Add(kvp.Key, entries_out);
+ continue;
}
+
+ entries_out.Entries.Add(entry);
}
- }
- if (fmgs_out.Count == 0)
- {
- TaskLogs.AddLog("All FMG entries in mod folder are identical to game folder. No files have been exported.",
- LogLevel.Information, TaskLogs.LogPriority.High);
- return;
+ if (entries_out.Entries.Count > 0)
+ {
+ fmgs_out.Add(kvp.Key, entries_out);
+ }
}
+ }
+
+ if (fmgs_out.Count == 0)
+ {
+ TaskLogs.AddLog("All FMG entries in mod folder are identical to game folder. No files have been exported.",
+ LogLevel.Information, TaskLogs.LogPriority.High);
+ return;
+ }
- foreach (var kvp in fmgs_out)
+ foreach (var kvp in fmgs_out)
+ {
+ var fileName = kvp.Key.ToString();
+ Dictionary> sharedText = new();
+ foreach (var entry in kvp.Value.Entries)
{
- var fileName = kvp.Key.ToString();
- Dictionary> sharedText = new();
- foreach (var entry in kvp.Value.Entries)
- {
- // Combine shared text
+ // Combine shared text
- if (entry.Text == null)
- continue;
+ if (entry.Text == null)
+ continue;
- entry.Text = entry.Text.TrimEnd('\n');
+ entry.Text = entry.Text.TrimEnd('\n');
- if (!sharedText.TryGetValue(entry.Text, out var ids))
- {
- sharedText[entry.Text] = ids = new();
- }
- ids.Add(entry.ID);
+ if (!sharedText.TryGetValue(entry.Text, out var ids))
+ {
+ sharedText[entry.Text] = ids = new();
}
+ ids.Add(entry.ID);
+ }
- List output = [];
- output.Add($"###ID {(int)kvp.Key}");
- foreach (var sharedKvp in sharedText)
- {
- var text = sharedKvp.Key;
- HashSet ids = sharedKvp.Value;
+ List output = [];
+ output.Add($"###ID {(int)kvp.Key}");
+ foreach (var sharedKvp in sharedText)
+ {
+ var text = sharedKvp.Key;
+ HashSet ids = sharedKvp.Value;
- text = text.Replace("\r", "");
- text = text.TrimEnd('\n');
+ text = text.Replace("\r", "");
+ text = text.TrimEnd('\n');
- output.Add("");
- string idsString = "";
- foreach (var id in ids)
- {
- idsString += _entrySeparator + id.ToString();
- }
- output.Add(idsString);
- output.AddRange(text.Split("\n"));
+ output.Add("");
+ string idsString = "";
+ foreach (var id in ids)
+ {
+ idsString += _entrySeparator + id.ToString();
}
-
- File.WriteAllLines($@"{path}\{fileName}.fmgmerge.txt", output);
+ output.Add(idsString);
+ output.AddRange(text.Split("\n"));
}
- TaskLogs.AddLog("Finished exporting FMG txt files",
- LogLevel.Information, TaskLogs.LogPriority.High);
+ File.WriteAllLines($@"{path}\{fileName}.fmgmerge.txt", output);
}
- [Obsolete]
- public static bool ExportJsonFMGs()
+ TaskLogs.AddLog("Finished exporting FMG txt files",
+ LogLevel.Information, TaskLogs.LogPriority.High);
+ }
+
+ [Obsolete]
+ public static bool ExportJsonFMGs(FMGBank bank)
+ {
+ if (!PlatformUtils.Instance.OpenFolderDialog("Choose Export Folder", out var path))
{
- if (!PlatformUtils.Instance.OpenFolderDialog("Choose Export Folder", out var path))
- {
- return false;
- }
+ return false;
+ }
+
+ var filecount = 0;
+ if (bank.Project.Type == GameType.DarkSoulsIISOTFS)
+ {
+ Directory.CreateDirectory(path);
- var filecount = 0;
- if (AssetLocator.Type == GameType.DarkSoulsIISOTFS)
+ foreach (FMGInfo info in bank.FmgInfoBank)
{
- Directory.CreateDirectory(path);
+ JsonFMG fmgPair = new(info.FmgID, info.Fmg);
+ var json = JsonSerializer.Serialize(fmgPair, FmgSerializerContext.Default.JsonFMG);
+ json = FormatJson(json);
- foreach (FMGInfo info in FmgInfoBank)
+ var fileName = info.Name;
+ if (CFG.Current.FMG_ShowOriginalNames)
{
- JsonFMG fmgPair = new(info.FmgID, info.Fmg);
- var json = JsonSerializer.Serialize(fmgPair, FmgSerializerContext.Default.JsonFMG);
- json = FormatJson(json);
-
- var fileName = info.Name;
- if (CFG.Current.FMG_ShowOriginalNames)
- {
- fileName = info.FileName;
- }
+ fileName = info.FileName;
+ }
- File.WriteAllText($@"{path}\{fileName}.fmg.json", json);
+ File.WriteAllText($@"{path}\{fileName}.fmg.json", json);
- filecount++;
- }
+ filecount++;
}
- else
+ }
+ else
+ {
+ var itemPath = $@"{path}\Item Text";
+ var menuPath = $@"{path}\Menu Text";
+ Directory.CreateDirectory(itemPath);
+ Directory.CreateDirectory(menuPath);
+ foreach (FMGInfo info in bank.FmgInfoBank)
{
- var itemPath = $@"{path}\Item Text";
- var menuPath = $@"{path}\Menu Text";
- Directory.CreateDirectory(itemPath);
- Directory.CreateDirectory(menuPath);
- foreach (FMGInfo info in FmgInfoBank)
+ if (info.FileCategory == FmgFileCategory.Item)
{
- if (info.UICategory == FmgUICategory.Item)
- {
- path = itemPath;
- }
- else if (info.UICategory == FmgUICategory.Menu)
- {
- path = menuPath;
- }
+ path = itemPath;
+ }
+ else if (info.FileCategory == FmgFileCategory.Menu)
+ {
+ path = menuPath;
+ }
- JsonFMG fmgPair = new(info.FmgID, info.Fmg);
- var json = JsonSerializer.Serialize(fmgPair, FmgSerializerContext.Default.JsonFMG);
- json = FormatJson(json);
+ JsonFMG fmgPair = new(info.FmgID, info.Fmg);
+ var json = JsonSerializer.Serialize(fmgPair, FmgSerializerContext.Default.JsonFMG);
+ json = FormatJson(json);
- var fileName = info.Name;
- if (CFG.Current.FMG_ShowOriginalNames)
- {
- fileName = info.FileName;
- }
+ var fileName = info.Name;
+ if (CFG.Current.FMG_ShowOriginalNames)
+ {
+ fileName = info.FileName;
+ }
- File.WriteAllText($@"{path}\{fileName}.fmg.json", json);
+ File.WriteAllText($@"{path}\{fileName}.fmg.json", json);
- filecount++;
- }
+ filecount++;
}
-
- TaskLogs.AddLog($"Finished exporting {filecount} text files",
- LogLevel.Information, TaskLogs.LogPriority.High);
- return true;
}
- private static bool ImportFmg(FmgIDType fmgId, FMG fmg, bool merge)
+ TaskLogs.AddLog($"Finished exporting {filecount} text files",
+ LogLevel.Information, TaskLogs.LogPriority.High);
+ return true;
+ }
+
+ private static bool ImportFmg(FMGLanguage lang, FmgIDType fmgId, FMG fmg, bool merge)
+ {
+ foreach (FMGInfo info in lang._FmgInfoBanks.SelectMany((x) => x.Value.FmgInfos))
{
- foreach (FMGInfo info in FmgInfoBank)
+ if (info.FmgID == fmgId)
{
- if (info.FmgID == fmgId)
+ if (merge)
{
- if (merge)
+ // Merge mode. Add and replace FMG entries instead of overwriting FMG entirely
+ foreach (var entry in fmg.Entries)
{
- // Merge mode. Add and replace FMG entries instead of overwriting FMG entirely
- foreach (var entry in fmg.Entries)
+ var currentEntry = info.Fmg.Entries.Find(e => e.ID == entry.ID);
+ if (currentEntry == null)
{
- var currentEntry = info.Fmg.Entries.Find(e => e.ID == entry.ID);
- if (currentEntry == null)
- {
- info.Fmg.Entries.Add(entry);
- }
- else if (currentEntry.Text != entry.Text)
- {
- currentEntry.Text = entry.Text;
- }
+ info.Fmg.Entries.Add(entry);
+ }
+ else if (currentEntry.Text != entry.Text)
+ {
+ currentEntry.Text = entry.Text;
}
}
- else
- {
- // Overwrite mode. Replace FMG with imported json
- info.Fmg = fmg;
- }
-
- return true;
}
+ else
+ {
+ // Overwrite mode. Replace FMG with imported json
+ info.Fmg = fmg;
+ }
+
+ return true;
}
+ }
- TaskLogs.AddLog($"FMG import error: No loaded FMGs have an ID of \"{fmgId}\"",
- LogLevel.Error, TaskLogs.LogPriority.Normal);
+ TaskLogs.AddLog($"FMG import error: No loaded FMGs have an ID of \"{fmgId}\"",
+ LogLevel.Error, TaskLogs.LogPriority.Normal);
+ return false;
+ }
+
+ public static bool ImportFmgJson(FMGLanguage lang, bool merge)
+ {
+ if (!PlatformUtils.Instance.OpenMultiFileDialog("Choose Files to Import",
+ new[] { AssetUtils.FmgJsonFilter }, out IReadOnlyList files))
+ {
return false;
}
- public static bool ImportFmgJson(bool merge)
+ if (files.Count == 0)
{
- if (!PlatformUtils.Instance.OpenMultiFileDialog("Choose Files to Import",
- new[] { AssetLocator.FmgJsonFilter }, out IReadOnlyList files))
- {
- return false;
- }
-
- if (files.Count == 0)
- {
- return false;
- }
+ return false;
+ }
- var filecount = 0;
- foreach (var filePath in files)
+ var filecount = 0;
+ foreach (var filePath in files)
+ {
+ try
{
- try
+ var file = File.ReadAllText(filePath);
+ JsonFMG json = JsonSerializer.Deserialize(file, FmgSerializerContext.Default.JsonFMG);
+ bool success = ImportFmg(lang, json.FmgID, json.Fmg, merge);
+ if (success)
{
- var file = File.ReadAllText(filePath);
- JsonFMG json = JsonSerializer.Deserialize(file, FmgSerializerContext.Default.JsonFMG);
- bool success = ImportFmg(json.FmgID, json.Fmg, merge);
- if (success)
- {
- filecount++;
- }
- }
- catch (JsonException e)
- {
- TaskLogs.AddLog($"FMG import error: Couldn't import \"{filePath}\"",
- LogLevel.Error, TaskLogs.LogPriority.Normal, e);
+ filecount++;
}
}
-
- if (filecount == 0)
+ catch (JsonException e)
{
- return false;
+ TaskLogs.AddLog($"FMG import error: Couldn't import \"{filePath}\"",
+ LogLevel.Error, TaskLogs.LogPriority.Normal, e);
}
+ }
- HandleDuplicateEntries();
- PlatformUtils.Instance.MessageBox($"Imported {filecount} json files", "Finished", MessageBoxButtons.OK);
- return true;
+ if (filecount == 0)
+ {
+ return false;
}
- public static bool ImportFmgTxt(bool merge)
+// lang.HandleDuplicateEntries();
+ PlatformUtils.Instance.MessageBox($"Imported {filecount} json files", "Finished", MessageBoxButtons.OK);
+ return true;
+ }
+
+ public static bool ImportFmgTxt(FMGLanguage lang, bool merge)
+ {
+ if (!PlatformUtils.Instance.OpenMultiFileDialog("Choose Files to Import",
+ new[] { AssetUtils.TxtFilter }, out IReadOnlyList files))
{
- if (!PlatformUtils.Instance.OpenMultiFileDialog("Choose Files to Import",
- new[] { AssetLocator.TxtFilter }, out IReadOnlyList files))
- {
- return false;
- }
+ return false;
+ }
- if (files.Count == 0)
- {
- return false;
- }
+ if (files.Count == 0)
+ {
+ return false;
+ }
- var filecount = 0;
- foreach (var filePath in files)
+ var filecount = 0;
+ foreach (var filePath in files)
+ {
+ try
{
+ string fileName = Path.GetFileName(filePath);
+ FMG fmg = new();
+ int fmgId = 0;
+ var file = File.ReadAllLines(filePath);
try
{
- string fileName = Path.GetFileName(filePath);
- FMG fmg = new();
- int fmgId = 0;
- var file = File.ReadAllLines(filePath);
- try
+ fmgId = int.Parse(file[0].Replace(_entrySeparator, "").Replace("ID", ""));
+ }
+ catch
+ {
+ TaskLogs.AddLog($"FMG import error for file {fileName}: Cannot parse FMG ID on line 1.",
+ LogLevel.Error, TaskLogs.LogPriority.Normal);
+ return false;
+ }
+
+ Queue entryIds = new();
+ List text = new();
+ for (var i = 1; i < file.Length; i++)
+ {
+ var line = file[i];
+ if (i + 1 == file.Length)
{
- fmgId = int.Parse(file[0].Replace(_entrySeparator, "").Replace("ID", ""));
+ text.Add(line);
+ string str = string.Join("\r\n", text);
+ while (entryIds.Count > 0)
+ {
+ fmg.Entries.Add(new(entryIds.Dequeue(), str));
+ }
}
- catch
+ else if (line.StartsWith(_entrySeparator))
{
- TaskLogs.AddLog($"FMG import error for file {fileName}: Cannot parse FMG ID on line 1.",
- LogLevel.Error, TaskLogs.LogPriority.Normal);
- return false;
- }
-
- Queue entryIds = new();
- List text = new();
- for (var i = 1; i < file.Length; i++)
- {
- var line = file[i];
- if (i + 1 == file.Length)
+ if (text.Count > 0)
{
- text.Add(line);
string str = string.Join("\r\n", text);
+
while (entryIds.Count > 0)
{
fmg.Entries.Add(new(entryIds.Dequeue(), str));
}
- }
- else if (line.StartsWith(_entrySeparator))
- {
- if (text.Count > 0)
- {
- string str = string.Join("\r\n", text);
- while (entryIds.Count > 0)
+ try
+ {
+ var ids = line.Split(_entrySeparator);
+ foreach (var id in ids)
{
- fmg.Entries.Add(new(entryIds.Dequeue(), str));
- }
+ if (string.IsNullOrEmpty(id))
+ continue;
- try
- {
- var ids = line.Split(_entrySeparator);
- foreach (var id in ids)
- {
- if (string.IsNullOrEmpty(id))
- continue;
-
- entryIds.Enqueue(int.Parse(id));
- }
- }
- catch
- {
- TaskLogs.AddLog($"FMG import error for file {fileName}: Cannot parse entry ID on line {i + 1}.",
- LogLevel.Error, TaskLogs.LogPriority.High);
- return false;
+ entryIds.Enqueue(int.Parse(id));
}
- text = new();
}
- }
- else
- {
- text.Add(line);
+ catch
+ {
+ TaskLogs.AddLog($"FMG import error for file {fileName}: Cannot parse entry ID on line {i + 1}.",
+ LogLevel.Error, TaskLogs.LogPriority.High);
+ return false;
+ }
+ text = new();
}
}
-
- bool success = ImportFmg((FmgIDType)fmgId, fmg, merge);
- if (success)
+ else
{
- filecount++;
+ text.Add(line);
}
}
- catch (Exception e)
+
+ bool success = ImportFmg(lang, (FmgIDType)fmgId, fmg, merge);
+ if (success)
{
- TaskLogs.AddLog($"FMG import error: Couldn't import \"{filePath}\"",
- LogLevel.Error, TaskLogs.LogPriority.Normal, e);
+ filecount++;
}
}
-
- if (filecount == 0)
+ catch (Exception e)
{
- return false;
+ TaskLogs.AddLog($"FMG import error: Couldn't import \"{filePath}\"",
+ LogLevel.Error, TaskLogs.LogPriority.Normal, e);
}
+ }
- FMGBank.HandleDuplicateEntries();
- TaskLogs.AddLog($"FMG import: Finished importing {filecount} txt files",
- LogLevel.Information, TaskLogs.LogPriority.Normal);
- return true;
+ if (filecount == 0)
+ {
+ return false;
}
+
+// lang.HandleDuplicateEntries();
+ TaskLogs.AddLog($"FMG import: Finished importing {filecount} txt files",
+ LogLevel.Information, TaskLogs.LogPriority.Normal);
+ return true;
}
}
diff --git a/src/StudioCore/TextEditor/TextEditorScreen.cs b/src/StudioCore/TextEditor/TextEditorScreen.cs
index 568950021..6bff6cc73 100644
--- a/src/StudioCore/TextEditor/TextEditorScreen.cs
+++ b/src/StudioCore/TextEditor/TextEditorScreen.cs
@@ -13,11 +13,8 @@ namespace StudioCore.TextEditor;
public unsafe class TextEditorScreen : EditorScreen
{
private readonly PropertyEditor _propEditor;
-
- public readonly AssetLocator AssetLocator;
-
- private FMGBank.EntryGroup _activeEntryGroup;
- private FMGBank.FMGInfo _activeFmgInfo;
+ private FMGEntryGroup _activeEntryGroup;
+ private FMGInfo _activeFmgInfo;
private int _activeIDCache = -1;
private bool _arrowKeyPressed;
@@ -31,12 +28,11 @@ public unsafe class TextEditorScreen : EditorScreen
private string _searchFilterCached = "";
private string _fmgSearchAllString = "";
private bool _fmgSearchAllActive = false;
- private List _filteredFmgInfo = new();
+ private List _filteredFmgInfo = new();
public ActionManager EditorActionManager = new();
- public TextEditorScreen(Sdl2Window window, GraphicsDevice device, AssetLocator locator)
+ public TextEditorScreen(Sdl2Window window, GraphicsDevice device)
{
- AssetLocator = locator;
_propEditor = new PropertyEditor(EditorActionManager);
}
@@ -46,7 +42,11 @@ public TextEditorScreen(Sdl2Window window, GraphicsDevice device, AssetLocator l
public void DrawEditorMenu()
{
- if (ImGui.BeginMenu("Edit", FMGBank.IsLoaded))
+ if (Locator.ActiveProject == null)
+ return;
+ FMGBank currentFmgBank = Locator.ActiveProject.FMGBank;
+
+ if (ImGui.BeginMenu("Edit", Locator.ActiveProject.FMGBank.IsLoaded))
{
if (ImGui.MenuItem("Undo", KeyBindings.Current.Core_Undo.HintText, false,
EditorActionManager.CanUndo()))
@@ -75,9 +75,9 @@ public void DrawEditorMenu()
ImGui.EndMenu();
}
- if (ImGui.BeginMenu("Text Language", !FMGBank.IsLoading))
+ if (ImGui.BeginMenu("Text Language", !Locator.ActiveProject.FMGBank.IsLoading))
{
- Dictionary folders = FMGBank.AssetLocator.GetMsgLanguages();
+ Dictionary folders = Locator.AssetLocator.GetMsgLanguages();
if (folders.Count == 0)
{
ImGui.TextColored(new Vector4(1.0f, 0.0f, 0.0f, 1.0f), "Cannot find language folders.");
@@ -86,7 +86,13 @@ public void DrawEditorMenu()
{
foreach (KeyValuePair path in folders)
{
- if (ImGui.MenuItem(path.Key, "", FMGBank.LanguageFolder == path.Key))
+ string disp = path.Key;
+ if (Locator.ActiveProject.FMGBank.fmgLangs.ContainsKey(path.Key))
+ {
+ disp += "*";
+ }
+
+ if (ImGui.MenuItem(disp, "", Locator.ActiveProject.FMGBank.LanguageFolder == path.Key))
{
ChangeLanguage(path.Key);
}
@@ -96,7 +102,7 @@ public void DrawEditorMenu()
ImGui.EndMenu();
}
- if (ImGui.BeginMenu("Import/Export", FMGBank.IsLoaded))
+ if (ImGui.BeginMenu("Import/Export", Locator.ActiveProject.FMGBank.IsLoaded))
{
if (ImGui.BeginMenu("Merge"))
{
@@ -105,7 +111,7 @@ public void DrawEditorMenu()
if (ImGui.MenuItem("Import text files and merge"))
{
- if (FMGBank.FmgExporter.ImportFmgTxt(true))
+ if (FmgExporter.ImportFmgTxt(currentFmgBank.fmgLangs[currentFmgBank.LanguageFolder], true))
{
ClearTextEditorCache();
ResetActionManager();
@@ -116,7 +122,7 @@ public void DrawEditorMenu()
"Export: only modded text (different than vanilla) will be exported");
if (ImGui.MenuItem("Export modded text to text files"))
{
- FMGBank.FmgExporter.ExportFmgTxt(true);
+ FmgExporter.ExportFmgTxt(currentFmgBank.fmgLangs[currentFmgBank.LanguageFolder], true);
}
ImGui.EndMenu();
@@ -129,7 +135,7 @@ public void DrawEditorMenu()
if (ImGui.MenuItem("Import text files and replace"))
{
- if (FMGBank.FmgExporter.ImportFmgTxt(false))
+ if (FmgExporter.ImportFmgTxt(currentFmgBank.fmgLangs[currentFmgBank.LanguageFolder], false))
{
ClearTextEditorCache();
ResetActionManager();
@@ -140,7 +146,7 @@ public void DrawEditorMenu()
"Export: all text will be exported");
if (ImGui.MenuItem("Export all text to text files"))
{
- FMGBank.FmgExporter.ExportFmgTxt(false);
+ FmgExporter.ExportFmgTxt(currentFmgBank.fmgLangs[currentFmgBank.LanguageFolder], false);
}
if (ImGui.BeginMenu("Legacy"))
@@ -150,7 +156,7 @@ public void DrawEditorMenu()
"Import: text replaces currently loaded text entirely.");
if (ImGui.MenuItem("Import json"))
{
- if (FMGBank.FmgExporter.ImportFmgJson(false))
+ if (FmgExporter.ImportFmgJson(currentFmgBank.fmgLangs[currentFmgBank.LanguageFolder], false))
{
ClearTextEditorCache();
ResetActionManager();
@@ -167,7 +173,7 @@ public void DrawEditorMenu()
public void OnGUI(string[] initcmd)
{
- if (FMGBank.AssetLocator == null)
+ if (Locator.AssetLocator == null)
{
return;
}
@@ -183,7 +189,7 @@ public void OnGUI(string[] initcmd)
ImGui.SetNextWindowPos(winp);
ImGui.SetNextWindowSize(wins);
- if (!ImGui.IsAnyItemActive() && FMGBank.IsLoaded)
+ if (!ImGui.IsAnyItemActive() && Locator.ActiveProject != null && Locator.ActiveProject.FMGBank.IsLoaded)
{
// Only allow key shortcuts when an item [text box] is not currently activated
if (EditorActionManager.CanUndo() && InputTracker.GetKeyDown(KeyBindings.Current.Core_Undo))
@@ -236,7 +242,7 @@ public void OnGUI(string[] initcmd)
searchName = initcmd[1];
}
- foreach (FMGBank.FMGInfo info in FMGBank.FmgInfoBank)
+ foreach (FMGInfo info in Locator.ActiveProject.FMGBank.FmgInfoBank)
{
var match = false;
// This matches top-level item FMGs
@@ -268,7 +274,7 @@ public void OnGUI(string[] initcmd)
var parsed = int.TryParse(initcmd[2], out var id);
if (parsed)
{
- _activeEntryGroup = FMGBank.GenerateEntryGroup(id, _activeFmgInfo);
+ _activeEntryGroup = Locator.ActiveProject.FMGBank.GenerateEntryGroup(id, _activeFmgInfo);
}
}
}
@@ -285,17 +291,16 @@ public void OnProjectChanged(ProjectSettings newSettings)
_filteredFmgInfo.Clear();
ClearTextEditorCache();
ResetActionManager();
- FMGBank.ReloadFMGs(_projectSettings.LastFmgLanguageUsed);
}
public void Save()
{
- FMGBank.SaveFMGs();
+ Locator.ActiveProject.FMGBank.SaveFMGs();
}
public void SaveAll()
{
- FMGBank.SaveFMGs();
+ Locator.ActiveProject.FMGBank.SaveFMGs();
}
private void ClearTextEditorCache()
@@ -318,7 +323,7 @@ private void ResetActionManager()
///
/// Duplicates all Entries in active EntryGroup from their FMGs
///
- private void DuplicateFMGEntries(FMGBank.EntryGroup entry)
+ private void DuplicateFMGEntries(FMGEntryGroup entry)
{
_activeIDCache = entry.GetNextUnusedID();
var action = new DuplicateFMGEntryAction(entry);
@@ -332,7 +337,7 @@ private void DuplicateFMGEntries(FMGBank.EntryGroup entry)
///
/// Deletes all Entries within active EntryGroup from their FMGs
///
- private void DeleteFMGEntries(FMGBank.EntryGroup entry)
+ private void DeleteFMGEntries(FMGEntryGroup entry)
{
var action = new DeleteFMGEntryAction(entry);
EditorActionManager.ExecuteAction(action);
@@ -381,7 +386,7 @@ private void FMGSearchLogic(ref bool doFocus)
}
// Descriptions
- foreach (FMG.Entry entry in FMGBank.GetFmgEntriesByCategoryAndTextType(_activeFmgInfo.EntryCategory,
+ foreach (FMG.Entry entry in Locator.ActiveProject.FMGBank.GetFmgEntriesByCategoryAndTextType(_activeFmgInfo.EntryCategory,
FmgEntryTextType.Description, false))
{
if (entry.Text != null)
@@ -398,7 +403,7 @@ private void FMGSearchLogic(ref bool doFocus)
}
// Summaries
- foreach (FMG.Entry entry in FMGBank.GetFmgEntriesByCategoryAndTextType(_activeFmgInfo.EntryCategory,
+ foreach (FMG.Entry entry in Locator.ActiveProject.FMGBank.GetFmgEntriesByCategoryAndTextType(_activeFmgInfo.EntryCategory,
FmgEntryTextType.Summary, false))
{
if (entry.Text != null)
@@ -415,7 +420,7 @@ private void FMGSearchLogic(ref bool doFocus)
}
// Extra Text
- foreach (FMG.Entry entry in FMGBank.GetFmgEntriesByCategoryAndTextType(_activeFmgInfo.EntryCategory,
+ foreach (FMG.Entry entry in Locator.ActiveProject.FMGBank.GetFmgEntriesByCategoryAndTextType(_activeFmgInfo.EntryCategory,
FmgEntryTextType.ExtraText, false))
{
if (entry.Text != null)
@@ -444,18 +449,18 @@ private void FMGSearchLogic(ref bool doFocus)
}
}
- private void CategoryListUI(FmgUICategory uiType, bool doFocus)
+ private void CategoryListUI(FmgFileCategory uiType, bool doFocus)
{
- List infos;
+ IEnumerable infos;
if (_fmgSearchAllActive)
infos = _filteredFmgInfo;
else
- infos = FMGBank.FmgInfoBank;
+ infos = Locator.ActiveProject.FMGBank.SortedFmgInfoBank;
foreach (var info in infos)
{
if (info.PatchParent == null
- && info.UICategory == uiType
+ && info.FileCategory == uiType
&& info.EntryType is FmgEntryTextType.Title or FmgEntryTextType.TextBody)
{
string displayName;
@@ -500,13 +505,13 @@ private void EditorGUI(bool doFocus)
{
var scale = MapStudioNew.GetUIScale();
- if (!FMGBank.IsLoaded)
+ if (Locator.ActiveProject == null || !Locator.ActiveProject.FMGBank.IsLoaded)
{
if (_projectSettings == null)
{
ImGui.Text("No project loaded. File -> New Project");
}
- else if (FMGBank.IsLoading)
+ else if (Locator.ActiveProject.FMGBank.IsLoading)
{
ImGui.Text("Loading...");
}
@@ -539,7 +544,7 @@ private void EditorGUI(bool doFocus)
{
_fmgSearchAllActive = true;
_filteredFmgInfo.Clear();
- foreach (var info in FMGBank.FmgInfoBank)
+ foreach (var info in Locator.ActiveProject.FMGBank.SortedFmgInfoBank)
{
if (info.PatchParent == null)
{
@@ -577,17 +582,14 @@ private void EditorGUI(bool doFocus)
}
ImGui.Separator();
- foreach (KeyValuePair v in FMGBank.ActiveUITypes)
+ foreach (FmgFileCategory v in Locator.ActiveProject.FMGBank.currentFmgInfoBanks)
{
- if (v.Value)
- {
- ImGui.Separator();
- ImGui.Text($" {v.Key} Text");
- ImGui.Separator();
- // Categories
- CategoryListUI(v.Key, doFocus);
- ImGui.Spacing();
- }
+ ImGui.Separator();
+ ImGui.Text($" {v} Text");
+ ImGui.Separator();
+ // Categories
+ CategoryListUI(v, doFocus);
+ ImGui.Spacing();
}
if (_activeFmgInfo != null)
@@ -666,11 +668,11 @@ private void EditorGUI(bool doFocus)
label = Utils.ImGui_WordWrapString(label, ImGui.GetColumnWidth(-1));
if (ImGui.Selectable(label, _activeIDCache == r.ID))
{
- _activeEntryGroup = FMGBank.GenerateEntryGroup(r.ID, _activeFmgInfo);
+ _activeEntryGroup = Locator.ActiveProject.FMGBank.GenerateEntryGroup(r.ID, _activeFmgInfo);
}
else if (_activeIDCache == r.ID && _activeEntryGroup == null)
{
- _activeEntryGroup = FMGBank.GenerateEntryGroup(r.ID, _activeFmgInfo);
+ _activeEntryGroup = Locator.ActiveProject.FMGBank.GenerateEntryGroup(r.ID, _activeFmgInfo);
_searchFilterCached = "";
}
@@ -678,7 +680,7 @@ private void EditorGUI(bool doFocus)
&& _activeEntryGroup?.ID != r.ID)
{
// Up/Down arrow key selection
- _activeEntryGroup = FMGBank.GenerateEntryGroup(r.ID, _activeFmgInfo);
+ _activeEntryGroup = Locator.ActiveProject.FMGBank.GenerateEntryGroup(r.ID, _activeFmgInfo);
_arrowKeyPressed = false;
}
@@ -692,13 +694,13 @@ private void EditorGUI(bool doFocus)
{
if (ImGui.Selectable("Duplicate Entry"))
{
- _activeEntryGroup = FMGBank.GenerateEntryGroup(r.ID, _activeFmgInfo);
+ _activeEntryGroup = Locator.ActiveProject.FMGBank.GenerateEntryGroup(r.ID, _activeFmgInfo);
DuplicateFMGEntries(_activeEntryGroup);
}
if (ImGui.Selectable("Delete Entry"))
{
- _activeEntryGroup = FMGBank.GenerateEntryGroup(r.ID, _activeFmgInfo);
+ _activeEntryGroup = Locator.ActiveProject.FMGBank.GenerateEntryGroup(r.ID, _activeFmgInfo);
DeleteFMGEntries(_activeEntryGroup);
}
@@ -766,6 +768,6 @@ private void ChangeLanguage(string path)
_filteredFmgInfo.Clear();
ClearTextEditorCache();
ResetActionManager();
- FMGBank.ReloadFMGs(path);
+ Locator.ActiveProject.FMGBank.LoadFMGs(path);
}
}