diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index a8e8e6de..f0389930 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -21,10 +21,10 @@ jobs: - name: Fetch Submodules Recursively run: git submodule update --init --recursive - - name: .NET 8 Setup + - name: .NET 10 Setup uses: actions/setup-dotnet@v5 with: - dotnet-version: '8.0.x' + dotnet-version: '10.0.x' - name: .NET Restore run: dotnet restore FModel diff --git a/.github/workflows/qa.yml b/.github/workflows/qa.yml index 140f6d92..61b7a550 100644 --- a/.github/workflows/qa.yml +++ b/.github/workflows/qa.yml @@ -14,16 +14,16 @@ jobs: with: submodules: 'recursive' - - name: .NET 8 Setup + - name: .NET 10 Setup uses: actions/setup-dotnet@v5 with: - dotnet-version: '8.0.x' + dotnet-version: '10.0.x' - name: .NET Restore run: dotnet restore "./FModel/FModel.slnx" -r win-x64 - name: .NET Publish - run: dotnet publish "./FModel/FModel.csproj" -c Release --no-restore --no-self-contained -r win-x64 -f net8.0-windows -o "./FModel/bin/Publish/" -p:PublishReadyToRun=false -p:PublishSingleFile=true -p:DebugType=None -p:GenerateDocumentationFile=false -p:DebugSymbols=false + run: dotnet publish "./FModel/FModel.csproj" -c Release --no-restore --no-self-contained -r win-x64 -f net10.0-windows -o "./FModel/bin/Publish/" -p:PublishReadyToRun=false -p:PublishSingleFile=true -p:DebugType=None -p:GenerateDocumentationFile=false -p:DebugSymbols=false - name: ZIP File uses: thedoctor0/zip-release@0.7.6 diff --git a/CUE4Parse b/CUE4Parse index 81458ae7..bf3c0908 160000 --- a/CUE4Parse +++ b/CUE4Parse @@ -1 +1 @@ -Subproject commit 81458ae77d3f3230d7582a77ffd938510430a4bf +Subproject commit bf3c09087c2a4d7d812582e268ec0d275a0827fd diff --git a/FModel/Creator/CreatorPackage.cs b/FModel/Creator/CreatorPackage.cs index b2b12284..4369fdd4 100644 --- a/FModel/Creator/CreatorPackage.cs +++ b/FModel/Creator/CreatorPackage.cs @@ -45,6 +45,7 @@ public class CreatorPackage : IDisposable case "AthenaMusicPackItemDefinition": case "AthenaBattleBusItemDefinition": case "AthenaCharacterItemDefinition": + case "ExtractableItemDefinition": case "AthenaMapMarkerItemDefinition": case "AthenaBackpackItemDefinition": case "CosmeticShoesItemDefinition": diff --git a/FModel/Enums.cs b/FModel/Enums.cs index 04f34036..dfbeeece 100644 --- a/FModel/Enums.cs +++ b/FModel/Enums.cs @@ -163,6 +163,7 @@ public enum EAssetCategory : uint Aion2 = GameSpecific + 2, RocoKingdomWorld = GameSpecific + 3, DeltaForce = GameSpecific + 4, + LegoBatman = GameSpecific + 5, } public enum EUnluacMode diff --git a/FModel/Extensions/AvalonExtensions.cs b/FModel/Extensions/AvalonExtensions.cs index 3021e178..bb5b7db6 100644 --- a/FModel/Extensions/AvalonExtensions.cs +++ b/FModel/Extensions/AvalonExtensions.cs @@ -49,6 +49,7 @@ public static class AvalonExtensions case "bat": case "txt": case "pem": + case "js": case "po": return null; default: diff --git a/FModel/FModel.csproj b/FModel/FModel.csproj index 90c2d391..af992309 100644 --- a/FModel/FModel.csproj +++ b/FModel/FModel.csproj @@ -1,8 +1,8 @@ - + WinExe - net8.0-windows + net10.0-windows true FModel.ico 4.4.4.0 @@ -152,27 +152,25 @@ - - - - + + + - - + + - - - + + - + diff --git a/FModel/FModel.sln b/FModel/FModel.sln deleted file mode 100644 index 238d1b59..00000000 --- a/FModel/FModel.sln +++ /dev/null @@ -1,37 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 17 -VisualStudioVersion = 17.0.31912.275 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FModel", "FModel.csproj", "{B1F494EA-90A6-4C24-800E-2F724A1884CA}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CUE4Parse", "..\CUE4Parse\CUE4Parse\CUE4Parse.csproj", "{C4620341-BBB7-4384-AC7D-5082D3E0386E}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CUE4Parse-Conversion", "..\CUE4Parse\CUE4Parse-Conversion\CUE4Parse-Conversion.csproj", "{D0E1E8F7-F56D-469A-8E24-C2439B9FFD83}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {B1F494EA-90A6-4C24-800E-2F724A1884CA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {B1F494EA-90A6-4C24-800E-2F724A1884CA}.Debug|Any CPU.Build.0 = Debug|Any CPU - {B1F494EA-90A6-4C24-800E-2F724A1884CA}.Release|Any CPU.ActiveCfg = Release|Any CPU - {B1F494EA-90A6-4C24-800E-2F724A1884CA}.Release|Any CPU.Build.0 = Release|Any CPU - {C4620341-BBB7-4384-AC7D-5082D3E0386E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {C4620341-BBB7-4384-AC7D-5082D3E0386E}.Debug|Any CPU.Build.0 = Debug|Any CPU - {C4620341-BBB7-4384-AC7D-5082D3E0386E}.Release|Any CPU.ActiveCfg = Release|Any CPU - {C4620341-BBB7-4384-AC7D-5082D3E0386E}.Release|Any CPU.Build.0 = Release|Any CPU - {D0E1E8F7-F56D-469A-8E24-C2439B9FFD83}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {D0E1E8F7-F56D-469A-8E24-C2439B9FFD83}.Debug|Any CPU.Build.0 = Debug|Any CPU - {D0E1E8F7-F56D-469A-8E24-C2439B9FFD83}.Release|Any CPU.ActiveCfg = Release|Any CPU - {D0E1E8F7-F56D-469A-8E24-C2439B9FFD83}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {53DB7A15-4E15-4575-9402-0110BDF2794E} - EndGlobalSection -EndGlobal diff --git a/FModel/Resources/Lua.xshd b/FModel/Resources/Lua.xshd index 148f5b97..88d749f2 100644 --- a/FModel/Resources/Lua.xshd +++ b/FModel/Resources/Lua.xshd @@ -1,58 +1,76 @@ - - - - - - - - - + + + + + + + + + + + + + + + --\[\[(.|\n)*?\]\] --.*$ + \[\[(.|\n)*?\]\] "([^"\\]|\\.)*" '([^'\\]|\\.)*' + \b0[xX][0-9A-Fa-f]+\b \b\d+\.\d+([eE][+-]?\d+)?\b \b\d+[eE][+-]?\d+\b \b\d+\b - return - function - goto - end - if + and + break + do else elseif - then + end for + function + goto + if in + or + repeat + return + then until while - break - or - and - repeat - do + false local nil not true - false + + + + self + _G + _ENV - assert collectgarbage + dofile error + getmetatable ipairs + load + loadfile + module next pairs pcall @@ -61,128 +79,24 @@ rawget rawlen rawset + require select setmetatable tonumber tostring type + unpack xpcall - getmetatable - require - module - - + bit32 + coroutine + debug + io math + os + package string table - coroutine - os - io utf8 - bit32 - package - debug - - - arshift - band - bnot - bor - bxor - btest - extract - lrotate - lshift - replace - rrotate - rshift - - - create - resume - running - status - wrap - yield - isyieldable - - - getuservalue - gethook - getinfo - getlocal - getregistry - getupvalue - upvaluejoin - upvalueid - setuservalue - sethook - setlocal - setupvalue - traceback - - - close - flush - input - lines - open - output - popen - read - tmpfile - seek - setvbuf - write - - - byte - char - dump - find - format - gmatch - gsub - len - lower - match - rep - reverse - sub - upper - pack - packsize - unpack - concat - maxn - insert - move - offset - codepoint - codes - charpattern - - - clock - date - difftime - execute - exit - getenv - remove - rename - setlocale - time - loadlib - searchpath - seeall - preload - cpath - path - searchers - loaded - - abs acos asin @@ -195,36 +109,140 @@ exp floor fmod - ult + frexp + huge + ldexp log log10 max + maxinteger min + mininteger modf pi + pow rad random randomseed sin + sinh sqrt tan - sinh tanh - pow - frexp - ldexp - huge - maxinteger - mininteger + tointeger + ult + byte + char + dump + find + format + gmatch + gsub + len + lower + match + pack + packsize + rep + reverse + sub + upper + concat + insert + maxn + move + remove + sort + close + flush + input + lines + open + output + popen + read + seek + setvbuf + tmpfile + write + clock + date + difftime + execute + exit + getenv + rename + setlocale + time + create + isyieldable + resume + running + status + wrap + yield + arshift + band + bnot + bor + btest + bxor + extract + lrotate + lshift + replace + rrotate + rshift + charpattern + codepoint + codes + offset + gethook + getinfo + getlocal + getregistry + getupvalue + getuservalue + sethook + setlocal + setupvalue + setuservalue + traceback + upvalueid + upvaluejoin + cpath + loaded + loadlib + path + preload + searchers + searchpath + seeall (\|)|(<<)|(>>)|(\/\/)|(==)|(~=)|(<=)|(>=)|(<)|(>)|(=)|(\()|(\))|(\{)|(\})|(\[)|(\])|(::)|(:)|(;)|(,)|(\.\.\.)|(\.\.)|(\.)|[+\-*%\^#&~] - (?<=function\s)[A-Za-z0-9_]+(?=\.) - - (?<=\.)[A-Za-z0-9_]+(?=\() - (?<=function\s)[A-Za-z0-9_]+(?=\s*\() + __[A-Za-z_][A-Za-z0-9_]*__ - \b[A-Z_][A-Z0-9_]*\b + (?<=::)[A-Za-z_][A-Za-z0-9_]*(?=::) + + (?<![A-Za-z0-9_])_(?![A-Za-z0-9_]) + + (?<=function\s)[A-Za-z_][A-Za-z0-9_]*(?=\.) + (?<=function\s)[A-Za-z_][A-Za-z0-9_]*(?=:) + + (?<=function\s)[A-Za-z_][A-Za-z0-9_]*(?=\s*\() + + [A-Za-z_][A-Za-z0-9_]*(?=\.) + [A-Za-z_][A-Za-z0-9_]*(?=:) + + (?<=:)[A-Za-z_][A-Za-z0-9_]*(?=\s*\() + (?<=\.)[A-Za-z_][A-Za-z0-9_]*(?=\s*\() + \b[A-Za-z_][A-Za-z0-9_]*(?=\s*\() + + (?<=\.)[A-Za-z_][A-Za-z0-9_]* + + \b[A-Z][A-Z0-9]*_[A-Z0-9_]*\b + \b[A-Z]{2}[A-Z0-9_]*\b diff --git a/FModel/Settings/UserSettings.cs b/FModel/Settings/UserSettings.cs index ea62298c..42991de9 100644 --- a/FModel/Settings/UserSettings.cs +++ b/FModel/Settings/UserSettings.cs @@ -300,7 +300,7 @@ namespace FModel.Settings } } - private EUnluacFlags _unluacFlags; + private EUnluacFlags _unluacFlags = EUnluacFlags.Decompile; public EUnluacFlags UnluacFlags { get => _unluacFlags; diff --git a/FModel/ViewModels/ApiEndpoints/ValorantApiEndpoint.cs b/FModel/ViewModels/ApiEndpoints/ValorantApiEndpoint.cs index fc0713c8..2a450517 100644 --- a/FModel/ViewModels/ApiEndpoints/ValorantApiEndpoint.cs +++ b/FModel/ViewModels/ApiEndpoints/ValorantApiEndpoint.cs @@ -53,7 +53,7 @@ public class VManifest Header = new VHeader(Ar); var compressedBuffer = Ar.ReadBytes((int) Header.CompressedSize); var uncompressedBuffer = new byte[(int)Header.UncompressedSize]; - ZlibHelper.Decompress(compressedBuffer, 0, compressedBuffer.Length, uncompressedBuffer, 0, uncompressedBuffer.Length); + Compression.Decompress(compressedBuffer, 0, compressedBuffer.Length, uncompressedBuffer, 0, uncompressedBuffer.Length, CompressionMethod.Zlib, Ar); var manifestAr = new FByteArchive("UncompressedValorantManifest", uncompressedBuffer); Chunks = manifestAr.ReadArray((int) Header.ChunkCount); diff --git a/FModel/ViewModels/ApplicationViewModel.cs b/FModel/ViewModels/ApplicationViewModel.cs index c16619b0..93f746c0 100644 --- a/FModel/ViewModels/ApplicationViewModel.cs +++ b/FModel/ViewModels/ApplicationViewModel.cs @@ -265,15 +265,8 @@ public class ApplicationViewModel : ViewModel { var zipDir = Path.GetDirectoryName(vgmZipFilePath)!; await using var zipFs = File.OpenRead(vgmZipFilePath); - using var zip = new ZipArchive(zipFs, ZipArchiveMode.Read); - - foreach (var entry in zip.Entries) - { - var entryPath = Path.Combine(zipDir, entry.FullName); - await using var entryFs = File.Create(entryPath); - await using var entryStream = entry.Open(); - await entryStream.CopyToAsync(entryFs); - } + await using var zip = await ZipArchive.CreateAsync(zipFs, ZipArchiveMode.Read, true, null); + await zip.ExtractToDirectoryAsync(zipDir, true); } else { @@ -305,9 +298,7 @@ public class ApplicationViewModel : ViewModel oodlePath = Path.Combine(UserSettings.Default.OutputDirectory, ".data", OodleHelper.OODLE_NAME_CURRENT); } - OodleHelper.Initialize(oodlePath); - if (OodleHelper.Instance is null) - FLogger.Append(ELog.Error, () => FLogger.Text("Failed to download Oodle", Constants.WHITE, true)); + await OodleHelper.InitializeAsync(oodlePath); } public static async Task InitZlib() @@ -319,12 +310,12 @@ public class ApplicationViewModel : ViewModel { if (!await ZlibHelper.DownloadDllAsync(zlibPath)) { - FLogger.Append(ELog.Error, () => FLogger.Text("Failed to download Zlib-ng", Constants.WHITE, true)); + zlibFileInfo.Refresh(); if (!zlibFileInfo.Exists) return; } } - ZlibHelper.Initialize(zlibPath); + await ZlibHelper.InitializeAsync(zlibPath); } public static async Task InitDetex() diff --git a/FModel/ViewModels/AudioPlayerViewModel.cs b/FModel/ViewModels/AudioPlayerViewModel.cs index 81a52065..997b986a 100644 --- a/FModel/ViewModels/AudioPlayerViewModel.cs +++ b/FModel/ViewModels/AudioPlayerViewModel.cs @@ -570,139 +570,126 @@ public class AudioPlayerViewModel : ViewModel, ISource, IDisposable { if (SelectedAudioFile?.Data == null) return false; + if (SelectedAudioFile.Extension == "wav") + return true; - switch (SelectedAudioFile.Extension) - { - case "binka": - case "adpcm": - case "xvag": - case "opus": - case "wem": - case "at9": - case "raw": - { - if (TryConvert(out var wavFilePath)) - { - var newAudio = new AudioFile(SelectedAudioFile.Id, new FileInfo(wavFilePath)); - Replace(newAudio); - return true; - } + if (!TryConvert(SelectedAudioFile.FilePath, SelectedAudioFile.Data, SelectedAudioFile.Extension, out var convertedFilePath, true)) + return false; - return false; - } - case "adx": - case "hca": - return TryConvertCriware(); - case "rada": - { - if (TryDecode(SelectedAudioFile.Extension, out var rawFilePath)) - { - var newAudio = new AudioFile(SelectedAudioFile.Id, new FileInfo(rawFilePath)); - Replace(newAudio); - return true; - } - - return false; - } - } + var newAudio = new AudioFile(SelectedAudioFile.Id, new FileInfo(convertedFilePath)); + Replace(newAudio); return true; } - private bool TryConvertCriware() + public static bool TryConvert(string inputFilePath, byte[] inputFileData, string extension, out string wavFilePath, bool updateUi = false) { + wavFilePath = string.Empty; + + switch (extension.ToLowerInvariant()) + { + case "hca": + case "adx": + return TryConvertCriware(inputFilePath, inputFileData, extension, out wavFilePath); + case "rada": + return TryConvertRada(inputFilePath, inputFileData, extension, out wavFilePath, updateUi); + default: + { + var vgmStreamPath = TryGetVgmstreamPath(); + if (string.IsNullOrEmpty(vgmStreamPath)) + return false; + + var success = TryConvertToWav(inputFilePath, inputFileData, vgmStreamPath, true, out wavFilePath); + + if (!success) + { + Log.Error("Failed to convert {InputFilePath} to .wav format", Path.GetFileName(inputFilePath)); + + if (updateUi) + { + FLogger.Append(ELog.Error, () => + { + FLogger.Text("Failed to convert audio to .wav format. See: ", Constants.WHITE); + FLogger.Link("→ link ←", Constants.AUDIO_ISSUE_LINK, true); + }); + } + } + + return success; + } + } + } + + private static bool TryConvertCriware(string inputFilePath, byte[] inputFileData, string extension, out string wavFilePath) + { + wavFilePath = string.Empty; + try { - byte[] wavData = SelectedAudioFile.Extension switch + byte[] wavData = extension switch { - "hca" => HcaWaveStream.ConvertHcaToWav( - SelectedAudioFile.Data, - UserSettings.Default.CurrentDir.CriwareDecryptionKey), - "adx" => AdxDecoder.ConvertAdxToWav( - SelectedAudioFile.Data, - UserSettings.Default.CurrentDir.CriwareDecryptionKey), + "hca" => HcaWaveStream.ConvertHcaToWav(inputFileData, UserSettings.Default.CurrentDir.CriwareDecryptionKey), + "adx" => AdxDecoder.ConvertAdxToWav(inputFileData, UserSettings.Default.CurrentDir.CriwareDecryptionKey), _ => throw new NotSupportedException() }; - if (wavData.Length is 0) + // Fallback for ADX + if (wavData.Length == 0) { - if (TryConvert(out var wavFilePathFallback)) - { - var newAudioFallback = new AudioFile(SelectedAudioFile.Id, new FileInfo(wavFilePathFallback)); - Replace(newAudioFallback); - return true; - } + var vgmStreamPath = TryGetVgmstreamPath(); + if (string.IsNullOrEmpty(vgmStreamPath)) + return false; + + return TryConvertToWav(inputFilePath, inputFileData, vgmStreamPath, true, out wavFilePath); } - string wavFilePath = Path.Combine( - UserSettings.Default.AudioDirectory, - SelectedAudioFile.FilePath.TrimStart('/')); - wavFilePath = Path.ChangeExtension(wavFilePath, ".wav"); + wavFilePath = Path.ChangeExtension(inputFilePath, ".wav"); + + var directory = Path.GetDirectoryName(wavFilePath); + if (!string.IsNullOrEmpty(directory)) + Directory.CreateDirectory(directory); - Directory.CreateDirectory(Path.GetDirectoryName(wavFilePath)!); File.WriteAllBytes(wavFilePath, wavData); - var newAudio = new AudioFile(SelectedAudioFile.Id, new FileInfo(wavFilePath)); - Replace(newAudio); - return true; } catch (CriwareDecryptionException ex) { - FLogger.Append(ELog.Error, () => FLogger.Text($"Encrypted {SelectedAudioFile.Extension.ToUpper()}: {ex.Message}", Constants.WHITE, true)); - Log.Error($"Encrypted {SelectedAudioFile.Extension.ToUpper()}: {ex.Message}"); + FLogger.Append(ELog.Error, () => FLogger.Text($"Encrypted {extension.ToUpper()}: {ex.Message}", Constants.WHITE, true)); + Log.Error($"Encrypted {extension.ToUpper()}: {ex.Message}"); + return false; } catch (Exception ex) { - FLogger.Append(ELog.Error, () => FLogger.Text($"Failed to convert {SelectedAudioFile.Extension.ToUpper()}: {ex.Message}", Constants.WHITE, true)); - Log.Error($"Failed to convert {SelectedAudioFile.Extension.ToUpper()}: {ex.Message}"); + FLogger.Append(ELog.Error, () => FLogger.Text($"Failed to convert {extension.ToUpper()}: {ex.Message}", Constants.WHITE, true)); + Log.Error($"Failed to convert {extension.ToUpper()}: {ex.Message}"); + return false; } } - private bool TryConvert(out string wavFilePath) => TryConvert(SelectedAudioFile.FilePath, SelectedAudioFile.Data, out wavFilePath, true); - public static bool TryConvert(string inputFilePath, byte[] inputFileData, out string wavFilePath, bool updateUi = false) - { - wavFilePath = string.Empty; - var vgmStreamPath = TryGetVgmstreamPath(); - if (string.IsNullOrEmpty(vgmStreamPath)) - return false; - - var success = TryConvertToWav(inputFilePath, inputFileData, vgmStreamPath, true, out wavFilePath); - - if (!success) - { - Log.Error("Failed to convert {InputFilePath} to .wav format", Path.GetFileName(inputFilePath)); - if (updateUi) - { - FLogger.Append(ELog.Error, () => - { - FLogger.Text("Failed to convert audio to .wav format. See: ", Constants.WHITE); - FLogger.Link("→ link ←", Constants.AUDIO_ISSUE_LINK, true); - }); - } - } - - return success; - } - - private bool TryDecode(string extension, out string rawFilePath) + private static bool TryConvertRada(string inputFilePath, byte[] inputFileData, string extension, out string rawFilePath, bool updateUi = false) { rawFilePath = string.Empty; var decoderPath = Path.Combine(UserSettings.Default.OutputDirectory, ".data", $"{extension}dec.exe"); if (!File.Exists(decoderPath)) { - Log.Error("Failed to convert {FilePath}, rada decoder is missing", SelectedAudioFile.FilePath); - FLogger.Append(ELog.Error, () => + Log.Error("Failed to convert {FilePath}, {Extension} decoder is missing", inputFilePath, extension); + + if (updateUi) { - FLogger.Text("Failed to convert audio because rada decoder is missing. See: ", Constants.WHITE); - FLogger.Link("→ link ←", Constants.RADA_ISSUE_LINK, true); - }); + FLogger.Append(ELog.Error, () => + { + FLogger.Text($"Failed to convert audio because {extension} decoder is missing. See: ", Constants.WHITE); + FLogger.Link("→ link ←", Constants.RADA_ISSUE_LINK, true); + }); + } + return false; } - return TryConvertToWav(SelectedAudioFile.FilePath, SelectedAudioFile.Data, decoderPath, false, out rawFilePath); + return TryConvertToWav(inputFilePath, inputFileData, decoderPath, false, out rawFilePath); } private static bool TryConvertToWav(string inputFilePath, byte[] inputFileData, string converterPath, bool usevgmstream, out string wavFilePath) diff --git a/FModel/ViewModels/CUE4ParseViewModel.cs b/FModel/ViewModels/CUE4ParseViewModel.cs index a4363437..f20cd939 100644 --- a/FModel/ViewModels/CUE4ParseViewModel.cs +++ b/FModel/ViewModels/CUE4ParseViewModel.cs @@ -26,6 +26,7 @@ using CUE4Parse.GameTypes.Borderlands4.Wwise; using CUE4Parse.GameTypes.DFHO.Assets.Objects; using CUE4Parse.GameTypes.HonorOfKings.FileProvider; using CUE4Parse.GameTypes.KRD.Assets.Exports; +using CUE4Parse.GameTypes.LegoBatman.Assets; using CUE4Parse.GameTypes.RocoKingdomWorld.Assets.Objects; using CUE4Parse.GameTypes.SMG.UE4.Assets.Exports.Wwise; using CUE4Parse.GameTypes.SquareEnix.UE4.Assets.Exports; @@ -65,7 +66,6 @@ using CUE4Parse_Conversion; using CUE4Parse_Conversion.Sounds; using EpicManifestParser; using EpicManifestParser.UE; -using EpicManifestParser.ZlibngDotNetDecompressor; using FModel.Creator; using FModel.Extensions; using FModel.Framework; @@ -94,6 +94,8 @@ public class CUE4ParseViewModel : ViewModel private readonly Regex _fnLiveRegex = new(@"^FortniteGame[/\\]Content[/\\]Paks[/\\]", RegexOptions.Compiled | RegexOptions.Singleline | RegexOptions.IgnoreCase | RegexOptions.CultureInvariant); + private static readonly HttpClient _chunkClient = ManifestParseOptions.CreateDefaultClient(); + private bool _modelIsOverwritingMaterial; public bool ModelIsOverwritingMaterial { @@ -224,9 +226,9 @@ public class CUE4ParseViewModel : ViewModel { Provider.OnDemandOptions = new IoStoreOnDemandOptions { - ChunkHostUri = new Uri("https://download.epicgames.com/", UriKind.Absolute), + ChunkHostUri = new Uri("https://egdownload.fastly-edge.com/", UriKind.Absolute), ChunkCacheDirectory = Directory.CreateDirectory(Path.Combine(UserSettings.Default.OutputDirectory, ".data")), - Timeout = TimeSpan.FromSeconds(30) + DownloaderClient = _chunkClient }; switch (Provider) @@ -247,9 +249,9 @@ public class CUE4ParseViewModel : ViewModel { ChunkCacheDirectory = cacheDir, ManifestCacheDirectory = cacheDir, - ChunkBaseUrl = "http://download.epicgames.com/Builds/Fortnite/CloudDir/", - Decompressor = ManifestZlibngDotNetDecompressor.Decompress, - DecompressorState = ZlibHelper.Instance, + ChunkBaseUrl = "https://egdownload.fastly-edge.com/Builds/Fortnite/CloudDir/", + Decompressor = Compression.Decompressor, + Client = _chunkClient, CacheChunksAsIs = false }; @@ -260,7 +262,7 @@ public class CUE4ParseViewModel : ViewModel { (manifest, _) = manifestInfo.DownloadAndParseAsync(manifestOptions, cancellationToken: cancellationToken, - elementManifestPredicate: static x => x.Uri.Host == "download.epicgames.com" + elementDownloadPredicate: static x => x.Uri.Host is "egdownload.fastly-edge.com" or "epicgames-download1.akamaized.net" or "download.epicgames.com" ).GetAwaiter().GetResult(); } catch (HttpRequestException ex) @@ -400,6 +402,16 @@ public class CUE4ParseViewModel : ViewModel }); } + private ITypeMappingsProvider SelectMappingsProvider(string path) + { + if (path.EndsWith(".jmap.gz", StringComparison.OrdinalIgnoreCase) || path.EndsWith(".jmap", StringComparison.OrdinalIgnoreCase)) + { + return new JmapTypeMappingsProvider(path); + } + + return new FileUsmapTypeMappingsProvider(path); + } + public Task InitMappings(bool force = false) { if (!UserSettings.IsEndpointValid(EEndpointType.Mapping, out var endpoint)) @@ -413,7 +425,7 @@ public class CUE4ParseViewModel : ViewModel var l = ELog.Information; if (endpoint.Overwrite && File.Exists(endpoint.FilePath)) { - Provider.MappingsContainer = new FileUsmapTypeMappingsProvider(endpoint.FilePath); + Provider.MappingsContainer = SelectMappingsProvider(endpoint.FilePath); } else if (endpoint.IsValid) { @@ -439,7 +451,7 @@ public class CUE4ParseViewModel : ViewModel _apiEndpointView.DownloadFile(mapping.Url, mappingPath); } - Provider.MappingsContainer = new FileUsmapTypeMappingsProvider(mappingPath); + Provider.MappingsContainer = SelectMappingsProvider(mappingPath); break; } } @@ -722,6 +734,7 @@ public class CUE4ParseViewModel : ViewModel case "archive": case "dnearchive": // Banishers: Ghosts of New Eden case "gitignore": + case "gitattributes": case "LICENSE": case "playstats": // Dispatch case "template": @@ -780,6 +793,8 @@ public class CUE4ParseViewModel : ViewModel case "bl": case "bm": case "br": + case "sql": + case "cs": { var data = Provider.SaveAsset(entry); using var stream = new MemoryStream(data) { Position = 0 }; @@ -789,6 +804,7 @@ public class CUE4ParseViewModel : ViewModel break; } + case "ebd" when Provider.Versions.Game is EGame.GAME_ArcRaiders: case "json": { var data = Provider.SaveAsset(entry); @@ -1018,9 +1034,25 @@ public class CUE4ParseViewModel : ViewModel var nonPath = Provider.Files.Keys.FirstOrDefault(k => k.EndsWith(nonFileName, StringComparison.OrdinalIgnoreCase)); // I will only get one localization file because they did not translate any languages, lol - var locPathKey = entry.Path.Replace("/BinData/", "/BinLocalize/en_US/").Replace("/BinDataCompressed/", "/BinLocalize/en_US/"); + var locPathKey = entry.Path.Replace("/BinData/", "/BinLocalize/zh_Hans/").Replace("/BinDataCompressed/", "/BinLocalize/zh_Hans/"); var locFileFound = Provider.Files.TryGetValue(locPathKey, out var locEntry); + if (entry.Path is "NRC/Content/ScriptC/Data/Audio/dataconfig_audio.bytes") + { + var descFound = Provider.Files.TryGetValue("NRC/Content/ScriptC/Data/Audio/dataconfig_audiodesc.bytes", out var descEntry); + var typeDescFound = Provider.Files.TryGetValue("NRC/Content/ScriptC/Data/Audio/typeDesc.bytes", out var typeDescEntry); + + if (!descFound || !typeDescFound) + { + Log.Warning("Could not find associated dataconfig_audiodesc.bytes or typeDesc.bytes, cannot parse audio config"); + return; + } + + var data = new FRocoAudioConfig(entry.CreateReader(), descEntry.CreateReader(), typeDescEntry.CreateReader()); + TabControl.SelectedTab.SetDocumentText(JsonConvert.SerializeObject(data, Formatting.Indented), saveProperties, updateUi); + return; + } + if (!string.IsNullOrEmpty(nonPath) && Provider.Files.TryGetValue(nonPath, out var nonEntry)) { string json = Encoding.UTF8.GetString(nonEntry.Read()); @@ -1309,8 +1341,7 @@ public class CUE4ParseViewModel : ViewModel _ => [] }; - var directory = Path.GetDirectoryName(atomObject.Owner?.Name) ?? "/Criware/"; - directory = Path.GetDirectoryName(atomObject.Owner.Provider.FixPath(directory)); + var directory = Path.GetDirectoryName(Provider.FixPath(atomObject.Owner?.Name ?? "/Criware/")); foreach (var sound in extractedSounds) { SaveAndPlaySound(cancellationToken, Path.Combine(directory, sound.Name).Replace("\\", "/"), sound.Extension, sound.Data, saveAudio, updateUi); @@ -1321,8 +1352,8 @@ public class CUE4ParseViewModel : ViewModel { var data = squareEnixObject switch { - USQEXSEADSoundBank sqexSoundBank => sqexSoundBank.SQEXSoundBankData?.Data ?? [], - USQEXSEADSound sqexSound => sqexSound.SQEXSoundData?.Data ?? [], + USQEXSEADSoundBank sqexSoundBank => sqexSoundBank.SQEXSoundBankData?.ReadDataOnce() ?? [], + USQEXSEADSound sqexSound => sqexSound.SQEXSoundData?.ReadDataOnce() ?? [], _ => [], }; var sabPath = Path.Combine(TabControl.SelectedTab.Entry.PathWithoutExtension.Replace('\\', '/').SubstringBeforeLast('/'), squareEnixObject.Name); @@ -1427,6 +1458,27 @@ public class CUE4ParseViewModel : ViewModel return false; } + // LEGO® Batman™: Legacy of the Dark Knight + case UWubAudioEvent when (isNone || saveAudio) && pointer.Object.Value is UWubAudioEvent wubAudioEvent: + { + var extractedSounds = WwiseProvider.ExtractWubAudioEventSounds(wubAudioEvent); + foreach (var sound in extractedSounds) + { + SaveAndPlaySound(cancellationToken, sound.OutputPath, sound.Extension, sound.Data?.GetData() ?? [], saveAudio, updateUi); + } + return false; + } + case UWubDialogueEvent when (isNone || saveAudio) && pointer.Object.Value is UWubDialogueEvent wubDialogueEvent: + { + var files = wubDialogueEvent.Wems + .SelectMany(wem => Provider.Files.Values.Where(file => file.Path.EndsWith(wem.Text + ".wem", StringComparison.OrdinalIgnoreCase))) + .ToList(); + foreach (var entry in files) + { + SaveAndPlaySound(cancellationToken, entry.PathWithoutExtension, entry.Extension, entry.Read(), saveAudio, updateUi); + } + return false; + } case UWorld when isNone && UserSettings.Default.PreviewWorlds: case UBlueprintGeneratedClass when isNone && UserSettings.Default.PreviewWorlds && TabControl.SelectedTab.ParentExportType switch { @@ -1583,7 +1635,7 @@ public class CUE4ParseViewModel : ViewModel bool conversionSuccess = true; if (UserSettings.Default.ConvertAudioOnBulkExport && extLower is not "wav") { - if (AudioPlayerViewModel.TryConvert(savedAudioPath, data, out string wavFilePath)) + if (AudioPlayerViewModel.TryConvert(savedAudioPath, data, extLower, out string wavFilePath)) savedAudioPath = wavFilePath; else { diff --git a/FModel/ViewModels/GameFileViewModel.cs b/FModel/ViewModels/GameFileViewModel.cs index 8f336ece..6bac2c92 100644 --- a/FModel/ViewModels/GameFileViewModel.cs +++ b/FModel/ViewModels/GameFileViewModel.cs @@ -10,6 +10,7 @@ using CUE4Parse.FileProvider.Objects; using CUE4Parse.GameTypes.Borderlands3.Assets.Exports; using CUE4Parse.GameTypes.Borderlands4.Assets.Exports; using CUE4Parse.GameTypes.FN.Assets.Exports.DataAssets; +using CUE4Parse.GameTypes.LegoBatman.Assets; using CUE4Parse.GameTypes.SMG.UE4.Assets.Exports.Wwise; using CUE4Parse.GameTypes.SMG.UE4.Assets.Objects; using CUE4Parse.GameTypes.SquareEnix.UE4.Assets.Exports; @@ -263,6 +264,7 @@ public class GameFileViewModel(GameFile asset) : ViewModel UBorderlandsDialogObject when GameVersion is EGame.GAME_Borderlands3 => (EAssetCategory.Borderlands, EBulkType.None), // Borderlands 3; UGbxGraphAsset or UDialogScriptData or UDialogPerformanceData when GameVersion is EGame.GAME_Borderlands4 or EGame.GAME_Borderlands3 => (EAssetCategory.Borderlands, EBulkType.Audio), // Borderlands 4; Borderlands 3; UFaceFXAnimSet when GameVersion is EGame.GAME_Borderlands4 => (EAssetCategory.Borderlands, EBulkType.Audio), // Borderlands 4; + UWubAudioEvent or UWubDialogueEvent when GameVersion is EGame.GAME_LEGOBatmanLegacyoftheDarkKnight => (EAssetCategory.LegoBatman, EBulkType.Audio), // Lego Batman: Legacy of the Dark Knight; _ => (EAssetCategory.All, EBulkType.None), }; @@ -350,11 +352,15 @@ public class GameFileViewModel(GameFile asset) : ViewModel case "pem": case "xml": case "gitignore": + case "gitattributes": case "html": case "css": case "js": case "data": case "csv": + case "sql": + case "py": + case "cs": AssetCategory = EAssetCategory.Data; break; case "stinfo": diff --git a/FModel/Views/Resources/Colors.xaml b/FModel/Views/Resources/Colors.xaml index eb034871..bd8a6d85 100644 --- a/FModel/Views/Resources/Colors.xaml +++ b/FModel/Views/Resources/Colors.xaml @@ -48,10 +48,14 @@ + + + + diff --git a/FModel/Views/Resources/Controls/DropOverlay.xaml.cs b/FModel/Views/Resources/Controls/DropOverlay.xaml.cs index ec6d4ca4..faacc412 100644 --- a/FModel/Views/Resources/Controls/DropOverlay.xaml.cs +++ b/FModel/Views/Resources/Controls/DropOverlay.xaml.cs @@ -68,7 +68,7 @@ public partial class DropOverlay : UserControl } else if (_dragStatus is DragStatus.File) { - TitleText.Text = "Drop .usmap to import"; + TitleText.Text = "Drop usmap/jmap to import"; DescriptionText.Text = "Mapping file will be applied immediately"; } } @@ -125,7 +125,6 @@ public partial class DropOverlay : UserControl if (!_applicationView.Status.IsReady || !e.Data.GetDataPresent(DataFormats.FileDrop) || e.Data.GetData(DataFormats.FileDrop) is not string[] files) return; - bool directorySelectorIsVisible = _applicationView.Status.Kind is EStatusKind.Configuring; if (!directorySelectorIsVisible && (Helper.IsWindowOpen() || Helper.IsWindowOpen())) { @@ -145,7 +144,9 @@ public partial class DropOverlay : UserControl _dragStatus = DragStatus.Folder; return; } - else if (File.Exists(path) && Path.GetExtension(path).Equals(".usmap", StringComparison.OrdinalIgnoreCase)) + else if (File.Exists(path) && path.EndsWith(".usmap", StringComparison.OrdinalIgnoreCase) || + path.EndsWith(".jmap", StringComparison.OrdinalIgnoreCase) || + path.EndsWith(".jmap.gz", StringComparison.OrdinalIgnoreCase)) { _path = path; _dragStatus = DragStatus.File; diff --git a/FModel/Views/Resources/Converters/FileToGeometryConverter.cs b/FModel/Views/Resources/Converters/FileToGeometryConverter.cs index cd620def..f5759955 100644 --- a/FModel/Views/Resources/Converters/FileToGeometryConverter.cs +++ b/FModel/Views/Resources/Converters/FileToGeometryConverter.cs @@ -80,10 +80,14 @@ public class FileToGeometryConverter : IMultiValueConverter "bin" => ("DataTableIcon", "BinaryBrush"), "xml" => ("XmlIcon", "JsonXmlBrush"), "gitignore" => ("GitIcon", "GitBrush"), + "gitattributes" => ("GitIcon", "GitBrush"), "html" => ("HtmlIcon", "HtmlBrush"), "js" => ("JavaScriptIcon", "JavaScriptBrush"), "css" => ("CssIcon", "CssBrush"), "csv" => ("CsvIcon", "CsvBrush"), + "sql" => ("SQLIcon", "SQLBrush"), + "py" => ("PythonIcon", "PythonBrush"), + "cs" => ("CSharpIcon", "CSharpBrush"), _ => ("DataTableIcon", "NeutralBrush") }, @@ -93,6 +97,7 @@ public class FileToGeometryConverter : IMultiValueConverter EAssetCategory.Aion2 => ("AionIcon", "AionBrush"), EAssetCategory.RocoKingdomWorld => ("RocoKingdomWorldIcon", "RocoKingdomWorldBrush"), EAssetCategory.DeltaForce => ("DeltaForceIcon", "DeltaForceBrush"), + EAssetCategory.LegoBatman => ("BatmanIcon", "BatmanBrush"), _ => ("AssetIcon", "NeutralBrush") }; diff --git a/FModel/Views/Resources/Icons.xaml b/FModel/Views/Resources/Icons.xaml index 59505988..b46d3ece 100644 --- a/FModel/Views/Resources/Icons.xaml +++ b/FModel/Views/Resources/Icons.xaml @@ -99,10 +99,14 @@ M14 2H6C4.9 2 4 2.9 4 4V20C4 21.1 4.9 22 6 22H18C19.1 22 20 21.1 20 20V8L14 2M15 16L13 20H10L12 16H9V11H15V16M13 9V3.5L18.5 9H13Z M12,2A2,2 0 0,1 14,4C14,4.74 13.6,5.39 13,5.73V7H14A7,7 0 0,1 21,14H22A1,1 0 0,1 23,15V18A1,1 0 0,1 22,19H21V20A2,2 0 0,1 19,22H5A2,2 0 0,1 3,20V19H2A1,1 0 0,1 1,18V15A1,1 0 0,1 2,14H3A7,7 0 0,1 10,7H11V5.73C10.4,5.39 10,4.74 10,4A2,2 0 0,1 12,2M7.5,13A2.5,2.5 0 0,0 5,15.5A2.5,2.5 0 0,0 7.5,18A2.5,2.5 0 0,0 10,15.5A2.5,2.5 0 0,0 7.5,13M16.5,13A2.5,2.5 0 0,0 14,15.5A2.5,2.5 0 0,0 16.5,18A2.5,2.5 0 0,0 19,15.5A2.5,2.5 0 0,0 16.5,13Z M14,12L10,8V11H2V13H10V16M20,18V6C20,4.89 19.1,4 18,4H6A2,2 0 0,0 4,6V9H6V6H18V18H6V15H4V18A2,2 0 0,0 6,20H18A2,2 0 0,0 20,18Z - + M231.822 132.778c1.2-5.152 6.352-8.357 11.505-7.158 5.153 1.2 8.357 6.352 7.158 11.505l-20.773 88.972c-1.199 5.153-6.352 8.358-11.504 7.158-5.153-1.199-8.358-6.352-7.158-11.505l20.772-88.972zM21.123 259.247h16.714V52.395C37.837 23.601 61.438 0 90.232 0h230.505a7.998 7.998 0 016.39 3.183l96.876 104.809a7.937 7.937 0 012.118 5.411h.041v145.844h16.714c11.618 0 21.124 9.525 21.124 21.124v163.863c0 11.599-9.526 21.124-21.124 21.124h-17.058c-3.001 25.877-25.473 46.505-52.051 46.505H90.232c-26.72 0-49.082-20.526-52.055-46.505H21.123C9.526 465.358 0 455.853 0 444.234V280.371c0-11.619 9.506-21.124 21.123-21.124zm32.731 0h356.292V136.525h-32.219v-.033h-.124c-19.111-.302-34.068-5.373-44.736-14.486-11.073-9.458-17.282-22.969-18.52-39.763l-.075-1.098V16.016H90.232c-20.032 0-36.378 16.346-36.378 36.379v206.852zm355.795 206.111H54.344c2.862 17.157 17.981 30.488 35.888 30.488h283.535c17.803 0 32.993-13.394 35.882-30.488zM330.467 30.272V81.11c.913 12.412 5.265 22.192 12.97 28.775 7.822 6.682 19.34 10.418 34.49 10.676v-.03h32.219v-4.052l-79.679-86.207zM199.303 204.095c3.972 3.477 4.377 9.521.9 13.493-3.478 3.973-9.521 4.377-13.494.9l-36.354-31.854c-3.972-3.477-4.377-9.521-.9-13.493.295-.336.606-.644.933-.927l36.321-31.826c3.973-3.478 10.016-3.073 13.494.899 3.477 3.973 3.072 10.016-.9 13.494l-28.14 24.656 28.14 24.658zm77.99 14.393c-3.972 3.477-10.016 3.073-13.493-.9-3.478-3.972-3.073-10.016.899-13.493l28.14-24.658-28.14-24.656c-3.972-3.478-4.377-9.521-.899-13.494 3.477-3.972 9.521-4.377 13.493-.899l36.318 31.826c.328.283.639.591.933.927 3.477 3.972 3.073 10.016-.899 13.493l-36.352 31.854zM120.405 400.89l3.805-19.455c8.333 2.083 15.827 3.123 22.484 3.123 6.66 0 12.024-.27 16.101-.815v-9.755l-12.228-1.086c-11.051-.999-18.635-3.648-22.759-7.951-4.121-4.302-6.181-10.665-6.181-19.089 0-11.592 2.514-19.565 7.54-23.911 5.029-4.35 13.565-6.523 25.612-6.523 12.047 0 22.915 1.134 32.61 3.398l-3.398 18.978c-8.423-1.358-15.171-2.038-20.244-2.038s-9.375.226-12.908.68v9.416l9.783.952c11.865 1.177 20.063 4.008 24.591 8.492 4.531 4.484 6.795 10.71 6.795 18.682 0 5.706-.77 10.528-2.311 14.47-1.541 3.94-3.373 6.927-5.502 8.966-2.129 2.038-5.141 3.601-9.037 4.687-3.892 1.087-7.312 1.745-10.255 1.97-2.944.228-6.864.341-11.755.341-11.775 0-22.688-1.177-32.743-3.532zm128.036-1.631l-11.548 3.125c-15.219 0-25.414-3.926-30.707-11.684-2.674-3.923-4.621-8.266-5.708-13.111-1.087-4.844-1.628-10.712-1.628-17.595 0-15.491 2.899-26.789 8.695-33.9 5.797-7.109 16.212-10.666 31.249-10.666 15.036 0 25.498 3.579 31.386 10.734 5.887 7.156 8.83 18.432 8.83 33.832 0 11.502-2.399 20.786-7.199 27.851l9.782 5.708-7.067 15.623-26.085-4.754v-5.163zm-20.382-18.072h11.279c3.714 0 6.407-.429 8.083-1.29 1.675-.861 2.514-2.83 2.514-5.909v-35.325h-11.414c-3.62 0-6.272.429-7.947 1.29-1.675.861-2.515 2.834-2.515 5.909v35.325zm115.536 21.197h-54.349v-84.917h27.175v63.179h27.174v21.738z + M19.14,7.5A2.86,2.86 0 0,1 22,10.36V14.14A2.86,2.86 0 0,1 19.14,17H12C12,17.39 12.32,17.96 12.71,17.96H17V19.64A2.86,2.86 0 0,1 14.14,22.5H9.86A2.86,2.86 0 0,1 7,19.64V15.89C7,14.31 8.28,13.04 9.86,13.04H15.11C16.69,13.04 17.96,11.76 17.96,10.18V7.5H19.14M14.86,19.29C14.46,19.29 14.14,19.59 14.14,20.18C14.14,20.77 14.46,20.89 14.86,20.89A0.71,0.71 0 0,0 15.57,20.18C15.57,19.59 15.25,19.29 14.86,19.29M4.86,17.5C3.28,17.5 2,16.22 2,14.64V10.86C2,9.28 3.28,8 4.86,8H12C12,7.61 11.68,7.04 11.29,7.04H7V5.36C7,3.78 8.28,2.5 9.86,2.5H14.14C15.72,2.5 17,3.78 17,5.36V9.11C17,10.69 15.72,11.96 14.14,11.96H8.89C7.31,11.96 6.04,13.24 6.04,14.82V17.5H4.86M9.14,5.71C9.54,5.71 9.86,5.41 9.86,4.82C9.86,4.23 9.54,4.11 9.14,4.11C8.75,4.11 8.43,4.23 8.43,4.82C8.43,5.41 8.75,5.71 9.14,5.71Z + M7878 15350 c-162 -15 -335 -63 -471 -131 -146 -74 -5492 -3082 -5567 -3133 -41 -28 -120 -96 -175 -151 -189 -189 -307 -411 -362 -682 -17 -84 -18 -245 -18 -3253 0 -3008 1 -3169 18 -3253 50 -249 159 -466 323 -645 64 -71 188 -173 269 -224 102 -64 5469 -3075 5535 -3106 367 -170 814 -166 1165 10 75 38 5370 3012 5482 3079 326 196 543 505 620 886 17 84 18 245 18 3253 0 3008 -1 3169 -18 3253 -55 271 -173 493 -362 682 -55 55 -134 123 -175 151 -75 51 -5421 3059 -5568 3133 -203 102 -479 152 -714 131z m591 -3534 c526 -70 1018 -235 1456 -489 298 -172 642 -446 866 -689 117 -126 259 -298 259 -312 -1 -6 -301 -184 -667 -396 -366 -212 -680 -393 -697 -403 l-31 -18 -85 82 c-583 568 -1404 778 -2184 559 -501 -141 -952 -471 -1245 -910 -249 -373 -374 -786 -374 -1240 0 -372 82 -709 250 -1030 337 -644 947 -1075 1678 -1185 133 -21 439 -23 570 -6 499 66 958 288 1304 631 l84 82 32 -18 c892 -514 1364 -791 1365 -800 1 -32 -300 -365 -462 -511 -583 -528 -1275 -856 -2043 -967 -200 -29 -382 -39 -638 -33 -277 6 -411 20 -672 72 -1512 301 -2719 1521 -3009 3040 -52 276 -61 378 -61 725 0 355 9 453 66 747 255 1307 1201 2410 2461 2867 312 113 669 190 1018 220 118 10 641 -2 759 -18z m3371 -2536 l0 -320 320 0 320 0 0 320 0 320 320 0 320 0 0 -320 0 -320 320 0 320 0 0 -320 0 -320 -320 0 -320 0 0 -320 0 -320 320 0 320 0 0 -320 0 -320 -320 0 -320 0 0 -320 0 -320 -320 0 -320 0 0 320 0 320 -320 0 -320 0 0 -320 0 -320 -320 0 -320 0 0 320 0 320 -320 0 -320 0 0 320 0 320 320 0 320 0 0 320 0 320 -320 0 -320 0 0 320 0 320 320 0 320 0 0 320 0 320 320 0 320 0 0 -320z M11840 8000 l0 -320 320 0 320 0 0 320 0 320 -320 0 -320 0 0 -320z + M13,9V3.5L18.5,9M6,2C4.89,2 4,2.89 4,4V20A2,2 0 0,0 6,22H18A2,2 0 0,0 20,20V8L14,2H6 ZM12,11A3,3 0 1,0 12,17A3,3 0 0,0 12,11 ZM12,12.5L14,16H13L12,14.5L11,16H10L12,12.5Z M609 180.1c-19.4 2.3-38.2 7.8-56.5 16.8-53.8 26.5-89.2 74.9-98.7 135.1-1.1 7-1.3 133.1-1.3 739 0 693.9.1 731 1.8 741.4 12.8 79.4 70.7 137.8 149.2 150.6 11.8 2 20.6 2 563.5 2s551.7 0 563.5-2c57.2-9.3 104-43 130.8-94.1 9.1-17.2 14.6-33.9 18.4-55.4 1.6-9.4 1.8-40.6 2-554l.3-544-268.2-268.2L1345.5 179l-364.5.1c-200.5.1-367.9.5-372 1m893 378.4L1747.5 804H1256V558.5c0-135 .1-245.5.3-245.5.1 0 110.7 110.5 245.7 245.5m-792.1 532c24.5 1.3 47 2.9 49.8 3.4 7.1 1.3 12.8 5.5 22.5 16.4 6.4 7.3 9.2 11.5 13.6 20.7 9.2 19.4 21.4 47.2 44.4 101.5 27.5 65.1 39.7 92.3 55.5 124 6.9 13.7 16.1 32.9 20.5 42.5 8.2 17.9 15.4 31.9 18.3 35.5 1.5 1.8 1.5-7.2.9-109-.6-108.7-.7-111.1-2.7-116.5-3.1-8.3-10-14.5-24.7-22-10.1-5.1-11.9-6.4-10.9-7.6 1.6-2 5.8-1.8 21.3 1.1 19.3 3.6 39.1 4.5 97.7 4.5 42.1 0 51.9.3 53.4 1.4 1.8 1.3 1.8 1.4-.1 1.9-1 .3-3.9.8-6.4 1.2s-8.5 1.7-13.5 3c-4.9 1.3-12.1 2.6-16 3-7.9.8-14.3 3.2-18 6.9l-2.5 2.5v123.7c0 121.8 0 123.8 2 125.9 1.4 1.5 2.1 4.1 2.6 9.2.8 8.1 2.2 10.1 12.6 17.2 9.3 6.5 9.3 6.5-26.7 7.3-17.6.4-45.3.7-61.5.5-29.2-.2-29.5-.2-29.8-2.3-.2-1.7.7-2.5 5.5-4.5 3.2-1.3 7.5-4.1 9.8-6.4 4.5-4.5 8.3-11 7.2-12.2-1.3-1.2-72.8-1.6-90.2-.5-13.5.9-16.2.8-17.5-.4-1.9-1.9-.9-2.7 8-6.4 9.8-4.1 11-5.2 11-11 0-3.9-3.7-13.2-22.3-56.1l-22.3-51.4-4.5-.6c-13.1-2-52.1-3.1-69.3-2-14.4.9-38.5 3.6-39.3 4.4-.1.1-5.6 13.5-12.3 29.7s-16 38.7-20.7 50c-7.4 17.9-8.5 21.1-8.1 25.1.6 5.6 3.9 10.3 10.2 14.3 4.8 3 5.8 5.1 2.9 5.8-1 .2-10.6 0-21.3-.5-21.7-.9-83.9-.2-108.4 1.3-22.1 1.4-22.5.3-1.7-5 17.9-4.6 33.3-9.6 42.4-13.7l7.7-3.6 6.9-13.1c3.8-7.2 14.2-27.5 23.1-45.2 17.9-35.6 19-38.9 15.5-47.9-1-2.7-1.4-5.6-1.1-7.1.4-1.5 8.1-10.1 17.5-19.8 9.2-9.4 17.6-18.6 18.5-20.4s6.4-15.7 12.2-30.8c5.7-15.1 17.9-46.7 27.1-70.2l16.6-42.7-9.3-18.2c-5.1-10-10.7-19.8-12.5-21.6-6-6.1-16.6-9.9-32-11.4-7.8-.8-8-.9-8.3-3.6s-.3-2.7 5.9-2.7c3.5 0 26.3 1.1 50.8 2.5m999.3 20.4c3 5.2 4.8 10.9 9.7 31 8.8 35.5 11.8 55.6 14.2 93.1 1.5 24.1.6 87-1.5 108-1.8 17.4-4.4 37.5-5.3 40.5-.3 1.3-.2 1.7.5 1 1.2-1.2 11.9-33.8 16.2-49.5 1.8-6.3 3.7-12.4 4.2-13.4 3.4-6.4 2.2 14.4-2 34.9-1.3 6.3-1.5 9.6-.9 10.7 2.1 3.3-9.4 55.8-18.3 83.3-5.5 17.2-15.6 42.7-18.1 45.9-1.1 1.5-2.6 2.3-3.4 1.9-.8-.3-5.7-6.9-10.9-14.7-17.4-26.2-33.3-45.2-60.7-72.1-16.4-16.1-29.1-27.5-45.6-41-4-3.2-7.5-6.5-7.8-7.3-1.2-3.2 5.5.3 19.9 10.4 8.1 5.8 15 10.3 15.2 10.2.4-.5-17.3-14.6-37.1-29.4-43.5-32.7-81.4-58.4-86.1-58.4-1.3 0-1.4 9.9-.8 86.7.4 61.2 1 87.5 1.8 89.3 1.4 3.1 7.5 7.2 14 9.5 6.9 2.4 7.6 3.2 4.6 5.5-2.4 1.9-5 2-74.2 2-45.3 0-71.8-.4-71.8-1 0-.9 3.2-1.9 12-3.9 9.2-2.1 22.3-6.2 26.9-8.6 7.6-3.8 8.9-8.7 10.1-38 1.3-29.8 2.5-203 1.5-217.8-.7-11.3-.9-12-3.8-15.3-1.6-1.9-4.3-4.2-6-5-5.1-2.7-24.7-6.3-42.9-7.9-9.7-.8-18.4-1.8-19.2-2.1-1.4-.5-2.2-2-1.3-2.6.3-.2 73.8-1.9 90.7-2.1 12.6-.2 13.9-.4 19.5-3 4.8-2.3 8.6-3.1 19.5-4.2 18.5-1.9 34.2-2.3 34.7-.9.3 1-2.3 4.6-10.9 14.7l-3.3 3.9-.3 20.2-.3 20.2 5.7 8c17.5 24.5 49.6 55.6 93.9 91 20 16.1 58.7 45.6 59.1 45.1.7-.7 6.5-38.1 8.5-55.7 3-25 3.3-66.8.6-84-2.5-16.2-9.6-43-11.4-43-.2 0-8.1 7.2-17.5 16.1-9.3 8.8-17.2 15.8-17.5 15.5s2.7-4.5 6.8-9.3c13-15.6 35.1-41.7 37.2-44.1 1.1-1.2 1.8-2.2 1.4-2.2-.3 0-16.9 17-36.8 37.7-37.3 38.8-41.5 43-42.6 41.9-.8-.8-4.1 3.1 54-63.3 28.4-32.6 51.7-59.6 51.7-59.9s-3.2 2.3-7 5.7c-14.3 12.9-15.9 13.8-7.5 4.4 16.1-18.1 32.8-35.6 33.9-35.2.6.2 2.8 3.2 4.8 6.6m-578.4 94.3c-.3.7-5 4.4-10.5 8.3-13.5 9.4-17.7 12.9-31.6 26.4-8.1 8-13.5 14.2-17.6 20.5-6.8 10.7-11.5 18.6-10.9 18.6.3 0 2-2.1 3.8-4.8 5.1-7.1 19.5-21.6 28.5-28.7 24.4-19.1 53.7-31.3 89-37.2 13.7-2.2 53.7-2.5 68.5-.5 45.5 6.4 82.4 22.6 109.1 48 26 24.7 40.4 54.7 45 93.7 1.7 14.2.6 42.3-2.1 54.9-8.5 39.6-25.4 68.8-53.5 92.6-15.5 13-29.1 20.9-45.7 26.5-18.4 6.1-35.4 7.7-56 5.3l-10.3-1.3 10.5-.6c11.4-.8 27.2-3.2 31.1-4.9 2.3-.9 2.2-1-.6-.5-15.1 2.4-38.9 3.2-48.9 1.5-11.5-1.9-10.1-4 6.3-9.9 6.2-2.3 15.4-6.2 20.4-8.8 56.5-29.2 84.7-97.9 69.1-168.3-11.5-51.5-43.4-85-89.3-93.6-11.4-2.1-32.9-2.2-44.2 0-40.6 7.7-70 34.9-84.5 78.1-5.8 17.5-7.7 31.8-7.1 54 .6 21.3 2.2 32.3 7.3 49.2 11.8 39 34.4 64.6 78.4 88.7 4.7 2.6 9.6 5.8 11 7.1 2.3 2.4 2.4 2.6.7 4.2-1.6 1.6-3.8 1.8-17 1.7-45.3-.2-82.1-18.2-112.6-55-4.2-5.1-9.6-12.4-12.1-16.2-2.5-3.9-4.9-7.1-5.4-7.1-.5-.1-.6 3.7-.3 8.5l.5 8.5-2.4-2.2c-3-2.8-10.5-17.2-14.3-27.7-7.2-19.5-12.1-46.9-12.1-67.8 0-30.8 5.7-56.3 18.5-81.9 16.2-32.6 43.1-58.4 79-75.7 10.3-4.9 13-5.7 12.3-3.6 M731 1231.2c-6.2 15.5-15.9 40.1-21.6 54.5-5.7 14.5-10.4 26.7-10.4 27.2 0 1.5 7.9 2 39 2.7 26.5.5 51.1-.3 52.6-1.8.6-.6-46.1-108.6-47.5-110.1-.5-.5-5.9 11.9-12.1 27.5 M 502.181 171.548 C 525.284 169.507 563.415 170.739 587.926 170.743 L 742.884 170.756 L 1028.85 170.763 C 1076.75 170.756 1124.66 170.622 1172.54 170.748 C 1178.78 170.765 1192.74 170.614 1197.23 174.349 C 1215.13 189.269 1234.07 209.589 1250.41 225.973 L 1371.16 346.803 L 1615.35 591.041 L 1670.89 646.405 C 1678.93 654.353 1701.51 675.779 1706.9 684.287 C 1707.13 687.508 1707.32 690.732 1707.47 693.959 C 1708.56 717.921 1707.73 747.055 1707.7 771.499 L 1707.66 909.749 L 1707.66 1342.96 L 1707.7 1593.56 L 1707.7 1663.97 C 1707.69 1686.9 1708.2 1709.99 1704.64 1732.73 C 1692 1813.63 1623.54 1873.01 1542.18 1876.37 C 1535.7 1877.17 1529.19 1877.65 1522.67 1877.81 C 1497.1 1878.4 1469.46 1877.84 1443.69 1877.81 L 1299.64 1877.78 L 847.281 1877.79 L 623.955 1877.83 C 579.324 1877.86 531.709 1879.82 487.755 1874.27 C 452.626 1869.83 419.092 1853.76 393.71 1829.13 C 355.864 1792.4 340.54 1746.12 340.426 1694.07 C 340.346 1657.71 340.332 1620.98 340.35 1584.46 L 340.365 1386.2 L 340.355 772.679 L 340.31 468.644 L 340.306 378.423 C 340.308 359.604 339.634 336.123 342.125 317.886 C 347.043 281.969 363.333 248.57 388.608 222.582 C 417.362 192.977 460.654 172.135 502.181 171.548 z M 1109.88 800.879 C 1091.88 814.863 1095.91 825.36 1086.36 844.19 L 1085.74 845.386 C 1078.68 848.687 1073.99 850.317 1071.45 858.063 C 1068.01 859.948 1055.81 851.122 1051.63 848.387 C 1025.78 831.466 967.755 807.858 937.222 807.881 C 923.311 827.662 926.562 870.012 928.918 893.577 C 912.133 882.589 905.888 879.959 885.818 879.938 C 881.298 891.399 876.793 912.379 875.526 924.708 C 861.575 920.274 844.596 918.405 829.983 917.333 C 799.554 915.1 767.157 915.34 736.708 917.223 C 699.882 919.501 537.679 938.213 513.45 960.45 C 505.813 967.459 504.101 977.953 503.856 987.827 C 502.159 1056.07 585.465 1156.91 632.678 1202.22 C 647.24 1216.19 665.788 1226.34 679.458 1240.9 L 680.518 1242.05 C 678.835 1252.68 675.247 1281.58 672.082 1289.48 C 662.414 1313.58 651.946 1329.59 649.229 1357.08 C 643.164 1418.43 687.597 1470.15 735.513 1502.25 C 746.525 1509.63 773.768 1526.09 781.623 1534.56 C 791.056 1544.73 801.016 1571.75 810.676 1585.56 C 820.985 1600.3 830.767 1607.11 841.49 1620.08 L 842.389 1621.18 C 830.255 1627.36 827.261 1630.11 813.572 1627.44 C 791.477 1623.08 770.749 1614.27 748.838 1609.12 C 727.369 1603.84 704.545 1603.12 683.182 1598.06 C 674.718 1596.06 662.578 1587.32 653.556 1583.27 C 642.568 1585.93 632.851 1590.45 624.916 1598.7 C 611.099 1613.01 603.811 1632.39 604.778 1652.25 C 607.266 1708.01 681.145 1787 732.744 1811.26 C 734.196 1811.95 741.56 1811.54 743.649 1811.44 C 745.035 1807.02 746.331 1802.65 747.52 1798.17 C 757.637 1760.09 777.968 1727.82 799.067 1695.18 C 769.737 1716.69 744.336 1769.45 739.358 1805.52 C 696.109 1780.47 641.527 1726.74 621.912 1679.66 C 608.616 1647.75 615.753 1607.1 651.926 1594.19 C 662.782 1597.53 670.166 1605.06 680.197 1607.64 C 696.862 1611.93 714.941 1612.25 731.979 1615.75 C 753.499 1620.16 774.28 1627.36 795.373 1633.6 C 803.903 1636.12 816.757 1634.75 819.907 1638.02 C 814.584 1643.38 809.893 1645.09 804.45 1650.58 C 810.433 1648.23 817.746 1645.55 822.938 1641.75 C 832.204 1637.7 841.3 1633.27 850.204 1628.47 C 857.292 1624.65 869.413 1616.51 876.538 1615.01 C 883.37 1617.19 890.75 1619.21 897.406 1621.62 L 896.041 1622.96 C 889.278 1629.5 875.711 1638.16 870.706 1643.98 C 847.536 1670.9 824.583 1704.41 820.068 1740.39 C 818.851 1750.09 824.478 1756.51 834.389 1756.07 C 835.95 1755.99 837.51 1755.9 839.068 1755.79 C 846.966 1750.47 858.077 1741.82 865.866 1737.29 C 887.811 1724.53 912.756 1711.92 936.136 1702.1 C 974.553 1686.01 1021.08 1678.62 1054.75 1653.33 C 1067.9 1642.57 1090.08 1622.47 1095.93 1606.13 C 1105.17 1580.32 1114.5 1574.42 1134.36 1557.93 C 1158.24 1538.11 1182.84 1522.52 1207.97 1504.73 C 1225.26 1492.49 1232.53 1476.76 1254.07 1468.92 C 1257.55 1470.18 1260.61 1471.16 1263.88 1472.93 C 1274.15 1487.59 1278.01 1511.55 1274.23 1528.5 C 1257.77 1602.41 1227.9 1676.57 1172.85 1730.31 C 1168.37 1734.68 1164.24 1740.26 1159.72 1744.62 C 1155.36 1748.59 1148.22 1754.32 1145.07 1758.53 C 1149.79 1757.82 1160.63 1749.38 1164.63 1746.41 C 1170.4 1742.45 1175.6 1738.33 1181.11 1734.03 C 1177.48 1744.74 1174.21 1759.7 1170.43 1771.13 C 1167.84 1778.98 1157.05 1804.88 1156.21 1810.09 C 1159.3 1812.01 1162.14 1811.52 1165.89 1811.52 C 1170.64 1798.61 1176.77 1786.73 1181.13 1774.1 C 1185.85 1762.6 1186.84 1738.88 1192.76 1728.87 C 1209 1701.39 1231.53 1677.93 1245.01 1648.03 C 1250.39 1636.11 1255.09 1625.28 1259.91 1612.87 C 1265.79 1597.72 1269.09 1579.5 1277.96 1565.84 C 1283.79 1558.91 1306.5 1547.52 1315.75 1541.23 C 1361.75 1509.99 1399.78 1474.62 1426.95 1425.59 C 1447.53 1388.45 1457.83 1352.75 1460.81 1310.67 C 1461.85 1295.93 1463.72 1286 1463.04 1270.38 C 1462.42 1256.03 1457.77 1240.64 1457.92 1227.29 C 1458.2 1201.29 1461.84 1174.98 1463.12 1149.21 C 1463.52 1141.1 1461.5 1125.48 1460.57 1116.67 C 1456.62 1076.97 1448.85 1037.74 1437.35 999.541 C 1421.07 943.224 1397.19 889.39 1366.37 839.526 C 1359.36 828.31 1345.85 807.534 1333.93 801.846 C 1313.65 792.165 1265.38 795.211 1245.04 801.336 C 1238.06 809.926 1229.29 826.683 1223.1 836.407 C 1219.73 841.694 1217.62 847.417 1213.23 852.126 C 1206.78 850.973 1193.77 836.04 1187.83 831.274 C 1182.52 827.007 1173.58 820.796 1168.72 816.767 C 1145.38 797.43 1138.12 799.196 1109.88 800.879 z M 1109.65 767.98 C 1218.68 766.387 1330.78 767.691 1440.03 767.718 L 1532.15 767.767 C 1545.11 767.782 1565.36 768.599 1577.48 767.821 C 1572.06 760.837 1548.74 738.902 1541.4 731.586 L 1462.04 652.303 L 1186.74 377.194 C 1178.37 368.824 1113.55 302.516 1109.15 301.308 C 1110.96 311.875 1110.16 349.668 1110.16 362.692 L 1110.14 491.261 L 1110.13 675.096 L 1110.19 731.34 C 1110.21 742.652 1110.64 756.905 1109.65 767.98 z M 939.412 958.05 C 940.822 975.761 942.035 983.829 952.621 998.838 C 955.591 999.959 958.611 1001.01 961.474 1002.36 C 1000.25 989.042 1037.49 976.485 1077.17 966.108 C 1074.92 970.771 1068.03 986.093 1078.36 987.062 C 1103.03 989.376 1128.65 986.27 1153.42 988.235 C 1170.22 989.656 1192.42 1004.35 1206.4 1013.05 C 1250.85 1040.69 1287.48 1071.97 1317.04 1115.66 C 1361.31 1181.11 1373.17 1262.9 1358.24 1339.63 C 1349.67 1383.73 1318.31 1460.44 1282.42 1486.71 C 1277.77 1473.98 1276.08 1469.71 1265.75 1460.76 C 1227.3 1457.94 1230.98 1475.3 1203.9 1495.05 C 1172.39 1518.04 1136.87 1539.39 1107.95 1565.76 C 1107.78 1535.28 1109.66 1505.02 1084.11 1483.76 C 1044.43 1498.08 1007.61 1556.07 1017.56 1598.82 L 1018.8 1599.69 C 1020.27 1596.88 1019.69 1582.86 1021.31 1576.02 C 1029.79 1540.39 1050.1 1509.18 1082.24 1491.43 C 1115.06 1523.54 1100.72 1603.44 1068.72 1633.97 C 1033.56 1667.5 992.745 1674.74 949.028 1690.4 C 919.598 1700.94 890.907 1714.86 864.378 1731.13 C 855.656 1736.47 841.422 1748.69 832.33 1750.63 C 814.507 1736.77 852.184 1677.17 862.491 1664.37 C 880.61 1641.86 896.451 1630.95 920.138 1616.04 C 914.371 1616.52 908.484 1617.33 902.807 1616.56 C 898.002 1615.12 892.983 1613.84 888.115 1612.42 C 877.56 1607.4 846.16 1593.5 846.492 1580.23 C 849.362 1575.46 852.436 1575.86 857.37 1574.34 C 877.358 1568.14 898.515 1579.6 918.51 1583.91 C 925.068 1586.04 954.072 1593.27 959.384 1590.89 C 957.073 1587.59 933.082 1582.44 927.479 1580.9 C 842.245 1557.9 719.443 1501.52 673.845 1422.54 C 659.395 1397.57 655.52 1367.86 663.082 1340.03 C 665.53 1331.21 668.725 1322.62 672.635 1314.35 C 674.763 1309.93 680.922 1298.66 681.753 1294.58 C 686.922 1269.2 689.839 1243.62 695.762 1218.33 C 711.077 1152.93 738.208 1091.09 782.106 1039.76 C 801.097 1017.34 810.453 1005.28 837.105 991.179 C 850.746 983.96 876.411 970.582 890.852 966.858 C 893.964 975.133 895.313 983.479 905.868 978.06 C 917.522 972.078 928.102 964.552 939.412 958.05 z M 974.696 1317.34 C 969.707 1312.14 956.44 1297.68 949.395 1297.21 C 942.984 1300.64 936.899 1304.79 930.453 1307.41 C 916.688 1313 899.442 1310.14 888.837 1320.53 C 883.835 1325.43 870.353 1327.99 863.611 1330.44 C 863.485 1331.05 863.359 1331.66 863.233 1332.27 C 865.378 1334.86 867.585 1335.6 870.612 1337.1 C 871.28 1344.82 864.971 1364.03 865.165 1373.45 C 866.029 1415.41 875.378 1450.36 912.039 1472.85 C 984.517 1513.35 1075.32 1456.74 1046.8 1371.56 C 1037.69 1344.35 1026.31 1326.96 1005.26 1307.15 C 1000.27 1302.46 995.785 1297.58 989.555 1294.51 C 984.875 1298.75 979.849 1310.77 974.696 1317.34 z M 885.611 1275.51 C 882.637 1279 876.418 1285.15 876.534 1289.33 C 878.643 1291.61 878.769 1290.86 882.883 1291.23 C 887.961 1291.06 888.135 1291.97 891.014 1289.4 C 892.403 1284.06 890.735 1278.05 885.611 1275.51 z M 895.581 1194.06 C 926.47 1162.21 951.899 1124.35 986.684 1095.26 C 993.635 1089.44 1026.34 1062.4 1027.42 1056.64 C 1024.86 1055.69 1025.8 1055.85 1023.13 1055.96 C 991.974 1066.31 959.285 1084.44 931.678 1102.16 C 920.593 1109.27 909.273 1118.79 898.344 1126.02 C 894.04 1118.36 865.952 1064.75 863.338 1063.21 L 861.808 1063.92 C 857.025 1080.27 862.864 1115.76 866.58 1132.5 C 874.111 1156.99 880.657 1172.28 895.581 1194.06 z M 726.687 1263.48 C 721.593 1263.8 716.483 1264.17 711.383 1264.29 C 712.183 1268.09 715.627 1279.87 715.096 1282.07 C 710.439 1284.43 706.653 1285.67 704.444 1290.27 C 704.427 1300.15 712.531 1299.11 720.254 1299.42 C 745.833 1300.46 769.479 1308.5 792.48 1320.02 C 803.848 1325.07 808.283 1327.63 816.082 1316.04 C 795.665 1291.13 771.817 1268.55 737.847 1263.97 C 735.151 1263.61 729.286 1263.11 726.687 1263.48 z M 1160.35 1391.09 C 1251.53 1392.46 1253.9 1293.28 1204.79 1242.48 C 1199 1236.53 1192.77 1231.01 1186.18 1225.96 C 1180.4 1221.58 1153.46 1205.61 1152.24 1201.45 C 1157.78 1199.82 1169.17 1198.34 1167.6 1189.86 C 1164.04 1187.93 1157.2 1188.81 1153.06 1189.23 C 1126.98 1194.47 1090.38 1213.73 1074.47 1236.12 C 1072.24 1239.25 1069.24 1244.47 1069.28 1248.43 C 1074.14 1251.6 1081.07 1245.16 1086.45 1246.31 C 1084.27 1256.84 1085.21 1262.16 1084.61 1272.28 C 1082.81 1302.29 1088.83 1332.54 1107.09 1357.02 C 1122.31 1378.07 1135.02 1385.59 1160.35 1391.09 z M 948.201 1306.94 C 960.591 1307.19 963.105 1322.67 973.968 1323.8 C 979.68 1324.4 989.207 1312.02 994.662 1307.1 C 1016.21 1320.57 1035.39 1355.1 1041.7 1379.71 C 999.68 1381.07 979.885 1390.77 943.494 1410.84 C 925.479 1420.74 911.279 1437.9 898.115 1453.11 C 891.437 1446.18 885.748 1438 882.4 1428.85 C 872.167 1400.89 867.583 1368.65 879.962 1340.62 C 889.414 1319.21 901.326 1320.36 920.687 1316.05 C 928.738 1314.26 940.253 1309.83 948.201 1306.94 z M 1024.87 1387.33 C 1031.05 1386.78 1037.24 1387.1 1043.45 1387.25 C 1047.15 1420.2 1041.33 1444.36 1013.1 1463.9 C 989.112 1480.51 957.419 1481.97 930.182 1473.72 C 920.355 1470.16 911.091 1465.31 903.118 1458.5 C 909.712 1451.68 930.263 1430.15 936.595 1425.53 C 958.743 1409.37 998.148 1391.18 1024.87 1387.33 z M 1138.21 1207.82 C 1142.13 1208.3 1147.74 1211.58 1151.23 1213.66 L 1151.48 1214.89 C 1147.47 1216.23 1145.46 1216.54 1141.25 1217.28 C 1138.22 1219.67 1137.48 1220.83 1136.03 1224.42 C 1126.6 1247.69 1150.02 1260.82 1167.77 1267.33 C 1174.49 1265.17 1181.29 1263.34 1187.38 1259.83 C 1187.71 1253.57 1187.79 1245.83 1189.43 1239.94 L 1190.88 1239.13 C 1192.94 1239.93 1194.19 1240.73 1195.73 1242.38 C 1221.62 1270.17 1240.61 1314.81 1223.99 1351.8 C 1221.43 1357.49 1216.36 1362.4 1211.99 1366.82 C 1208.03 1370.52 1203.68 1374.58 1198.96 1376.87 C 1120.5 1414.99 1076.12 1308.92 1093 1246.95 C 1098.78 1225.73 1120.43 1217.07 1138.21 1207.82 z M 1152.7 1218.64 C 1168.54 1220.14 1199.1 1249.69 1169.41 1261.29 C 1149.62 1257.99 1146.47 1247.75 1138.66 1231.48 C 1143.33 1225.47 1146.51 1222.7 1152.7 1218.64 z M 999.947 1071.95 C 998.927 1079.19 968.822 1102.98 961.621 1109.71 C 939.503 1130.36 916.692 1163.07 895.562 1182.86 C 883.914 1161.74 880.341 1152.67 873.344 1130.22 C 871.932 1123.45 865.9 1098.4 869.002 1092.95 C 872.399 1094.35 894.598 1131.29 899.489 1137.93 C 929.206 1107.55 961.66 1089.94 999.947 1071.95 z M 1271.53 804.311 C 1282.18 802.516 1305.24 803.653 1316.29 805.355 C 1328.82 807.285 1333.84 810.452 1341.04 820.735 C 1401.61 907.946 1439.84 1014.32 1449.85 1119.96 C 1450.93 1131.38 1456.56 1181.57 1447.46 1187.69 C 1444.27 1183.94 1440.5 1171.16 1438.46 1166.16 C 1435.16 1158.06 1416.55 1120.52 1409.35 1116.7 C 1408.48 1121.79 1418.45 1139.01 1421.08 1144.47 C 1427.32 1157.39 1432.6 1170.76 1436.88 1184.45 C 1470.27 1291.6 1449.24 1405.83 1368.65 1485.83 C 1358.34 1496.06 1293.79 1548.28 1282.73 1547.11 C 1280.89 1542.69 1285.97 1525.34 1286.35 1516.92 L 1286.43 1515 C 1286.68 1509.2 1284.83 1505.36 1282.86 1499.87 C 1285.57 1495.95 1293.29 1487.89 1296.77 1483.98 C 1303.32 1476.61 1309.39 1468.84 1314.93 1460.69 C 1324.8 1446.36 1333.33 1428.64 1341.04 1412.99 C 1357.98 1379.75 1363.78 1345.27 1368.52 1308.99 C 1372.23 1280.57 1371.23 1268.33 1368.4 1240.31 C 1362.87 1185.46 1344 1136.77 1309.62 1093.5 C 1299.86 1081.21 1287.6 1069.72 1276.4 1058.66 C 1250.27 1032.46 1188 986.011 1151.51 981.09 C 1138.04 979.274 1095.47 980.665 1077.65 979.812 C 1080.62 974.22 1090.21 963.517 1086.96 957.738 C 1073.96 958.533 973.467 989.756 960.851 996.441 C 945.618 980.856 950.631 970.427 942.829 951.293 C 926.681 954.858 915.28 964.682 902.254 974.5 C 898.14 968.204 896.948 966.073 894.006 959.17 C 881.394 963.105 871.069 966.851 858.657 971.432 C 865.139 962.13 879.844 956.367 889.592 948.377 C 890.512 945.75 888.101 936.111 887.76 931.86 C 882.343 864.285 918.702 895.363 947.94 925.598 C 940.92 911.592 939.715 894.031 937.499 878.59 C 934.724 859.26 938.699 838.31 940.66 818.806 C 973.387 819.53 1037.64 848.069 1063.96 869.987 C 1074.85 879.059 1072.89 887.892 1073.76 901.868 C 1078.06 884.278 1079.55 876.563 1080.7 858.534 C 1122.49 876.712 1150.33 899.417 1184.27 929.361 C 1191.16 935.441 1201.39 950.536 1207.08 954.421 L 1208.06 953.654 C 1207.64 950.541 1207.69 950.814 1205.82 948.399 C 1185.09 921.41 1161.42 898.266 1133.25 879.08 C 1121.74 871.239 1105.89 864.849 1095.87 855.81 C 1101.55 843.998 1103.69 809.235 1117.54 807.322 C 1155.45 802.084 1187.09 842.776 1214.43 864.6 C 1222.62 851.14 1240.35 818.518 1249.43 808.569 C 1257.03 806.599 1263.79 805.55 1271.53 804.311 z M 744.491 927.502 C 765.752 926.975 867.943 923.62 879.843 941.157 C 879.264 942.428 854.1 958.886 850.544 961.305 C 765.361 1019.25 699.204 1126.2 683.074 1228.59 C 676.866 1224.33 670.509 1220.18 664.835 1215.25 C 657.459 1209.53 650.05 1203.79 643.242 1197.39 C 631.005 1185.9 571.891 1126.12 571.465 1111.92 C 571.195 1102.96 580.4 1090.34 586.409 1084.02 C 623.612 1074.01 656.366 1069.41 692.962 1053.69 C 684.434 1041.63 675.885 1022.46 667.342 1009.27 C 657.678 994.348 643.057 976.25 635.938 960.649 C 639.027 952.874 641.934 945.491 644.685 937.593 C 660.168 933.207 692.698 932.298 709.614 930.633 C 721.172 929.496 732.902 928.012 744.491 927.502 z M 629.674 939.283 C 632.286 938.766 632.214 938.874 634.882 939.295 C 636.785 943.908 631.016 955.756 628.907 961.015 C 641.615 988.808 669.676 1020.26 682.017 1049.4 L 681.097 1050.92 C 666.52 1058.63 598.991 1075.66 580.248 1077.27 C 576.705 1082.71 571.961 1092.53 568.823 1098.55 C 568.336 1099.57 567.501 1100.87 566.91 1101.87 C 565.272 1101.88 564.912 1102.08 563.419 1101.18 C 548.845 1092.41 516.51 1021.64 512.806 1003.05 C 510.715 992.559 511.131 980.985 517.578 971.994 C 528.827 956.306 609.331 942.323 629.674 939.283 z M 800.794 1543.78 C 808.6 1544.52 842.886 1561.95 857.751 1565.72 C 850.09 1569.16 846.494 1571.25 840.462 1577.03 C 840.199 1581 840.685 1586.24 840.933 1590.31 C 847.937 1597.75 851.148 1601.3 860.145 1606.11 C 863.389 1608.36 862.563 1606.93 863.838 1610.01 C 862.822 1613.06 858.795 1615.62 856.109 1617.77 C 835.213 1598.56 820.756 1585.9 808.028 1559.59 C 805.536 1554.44 802.492 1549.28 800.794 1543.78 z M 927.479 1580.9 C 933.082 1582.44 957.073 1587.59 959.384 1590.89 C 954.072 1593.27 925.068 1586.04 918.51 1583.91 C 921.772 1584.12 924.263 1584.64 927.201 1583.35 L 927.479 1580.9 z M 888.115 1612.42 C 892.983 1613.84 898.002 1615.12 902.807 1616.56 C 899.91 1618.66 899.632 1618.67 897.406 1621.62 C 890.75 1619.21 883.37 1617.19 876.538 1615.01 C 882.095 1614.49 884.798 1615.41 888.115 1612.42 z M 1159.72 1744.62 L 1164.63 1746.41 C 1160.63 1749.38 1149.79 1757.82 1145.07 1758.53 C 1148.22 1754.32 1155.36 1748.59 1159.72 1744.62 z M 819.907 1638.02 L 820.687 1641.24 L 822.938 1641.75 C 817.746 1645.55 810.433 1648.23 804.45 1650.58 C 809.893 1645.09 814.584 1643.38 819.907 1638.02 z M87 394c0-104.133.024-207.766-.03-311.4-.006-13.608 6.762-23.51 16.837-31.523 7.754-6.167 16.77-8.237 26.768-8.193 54.98.243 109.963.145 164.946.055 3.949-.007 6.776 1.039 9.657 3.986 21.836 22.338 43.869 44.483 65.897 66.632 17.974 18.074 36.077 36.02 53.959 54.186 1.608 1.634 2.842 4.459 2.845 6.733.143 86.305.357 172.612-.118 258.915-.076 13.886-8.294 24.513-20.337 31.764-6.993 4.211-14.445 5.94-22.668 5.928-85.805-.135-171.61-.012-257.416-.15-15.197-.024-26.452-7.599-34.362-20.33-4.292-6.908-6.424-14.292-6.09-22.616.45-11.146.112-22.323.112-33.987m230.036-58.587c-9.35-15.192-18.706-30.381-28.048-45.578-11.872-19.312-23.87-38.549-35.49-58.01-2.627-4.397-4.007-2.94-5.855.058-9.028 14.64-18.017 29.304-27.02 43.96-11.697 19.041-23.413 38.07-35.08 57.13-4.59 7.5-9.068 15.067-13.964 23.214h23.358l-24.97 72.229 1.251 1.045 91.933-98.061h-31.955l-1.005-1.367 20.48-33.026L300.65 378c-16.866 0-32.688-.103-48.506.122-2.142.03-4.694 1.242-6.3 2.725-3.49 3.222-6.49 6.974-9.692 10.508-5.703 6.298-11.408 12.595-17.472 19.29h144.534c-15.406-25.159-30.557-49.9-46.177-75.232M323.5 121l-44.175-43.55v114.26h114.883z + M209.195,326.458l-91.46-38.359c-2.957-1.241-6.329-0.987-9.067,0.68c-2.739,1.667-4.512,4.546-4.769,7.742 c-2.154,26.854,13.093,51.897,37.941,62.319c7.675,3.219,15.756,4.851,24.02,4.851c18.062,0,35.201-7.822,47.024-21.461 c2.1-2.423,2.911-5.706,2.181-8.827C214.334,330.281,212.151,327.698,209.195,326.458z M165.859,343.691 c-5.593,0-11.071-1.109-16.284-3.295c-12.136-5.09-20.896-15.321-24.306-27.45l60.906,25.544 C180.02,341.866,173.047,343.691,165.859,343.691z M394.87,0.131c-4.841-0.789-9.535,2.045-11.091,6.693l-55.704,166.286c-28.719-19.709-63.039-30.432-98.075-30.432 s-69.355,10.724-98.075,30.432L76.222,6.825c-1.557-4.648-6.251-7.482-11.091-6.693c-4.837,0.789-8.391,4.968-8.391,9.87v359.52 c0,3.808,2.163,7.286,5.579,8.969l163.26,80.48c1.394,0.687,2.908,1.031,4.421,1.031s3.028-0.344,4.421-1.031l163.26-80.48 c3.416-1.684,5.579-5.161,5.579-8.969V10.001C403.261,5.099,399.708,0.92,394.87,0.131z M383.261,363.301l-153.26,75.551 L76.74,363.301V71.335l40.616,121.247c1.043,3.114,3.549,5.518,6.704,6.43c3.155,0.913,6.558,0.217,9.102-1.86 c27.234-22.231,61.625-34.475,96.838-34.475s69.604,12.243,96.838,34.475c2.545,2.077,5.947,2.771,9.102,1.86 c3.155-0.912,5.661-3.316,6.704-6.43l40.616-121.247V363.301z M250.806,326.458c-2.957,1.24-5.14,3.823-5.87,6.945c-0.73,3.122,0.081,6.405,2.181,8.827 c11.823,13.639,28.962,21.461,47.024,21.461c8.263,0,16.344-1.632,24.02-4.851c24.848-10.421,40.095-35.465,37.941-62.319 c-0.257-3.196-2.03-6.075-4.769-7.742c-2.739-1.667-6.111-1.92-9.067-0.68L250.806,326.458z M310.426,340.396 c-5.213,2.186-10.691,3.295-16.284,3.295c-7.188,0-14.16-1.825-20.315-5.2l60.906-25.544 C331.322,325.075,322.562,335.306,310.426,340.396z z diff --git a/FModel/Views/Snooper/Models/Morph.cs b/FModel/Views/Snooper/Models/Morph.cs index 88eef114..a53aeb09 100644 --- a/FModel/Views/Snooper/Models/Morph.cs +++ b/FModel/Views/Snooper/Models/Morph.cs @@ -61,13 +61,13 @@ public class Morph : IDisposable } } - public Morph(float[] vertices, Dictionary dict, UMorphTarget morphTarget) + public Morph(float[] vertices, Dictionary dict, UMorphTarget morphTarget, int index = 0) { Name = morphTarget.Name; Vertices = new float[vertices.Length]; Array.Copy(vertices, Vertices, vertices.Length); - foreach (var vert in morphTarget.MorphLODModels[0].Vertices) + foreach (var vert in morphTarget.MorphLODModels[index].Vertices) { var count = 0; if (dict.TryGetValue(vert.SourceIdx, out var baseIndex)) diff --git a/FModel/Views/Snooper/Models/SkeletalModel.cs b/FModel/Views/Snooper/Models/SkeletalModel.cs index fcc25ac8..725bd450 100644 --- a/FModel/Views/Snooper/Models/SkeletalModel.cs +++ b/FModel/Views/Snooper/Models/SkeletalModel.cs @@ -100,11 +100,11 @@ public class SkeletalModel : UModel foreach (var morph in export.MorphTargets) { - if (!morph.TryLoad(out UMorphTarget morphTarget) || morphTarget.MorphLODModels.Length < 1 || - morphTarget.MorphLODModels[0].Vertices.Length < 1) + if (!morph.TryLoad(out UMorphTarget morphTarget) || morphTarget.MorphLODModels.Length <= skeletalMesh.LODs[LodLevel].LODIndex || + morphTarget.MorphLODModels[skeletalMesh.LODs[LodLevel].LODIndex].Vertices.Length < 1) continue; - Morphs.Add(new Morph(cachedVertices, vertexLookup, morphTarget)); + Morphs.Add(new Morph(cachedVertices, vertexLookup, morphTarget, skeletalMesh.LODs[LodLevel].LODIndex)); } } diff --git a/FModel/Views/Snooper/Options.cs b/FModel/Views/Snooper/Options.cs index b0d21e64..b1f695f4 100644 --- a/FModel/Views/Snooper/Options.cs +++ b/FModel/Views/Snooper/Options.cs @@ -247,7 +247,7 @@ public class Options { return _game switch { - "LIESOFP" or "CODEVEIN2" or "HIGHONLIFE2" => true, + "LIESOFP" or "CODEVEIN2" or "HIGHONLIFE2" or "MORTALSHELL2" => true, _ => false, }; }