├── .gitignore
├── AltTool
├── icon_alpha.ico
├── Resources
│ ├── gtav_aes_key.dat
│ ├── gtav_ng_key.dat
│ ├── gtav_hash_lut.dat
│ ├── gtav_ng_decrypt_tables.dat
│ ├── gtav_ng_encrypt_luts.dat
│ └── gtav_ng_encrypt_tables.dat
├── App.config
├── Properties
│ ├── Settings.settings
│ ├── Settings.Designer.cs
│ ├── AssemblyInfo.cs
│ ├── Resources.Designer.cs
│ └── Resources.resx
├── packages.config
├── App.xaml
├── App.xaml.cs
├── StatusController.cs
├── ProjectBuilder.cs
├── Utils.cs
├── ProjectBuild.xaml
├── ProjectBuild.xaml.cs
├── ProjectController.cs
├── Resource.Designer.cs
├── ClothNameResolved.cs
├── ClothData.cs
├── AltTool.csproj
├── Resource.resx
├── MainWindow.xaml
├── MainWindow.xaml.cs
└── ResourceBuilder.cs
├── make-dist.ps1
├── packages
├── Newtonsoft.Json.12.0.3
│ ├── .signature.p7s
│ ├── packageIcon.png
│ ├── Newtonsoft.Json.12.0.3.nupkg
│ ├── lib
│ │ ├── net20
│ │ │ └── Newtonsoft.Json.dll
│ │ ├── net35
│ │ │ └── Newtonsoft.Json.dll
│ │ ├── net40
│ │ │ └── Newtonsoft.Json.dll
│ │ ├── net45
│ │ │ └── Newtonsoft.Json.dll
│ │ ├── netstandard1.0
│ │ │ └── Newtonsoft.Json.dll
│ │ ├── netstandard1.3
│ │ │ └── Newtonsoft.Json.dll
│ │ ├── netstandard2.0
│ │ │ └── Newtonsoft.Json.dll
│ │ ├── portable-net45+win8+wp8+wpa81
│ │ │ └── Newtonsoft.Json.dll
│ │ └── portable-net40+sl5+win8+wp8+wpa81
│ │ │ └── Newtonsoft.Json.dll
│ └── LICENSE.md
└── Ookii.Dialogs.Wpf.1.1.0
│ ├── .signature.p7s
│ ├── Ookii.Dialogs.Wpf.1.1.0.nupkg
│ └── lib
│ └── net45
│ ├── Ookii.Dialogs.Wpf.dll
│ └── Ookii.Dialogs.Wpf.pdb
├── README.md
└── AltTool.sln
/.gitignore:
--------------------------------------------------------------------------------
1 | *.zip
2 | AltTool/bin
3 | AltTool/obj
4 | .vs
--------------------------------------------------------------------------------
/AltTool/icon_alpha.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/indilo53/altv-cloth-tool/HEAD/AltTool/icon_alpha.ico
--------------------------------------------------------------------------------
/AltTool/Resources/gtav_aes_key.dat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/indilo53/altv-cloth-tool/HEAD/AltTool/Resources/gtav_aes_key.dat
--------------------------------------------------------------------------------
/AltTool/Resources/gtav_ng_key.dat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/indilo53/altv-cloth-tool/HEAD/AltTool/Resources/gtav_ng_key.dat
--------------------------------------------------------------------------------
/make-dist.ps1:
--------------------------------------------------------------------------------
1 | 7z a -tzip alttool-0.0.0.zip `
2 | .\AltTool\bin\Release\*.exe `
3 | .\AltTool\bin\Release\*.dll
4 |
5 |
--------------------------------------------------------------------------------
/AltTool/Resources/gtav_hash_lut.dat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/indilo53/altv-cloth-tool/HEAD/AltTool/Resources/gtav_hash_lut.dat
--------------------------------------------------------------------------------
/AltTool/Resources/gtav_ng_decrypt_tables.dat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/indilo53/altv-cloth-tool/HEAD/AltTool/Resources/gtav_ng_decrypt_tables.dat
--------------------------------------------------------------------------------
/AltTool/Resources/gtav_ng_encrypt_luts.dat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/indilo53/altv-cloth-tool/HEAD/AltTool/Resources/gtav_ng_encrypt_luts.dat
--------------------------------------------------------------------------------
/AltTool/Resources/gtav_ng_encrypt_tables.dat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/indilo53/altv-cloth-tool/HEAD/AltTool/Resources/gtav_ng_encrypt_tables.dat
--------------------------------------------------------------------------------
/packages/Newtonsoft.Json.12.0.3/.signature.p7s:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/indilo53/altv-cloth-tool/HEAD/packages/Newtonsoft.Json.12.0.3/.signature.p7s
--------------------------------------------------------------------------------
/packages/Newtonsoft.Json.12.0.3/packageIcon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/indilo53/altv-cloth-tool/HEAD/packages/Newtonsoft.Json.12.0.3/packageIcon.png
--------------------------------------------------------------------------------
/packages/Ookii.Dialogs.Wpf.1.1.0/.signature.p7s:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/indilo53/altv-cloth-tool/HEAD/packages/Ookii.Dialogs.Wpf.1.1.0/.signature.p7s
--------------------------------------------------------------------------------
/packages/Newtonsoft.Json.12.0.3/Newtonsoft.Json.12.0.3.nupkg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/indilo53/altv-cloth-tool/HEAD/packages/Newtonsoft.Json.12.0.3/Newtonsoft.Json.12.0.3.nupkg
--------------------------------------------------------------------------------
/packages/Newtonsoft.Json.12.0.3/lib/net20/Newtonsoft.Json.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/indilo53/altv-cloth-tool/HEAD/packages/Newtonsoft.Json.12.0.3/lib/net20/Newtonsoft.Json.dll
--------------------------------------------------------------------------------
/packages/Newtonsoft.Json.12.0.3/lib/net35/Newtonsoft.Json.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/indilo53/altv-cloth-tool/HEAD/packages/Newtonsoft.Json.12.0.3/lib/net35/Newtonsoft.Json.dll
--------------------------------------------------------------------------------
/packages/Newtonsoft.Json.12.0.3/lib/net40/Newtonsoft.Json.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/indilo53/altv-cloth-tool/HEAD/packages/Newtonsoft.Json.12.0.3/lib/net40/Newtonsoft.Json.dll
--------------------------------------------------------------------------------
/packages/Newtonsoft.Json.12.0.3/lib/net45/Newtonsoft.Json.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/indilo53/altv-cloth-tool/HEAD/packages/Newtonsoft.Json.12.0.3/lib/net45/Newtonsoft.Json.dll
--------------------------------------------------------------------------------
/packages/Ookii.Dialogs.Wpf.1.1.0/Ookii.Dialogs.Wpf.1.1.0.nupkg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/indilo53/altv-cloth-tool/HEAD/packages/Ookii.Dialogs.Wpf.1.1.0/Ookii.Dialogs.Wpf.1.1.0.nupkg
--------------------------------------------------------------------------------
/packages/Ookii.Dialogs.Wpf.1.1.0/lib/net45/Ookii.Dialogs.Wpf.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/indilo53/altv-cloth-tool/HEAD/packages/Ookii.Dialogs.Wpf.1.1.0/lib/net45/Ookii.Dialogs.Wpf.dll
--------------------------------------------------------------------------------
/packages/Ookii.Dialogs.Wpf.1.1.0/lib/net45/Ookii.Dialogs.Wpf.pdb:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/indilo53/altv-cloth-tool/HEAD/packages/Ookii.Dialogs.Wpf.1.1.0/lib/net45/Ookii.Dialogs.Wpf.pdb
--------------------------------------------------------------------------------
/packages/Newtonsoft.Json.12.0.3/lib/netstandard1.0/Newtonsoft.Json.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/indilo53/altv-cloth-tool/HEAD/packages/Newtonsoft.Json.12.0.3/lib/netstandard1.0/Newtonsoft.Json.dll
--------------------------------------------------------------------------------
/packages/Newtonsoft.Json.12.0.3/lib/netstandard1.3/Newtonsoft.Json.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/indilo53/altv-cloth-tool/HEAD/packages/Newtonsoft.Json.12.0.3/lib/netstandard1.3/Newtonsoft.Json.dll
--------------------------------------------------------------------------------
/packages/Newtonsoft.Json.12.0.3/lib/netstandard2.0/Newtonsoft.Json.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/indilo53/altv-cloth-tool/HEAD/packages/Newtonsoft.Json.12.0.3/lib/netstandard2.0/Newtonsoft.Json.dll
--------------------------------------------------------------------------------
/AltTool/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/packages/Newtonsoft.Json.12.0.3/lib/portable-net45+win8+wp8+wpa81/Newtonsoft.Json.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/indilo53/altv-cloth-tool/HEAD/packages/Newtonsoft.Json.12.0.3/lib/portable-net45+win8+wp8+wpa81/Newtonsoft.Json.dll
--------------------------------------------------------------------------------
/packages/Newtonsoft.Json.12.0.3/lib/portable-net40+sl5+win8+wp8+wpa81/Newtonsoft.Json.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/indilo53/altv-cloth-tool/HEAD/packages/Newtonsoft.Json.12.0.3/lib/portable-net40+sl5+win8+wp8+wpa81/Newtonsoft.Json.dll
--------------------------------------------------------------------------------
/AltTool/Properties/Settings.settings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/AltTool/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/AltTool/App.xaml:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/AltTool/App.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Configuration;
4 | using System.Data;
5 | using System.Linq;
6 | using System.Threading.Tasks;
7 | using System.Windows;
8 |
9 | namespace AltTool
10 | {
11 | ///
12 | /// Логика взаимодействия для App.xaml
13 | ///
14 | public partial class App : Application
15 | {
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/AltTool/StatusController.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace AltTool
8 | {
9 | class StatusController
10 | {
11 |
12 | public static void SetStatus(string status)
13 | {
14 | MainWindow.SetStatus(status);
15 | }
16 |
17 | public static void SetProgress(double progress)
18 | {
19 | MainWindow.SetProgress(progress);
20 | }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # altv-cloth-tool
2 |
3 | ### Generate alt:V resource / SP dlc or FiveM Resource for addon ped component / props
4 |
5 | 
6 | 
7 |
8 | ### Additional notes (from Divined#2725)
9 |
10 | ```
11 | feet ydd needs to be imported with _r
12 | lowr ydd needs to be imported with _r
13 | teef ydd needs to be imported with _u
14 | everything else imported with _u for .ydd
15 | ```
16 |
17 |
18 |
19 | ### Thanks [Tuxick](https://github.com/emcifuntik) for initial version of this tool :)
--------------------------------------------------------------------------------
/AltTool/ProjectBuilder.cs:
--------------------------------------------------------------------------------
1 | using Newtonsoft.Json;
2 | using Newtonsoft.Json.Linq;
3 | using System.Collections.Generic;
4 | using System.Collections.ObjectModel;
5 | using System.IO;
6 | using System.Linq;
7 |
8 | namespace AltTool
9 | {
10 |
11 | class ProjectBuilder
12 | {
13 | public static void BuildProject(string outputFile)
14 | {
15 | var data = JsonConvert.SerializeObject(MainWindow.clothes, Formatting.Indented);
16 |
17 | File.WriteAllText(outputFile, data);
18 | }
19 |
20 | public static void LoadProject(string inputFile)
21 | {
22 | string dir = Path.GetDirectoryName(inputFile);
23 | var data = JsonConvert.DeserializeObject>(File.ReadAllText(inputFile));
24 |
25 | MainWindow.clothes.Clear();
26 |
27 | var _clothes = data.OrderBy(x => x.Name, new AlphanumericComparer()).ToList();
28 |
29 | foreach (var cd in _clothes)
30 | {
31 | MainWindow.clothes.Add(cd);
32 | }
33 | }
34 | }
35 |
36 | }
--------------------------------------------------------------------------------
/packages/Newtonsoft.Json.12.0.3/LICENSE.md:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2007 James Newton-King
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy of
6 | this software and associated documentation files (the "Software"), to deal in
7 | the Software without restriction, including without limitation the rights to
8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9 | the Software, and to permit persons to whom the Software is furnished to do so,
10 | subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 |
--------------------------------------------------------------------------------
/AltTool.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 16
4 | VisualStudioVersion = 16.0.29123.88
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AltTool", "AltTool\AltTool.csproj", "{064EA8C0-7ADF-43DC-BEA0-5852DA38C3AA}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|Any CPU = Debug|Any CPU
11 | Release|Any CPU = Release|Any CPU
12 | EndGlobalSection
13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
14 | {064EA8C0-7ADF-43DC-BEA0-5852DA38C3AA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
15 | {064EA8C0-7ADF-43DC-BEA0-5852DA38C3AA}.Debug|Any CPU.Build.0 = Debug|Any CPU
16 | {064EA8C0-7ADF-43DC-BEA0-5852DA38C3AA}.Release|Any CPU.ActiveCfg = Release|Any CPU
17 | {064EA8C0-7ADF-43DC-BEA0-5852DA38C3AA}.Release|Any CPU.Build.0 = Release|Any CPU
18 | EndGlobalSection
19 | GlobalSection(SolutionProperties) = preSolution
20 | HideSolutionNode = FALSE
21 | EndGlobalSection
22 | GlobalSection(ExtensibilityGlobals) = postSolution
23 | SolutionGuid = {9807173A-A635-4D55-8663-161E34393841}
24 | EndGlobalSection
25 | EndGlobal
26 |
--------------------------------------------------------------------------------
/AltTool/Properties/Settings.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // Этот код создан программой.
4 | // Исполняемая версия:4.0.30319.42000
5 | //
6 | // Изменения в этом файле могут привести к неправильной работе и будут потеряны в случае
7 | // повторной генерации кода.
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace AltTool.Properties {
12 |
13 |
14 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
15 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.2.0.0")]
16 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
17 |
18 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
19 |
20 | public static Settings Default {
21 | get {
22 | return defaultInstance;
23 | }
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/AltTool/Utils.cs:
--------------------------------------------------------------------------------
1 | using RageLib.GTA5.Cryptography;
2 | using RageLib.GTA5.Cryptography.Helpers;
3 | using System;
4 | using System.Collections;
5 | using System.Collections.Generic;
6 | using System.IO;
7 | using System.Linq;
8 | using System.Runtime.InteropServices;
9 | using System.Text;
10 | using System.Threading.Tasks;
11 |
12 | namespace AltTool
13 | {
14 | class Utils
15 | {
16 | public static void EnsureKeys()
17 | {
18 | GTA5Constants.PC_AES_KEY = Resource.gtav_aes_key;
19 | GTA5Constants.PC_NG_KEYS = CryptoIO.ReadNgKeys(Resource.gtav_ng_key);
20 | GTA5Constants.PC_NG_DECRYPT_TABLES = CryptoIO.ReadNgTables(Resource.gtav_ng_decrypt_tables);
21 | GTA5Constants.PC_NG_ENCRYPT_TABLES = CryptoIO.ReadNgTables(Resource.gtav_ng_encrypt_tables);
22 | GTA5Constants.PC_NG_ENCRYPT_LUTs = CryptoIO.ReadNgLuts(Resource.gtav_ng_encrypt_luts);
23 | GTA5Constants.PC_LUT = Resource.gtav_hash_lut;
24 | }
25 |
26 | public static string GetRelativePath(string filespec, string folder)
27 | {
28 | Uri pathUri = new Uri(filespec);
29 |
30 | if (!folder.EndsWith(Path.DirectorySeparatorChar.ToString()))
31 | {
32 | folder += Path.DirectorySeparatorChar;
33 | }
34 |
35 | Uri folderUri = new Uri(folder);
36 |
37 | return Uri.UnescapeDataString(folderUri.MakeRelativeUri(pathUri).ToString().Replace('/', Path.DirectorySeparatorChar));
38 | }
39 | }
40 |
41 | public class AlphanumericComparer : IComparer
42 | {
43 | [DllImport("shlwapi.dll", CharSet = CharSet.Unicode)]
44 | static extern int StrCmpLogicalW(string s1, string s2);
45 |
46 | public int Compare(string x, string y) => StrCmpLogicalW(x, y);
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/AltTool/ProjectBuild.xaml:
--------------------------------------------------------------------------------
1 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/AltTool/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Resources;
3 | using System.Runtime.CompilerServices;
4 | using System.Runtime.InteropServices;
5 | using System.Windows;
6 |
7 | // Общие сведения об этой сборке предоставляются следующим набором
8 | // набор атрибутов. Измените значения этих атрибутов, чтобы изменить сведения,
9 | // связанные со сборкой.
10 | [assembly: AssemblyTitle("AltTool")]
11 | [assembly: AssemblyDescription("")]
12 | [assembly: AssemblyConfiguration("")]
13 | [assembly: AssemblyCompany("")]
14 | [assembly: AssemblyProduct("AltTool")]
15 | [assembly: AssemblyCopyright("Copyright © 2019")]
16 | [assembly: AssemblyTrademark("")]
17 | [assembly: AssemblyCulture("")]
18 |
19 | // Установка значения False для параметра ComVisible делает типы в этой сборке невидимыми
20 | // для компонентов COM. Если необходимо обратиться к типу в этой сборке через
21 | // из модели COM, установите атрибут ComVisible для этого типа в значение true.
22 | [assembly: ComVisible(false)]
23 |
24 | //Чтобы начать создание локализуемых приложений, задайте
25 | //CultureYouAreCodingWith в файле .csproj
26 | //в . Например, при использовании английского (США)
27 | //в своих исходных файлах установите в en-US. Затем отмените преобразование в комментарий
28 | //атрибута NeutralResourceLanguage ниже. Обновите "en-US" в
29 | //строка внизу для обеспечения соответствия настройки UICulture в файле проекта.
30 |
31 | //[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]
32 |
33 |
34 | [assembly: ThemeInfo(
35 | ResourceDictionaryLocation.None, //где расположены словари ресурсов по конкретным тематикам
36 | //(используется, если ресурс не найден на странице,
37 | // или в словарях ресурсов приложения)
38 | ResourceDictionaryLocation.SourceAssembly //где расположен словарь универсальных ресурсов
39 | //(используется, если ресурс не найден на странице,
40 | // в приложении или в каких-либо словарях ресурсов для конкретной темы)
41 | )]
42 |
43 |
44 | // Сведения о версии для сборки включают четыре следующих значения:
45 | //
46 | // Основной номер версии
47 | // Дополнительный номер версии
48 | // Номер сборки
49 | // Номер редакции
50 | //
51 | // Можно задать все значения или принять номера сборки и редакции по умолчанию
52 | // используя "*", как показано ниже:
53 | // [assembly: AssemblyVersion("1.0.*")]
54 | [assembly: AssemblyVersion("1.0.0.0")]
55 | [assembly: AssemblyFileVersion("1.0.0.0")]
56 |
--------------------------------------------------------------------------------
/AltTool/ProjectBuild.xaml.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Win32;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Text.RegularExpressions;
7 | using System.Threading.Tasks;
8 | using System.Windows;
9 | using System.Windows.Controls;
10 | using System.Windows.Data;
11 | using System.Windows.Documents;
12 | using System.Windows.Input;
13 | using System.Windows.Media;
14 | using System.Windows.Media.Imaging;
15 | using System.Windows.Shapes;
16 |
17 | namespace AltTool
18 | {
19 | ///
20 | /// Логика взаимодействия для ProjectBuild.xaml
21 | ///
22 | public partial class ProjectBuild : Window
23 | {
24 | public enum TargetResourceType
25 | {
26 | Altv,
27 | Single,
28 | Fivem
29 | }
30 | public string outputFolder = "";
31 | public string collectionName = "";
32 | public ProjectBuild()
33 | {
34 | InitializeComponent();
35 | }
36 |
37 | private void BuildButton_Click(object sender, RoutedEventArgs e)
38 | {
39 | TargetResourceType resType = TargetResourceType.Altv;
40 |
41 | if (isSinglePlayerRadio.IsChecked == true)
42 | resType = TargetResourceType.Single;
43 | else if (isFivemResourceRadio.IsChecked == true)
44 | resType = TargetResourceType.Fivem;
45 |
46 | collectionName = collectionNameText.Text;
47 |
48 | switch (resType)
49 | {
50 | case TargetResourceType.Altv:
51 | ResourceBuilder.BuildResourceAltv(outputFolder, collectionName);
52 | break;
53 |
54 | case TargetResourceType.Single:
55 | ResourceBuilder.BuildResourceSingle(outputFolder, collectionName);
56 | break;
57 |
58 | case TargetResourceType.Fivem:
59 | ResourceBuilder.BuildResourceFivem(outputFolder, collectionName);
60 | break;
61 | }
62 | }
63 |
64 | private void SelectFolderButton_Click(object sender, RoutedEventArgs e)
65 | {
66 | var dialog = new Ookii.Dialogs.Wpf.VistaFolderBrowserDialog();
67 | if (dialog.ShowDialog(this).GetValueOrDefault())
68 | {
69 | outputFolder = dialog.SelectedPath;
70 | outFolderPathText.Content = outputFolder;
71 | }
72 | }
73 |
74 | private void ValidationTextBox(object sender, TextCompositionEventArgs e)
75 | {
76 | Regex regex = new Regex(@"^[A-Za-z_]$");
77 | e.Handled = !regex.IsMatch(e.Text);
78 | }
79 |
80 | private void CollectionNameText_PreviewKeyDown(object sender, KeyEventArgs e)
81 | {
82 | if (e.Key == Key.Space)
83 | e.Handled = true;
84 | }
85 | }
86 | }
87 |
--------------------------------------------------------------------------------
/AltTool/Properties/Resources.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // Этот код создан программой.
4 | // Исполняемая версия:4.0.30319.42000
5 | //
6 | // Изменения в этом файле могут привести к неправильной работе и будут потеряны в случае
7 | // повторной генерации кода.
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace AltTool.Properties {
12 | using System;
13 |
14 |
15 | ///
16 | /// Класс ресурса со строгой типизацией для поиска локализованных строк и т.д.
17 | ///
18 | // Этот класс создан автоматически классом StronglyTypedResourceBuilder
19 | // с помощью такого средства, как ResGen или Visual Studio.
20 | // Чтобы добавить или удалить член, измените файл .ResX и снова запустите ResGen
21 | // с параметром /str или перестройте свой проект VS.
22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")]
23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
25 | internal class Resources {
26 |
27 | private static global::System.Resources.ResourceManager resourceMan;
28 |
29 | private static global::System.Globalization.CultureInfo resourceCulture;
30 |
31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
32 | internal Resources() {
33 | }
34 |
35 | ///
36 | /// Возвращает кэшированный экземпляр ResourceManager, использованный этим классом.
37 | ///
38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
39 | internal static global::System.Resources.ResourceManager ResourceManager {
40 | get {
41 | if (object.ReferenceEquals(resourceMan, null)) {
42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("AltTool.Properties.Resources", typeof(Resources).Assembly);
43 | resourceMan = temp;
44 | }
45 | return resourceMan;
46 | }
47 | }
48 |
49 | ///
50 | /// Перезаписывает свойство CurrentUICulture текущего потока для всех
51 | /// обращений к ресурсу с помощью этого класса ресурса со строгой типизацией.
52 | ///
53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
54 | internal static global::System.Globalization.CultureInfo Culture {
55 | get {
56 | return resourceCulture;
57 | }
58 | set {
59 | resourceCulture = value;
60 | }
61 | }
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/AltTool/ProjectController.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Win32;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Collections.ObjectModel;
5 | using System.IO;
6 | using System.Linq;
7 | using System.Text;
8 | using System.Threading.Tasks;
9 | using System.Windows;
10 |
11 | namespace AltTool
12 | {
13 | class ProjectController
14 | {
15 |
16 | static ProjectController singleton = null;
17 | public static ProjectController Instance()
18 | {
19 | if(singleton == null)
20 | singleton = new ProjectController();
21 | return singleton;
22 | }
23 |
24 | public void AddFiles(ClothData.Sex targetSex)
25 | {
26 | OpenFileDialog openFileDialog = new OpenFileDialog();
27 | openFileDialog.CheckFileExists = true;
28 | openFileDialog.Filter = "Clothes geometry (*.ydd)|*.ydd";
29 | openFileDialog.FilterIndex = 1;
30 | openFileDialog.DefaultExt = "ydd";
31 | openFileDialog.Multiselect = true;
32 | openFileDialog.Title = "Adding " + ((targetSex == ClothData.Sex.Male) ? "male" : "female") + " clothes";
33 | if (openFileDialog.ShowDialog() == true)
34 | {
35 | foreach (string filename in openFileDialog.FileNames)
36 | {
37 | string baseFileName = Path.GetFileName(filename);
38 | ClothNameResolver cData = new ClothNameResolver(baseFileName);
39 |
40 | if(!cData.isVariation)
41 | {
42 | ClothData nextCloth = new ClothData(filename, cData.clothType, cData.drawableType, cData.bindedNumber, cData.postfix, targetSex);
43 |
44 | if(cData.clothType == ClothNameResolver.Type.Component)
45 | {
46 | nextCloth.SearchForFPModel();
47 | nextCloth.SearchForTextures();
48 |
49 | var _clothes = MainWindow.clothes.ToList();
50 | _clothes.Add(nextCloth);
51 | _clothes = _clothes.OrderBy(x => x.Name, new AlphanumericComparer()).ToList();
52 | MainWindow.clothes.Clear();
53 |
54 | foreach(var cloth in _clothes)
55 | {
56 | MainWindow.clothes.Add(cloth);
57 | }
58 |
59 | StatusController.SetStatus(nextCloth.ToString() + " added (FP model found: " + (nextCloth.fpModelPath != "" ? "Yes" : "No") + ", Textures: " + (nextCloth.textures.Count) + "). Total: " + MainWindow.clothes.Count);
60 | }
61 | else
62 | {
63 | nextCloth.SearchForTextures();
64 |
65 | var _clothes = MainWindow.clothes.ToList();
66 | _clothes.Add(nextCloth);
67 | _clothes = _clothes.OrderBy(x => x.Name, new AlphanumericComparer()).ToList();
68 | MainWindow.clothes.Clear();
69 |
70 | foreach (var cloth in _clothes)
71 | {
72 | MainWindow.clothes.Add(cloth);
73 | }
74 |
75 | StatusController.SetStatus(nextCloth.ToString() + " added, Textures: " + (nextCloth.textures.Count) + "). Total: " + MainWindow.clothes.Count);
76 | }
77 | }
78 | else
79 | StatusController.SetStatus("Item " + baseFileName + " can't be added. Looks like it's variant of another item");
80 | }
81 | }
82 | }
83 |
84 | public void AddTexture(ClothData cloth)
85 | {
86 | OpenFileDialog openFileDialog = new OpenFileDialog();
87 | openFileDialog.CheckFileExists = true;
88 | openFileDialog.Filter = "Clothes texture (*.ytd)|*.ytd";
89 | openFileDialog.FilterIndex = 1;
90 | openFileDialog.DefaultExt = "ytd";
91 | openFileDialog.Multiselect = true;
92 | if (openFileDialog.ShowDialog() == true)
93 | {
94 | foreach (string filename in openFileDialog.FileNames)
95 | {
96 | if(filename.EndsWith(".ytd"))
97 | {
98 | cloth.AddTexture(filename);
99 | }
100 | }
101 | }
102 | }
103 |
104 | public void SetFPModel(ClothData cloth)
105 | {
106 | OpenFileDialog openFileDialog = new OpenFileDialog();
107 | openFileDialog.CheckFileExists = true;
108 | openFileDialog.Filter = "Clothes drawable (*.ydd)|*.ydd";
109 | openFileDialog.FilterIndex = 1;
110 | openFileDialog.DefaultExt = "ydd";
111 | openFileDialog.Multiselect = false;
112 | if (openFileDialog.ShowDialog() == true)
113 | {
114 | foreach (string filename in openFileDialog.FileNames)
115 | {
116 | if (filename.EndsWith(".ydd"))
117 | {
118 | cloth.SetFPModel(filename);
119 | }
120 | }
121 | }
122 | }
123 | }
124 | }
125 |
--------------------------------------------------------------------------------
/AltTool/Resource.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // Ce code a été généré par un outil.
4 | // Version du runtime :4.0.30319.42000
5 | //
6 | // Les modifications apportées à ce fichier peuvent provoquer un comportement incorrect et seront perdues si
7 | // le code est régénéré.
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace AltTool
12 | {
13 | using System;
14 |
15 |
16 | ///
17 | /// Une classe de ressource fortement typée destinée, entre autres, à la consultation des chaînes localisées.
18 | ///
19 | // Cette classe a été générée automatiquement par la classe StronglyTypedResourceBuilder
20 | // à l'aide d'un outil, tel que ResGen ou Visual Studio.
21 | // Pour ajouter ou supprimer un membre, modifiez votre fichier .ResX, puis réexécutez ResGen
22 | // avec l'option /str ou régénérez votre projet VS.
23 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")]
24 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
25 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
26 | internal class Resource {
27 |
28 | private static global::System.Resources.ResourceManager resourceMan;
29 |
30 | private static global::System.Globalization.CultureInfo resourceCulture;
31 |
32 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
33 | internal Resource() {
34 | }
35 |
36 | ///
37 | /// Retourne l'instance ResourceManager mise en cache utilisée par cette classe.
38 | ///
39 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
40 | internal static global::System.Resources.ResourceManager ResourceManager {
41 | get {
42 | if (object.ReferenceEquals(resourceMan, null)) {
43 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("AltTool.Resource", typeof(Resource).Assembly);
44 | resourceMan = temp;
45 | }
46 | return resourceMan;
47 | }
48 | }
49 |
50 | ///
51 | /// Remplace la propriété CurrentUICulture du thread actuel pour toutes
52 | /// les recherches de ressources à l'aide de cette classe de ressource fortement typée.
53 | ///
54 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
55 | internal static global::System.Globalization.CultureInfo Culture {
56 | get {
57 | return resourceCulture;
58 | }
59 | set {
60 | resourceCulture = value;
61 | }
62 | }
63 |
64 | ///
65 | /// Recherche une ressource localisée de type System.Byte[].
66 | ///
67 | internal static byte[] gtav_aes_key {
68 | get {
69 | object obj = ResourceManager.GetObject("gtav_aes_key", resourceCulture);
70 | return ((byte[])(obj));
71 | }
72 | }
73 |
74 | ///
75 | /// Recherche une ressource localisée de type System.Byte[].
76 | ///
77 | internal static byte[] gtav_hash_lut {
78 | get {
79 | object obj = ResourceManager.GetObject("gtav_hash_lut", resourceCulture);
80 | return ((byte[])(obj));
81 | }
82 | }
83 |
84 | ///
85 | /// Recherche une ressource localisée de type System.Byte[].
86 | ///
87 | internal static byte[] gtav_ng_decrypt_tables {
88 | get {
89 | object obj = ResourceManager.GetObject("gtav_ng_decrypt_tables", resourceCulture);
90 | return ((byte[])(obj));
91 | }
92 | }
93 |
94 | ///
95 | /// Recherche une ressource localisée de type System.Byte[].
96 | ///
97 | internal static byte[] gtav_ng_encrypt_luts {
98 | get {
99 | object obj = ResourceManager.GetObject("gtav_ng_encrypt_luts", resourceCulture);
100 | return ((byte[])(obj));
101 | }
102 | }
103 |
104 | ///
105 | /// Recherche une ressource localisée de type System.Byte[].
106 | ///
107 | internal static byte[] gtav_ng_encrypt_tables {
108 | get {
109 | object obj = ResourceManager.GetObject("gtav_ng_encrypt_tables", resourceCulture);
110 | return ((byte[])(obj));
111 | }
112 | }
113 |
114 | ///
115 | /// Recherche une ressource localisée de type System.Byte[].
116 | ///
117 | internal static byte[] gtav_ng_key {
118 | get {
119 | object obj = ResourceManager.GetObject("gtav_ng_key", resourceCulture);
120 | return ((byte[])(obj));
121 | }
122 | }
123 | }
124 | }
125 |
--------------------------------------------------------------------------------
/AltTool/Properties/Resources.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 | text/microsoft-resx
107 |
108 |
109 | 2.0
110 |
111 |
112 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
113 |
114 |
115 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
--------------------------------------------------------------------------------
/AltTool/ClothNameResolved.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 |
8 | namespace AltTool
9 | {
10 | public class ClothNameResolver
11 | {
12 | public enum Type
13 | {
14 | Component,
15 | PedProp
16 | }
17 |
18 | public enum DrawableType
19 | {
20 | Head,
21 | Mask,
22 | Hair,
23 | Body,
24 | Legs,
25 | Bag,
26 | Shoes,
27 | Accessories,
28 | Undershirt,
29 | Armor,
30 | Decal,
31 | Top,
32 | PropHead,
33 | PropEyes,
34 | PropEars,
35 | PropMouth,
36 | PropLHand,
37 | PropRHand,
38 | PropLWrist,
39 | PropRWrist,
40 | PropHip,
41 | PropLFoot,
42 | PropRFoot,
43 | PropUnk1,
44 | PropUnk2,
45 | COUNT
46 | }
47 |
48 | public Type clothType;
49 | public DrawableType drawableType;
50 | public string bindedNumber = "";
51 | public string postfix = "";
52 | public bool isVariation = false;
53 | public ClothNameResolver(string filename)
54 | {
55 | string[] parts = Path.GetFileNameWithoutExtension(filename).Split('_');
56 | if (parts.Length < 3)
57 | throw new Exception("Wrong drawable name");
58 |
59 | if(parts[0].ToLower() == "p")
60 | {
61 | clothType = Type.PedProp;
62 |
63 | string drName = parts[1].ToLower();
64 | switch(drName)
65 | {
66 | case "head": drawableType = DrawableType.PropHead; break;
67 | case "eyes": drawableType = DrawableType.PropEyes; break;
68 | case "ears": drawableType = DrawableType.PropEars; break;
69 | case "mouth": drawableType = DrawableType.PropMouth; break;
70 | case "lhand": drawableType = DrawableType.PropLHand; break;
71 | case "rhand": drawableType = DrawableType.PropRHand; break;
72 | case "lwrist": drawableType = DrawableType.PropLWrist; break;
73 | case "rwrist": drawableType = DrawableType.PropRWrist; break;
74 | case "hip": drawableType = DrawableType.PropHip; break;
75 | case "lfoot": drawableType = DrawableType.PropLFoot; break;
76 | case "rfoot": drawableType = DrawableType.PropRFoot; break;
77 | case "unk1": drawableType = DrawableType.PropUnk1; break;
78 | case "unk2": drawableType = DrawableType.PropUnk2; break;
79 | default: break;
80 | }
81 |
82 | bindedNumber = parts[2];
83 | }
84 | else
85 | {
86 | clothType = Type.Component;
87 |
88 | string drName = parts[0].ToLower();
89 | switch(drName)
90 | {
91 | case "head": drawableType = DrawableType.Head; break;
92 | case "berd": drawableType = DrawableType.Mask; break;
93 | case "hair": drawableType = DrawableType.Hair; break;
94 | case "uppr": drawableType = DrawableType.Body; break;
95 | case "lowr": drawableType = DrawableType.Legs; break;
96 | case "hand": drawableType = DrawableType.Bag; break;
97 | case "feet": drawableType = DrawableType.Shoes; break;
98 | case "teef": drawableType = DrawableType.Accessories; break;
99 | case "accs": drawableType = DrawableType.Undershirt; break;
100 | case "task": drawableType = DrawableType.Armor; break;
101 | case "decl": drawableType = DrawableType.Decal; break;
102 | case "jbib": drawableType = DrawableType.Top; break;
103 | default: break;
104 | }
105 |
106 | bindedNumber = parts[1];
107 | postfix = parts[2].ToLower();
108 | if (parts.Length > 3)
109 | isVariation = true;
110 | }
111 | }
112 |
113 | public override string ToString()
114 | {
115 | return clothType.ToString() + " " + drawableType.ToString() + " " + bindedNumber;
116 | }
117 |
118 | public static string DrawableTypeToString(DrawableType type)
119 | {
120 | switch(type)
121 | {
122 | case DrawableType.Head: return "head";
123 | case DrawableType.Mask: return "berd";
124 | case DrawableType.Hair: return "hair";
125 | case DrawableType.Body: return "uppr";
126 | case DrawableType.Legs: return "lowr";
127 | case DrawableType.Bag: return "hand";
128 | case DrawableType.Shoes: return "feet";
129 | case DrawableType.Accessories: return "teef";
130 | case DrawableType.Undershirt: return "accs";
131 | case DrawableType.Armor: return "task";
132 | case DrawableType.Decal: return "decl";
133 | case DrawableType.Top: return "jbib";
134 | case DrawableType.PropHead: return "p_head";
135 | case DrawableType.PropEyes: return "p_eyes";
136 | case DrawableType.PropEars: return "p_ears";
137 | case DrawableType.PropMouth: return "p_mouth";
138 | case DrawableType.PropLHand: return "p_lhand";
139 | case DrawableType.PropRHand: return "p_rhand";
140 | case DrawableType.PropLWrist: return "p_lwrist";
141 | case DrawableType.PropRWrist: return "p_rwrist";
142 | case DrawableType.PropHip: return "p_hip";
143 | case DrawableType.PropLFoot: return "p_lfoot";
144 | case DrawableType.PropRFoot: return "p_rfoot";
145 | case DrawableType.PropUnk1: return "p_unk1";
146 | case DrawableType.PropUnk2: return "p_unk2";
147 | default: return "";
148 | }
149 | }
150 | }
151 | }
152 |
--------------------------------------------------------------------------------
/AltTool/ClothData.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Collections.ObjectModel;
4 | using System.ComponentModel;
5 | using System.IO;
6 | using System.Linq;
7 | using System.Runtime.CompilerServices;
8 | using System.Text;
9 | using System.Threading.Tasks;
10 | using Newtonsoft.Json;
11 | using Newtonsoft.Json.Linq;
12 |
13 | namespace AltTool
14 | {
15 | public class ClothData: INotifyPropertyChanged
16 | {
17 | public ClothNameResolver.Type clothType;
18 | public ClothNameResolver.DrawableType drawableType;
19 |
20 | public struct ComponentFlags
21 | {
22 | public bool unkFlag1;
23 | public bool unkFlag2;
24 | public bool unkFlag3;
25 | public bool unkFlag4;
26 | public bool isHighHeels;
27 | }
28 |
29 | public struct PedPropFlags
30 | {
31 | public bool unkFlag1;
32 | public bool unkFlag2;
33 | public bool unkFlag3;
34 | public bool unkFlag4;
35 | public bool unkFlag5;
36 | }
37 |
38 | public enum Sex
39 | {
40 | Male,
41 | Female
42 | }
43 |
44 | static int[] idsOffset = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
45 | static char offsetLetter = 'a';
46 | static string[] sexIcons = { "👨🏻", "👩🏻" };
47 | static string[] typeIcons = { "🧥", "👓" };
48 |
49 | public string mainPath = "";
50 | string origNumerics = "";
51 | string postfix = "";
52 |
53 | public ComponentFlags componentFlags;
54 | public PedPropFlags pedPropFlags;
55 |
56 | public string fpModelPath;
57 | public ObservableCollection textures = new ObservableCollection();
58 |
59 | public Sex targetSex;
60 |
61 | public string name = "";
62 |
63 | public string Icon
64 | {
65 | get
66 | {
67 | return sexIcons[(int)targetSex];
68 | }
69 | }
70 |
71 | public string Type
72 | {
73 | get
74 | {
75 | return typeIcons[(int)clothType];
76 | }
77 | }
78 |
79 | public string Name
80 | {
81 | get
82 | {
83 | return name;
84 | }
85 | set
86 | {
87 | name = value;
88 | OnPropertyChanged("Name");
89 | }
90 | }
91 |
92 | public ClothData()
93 | {
94 |
95 | }
96 |
97 | public ClothData(string path, ClothNameResolver.Type _type, ClothNameResolver.DrawableType _drawableType, string numeric, string _postfix, Sex sex)
98 | {
99 | if (!File.Exists(path))
100 | throw new Exception("YDD file not found");
101 |
102 | clothType = _type;
103 | drawableType = _drawableType;
104 | origNumerics = numeric;
105 |
106 | targetSex = sex;
107 | postfix = _postfix;
108 |
109 | name = drawableType.ToString() + "_" + origNumerics;
110 |
111 | mainPath = path;
112 | }
113 |
114 | public void SearchForFPModel()
115 | {
116 | string rootPath = Path.GetDirectoryName(mainPath);
117 | string fileName = Path.GetFileNameWithoutExtension(mainPath);
118 | string relPath = rootPath + "\\" + fileName + "_1.ydd";
119 | if (File.Exists(relPath))
120 | fpModelPath = relPath;
121 | else
122 | fpModelPath = "";
123 | }
124 |
125 | public void SetFPModel(string path)
126 | {
127 | fpModelPath = path;
128 | }
129 |
130 | public void SearchForTextures()
131 | {
132 | textures.Clear();
133 | string rootPath = Path.GetDirectoryName(mainPath);
134 |
135 | if(IsComponent())
136 | {
137 | for (int i = 0; ; ++i)
138 | {
139 | string relPath = rootPath + "\\" + ClothNameResolver.DrawableTypeToString(drawableType) + "_diff_" + origNumerics + "_" + (char)(offsetLetter + i) + "_uni.ytd";
140 | if (!File.Exists(relPath))
141 | break;
142 | textures.Add(relPath);
143 | }
144 | for (int i = 0; ; ++i)
145 | {
146 | string relPath = rootPath + "\\" + ClothNameResolver.DrawableTypeToString(drawableType) + "_diff_" + origNumerics + "_" + (char)(offsetLetter + i) + "_whi.ytd";
147 | if (!File.Exists(relPath))
148 | break;
149 | textures.Add(relPath);
150 | }
151 | }
152 | else
153 | {
154 | for (int i = 0; ; ++i)
155 | {
156 | string relPath = rootPath + "\\" + ClothNameResolver.DrawableTypeToString(drawableType) + "_diff_" + origNumerics + "_" + (char)(offsetLetter + i) + ".ytd";
157 | if (!File.Exists(relPath))
158 | break;
159 | textures.Add(relPath);
160 | }
161 | }
162 | }
163 |
164 | public void AddTexture(string path)
165 | {
166 | if(!textures.Contains(path))
167 | textures.Add(path);
168 | }
169 |
170 | public override string ToString()
171 | {
172 | return sexIcons[(int)targetSex] + " " + name;
173 | }
174 |
175 | public event PropertyChangedEventHandler PropertyChanged;
176 |
177 | void OnPropertyChanged([CallerMemberName] string propertyName = null)
178 | {
179 | var handler = PropertyChanged;
180 | if (handler != null)
181 | {
182 | handler(this, new PropertyChangedEventArgs(propertyName));
183 | }
184 | }
185 |
186 | public bool IsComponent()
187 | {
188 | if (drawableType <= ClothNameResolver.DrawableType.Top)
189 | return true;
190 | return false;
191 | }
192 |
193 | public byte GetComponentTypeID()
194 | {
195 | if(IsComponent())
196 | return (byte)drawableType;
197 | return 255;
198 | }
199 |
200 | public bool IsPedProp()
201 | {
202 | return !IsComponent();
203 | }
204 |
205 | public byte GetPedPropTypeID()
206 | {
207 | if (IsPedProp())
208 | return (byte)((int)drawableType - (int)ClothNameResolver.DrawableType.PropHead);
209 | return 255;
210 | }
211 |
212 | public string GetPrefix()
213 | {
214 | return ClothNameResolver.DrawableTypeToString(drawableType);
215 | }
216 | }
217 | }
218 |
--------------------------------------------------------------------------------
/AltTool/AltTool.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {064EA8C0-7ADF-43DC-BEA0-5852DA38C3AA}
8 | WinExe
9 | AltTool
10 | AltTool
11 | v4.7.2
12 | 512
13 | {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
14 | 4
15 | true
16 | true
17 |
18 |
19 |
20 | AnyCPU
21 | true
22 | full
23 | false
24 | bin\Debug\
25 | DEBUG;TRACE
26 | prompt
27 | 4
28 |
29 |
30 | AnyCPU
31 | pdbonly
32 | true
33 | bin\Release\
34 | TRACE
35 | prompt
36 | 4
37 |
38 |
39 |
40 | ..\packages\Newtonsoft.Json.12.0.3\lib\net45\Newtonsoft.Json.dll
41 |
42 |
43 | ..\packages\Ookii.Dialogs.Wpf.1.1.0\lib\net45\Ookii.Dialogs.Wpf.dll
44 |
45 |
46 | False
47 | ..\..\gtautil\gtautil\Libraries\gta-toolkit\RageLib\bin\Debug\RageLib.dll
48 |
49 |
50 | False
51 | ..\..\gtautil\gtautil\Libraries\gta-toolkit\RageLib.GTA5\bin\Debug\RageLib.GTA5.dll
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 | 4.0
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 | MSBuild:Compile
74 | Designer
75 |
76 |
77 | ProjectBuild.xaml
78 |
79 |
80 |
81 | True
82 | True
83 | Resource.resx
84 |
85 |
86 |
87 |
88 |
89 | MSBuild:Compile
90 | Designer
91 |
92 |
93 | App.xaml
94 | Code
95 |
96 |
97 |
98 |
99 | MainWindow.xaml
100 | Code
101 |
102 |
103 | Designer
104 | MSBuild:Compile
105 |
106 |
107 |
108 |
109 |
110 | Code
111 |
112 |
113 | True
114 | True
115 | Resources.resx
116 |
117 |
118 | True
119 | Settings.settings
120 | True
121 |
122 |
123 | ResXFileCodeGenerator
124 | Resources.Designer.cs
125 |
126 |
127 | ResXFileCodeGenerator
128 | Resource.Designer.cs
129 |
130 |
131 |
132 | SettingsSingleFileGenerator
133 | Settings.Designer.cs
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
--------------------------------------------------------------------------------
/AltTool/Resource.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 | text/microsoft-resx
110 |
111 |
112 | 2.0
113 |
114 |
115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
119 |
120 |
121 |
122 | Resources\gtav_aes_key.dat;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
123 |
124 |
125 | Resources\gtav_ng_key.dat;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
126 |
127 |
128 | Resources\gtav_ng_decrypt_tables.dat;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
129 |
130 |
131 | Resources\gtav_ng_encrypt_tables.dat;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
132 |
133 |
134 | Resources\gtav_ng_encrypt_luts.dat;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
135 |
136 |
137 | Resources\gtav_hash_lut.dat;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
138 |
139 |
--------------------------------------------------------------------------------
/AltTool/MainWindow.xaml:
--------------------------------------------------------------------------------
1 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
30 |
32 |
34 |
35 |
36 |
37 |
38 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
123 |
124 |
125 |
--------------------------------------------------------------------------------
/AltTool/MainWindow.xaml.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Win32;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Collections.ObjectModel;
5 | using System.Linq;
6 | using System.Text;
7 | using System.Threading.Tasks;
8 | using System.Windows;
9 | using System.Windows.Controls;
10 | using System.Windows.Data;
11 | using System.Windows.Documents;
12 | using System.Windows.Input;
13 | using System.Windows.Media;
14 | using System.Windows.Media.Imaging;
15 | using System.Windows.Navigation;
16 | using System.Windows.Shapes;
17 | using static AltTool.ClothData;
18 |
19 | namespace AltTool
20 | {
21 | ///
22 | /// Логика взаимодействия для MainWindow.xaml
23 | ///
24 | public partial class MainWindow : Window
25 | {
26 | private static TextBlock statusTextBlock = null;
27 | private static ProgressBar statusProgress = null;
28 | public static ObservableCollection clothes;
29 | private static ClothData selectedCloth = null;
30 | public static ProjectBuild projectBuildWindow = null;
31 |
32 | public MainWindow()
33 | {
34 | InitializeComponent();
35 |
36 | statusTextBlock = ((TextBlock)FindName("currentStatusBar"));
37 | statusProgress = ((ProgressBar)FindName("currentProgress"));
38 |
39 | clothes = new ObservableCollection();
40 | clothesListBox.ItemsSource = clothes;
41 |
42 | }
43 |
44 | public static void SetStatus(string status)
45 | {
46 | statusTextBlock.Text = status;
47 | }
48 |
49 | public static void SetProgress(double progress)
50 | {
51 | if (progress > 1)
52 | progress = 1;
53 | if (progress < 0)
54 | progress = 0;
55 |
56 | statusProgress.Value = statusProgress.Maximum * progress;
57 | }
58 |
59 | private void AddMaleClothes_Click(object sender, RoutedEventArgs e)
60 | {
61 | ProjectController.Instance().AddFiles(Sex.Male);
62 | }
63 |
64 | private void AddFemaleClothes_Click(object sender, RoutedEventArgs e)
65 | {
66 | ProjectController.Instance().AddFiles(Sex.Female);
67 | }
68 |
69 | private void RemoveUnderCursor_Click(object sender, RoutedEventArgs e)
70 | {
71 | if (selectedCloth != null)
72 | {
73 | var _clothes = clothes.OrderBy(x => x.Name, new AlphanumericComparer()).ToList();
74 |
75 | clothes.Clear();
76 |
77 | foreach(var cloth in _clothes)
78 | {
79 | if(cloth != selectedCloth)
80 | {
81 | clothes.Add(cloth);
82 | }
83 | }
84 |
85 | selectedCloth = null;
86 | editGroupBox.Visibility = Visibility.Hidden;
87 | }
88 | }
89 |
90 | private void ClothesListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
91 | {
92 | if(e.AddedItems.Count > 0)
93 | {
94 | selectedCloth = (ClothData)e.AddedItems[0];
95 |
96 | if (selectedCloth != null)
97 | {
98 | clothEditWindow.Visibility = Visibility.Collapsed;
99 | pedPropEditWindow.Visibility = Visibility.Collapsed;
100 |
101 | if (selectedCloth.IsComponent())
102 | {
103 | clothEditWindow.Visibility = Visibility.Visible;
104 | drawableName.Text = selectedCloth.Name;
105 |
106 | texturesList.ItemsSource = selectedCloth.textures;
107 | fpModelPath.Text = selectedCloth.fpModelPath != "" ? selectedCloth.fpModelPath : "Not selected...";
108 |
109 | unkFlag1Check.IsChecked = selectedCloth.componentFlags.unkFlag1;
110 | unkFlag2Check.IsChecked = selectedCloth.componentFlags.unkFlag2;
111 | unkFlag3Check.IsChecked = selectedCloth.componentFlags.unkFlag3;
112 | unkFlag4Check.IsChecked = selectedCloth.componentFlags.unkFlag4;
113 | isHighHeelsCheck.IsChecked = selectedCloth.componentFlags.isHighHeels;
114 | }
115 | else
116 | {
117 | pedPropEditWindow.Visibility = Visibility.Visible;
118 | drawableName.Text = selectedCloth.Name;
119 | pedPropName.Text = selectedCloth.Name;
120 |
121 | pedPropTexturesList.ItemsSource = selectedCloth.textures;
122 |
123 | pedPropFlag1.IsChecked = selectedCloth.pedPropFlags.unkFlag1;
124 | pedPropFlag2.IsChecked = selectedCloth.pedPropFlags.unkFlag2;
125 | pedPropFlag3.IsChecked = selectedCloth.pedPropFlags.unkFlag3;
126 | pedPropFlag4.IsChecked = selectedCloth.pedPropFlags.unkFlag4;
127 | pedPropFlag5.IsChecked = selectedCloth.pedPropFlags.unkFlag5;
128 | }
129 | }
130 | }
131 | }
132 |
133 | private void DrawableName_TextChanged(object sender, TextChangedEventArgs e)
134 | {
135 | if(selectedCloth != null)
136 | {
137 | selectedCloth.Name = drawableName.Text;
138 | }
139 | }
140 |
141 | private void NewProjectButton_Click(object sender, RoutedEventArgs e)
142 | {
143 | clothes.Clear();
144 | }
145 |
146 | private void OpenProjectButton_Click(object sender, RoutedEventArgs e)
147 | {
148 | OpenFileDialog openFileDialog = new OpenFileDialog();
149 | openFileDialog.CheckFileExists = true;
150 | openFileDialog.Filter = "altV cloth JSON (*.altv-cloth.json)|*.altv-cloth.json";
151 | openFileDialog.FilterIndex = 1;
152 | openFileDialog.DefaultExt = "altv-cloth.json";
153 |
154 | if (openFileDialog.ShowDialog() == true)
155 | {
156 | foreach (string filename in openFileDialog.FileNames)
157 | {
158 | ProjectBuilder.LoadProject(filename);
159 | }
160 | }
161 | }
162 |
163 | private void SaveProjectButton_Click(object sender, RoutedEventArgs e)
164 | {
165 | SaveFileDialog saveFileDialog = new SaveFileDialog();
166 | saveFileDialog.Filter = "altV cloth JSON (*.altv-cloth.json)|*.altv-cloth.json";
167 | saveFileDialog.FilterIndex = 1;
168 | saveFileDialog.DefaultExt = "altv-cloth.json";
169 |
170 | if (saveFileDialog.ShowDialog() == true)
171 | {
172 | foreach (string filename in saveFileDialog.FileNames)
173 | {
174 | ProjectBuilder.BuildProject(filename);
175 | }
176 | }
177 | }
178 |
179 | private void AddTexture_Click(object sender, RoutedEventArgs e)
180 | {
181 | if(selectedCloth != null)
182 | ProjectController.Instance().AddTexture(selectedCloth);
183 | }
184 |
185 | private void RemoveTexture_Click(object sender, RoutedEventArgs e)
186 | {
187 | if(texturesList.SelectedItem != null)
188 | {
189 | ((ObservableCollection)texturesList.ItemsSource).Remove((string)texturesList.SelectedItem);
190 | }
191 | }
192 |
193 | private void BuildProjectButton_Click(object sender, RoutedEventArgs e)
194 | {
195 | projectBuildWindow = new ProjectBuild();
196 | projectBuildWindow.Show();
197 | }
198 |
199 | private void UnkFlag1Check_Checked(object sender, RoutedEventArgs e)
200 | {
201 | if (selectedCloth != null)
202 | selectedCloth.componentFlags.unkFlag1 = unkFlag1Check.IsChecked.GetValueOrDefault(false);
203 | }
204 |
205 | private void UnkFlag2Check_Checked(object sender, RoutedEventArgs e)
206 | {
207 | if (selectedCloth != null)
208 | selectedCloth.componentFlags.unkFlag2 = unkFlag2Check.IsChecked.GetValueOrDefault(false);
209 | }
210 |
211 | private void UnkFlag3Check_Checked(object sender, RoutedEventArgs e)
212 | {
213 | if (selectedCloth != null)
214 | selectedCloth.componentFlags.unkFlag3 = unkFlag3Check.IsChecked.GetValueOrDefault(false);
215 | }
216 |
217 | private void UnkFlag4Check_Checked(object sender, RoutedEventArgs e)
218 | {
219 | if (selectedCloth != null)
220 | selectedCloth.componentFlags.unkFlag4 = unkFlag4Check.IsChecked.GetValueOrDefault(false);
221 | }
222 |
223 | private void IsHighHeelsCheck_Checked(object sender, RoutedEventArgs e)
224 | {
225 | if (selectedCloth != null)
226 | selectedCloth.componentFlags.isHighHeels = isHighHeelsCheck.IsChecked.GetValueOrDefault(false);
227 | }
228 |
229 | private void ClearFPModel_Click(object sender, RoutedEventArgs e)
230 | {
231 | if (selectedCloth != null)
232 | selectedCloth.fpModelPath = "";
233 | fpModelPath.Text = "Not selected...";
234 | }
235 |
236 | private void SelectFPModel_Click(object sender, RoutedEventArgs e)
237 | {
238 | if (selectedCloth != null)
239 | ProjectController.Instance().SetFPModel(selectedCloth);
240 | fpModelPath.Text = selectedCloth.fpModelPath != "" ? selectedCloth.fpModelPath : "Not selected...";
241 | }
242 |
243 | private void PedPropName_TextChanged(object sender, TextChangedEventArgs e)
244 | {
245 | if (selectedCloth != null)
246 | {
247 | selectedCloth.Name = drawableName.Text;
248 | }
249 | }
250 |
251 | private void PedPropFlag1_Checked(object sender, RoutedEventArgs e)
252 | {
253 | if (selectedCloth != null)
254 | selectedCloth.pedPropFlags.unkFlag1 = unkFlag1Check.IsChecked.GetValueOrDefault(false);
255 | }
256 |
257 | private void PedPropFlag2_Checked(object sender, RoutedEventArgs e)
258 | {
259 | if (selectedCloth != null)
260 | selectedCloth.pedPropFlags.unkFlag2 = unkFlag1Check.IsChecked.GetValueOrDefault(false);
261 | }
262 |
263 | private void PedPropFlag3_Checked(object sender, RoutedEventArgs e)
264 | {
265 | if (selectedCloth != null)
266 | selectedCloth.pedPropFlags.unkFlag3 = unkFlag1Check.IsChecked.GetValueOrDefault(false);
267 | }
268 |
269 | private void PedPropFlag4_Checked(object sender, RoutedEventArgs e)
270 | {
271 | if (selectedCloth != null)
272 | selectedCloth.pedPropFlags.unkFlag4 = unkFlag1Check.IsChecked.GetValueOrDefault(false);
273 | }
274 |
275 | private void PedPropFlag5_Checked(object sender, RoutedEventArgs e)
276 | {
277 | if (selectedCloth != null)
278 | selectedCloth.pedPropFlags.unkFlag5 = unkFlag1Check.IsChecked.GetValueOrDefault(false);
279 | }
280 | }
281 | }
282 |
--------------------------------------------------------------------------------
/AltTool/ResourceBuilder.cs:
--------------------------------------------------------------------------------
1 | using RageLib.Archives;
2 | using RageLib.GTA5.Archives;
3 | using RageLib.GTA5.ArchiveWrappers;
4 | using RageLib.GTA5.ResourceWrappers.PC.Meta.Structures;
5 | using RageLib.Resources.GTA5.PC.GameFiles;
6 | using RageLib.Resources.GTA5.PC.Meta;
7 | using System;
8 | using System.Collections.Generic;
9 | using System.IO;
10 | using System.Linq;
11 | using System.Text;
12 | using System.Threading.Tasks;
13 | using System.Windows;
14 | using static AltTool.ClothData;
15 |
16 | namespace AltTool
17 | {
18 | public class ResourceBuilder
19 | {
20 | public static string GenerateShopMeta(Sex targetSex, string collectionName)
21 | {
22 | string targetName = targetSex == Sex.Male ? "mp_m_freemode_01" : "mp_f_freemode_01";
23 | string dlcName = (targetSex == Sex.Male ? "mp_m_" : "mp_f_") + collectionName;
24 | string character = (targetSex == Sex.Male ? "SCR_CHAR_MULTIPLAYER" : "SCR_CHAR_MULTIPLAYER_F");
25 | return $@"
26 |
27 | {targetName}
28 | {dlcName}
29 | {targetName}_{dlcName}
30 | {character}
31 | MP_CreatureMetadata_{collectionName}
32 |
33 |
34 |
35 |
36 |
37 |
38 | ";
39 | }
40 |
41 | public static string GenerateStreamCfg(List files, List metas)
42 | {
43 | string filesText = "";
44 | for(int i = 0; i < files.Count; ++i)
45 | {
46 | if (i != 0)
47 | filesText += "\n";
48 | filesText += " " + files[i];
49 | }
50 |
51 | string metasText = "";
52 | for(int i = 0; i < metas.Count; ++i)
53 | {
54 | if (i != 0)
55 | metasText += "\n";
56 | metasText += " " + metas[i];
57 | }
58 |
59 | return $"files: [\n{filesText}/*\n]\nmeta: {{\n{metasText}\n}}\n";
60 | }
61 |
62 | public static string GenerateResourceCfg()
63 | {
64 | return "type: dlc,\nmain: stream.cfg,\nclient-files: [\n stream/*\n]\n";
65 | }
66 |
67 | public static string GenerateResourceLua(List metas)
68 | {
69 | string filesText = "";
70 | for (int i = 0; i < metas.Count; ++i)
71 | {
72 | if (i != 0)
73 | filesText += ",\n";
74 | filesText += " '" + metas[i] + "'";
75 | }
76 |
77 | string metasText = "";
78 | for (int i = 0; i < metas.Count; ++i)
79 | {
80 | if (i != 0)
81 | metasText += "\n";
82 | metasText += "data_file 'SHOP_PED_APPAREL_META_FILE' '" + metas[i] + "'";
83 | }
84 |
85 | string manifestContent = "-- Generated with AltTool\n\n";
86 | manifestContent += "fx_version 'adamant'\n";
87 | manifestContent += "game 'gta5'\n\n";
88 | manifestContent += "files {{\n{filesText}\n}}\n\n{metasText}";
89 | return manifestContent;
90 | }
91 |
92 | public static string GenerateContentXML(string collectionName, bool hasMale, bool hasFemale, bool hasMaleProps, bool hasFemaleProps)
93 | {
94 | string str = $@"
95 |
96 |
97 |
98 |
99 |
100 | ";
101 |
102 | if(hasMale)
103 | {
104 | str += $@" -
105 | dlc_{collectionName}:/common/data/mp_m_freemode_01_mp_m_{collectionName}.meta
106 | SHOP_PED_APPAREL_META_FILE
107 |
108 |
109 |
110 |
111 | -
112 | dlc_{collectionName}:/%PLATFORM%/models/cdimages/{collectionName}_male.rpf
113 | RPF_FILE
114 |
115 |
116 |
117 |
118 | ";
119 | }
120 |
121 | if(hasFemale)
122 | {
123 | str += $@" -
124 | dlc_{collectionName}:/common/data/mp_f_freemode_01_mp_f_{collectionName}.meta
125 | SHOP_PED_APPAREL_META_FILE
126 |
127 |
128 |
129 |
130 | -
131 | dlc_{collectionName}:/%PLATFORM%/models/cdimages/{collectionName}_female.rpf
132 | RPF_FILE
133 |
134 |
135 |
136 |
137 | ";
138 | }
139 |
140 | if (hasMaleProps)
141 | {
142 | str += $@" -
143 | dlc_{collectionName}:/%PLATFORM%/models/cdimages/{collectionName}_male_p.rpf
144 | RPF_FILE
145 |
146 |
147 |
148 |
149 | ";
150 | }
151 |
152 | if (hasFemaleProps)
153 | {
154 | str += $@" -
155 | dlc_{collectionName}:/%PLATFORM%/models/cdimages/{collectionName}_female_p.rpf
156 | RPF_FILE
157 |
158 |
159 |
160 |
161 | ";
162 | }
163 |
164 | str += $@"
165 |
166 | -
167 | {collectionName.ToUpper()}_AUTOGEN
168 |
169 |
170 |
171 |
172 | ";
173 | if(hasMale)
174 | {
175 | str += $"
- dlc_{collectionName}:/common/data/mp_m_freemode_01_mp_m_{collectionName}.meta
\n";
176 | str += $" - dlc_{collectionName}:/%PLATFORM%/models/cdimages/{collectionName}_male.rpf
\n";
177 | }
178 |
179 | if(hasFemale)
180 | {
181 | str += $" - dlc_{collectionName}:/common/data/mp_f_freemode_01_mp_f_{collectionName}.meta
\n";
182 | str += $" - dlc_{collectionName}:/%PLATFORM%/models/cdimages/{collectionName}_female.rpf
\n";
183 | }
184 |
185 | if (hasMaleProps)
186 | {
187 | str += $" - dlc_{collectionName}:/%PLATFORM%/models/cdimages/{collectionName}_male_p.rpf
\n";
188 | }
189 |
190 | if (hasFemaleProps)
191 | {
192 | str += $" - dlc_{collectionName}:/%PLATFORM%/models/cdimages/{collectionName}_female_p.rpf
\n";
193 | }
194 |
195 | str += $@"
196 |
197 |
198 |
199 | ";
200 |
201 | return str;
202 | }
203 |
204 | public static string GenerateSetup2XML(string collectionName, int order = 1000)
205 | {
206 | return $@"
207 |
208 | dlc_{collectionName}
209 | content.xml
210 | 07/07/2077 07:07:07
211 | {collectionName}
212 |
213 |
214 | -
215 | GROUP_STARTUP
216 |
217 |
- {collectionName.ToUpper()}_AUTOGEN
218 |
219 |
220 |
221 |
222 |
223 | EXTRACONTENT_COMPAT_PACK
224 |
225 |
226 |
227 |
228 |
229 |
230 | ";
231 | }
232 |
233 | private static string[] prefixes = { "mp_m_", "mp_f_" };
234 | private static string[] folderNames = { "ped_male", "ped_female" };
235 |
236 | public static void BuildResourceAltv(string outputFolder, string collectionName)
237 | {
238 | List streamCfgMetas = new List();
239 | List streamCfgIncludes = new List();
240 | for(int sexNr = 0; sexNr < 2; ++sexNr)
241 | {
242 | //Male YMT generating
243 | YmtPedDefinitionFile ymt = new YmtPedDefinitionFile();
244 |
245 | ymt.metaYmtName = prefixes[sexNr] + collectionName;
246 | ymt.Unk_376833625.DlcName = RageLib.Hash.Jenkins.Hash(prefixes[sexNr] + collectionName);
247 |
248 | MUnk_3538495220[] componentTextureBindings = { null, null, null, null, null, null, null, null, null, null, null, null };
249 | int[] componentIndexes = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
250 | int[] propIndexes = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
251 |
252 | //ymt.Unk_376833625.Unk_1235281004 = 0;
253 | //ymt.Unk_376833625.Unk_4086467184 = 0;
254 | //ymt.Unk_376833625.Unk_911147899 = 0;
255 | //ymt.Unk_376833625.Unk_315291935 = 0;
256 | //ymt.Unk_376833625.Unk_2996560424 = ;
257 |
258 | bool isAnyClothAdded = false;
259 | bool isAnyPropAdded = false;
260 |
261 | foreach (ClothData cd in MainWindow.clothes)
262 | {
263 | if (cd.IsComponent())
264 | {
265 |
266 | byte componentTypeID = cd.GetComponentTypeID();
267 |
268 | if (cd.textures.Count > 0 && (int)cd.targetSex == sexNr)
269 | {
270 | YmtPedDefinitionFile targetYmt = ymt;
271 |
272 | if (componentTextureBindings[componentTypeID] == null)
273 | componentTextureBindings[componentTypeID] = new MUnk_3538495220();
274 |
275 | MUnk_1535046754 textureDescription = new MUnk_1535046754();
276 |
277 | byte nextPropMask = 17;
278 |
279 | switch (componentTypeID)
280 | {
281 | case 2:
282 | case 7:
283 | nextPropMask = 11; break;
284 | case 5:
285 | case 8:
286 | nextPropMask = 65; break;
287 | case 9:
288 | nextPropMask = 1; break;
289 | case 10:
290 | nextPropMask = 5; break;
291 | case 11:
292 | nextPropMask = 1; break;
293 | default:
294 | break;
295 | }
296 |
297 | textureDescription.PropMask = nextPropMask;
298 | textureDescription.Unk_2806194106 = (byte)(cd.fpModelPath != "" ? 1 : 0);
299 |
300 | byte texId = (byte)(cd.mainPath.EndsWith("_u.ydd") ? 0 : 1);
301 | string postfix = cd.mainPath.EndsWith("_u.ydd") ? "u" : "r";
302 | string ytdPostfix = cd.mainPath.EndsWith("_u.ydd") ? "uni" : "whi";
303 |
304 | if((cd.drawableType == ClothNameResolver.DrawableType.Shoes) || (cd.drawableType == ClothNameResolver.DrawableType.Accessories))
305 | {
306 | postfix = "r";
307 | ytdPostfix = "uni";
308 | }
309 |
310 | foreach (string texPath in cd.textures)
311 | {
312 | MUnk_1036962405 texInfo = new MUnk_1036962405();
313 | texInfo.Distribution = 255;
314 | texInfo.TexId = texId;
315 | textureDescription.ATexData.Add(texInfo);
316 | }
317 |
318 | textureDescription.ClothData.Unk_2828247905 = 0;
319 |
320 | componentTextureBindings[componentTypeID].Unk_1756136273.Add(textureDescription);
321 |
322 | byte componentTextureLocalId = (byte)(componentTextureBindings[componentTypeID].Unk_1756136273.Count - 1);
323 |
324 | MCComponentInfo componentInfo = new MCComponentInfo();
325 | componentInfo.Unk_802196719 = 0;
326 | componentInfo.Unk_4233133352 = 0;
327 | componentInfo.Unk_128864925.b0 = (byte)(cd.componentFlags.unkFlag1 ? 1 : 0);
328 | componentInfo.Unk_128864925.b1 = (byte)(cd.componentFlags.unkFlag2 ? 1 : 0);
329 | componentInfo.Unk_128864925.b2 = (byte)(cd.componentFlags.unkFlag3 ? 1 : 0);
330 | componentInfo.Unk_128864925.b3 = (byte)(cd.componentFlags.unkFlag4 ? 1 : 0);
331 | componentInfo.Unk_128864925.b4 = (byte)(cd.componentFlags.isHighHeels ? 1 : 0);
332 | componentInfo.Flags = 0;
333 | componentInfo.Inclusions = 0;
334 | componentInfo.Exclusions = 0;
335 | componentInfo.Unk_1613922652 = 0;
336 | componentInfo.Unk_2114993291 = 0;
337 | componentInfo.Unk_3509540765 = componentTypeID;
338 | componentInfo.Unk_4196345791 = componentTextureLocalId;
339 |
340 | targetYmt.Unk_376833625.CompInfos.Add(componentInfo);
341 |
342 | if (!isAnyClothAdded)
343 | {
344 | isAnyClothAdded = true;
345 | Directory.CreateDirectory(outputFolder + "\\stream");
346 | Directory.CreateDirectory(outputFolder + "\\stream\\" + folderNames[sexNr] + ".rpf");
347 | Directory.CreateDirectory(outputFolder + "\\stream\\" + folderNames[sexNr] + ".rpf\\" + prefixes[sexNr] + "freemode_01_" + prefixes[sexNr] + collectionName);
348 | }
349 |
350 | int currentComponentIndex = componentIndexes[componentTypeID]++;
351 |
352 | string componentNumerics = currentComponentIndex.ToString().PadLeft(3, '0');
353 | string prefix = cd.GetPrefix();
354 |
355 | File.Copy(cd.mainPath, outputFolder + "\\stream\\" + folderNames[sexNr] + ".rpf\\" + prefixes[sexNr] + "freemode_01_" + prefixes[sexNr] + collectionName + "\\" + prefix + "_" + componentNumerics + "_" + postfix + ".ydd");
356 |
357 | char offsetLetter = 'a';
358 | for (int i = 0; i < cd.textures.Count; ++i)
359 | File.Copy(cd.textures[i], outputFolder + "\\stream\\" + folderNames[sexNr] + ".rpf\\" + prefixes[sexNr] + "freemode_01_" + prefixes[sexNr] + collectionName + "\\" + prefix + "_diff_" + componentNumerics + "_" + (char)(offsetLetter + i) + "_" + ytdPostfix + ".ytd");
360 |
361 | if (cd.fpModelPath != "")
362 | File.Copy(cd.fpModelPath, outputFolder + "\\stream\\" + folderNames[sexNr] + ".rpf\\" + prefixes[sexNr] + "freemode_01_" + prefixes[sexNr] + collectionName + "\\" + prefix + "_" + componentNumerics + "_" + postfix + "_1.ydd");
363 | }
364 | }
365 | else
366 | {
367 | Unk_2834549053 anchor = (Unk_2834549053)cd.GetPedPropTypeID();
368 |
369 | if (cd.textures.Count > 0 && (int)cd.targetSex == sexNr)
370 | {
371 | YmtPedDefinitionFile targetYmt = ymt;
372 |
373 | var defs = ymt.Unk_376833625.PropInfo.Props[anchor] ?? new List();
374 | var item = new MUnk_94549140(ymt.Unk_376833625.PropInfo);
375 |
376 | item.AnchorId = (byte)anchor;
377 |
378 | for (int i = 0; i < cd.textures.Count; i++)
379 | {
380 | var texture = new MUnk_254518642();
381 | texture.TexId = (byte)i;
382 | item.TexData.Add(texture);
383 | }
384 |
385 | // Get or create linked anchor
386 | var aanchor = ymt.Unk_376833625.PropInfo.AAnchors.Find(e => e.Anchor == anchor);
387 |
388 | if (aanchor == null)
389 | {
390 | aanchor = new MCAnchorProps(ymt.Unk_376833625.PropInfo)
391 | {
392 | Anchor = anchor
393 | };
394 |
395 | aanchor.PropsMap[item] = (byte)item.TexData.Count;
396 |
397 | ymt.Unk_376833625.PropInfo.AAnchors.Add(aanchor);
398 | }
399 | else
400 | {
401 | aanchor.PropsMap[item] = (byte)item.TexData.Count;
402 | }
403 |
404 | defs.Add(item);
405 |
406 | if (!isAnyPropAdded)
407 | {
408 | isAnyPropAdded = true;
409 | Directory.CreateDirectory(outputFolder + "\\stream");
410 | Directory.CreateDirectory(outputFolder + "\\stream\\" + folderNames[sexNr] + "_p.rpf");
411 | Directory.CreateDirectory(outputFolder + "\\stream\\" + folderNames[sexNr] + "_p.rpf\\" + prefixes[sexNr] + "freemode_01_p_" + prefixes[sexNr] + collectionName);
412 | }
413 |
414 | int currentPropIndex = propIndexes[(byte)anchor]++;
415 |
416 | string componentNumerics = currentPropIndex.ToString().PadLeft(3, '0');
417 | string prefix = cd.GetPrefix();
418 |
419 | var ydr = new YdrFile();
420 |
421 | File.Copy(cd.mainPath, outputFolder + "\\stream\\" + folderNames[sexNr] + "_p.rpf\\" + prefixes[sexNr] + "freemode_01_p_" + prefixes[sexNr] + collectionName + "\\" + prefix + "_" + componentNumerics + ".ydd", true);
422 |
423 | char offsetLetter = 'a';
424 | for (int i = 0; i < cd.textures.Count; ++i)
425 | {
426 | File.Copy(cd.textures[i], outputFolder + "\\stream\\" + folderNames[sexNr] + "_p.rpf\\" + prefixes[sexNr] + "freemode_01_p_" + prefixes[sexNr] + collectionName + "\\" + prefix + "_diff_" + componentNumerics + "_" + (char)(offsetLetter + i) + ".ytd", true);
427 | }
428 | }
429 | }
430 | }
431 |
432 |
433 | if (isAnyClothAdded)
434 | {
435 |
436 | int arrIndex = 0;
437 | for (int i = 0; i < componentTextureBindings.Length; ++i)
438 | {
439 | if (componentTextureBindings[i] != null)
440 | {
441 | byte id = (byte)(arrIndex++);
442 | ymt.Unk_376833625.Unk_2996560424.SetByte(i, id);
443 | }
444 |
445 | ymt.Unk_376833625.Components[(Unk_884254308)i] = componentTextureBindings[i];
446 | }
447 | }
448 |
449 | if(isAnyPropAdded)
450 | {
451 | streamCfgIncludes.Add("stream/" + folderNames[sexNr] + "_p.rpf");
452 | }
453 |
454 | if (isAnyClothAdded || isAnyPropAdded)
455 | {
456 | File.WriteAllText(outputFolder + "\\stream\\" + prefixes[sexNr] + "freemode_01_" + prefixes[sexNr] + collectionName + ".meta", GenerateShopMeta((Sex)sexNr, collectionName));
457 | streamCfgMetas.Add("stream/" + prefixes[sexNr] + "freemode_01_" + prefixes[sexNr] + collectionName + ".meta: SHOP_PED_APPAREL_META_FILE");
458 | ymt.Save(outputFolder + "\\stream\\" + folderNames[sexNr] + ".rpf\\" + prefixes[sexNr] + "freemode_01_" + prefixes[sexNr] + collectionName + ".ymt");
459 | streamCfgIncludes.Add("stream/" + folderNames[sexNr] + ".rpf");
460 | }
461 |
462 | }
463 |
464 | File.WriteAllText(outputFolder + "\\stream.cfg", GenerateStreamCfg(streamCfgIncludes, streamCfgMetas));
465 | File.WriteAllText(outputFolder + "\\resource.cfg", GenerateResourceCfg());
466 |
467 | MessageBox.Show("Resource built!");
468 | }
469 |
470 | public static void BuildResourceSingle(string outputFolder, string collectionName)
471 | {
472 | Utils.EnsureKeys();
473 |
474 | using (RageArchiveWrapper7 rpf = RageArchiveWrapper7.Create(outputFolder + @"\dlc.rpf"))
475 | {
476 | rpf.archive_.Encryption = RageArchiveEncryption7.NG;
477 |
478 | var dir = rpf.Root.CreateDirectory();
479 | dir.Name = "common";
480 |
481 | var dataDir = dir.CreateDirectory();
482 | dataDir.Name = "data";
483 |
484 | dir = rpf.Root.CreateDirectory();
485 | dir.Name = "x64";
486 |
487 | dir = dir.CreateDirectory();
488 | dir.Name = "models";
489 |
490 | var cdimagesDir = dir.CreateDirectory();
491 | cdimagesDir.Name = "cdimages";
492 |
493 | RageArchiveWrapper7 currComponentRpf = null;
494 | IArchiveDirectory currComponentDir = null;
495 |
496 | RageArchiveWrapper7 currPropRpf = null;
497 | IArchiveDirectory currPropDir = null;
498 |
499 | bool hasMale = false;
500 | bool hasFemale = false;
501 | bool hasMaleProps = false;
502 | bool hasFemaleProps = false;
503 |
504 | for (int sexNr = 0; sexNr < 2; ++sexNr)
505 | {
506 | //Male YMT generating
507 | YmtPedDefinitionFile ymt = new YmtPedDefinitionFile();
508 |
509 | ymt.metaYmtName = prefixes[sexNr] + collectionName;
510 | ymt.Unk_376833625.DlcName = RageLib.Hash.Jenkins.Hash(prefixes[sexNr] + collectionName);
511 |
512 | MUnk_3538495220[] componentTextureBindings = { null, null, null, null, null, null, null, null, null, null, null, null };
513 | int[] componentIndexes = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
514 | int[] propIndexes = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
515 |
516 | //ymt.Unk_376833625.Unk_1235281004 = 0;
517 | //ymt.Unk_376833625.Unk_4086467184 = 0;
518 | //ymt.Unk_376833625.Unk_911147899 = 0;
519 | //ymt.Unk_376833625.Unk_315291935 = 0;
520 | //ymt.Unk_376833625.Unk_2996560424 = ;
521 |
522 | bool isAnyClothAdded = false;
523 | bool isAnyPropAdded = false;
524 |
525 | foreach (ClothData cd in MainWindow.clothes)
526 | {
527 | if (cd.IsComponent())
528 | {
529 | byte componentTypeID = cd.GetComponentTypeID();
530 |
531 | if (cd.textures.Count > 0 && (int)cd.targetSex == sexNr)
532 | {
533 | YmtPedDefinitionFile targetYmt = ymt;
534 |
535 | if (componentTextureBindings[componentTypeID] == null)
536 | componentTextureBindings[componentTypeID] = new MUnk_3538495220();
537 |
538 | MUnk_1535046754 textureDescription = new MUnk_1535046754();
539 |
540 | byte nextPropMask = 17;
541 |
542 | switch (componentTypeID)
543 | {
544 | case 2:
545 | case 7:
546 | nextPropMask = 11; break;
547 | case 5:
548 | case 8:
549 | nextPropMask = 65; break;
550 | case 9:
551 | nextPropMask = 1; break;
552 | case 10:
553 | nextPropMask = 5; break;
554 | case 11:
555 | nextPropMask = 1; break;
556 | default:
557 | break;
558 | }
559 |
560 | textureDescription.PropMask = nextPropMask;
561 | textureDescription.Unk_2806194106 = (byte)(cd.fpModelPath != "" ? 1 : 0);
562 |
563 | byte texId = (byte)(cd.mainPath.EndsWith("_u.ydd") ? 0 : 1);
564 | string postfix = cd.mainPath.EndsWith("_u.ydd") ? "u" : "r";
565 | string ytdPostfix = cd.mainPath.EndsWith("_u.ydd") ? "uni" : "whi";
566 |
567 | foreach (string texPath in cd.textures)
568 | {
569 | MUnk_1036962405 texInfo = new MUnk_1036962405();
570 | texInfo.Distribution = 255;
571 | texInfo.TexId = texId;
572 | textureDescription.ATexData.Add(texInfo);
573 | }
574 |
575 | textureDescription.ClothData.Unk_2828247905 = 0;
576 |
577 | componentTextureBindings[componentTypeID].Unk_1756136273.Add(textureDescription);
578 |
579 | byte componentTextureLocalId = (byte)(componentTextureBindings[componentTypeID].Unk_1756136273.Count - 1);
580 |
581 | MCComponentInfo componentInfo = new MCComponentInfo();
582 | componentInfo.Unk_802196719 = 0;
583 | componentInfo.Unk_4233133352 = 0;
584 | componentInfo.Unk_128864925.b0 = (byte)(cd.componentFlags.unkFlag1 ? 1 : 0);
585 | componentInfo.Unk_128864925.b1 = (byte)(cd.componentFlags.unkFlag2 ? 1 : 0);
586 | componentInfo.Unk_128864925.b2 = (byte)(cd.componentFlags.unkFlag3 ? 1 : 0);
587 | componentInfo.Unk_128864925.b3 = (byte)(cd.componentFlags.unkFlag4 ? 1 : 0);
588 | componentInfo.Unk_128864925.b4 = (byte)(cd.componentFlags.isHighHeels ? 1 : 0);
589 | componentInfo.Flags = 0;
590 | componentInfo.Inclusions = 0;
591 | componentInfo.Exclusions = 0;
592 | componentInfo.Unk_1613922652 = 0;
593 | componentInfo.Unk_2114993291 = 0;
594 | componentInfo.Unk_3509540765 = componentTypeID;
595 | componentInfo.Unk_4196345791 = componentTextureLocalId;
596 |
597 | targetYmt.Unk_376833625.CompInfos.Add(componentInfo);
598 |
599 | if (!isAnyClothAdded)
600 | {
601 | isAnyClothAdded = true;
602 |
603 | var ms = new MemoryStream();
604 |
605 | currComponentRpf = RageArchiveWrapper7.Create(ms, folderNames[sexNr].Replace("ped_", collectionName + "_") + ".rpf");
606 | currComponentRpf.archive_.Encryption = RageArchiveEncryption7.NG;
607 | currComponentDir = currComponentRpf.Root.CreateDirectory();
608 | currComponentDir.Name = prefixes[sexNr] + "freemode_01_" + prefixes[sexNr] + collectionName;
609 | }
610 |
611 | int currentComponentIndex = componentIndexes[componentTypeID]++;
612 |
613 | string componentNumerics = currentComponentIndex.ToString().PadLeft(3, '0');
614 | string prefix = cd.GetPrefix();
615 |
616 | var resource = currComponentDir.CreateResourceFile();
617 | resource.Name = prefix + "_" + componentNumerics + "_" + postfix + ".ydd";
618 | resource.Import(cd.mainPath);
619 |
620 | char offsetLetter = 'a';
621 |
622 | for (int i = 0; i < cd.textures.Count; ++i)
623 | {
624 | resource = currComponentDir.CreateResourceFile();
625 | resource.Name = prefix + "_diff_" + componentNumerics + "_" + (char)(offsetLetter + i) + "_" + ytdPostfix + ".ytd";
626 | resource.Import(cd.textures[i]);
627 | }
628 |
629 | if (cd.fpModelPath != "")
630 | {
631 | resource = currComponentDir.CreateResourceFile();
632 | resource.Name = prefix + "_" + componentNumerics + "_" + postfix + "_1.ydd";
633 | resource.Import(cd.fpModelPath);
634 | }
635 |
636 | }
637 | }
638 | else
639 | {
640 | Unk_2834549053 anchor = (Unk_2834549053)cd.GetPedPropTypeID();
641 |
642 | if (cd.textures.Count > 0 && (int)cd.targetSex == sexNr)
643 | {
644 | YmtPedDefinitionFile targetYmt = ymt;
645 |
646 | var defs = ymt.Unk_376833625.PropInfo.Props[anchor] ?? new List();
647 | var item = new MUnk_94549140(ymt.Unk_376833625.PropInfo);
648 |
649 | item.AnchorId = (byte)anchor;
650 |
651 | for (int i = 0; i < cd.textures.Count; i++)
652 | {
653 | var texture = new MUnk_254518642();
654 | texture.TexId = (byte)i;
655 | item.TexData.Add(texture);
656 | }
657 |
658 | // Get or create linked anchor
659 | var aanchor = ymt.Unk_376833625.PropInfo.AAnchors.Find(e => e.Anchor == anchor);
660 |
661 | if (aanchor == null)
662 | {
663 | aanchor = new MCAnchorProps(ymt.Unk_376833625.PropInfo)
664 | {
665 | Anchor = anchor
666 | };
667 |
668 | aanchor.PropsMap[item] = (byte)item.TexData.Count;
669 |
670 | ymt.Unk_376833625.PropInfo.AAnchors.Add(aanchor);
671 | }
672 | else
673 | {
674 | aanchor.PropsMap[item] = (byte)item.TexData.Count;
675 | }
676 |
677 | defs.Add(item);
678 |
679 | if (!isAnyPropAdded)
680 | {
681 | isAnyPropAdded = true;
682 |
683 | var ms = new MemoryStream();
684 |
685 | currPropRpf = RageArchiveWrapper7.Create(ms, folderNames[sexNr].Replace("ped_", collectionName + "_") + "_p.rpf");
686 | currPropRpf.archive_.Encryption = RageArchiveEncryption7.NG;
687 | currPropDir = currPropRpf.Root.CreateDirectory();
688 | currPropDir.Name = prefixes[sexNr] + "freemode_01_p_" + prefixes[sexNr] + collectionName;
689 | }
690 |
691 | int currentPropIndex = propIndexes[(byte)anchor]++;
692 |
693 | string componentNumerics = currentPropIndex.ToString().PadLeft(3, '0');
694 | string prefix = cd.GetPrefix();
695 |
696 | var resource = currPropDir.CreateResourceFile();
697 | resource.Name = prefix + "_" + componentNumerics + ".ydd";
698 | resource.Import(cd.mainPath);
699 |
700 | char offsetLetter = 'a';
701 | for (int i = 0; i < cd.textures.Count; ++i)
702 | {
703 | resource = currPropDir.CreateResourceFile();
704 | resource.Name = prefix + "_diff_" + componentNumerics + "_" + (char)(offsetLetter + i) + ".ytd";
705 | resource.Import(cd.textures[i]);
706 | }
707 | }
708 | }
709 | }
710 |
711 | if (isAnyClothAdded)
712 | {
713 | if (sexNr == 0)
714 | hasMale = true;
715 | else if (sexNr == 1)
716 | hasFemale = true;
717 |
718 | int arrIndex = 0;
719 | for (int i = 0; i < componentTextureBindings.Length; ++i)
720 | {
721 | if (componentTextureBindings[i] != null)
722 | {
723 | byte id = (byte)(arrIndex++);
724 | ymt.Unk_376833625.Unk_2996560424.SetByte(i, id);
725 | }
726 |
727 | ymt.Unk_376833625.Components[(Unk_884254308)i] = componentTextureBindings[i];
728 | }
729 | }
730 |
731 | if (isAnyClothAdded || isAnyPropAdded)
732 | {
733 | using (MemoryStream stream = new MemoryStream(Encoding.UTF8.GetBytes(GenerateShopMeta((Sex)sexNr, collectionName))))
734 | {
735 | var binFile = dataDir.CreateBinaryFile();
736 | binFile.Name = prefixes[sexNr] + "freemode_01_" + prefixes[sexNr] + collectionName + ".meta";
737 | binFile.Import(stream);
738 | }
739 | currComponentRpf.Flush();
740 |
741 | var binRpfFile = cdimagesDir.CreateBinaryFile();
742 | binRpfFile.Name = folderNames[sexNr].Replace("ped_", collectionName + "_") + ".rpf";
743 | binRpfFile.Import(currComponentRpf.archive_.BaseStream);
744 |
745 | currComponentRpf.Dispose();
746 | }
747 |
748 | if (isAnyPropAdded)
749 | {
750 | if (sexNr == 0)
751 | hasMaleProps = true;
752 | else if (sexNr == 1)
753 | hasFemaleProps = true;
754 |
755 | currPropRpf.Flush();
756 |
757 | var binRpfFile = cdimagesDir.CreateBinaryFile();
758 | binRpfFile.Name = folderNames[sexNr].Replace("ped_", collectionName + "_") + "_p.rpf";
759 | binRpfFile.Import(currPropRpf.archive_.BaseStream);
760 |
761 | currPropRpf.Dispose();
762 | }
763 | }
764 |
765 | using (MemoryStream stream = new MemoryStream(Encoding.UTF8.GetBytes(GenerateContentXML(collectionName, hasMale, hasFemale, hasMaleProps, hasFemaleProps))))
766 | {
767 | var binFile = rpf.Root.CreateBinaryFile();
768 | binFile.Name = "content.xml";
769 | binFile.Import(stream);
770 | }
771 |
772 | using (MemoryStream stream = new MemoryStream(Encoding.UTF8.GetBytes(GenerateSetup2XML(collectionName))))
773 | {
774 | var binFile = rpf.Root.CreateBinaryFile();
775 | binFile.Name = "setup2.xml";
776 | binFile.Import(stream);
777 | }
778 |
779 | rpf.Flush();
780 | rpf.Dispose();
781 |
782 | MessageBox.Show("Resource built!");
783 | }
784 | }
785 |
786 | public static void BuildResourceFivem(string outputFolder, string collectionName)
787 | {
788 | List resourceLUAMetas = new List();
789 |
790 | for(int sexNr = 0; sexNr < 2; ++sexNr)
791 | {
792 | //Male YMT generating
793 | YmtPedDefinitionFile ymt = new YmtPedDefinitionFile();
794 |
795 | ymt.metaYmtName = prefixes[sexNr] + collectionName;
796 | ymt.Unk_376833625.DlcName = RageLib.Hash.Jenkins.Hash(prefixes[sexNr] + collectionName);
797 |
798 | MUnk_3538495220[] componentTextureBindings = { null, null, null, null, null, null, null, null, null, null, null, null };
799 | int[] componentIndexes = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
800 | int[] propIndexes = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
801 |
802 | //ymt.Unk_376833625.Unk_1235281004 = 0;
803 | //ymt.Unk_376833625.Unk_4086467184 = 0;
804 | //ymt.Unk_376833625.Unk_911147899 = 0;
805 | //ymt.Unk_376833625.Unk_315291935 = 0;
806 | //ymt.Unk_376833625.Unk_2996560424 = ;
807 |
808 | bool isAnyClothAdded = false;
809 | bool isAnyPropAdded = false;
810 |
811 | foreach (ClothData cd in MainWindow.clothes)
812 | {
813 | if (cd.IsComponent())
814 | {
815 | byte componentTypeID = cd.GetComponentTypeID();
816 |
817 | if (cd.textures.Count > 0 && (int)cd.targetSex == sexNr)
818 | {
819 | YmtPedDefinitionFile targetYmt = ymt;
820 |
821 | if (componentTextureBindings[componentTypeID] == null)
822 | componentTextureBindings[componentTypeID] = new MUnk_3538495220();
823 |
824 | MUnk_1535046754 textureDescription = new MUnk_1535046754();
825 |
826 | byte nextPropMask = 17;
827 |
828 | switch (componentTypeID)
829 | {
830 | case 2:
831 | case 7:
832 | nextPropMask = 11; break;
833 | case 5:
834 | case 8:
835 | nextPropMask = 65; break;
836 | case 9:
837 | nextPropMask = 1; break;
838 | case 10:
839 | nextPropMask = 5; break;
840 | case 11:
841 | nextPropMask = 1; break;
842 | default:
843 | break;
844 | }
845 |
846 | textureDescription.PropMask = nextPropMask;
847 | textureDescription.Unk_2806194106 = (byte)(cd.fpModelPath != "" ? 1 : 0);
848 |
849 | byte texId = (byte)(cd.mainPath.EndsWith("_u.ydd") ? 0 : 1);
850 | string postfix = cd.mainPath.EndsWith("_u.ydd") ? "u" : "r";
851 | string ytdPostfix = cd.mainPath.EndsWith("_u.ydd") ? "uni" : "whi";
852 |
853 | foreach (string texPath in cd.textures)
854 | {
855 | MUnk_1036962405 texInfo = new MUnk_1036962405();
856 | texInfo.Distribution = 255;
857 | texInfo.TexId = texId;
858 | textureDescription.ATexData.Add(texInfo);
859 | }
860 |
861 | textureDescription.ClothData.Unk_2828247905 = 0;
862 |
863 | componentTextureBindings[componentTypeID].Unk_1756136273.Add(textureDescription);
864 |
865 | byte componentTextureLocalId = (byte)(componentTextureBindings[componentTypeID].Unk_1756136273.Count - 1);
866 |
867 | MCComponentInfo componentInfo = new MCComponentInfo();
868 | componentInfo.Unk_802196719 = 0;
869 | componentInfo.Unk_4233133352 = 0;
870 | componentInfo.Unk_128864925.b0 = (byte)(cd.componentFlags.unkFlag1 ? 1 : 0);
871 | componentInfo.Unk_128864925.b1 = (byte)(cd.componentFlags.unkFlag2 ? 1 : 0);
872 | componentInfo.Unk_128864925.b2 = (byte)(cd.componentFlags.unkFlag3 ? 1 : 0);
873 | componentInfo.Unk_128864925.b3 = (byte)(cd.componentFlags.unkFlag4 ? 1 : 0);
874 | componentInfo.Unk_128864925.b4 = (byte)(cd.componentFlags.isHighHeels ? 1 : 0);
875 | componentInfo.Flags = 0;
876 | componentInfo.Inclusions = 0;
877 | componentInfo.Exclusions = 0;
878 | componentInfo.Unk_1613922652 = 0;
879 | componentInfo.Unk_2114993291 = 0;
880 | componentInfo.Unk_3509540765 = componentTypeID;
881 | componentInfo.Unk_4196345791 = componentTextureLocalId;
882 |
883 | targetYmt.Unk_376833625.CompInfos.Add(componentInfo);
884 |
885 | if (!isAnyClothAdded)
886 | {
887 | isAnyClothAdded = true;
888 | Directory.CreateDirectory(outputFolder + "\\stream");
889 | Directory.CreateDirectory(outputFolder + "\\stream\\" + prefixes[sexNr] + "freemode_01_" + prefixes[sexNr] + collectionName);
890 | }
891 |
892 | int currentComponentIndex = componentIndexes[componentTypeID]++;
893 |
894 | string componentNumerics = currentComponentIndex.ToString().PadLeft(3, '0');
895 | string prefix = cd.GetPrefix();
896 |
897 | File.Copy(cd.mainPath, outputFolder + "\\stream\\" + prefixes[sexNr] + "freemode_01_" + prefixes[sexNr] + collectionName + "\\" + prefixes[sexNr] + "freemode_01_" + prefixes[sexNr] + collectionName + "^" + prefix + "_" + componentNumerics + "_" + postfix + ".ydd", true);
898 |
899 | char offsetLetter = 'a';
900 | for (int i = 0; i < cd.textures.Count; ++i)
901 | File.Copy(cd.textures[i], outputFolder + "\\stream\\" + prefixes[sexNr] + "freemode_01_" + prefixes[sexNr] + collectionName + "\\" + prefixes[sexNr] + "freemode_01_" + prefixes[sexNr] + collectionName + "^" + prefix + "_diff_" + componentNumerics + "_" + (char)(offsetLetter + i) + "_" + ytdPostfix + ".ytd", true);
902 |
903 | if (cd.fpModelPath != "")
904 | File.Copy(cd.fpModelPath, outputFolder + "\\stream\\" + prefixes[sexNr] + "freemode_01_" + prefixes[sexNr] + collectionName + "\\" + prefixes[sexNr] + "freemode_01_" + prefixes[sexNr] + collectionName + "^" + prefix + "_" + componentNumerics + "_" + postfix + "_1.ydd", true);
905 | }
906 | }
907 | else
908 | {
909 | Unk_2834549053 anchor = (Unk_2834549053)cd.GetPedPropTypeID();
910 |
911 | if (cd.textures.Count > 0 && (int)cd.targetSex == sexNr)
912 | {
913 | YmtPedDefinitionFile targetYmt = ymt;
914 |
915 | var defs = ymt.Unk_376833625.PropInfo.Props[anchor] ?? new List();
916 | var item = new MUnk_94549140(ymt.Unk_376833625.PropInfo);
917 |
918 | item.AnchorId = (byte)anchor;
919 |
920 | for (int i = 0; i < cd.textures.Count; i++)
921 | {
922 | var texture = new MUnk_254518642();
923 | texture.TexId = (byte)i;
924 | item.TexData.Add(texture);
925 | }
926 |
927 | // Get or create linked anchor
928 | var aanchor = ymt.Unk_376833625.PropInfo.AAnchors.Find(e => e.Anchor == anchor);
929 |
930 | if (aanchor == null)
931 | {
932 | aanchor = new MCAnchorProps(ymt.Unk_376833625.PropInfo)
933 | {
934 | Anchor = anchor
935 | };
936 |
937 | aanchor.PropsMap[item] = (byte)item.TexData.Count;
938 |
939 | ymt.Unk_376833625.PropInfo.AAnchors.Add(aanchor);
940 | }
941 | else
942 | {
943 | aanchor.PropsMap[item] = (byte)item.TexData.Count;
944 | }
945 |
946 | defs.Add(item);
947 |
948 | if (!isAnyPropAdded)
949 | {
950 | isAnyPropAdded = true;
951 | Directory.CreateDirectory(outputFolder + "\\stream");
952 | Directory.CreateDirectory(outputFolder + "\\stream\\" + prefixes[sexNr] + "freemode_01_p_" + prefixes[sexNr] + collectionName);
953 | }
954 |
955 | int currentPropIndex = propIndexes[(byte)anchor]++;
956 |
957 | string componentNumerics = currentPropIndex.ToString().PadLeft(3, '0');
958 | string prefix = cd.GetPrefix();
959 |
960 | File.Copy(cd.mainPath, outputFolder + "\\stream\\" + prefixes[sexNr] + "freemode_01_p_" + prefixes[sexNr] + collectionName + "\\" + prefixes[sexNr] + "freemode_01_p_" + prefixes[sexNr] + collectionName + "^" + prefix + "_" + componentNumerics + ".ydd", true);
961 |
962 | char offsetLetter = 'a';
963 | for (int i = 0; i < cd.textures.Count; ++i)
964 | {
965 | File.Copy(cd.textures[i], outputFolder + "\\stream\\" + prefixes[sexNr] + "freemode_01_p_" + prefixes[sexNr] + collectionName + "\\" + prefixes[sexNr] + "freemode_01_p_" + prefixes[sexNr] + collectionName + "^" + prefix + "_diff_" + componentNumerics + "_" + (char)(offsetLetter + i) + ".ytd", true);
966 | }
967 | }
968 | }
969 | }
970 |
971 |
972 | if (isAnyClothAdded)
973 | {
974 |
975 | int arrIndex = 0;
976 | for (int i = 0; i < componentTextureBindings.Length; ++i)
977 | {
978 | if (componentTextureBindings[i] != null)
979 | {
980 | byte id = (byte)(arrIndex++);
981 | ymt.Unk_376833625.Unk_2996560424.SetByte(i, id);
982 | }
983 |
984 | ymt.Unk_376833625.Components[(Unk_884254308)i] = componentTextureBindings[i];
985 | }
986 | }
987 |
988 | if(isAnyClothAdded || isAnyPropAdded)
989 | {
990 | ymt.Save(outputFolder + "\\stream\\" + prefixes[sexNr] + "freemode_01_" + prefixes[sexNr] + collectionName + ".ymt");
991 | File.WriteAllText(outputFolder + "\\" + prefixes[sexNr] + "freemode_01_" + prefixes[sexNr] + collectionName + ".meta", GenerateShopMeta((Sex)sexNr, collectionName));
992 | resourceLUAMetas.Add(prefixes[sexNr] + "freemode_01_" + prefixes[sexNr] + collectionName + ".meta");
993 | }
994 | }
995 |
996 | File.WriteAllText(outputFolder + "\\fxmanifest.lua", GenerateResourceLua(resourceLUAMetas));
997 |
998 | MessageBox.Show("Resource built!");
999 | }
1000 | }
1001 | }
1002 |
--------------------------------------------------------------------------------