├── .gitignore
├── MultiConverter.GUI
├── About.Designer.cs
├── About.cs
├── About.resx
├── MainForm.Designer.cs
├── MainForm.cs
├── MainForm.resx
├── MultiConverter.GUI.csproj
└── Program.cs
├── MultiConverter.Lib
├── Common
│ ├── C3Vector.cs
│ ├── C4Plane.cs
│ ├── CAaBox.cs
│ └── CArgb.cs
├── Converters
│ ├── ADT
│ │ └── ADTFile.cs
│ ├── AdtConverter.cs
│ ├── AnimConverter.cs
│ ├── Base
│ │ ├── ChunkedWowFile.cs
│ │ ├── IChunk.cs
│ │ ├── IConverter.cs
│ │ └── WowFile.cs
│ ├── Chunks.cs
│ ├── ModelConverter.cs
│ ├── SkinConverter.cs
│ ├── WDTConverter.cs
│ ├── WMO
│ │ ├── Chunks
│ │ │ ├── MFOG.cs
│ │ │ ├── MODD.cs
│ │ │ ├── MODI.cs
│ │ │ ├── MODN.cs
│ │ │ ├── MODS.cs
│ │ │ ├── MOGI.cs
│ │ │ ├── MOGN.cs
│ │ │ ├── MOHD.cs
│ │ │ ├── MOLT.cs
│ │ │ ├── MOMT.cs
│ │ │ ├── MOPR.cs
│ │ │ ├── MOPT.cs
│ │ │ ├── MOPV.cs
│ │ │ ├── MOSB.cs
│ │ │ ├── MOTX.cs
│ │ │ ├── MOVB.cs
│ │ │ ├── MOVV.cs
│ │ │ └── MVER.cs
│ │ ├── Entries
│ │ │ ├── MFOGEntry.cs
│ │ │ ├── MODDEntry.cs
│ │ │ ├── MODSEntry.cs
│ │ │ ├── MOGIEntry.cs
│ │ │ ├── MOHDEntry.cs
│ │ │ ├── MOLTEntry.cs
│ │ │ ├── MOMTEntry.cs
│ │ │ ├── MOPREntry.cs
│ │ │ ├── MOPTEntry.cs
│ │ │ └── MOPVEntry.cs
│ │ └── WMOFile.cs
│ └── WMOGroupConverter.cs
├── MultiConverter.Lib.csproj
├── Updater
│ ├── Update.cs
│ └── UpdateManager.cs
└── Util
│ ├── Extensions.cs
│ ├── Listfile.cs
│ └── Utils.cs
├── MultiConverter.Updater
├── MainForm.Designer.cs
├── MainForm.cs
├── MainForm.resx
├── MultiConverter.Updater.csproj
├── Program.cs
└── Updater
│ ├── Update.cs
│ └── UpdateManager.cs
├── MultiConverter.sln
├── README.MD
├── update.json
└── update_beta.json
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 |
4 | # User-specific files
5 | *.suo
6 | *.user
7 | *.userosscache
8 | *.sln.docstates
9 | Changes.txt
10 |
11 | # User-specific files (MonoDevelop/Xamarin Studio)
12 | *.userprefs
13 |
14 | # Build results
15 | [Dd]ebug/
16 | [Dd]ebugPublic/
17 | [Rr]elease/
18 | [Rr]eleases/
19 | bld/
20 | [Bb]in/
21 | [Oo]bj/
22 | [Ll]og/
23 |
24 | # Visual Studio 2015 cache/options directory
25 | .vs/
26 | # Uncomment if you have tasks that create the project's static files in wwwroot
27 | #wwwroot/
28 |
29 | # MSTest test Results
30 | [Tt]est[Rr]esult*/
31 | [Bb]uild[Ll]og.*
32 |
33 | # NUNIT
34 | *.VisualState.xml
35 | TestResult.xml
36 |
37 | # Build Results of an ATL Project
38 | [Dd]ebugPS/
39 | [Rr]eleasePS/
40 | dlldata.c
41 |
42 | # DNX
43 | project.lock.json
44 | artifacts/
45 |
46 | *_i.c
47 | *_p.c
48 | *_i.h
49 | *.ilk
50 | *.meta
51 | *.obj
52 | *.pch
53 | *.pdb
54 | *.pgc
55 | *.pgd
56 | *.rsp
57 | *.sbr
58 | *.tlb
59 | *.tli
60 | *.tlh
61 | *.tmp
62 | *.tmp_proj
63 | *.log
64 | *.vspscc
65 | *.vssscc
66 | .builds
67 | *.pidb
68 | *.svclog
69 | *.scc
70 |
71 | # Chutzpah Test files
72 | _Chutzpah*
73 |
74 | # Visual C++ cache files
75 | ipch/
76 | *.aps
77 | *.ncb
78 | *.opendb
79 | *.opensdf
80 | *.sdf
81 | *.cachefile
82 | *.VC.db
83 | *.VC.VC.opendb
84 |
85 | # Visual Studio profiler
86 | *.psess
87 | *.vsp
88 | *.vspx
89 | *.sap
90 |
91 | # TFS 2012 Local Workspace
92 | $tf/
93 |
94 | # Guidance Automation Toolkit
95 | *.gpState
96 |
97 | # ReSharper is a .NET coding add-in
98 | _ReSharper*/
99 | *.[Rr]e[Ss]harper
100 | *.DotSettings.user
101 |
102 | # JustCode is a .NET coding add-in
103 | .JustCode
104 |
105 | # TeamCity is a build add-in
106 | _TeamCity*
107 |
108 | # DotCover is a Code Coverage Tool
109 | *.dotCover
110 |
111 | # NCrunch
112 | _NCrunch_*
113 | .*crunch*.local.xml
114 | nCrunchTemp_*
115 |
116 | # MightyMoose
117 | *.mm.*
118 | AutoTest.Net/
119 |
120 | # Web workbench (sass)
121 | .sass-cache/
122 |
123 | # Installshield output folder
124 | [Ee]xpress/
125 |
126 | # DocProject is a documentation generator add-in
127 | DocProject/buildhelp/
128 | DocProject/Help/*.HxT
129 | DocProject/Help/*.HxC
130 | DocProject/Help/*.hhc
131 | DocProject/Help/*.hhk
132 | DocProject/Help/*.hhp
133 | DocProject/Help/Html2
134 | DocProject/Help/html
135 |
136 | # Click-Once directory
137 | publish/
138 |
139 | # Publish Web Output
140 | *.[Pp]ublish.xml
141 | *.azurePubxml
142 | # TODO: Comment the next line if you want to checkin your web deploy settings
143 | # but database connection strings (with potential passwords) will be unencrypted
144 | *.pubxml
145 | *.publishproj
146 |
147 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
148 | # checkin your Azure Web App publish settings, but sensitive information contained
149 | # in these scripts will be unencrypted
150 | PublishScripts/
151 |
152 | # NuGet Packages
153 | *.nupkg
154 | # The packages folder can be ignored because of Package Restore
155 | **/packages/*
156 | # except build/, which is used as an MSBuild target.
157 | !**/packages/build/
158 | # Uncomment if necessary however generally it will be regenerated when needed
159 | #!**/packages/repositories.config
160 | # NuGet v3's project.json files produces more ignoreable files
161 | *.nuget.props
162 | *.nuget.targets
163 |
164 | # Microsoft Azure Build Output
165 | csx/
166 | *.build.csdef
167 |
168 | # Microsoft Azure Emulator
169 | ecf/
170 | rcf/
171 |
172 | # Windows Store app package directories and files
173 | AppPackages/
174 | BundleArtifacts/
175 | Package.StoreAssociation.xml
176 | _pkginfo.txt
177 |
178 | # Visual Studio cache files
179 | # files ending in .cache can be ignored
180 | *.[Cc]ache
181 | # but keep track of directories ending in .cache
182 | !*.[Cc]ache/
183 |
184 | # Others
185 | ClientBin/
186 | ~$*
187 | *~
188 | *.dbmdl
189 | *.dbproj.schemaview
190 | *.publishsettings
191 | node_modules/
192 | orleans.codegen.cs
193 |
194 | # Since there are multiple workflows, uncomment next line to ignore bower_components
195 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
196 | #bower_components/
197 |
198 | # RIA/Silverlight projects
199 | Generated_Code/
200 |
201 | # Backup & report files from converting an old project file
202 | # to a newer Visual Studio version. Backup files are not needed,
203 | # because we have git ;-)
204 | _UpgradeReport_Files/
205 | UpgradeLog*.XML
206 | UpgradeLog*.htm
207 |
208 | # SQL Server files
209 | *.mdf
210 | *.ldf
211 |
212 | # Business Intelligence projects
213 | *.rdl.data
214 | *.bim.layout
215 | *.bim_*.settings
216 |
217 | # Microsoft Fakes
218 | FakesAssemblies/
219 |
220 | # GhostDoc plugin setting file
221 | *.GhostDoc.xml
222 |
223 | # Node.js Tools for Visual Studio
224 | .ntvs_analysis.dat
225 |
226 | # Visual Studio 6 build log
227 | *.plg
228 |
229 | # Visual Studio 6 workspace options file
230 | *.opt
231 |
232 | # Visual Studio LightSwitch build output
233 | **/*.HTMLClient/GeneratedArtifacts
234 | **/*.DesktopClient/GeneratedArtifacts
235 | **/*.DesktopClient/ModelManifest.xml
236 | **/*.Server/GeneratedArtifacts
237 | **/*.Server/ModelManifest.xml
238 | _Pvt_Extensions
239 |
240 | # Paket dependency manager
241 | .paket/paket.exe
242 | paket-files/
243 |
244 | # FAKE - F# Make
245 | .fake/
246 |
247 | # JetBrains Rider
248 | .idea/
249 | *.sln.iml
250 |
--------------------------------------------------------------------------------
/MultiConverter.GUI/About.Designer.cs:
--------------------------------------------------------------------------------
1 | namespace MultiConverter.GUI
2 | {
3 | partial class About
4 | {
5 | ///
6 | /// Required designer variable.
7 | ///
8 | private System.ComponentModel.IContainer components = null;
9 |
10 | ///
11 | /// Clean up any resources being used.
12 | ///
13 | protected override void Dispose(bool disposing)
14 | {
15 | if (disposing && (components != null))
16 | {
17 | components.Dispose();
18 | }
19 | base.Dispose(disposing);
20 | }
21 |
22 | #region Windows Form Designer generated code
23 |
24 | ///
25 | /// Required method for Designer support - do not modify
26 | /// the contents of this method with the code editor.
27 | ///
28 | private void InitializeComponent()
29 | {
30 | this.tableLayoutPanel = new System.Windows.Forms.TableLayoutPanel();
31 | this.labelProductName = new System.Windows.Forms.Label();
32 | this.labelVersion = new System.Windows.Forms.Label();
33 | this.labelCopyright = new System.Windows.Forms.Label();
34 | this.labelCompanyName = new System.Windows.Forms.Label();
35 | this.textBoxDescription = new System.Windows.Forms.TextBox();
36 | this.okButton = new System.Windows.Forms.Button();
37 | this.tableLayoutPanel.SuspendLayout();
38 | this.SuspendLayout();
39 | //
40 | // tableLayoutPanel
41 | //
42 | this.tableLayoutPanel.ColumnCount = 1;
43 | this.tableLayoutPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
44 | this.tableLayoutPanel.Controls.Add(this.labelProductName, 0, 0);
45 | this.tableLayoutPanel.Controls.Add(this.labelVersion, 0, 1);
46 | this.tableLayoutPanel.Controls.Add(this.labelCopyright, 0, 2);
47 | this.tableLayoutPanel.Controls.Add(this.labelCompanyName, 0, 3);
48 | this.tableLayoutPanel.Controls.Add(this.textBoxDescription, 0, 4);
49 | this.tableLayoutPanel.Controls.Add(this.okButton, 0, 5);
50 | this.tableLayoutPanel.Dock = System.Windows.Forms.DockStyle.Fill;
51 | this.tableLayoutPanel.Location = new System.Drawing.Point(10, 10);
52 | this.tableLayoutPanel.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
53 | this.tableLayoutPanel.Name = "tableLayoutPanel";
54 | this.tableLayoutPanel.RowCount = 6;
55 | this.tableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 10.03788F));
56 | this.tableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 10.03788F));
57 | this.tableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 10.22727F));
58 | this.tableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 9.469697F));
59 | this.tableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50.18939F));
60 | this.tableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 10.03788F));
61 | this.tableLayoutPanel.Size = new System.Drawing.Size(487, 307);
62 | this.tableLayoutPanel.TabIndex = 0;
63 | //
64 | // labelProductName
65 | //
66 | this.labelProductName.Dock = System.Windows.Forms.DockStyle.Fill;
67 | this.labelProductName.Location = new System.Drawing.Point(7, 0);
68 | this.labelProductName.Margin = new System.Windows.Forms.Padding(7, 0, 4, 0);
69 | this.labelProductName.MaximumSize = new System.Drawing.Size(0, 20);
70 | this.labelProductName.Name = "labelProductName";
71 | this.labelProductName.Size = new System.Drawing.Size(476, 20);
72 | this.labelProductName.TabIndex = 19;
73 | this.labelProductName.Text = "Product Name";
74 | this.labelProductName.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
75 | //
76 | // labelVersion
77 | //
78 | this.labelVersion.Dock = System.Windows.Forms.DockStyle.Fill;
79 | this.labelVersion.Location = new System.Drawing.Point(7, 30);
80 | this.labelVersion.Margin = new System.Windows.Forms.Padding(7, 0, 4, 0);
81 | this.labelVersion.MaximumSize = new System.Drawing.Size(0, 20);
82 | this.labelVersion.Name = "labelVersion";
83 | this.labelVersion.Size = new System.Drawing.Size(476, 20);
84 | this.labelVersion.TabIndex = 0;
85 | this.labelVersion.Text = "Version";
86 | this.labelVersion.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
87 | //
88 | // labelCopyright
89 | //
90 | this.labelCopyright.Dock = System.Windows.Forms.DockStyle.Fill;
91 | this.labelCopyright.Location = new System.Drawing.Point(7, 60);
92 | this.labelCopyright.Margin = new System.Windows.Forms.Padding(7, 0, 4, 0);
93 | this.labelCopyright.MaximumSize = new System.Drawing.Size(0, 20);
94 | this.labelCopyright.Name = "labelCopyright";
95 | this.labelCopyright.Size = new System.Drawing.Size(476, 20);
96 | this.labelCopyright.TabIndex = 21;
97 | this.labelCopyright.Text = "Copyright";
98 | this.labelCopyright.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
99 | //
100 | // labelCompanyName
101 | //
102 | this.labelCompanyName.Dock = System.Windows.Forms.DockStyle.Fill;
103 | this.labelCompanyName.Location = new System.Drawing.Point(7, 91);
104 | this.labelCompanyName.Margin = new System.Windows.Forms.Padding(7, 0, 4, 0);
105 | this.labelCompanyName.MaximumSize = new System.Drawing.Size(0, 20);
106 | this.labelCompanyName.Name = "labelCompanyName";
107 | this.labelCompanyName.Size = new System.Drawing.Size(476, 20);
108 | this.labelCompanyName.TabIndex = 22;
109 | this.labelCompanyName.Text = "Company Name";
110 | this.labelCompanyName.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
111 | //
112 | // textBoxDescription
113 | //
114 | this.textBoxDescription.Dock = System.Windows.Forms.DockStyle.Fill;
115 | this.textBoxDescription.Location = new System.Drawing.Point(7, 123);
116 | this.textBoxDescription.Margin = new System.Windows.Forms.Padding(7, 3, 4, 3);
117 | this.textBoxDescription.Multiline = true;
118 | this.textBoxDescription.Name = "textBoxDescription";
119 | this.textBoxDescription.ReadOnly = true;
120 | this.textBoxDescription.ScrollBars = System.Windows.Forms.ScrollBars.Both;
121 | this.textBoxDescription.Size = new System.Drawing.Size(476, 148);
122 | this.textBoxDescription.TabIndex = 23;
123 | this.textBoxDescription.TabStop = false;
124 | this.textBoxDescription.Text = "Description";
125 | //
126 | // okButton
127 | //
128 | this.okButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
129 | this.okButton.DialogResult = System.Windows.Forms.DialogResult.Cancel;
130 | this.okButton.Location = new System.Drawing.Point(395, 279);
131 | this.okButton.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
132 | this.okButton.Name = "okButton";
133 | this.okButton.Size = new System.Drawing.Size(88, 25);
134 | this.okButton.TabIndex = 24;
135 | this.okButton.Text = "&OK";
136 | this.okButton.Click += new System.EventHandler(this.okButton_Click);
137 | //
138 | // About
139 | //
140 | this.AcceptButton = this.okButton;
141 | this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F);
142 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
143 | this.ClientSize = new System.Drawing.Size(507, 327);
144 | this.Controls.Add(this.tableLayoutPanel);
145 | this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
146 | this.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
147 | this.MaximizeBox = false;
148 | this.MinimizeBox = false;
149 | this.Name = "About";
150 | this.Padding = new System.Windows.Forms.Padding(10, 10, 10, 10);
151 | this.ShowIcon = false;
152 | this.ShowInTaskbar = false;
153 | this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
154 | this.Text = "About";
155 | this.tableLayoutPanel.ResumeLayout(false);
156 | this.tableLayoutPanel.PerformLayout();
157 | this.ResumeLayout(false);
158 |
159 | }
160 |
161 | #endregion
162 |
163 | private System.Windows.Forms.TableLayoutPanel tableLayoutPanel;
164 | private System.Windows.Forms.Label labelProductName;
165 | private System.Windows.Forms.Label labelVersion;
166 | private System.Windows.Forms.Label labelCopyright;
167 | private System.Windows.Forms.Label labelCompanyName;
168 | private System.Windows.Forms.TextBox textBoxDescription;
169 | private System.Windows.Forms.Button okButton;
170 | }
171 | }
172 |
--------------------------------------------------------------------------------
/MultiConverter.GUI/About.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Reflection;
3 | using System.Windows.Forms;
4 |
5 | namespace MultiConverter.GUI
6 | {
7 | partial class About : Form
8 | {
9 | public About()
10 | {
11 | InitializeComponent();
12 | this.Text = String.Format("About {0}", AssemblyTitle);
13 | this.labelProductName.Text = AssemblyProduct;
14 | this.labelVersion.Text = String.Format("Version {0}", AssemblyVersion);
15 | this.labelCopyright.Text = AssemblyCopyright;
16 | this.labelCompanyName.Text = AssemblyCompany;
17 | this.textBoxDescription.Text = AssemblyDescription;
18 | }
19 |
20 | #region Assembly Attribute Accessors
21 |
22 | public string AssemblyTitle
23 | {
24 | get
25 | {
26 | object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyTitleAttribute), false);
27 | if (attributes.Length > 0)
28 | {
29 | AssemblyTitleAttribute titleAttribute = (AssemblyTitleAttribute)attributes[0];
30 | if (titleAttribute.Title != "")
31 | {
32 | return titleAttribute.Title;
33 | }
34 | }
35 | return System.IO.Path.GetFileNameWithoutExtension(Assembly.GetExecutingAssembly().CodeBase);
36 | }
37 | }
38 |
39 | public string AssemblyVersion
40 | {
41 | get
42 | {
43 | return Assembly.GetExecutingAssembly().GetName().Version.ToString();
44 | }
45 | }
46 |
47 | public string AssemblyDescription
48 | {
49 | get
50 | {
51 | object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyDescriptionAttribute), false);
52 | if (attributes.Length == 0)
53 | {
54 | return "";
55 | }
56 | return ((AssemblyDescriptionAttribute)attributes[0]).Description;
57 | }
58 | }
59 |
60 | public string AssemblyProduct
61 | {
62 | get
63 | {
64 | object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyProductAttribute), false);
65 | if (attributes.Length == 0)
66 | {
67 | return "";
68 | }
69 | return ((AssemblyProductAttribute)attributes[0]).Product;
70 | }
71 | }
72 |
73 | public string AssemblyCopyright
74 | {
75 | get
76 | {
77 | object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyCopyrightAttribute), false);
78 | if (attributes.Length == 0)
79 | {
80 | return "";
81 | }
82 | return ((AssemblyCopyrightAttribute)attributes[0]).Copyright;
83 | }
84 | }
85 |
86 | public string AssemblyCompany
87 | {
88 | get
89 | {
90 | object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyCompanyAttribute), false);
91 | if (attributes.Length == 0)
92 | {
93 | return "";
94 | }
95 | return ((AssemblyCompanyAttribute)attributes[0]).Company;
96 | }
97 | }
98 | #endregion
99 |
100 | private void okButton_Click(object sender, EventArgs e)
101 | {
102 | Close();
103 | }
104 | }
105 | }
106 |
--------------------------------------------------------------------------------
/MultiConverter.GUI/About.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 | text/microsoft-resx
50 |
51 |
52 | 2.0
53 |
54 |
55 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
56 |
57 |
58 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
59 |
60 |
--------------------------------------------------------------------------------
/MultiConverter.GUI/MainForm.Designer.cs:
--------------------------------------------------------------------------------
1 | namespace MultiConverter.GUI
2 | {
3 | partial class ConverterForm
4 | {
5 | ///
6 | /// Required designer variable.
7 | ///
8 | private System.ComponentModel.IContainer components = null;
9 |
10 | ///
11 | /// Clean up any resources being used.
12 | ///
13 | /// true if managed resources should be disposed; otherwise, false.
14 | protected override void Dispose(bool disposing)
15 | {
16 | if (disposing && (components != null))
17 | {
18 | components.Dispose();
19 | }
20 | base.Dispose(disposing);
21 | }
22 |
23 | #region Windows Form Designer generated code
24 |
25 | ///
26 | /// Required method for Designer support - do not modify
27 | /// the contents of this method with the code editor.
28 | ///
29 | private void InitializeComponent()
30 | {
31 | this.fix_btn = new System.Windows.Forms.Button();
32 | this.lb = new System.Windows.Forms.ListBox();
33 | this.button1 = new System.Windows.Forms.Button();
34 | this.progress = new System.Windows.Forms.ProgressBar();
35 | this.cb_wod = new System.Windows.Forms.CheckBox();
36 | this.adt_water = new System.Windows.Forms.CheckBox();
37 | this.adt_models = new System.Windows.Forms.CheckBox();
38 | this.adt_group = new System.Windows.Forms.GroupBox();
39 | this.wmo_group = new System.Windows.Forms.GroupBox();
40 | this.m2_group = new System.Windows.Forms.GroupBox();
41 | this.helmFix = new System.Windows.Forms.CheckBox();
42 | this.menuStrip1 = new System.Windows.Forms.MenuStrip();
43 | this.helpToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
44 | this.aboutToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
45 | this.adt_group.SuspendLayout();
46 | this.wmo_group.SuspendLayout();
47 | this.m2_group.SuspendLayout();
48 | this.menuStrip1.SuspendLayout();
49 | this.SuspendLayout();
50 | //
51 | // fix_btn
52 | //
53 | this.fix_btn.Location = new System.Drawing.Point(371, 39);
54 | this.fix_btn.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
55 | this.fix_btn.Name = "fix_btn";
56 | this.fix_btn.Size = new System.Drawing.Size(180, 45);
57 | this.fix_btn.TabIndex = 0;
58 | this.fix_btn.Text = "Fix";
59 | this.fix_btn.UseVisualStyleBackColor = true;
60 | this.fix_btn.Click += new System.EventHandler(this.fix_btn_Click);
61 | //
62 | // lb
63 | //
64 | this.lb.AllowDrop = true;
65 | this.lb.FormattingEnabled = true;
66 | this.lb.ItemHeight = 15;
67 | this.lb.Location = new System.Drawing.Point(15, 40);
68 | this.lb.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
69 | this.lb.Name = "lb";
70 | this.lb.Size = new System.Drawing.Size(348, 244);
71 | this.lb.TabIndex = 2;
72 | this.lb.DragDrop += new System.Windows.Forms.DragEventHandler(this.filepath_OnDrop);
73 | this.lb.DragEnter += new System.Windows.Forms.DragEventHandler(this.filepath_DragEnter);
74 | //
75 | // button1
76 | //
77 | this.button1.Location = new System.Drawing.Point(371, 91);
78 | this.button1.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
79 | this.button1.Name = "button1";
80 | this.button1.Size = new System.Drawing.Size(180, 45);
81 | this.button1.TabIndex = 3;
82 | this.button1.Text = "Clear";
83 | this.button1.UseVisualStyleBackColor = true;
84 | this.button1.Click += new System.EventHandler(this.button1_Click);
85 | //
86 | // progress
87 | //
88 | this.progress.Location = new System.Drawing.Point(15, 288);
89 | this.progress.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
90 | this.progress.Name = "progress";
91 | this.progress.Size = new System.Drawing.Size(349, 27);
92 | this.progress.TabIndex = 4;
93 | //
94 | // cb_wod
95 | //
96 | this.cb_wod.AutoSize = true;
97 | this.cb_wod.Location = new System.Drawing.Point(6, 16);
98 | this.cb_wod.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
99 | this.cb_wod.Name = "cb_wod";
100 | this.cb_wod.Size = new System.Drawing.Size(102, 19);
101 | this.cb_wod.TabIndex = 5;
102 | this.cb_wod.Text = "Legion > WoD";
103 | this.cb_wod.UseVisualStyleBackColor = true;
104 | //
105 | // adt_water
106 | //
107 | this.adt_water.AutoSize = true;
108 | this.adt_water.Checked = true;
109 | this.adt_water.CheckState = System.Windows.Forms.CheckState.Checked;
110 | this.adt_water.Location = new System.Drawing.Point(7, 22);
111 | this.adt_water.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
112 | this.adt_water.Name = "adt_water";
113 | this.adt_water.Size = new System.Drawing.Size(136, 19);
114 | this.adt_water.TabIndex = 6;
115 | this.adt_water.Text = "Liquids (Water, Lava)";
116 | this.adt_water.UseVisualStyleBackColor = true;
117 | //
118 | // adt_models
119 | //
120 | this.adt_models.AutoSize = true;
121 | this.adt_models.Checked = true;
122 | this.adt_models.CheckState = System.Windows.Forms.CheckState.Checked;
123 | this.adt_models.Location = new System.Drawing.Point(7, 46);
124 | this.adt_models.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
125 | this.adt_models.Name = "adt_models";
126 | this.adt_models.Size = new System.Drawing.Size(130, 19);
127 | this.adt_models.TabIndex = 7;
128 | this.adt_models.Text = "Models (WMO, M2)";
129 | this.adt_models.UseVisualStyleBackColor = true;
130 | //
131 | // adt_group
132 | //
133 | this.adt_group.Controls.Add(this.adt_models);
134 | this.adt_group.Controls.Add(this.adt_water);
135 | this.adt_group.Location = new System.Drawing.Point(371, 241);
136 | this.adt_group.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
137 | this.adt_group.Name = "adt_group";
138 | this.adt_group.Padding = new System.Windows.Forms.Padding(4, 3, 4, 3);
139 | this.adt_group.Size = new System.Drawing.Size(180, 74);
140 | this.adt_group.TabIndex = 8;
141 | this.adt_group.TabStop = false;
142 | this.adt_group.Text = "ADT";
143 | //
144 | // wmo_group
145 | //
146 | this.wmo_group.Controls.Add(this.cb_wod);
147 | this.wmo_group.Location = new System.Drawing.Point(371, 143);
148 | this.wmo_group.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
149 | this.wmo_group.Name = "wmo_group";
150 | this.wmo_group.Padding = new System.Windows.Forms.Padding(4, 3, 4, 3);
151 | this.wmo_group.Size = new System.Drawing.Size(180, 43);
152 | this.wmo_group.TabIndex = 9;
153 | this.wmo_group.TabStop = false;
154 | this.wmo_group.Text = "WMO";
155 | //
156 | // m2_group
157 | //
158 | this.m2_group.Controls.Add(this.helmFix);
159 | this.m2_group.Location = new System.Drawing.Point(371, 193);
160 | this.m2_group.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
161 | this.m2_group.Name = "m2_group";
162 | this.m2_group.Padding = new System.Windows.Forms.Padding(4, 3, 4, 3);
163 | this.m2_group.Size = new System.Drawing.Size(180, 42);
164 | this.m2_group.TabIndex = 10;
165 | this.m2_group.TabStop = false;
166 | this.m2_group.Text = "M2";
167 | //
168 | // helmFix
169 | //
170 | this.helmFix.AutoSize = true;
171 | this.helmFix.Checked = true;
172 | this.helmFix.CheckState = System.Windows.Forms.CheckState.Checked;
173 | this.helmFix.Location = new System.Drawing.Point(9, 16);
174 | this.helmFix.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
175 | this.helmFix.Name = "helmFix";
176 | this.helmFix.Size = new System.Drawing.Size(108, 19);
177 | this.helmFix.TabIndex = 0;
178 | this.helmFix.Text = "Helm Offset Fix";
179 | this.helmFix.UseVisualStyleBackColor = true;
180 | //
181 | // menuStrip1
182 | //
183 | this.menuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
184 | this.helpToolStripMenuItem});
185 | this.menuStrip1.Location = new System.Drawing.Point(0, 0);
186 | this.menuStrip1.Name = "menuStrip1";
187 | this.menuStrip1.Padding = new System.Windows.Forms.Padding(7, 2, 0, 2);
188 | this.menuStrip1.Size = new System.Drawing.Size(565, 24);
189 | this.menuStrip1.TabIndex = 11;
190 | this.menuStrip1.Text = "menuStrip1";
191 | //
192 | // helpToolStripMenuItem
193 | //
194 | this.helpToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
195 | this.aboutToolStripMenuItem});
196 | this.helpToolStripMenuItem.Name = "helpToolStripMenuItem";
197 | this.helpToolStripMenuItem.Size = new System.Drawing.Size(44, 20);
198 | this.helpToolStripMenuItem.Text = "Help";
199 | //
200 | // aboutToolStripMenuItem
201 | //
202 | this.aboutToolStripMenuItem.Name = "aboutToolStripMenuItem";
203 | this.aboutToolStripMenuItem.Size = new System.Drawing.Size(107, 22);
204 | this.aboutToolStripMenuItem.Text = "About";
205 | this.aboutToolStripMenuItem.Click += new System.EventHandler(this.aboutToolStripMenuItem_Click);
206 | //
207 | // ConverterForm
208 | //
209 | this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F);
210 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
211 | this.ClientSize = new System.Drawing.Size(565, 330);
212 | this.Controls.Add(this.m2_group);
213 | this.Controls.Add(this.wmo_group);
214 | this.Controls.Add(this.adt_group);
215 | this.Controls.Add(this.progress);
216 | this.Controls.Add(this.button1);
217 | this.Controls.Add(this.lb);
218 | this.Controls.Add(this.fix_btn);
219 | this.Controls.Add(this.menuStrip1);
220 | this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedToolWindow;
221 | this.MainMenuStrip = this.menuStrip1;
222 | this.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
223 | this.MaximumSize = new System.Drawing.Size(581, 369);
224 | this.MinimumSize = new System.Drawing.Size(581, 369);
225 | this.Name = "ConverterForm";
226 | this.Text = "Multi-Converter";
227 | this.adt_group.ResumeLayout(false);
228 | this.adt_group.PerformLayout();
229 | this.wmo_group.ResumeLayout(false);
230 | this.wmo_group.PerformLayout();
231 | this.m2_group.ResumeLayout(false);
232 | this.m2_group.PerformLayout();
233 | this.menuStrip1.ResumeLayout(false);
234 | this.menuStrip1.PerformLayout();
235 | this.ResumeLayout(false);
236 | this.PerformLayout();
237 |
238 | }
239 |
240 | #endregion
241 |
242 | private System.Windows.Forms.Button fix_btn;
243 | private System.Windows.Forms.ListBox lb;
244 | private System.Windows.Forms.Button button1;
245 | private System.Windows.Forms.ProgressBar progress;
246 | private System.Windows.Forms.CheckBox cb_wod;
247 | private System.Windows.Forms.CheckBox adt_water;
248 | private System.Windows.Forms.CheckBox adt_models;
249 | private System.Windows.Forms.GroupBox adt_group;
250 | private System.Windows.Forms.GroupBox wmo_group;
251 | private System.Windows.Forms.GroupBox m2_group;
252 | private System.Windows.Forms.CheckBox helmFix;
253 | private System.Windows.Forms.MenuStrip menuStrip1;
254 | private System.Windows.Forms.ToolStripMenuItem helpToolStripMenuItem;
255 | private System.Windows.Forms.ToolStripMenuItem aboutToolStripMenuItem;
256 | }
257 | }
258 |
259 |
--------------------------------------------------------------------------------
/MultiConverter.GUI/MainForm.cs:
--------------------------------------------------------------------------------
1 | using MultiConverter.Lib;
2 | using MultiConverter.Lib.Updater;
3 | using MultiConverter.Lib.Converters;
4 | using MultiConverter.Lib.Converters.ADT;
5 | using MultiConverter.Lib.Converters.Base;
6 | using MultiConverter.Lib.Converters.WMO;
7 | using System;
8 | using System.Collections.Generic;
9 | using System.ComponentModel;
10 | using System.Diagnostics;
11 | using System.IO;
12 | using System.Text.RegularExpressions;
13 | using System.Threading;
14 | using System.Windows.Forms;
15 | using System.Reflection;
16 |
17 | namespace MultiConverter.GUI
18 | {
19 | public partial class ConverterForm : Form
20 | {
21 | public static int PROGRESS = 5;
22 |
23 | public ConverterForm()
24 | {
25 | new Thread(() =>
26 | {
27 | if (!Listfile.IsInitialized)
28 | Listfile.Initialize();
29 | }).Start();
30 |
31 | InitializeComponent();
32 | lb.HorizontalScrollbar = true;
33 |
34 | new Thread(() =>
35 | {
36 | Thread.Sleep(3000);
37 |
38 | var hasUpdate = UpdateManager.HasUpdates(AssemblyVersion);
39 | if (hasUpdate.Item1)
40 | {
41 | var messageBox = MessageBox.Show($"An update is available! From: {AssemblyVersion} To: {hasUpdate.Item2}.\nPress OK to update.", "Update!", MessageBoxButtons.OK);
42 | if (messageBox == DialogResult.OK)
43 | {
44 | // Start the updater..
45 | UpdateManager.StartUpdater();
46 |
47 | // Close the current window.
48 | Invoke((MethodInvoker)delegate
49 | {
50 | Close();
51 | });
52 | }
53 | }
54 | }).Start();
55 | }
56 |
57 | private void Clear() => lb.Items.Clear();
58 |
59 | private void fix_btn_Click(object sender, EventArgs e)
60 | {
61 | if (lb.Items.Count == 0)
62 | return;
63 |
64 | if (lb.Items.Count > 0)
65 | {
66 | progress.Value = 0;
67 | progress.Maximum = lb.Items.Count;
68 | progress.Step = PROGRESS;
69 | Fix();
70 | }
71 | }
72 |
73 | private void Fix()
74 | {
75 | Enabled = false;
76 |
77 | var filenameList = new List();
78 | foreach (var item in lb.Items)
79 | filenameList.Add(item.ToString());
80 |
81 | FixList(filenameList);
82 | }
83 |
84 | private void FixList(List list)
85 | {
86 | var bw = new BackgroundWorker();
87 | bw.WorkerReportsProgress = true;
88 |
89 | bw.DoWork += new DoWorkEventHandler((sender, e) =>
90 | {
91 | var filenames = e.Argument as List;
92 | var progress = 0;
93 |
94 | var worker = sender as BackgroundWorker;
95 |
96 | foreach (string filename in filenames)
97 | {
98 | IConverter converter = null;
99 |
100 | if (filename.EndsWith("m2"))
101 | {
102 | var m2converter = new M2Converter(filename, helmFix.Checked);
103 | if (m2converter.Fix())
104 | m2converter.Save();
105 |
106 | continue;
107 | }
108 | else if (filename.EndsWith("adt"))
109 | converter = new ADTFile(filename.Replace(".adt", "_obj0.adt"), filename.Replace(".adt", "_tex0.adt"));
110 | // else if (filename.EndsWith("wdt"))
111 | // converter = new WDTConverter(filename);
112 | else if (Regex.IsMatch(filename, @".*_[0-9]{3}(_(lod[0-9]))?\.(wmo)"))
113 | {
114 | var wmoconverter = new WMOGroupConverter(filename, false);
115 | if (wmoconverter.Fix())
116 | wmoconverter.Save();
117 |
118 | continue;
119 | }
120 | else if (filename.EndsWith(".skin"))
121 | continue;
122 | if (filename.EndsWith("wmo"))
123 | converter = new WMOFile();
124 | // else if (filename.EndsWith("anim"))
125 | // converter = new AnimConverter(filename);
126 |
127 | converter.Read(File.ReadAllBytes(filename));
128 | converter.Write(filename);
129 |
130 | if (++progress == PROGRESS)
131 | {
132 | worker.ReportProgress(1);
133 | progress = 0;
134 | }
135 | }
136 | });
137 |
138 | bw.ProgressChanged += new ProgressChangedEventHandler((sender, e) =>
139 | {
140 | progress.PerformStep();
141 | });
142 |
143 | bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler((sender, e) =>
144 | {
145 | if (e.Error != null)
146 | MessageBox.Show(e.Error.ToString());
147 |
148 | progress.Value = progress.Maximum;
149 | Enabled = true;
150 | Clear();
151 | });
152 |
153 | bw.RunWorkerAsync(list);
154 | }
155 |
156 | private void filepath_DragEnter(object sender, DragEventArgs e)
157 | {
158 | if (e.Data.GetDataPresent(DataFormats.FileDrop))
159 | e.Effect = DragDropEffects.Copy;
160 | else
161 | e.Effect = DragDropEffects.None;
162 | }
163 |
164 | private void filepath_OnDrop(object sender, DragEventArgs e)
165 | {
166 | if (e.Data.GetDataPresent(DataFormats.FileDrop))
167 | {
168 | progress.Value = 0;
169 | var list = (string[])e.Data.GetData(DataFormats.FileDrop, false);
170 | LoadFiles(list);
171 | }
172 | }
173 |
174 | private void LoadFiles(string[] list)
175 | {
176 | this.Enabled = false;
177 |
178 | BackgroundWorker bw = new BackgroundWorker();
179 | bw.WorkerReportsProgress = true;
180 | bw.WorkerSupportsCancellation = false;
181 |
182 | bw.DoWork += new DoWorkEventHandler((sender, e) =>
183 | {
184 | Process.GetCurrentProcess().PriorityClass = ProcessPriorityClass.High;
185 | var files = e.Argument as string[];
186 | var lf = new HashSet();
187 |
188 | foreach (var s in files)
189 | {
190 | if (Directory.Exists(s))
191 | {
192 | foreach (string file in Directory.EnumerateFiles(s, "*.*", SearchOption.AllDirectories))
193 | if (Utils.IsCorrectFile(file) && !lf.Contains(file))
194 | lf.Add(file.ToLower());
195 | }
196 | else if (Utils.IsCorrectFile(s) && !lf.Contains(s))
197 | lf.Add(s.ToLower());
198 | }
199 |
200 | e.Result = lf;
201 | });
202 |
203 | bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler((sender, e) =>
204 | {
205 | var files = (HashSet)e.Result;
206 | foreach (string file in files)
207 | lb.Items.Add(file);
208 | Enabled = true;
209 | });
210 |
211 | bw.RunWorkerAsync(list);
212 | }
213 |
214 | private void button1_Click(object sender, EventArgs e)
215 | {
216 | progress.Value = 0;
217 | Clear();
218 | }
219 |
220 | private void aboutToolStripMenuItem_Click(object sender, EventArgs e)
221 | {
222 | var aboutBox = new About();
223 | aboutBox.Show();
224 | }
225 |
226 | public string AssemblyVersion
227 | {
228 | get
229 | {
230 | return Assembly.GetExecutingAssembly().GetName().Version.ToString();
231 | }
232 | }
233 | }
234 | }
235 |
--------------------------------------------------------------------------------
/MultiConverter.GUI/MainForm.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 | text/microsoft-resx
50 |
51 |
52 | 2.0
53 |
54 |
55 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
56 |
57 |
58 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
59 |
60 |
--------------------------------------------------------------------------------
/MultiConverter.GUI/MultiConverter.GUI.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | netcoreapp3.1
6 | true
7 | 3.6.1.0
8 | WoW - MultiConverter
9 | MaxtorCoder & Adspartan
10 | The Fuckporting Company
11 | WoW - MultiConverter
12 | Copyright © 2018 - 2020
13 | WoW Multi-Converter made by Adspartan and maintained by MaxtorCoder.
14 |
15 | Code is on https://github.com/MaxtorCoder/MultiConverter
16 | https://github.com/MaxtorCoder/MultiConverter
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 | false
25 | false
26 | 3.6.2.0
27 | 3.6.2.0
28 |
29 |
30 |
31 | ..\bin\Debug\
32 |
33 |
34 | ..\bin\Release\
35 |
36 |
37 |
--------------------------------------------------------------------------------
/MultiConverter.GUI/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Windows.Forms;
3 |
4 | namespace MultiConverter.GUI
5 | {
6 | static class Program
7 | {
8 | ///
9 | /// The main entry point for the application.
10 | ///
11 | [STAThread]
12 | static void Main()
13 | {
14 | Application.SetHighDpiMode(HighDpiMode.SystemAware);
15 | Application.EnableVisualStyles();
16 | Application.SetCompatibleTextRenderingDefault(false);
17 | Application.Run(new ConverterForm());
18 | }
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/MultiConverter.Lib/Common/C3Vector.cs:
--------------------------------------------------------------------------------
1 | namespace MultiConverter.Lib.Common
2 | {
3 | public struct C3Vector
4 | {
5 | public float X;
6 | public float Y;
7 | public float Z;
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/MultiConverter.Lib/Common/C4Plane.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text;
4 |
5 | namespace MultiConverter.Lib.Common
6 | {
7 | public struct C4Plane
8 | {
9 | public C3Vector Normal;
10 | public float Distance;
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/MultiConverter.Lib/Common/CAaBox.cs:
--------------------------------------------------------------------------------
1 | namespace MultiConverter.Lib.Common
2 | {
3 | public struct CAaBox
4 | {
5 | public C3Vector Min;
6 | public C3Vector Max;
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/MultiConverter.Lib/Common/CArgb.cs:
--------------------------------------------------------------------------------
1 | namespace MultiConverter.Lib.Common
2 | {
3 | public struct CArgb
4 | {
5 | public byte R;
6 | public byte G;
7 | public byte B;
8 | public byte A;
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/MultiConverter.Lib/Converters/ADT/ADTFile.cs:
--------------------------------------------------------------------------------
1 | using MultiConverter.Lib.Converters.Base;
2 | // using MultiConverter.Lib.Converters.ADT.Chunks;
3 | using System;
4 | using System.Collections.Generic;
5 | using System.IO;
6 | using System.Linq;
7 |
8 |
9 | namespace MultiConverter.Lib.Converters.ADT
10 | {
11 | public class ADTFile : IConverter
12 | {
13 | public static List Chunks = new List();
14 | public static Dictionary ChunkData = new Dictionary();
15 | public static Dictionary ChunkExtraData = new Dictionary();
16 |
17 | public static bool DisableDoodads = false;
18 | public static bool DisableWMOs = false;
19 |
20 | public ADTFile(string objFilename, string texFilename)
21 | {
22 |
23 | }
24 |
25 | public void Read(byte[] inData)
26 | {
27 | // Clear chunks to prevent double data.
28 | Chunks.Clear();
29 |
30 | using (var stream = new MemoryStream(inData))
31 | using (var reader = new BinaryReader(stream))
32 | {
33 | var chunkOrder = 0u;
34 | while (reader.BaseStream.Position < reader.BaseStream.Length)
35 | {
36 | var chunkId = new string(reader.ReadChars(4).Reverse().ToArray());
37 | var chunkSize = reader.ReadUInt32();
38 |
39 | var chunkData = new byte[chunkSize];
40 | Buffer.BlockCopy(stream.ToArray(), (int)reader.BaseStream.Position, chunkData, 0, (int)chunkSize);
41 |
42 | IChunk chunk = null;
43 | switch (chunkId)
44 | {
45 | default:
46 | Console.WriteLine($"Skipping {chunkId}");
47 | break;
48 | }
49 |
50 | if (chunk != null)
51 | chunk.Read(chunkData);
52 |
53 | ChunkExtraData.Add(chunkId, (chunkOrder, false));
54 | ChunkData.Add(chunkId, chunk != null ? chunk.Write() : chunkData);
55 |
56 | ++chunkOrder;
57 | reader.BaseStream.Position += chunkSize;
58 | }
59 |
60 | // Close the streams so they can be written.
61 | reader.Close();
62 | stream.Close();
63 | }
64 | }
65 |
66 | public void Write(string filename)
67 | {
68 | using (var stream = new MemoryStream())
69 | using (var writer = new BinaryWriter(stream))
70 | {
71 | foreach (var chunk in ChunkData)
72 | {
73 | var reversedSignature = chunk.Key.Reverse().ToArray();
74 |
75 | foreach (var signatureChar in reversedSignature)
76 | writer.Write(signatureChar);
77 |
78 | writer.Write(chunk.Value.Length);
79 | writer.Write(chunk.Value);
80 | }
81 |
82 | File.WriteAllBytes(filename, stream.ToArray());
83 | }
84 | }
85 | }
86 | }
87 |
--------------------------------------------------------------------------------
/MultiConverter.Lib/Converters/AdtConverter.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Linq;
3 | using System.IO;
4 | using MultiConverter.Lib.Converters.Base;
5 | using MultiConverter.Lib.Common;
6 | using MultiConverter.Lib.Util;
7 |
8 | namespace MultiConverter.Lib.Converters
9 | {
10 | public class AdtConverter
11 | {
12 | private string modelname;
13 | private string file;
14 | private ChunkedWowFile adt;
15 | private ChunkedWowFile obj;
16 | private ChunkedWowFile tex;
17 | private bool water;
18 | private bool models;
19 | private int textureCount = 0;
20 |
21 | private int adtPos = 0;
22 | private int texPos = 0;
23 | private int objPos = 0;
24 |
25 | private Dictionary MDXFilenames = new Dictionary();
26 | private Dictionary WMOFilenames = new Dictionary();
27 | private Dictionary MapTextures = new Dictionary();
28 | private List MDDFs = new List();
29 | private List MODFs = new List();
30 |
31 | public AdtConverter(string path, bool h2o, bool model)
32 | {
33 | file = path;
34 | water = h2o;
35 | models = model;
36 | modelname = Path.GetFileNameWithoutExtension(path);
37 |
38 | adt = new ChunkedWowFile(path);
39 | obj = new ChunkedWowFile(path.Replace(".adt", "_obj0.adt"));
40 | tex = new ChunkedWowFile(path.Replace(".adt", "_tex0.adt"));
41 |
42 | // clean the folder
43 | Utils.DeleteFile(path.Replace(".adt", "_obj1.adt"));
44 | Utils.DeleteFile(path.Replace(".adt", "_lod.adt"));
45 | }
46 |
47 | public bool Fix()
48 | {
49 | // already converted
50 | if (!adt.Valid || !obj.Valid || !tex.Valid || adt.ReadUInt(0x18) > 0)
51 | return false;
52 |
53 | // Update the version
54 | adt.WriteInt(8, 12);
55 |
56 | CreateMCIN();
57 |
58 | if (adt.HasChunk("MTEX"))
59 | RetrieveMTEX();
60 | if (adt.HasChunk("MMDX"))
61 | RetrieveMMDX();
62 | if (tex.HasChunk("MDID") && tex.HasChunk("MHID")) //< Textures.
63 | {
64 | RetrieveTextures();
65 | WriteMTEX();
66 | }
67 |
68 | if (obj.HasChunk("MMID") && obj.HasChunk("MWMO") && obj.HasChunk("MWID"))
69 | {
70 | RetrieveMMID();
71 | RetrieveMWMO();
72 | RetrieveMWID();
73 | }
74 |
75 | if (obj.HasChunk("MDDF") && obj.HasChunk("MODF"))
76 | {
77 |
78 | }
79 |
80 | CheckMH2O();
81 |
82 | for (int i = 0; i < 256; ++i)
83 | RetrieveMCNK(i);
84 |
85 | CheckMFBO();
86 |
87 | RetrieveMTXF();
88 |
89 | return true;
90 | }
91 |
92 | private void CreateMDXChunks()
93 | {
94 | var calculatedSize = CalculateChunkSize(MDXFilenames);
95 | adt.AddEmptyBytes(adtPos, (int)calculatedSize + 8);
96 | adt.WriteHeaderMagic("MMDX", ref adtPos);
97 | adt.WriteUInt(calculatedSize, ref adtPos);
98 |
99 | foreach (var filename in MDXFilenames.Values)
100 | adt.WriteString(filename, ref adtPos);
101 |
102 | adt.AddEmptyBytes(adtPos, (MDXFilenames.Count * 4) + 8);
103 | adt.WriteHeaderMagic("MMID", ref adtPos);
104 | adt.WriteInt(MDXFilenames.Count * 4, ref adtPos);
105 |
106 | var mdxFilenames = MDXFilenames.Values.ToList();
107 | var lastMDX = string.Empty;
108 | foreach (var filename in mdxFilenames)
109 | {
110 | if (lastMDX == string.Empty)
111 | adt.WriteInt(0, ref adtPos);
112 | else
113 | adt.WriteInt(lastMDX.Length, ref adtPos);
114 |
115 | lastMDX = filename;
116 | }
117 | }
118 |
119 | private void CreateWMOChunks()
120 | {
121 | var calculatedSize = CalculateChunkSize(WMOFilenames);
122 | adt.AddEmptyBytes(adtPos, (int)calculatedSize + 8);
123 | adt.WriteHeaderMagic("MWMO", ref adtPos);
124 | adt.WriteUInt(calculatedSize, ref adtPos);
125 |
126 | foreach (var filename in WMOFilenames.Values)
127 | adt.WriteString(filename, ref adtPos);
128 |
129 | adt.AddEmptyBytes(adtPos, (WMOFilenames.Count * 4) + 8);
130 | adt.WriteHeaderMagic("MWID", ref adtPos);
131 | adt.WriteInt(WMOFilenames.Count * 4, ref adtPos);
132 |
133 | var wmoFilenames = WMOFilenames.Values.ToList();
134 | var lastWMO = string.Empty;
135 | foreach (var filename in wmoFilenames)
136 | {
137 | if (lastWMO == string.Empty)
138 | adt.WriteInt(0, ref adtPos);
139 | else
140 | adt.WriteInt(lastWMO.Length, ref adtPos);
141 |
142 | lastWMO = filename;
143 | }
144 | }
145 |
146 | private void CreateMCIN()
147 | {
148 | adt.AddEmptyBytes(0x54, 0x1008);
149 | adt.WriteInt(0x54, ChunkedWowFile.MagicToInt("MCIN"));
150 | adt.WriteInt(0x58, 0x1000); // chunk size
151 | adt.WriteInt(0x18, 0x40);
152 |
153 | // after mcin chunk
154 | adtPos = 0x1008 + 0x54;
155 | }
156 |
157 | private void RetrieveMTEX()
158 | {
159 | // skip MAMP chunk
160 | int start_mtex = tex.IsChunk(0xC, ChunkedWowFile.MagicToInt("MAMP")) ? tex.ReadInt(0x10) + 0x14 : 0xC;
161 |
162 | // real size = size + 0x8 (header size)
163 | int size = tex.ReadInt(start_mtex + 4) + 0x8;
164 |
165 | // start MTEX
166 | adt.AddEmptyBytes(adtPos, size);
167 |
168 | tex.BlockCopy(start_mtex, adt, adtPos, size);
169 | // remove unecessary data
170 | tex.RemoveBytes(0x0, start_mtex + size);
171 |
172 | adt.WriteInt(0x1C, adtPos - 0x14);
173 |
174 | for (int i = adtPos + 0x8; i < adtPos + size; ++i)
175 | {
176 | if (adt.Data[i] == 0)
177 | {
178 | textureCount++;
179 | }
180 | }
181 |
182 | adtPos += size;
183 | }
184 |
185 | private void RetrieveMMDX()
186 | {
187 | int size = 0x8;
188 |
189 | if (models)
190 | {
191 | size += obj.ReadInt(0x10);
192 |
193 | adt.AddEmptyBytes(adtPos, size);
194 | obj.BlockCopy(0xC, adt, adtPos, size);
195 | obj.RemoveBytes(0, size + 0xC);
196 |
197 | }
198 | else
199 | {
200 | adt.AddEmptyBytes(adtPos, size);
201 | adt.WriteHeaderMagic(adtPos, "MMDX");
202 | obj.RemoveBytes(0, obj.ReadInt(0x10) + 0xC + 0x8);
203 | }
204 |
205 | adt.WriteInt(0x20, adtPos - 0x14);
206 | adtPos += size;
207 | }
208 |
209 | private void RetrieveMMID()
210 | {
211 | int size = 0x8;
212 |
213 | if (models)
214 | {
215 | size += obj.ReadInt(0x4);
216 | adt.AddEmptyBytes(adtPos, size);
217 | obj.BlockCopy(0, adt, adtPos, size);
218 | obj.RemoveBytes(0, size);
219 | }
220 | else
221 | {
222 | adt.AddEmptyBytes(adtPos, size);
223 | adt.WriteHeaderMagic(adtPos, "MMID");
224 | obj.RemoveBytes(0, obj.ReadInt(0x4) + 0x8);
225 | }
226 |
227 | adt.WriteInt(0x24, adtPos - 0x14);
228 | adtPos += size;
229 | }
230 |
231 | private void RetrieveMWMO()
232 | {
233 | int size = 0x8;
234 |
235 | if (models)
236 | {
237 | size += obj.ReadInt(0x4);
238 | adt.AddEmptyBytes(adtPos, size);
239 | obj.BlockCopy(0, adt, adtPos, size);
240 | obj.RemoveBytes(0, size);
241 | }
242 | else
243 | {
244 | adt.AddEmptyBytes(adtPos, size);
245 | adt.WriteHeaderMagic(adtPos, "MWMO");
246 | obj.RemoveBytes(0, obj.ReadInt(0x4) + 0x8);
247 | }
248 |
249 |
250 | adt.WriteInt(0x28, adtPos - 0x14);
251 | adtPos += size;
252 | }
253 |
254 | private void RetrieveMWID()
255 | {
256 | int size = 0x8;
257 |
258 | if (models)
259 | {
260 | size += obj.ReadInt(0x4);
261 | adt.AddEmptyBytes(adtPos, size);
262 | obj.BlockCopy(0, adt, adtPos, size);
263 | obj.RemoveBytes(0, size);
264 | }
265 | else
266 | {
267 | adt.AddEmptyBytes(adtPos, size);
268 | adt.WriteHeaderMagic(adtPos, "MWID");
269 | obj.RemoveBytes(0, obj.ReadInt(0x4) + 0x8);
270 | }
271 |
272 | adt.WriteInt(0x2C, adtPos - 0x14);
273 | adtPos += size;
274 | }
275 |
276 | private void RetrieveTextures()
277 | {
278 | using (var stream = new MemoryStream(tex.Data))
279 | using (var reader = new BinaryReader(stream))
280 | {
281 | while (reader.BaseStream.Position < reader.BaseStream.Length)
282 | {
283 | var chunk = new string(reader.ReadChars(4));
284 | var size = reader.ReadUInt32();
285 |
286 | switch (chunk)
287 | {
288 | case "PMAM":
289 | texPos += (int)size + 8;
290 | reader.BaseStream.Position += size;
291 | break;
292 | case "DIDM": //< Texures
293 | for (var i = 0; i < size / 4; ++i)
294 | {
295 | var filedataid = reader.ReadUInt32();
296 | if (filedataid != 0)
297 | {
298 | var filename = Listfile.LookupFilename(filedataid, ".adt", modelname) + "\0";
299 | MapTextures.Add(filedataid, filename);
300 | }
301 | }
302 |
303 | texPos += (int)size + 8;
304 | break;
305 | case "DIHM": //< Textures as well
306 | for (var i = 0; i < size / 4; ++i)
307 | {
308 | var filedataid = reader.ReadUInt32();
309 | if (filedataid != 0)
310 | {
311 | var filename = Listfile.LookupFilename(filedataid, ".adt", modelname) + "\0";
312 | MapTextures.Add(filedataid, filename);
313 | }
314 | }
315 |
316 | texPos += (int)size + 8;
317 | break;
318 | default:
319 | reader.BaseStream.Position += size;
320 | break;
321 | }
322 | }
323 | }
324 | }
325 |
326 | private void WriteMTEX()
327 | {
328 | var calculatedSize = CalculateChunkSize(MapTextures);
329 | adt.AddEmptyBytes(adtPos, (int)calculatedSize + 8);
330 | adt.WriteHeaderMagic("MTEX", ref adtPos);
331 | adt.WriteUInt(calculatedSize, ref adtPos);
332 |
333 | foreach (var texture in MapTextures.Values)
334 | adt.WriteString(texture, ref adtPos);
335 | }
336 |
337 | private void Fix_MH2O_Info(int pos)
338 | {
339 | ushort id = adt.ReadUShort(pos);
340 | ushort type = adt.ReadUShort(pos + 0x2);
341 |
342 | if (id > 100)
343 | {
344 | switch (id)
345 | {
346 | case 181:
347 | case 221:
348 | case 301:
349 | case 406:
350 | case 407:
351 | case 411:
352 | case 689:
353 | case 733:
354 | case 750:
355 | case 751:
356 | case 752:
357 | case 760:
358 | case 761:
359 | case 763:
360 | case 764:
361 | case 765:
362 | case 787:
363 | case 805:
364 | case 806:
365 | case 807:
366 | case 808:
367 | case 809:
368 | case 812:
369 | case 814:
370 | case 834:
371 | case 837:
372 | case 839:
373 | case 844:
374 | case 848:
375 | case 849:
376 | case 850:
377 | case 851:
378 | case 852:
379 | case 853:
380 | case 855:
381 | case 864:
382 | case 865:
383 | case 866:
384 | case 872:
385 | case 880:
386 | case 881:
387 | case 884:
388 | case 885:
389 | case 886:
390 | case 887:
391 | case 888:
392 | case 892:
393 | case 894:
394 | default: // water for default
395 | id = 5;
396 | break;
397 | case 101:
398 | case 321:
399 | case 324:
400 | case 350:
401 | case 412:
402 | case 868:
403 | case 890:
404 | case 891:
405 | case 896:
406 | id = 2;
407 | break;
408 | case 121:
409 | case 141:
410 | case 302:
411 | case 303:
412 | case 397:
413 | case 404:
414 | case 671:
415 | case 739:
416 | case 859:
417 | case 860:
418 | case 869:
419 | case 870:
420 | case 873:
421 | case 874:
422 | case 875:
423 | case 876:
424 | case 877:
425 | case 878:
426 | case 879:
427 | id = 7;
428 | break;
429 | case 586:
430 | id = 4;
431 | break;
432 |
433 | }
434 | }
435 |
436 | switch (id)
437 | {
438 | // ocean
439 | case 2:
440 | case 6:
441 | case 10:
442 | case 14:
443 | case 100:
444 | type = 2;
445 | break;
446 | // lava
447 | case 3:
448 | case 7:
449 | case 11:
450 | case 15:
451 | type = 1;
452 | break;
453 | // water and slime (no data found for this one that's why)
454 | default:
455 | type = 0;
456 | break;
457 | }
458 | adt.WriteUShort(pos, id);
459 | adt.WriteUShort(pos + 0x2, type);
460 | }
461 |
462 | private void FixMH2O(int start)
463 | {
464 | int pos = start;
465 |
466 | for (int i = 0; i < 256; ++i)
467 | {
468 | int ofs = adt.ReadInt(pos);
469 | if (ofs > 0)
470 | {
471 | Fix_MH2O_Info(start + ofs);
472 | }
473 | pos += 0xC;
474 | }
475 | }
476 |
477 | private void CheckMH2O()
478 | {
479 | if (adt.IsChunk(adtPos, "MH2O"))
480 | {
481 | if (water)
482 | {
483 | FixMH2O(adtPos + 0x8);
484 | int size = adt.ReadInt(adtPos + 4) + 0x8;
485 | adt.WriteInt(0x3C, adtPos - 0x14);
486 | adtPos += size;
487 | }
488 | else
489 | {
490 | adt.RemoveBytes(adtPos, adt.ReadInt(adtPos + 4) + 0x8);
491 | adt.WriteInt(0x3C, 0);
492 | }
493 | }
494 | else // no MH2O
495 | {
496 | adt.WriteInt(0x3C, 0);
497 | }
498 | }
499 |
500 | private ushort HighToLowResHole(ulong hole)
501 | {
502 | if (hole == 0)
503 | {
504 | return 0;
505 | }
506 |
507 | ushort low = 0x0000;
508 |
509 | for (int i = 0; i < 64; ++i)
510 | {
511 | if (((hole >> i) & 0x1) != 0)
512 | {
513 | int x = (i % 8) / 2, y = i / 16;
514 | low |= (ushort)(1 << (x + y * 4));
515 | }
516 | }
517 |
518 | return low;
519 | }
520 |
521 | enum chunks : int
522 | {
523 | MCNK = 1296256587,
524 | MCCV = 1296253782,
525 | MCNR = 1296256594,
526 | MCLY = 1296256089,
527 | MCRF = 1296257606,
528 | MCSH = 1296257864,
529 | MCAL = 1296253260,
530 | MCSE = 1296257861,
531 | // cata+
532 | MCRD = 1296257604,
533 | MCRW = 1296257623,
534 | MCLV = 1296256086,
535 | }
536 |
537 | private void RetrieveMCNK(int id = 0)
538 | {
539 | // adt.RemoveUnwantedChunksUntil(0, (int)chunks.MCNK);
540 | // tex.RemoveUnwantedChunksUntil(0, (int)chunks.MCNK);
541 | // obj.RemoveUnwantedChunksUntil(0, (int)chunks.MCNK);
542 |
543 | var root_mcnk_int = ChunkedWowFile.MagicToInt("MCNK");
544 | var mcnk_ofs_root = adt.ChunksOfs(0, root_mcnk_int);
545 | var mcnk_ofs_tex = tex.ChunksOfs(0, root_mcnk_int);
546 | var mcnk_ofs_obj = obj.ChunksOfs(0, root_mcnk_int);
547 |
548 | int size_root_mcnk = adt.ReadInt(mcnk_ofs_root[root_mcnk_int] + 4);
549 | int size_tex_mcnk = tex.ReadInt(mcnk_ofs_tex[root_mcnk_int] + 4);
550 | int size_obj_mcnk = obj.ReadInt(mcnk_ofs_obj[root_mcnk_int] + 4);
551 |
552 | mcnk_ofs_root.Remove(root_mcnk_int);
553 | mcnk_ofs_tex.Remove(root_mcnk_int);
554 | mcnk_ofs_obj.Remove(root_mcnk_int);
555 |
556 | ChunkedWowFile root_mcnk = new ChunkedWowFile(adt.Data, mcnk_ofs_root[root_mcnk_int] + 8, size_root_mcnk);
557 | ChunkedWowFile tex_mcnk = new ChunkedWowFile(tex.Data, mcnk_ofs_tex[root_mcnk_int] + 8, size_tex_mcnk);
558 | ChunkedWowFile obj_mcnk = new ChunkedWowFile(obj.Data, mcnk_ofs_obj[root_mcnk_int] + 8, size_obj_mcnk);
559 |
560 | // remove MCNK in split files
561 | tex.RemoveBytes(0, size_tex_mcnk + 8);
562 | obj.RemoveBytes(0, size_obj_mcnk + 8);
563 |
564 | Dictionary adt_chunks = root_mcnk.ChunksOfs(0x88, (int)chunks.MCNK);
565 | Dictionary tex_chunks = tex_mcnk.ChunksOfs(0, (int)chunks.MCNK);
566 | Dictionary obj_chunks = obj_mcnk.ChunksOfs(0, (int)chunks.MCNK);
567 |
568 | int pos = 0;
569 | int ofsMCVT = 0x88;
570 | int sizeMCVT = (9 * 9 + 8 * 8) * 4;
571 |
572 | root_mcnk.WriteInt(pos + 0x3C, 0);
573 |
574 | uint flags = root_mcnk.ReadUInt(pos + 0x8);
575 |
576 | // fix high res hole
577 | if ((flags & 0x10000) != 0)
578 | {
579 | root_mcnk.WriteUShort(pos + 0x3C + 0x8, HighToLowResHole(root_mcnk.ReadULong(pos + 0x14 + 0x8)));
580 | }
581 |
582 | root_mcnk.WriteUInt(pos + 0x8, flags & 0xFFFF);
583 |
584 | pos += ofsMCVT + 0x8 + sizeMCVT;
585 |
586 | int ofsMCCV = 0;
587 | int sizeMCCV = 0;
588 |
589 | if (adt_chunks.ContainsKey((int)chunks.MCCV))
590 | {
591 | ofsMCCV = pos;
592 | sizeMCCV = root_mcnk.ReadInt(ofsMCCV + 0x4) + 0x8;
593 | pos += sizeMCCV;
594 | }
595 |
596 | // remove MCLV
597 | if (adt_chunks.ContainsKey((int)chunks.MCLV))
598 | {
599 | root_mcnk.RemoveUnwantedChunksUntil(pos, (int)chunks.MCNR);
600 | }
601 |
602 | int ofsMCNR = pos;
603 | pos += 448 + 0x8;
604 | root_mcnk.WriteInt(ofsMCNR + 0x4, 435);
605 |
606 | int ofsMCLY = 0;
607 | int sizeMCLY = 0;
608 |
609 | int nLayer = 0;
610 |
611 | List mcal_offsets = new List();
612 |
613 | if (tex_chunks.ContainsKey((int)chunks.MCLY))
614 | {
615 | tex_mcnk.RemoveUnwantedChunksUntil(0, (int)chunks.MCLY);
616 | ofsMCLY = pos;
617 | int size = tex_mcnk.ReadInt(0x4);
618 | sizeMCLY = size + 0x8;
619 | root_mcnk.AddEmptyBytes(pos, sizeMCLY);
620 | tex_mcnk.BlockCopy(0, root_mcnk, pos, sizeMCLY);
621 | tex_mcnk.RemoveBytes(0, sizeMCLY);
622 |
623 | nLayer = size / 0x10;
624 |
625 | int layer_pos = pos + 0x8;
626 | for (int i = 0; i < nLayer; ++i)
627 | {
628 | uint groundEffect = root_mcnk.ReadUInt(layer_pos + 0xC);
629 | if (groundEffect > 73186) // max wotlk id in GroundEffectTexture
630 | {
631 | root_mcnk.WriteInt(layer_pos + 0xC, 0);
632 | }
633 | root_mcnk.WriteUInt(layer_pos + 0x4, root_mcnk.ReadUInt(layer_pos + 0x4) & 0x7FF);
634 | mcal_offsets.Add(root_mcnk.ReadInt(layer_pos + 0x8));
635 |
636 | layer_pos += 0x10;
637 | }
638 |
639 | if (nLayer > 4)
640 | {
641 | root_mcnk.RemoveBytes(pos + 0x8 + 64, 16 * (nLayer - 4));
642 | sizeMCLY = 64 + 0x8;
643 | root_mcnk.WriteInt(pos + 0x4, 64);
644 | nLayer = 4;
645 | }
646 | pos += sizeMCLY;
647 | }
648 |
649 | int ofsMCRF = pos;
650 | int sizeMCRF = 0x8;
651 |
652 | int nDoodads = 0, nMapObjRefs = 0;
653 |
654 | root_mcnk.AddEmptyBytes(pos, 8);
655 | root_mcnk.WriteInt(pos, ChunkedWowFile.MagicToInt("MCRF"));
656 | pos += 0x8;
657 |
658 | if (models)
659 | {
660 | if (obj_chunks.ContainsKey((int)chunks.MCRD))
661 | {
662 | obj_mcnk.RemoveUnwantedChunksUntil(0, (int)chunks.MCRD);
663 | int sizeMCRD = obj_mcnk.ReadInt(0x4);
664 | root_mcnk.AddEmptyBytes(pos, sizeMCRD);
665 | obj_mcnk.BlockCopy(0x8, root_mcnk, pos, sizeMCRD);
666 | pos += sizeMCRD;
667 | nDoodads = sizeMCRD / 4;
668 | sizeMCRF += sizeMCRD;
669 | obj_mcnk.RemoveBytes(0, 0x8 + sizeMCRD);
670 | }
671 |
672 | if (obj_chunks.ContainsKey((int)chunks.MCRW))
673 | {
674 | obj_mcnk.RemoveUnwantedChunksUntil(0, (int)chunks.MCRW);
675 | int sizeMCRW = obj_mcnk.ReadInt(0x4);
676 | root_mcnk.AddEmptyBytes(pos, sizeMCRW);
677 | obj_mcnk.BlockCopy(0x8, root_mcnk, pos, sizeMCRW);
678 | pos += sizeMCRW;
679 | nMapObjRefs = sizeMCRW / 4;
680 | sizeMCRF += sizeMCRW;
681 | obj_mcnk.RemoveBytes(0, 0x8 + sizeMCRW);
682 | }
683 | }
684 |
685 | // update MCRF size
686 | root_mcnk.WriteInt(ofsMCRF + 0x4, sizeMCRF - 0x8);
687 |
688 | // MCSH
689 | int ofsMCSH = 0;
690 | int sizeMCSH = 0;
691 |
692 | if (tex_chunks.ContainsKey((int)chunks.MCSH))
693 | {
694 | ofsMCSH = pos;
695 | tex_mcnk.RemoveUnwantedChunksUntil(0, (int)chunks.MCSH);
696 | sizeMCSH = tex_mcnk.ReadInt(0x4) + 0x8;
697 | root_mcnk.AddEmptyBytes(pos, sizeMCSH);
698 | tex_mcnk.BlockCopy(0, root_mcnk, pos, sizeMCSH);
699 | pos += sizeMCSH;
700 | tex_mcnk.RemoveBytes(0, sizeMCSH);
701 | }
702 |
703 |
704 | // MCAL
705 | int ofsMCAL = 0;
706 | int sizeMCAL = 0;
707 | ofsMCAL = pos;
708 |
709 | if (tex_chunks.ContainsKey((int)chunks.MCAL))
710 | {
711 | tex_mcnk.RemoveUnwantedChunksUntil(0, (int)chunks.MCAL);
712 | sizeMCAL = tex_mcnk.ReadInt(0x4) + 0x8;
713 | root_mcnk.AddEmptyBytes(pos, sizeMCAL);
714 | tex_mcnk.BlockCopy(0, root_mcnk, pos, sizeMCAL);
715 | tex_mcnk.RemoveBytes(0, sizeMCAL);
716 |
717 | if (mcal_offsets.Count() > 4)
718 | {
719 | int size = sizeMCAL - 0x8;
720 | int target = mcal_offsets[4];
721 | root_mcnk.RemoveBytes(pos + 0x8 + target, size - target);
722 | sizeMCAL = target + 0x8;
723 | root_mcnk.WriteInt(pos + 0x4, target);
724 | }
725 |
726 | pos += sizeMCAL;
727 |
728 | }
729 | if (sizeMCAL == 0)
730 | {
731 | root_mcnk.AddEmptyBytes(pos, 8);
732 | root_mcnk.WriteInt(pos, (int)chunks.MCAL);
733 | sizeMCAL = 0x8;
734 | pos += 8;
735 | }
736 |
737 | // MCSE
738 | int ofsMCSE = pos;
739 | int sizeMCSE = 0;
740 | int nSoundEmitter = 0;
741 |
742 | if (adt_chunks.ContainsKey((int)chunks.MCSE))
743 | {
744 | root_mcnk.RemoveUnwantedChunksUntil(pos, (int)chunks.MCSE);
745 | sizeMCSE = root_mcnk.ReadInt(pos + 0x4) + 0x8;
746 | nSoundEmitter = (sizeMCSE - 8) / 0x1C;
747 | pos += sizeMCSE;
748 | }
749 | else
750 | {
751 | ofsMCSE = 0;
752 | }
753 |
754 | adt.AddEmptyBytes(adtPos, root_mcnk.Size() - size_root_mcnk - 8);
755 | root_mcnk.BlockCopy(0, adt.Data, adtPos, root_mcnk.Size());
756 |
757 | FillMCIN(id, adtPos, root_mcnk.Size());
758 |
759 | adt.WriteInt(adtPos, ChunkedWowFile.MagicToInt("MCNK")); // should not be necessary
760 | adt.WriteInt(adtPos + 0x4, root_mcnk.Size() - 0x8);
761 |
762 | int ofsPos = adtPos + 0x8; // MCNK header for offsets
763 |
764 | // Update headers
765 | adt.WriteInt(ofsPos + 0x4, (id % 16));
766 | adt.WriteInt(ofsPos + 0x8, (id / 16));
767 | // nLayer
768 | adt.WriteInt(ofsPos + 0xC, nLayer);
769 | // nDoodads
770 | adt.WriteInt(ofsPos + 0x10, nDoodads);
771 | adt.WriteInt(ofsPos + 0x14, ofsMCVT);
772 | adt.WriteInt(ofsPos + 0x18, ofsMCNR);
773 | adt.WriteInt(ofsPos + 0x1C, ofsMCLY);
774 | adt.WriteInt(ofsPos + 0x20, ofsMCRF);
775 | adt.WriteInt(ofsPos + 0x24, ofsMCAL);
776 | // sizeAlpha
777 | adt.WriteInt(ofsPos + 0x28, sizeMCAL);
778 | adt.WriteInt(ofsPos + 0x2C, ofsMCSH);
779 | // size shadow
780 | adt.WriteInt(ofsPos + 0x30, sizeMCSH);
781 | // area id
782 | adt.WriteInt(ofsPos + 0x34, 0);
783 | // nMapObjRefs
784 | adt.WriteInt(ofsPos + 0x38, nMapObjRefs);
785 | adt.WriteInt(ofsPos + 0x50, 0);
786 | adt.WriteInt(ofsPos + 0x58, ofsMCSE);
787 | // nSoundEmitter
788 | adt.WriteInt(ofsPos + 0x5C, nSoundEmitter);
789 | adt.WriteInt(ofsPos + 0x60, 0); // MCLQ
790 | adt.WriteInt(ofsPos + 0x64, 0); // size Liquid
791 | adt.WriteInt(ofsPos + 0x74, ofsMCCV);
792 | adt.WriteInt(ofsPos + 0x78, 0);
793 | adt.WriteInt(ofsPos + 0x7C, 0);
794 |
795 | adtPos += root_mcnk.Size();
796 | }
797 |
798 | private void FillMCIN(int id, int ofs, int size)
799 | {
800 | int pos = 0x5C + 0x10 * id;
801 | adt.WriteInt(pos, ofs);
802 | adt.WriteInt(pos + 0x4, size);
803 | }
804 |
805 | private void CheckMFBO()
806 | {
807 | adt.RemoveUnwantedChunksUntil(adtPos, "MFBO");
808 |
809 | if (adtPos < adt.Size() - 4 && adt.ReadInt(adtPos) == ChunkedWowFile.MagicToInt("MFBO"))
810 | {
811 | adt.WriteInt(0x38, adtPos - 0x14);
812 | adtPos += adt.ReadInt(adtPos + 0x4) + 0x8;
813 | }
814 | else
815 | {
816 | adt.WriteInt(0x38, 0x0);
817 | }
818 | }
819 |
820 | private void RetrieveMTXF()
821 | {
822 | adt.WriteInt(0x40, adtPos - 0x14);
823 |
824 | int posMTXF = 0, posMTXP = 0;
825 | int i = 0;
826 | for (i = 0; i < tex.Size() - 8; i += tex.ReadInt(i + 4))
827 | {
828 | if (tex.IsChunk(i, "MTXF"))
829 | {
830 | posMTXF = i;
831 | break;
832 | }
833 | else if (tex.IsChunk(i, "MTXP"))
834 | {
835 | posMTXP = i;
836 | break;
837 | }
838 | }
839 |
840 | if (posMTXF > 0)
841 | {
842 | int size = tex.ReadInt(i + 0x4);
843 | adt.AddEmptyBytes(adtPos, 0x8 + size);
844 | adt.WriteInt(adtPos, ChunkedWowFile.MagicToInt("MTXF"));
845 | adt.WriteInt(adtPos + 0x4, size);
846 | adtPos += 0x8;
847 |
848 | for (int k = posMTXF + 0x8; k < posMTXF + 0x8 + size; k += 0x4)
849 | {
850 | // only flag used in wotlk
851 | adt.WriteInt(adtPos, tex.Data[k] & 0x1);
852 | adtPos += 0x4;
853 | }
854 | }
855 | else if (posMTXP > 0)
856 | {
857 | int size = tex.ReadInt(i + 0x4);
858 | int mtxf_size = size / 4;
859 |
860 | adt.AddEmptyBytes(adtPos, 0x8 + mtxf_size);
861 | adt.WriteInt(adtPos, ChunkedWowFile.MagicToInt("MTXF"));
862 | adt.WriteInt(adtPos + 0x4, mtxf_size);
863 | adtPos += 0x8;
864 |
865 | for (int k = posMTXP + 0x8; k < posMTXP + 0x8 + size; k += 0x10)
866 | {
867 | // only flag used in wotlk
868 | adt.WriteInt(adtPos, tex.Data[k] & 0x1);
869 | adtPos += 0x4;
870 | }
871 | }
872 | else
873 | {
874 | adt.AddEmptyBytes(adtPos, 0x8 + textureCount * 4);
875 | adt.WriteInt(adtPos, ChunkedWowFile.MagicToInt("MTXF"));
876 | adt.WriteInt(adtPos + 0x4, textureCount * 4);
877 | adtPos += 0x8 + textureCount * 4;
878 | }
879 | }
880 |
881 | private uint CalculateChunkSize(IDictionary filenames)
882 | {
883 | var finalSize = 0u;
884 |
885 | foreach (var filename in filenames)
886 | finalSize += (uint)filename.Value.Length;
887 |
888 | return finalSize;
889 | }
890 |
891 | public void Save()
892 | {
893 | adt.Save();
894 |
895 | // Cleanup
896 | obj.RemoveOnDisk();
897 | tex.RemoveOnDisk();
898 | Utils.DeleteFile(file.Replace(".adt", ".tex"));
899 | Utils.DeleteFile(file.Replace(".adt", "_occ.wdt"));
900 | Utils.DeleteFile(file.Replace(".adt", "_lgt.wdt"));
901 | }
902 | }
903 |
904 | public struct MDDF
905 | {
906 | public uint NameId;
907 | public uint UniqueId;
908 | public C3Vector Position;
909 | public C3Vector Rotation;
910 | public ushort Scale;
911 | public ushort Flags;
912 | }
913 |
914 | public struct MODF
915 | {
916 | public uint NameId;
917 | public uint UniqueId;
918 | public C3Vector Position;
919 | public C3Vector Rotation;
920 | public CAaBox Extents;
921 | public ushort Flags;
922 | public ushort DoodadSet;
923 | public ushort NameSet;
924 | public ushort Scale;
925 | }
926 | }
927 |
--------------------------------------------------------------------------------
/MultiConverter.Lib/Converters/AnimConverter.cs:
--------------------------------------------------------------------------------
1 | using MultiConverter.Lib.Converters.Base;
2 |
3 | namespace MultiConverter.Lib.Converters
4 | {
5 | public class AnimConverter : ChunkedWowFile
6 | {
7 | public AnimConverter(string file) : base(file)
8 | {
9 |
10 | }
11 |
12 | public bool Fix()
13 | {
14 | if (IsChunk(0, "2MFA"))
15 | {
16 | RemoveBytes(0, 0x8);
17 | return true;
18 | }
19 |
20 | return false;
21 | }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/MultiConverter.Lib/Converters/Base/ChunkedWowFile.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 |
4 | namespace MultiConverter.Lib.Converters.Base
5 | {
6 | public class ChunkedWowFile : WowFile
7 | {
8 | public ChunkedWowFile(string file) : base(file)
9 | {
10 | }
11 |
12 | public ChunkedWowFile(byte[] buff, int start, int count) : base("")
13 | {
14 | Data = new byte[count];
15 | Buffer.BlockCopy(buff, start, Data, 0, count);
16 | }
17 |
18 | public bool IsChunk(int pos, string magic)
19 | {
20 | return IsChunk(pos, MagicToInt(magic));
21 | }
22 |
23 | public bool IsChunk(int pos, int magic)
24 | {
25 | return BitConverter.ToInt32(Data, pos) == magic;
26 | }
27 |
28 | public void WriteHeaderMagic(int pos, string magic)
29 | {
30 | WriteInt(pos, MagicToInt(magic));
31 | }
32 |
33 | public void WriteHeaderMagic(string magic, ref int pos)
34 | {
35 | WriteInt(MagicToInt(magic), ref pos);
36 | }
37 |
38 | ///
39 | /// Remove all chunks between the starting position and the desired chunk
40 | ///
41 | /// starting pos
42 | /// chunk
43 | public void RemoveUnwantedChunksUntil(int start, string magic)
44 | {
45 | int value = MagicToInt(magic.ToUpper());
46 | // valid chunk
47 | if (value > 0)
48 | {
49 | RemoveUnwantedChunksUntil(start, value);
50 | }
51 | }
52 |
53 | ///
54 | /// Convert chunk magic to the value when stored in the file
55 | ///
56 | /// chunk magic (ex: MCNK)
57 | /// chunkk magic
58 | public static int MagicToInt(string chunk)
59 | {
60 | if (chunk.Length != 4)
61 | {
62 | return 0;
63 | }
64 |
65 | int magic = 0;
66 |
67 | for (int i = 0; i < 4; ++i)
68 | {
69 | // it's inverted in the file
70 | magic += chunk[3 - i] << (8 * i);
71 | }
72 |
73 | return magic;
74 | }
75 |
76 | public static int InvertedMagicToInt(string chunk)
77 | {
78 | if (chunk.Length != 4)
79 | {
80 | return 0;
81 | }
82 |
83 | int magic = 0;
84 |
85 | for (int i = 0; i < 4; ++i)
86 | {
87 | // it's inverted in the file
88 | magic += chunk[i] << (8 * i);
89 | }
90 |
91 | return magic;
92 | }
93 |
94 | ///
95 | /// Remove all chunks between the starting position and the desired chunk
96 | ///
97 | /// starting pos
98 | /// chunk magic
99 | public void RemoveUnwantedChunksUntil(int start, int magic)
100 | {
101 | if (Data.Length < start + 9)
102 | {
103 | return;
104 | }
105 |
106 | int header = ReadInt(start);
107 | int end = start;
108 | // check to prevent out of bound exception
109 | while (header != magic && Data.Length > end + 8)
110 | {
111 | end += ReadInt(end + 0x4) + 0x8;
112 |
113 | if (Data.Length < end + 4)
114 | {
115 | break;
116 | }
117 | header = ReadInt(end);
118 | }
119 | RemoveBytes(start, end - start);
120 | }
121 |
122 | public Dictionary ChunksOfs(int start, string end_magic)
123 | {
124 | return ChunksOfs(start, MagicToInt(end_magic));
125 | }
126 |
127 | public Dictionary ChunksOfs(int start, int end_magic)
128 | {
129 | var chunk_pos = new Dictionary();
130 |
131 | if (start < Data.Length)
132 | {
133 | int pos = start;
134 | int magic = ReadInt(pos);
135 |
136 | if (magic == end_magic)
137 | chunk_pos.Add(magic, pos);
138 |
139 | while (magic != end_magic && pos <= Data.Length - 8)
140 | {
141 | magic = ReadInt(pos);
142 | if (!chunk_pos.ContainsKey(magic))
143 | chunk_pos.Add(magic, pos);
144 |
145 | int size = ReadInt(pos + 0x4) + 0x8;
146 | pos += size;
147 | }
148 | }
149 |
150 | return chunk_pos;
151 | }
152 |
153 | public bool HasChunk(string chunkMagic)
154 | {
155 | var magic = MagicToInt(chunkMagic);
156 | var chunks = ChunksOfs(0, magic);
157 |
158 | return chunks.ContainsKey(magic);
159 | }
160 |
161 | public int SkipChunk(int pos, string magic)
162 | {
163 | RemoveUnwantedChunksUntil(pos, magic);
164 | // Console.WriteLine($"Magic: {magic} Current Pos: {pos} New Pos: {pos + ReadInt(pos + 0x4) + 0x8}");
165 | return pos + ReadInt(pos + 0x4) + 0x8;
166 | }
167 | }
168 | }
169 |
--------------------------------------------------------------------------------
/MultiConverter.Lib/Converters/Base/IChunk.cs:
--------------------------------------------------------------------------------
1 | namespace MultiConverter.Lib.Converters.Base
2 | {
3 | public interface IChunk
4 | {
5 | ///
6 | /// Chunk Magic
7 | ///
8 | string Signature { get; }
9 |
10 | ///
11 | /// Chunk Length
12 | ///
13 | uint Length { get; }
14 |
15 | ///
16 | /// Order 'id' of the chunk
17 | /// and where to place it.
18 | ///
19 | uint Order { get; }
20 |
21 | ///
22 | /// Read the chunk data.
23 | ///
24 | ///
25 | void Read(byte[] inData);
26 |
27 | ///
28 | /// Write the chunk data.
29 | ///
30 | ///
31 | byte[] Write();
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/MultiConverter.Lib/Converters/Base/IConverter.cs:
--------------------------------------------------------------------------------
1 | namespace MultiConverter.Lib.Converters.Base
2 | {
3 | public interface IConverter
4 | {
5 | void Read(byte[] inData);
6 | void Write(string filename);
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/MultiConverter.Lib/Converters/Base/WowFile.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.IO;
3 |
4 | namespace MultiConverter.Lib.Converters.Base
5 | {
6 | public class WowFile
7 | {
8 | public byte[] Data { get; protected set; }
9 | public string Path { get; }
10 | public bool Valid { get; } = false;
11 |
12 | public WowFile(string file)
13 | {
14 | Path = file;
15 |
16 | if (File.Exists(Path))
17 | {
18 | Valid = true;
19 | Data = File.ReadAllBytes(Path);
20 | }
21 | }
22 |
23 | #region read
24 | public char ReadChar(int pos)
25 | {
26 | return BitConverter.ToChar(Data, pos);
27 | }
28 | public short ReadShort(int pos)
29 | {
30 | return BitConverter.ToInt16(Data, pos);
31 | }
32 | public ushort ReadUShort(int pos)
33 | {
34 | return BitConverter.ToUInt16(Data, pos);
35 | }
36 | public int ReadInt(int pos)
37 | {
38 | return BitConverter.ToInt32(Data, pos);
39 | }
40 | public uint ReadUInt(int pos)
41 | {
42 | return BitConverter.ToUInt32(Data, pos);
43 | }
44 | public ulong ReadULong(int pos)
45 | {
46 | return BitConverter.ToUInt64(Data, pos);
47 | }
48 | public float ReadFloat(int pos)
49 | {
50 | return BitConverter.ToSingle(Data, pos);
51 | }
52 | #endregion
53 |
54 | #region write
55 | public void WriteChar(int pos, char value)
56 | {
57 | Buffer.BlockCopy(BitConverter.GetBytes(value), 0, Data, pos, 1);
58 | }
59 | public void WriteChar(char value, ref int pos)
60 | {
61 | Buffer.BlockCopy(BitConverter.GetBytes(value), 0, Data, pos, 1);
62 | pos += 1;
63 | }
64 | public void WriteShort(int pos, short value)
65 | {
66 | Buffer.BlockCopy(BitConverter.GetBytes(value), 0, Data, pos, 2);
67 | }
68 | public void WriteShort(short value, ref int pos)
69 | {
70 | Buffer.BlockCopy(BitConverter.GetBytes(value), 0, Data, pos, 2);
71 | pos += 2;
72 | }
73 | public void WriteUShort(int pos, ushort value)
74 | {
75 | Buffer.BlockCopy(BitConverter.GetBytes(value), 0, Data, pos, 2);
76 | }
77 | public void WriteUShort(ushort value, ref int pos)
78 | {
79 | Buffer.BlockCopy(BitConverter.GetBytes(value), 0, Data, pos, 2);
80 | pos += 2;
81 | }
82 | public void WriteInt(int pos, int value)
83 | {
84 | Buffer.BlockCopy(BitConverter.GetBytes(value), 0, Data, pos, 4);
85 | }
86 | public void WriteInt(int value, ref int pos)
87 | {
88 | Buffer.BlockCopy(BitConverter.GetBytes(value), 0, Data, pos, 4);
89 | pos += 4;
90 | }
91 | public void WriteUInt(int pos, uint value)
92 | {
93 | Buffer.BlockCopy(BitConverter.GetBytes(value), 0, Data, pos, 4);
94 | }
95 | public void WriteUInt(uint value, ref int pos)
96 | {
97 | Buffer.BlockCopy(BitConverter.GetBytes(value), 0, Data, pos, 4);
98 | pos += 4;
99 | }
100 | public void WriteFloat(int pos, float value)
101 | {
102 | Buffer.BlockCopy(BitConverter.GetBytes(value), 0, Data, pos, 4);
103 | }
104 | public void WriteFloat(float value, ref int pos)
105 | {
106 | Buffer.BlockCopy(BitConverter.GetBytes(value), 0, Data, pos, 4);
107 | pos += 4;
108 | }
109 | public void WriteString(string value, ref int pos)
110 | {
111 | for (var i = 0; i < value.Length; ++i)
112 | WriteChar(pos + i, value[i]);
113 |
114 | pos += value.Length;
115 | }
116 | #endregion
117 |
118 | #region edit
119 | public void RemoveBytes(int start, int count)
120 | {
121 | int size = Data.Length;
122 |
123 | if (size < start + count || count <= 0)
124 | {
125 | // todo: exceptions
126 | return;
127 | }
128 |
129 | byte[] tmp = new byte[size - count];
130 | if (start > 0)
131 | {
132 | Buffer.BlockCopy(Data, 0, tmp, 0, start);
133 | }
134 | Buffer.BlockCopy(Data, start + count, tmp, start, size - count - start);
135 | Data = tmp;
136 | }
137 |
138 | public void AddEmptyBytes(int start, int count)
139 | {
140 | int size = Data.Length;
141 | byte[] tmp = new byte[size + count];
142 | Buffer.BlockCopy(Data, 0, tmp, 0, start);
143 | Buffer.BlockCopy(Data, start, tmp, start + count, size - start);
144 | Data = tmp;
145 | }
146 |
147 | public void InsertBytes(int start, byte[] bytes)
148 | {
149 | AddEmptyBytes(start, bytes.Length);
150 | Buffer.BlockCopy(bytes, 0, Data, start, bytes.Length);
151 | }
152 |
153 | public void BlockCopy(int source_ofs, WowFile dest, int dest_ofs, int count)
154 | {
155 | Buffer.BlockCopy(Data, source_ofs, dest.Data, dest_ofs, count);
156 | }
157 |
158 | public void BlockCopy(int source_ofs, Array dest, int dest_ofs, int count)
159 | {
160 | Buffer.BlockCopy(Data, source_ofs, dest, dest_ofs, count);
161 | }
162 | #endregion
163 |
164 | public int Size() => Data.Length;
165 |
166 | public void RemoveOnDisk()
167 | {
168 | if (Valid)
169 | File.Delete(Path);
170 | }
171 |
172 | public virtual void Save()
173 | {
174 | if (Valid)
175 | File.WriteAllBytes(Path, Data);
176 | }
177 | };
178 | }
179 |
--------------------------------------------------------------------------------
/MultiConverter.Lib/Converters/Chunks.cs:
--------------------------------------------------------------------------------
1 | namespace MultiConverter.Lib.Converters
2 | {
3 | public enum WMOChunkId
4 | {
5 | MVER = 0x4d564552,
6 | MOMO = 0x4d4f4d4f,
7 | MOHD = 0x4d4f4844,
8 | MOTX = 0x4d4f5458,
9 | MOMT = 0x4d4f4d54,
10 | MOUV = 0x4d4f5556,
11 | MOGN = 0x4d4f474e,
12 | MOGI = 0x4d4f4749,
13 | MOSB = 0x4d4f5342,
14 | MOPV = 0x4d4f5056,
15 | MOPT = 0x4d4f5054,
16 | MOPR = 0x4d4f5052,
17 | MOVV = 0x4d4f5656,
18 | MOVB = 0x4d4f5642,
19 | MOLT = 0x4d4f4c54,
20 | MODS = 0x4d4f4453,
21 | MODN = 0x4d4f444e,
22 | MODI = 0x4d4f4449,
23 | MODD = 0x4d4f4444,
24 | MFOG = 0x4d464f47,
25 | MCVP = 0x4d435650,
26 | GFID = 0x47464944,
27 | MOGP = 0x4d4f4750,
28 | MOPY = 0x4d4f5059,
29 | MOVI = 0x4d4f5649,
30 | MOVT = 0x4d4f5654,
31 | MONR = 0x4d4f4e52,
32 | MOTV = 0x4d4f5456,
33 | MOLV = 0x4d4f4c56,
34 | MOIN = 0x4d4f494e,
35 | MOBA = 0x4d4f4241,
36 | MOLR = 0x4d4f4c52,
37 | MODR = 0x4d4f4452,
38 | MOBN = 0x4d4f424e,
39 | MOBR = 0x4d4f4252,
40 | MOCV = 0x4d4f4356,
41 | MLIQ = 0x4d4c4951,
42 | MORI = 0x4d4f5249,
43 | MORB = 0x4d4f5242,
44 | MOTA = 0x4d4f5441,
45 | MOBS = 0x4d4f4253,
46 | MDAL = 0x4d44414c,
47 | MOPL = 0x4d4f504c,
48 | MOPB = 0x4d4f5042,
49 | MOLS = 0x4d4f4c53,
50 | MOLP = 0x4d4f4c50,
51 | MOLM = 0x4d4f4c4d,
52 | MOLD = 0x4d4f4c44,
53 | MPBV = 0x4d504256,
54 | MPBP = 0x4d504250,
55 | MPBI = 0x4d504249,
56 | MPBG = 0x4d504247,
57 | MGI2 = 0x4D474932,
58 | MDDI = 0x4D444449,
59 | MNLD = 0x4D4E4C44,
60 | MFED = 0x4D464544,
61 | MVAD = 0x4D415644,
62 | }
63 |
64 | public enum M2ChunkId
65 | {
66 | PFID = 0x44494650,
67 | SFID = 0x44494653,
68 | AFID = 0x44494641,
69 | BFID = 0x44494642,
70 | MD21 = 0x3132444D,
71 | TXAC = 0x43415854,
72 | EXPT = 0x54505845,
73 | EXP2 = 0x32505845,
74 | PABC = 0x43424150,
75 | PADC = 0x43444150,
76 | PSBC = 0x43425350,
77 | PEDC = 0x43444550,
78 | SKID = 0x44494B53,
79 | TXID = 0x44495854,
80 | LDV1 = 0x3156444C,
81 | MD20 = 0x3032444D
82 | }
83 | }
84 |
--------------------------------------------------------------------------------
/MultiConverter.Lib/Converters/SkinConverter.cs:
--------------------------------------------------------------------------------
1 | using MultiConverter.Lib.Converters.Base;
2 | using System;
3 | using System.Collections.Generic;
4 |
5 | namespace MultiConverter.Lib.Converters
6 | {
7 | public class SkinConverter : WowFile
8 | {
9 | private HashSet badsubmesh;
10 |
11 | public SkinConverter(string skin) : base(skin)
12 | {
13 | badsubmesh = new HashSet();
14 | }
15 |
16 | public void Fix(ref List texture_unit_lookup, ref List blendmode_override, int n_transparency_lookup)
17 | {
18 | FixSubmesh();
19 | FixTexUnit(ref texture_unit_lookup, ref blendmode_override, n_transparency_lookup);
20 | }
21 |
22 | private void FixSubmesh()
23 | {
24 | uint n = ReadUInt(0x1C);
25 | uint ofs = ReadUInt(0x20);
26 |
27 | for (uint i = 0; i < n; i++)
28 | {
29 | int pos = (int)(ofs + i * 0x30);
30 |
31 | if (ReadUShort(pos + 0x2) > 0)
32 | {
33 | for (int k = pos + 0x2; k < pos + 0x14; ++k)
34 | {
35 | Data[k] = 0;
36 | }
37 | badsubmesh.Add(i);
38 | }
39 | else if (Data[pos + 0x10] == 0)
40 | {
41 | Data[pos + 0x10] = 1;
42 | }
43 | Data[pos + 0x11] = 0;
44 | }
45 | }
46 |
47 | private void DuplicateTextureUnit(int start)
48 | {
49 | AddEmptyBytes(start + 0x18, 0x18);
50 | Buffer.BlockCopy(Data, start, Data, start + 0x18, 0x18);
51 | }
52 |
53 | private void FixTexUnit(ref List texture_unit_lookup, ref List blendmode_override, int n_transparency_lookup)
54 | {
55 | uint nTexUnit = ReadUInt(0x24);
56 | uint ofsTextUnit = ReadUInt(0x28);
57 |
58 | for (int i = (int)ofsTextUnit; i < ofsTextUnit + nTexUnit * 0x18; i += 0x18)
59 | {
60 | ushort shader_id = ReadUShort(i + 0x2), shader_to_save = 0;
61 | byte flags = Data[i];
62 |
63 | ushort submesh = ReadUShort((int)i + 0x4);
64 |
65 | if (badsubmesh.Contains(submesh))
66 | {
67 | WriteUInt((int)i + 0x2, 0x8000);
68 | continue;
69 | }
70 |
71 | ushort texture_count = ReadUShort(i + 0xE);
72 | Data[i] &= 0x10;
73 |
74 | bool skip_next_tu = false;
75 |
76 | if (shader_id >= 0x8000)
77 | {
78 | ushort low = (ushort)(shader_id & 0xFF);
79 |
80 | switch (low)
81 | {
82 | case 0:
83 | case 3:
84 | case 9:
85 | case 17:
86 | case 24:
87 | {
88 | skip_next_tu = true;
89 | texture_count = 2;
90 | DuplicateTextureUnit(i);
91 | nTexUnit++;
92 |
93 | Data[i + 0xE + 0x18] = 1; // next tu has 1 tex
94 |
95 | // use next renderflags
96 | WriteUShort(i + 0x18 + 0xA, (ushort)(ReadUShort(i + 0xA) + 1));
97 | // material layer
98 | WriteShort(i + 0x18 + 0xC, 1);
99 |
100 | ushort blend_1 = 1;
101 | ushort blend_2 = 4;
102 | short[] tu_lookup = { 0, -1 };
103 |
104 | bool added = false;
105 |
106 | for (ushort n = 0; n < blendmode_override.Count; n += 2)
107 | {
108 | if (blendmode_override[n] == blend_1 && blendmode_override[n + 1] == blend_2)
109 | {
110 | shader_to_save = n;
111 | added = true;
112 | break;
113 | }
114 | }
115 |
116 | if (!added)
117 | {
118 | shader_to_save = (ushort)blendmode_override.Count;
119 | blendmode_override.Add(blend_1);
120 | blendmode_override.Add(blend_2);
121 | }
122 |
123 | added = false;
124 | ushort tex_coord_to_save = 0;
125 | for (ushort n = 0; n < texture_unit_lookup.Count - 1; ++n)
126 | {
127 | if (texture_unit_lookup[n] == tu_lookup[0] && texture_unit_lookup[n + 1] == tu_lookup[1])
128 | {
129 | tex_coord_to_save = n;
130 | added = true;
131 | break;
132 | }
133 | }
134 |
135 | if (!added)
136 | {
137 | int tul_size = texture_unit_lookup.Count;
138 | if (tul_size > 1 && texture_unit_lookup[tul_size - 1] == tu_lookup[0])
139 | {
140 | tex_coord_to_save = (ushort)(tul_size - 1);
141 | texture_unit_lookup.Add(tu_lookup[1]);
142 | }
143 | else
144 | {
145 | tex_coord_to_save = (ushort)(tul_size);
146 | texture_unit_lookup.Add(tu_lookup[0]);
147 | texture_unit_lookup.Add(tu_lookup[1]);
148 | }
149 | }
150 |
151 | // texture coord combo
152 | WriteUShort(i + 0x12, tex_coord_to_save);
153 | WriteUShort(i + 0x18 + 0x12, tex_coord_to_save);
154 |
155 | WriteUShort(i + 0x2, shader_to_save);
156 | WriteUShort(i + 0x2 + 0x18, shader_to_save);
157 | }
158 | break;
159 | case 1:
160 | case 15:
161 | {
162 | skip_next_tu = true;
163 | texture_count = 1;
164 | DuplicateTextureUnit(i);
165 | nTexUnit++;
166 |
167 | Data[i + 0xE] = 1; // this tu has 1 tex
168 | Data[i + 0xE + 0x18] = 1; // next tu has 1 tex
169 |
170 | // use next renderflags
171 | WriteUShort(i + 0x18 + 0xA, (ushort)(ReadUShort(i + 0xA) + 1));
172 | // material layer
173 | WriteShort(i + 0x18 + 0xC, 1);
174 | // texture combo
175 | WriteUShort(i + 0x18 + 0x10, (ushort)(ReadUShort(i + 0x10) + 1));
176 | // transparency combo
177 | ushort transparency_combo = (ushort)(ReadUShort(i + 0x14));
178 | if (transparency_combo + 1 < n_transparency_lookup)
179 | {
180 | transparency_combo++;
181 | }
182 |
183 | WriteUShort(i + 0x18 + 0x14, transparency_combo);
184 |
185 | short[] tu_lookup = { 0, (short)(shader_id == 0x8001 ? -1 : 1) };
186 |
187 | // no blend override
188 | WriteUShort(i + 0x2, 0);
189 | WriteUShort(i + 0x2 + 0x18, 0);
190 |
191 |
192 | bool added = false;
193 | ushort tex_coord_to_save = 0;
194 | for (ushort n = 0; n < texture_unit_lookup.Count - 1; ++n)
195 | {
196 | if (texture_unit_lookup[n] == tu_lookup[0] && texture_unit_lookup[n + 1] == tu_lookup[1])
197 | {
198 | tex_coord_to_save = n;
199 | added = true;
200 | break;
201 | }
202 | }
203 |
204 | if (!added)
205 | {
206 | int tul_size = texture_unit_lookup.Count;
207 | if (tul_size > 1 && texture_unit_lookup[tul_size - 1] == tu_lookup[0])
208 | {
209 | tex_coord_to_save = (ushort)(tul_size - 1);
210 | texture_unit_lookup.Add(tu_lookup[1]);
211 | }
212 | else
213 | {
214 | tex_coord_to_save = (ushort)(tul_size);
215 | texture_unit_lookup.Add(tu_lookup[0]);
216 | texture_unit_lookup.Add(tu_lookup[1]);
217 | }
218 | }
219 |
220 | // texture coord combo
221 | WriteUShort(i + 0x12, tex_coord_to_save);
222 | tex_coord_to_save++;
223 | WriteUShort(i + 0x18 + 0x12, tex_coord_to_save);
224 | }
225 | break;
226 | case 2:
227 | {
228 | skip_next_tu = true;
229 | DuplicateTextureUnit(i);
230 | nTexUnit++;
231 |
232 | Data[i + 0xE + 0x18] = 1; // next tu has 1 tex
233 |
234 | // use next renderflags
235 | WriteUShort(i + 0x18 + 0xA, (ushort)(ReadUShort(i + 0xA) + 1));
236 | // material layer
237 | WriteShort(i + 0x18 + 0xC, 1);
238 |
239 | ushort blend_1 = 1;
240 | ushort blend_2 = 3;
241 | short[] tu_lookup = { 0, -1 };
242 |
243 | bool added = false;
244 |
245 | for (ushort n = 0; n < blendmode_override.Count; n += 2)
246 | {
247 | if (blendmode_override[n] == blend_1 && blendmode_override[n + 1] == blend_2)
248 | {
249 | shader_to_save = n;
250 | added = true;
251 | break;
252 | }
253 | }
254 |
255 | if (!added)
256 | {
257 | shader_to_save = (ushort)blendmode_override.Count;
258 | blendmode_override.Add(blend_1);
259 | blendmode_override.Add(blend_2);
260 | }
261 |
262 | WriteUShort(i + 0x2, shader_to_save);
263 | WriteUShort(i + 0x2 + 0x18, shader_to_save);
264 |
265 | added = false;
266 | ushort tex_coord_to_save = 0;
267 | for (ushort n = 0; n < texture_unit_lookup.Count - 1; ++n)
268 | {
269 | if (texture_unit_lookup[n] == tu_lookup[0] && texture_unit_lookup[n + 1] == tu_lookup[1])
270 | {
271 | tex_coord_to_save = n;
272 | added = true;
273 | break;
274 | }
275 | }
276 |
277 | if (!added)
278 | {
279 | int tul_size = texture_unit_lookup.Count;
280 | if (tul_size > 1 && texture_unit_lookup[tul_size - 1] == tu_lookup[0])
281 | {
282 | tex_coord_to_save = (ushort)(tul_size - 1);
283 | texture_unit_lookup.Add(tu_lookup[1]);
284 | }
285 | else
286 | {
287 | tex_coord_to_save = (ushort)(tul_size);
288 | texture_unit_lookup.Add(tu_lookup[0]);
289 | texture_unit_lookup.Add(tu_lookup[1]);
290 | }
291 | }
292 |
293 | // texture coord combo
294 | WriteUShort(i + 0x12, tex_coord_to_save);
295 | WriteUShort(i + 0x18 + 0x12, tex_coord_to_save);
296 | }
297 | break;
298 | case 5:
299 | case 8:
300 | case 10:
301 | case 12:
302 | case 16:
303 | case 23:
304 | shader_id = 0;
305 | texture_count = 1;
306 | break;
307 | // Combiners_Mod_Mod
308 | case 21:
309 | shader_id = 0x4011;
310 | texture_count = 2;
311 | break;
312 | // default: Combiners_Mod
313 | default:
314 | shader_id = 0x0010;
315 | texture_count = 1;
316 | break;
317 | }
318 | }
319 |
320 | if (shader_id < 0x8000)
321 | {
322 | ushort blend_1 = (ushort)((shader_id >> 4) & 0x7);
323 | ushort blend_2 = (ushort)(shader_id & 0x7);
324 |
325 | // T2
326 | if (texture_count > 1 && (shader_id & 0x4000) != 0 && blend_1 != 0 && blend_2 != 0)
327 | {
328 | bool added = false;
329 |
330 | for (ushort n = 0; n < blendmode_override.Count; n += 2)
331 | {
332 | if (blendmode_override[n] == blend_1 && blendmode_override[n + 1] == blend_2)
333 | {
334 | shader_to_save = n;
335 | added = true;
336 | break;
337 | }
338 | }
339 |
340 | if (!added)
341 | {
342 | shader_to_save = (ushort)blendmode_override.Count;
343 | blendmode_override.Add(blend_1);
344 | blendmode_override.Add(blend_2);
345 | }
346 | }
347 | else
348 | {
349 | texture_count = 1;
350 | }
351 |
352 | Data[i] &= 0x10;
353 | WriteUShort(i + 0x2, shader_to_save);
354 |
355 | // generate texture unit lookup
356 | short[] tu_lookup = new short[2];
357 |
358 | if (texture_count == 1)
359 | {
360 | if ((shader_id & 0x80) != 0)
361 | {
362 | tu_lookup[0] = -1;
363 | }
364 | else
365 | {
366 | tu_lookup[0] = 0;
367 | }
368 |
369 | if (texture_unit_lookup.Contains(tu_lookup[0]))
370 | {
371 | WriteUShort(i + 0x12, (ushort)texture_unit_lookup.IndexOf(tu_lookup[0]));
372 | }
373 | else
374 | {
375 | WriteUShort(i + 0x12, (ushort)texture_unit_lookup.Count);
376 | texture_unit_lookup.Add(tu_lookup[0]);
377 | }
378 | }
379 | else
380 | {
381 | if ((shader_id & 0x80) != 0)
382 | {
383 | tu_lookup[0] = -1;
384 | // check if wotlk need to use Env_T2 rather than Env_T1
385 | tu_lookup[1] = (short)(((shader_id & 0x8) != 0) ? -1 : 0);
386 | }
387 | else
388 | {
389 | tu_lookup[0] = 0;
390 | tu_lookup[1] = (short)(((shader_id & 0x8) != 0) ? -1 : (((shader_id & 0x4000) != 0) ? 1 : 0));
391 | }
392 |
393 | bool added = false;
394 | for (ushort n = 0; n < texture_unit_lookup.Count - 1; ++n)
395 | {
396 | if (texture_unit_lookup[n] == tu_lookup[0] && texture_unit_lookup[n + 1] == tu_lookup[1])
397 | {
398 | WriteUShort(i + 0x12, n);
399 | added = true;
400 | break;
401 | }
402 | }
403 |
404 | if (!added)
405 | {
406 | int tul_size = texture_unit_lookup.Count;
407 | if (tul_size > 1 && texture_unit_lookup[tul_size - 1] == tu_lookup[0])
408 | {
409 | WriteUShort(i + 0x12, (ushort)(tul_size - 1));
410 | texture_unit_lookup.Add(tu_lookup[1]);
411 | }
412 | else
413 | {
414 | WriteUShort(i + 0x12, (ushort)tul_size);
415 | texture_unit_lookup.Add(tu_lookup[0]);
416 | texture_unit_lookup.Add(tu_lookup[1]);
417 | }
418 | }
419 | }
420 | }
421 |
422 | WriteUShort(i + 0xE, Math.Min(texture_count, (ushort)2));
423 |
424 | if (skip_next_tu)
425 | {
426 | i += 0x18;
427 | }
428 | }
429 |
430 | WriteUInt(0x24, nTexUnit);
431 | }
432 | }
433 | }
434 |
--------------------------------------------------------------------------------
/MultiConverter.Lib/Converters/WDTConverter.cs:
--------------------------------------------------------------------------------
1 | using MultiConverter.Lib.Converters.Base;
2 |
3 | namespace MultiConverter.Lib.Converters
4 | {
5 | public class WDTConverter : ChunkedWowFile
6 | {
7 | public WDTConverter(string file) : base(file)
8 | {
9 | }
10 |
11 | public bool Fix()
12 | {
13 | int flags = ReadInt(0x14);
14 | if ((flags & 0x80) != 0)
15 | {
16 | flags |= 0x4;
17 | }
18 | Data[0x14] = (byte)(flags & 0x1f);
19 |
20 | for (int i = 0x3C; i < 0x3C + 32768; i += 0x8)
21 | {
22 | Data[i] &= 0x1;
23 | }
24 |
25 | return true;
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/MultiConverter.Lib/Converters/WMO/Chunks/MFOG.cs:
--------------------------------------------------------------------------------
1 | using MultiConverter.Lib.Converters.Base;
2 | using MultiConverter.Lib.Converters.WMO.Entries;
3 | using MultiConverter.Lib.Util;
4 | using System;
5 | using System.Collections.Generic;
6 | using System.IO;
7 | using System.Text;
8 |
9 | namespace MultiConverter.Lib.Converters.WMO.Chunks
10 | {
11 | public class MFOG : IChunk
12 | {
13 | public string Signature => "MFOG";
14 | public uint Length => (uint)Write().Length;
15 | public uint Order => 16;
16 |
17 | ///
18 | /// List of
19 | ///
20 | public List MFOGs = new List();
21 |
22 | public void Read(byte[] inData)
23 | {
24 | using (var stream = new MemoryStream(inData))
25 | using (var reader = new BinaryReader(stream))
26 | {
27 | var mfogSize = inData.Length / 48;
28 | for (var i = 0; i < mfogSize; ++i)
29 | {
30 | MFOGs.Add(new MFOGEntry
31 | {
32 | Flags = reader.ReadUInt32(),
33 | Position = reader.ReadC3Vector(),
34 | SmallRadius = reader.ReadSingle(),
35 | LargeRadius = reader.ReadSingle(),
36 | FogEnd = reader.ReadSingle(),
37 | FogStartMultiplier = reader.ReadSingle(),
38 | FogColor = reader.ReadCArgb(),
39 | Unk1 = reader.ReadSingle(),
40 | Unk2 = reader.ReadSingle(),
41 | FogColor2 = reader.ReadCArgb()
42 | });
43 | }
44 | }
45 | }
46 |
47 | public byte[] Write()
48 | {
49 | using (var stream = new MemoryStream())
50 | using (var writer = new BinaryWriter(stream))
51 | {
52 | foreach (var mfog in MFOGs)
53 | {
54 | writer.Write(mfog.Flags);
55 | writer.WriteC3Vector(mfog.Position);
56 | writer.Write(mfog.SmallRadius);
57 | writer.Write(mfog.LargeRadius);
58 | writer.Write(mfog.FogEnd);
59 | writer.Write(mfog.FogStartMultiplier);
60 | writer.WriteCArgb(mfog.FogColor);
61 | writer.Write(mfog.Unk1);
62 | writer.Write(mfog.Unk2);
63 | writer.WriteCArgb(mfog.FogColor2);
64 | }
65 |
66 | return stream.ToArray();
67 | }
68 | }
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/MultiConverter.Lib/Converters/WMO/Chunks/MODD.cs:
--------------------------------------------------------------------------------
1 | using MultiConverter.Lib.Converters.Base;
2 | using MultiConverter.Lib.Converters.WMO.Entries;
3 | using MultiConverter.Lib.Util;
4 | using System;
5 | using System.Collections.Generic;
6 | using System.IO;
7 | using System.Linq;
8 | using System.Text;
9 |
10 | namespace MultiConverter.Lib.Converters.WMO.Chunks
11 | {
12 | public class MODD : IChunk
13 | {
14 | public string Signature => "MODD";
15 | public uint Length => (uint)Write().Length;
16 | public uint Order => 15;
17 |
18 | ///
19 | /// List of
20 | ///
21 | public List MODDs = new List();
22 |
23 | ///
24 | /// List of all filenames
25 | ///
26 | public Dictionary Filenames = new Dictionary();
27 |
28 | private uint doodadOffset = 0;
29 |
30 | public void Read(byte[] inData)
31 | {
32 | using (var stream = new MemoryStream(inData))
33 | using (var reader = new BinaryReader(stream))
34 | {
35 | var moddSize = inData.Length / 40;
36 | for (var i = 0; i < moddSize; ++i)
37 | {
38 | var finalNameBytes = new byte[4];
39 | var nameOffsetBytes = reader.ReadBytes(3);
40 | Buffer.BlockCopy(nameOffsetBytes, 0, finalNameBytes, 0, 3);
41 |
42 | var modd = new MODDEntry
43 | {
44 | NameIndex = BitConverter.ToInt32(finalNameBytes, 0),
45 | Flags = reader.ReadByte(),
46 | Position = reader.ReadC3Vector(),
47 | Rotation = reader.ReadC3Vector(),
48 | RotationW = reader.ReadSingle(),
49 | Scale = reader.ReadSingle(),
50 | Color = reader.ReadCArgb()
51 | };
52 |
53 | var filename = AddFilename(MODI.DoodadFileIds[modd.NameIndex]);
54 | if (filename != string.Empty)
55 | {
56 | var idx = Filenames[filename];
57 | nameOffsetBytes = BitConverter.GetBytes(idx);
58 |
59 | Buffer.BlockCopy(nameOffsetBytes, 0, finalNameBytes, 0, 3);
60 | modd.NameIndex = BitConverter.ToInt32(finalNameBytes, 0);
61 | }
62 | else
63 | modd.NameIndex = -1;
64 |
65 | MODDs.Add(modd);
66 | }
67 | }
68 | }
69 |
70 | public byte[] Write()
71 | {
72 | using (var stream = new MemoryStream())
73 | using (var writer = new BinaryWriter(stream))
74 | {
75 | // Disable doodads.
76 | if (!WMOFile.DisableDoodads)
77 | {
78 | foreach (var modd in MODDs)
79 | {
80 | var nameOffsetBytes = BitConverter.GetBytes(modd.NameIndex);
81 | var finalNameOffsetBytes = new byte[3];
82 | Buffer.BlockCopy(nameOffsetBytes, 0, finalNameOffsetBytes, 0, 3);
83 |
84 | writer.Write(finalNameOffsetBytes);
85 | writer.Write(modd.Flags);
86 | writer.WriteC3Vector(modd.Position);
87 | writer.WriteC3Vector(modd.Rotation);
88 | writer.Write(modd.RotationW);
89 | writer.Write(modd.Scale);
90 | writer.WriteCArgb(modd.Color);
91 | }
92 | }
93 |
94 | return stream.ToArray();
95 | }
96 | }
97 |
98 | private string AddFilename(uint fdid)
99 | {
100 | if (fdid != 0)
101 | {
102 | var textureFilename = Listfile.LookupFilename(fdid, ".wmo").Replace('/', '\\') + "\0";
103 |
104 | if (!Filenames.ContainsKey(textureFilename))
105 | {
106 | Filenames.Add(textureFilename, doodadOffset);
107 | doodadOffset += (uint)textureFilename.Length;
108 | }
109 |
110 | return textureFilename;
111 | }
112 |
113 | return string.Empty;
114 | }
115 | }
116 | }
117 |
--------------------------------------------------------------------------------
/MultiConverter.Lib/Converters/WMO/Chunks/MODI.cs:
--------------------------------------------------------------------------------
1 | using MultiConverter.Lib.Converters.Base;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Linq;
5 |
6 | namespace MultiConverter.Lib.Converters.WMO.Chunks
7 | {
8 | public class MODI : IChunk
9 | {
10 | public string Signature => "MODI";
11 | public uint Length => 0;
12 | public uint Order => 0;
13 |
14 | public static uint[] DoodadFileIds;
15 | public static Dictionary DoodadNames = new Dictionary();
16 |
17 | public void Read(byte[] inData)
18 | {
19 | using (var stream = new MemoryStream(inData))
20 | using (var reader = new BinaryReader(stream))
21 | {
22 | var modiSize = inData.Length / 4;
23 | DoodadFileIds = new uint[modiSize];
24 |
25 | for (var i = 0; i < modiSize; ++i)
26 | {
27 | var filedataId = reader.ReadUInt32();
28 | var filename = Listfile.LookupFilename(filedataId, ".wmo", "m2").Replace("m2", "mdx").Replace("/", "\\") + "\0";
29 |
30 | if (!DoodadNames.ContainsKey(filedataId))
31 | DoodadNames.Add(filedataId, filename);
32 |
33 | DoodadFileIds[i] = filedataId;
34 | }
35 | }
36 |
37 | if (WMOFile.DisableDoodads)
38 | WMOFile.Chunks.Add(new MODN());
39 | else
40 | WMOFile.Chunks.Add(new MODN { DoodadFilenames = DoodadNames.Values.ToList() });
41 | }
42 |
43 | public byte[] Write() => new byte[0];
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/MultiConverter.Lib/Converters/WMO/Chunks/MODN.cs:
--------------------------------------------------------------------------------
1 | using MultiConverter.Lib.Converters.Base;
2 | using System.Collections.Generic;
3 | using System.IO;
4 |
5 | namespace MultiConverter.Lib.Converters.WMO.Chunks
6 | {
7 | public class MODN : IChunk
8 | {
9 | public string Signature => "MODN";
10 | public uint Length => (uint)Write().Length;
11 | public uint Order => 14;
12 |
13 | ///
14 | /// List of DoodadFilenames.
15 | ///
16 | public List DoodadFilenames = new List();
17 |
18 | public void Read(byte[] inData) { }
19 |
20 | public byte[] Write()
21 | {
22 | using (var stream = new MemoryStream())
23 | using (var writer = new BinaryWriter(stream))
24 | {
25 | // O(n^2), really don't care at this point.
26 | foreach (var filename in DoodadFilenames)
27 | foreach (var fileChar in filename)
28 | writer.Write(fileChar);
29 |
30 | return stream.ToArray();
31 | }
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/MultiConverter.Lib/Converters/WMO/Chunks/MODS.cs:
--------------------------------------------------------------------------------
1 | using MultiConverter.Lib.Converters.Base;
2 | using MultiConverter.Lib.Converters.WMO.Entries;
3 | using System;
4 | using System.Collections.Generic;
5 | using System.IO;
6 | using System.Text;
7 |
8 | namespace MultiConverter.Lib.Converters.WMO.Chunks
9 | {
10 | public class MODS : IChunk
11 | {
12 | public string Signature => "MODS";
13 | public uint Length => (uint)Write().Length;
14 | public uint Order => 13;
15 |
16 | ///
17 | /// List of
18 | ///
19 | public List MODSs = new List();
20 |
21 | public void Read(byte[] inData)
22 | {
23 | using (var stream = new MemoryStream(inData))
24 | using (var reader = new BinaryReader(stream))
25 | {
26 | var modsSize = inData.Length / 32;
27 | for (var i = 0; i < modsSize; ++i)
28 | {
29 | var mods = new MODSEntry
30 | {
31 | SetName = new string(reader.ReadChars(20)),
32 | FirstDoodadInSet = reader.ReadUInt32(),
33 | DoodadInSetCount = reader.ReadUInt32(),
34 | Padding = reader.ReadUInt32()
35 | };
36 |
37 | if (WMOFile.DisableDoodads)
38 | mods.DoodadInSetCount = 0;
39 |
40 | MODSs.Add(mods);
41 | }
42 | }
43 | }
44 |
45 | public byte[] Write()
46 | {
47 | using (var stream = new MemoryStream())
48 | using (var writer = new BinaryWriter(stream))
49 | {
50 | foreach (var mods in MODSs)
51 | {
52 | for (var i = 0; i < 20; ++i)
53 | writer.Write(mods.SetName[i]);
54 |
55 | writer.Write(mods.FirstDoodadInSet);
56 | writer.Write(mods.DoodadInSetCount);
57 | writer.Write(mods.Padding);
58 | }
59 |
60 | return stream.ToArray();
61 | }
62 | }
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/MultiConverter.Lib/Converters/WMO/Chunks/MOGI.cs:
--------------------------------------------------------------------------------
1 | using MultiConverter.Lib.Converters.Base;
2 | using MultiConverter.Lib.Converters.WMO.Entries;
3 | using System.Collections.Generic;
4 | using System.IO;
5 |
6 | namespace MultiConverter.Lib.Converters.WMO.Chunks
7 | {
8 | public class MOGI : IChunk
9 | {
10 | public string Signature => "MOGI";
11 | public uint Length => (uint)Write().Length;
12 | public uint Order => 5;
13 |
14 | ///
15 | /// List of
16 | ///
17 | public List MOGIs = new List();
18 |
19 | public void Read(byte[] inData)
20 | {
21 | using (var stream = new MemoryStream(inData))
22 | using (var reader = new BinaryReader(stream))
23 | {
24 | var mogiSize = inData.Length / 32;
25 | for (var i = 0; i < mogiSize; ++i)
26 | {
27 | var mogi = new MOGIEntry();
28 | mogi.Flags = reader.ReadUInt32();
29 | mogi.Flags &= 0x7FFFFF7F;
30 |
31 | for (var j = 0; j < 3; ++j)
32 | mogi.BBoxCorner1[j] = reader.ReadSingle();
33 |
34 | for (var j = 0; j < 3; ++j)
35 | mogi.BBoxCorner2[j] = reader.ReadSingle();
36 |
37 | mogi.NameOffset = reader.ReadInt32();
38 |
39 | MOGIs.Add(mogi);
40 | }
41 | }
42 | }
43 |
44 | public byte[] Write()
45 | {
46 | using (var stream = new MemoryStream())
47 | using (var writer = new BinaryWriter(stream))
48 | {
49 | foreach (var mogi in MOGIs)
50 | {
51 | writer.Write(mogi.Flags);
52 |
53 | for (var i = 0; i < 3; ++i)
54 | writer.Write(mogi.BBoxCorner1[i]);
55 |
56 | for (var i = 0; i < 3; ++i)
57 | writer.Write(mogi.BBoxCorner2[i]);
58 |
59 | writer.Write(mogi.NameOffset);
60 | }
61 |
62 | return stream.ToArray();
63 | }
64 | }
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/MultiConverter.Lib/Converters/WMO/Chunks/MOGN.cs:
--------------------------------------------------------------------------------
1 | using MultiConverter.Lib.Converters.Base;
2 | using System.IO;
3 |
4 | namespace MultiConverter.Lib.Converters.WMO.Chunks
5 | {
6 | public class MOGN : IChunk
7 | {
8 | public string Signature => "MOGN";
9 | public uint Length => (uint)Write().Length;
10 | public uint Order => 4;
11 |
12 | ///
13 | /// Group Names
14 | ///
15 | public byte[] GroupNames { get; set; }
16 |
17 | public void Read(byte[] inData)
18 | {
19 | using (var stream = new MemoryStream(inData))
20 | using (var reader = new BinaryReader(stream))
21 | {
22 | GroupNames = reader.ReadBytes(inData.Length);
23 | }
24 | }
25 |
26 | public byte[] Write()
27 | {
28 | using (var stream = new MemoryStream())
29 | using (var writer = new BinaryWriter(stream))
30 | {
31 | writer.Write(GroupNames, 0, GroupNames.Length);
32 |
33 | return stream.ToArray();
34 | }
35 | }
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/MultiConverter.Lib/Converters/WMO/Chunks/MOHD.cs:
--------------------------------------------------------------------------------
1 | using MultiConverter.Lib.Converters.Base;
2 | using MultiConverter.Lib.Converters.WMO.Entries;
3 | using MultiConverter.Lib.Util;
4 | using System.IO;
5 |
6 | namespace MultiConverter.Lib.Converters.WMO.Chunks
7 | {
8 | public class MOHD : IChunk
9 | {
10 | public string Signature => "MOHD";
11 | public uint Length => (uint)Write().Length;
12 | public uint Order => 1;
13 |
14 | public MOHDEntry MOHDEntry { get; set; } = new MOHDEntry();
15 |
16 | public void Read(byte[] inData)
17 | {
18 | using (var stream = new MemoryStream(inData))
19 | using (var reader = new BinaryReader(stream))
20 | {
21 | MOHDEntry.MaterialCount = reader.ReadUInt32();
22 | MOHDEntry.GroupCount = reader.ReadUInt32();
23 | MOHDEntry.PortalCount = reader.ReadUInt32();
24 | MOHDEntry.LightCount = reader.ReadUInt32();
25 | MOHDEntry.ModelCount = reader.ReadUInt32();
26 | MOHDEntry.DoodadCount = reader.ReadUInt32();
27 | MOHDEntry.SetCount = reader.ReadUInt32();
28 |
29 | MOHDEntry.Color = reader.ReadCArgb();
30 | MOHDEntry.WMOId = reader.ReadUInt32();
31 |
32 | for (var i = 0; i < 3; ++i)
33 | MOHDEntry.BBoxCorner1[i] = reader.ReadSingle();
34 |
35 | for (var i = 0; i < 3; ++i)
36 | MOHDEntry.BBoxCorner2[i] = reader.ReadSingle();
37 |
38 | MOHDEntry.FlagLod = reader.ReadUInt16();
39 | MOHDEntry.LodCount = reader.ReadUInt16();
40 |
41 | if (WMOFile.DisableDoodads)
42 | {
43 | MOHDEntry.DoodadCount = 0;
44 | MOHDEntry.ModelCount = 0;
45 | }
46 | }
47 | }
48 |
49 | public byte[] Write()
50 | {
51 | using (var stream = new MemoryStream())
52 | using (var writer = new BinaryWriter(stream))
53 | {
54 | writer.Write(MOHDEntry.MaterialCount);
55 | writer.Write(MOHDEntry.GroupCount);
56 | writer.Write(MOHDEntry.PortalCount);
57 | writer.Write(MOHDEntry.LightCount);
58 | writer.Write(MOHDEntry.ModelCount);
59 | writer.Write(MOHDEntry.DoodadCount);
60 | writer.Write(MOHDEntry.SetCount);
61 |
62 | writer.WriteCArgb(MOHDEntry.Color);
63 | writer.Write(MOHDEntry.WMOId);
64 |
65 | for (var i = 0; i < 3; ++i)
66 | writer.Write(MOHDEntry.BBoxCorner1[i]);
67 |
68 | for (var i = 0; i < 3; ++i)
69 | writer.Write(MOHDEntry.BBoxCorner2[i]);
70 |
71 | writer.Write(MOHDEntry.FlagLod);
72 | writer.Write(MOHDEntry.LodCount);
73 |
74 | return stream.ToArray();
75 | }
76 | }
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/MultiConverter.Lib/Converters/WMO/Chunks/MOLT.cs:
--------------------------------------------------------------------------------
1 | using MultiConverter.Lib.Converters.Base;
2 | using MultiConverter.Lib.Converters.WMO.Entries;
3 | using MultiConverter.Lib.Util;
4 | using System;
5 | using System.Collections.Generic;
6 | using System.IO;
7 | using System.Text;
8 |
9 | namespace MultiConverter.Lib.Converters.WMO.Chunks
10 | {
11 | public class MOLT : IChunk
12 | {
13 | public string Signature => "MOLT";
14 | public uint Length => (uint)Write().Length;
15 | public uint Order => 12;
16 |
17 | ///
18 | /// List of .
19 | ///
20 | public List MOLTs = new List();
21 |
22 | public void Read(byte[] inData)
23 | {
24 | using (var stream = new MemoryStream(inData))
25 | using (var reader = new BinaryReader(stream))
26 | {
27 | var moltSize = inData.Length / 48;
28 | for (var i = 0; i < moltSize; ++i)
29 | {
30 | var molt = new MOLTEntry();
31 | molt.Type = reader.ReadByte();
32 |
33 | for (var j = 0; j < 3; ++j)
34 | molt.Flags[j] = reader.ReadByte();
35 |
36 | molt.Color = reader.ReadCArgb();
37 | molt.Position = reader.ReadC3Vector();
38 | molt.Intensity = reader.ReadSingle();
39 |
40 | for (var j = 0; j < 4; ++j)
41 | molt.UnkShit[j] = reader.ReadSingle();
42 |
43 | molt.AttenStart = reader.ReadSingle();
44 | molt.AttenEnd = reader.ReadSingle();
45 | }
46 | }
47 | }
48 |
49 | public byte[] Write()
50 | {
51 | using (var stream = new MemoryStream())
52 | using (var writer = new BinaryWriter(stream))
53 | {
54 | foreach (var molt in MOLTs)
55 | {
56 | writer.Write(molt.Type);
57 | writer.Write(molt.Flags);
58 | writer.WriteCArgb(molt.Color);
59 | writer.WriteC3Vector(molt.Position);
60 | writer.Write(molt.Intensity);
61 |
62 | for (var j = 0; j < 4; ++j)
63 | writer.Write(molt.UnkShit[j]);
64 |
65 | writer.Write(molt.AttenStart);
66 | writer.Write(molt.AttenEnd);
67 | }
68 |
69 | return stream.ToArray();
70 | }
71 | }
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/MultiConverter.Lib/Converters/WMO/Chunks/MOMT.cs:
--------------------------------------------------------------------------------
1 | using MultiConverter.Lib.Converters.Base;
2 | using MultiConverter.Lib.Converters.WMO.Entries;
3 | using MultiConverter.Lib.Util;
4 | using System.Collections.Generic;
5 | using System.IO;
6 | using System.Linq;
7 |
8 | namespace MultiConverter.Lib.Converters.WMO.Chunks
9 | {
10 | public class MOMT : IChunk
11 | {
12 | public string Signature => "MOMT";
13 | public uint Length => (uint)Write().Length;
14 | public uint Order => 3;
15 |
16 | ///
17 | /// List of all filenames
18 | ///
19 | public Dictionary Filenames = new Dictionary();
20 |
21 | ///
22 | /// List of
23 | ///
24 | public List MOMTs = new List();
25 |
26 | private uint textureOffset = 0;
27 |
28 | public void Read(byte[] inData)
29 | {
30 | using (var stream = new MemoryStream(inData))
31 | using (var reader = new BinaryReader(stream))
32 | {
33 | var momtSize = inData.Length / 64;
34 |
35 | for (var i = 0; i < momtSize; ++i)
36 | {
37 | var momt = new MOMTEntry
38 | {
39 | Flags1 = reader.ReadUInt32(),
40 | ShaderType = reader.ReadUInt32(),
41 | BlendMode = reader.ReadUInt32(),
42 | TextureId1 = reader.ReadUInt32(),
43 | SidnColor = reader.ReadCArgb(),
44 | FrameSidnColor = reader.ReadCArgb(),
45 | TextureId2 = reader.ReadUInt32(),
46 | DiffColor = reader.ReadCArgb(),
47 | GroundType = reader.ReadUInt32(),
48 | TextureId3 = reader.ReadUInt32(),
49 | Color = reader.ReadCArgb(),
50 | Flags2 = reader.ReadUInt32()
51 | };
52 |
53 | momt.Flags1 &= 0xFF;
54 |
55 | for (var j = 0; j < 4; ++j)
56 | momt.RunTimeData[j] = reader.ReadUInt32();
57 |
58 | var filename = AddFilename(momt.TextureId1);
59 | if (filename != string.Empty)
60 | {
61 | var idx = Filenames[filename];
62 | momt.TextureId1 = idx;
63 | }
64 | else
65 | momt.TextureId1 = 0;
66 |
67 | filename = AddFilename(momt.TextureId2);
68 | if (filename != string.Empty)
69 | {
70 | var idx = Filenames[filename];
71 | momt.TextureId2 = idx;
72 | }
73 | else
74 | momt.TextureId2 = 0;
75 |
76 | filename = AddFilename(momt.TextureId3);
77 | if (filename != string.Empty)
78 | {
79 | var idx = Filenames[filename];
80 | momt.TextureId3 = idx;
81 | }
82 | else
83 | momt.TextureId3 = 0;
84 |
85 | switch (momt.ShaderType)
86 | {
87 | case 13:
88 | case 14:
89 | case 15:
90 | case 16:
91 | case 7: momt.ShaderType = 6; break;
92 | case 9: momt.ShaderType = 0; break;
93 | case 12: momt.ShaderType = 5; break;
94 | default:
95 | if (momt.ShaderType >= 13)
96 | momt.ShaderType = 4;
97 | break;
98 | }
99 |
100 | MOMTs.Add(momt);
101 | }
102 | }
103 |
104 | var motx = new MOTX { Filenames = Filenames.Keys.ToList() };
105 | WMOFile.Chunks.Add(motx);
106 | }
107 |
108 | public byte[] Write()
109 | {
110 | using (var stream = new MemoryStream())
111 | using (var writer = new BinaryWriter(stream))
112 | {
113 | foreach (var momt in MOMTs)
114 | {
115 | writer.Write(momt.Flags1);
116 | writer.Write(momt.ShaderType);
117 | writer.Write(momt.BlendMode);
118 | writer.Write(momt.TextureId1);
119 | writer.WriteCArgb(momt.SidnColor);
120 | writer.WriteCArgb(momt.FrameSidnColor);
121 | writer.Write(momt.TextureId2);
122 | writer.WriteCArgb(momt.DiffColor);
123 | writer.Write(momt.GroundType);
124 | writer.Write(momt.TextureId3);
125 | writer.WriteCArgb(momt.Color);
126 | writer.Write(momt.Flags2);
127 |
128 | for (var i = 0; i < 4; i++)
129 | writer.Write(momt.RunTimeData[i]);
130 | }
131 |
132 | return stream.ToArray();
133 | }
134 | }
135 |
136 | private string AddFilename(uint fdid)
137 | {
138 | if (fdid != 0)
139 | {
140 | var textureFilename = Listfile.LookupFilename(fdid, ".wmo").Replace('/', '\\') + "\0";
141 |
142 | if (!Filenames.ContainsKey(textureFilename))
143 | {
144 | Filenames.Add(textureFilename, textureOffset);
145 | textureOffset += (uint)textureFilename.Length;
146 | }
147 |
148 | return textureFilename;
149 | }
150 |
151 | return string.Empty;
152 | }
153 | }
154 | }
155 |
--------------------------------------------------------------------------------
/MultiConverter.Lib/Converters/WMO/Chunks/MOPR.cs:
--------------------------------------------------------------------------------
1 | using MultiConverter.Lib.Converters.Base;
2 | using MultiConverter.Lib.Converters.WMO.Entries;
3 | using System;
4 | using System.Collections.Generic;
5 | using System.IO;
6 | using System.Text;
7 |
8 | namespace MultiConverter.Lib.Converters.WMO.Chunks
9 | {
10 | public class MOPR : IChunk
11 | {
12 | public string Signature => "MOPR";
13 | public uint Length => (uint)Write().Length;
14 | public uint Order => 9;
15 |
16 | ///
17 | /// List of .
18 | ///
19 | public List MOPRs = new List();
20 |
21 | public void Read(byte[] inData)
22 | {
23 | using (var stream = new MemoryStream(inData))
24 | using (var reader = new BinaryReader(stream))
25 | {
26 | var moprSize = inData.Length / 8;
27 | for (var i = 0; i < moprSize; ++i)
28 | {
29 | MOPRs.Add(new MOPREntry
30 | {
31 | PortalIndex = reader.ReadUInt16(),
32 | WMOGroupIndex = reader.ReadUInt16(),
33 | Direction = reader.ReadInt16(),
34 | AlwaysZero = reader.ReadUInt16(),
35 | });
36 | }
37 | }
38 | }
39 |
40 | public byte[] Write()
41 | {
42 | using (var stream = new MemoryStream())
43 | using (var writer = new BinaryWriter(stream))
44 | {
45 | foreach (var mopr in MOPRs)
46 | {
47 | writer.Write(mopr.PortalIndex);
48 | writer.Write(mopr.WMOGroupIndex);
49 | writer.Write(mopr.Direction);
50 | writer.Write(mopr.AlwaysZero);
51 | }
52 |
53 | return stream.ToArray();
54 | }
55 | }
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/MultiConverter.Lib/Converters/WMO/Chunks/MOPT.cs:
--------------------------------------------------------------------------------
1 | using MultiConverter.Lib.Converters.Base;
2 | using MultiConverter.Lib.Converters.WMO.Entries;
3 | using MultiConverter.Lib.Util;
4 | using System;
5 | using System.Collections.Generic;
6 | using System.IO;
7 | using System.Text;
8 |
9 | namespace MultiConverter.Lib.Converters.WMO.Chunks
10 | {
11 | public class MOPT : IChunk
12 | {
13 | public string Signature => "MOPT";
14 | public uint Length => (uint)Write().Length;
15 | public uint Order => 8;
16 |
17 | ///
18 | /// A list of .
19 | ///
20 | public List MOPTs = new List();
21 |
22 | public void Read(byte[] inData)
23 | {
24 | using (var stream = new MemoryStream(inData))
25 | using (var reader = new BinaryReader(stream))
26 | {
27 | var moptSize = inData.Length / 20;
28 | for (var i = 0; i < moptSize; ++i)
29 | {
30 | var mopt = new MOPTEntry
31 | {
32 | StartVertex = reader.ReadUInt16(),
33 | Count = reader.ReadUInt16(),
34 | Plane = reader.ReadC4Plane()
35 | };
36 |
37 | MOPTs.Add(mopt);
38 | }
39 | }
40 | }
41 |
42 | public byte[] Write()
43 | {
44 | using (var stream = new MemoryStream())
45 | using (var writer = new BinaryWriter(stream))
46 | {
47 | foreach (var mopt in MOPTs)
48 | {
49 | writer.Write(mopt.StartVertex);
50 | writer.Write(mopt.Count);
51 | writer.WriteC4Plane(mopt.Plane);
52 | }
53 |
54 | return stream.ToArray();
55 | }
56 | }
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/MultiConverter.Lib/Converters/WMO/Chunks/MOPV.cs:
--------------------------------------------------------------------------------
1 | using MultiConverter.Lib.Converters.Base;
2 | using MultiConverter.Lib.Converters.WMO.Entries;
3 | using System;
4 | using System.Collections.Generic;
5 | using System.IO;
6 | using System.Text;
7 |
8 | namespace MultiConverter.Lib.Converters.WMO.Chunks
9 | {
10 | public class MOPV : IChunk
11 | {
12 | public string Signature => "MOPV";
13 | public uint Length => (uint)Write().Length;
14 | public uint Order => 7;
15 |
16 | ///
17 | /// List of .
18 | ///
19 | public List MOPVs = new List();
20 |
21 | public void Read(byte[] inData)
22 | {
23 | using (var stream = new MemoryStream(inData))
24 | using (var reader = new BinaryReader(stream))
25 | {
26 | var mopvSize = inData.Length / 48;
27 | for (var i = 0; i < mopvSize; ++i)
28 | {
29 | var mopv = new MOPVEntry();
30 |
31 | for (var j = 0; j < 3; ++j)
32 | mopv.Corner1[j] = reader.ReadSingle();
33 |
34 | for (var j = 0; j < 3; ++j)
35 | mopv.Corner2[j] = reader.ReadSingle();
36 |
37 | for (var j = 0; j < 3; ++j)
38 | mopv.Corner3[j] = reader.ReadSingle();
39 |
40 | for (var j = 0; j < 3; ++j)
41 | mopv.Corner4[j] = reader.ReadSingle();
42 |
43 | MOPVs.Add(mopv);
44 | }
45 | }
46 | }
47 |
48 | public byte[] Write()
49 | {
50 | using (var stream = new MemoryStream())
51 | using (var writer = new BinaryWriter(stream))
52 | {
53 | foreach (var mopv in MOPVs)
54 | {
55 | for (var j = 0; j < 3; ++j)
56 | writer.Write(mopv.Corner1[j]);
57 |
58 | for (var j = 0; j < 3; ++j)
59 | writer.Write(mopv.Corner2[j]);
60 |
61 | for (var j = 0; j < 3; ++j)
62 | writer.Write(mopv.Corner3[j]);
63 |
64 | for (var j = 0; j < 3; ++j)
65 | writer.Write(mopv.Corner4[j]);
66 | }
67 |
68 | return stream.ToArray();
69 | }
70 | }
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/MultiConverter.Lib/Converters/WMO/Chunks/MOSB.cs:
--------------------------------------------------------------------------------
1 | using MultiConverter.Lib.Converters.Base;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.IO;
5 | using System.Text;
6 |
7 | namespace MultiConverter.Lib.Converters.WMO.Chunks
8 | {
9 | public class MOSB : IChunk
10 | {
11 | public string Signature => "MOSB";
12 | public uint Length => (uint)Write().Length;
13 | public uint Order => 6;
14 |
15 | ///
16 | /// Originaly the skybox filename.
17 | ///
18 | public uint Padding { get; set; }
19 |
20 | public void Read(byte[] inData)
21 | {
22 | using (var stream = new MemoryStream(inData))
23 | using (var reader = new BinaryReader(stream))
24 | {
25 | Padding = reader.ReadUInt32();
26 | }
27 | }
28 |
29 | public byte[] Write()
30 | {
31 | using (var stream = new MemoryStream())
32 | using (var writer = new BinaryWriter(stream))
33 | {
34 | writer.Write(Padding);
35 |
36 | return stream.ToArray();
37 | }
38 | }
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/MultiConverter.Lib/Converters/WMO/Chunks/MOTX.cs:
--------------------------------------------------------------------------------
1 | using MultiConverter.Lib.Converters.Base;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.IO;
5 |
6 | namespace MultiConverter.Lib.Converters.WMO.Chunks
7 | {
8 | public class MOTX : IChunk
9 | {
10 | public string Signature => "MOTX";
11 | public uint Length => (uint)Write().Length;
12 | public uint Order => 2;
13 |
14 | public List Filenames = new List();
15 |
16 | public void Read(byte[] inData)
17 | {
18 | using (var stream = new MemoryStream(inData))
19 | using (var reader = new BinaryReader(stream))
20 | {
21 | throw new Exception("I am pleb, come back later");
22 | }
23 | }
24 |
25 | public byte[] Write()
26 | {
27 | using (var stream = new MemoryStream())
28 | using (var writer = new BinaryWriter(stream))
29 | {
30 | // O(n^2), really don't care at this point.
31 | foreach (var filename in Filenames)
32 | foreach (var fileChar in filename)
33 | writer.Write(fileChar);
34 |
35 | return stream.ToArray();
36 | }
37 | }
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/MultiConverter.Lib/Converters/WMO/Chunks/MOVB.cs:
--------------------------------------------------------------------------------
1 | using MultiConverter.Lib.Converters.Base;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Text;
5 |
6 | namespace MultiConverter.Lib.Converters.WMO.Chunks
7 | {
8 | public class MOVB : IChunk
9 | {
10 | public string Signature => "MOVB";
11 | public uint Length => (uint)Write().Length;
12 | public uint Order => 11;
13 |
14 | public void Read(byte[] inData) { }
15 |
16 | public byte[] Write() => new byte[0];
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/MultiConverter.Lib/Converters/WMO/Chunks/MOVV.cs:
--------------------------------------------------------------------------------
1 | using MultiConverter.Lib.Converters.Base;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.IO;
5 | using System.Text;
6 |
7 | namespace MultiConverter.Lib.Converters.WMO.Chunks
8 | {
9 | public class MOVV : IChunk
10 | {
11 | public string Signature => "MOVV";
12 | public uint Length => (uint)Write().Length;
13 | public uint Order => 10;
14 |
15 | public void Read(byte[] inData) { }
16 |
17 | public byte[] Write() => new byte[0];
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/MultiConverter.Lib/Converters/WMO/Chunks/MVER.cs:
--------------------------------------------------------------------------------
1 | using MultiConverter.Lib.Converters.Base;
2 | using System.IO;
3 |
4 | namespace MultiConverter.Lib.Converters.WMO.Chunks
5 | {
6 | public class MVER : IChunk
7 | {
8 | public string Signature => "MVER";
9 | public uint Length => (uint)Write().Length;
10 | public uint Order => 0;
11 |
12 | ///
13 | /// The Version of .
14 | ///
15 | public uint Version { get; set; }
16 |
17 | public void Read(byte[] inData)
18 | {
19 | using (var stream = new MemoryStream(inData))
20 | using (var reader = new BinaryReader(stream))
21 | {
22 | Version = reader.ReadUInt32();
23 | }
24 | }
25 |
26 | public byte[] Write()
27 | {
28 | using (var stream = new MemoryStream())
29 | using (var writer = new BinaryWriter(stream))
30 | {
31 | writer.Write(Version);
32 |
33 | return stream.ToArray();
34 | }
35 | }
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/MultiConverter.Lib/Converters/WMO/Entries/MFOGEntry.cs:
--------------------------------------------------------------------------------
1 | using MultiConverter.Lib.Common;
2 |
3 | namespace MultiConverter.Lib.Converters.WMO.Entries
4 | {
5 | public class MFOGEntry
6 | {
7 | public uint Flags { get; set; }
8 | public C3Vector Position { get; set; }
9 | public float SmallRadius { get; set; }
10 | public float LargeRadius { get; set; }
11 | public float FogEnd { get; set; }
12 | public float FogStartMultiplier { get; set; }
13 | public CArgb FogColor { get; set; }
14 | public float Unk1 { get; set; }
15 | public float Unk2 { get; set; }
16 | public CArgb FogColor2 { get; set; }
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/MultiConverter.Lib/Converters/WMO/Entries/MODDEntry.cs:
--------------------------------------------------------------------------------
1 | using MultiConverter.Lib.Common;
2 |
3 | namespace MultiConverter.Lib.Converters.WMO.Entries
4 | {
5 | public class MODDEntry
6 | {
7 | public int NameIndex { get; set; }
8 | public byte Flags { get; set; }
9 | public C3Vector Position { get; set; }
10 | public C3Vector Rotation { get; set; }
11 | public float RotationW { get; set; }
12 | public float Scale { get; set; }
13 | public CArgb Color { get; set; }
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/MultiConverter.Lib/Converters/WMO/Entries/MODSEntry.cs:
--------------------------------------------------------------------------------
1 | namespace MultiConverter.Lib.Converters.WMO.Entries
2 | {
3 | public class MODSEntry
4 | {
5 | public string SetName { get; set; }
6 | public uint FirstDoodadInSet { get; set; }
7 | public uint DoodadInSetCount { get; set; }
8 | public uint Padding { get; set; }
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/MultiConverter.Lib/Converters/WMO/Entries/MOGIEntry.cs:
--------------------------------------------------------------------------------
1 | namespace MultiConverter.Lib.Converters.WMO.Entries
2 | {
3 | public class MOGIEntry
4 | {
5 | public uint Flags { get; set; }
6 | public float[] BBoxCorner1 { get; set; } = new float[3];
7 | public float[] BBoxCorner2 { get; set; } = new float[3];
8 | public int NameOffset { get; set; }
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/MultiConverter.Lib/Converters/WMO/Entries/MOHDEntry.cs:
--------------------------------------------------------------------------------
1 | using MultiConverter.Lib.Common;
2 |
3 | namespace MultiConverter.Lib.Converters.WMO.Entries
4 | {
5 | public class MOHDEntry
6 | {
7 | public uint MaterialCount { get; set; }
8 | public uint GroupCount { get; set; }
9 | public uint PortalCount { get; set; }
10 | public uint LightCount { get; set; }
11 | public uint ModelCount { get; set; }
12 | public uint DoodadCount { get; set; }
13 | public uint SetCount { get; set; }
14 | public CArgb Color { get; set; }
15 | public uint WMOId { get; set; }
16 | public float[] BBoxCorner1 { get; set; } = new float[3];
17 | public float[] BBoxCorner2 { get; set; } = new float[3];
18 | public ushort FlagLod { get; set; }
19 | public ushort LodCount { get; set; }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/MultiConverter.Lib/Converters/WMO/Entries/MOLTEntry.cs:
--------------------------------------------------------------------------------
1 | using MultiConverter.Lib.Common;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Text;
5 |
6 | namespace MultiConverter.Lib.Converters.WMO.Entries
7 | {
8 | public class MOLTEntry
9 | {
10 | public byte Type { get; set; }
11 | public byte[] Flags { get; set; } = new byte[3];
12 | public CArgb Color { get; set; }
13 | public C3Vector Position { get; set; }
14 | public float Intensity { get; set; }
15 | public float[] UnkShit { get; set; } = new float[4];
16 | public float AttenStart { get; set; }
17 | public float AttenEnd { get; set; }
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/MultiConverter.Lib/Converters/WMO/Entries/MOMTEntry.cs:
--------------------------------------------------------------------------------
1 | using MultiConverter.Lib.Common;
2 |
3 | namespace MultiConverter.Lib.Converters.WMO.Entries
4 | {
5 | public class MOMTEntry
6 | {
7 | public uint Flags1 { get; set; }
8 | public uint ShaderType { get; set; }
9 | public uint BlendMode { get; set; }
10 | public uint TextureId1 { get; set; }
11 | public CArgb SidnColor { get; set; }
12 | public CArgb FrameSidnColor { get; set; }
13 | public uint TextureId2 { get; set; }
14 | public CArgb DiffColor { get; set; }
15 | public uint GroundType { get; set; }
16 | public uint TextureId3 { get; set; }
17 | public CArgb Color { get; set; }
18 | public uint Flags2 { get; set; }
19 | public uint[] RunTimeData { get; set; } = new uint[4];
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/MultiConverter.Lib/Converters/WMO/Entries/MOPREntry.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text;
4 |
5 | namespace MultiConverter.Lib.Converters.WMO.Entries
6 | {
7 | public class MOPREntry
8 | {
9 | public ushort PortalIndex { get; set; }
10 | public ushort WMOGroupIndex { get; set; }
11 | public short Direction { get; set; }
12 | public ushort AlwaysZero { get; set; }
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/MultiConverter.Lib/Converters/WMO/Entries/MOPTEntry.cs:
--------------------------------------------------------------------------------
1 | using MultiConverter.Lib.Common;
2 |
3 | namespace MultiConverter.Lib.Converters.WMO.Entries
4 | {
5 | public class MOPTEntry
6 | {
7 | public ushort StartVertex { get; set; }
8 | public ushort Count { get; set; }
9 | public C4Plane Plane { get; set; }
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/MultiConverter.Lib/Converters/WMO/Entries/MOPVEntry.cs:
--------------------------------------------------------------------------------
1 | namespace MultiConverter.Lib.Converters.WMO.Entries
2 | {
3 | public class MOPVEntry
4 | {
5 | public float[] Corner1 { get; set; } = new float[3];
6 | public float[] Corner2 { get; set; } = new float[3];
7 | public float[] Corner3 { get; set; } = new float[3];
8 | public float[] Corner4 { get; set; } = new float[3];
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/MultiConverter.Lib/Converters/WMO/WMOFile.cs:
--------------------------------------------------------------------------------
1 | using MultiConverter.Lib.Converters.Base;
2 | using MultiConverter.Lib.Converters.WMO.Chunks;
3 | using System;
4 | using System.Collections.Generic;
5 | using System.IO;
6 | using System.Linq;
7 |
8 | namespace MultiConverter.Lib.Converters.WMO
9 | {
10 | public class WMOFile : IConverter
11 | {
12 | public static List Chunks = new List();
13 | public static bool DisableDoodads = true;
14 |
15 | public void Read(byte[] data)
16 | {
17 | // Clear chunks to prevent double data.
18 | Chunks.Clear();
19 |
20 | using (var stream = new MemoryStream(data))
21 | using (var reader = new BinaryReader(stream))
22 | {
23 | while (reader.BaseStream.Position < reader.BaseStream.Length)
24 | {
25 | var chunkId = (WMOChunkId)reader.ReadUInt32();
26 | var chunkSize = reader.ReadUInt32();
27 |
28 | var chunkData = new byte[chunkSize];
29 | Buffer.BlockCopy(stream.ToArray(), (int)reader.BaseStream.Position, chunkData, 0, (int)chunkSize);
30 |
31 | IChunk chunk = null;
32 | switch (chunkId)
33 | {
34 | case WMOChunkId.MVER: chunk = new MVER(); break;
35 | case WMOChunkId.MOHD: chunk = new MOHD(); break;
36 | case WMOChunkId.MOTX: chunk = new MOTX(); break;
37 | case WMOChunkId.MOMT: chunk = new MOMT(); break;
38 | case WMOChunkId.MOGN: chunk = new MOGN(); break;
39 | case WMOChunkId.MOGI: chunk = new MOGI(); break;
40 | case WMOChunkId.MOPV: chunk = new MOPV(); break;
41 | case WMOChunkId.MOPT: chunk = new MOPT(); break;
42 | case WMOChunkId.MOPR: chunk = new MOPR(); break;
43 | case WMOChunkId.MOLT: chunk = new MOLT(); break;
44 | case WMOChunkId.MODS: chunk = new MODS(); break;
45 | case WMOChunkId.MODI: chunk = new MODI(); break;
46 | case WMOChunkId.MODD: chunk = new MODD(); break;
47 | case WMOChunkId.MFOG: chunk = new MFOG(); break;
48 | default: Console.WriteLine($"Skipping {chunkId} (0x{(uint)chunkId:X})"); break;
49 | }
50 |
51 | if (chunk != null)
52 | {
53 | chunk.Read(chunkData);
54 | Chunks.Add(chunk);
55 | }
56 |
57 | reader.BaseStream.Position += chunkSize;
58 | }
59 |
60 | // Add mandatory chunks.
61 | Chunks.Add(new MOSB());
62 | Chunks.Add(new MOVV());
63 | Chunks.Add(new MOVB());
64 |
65 | // Close the streams so they can be written.
66 | reader.Close();
67 | stream.Close();
68 | }
69 | }
70 |
71 | public void Write(string filename)
72 | {
73 | Chunks = Chunks.OrderBy(x => x.Order).ToList();
74 |
75 | using (var stream = new MemoryStream())
76 | using (var writer = new BinaryWriter(stream))
77 | {
78 | foreach (var chunk in Chunks)
79 | {
80 | // Ignore this chunk because it does not have to be written
81 | if (chunk.Signature == "MODI")
82 | continue;
83 |
84 | var reversedSignature = chunk.Signature.Reverse().ToArray();
85 |
86 | foreach (var signatureChar in reversedSignature)
87 | writer.Write(signatureChar);
88 |
89 | writer.Write(chunk.Length);
90 | writer.Write(chunk.Write());
91 | }
92 |
93 | File.WriteAllBytes(filename, stream.ToArray());
94 | }
95 | }
96 | }
97 | }
98 |
--------------------------------------------------------------------------------
/MultiConverter.Lib/Converters/WMOGroupConverter.cs:
--------------------------------------------------------------------------------
1 | using MultiConverter.Lib.Converters.Base;
2 | using System;
3 |
4 | namespace MultiConverter.Lib.Converters
5 | {
6 | public enum GroupChunk
7 | {
8 | MOGP = 1297041232,
9 | MOPY = 1297043545,
10 | MOVI = 1297045065,
11 | MOVT = 1297045076,
12 | MONR = 1297043026,
13 | MOTV = 1297044566,
14 | MOBA = 1297039937,
15 | MOLR = 1297042514,
16 | MODR = 1297040466,
17 | MOBN = 1297039950,
18 | MOBR = 1297039954,
19 | MOCR = 1297039954,
20 | MOCV = 1297040214,
21 | MLIQ = 1296845137
22 | };
23 |
24 | public class WMOGroupConverter : ChunkedWowFile
25 | {
26 | private int posMOVT = 0;
27 | private bool wod;
28 |
29 | public WMOGroupConverter(string wmo, bool wod = false) : base(wmo)
30 | {
31 | this.wod = wod;
32 | }
33 |
34 | private bool FixWod()
35 | {
36 | int pos_moba = CheckChunk(0xC, GroupChunk.MOTV, false, false);
37 | FixMOBA(pos_moba);
38 |
39 | return true;
40 | }
41 |
42 | private bool FixLK()
43 | {
44 | int pos = 0xC, posMOBA = 0, posMLIQ = 0;
45 |
46 | uint flags = ReadUInt(0x1C);
47 | WriteUInt(0x1C, flags & 0x7FFFFFF);
48 |
49 | // MOPY pos
50 | pos = 0x58;
51 |
52 | // Mandatory chunks
53 | pos = CheckChunk(pos, GroupChunk.MOPY);
54 | pos = CheckChunk(pos, GroupChunk.MOVI); posMOVT = pos;
55 | pos = CheckChunk(pos, GroupChunk.MOVT);
56 | pos = CheckChunk(pos, GroupChunk.MONR);
57 | pos = CheckChunk(pos, GroupChunk.MOTV); posMOBA = pos;
58 | pos = CheckChunk(pos, GroupChunk.MOBA);
59 |
60 | // Optionnal chunks
61 | if ((flags & 0x200) != 0)
62 | {
63 | pos = CheckChunk(pos, GroupChunk.MOLR);
64 | }
65 | if ((flags & 0x800) != 0)
66 | {
67 | pos = CheckChunk(pos, GroupChunk.MODR);
68 | }
69 | if ((flags & 0x1) != 0)
70 | {
71 | int pos_mobn = FindChunk(pos, GroupChunk.MOBN);
72 | int pos_mobr = FindChunk(pos, GroupChunk.MOBR);
73 |
74 | if (pos_mobn == -1 && pos_mobr == -1)
75 | {
76 | // remove flag (fix client freezing)
77 | WriteInt(0x1C, (int)flags & ~0x1);
78 | }
79 | else
80 | {
81 | pos = CheckChunk(pos, GroupChunk.MOBN);
82 | pos = CheckChunk(pos, GroupChunk.MOBR);
83 | }
84 | }
85 | if ((flags & 0x4) != 0)
86 | {
87 | pos = CheckChunk(pos, GroupChunk.MOCV);
88 | }
89 | if ((flags & 0x1000) != 0)
90 | {
91 | posMLIQ = pos;
92 | pos = CheckChunk(pos, GroupChunk.MLIQ);
93 | }
94 | if ((flags & 0x2000000) != 0)
95 | {
96 | pos = CheckChunk(pos, GroupChunk.MOTV);
97 | }
98 | if ((flags & 0x1000000) != 0)
99 | {
100 | pos = CheckChunk(pos, GroupChunk.MOCV);
101 | }
102 |
103 | // Cleanup
104 | RemoveBytes(pos, Size() - pos);
105 |
106 | FixMOBA(posMOBA);
107 |
108 | int liquidID = ReadInt(0x48);
109 | if (liquidID > 181)
110 | {
111 | WriteInt(0x48, 5);
112 | }
113 |
114 | return true;
115 | }
116 |
117 | public bool Fix()
118 | {
119 | if (!Valid || Size() < 0x58 || !IsChunk(0xC, "MOGP"))
120 | {
121 | return false;
122 | }
123 |
124 | return wod ? FixWod() : FixLK();
125 | }
126 |
127 | private void FixMOBA(int pos)
128 | {
129 | int size = ReadInt(pos + 0x4);
130 | int n = size / 0x18;
131 | pos += 0x8;
132 |
133 |
134 |
135 | for (int i = 0; i < n; i++)
136 | {
137 | if ((Data[pos + 0x16] & 2) != 0)
138 | {
139 | Data[pos + 0x16] = 0;
140 | Data[pos + 0x17] = Data[pos + 0xA];
141 | FixMOBA_box(pos, ReadUShort(pos + 0x12), ReadUShort(pos + 0x14));
142 | }
143 | pos += 0x18;
144 | }
145 | }
146 |
147 | private void GetVerticeCoord(ushort id, out float x, out float y, out float z)
148 | {
149 | int pos = posMOVT + 0x8 + 0xC * id;
150 |
151 | x = ReadFloat(pos);
152 | y = ReadFloat(pos + 0x4);
153 | z = ReadFloat(pos + 0x8);
154 | }
155 |
156 | private void FixMOBA_box(int box, ushort start, ushort end)
157 | {
158 | float[] f = { float.MaxValue, float.MaxValue, float.MaxValue, float.MinValue, float.MinValue, float.MinValue };
159 |
160 | for (ushort i = start; i <= end; i++)
161 | {
162 | for (int k = 0; k < 3; ++k)
163 | {
164 | float x, y, z;
165 |
166 | GetVerticeCoord(i, out x, out y, out z);
167 |
168 | f[0] = Math.Min(x, f[0]);
169 | f[3] = Math.Max(x, f[3]);
170 |
171 | f[1] = Math.Min(y, f[1]);
172 | f[4] = Math.Max(y, f[4]);
173 |
174 | f[2] = Math.Min(z, f[2]);
175 | f[5] = Math.Max(z, f[5]);
176 | }
177 | }
178 |
179 | for (int i = 0; i < 6; i++)
180 | {
181 | WriteShort(box + 2 * i, (short)((i < 3 ? Math.Floor(f[i]) : Math.Ceiling(f[i]))));
182 | }
183 | }
184 |
185 | private int FindChunk(int pos, GroupChunk chunk)
186 | {
187 | int found = -1;
188 | for (int i = pos; i + 8 <= Size(); i += (ReadInt(i + 0x4) + 0x8))
189 | {
190 | if (ReadInt(i) == (int)chunk)
191 | {
192 | found = i;
193 | break;
194 | }
195 | }
196 |
197 | return found;
198 | }
199 |
200 |
201 | ///
202 | /// Check if the chunk is present, if not it'll be created with a size of 0 if create is true
203 | /// Additionnal chunks between the starting pos and the chunk will be deleted
204 | ///
205 | /// starting pos for the search
206 | /// magic value of the wanted chunk
207 | /// if this is set to true and the chunk isn't there it will create it empty
208 | /// the new pos after the chunk
209 | private int CheckChunk(int pos, GroupChunk chunk, bool create = true, bool delete = true)
210 | {
211 | int found = FindChunk(pos, chunk);
212 |
213 | if (found == -1 && create)
214 | {
215 | AddEmptyBytes(pos, 8);
216 | WriteInt(pos, (int)chunk);
217 | return pos + 0x8;
218 | }
219 | if (found > pos)
220 | {
221 | if (delete)
222 | {
223 | RemoveBytes(pos, found - pos);
224 | }
225 | else
226 | {
227 | pos = found;
228 | }
229 | }
230 |
231 | if (found != -1)
232 | {
233 | pos += ReadInt(pos + 0x4) + 0x8;
234 | }
235 |
236 | // return the current pos
237 | return pos;
238 | }
239 | }
240 | }
241 |
--------------------------------------------------------------------------------
/MultiConverter.Lib/MultiConverter.Lib.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netcoreapp3.1
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 | false
19 | false
20 |
21 |
22 |
23 | ..\bin\Debug\
24 |
25 |
26 | ..\bin\Release\
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/MultiConverter.Lib/Updater/Update.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Net;
3 |
4 | namespace MultiConverter.Lib.Updater
5 | {
6 | public class Update
7 | {
8 | public string VersionString { get; set; }
9 | public string DownloadUrl { get; set; }
10 | public string Changelog { get; set; }
11 |
12 | [NonSerialized]
13 | public WebClient WebClient;
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/MultiConverter.Lib/Updater/UpdateManager.cs:
--------------------------------------------------------------------------------
1 | using Newtonsoft.Json;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Diagnostics;
5 | using System.Net;
6 | using System.Text;
7 |
8 | namespace MultiConverter.Lib.Updater
9 | {
10 | public static class UpdateManager
11 | {
12 | public const string UpdateUrl = "https://raw.githubusercontent.com/MaxtorCoder/MultiConverter/master/update.json";
13 | public const string BetaUpdateUrl = "https://raw.githubusercontent.com/MaxtorCoder/MultiConverter/master/update_beta.json";
14 |
15 | public static (bool, string) HasUpdates(string versionString, bool hasBeta = false)
16 | {
17 | using (var webclient = new WebClient())
18 | {
19 | var reponseString = webclient.DownloadString(hasBeta ? BetaUpdateUrl : UpdateUrl);
20 |
21 | var update = JsonConvert.DeserializeObject(reponseString);
22 | if (update.VersionString == versionString)
23 | return (false, string.Empty);
24 |
25 | return (true, update.VersionString);
26 | }
27 | }
28 |
29 | public static string GetChangelog(bool hasBeta = false)
30 | {
31 | using (var webclient = new WebClient())
32 | {
33 | var reponseString = webclient.DownloadString(hasBeta ? BetaUpdateUrl : UpdateUrl);
34 |
35 | var update = JsonConvert.DeserializeObject(reponseString);
36 | return update.Changelog;
37 | }
38 | }
39 |
40 | public static void StartUpdater(bool hasBeta = false)
41 | {
42 | Process.Start("MultiConverter.Updater.exe", $"-b \"{(hasBeta ? true : false)}\"");
43 | }
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/MultiConverter.Lib/Util/Extensions.cs:
--------------------------------------------------------------------------------
1 | using MultiConverter.Lib.Common;
2 | using System;
3 | using System.IO;
4 | using System.Text;
5 |
6 | namespace MultiConverter.Lib.Util
7 | {
8 | public static class Extensions
9 | {
10 | public static CAaBox ReadCAaBox(this BinaryReader reader)
11 | {
12 | return new CAaBox
13 | {
14 | Min = reader.ReadC3Vector(),
15 | Max = reader.ReadC3Vector()
16 | };
17 | }
18 | public static void WriteCAaBox(this BinaryWriter writer, CAaBox box)
19 | {
20 | writer.WriteC3Vector(box.Min);
21 | writer.WriteC3Vector(box.Max);
22 | }
23 |
24 | public static CArgb ReadCArgb(this BinaryReader reader)
25 | {
26 | return new CArgb
27 | {
28 | R = reader.ReadByte(),
29 | G = reader.ReadByte(),
30 | B = reader.ReadByte(),
31 | A = reader.ReadByte(),
32 | };
33 | }
34 | public static void WriteCArgb(this BinaryWriter writer, CArgb color)
35 | {
36 | writer.Write(color.R);
37 | writer.Write(color.G);
38 | writer.Write(color.B);
39 | writer.Write(color.A);
40 | }
41 |
42 | public static C3Vector ReadC3Vector(this BinaryReader reader)
43 | {
44 | return new C3Vector
45 | {
46 | X = reader.ReadSingle(),
47 | Y = reader.ReadSingle(),
48 | Z = reader.ReadSingle(),
49 | };
50 | }
51 | public static void WriteC3Vector(this BinaryWriter writer, C3Vector vector)
52 | {
53 | writer.Write(vector.X);
54 | writer.Write(vector.Y);
55 | writer.Write(vector.Z);
56 | }
57 |
58 | public static C4Plane ReadC4Plane(this BinaryReader reader)
59 | {
60 | return new C4Plane
61 | {
62 | Normal = reader.ReadC3Vector(),
63 | Distance = reader.ReadSingle()
64 | };
65 | }
66 | public static void WriteC4Plane(this BinaryWriter writer, C4Plane plane)
67 | {
68 | writer.WriteC3Vector(plane.Normal);
69 | writer.Write(plane.Distance);
70 | }
71 |
72 | public static string ReadNullTerminatedString(this BinaryReader reader)
73 | {
74 | var sb = new StringBuilder();
75 | char c;
76 |
77 | while ((c = Convert.ToChar(reader.ReadByte())) != 0)
78 | sb.Append(c);
79 |
80 | return sb.ToString();
81 | }
82 | }
83 | }
84 |
--------------------------------------------------------------------------------
/MultiConverter.Lib/Util/Listfile.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Net;
5 |
6 | namespace MultiConverter.Lib
7 | {
8 | public static class Listfile
9 | {
10 | private static WebClient webClient = new WebClient();
11 | private static string buildConfig = "";
12 | private static string listfile = "listfile.csv";
13 | private static string listUrl = "https://wow.tools/casc/listfile/download/csv/unverified";
14 | private static Dictionary FiledataPair = new Dictionary();
15 |
16 | public static bool IsInitialized = false;
17 |
18 | public static void Initialize()
19 | {
20 | // Download listfile if file does not exist.
21 | if (!File.Exists(listfile))
22 | webClient.DownloadFile(listUrl, listfile);
23 | else
24 | {
25 | using (var reader = new StreamReader(listfile))
26 | {
27 | while (!reader.EndOfStream)
28 | {
29 | var line = reader.ReadLine();
30 | var array = line.Split(';');
31 |
32 | FiledataPair.Add(uint.Parse(array[0]), array[1]);
33 | }
34 |
35 | IsInitialized = true;
36 | }
37 | }
38 |
39 | // Check latest buildconfig.
40 | using (var stream = new MemoryStream(webClient.DownloadData("http://us.patch.battle.net:1119/wow_beta/versions")))
41 | using (var reader = new StreamReader(stream))
42 | {
43 | // Read useless lines.
44 | reader.ReadLine();
45 | reader.ReadLine();
46 |
47 | var line = reader.ReadLine();
48 | var array = line.Split('|');
49 |
50 | // second element of the array
51 | // us|3f483ee25f283e9072d1a9dceb0160c2|230ddf963c980e2d5ec9882c2a8a00ce||32861|8.3.0.32861|a96756c514489774e38ef1edbc17dcc5
52 | buildConfig = array[1];
53 | }
54 | }
55 |
56 | public static string LookupFilename(uint id, string extension, string downloadExtension = "blp")
57 | {
58 | // Lookup the Id in the listfile, if it does not exist
59 | // download and place in blp///
60 | if (FiledataPair.TryGetValue(id, out string filename))
61 | {
62 | Console.WriteLine($"Filename: {filename} (Length: {filename.Length} ID: {id})");
63 | return filename;
64 | }
65 | else
66 | {
67 | if (id != 0)
68 | {
69 | var newFilename = $"{id}.{downloadExtension}";
70 | var newExtension = extension.Remove(0, 1);
71 | var pathName = $"Unk/{downloadExtension}/{newExtension}/{newFilename}";
72 |
73 | if (!Directory.Exists($"Unk/{downloadExtension}"))
74 | Directory.CreateDirectory($"Unk/{downloadExtension}");
75 | if (!Directory.Exists($"Unk/{downloadExtension}/{newExtension}"))
76 | Directory.CreateDirectory($"Unk/{downloadExtension}/{newExtension}");
77 |
78 | if (File.Exists(pathName))
79 | {
80 | Console.WriteLine($"Filename: {pathName} (Length: {pathName.Length} ID: {id})");
81 | }
82 | else
83 | {
84 | Console.WriteLine($"Downloading: {newFilename} (Id: {id})");
85 | webClient.DownloadFile($"https://wow.tools/casc/file/fdid?buildconfig={buildConfig}&filename={newFilename}&filedataid={id}", pathName);
86 | }
87 |
88 | return pathName;
89 | }
90 | }
91 |
92 | return string.Empty;
93 | }
94 | }
95 | }
96 |
--------------------------------------------------------------------------------
/MultiConverter.Lib/Util/Utils.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.IO;
3 | using System.Text.RegularExpressions;
4 |
5 | namespace MultiConverter.Lib
6 | {
7 | public class Utils
8 | {
9 | public static bool IsCorrectFile(string s)
10 | {
11 | return s.EndsWith(".m2", StringComparison.OrdinalIgnoreCase)
12 | || s.EndsWith(".anim", StringComparison.OrdinalIgnoreCase)
13 | || s.EndsWith(".wmo", StringComparison.OrdinalIgnoreCase)
14 | || s.EndsWith(".adt", StringComparison.OrdinalIgnoreCase)
15 | || s.EndsWith(".wdt", StringComparison.OrdinalIgnoreCase)
16 | || s.EndsWith(".skin", StringComparison.OrdinalIgnoreCase);
17 | }
18 |
19 | public static bool IsChunk(ref byte[] buff, int pos, int magic)
20 | {
21 | return BitConverter.ToInt32(buff, pos) == magic;
22 | }
23 |
24 | public static void CopyInt(ref byte[] buff, int pos, int value)
25 | {
26 | Buffer.BlockCopy(BitConverter.GetBytes(value), 0, buff, pos, 4);
27 | }
28 |
29 | public static void RemoveBytes(ref byte[] buff, int start, int count)
30 | {
31 | int size = buff.Length;
32 |
33 | if (size <= start + count || count <= 0)
34 | {
35 | return;
36 | }
37 |
38 | byte[] tmp = new byte[size - count];
39 | if (start > 0)
40 | {
41 | Buffer.BlockCopy(buff, 0, tmp, 0, start);
42 | }
43 | Buffer.BlockCopy(buff, start + count, tmp, start, size - count - start);
44 | buff = tmp;
45 | }
46 |
47 | public static void AddEmptyBytes(ref byte[] buff, int start, int count)
48 | {
49 | int size = buff.Length;
50 | byte[] tmp = new byte[size + count];
51 | Buffer.BlockCopy(buff, 0, tmp, 0, start);
52 | Buffer.BlockCopy(buff, start, tmp, start + count, size - start);
53 | buff = tmp;
54 | }
55 |
56 | public static void InsertBytes(ref byte[] buff, int start, byte[] bytes)
57 | {
58 | AddEmptyBytes(ref buff, start, bytes.Length);
59 | Buffer.BlockCopy(bytes, 0, buff, start, bytes.Length);
60 | }
61 |
62 | public static void RemoveUnwantedChunks(ref byte[] tab, int start, int magic)
63 | {
64 | if (tab.Length < start + 9)
65 | {
66 | return;
67 | }
68 |
69 | int header = BitConverter.ToInt32(tab, start);
70 | int end = start;
71 | // check to prevent out of bound exception
72 | while (header != magic && tab.Length > end + 8)
73 | {
74 | if (header < 1291845632)
75 | {
76 | end += 0x4;
77 | }
78 | else
79 | {
80 | end += BitConverter.ToInt32(tab, start + 0x4) + 0x8;
81 | }
82 | if (tab.Length < end + 4)
83 | {
84 | break;
85 | }
86 | header = BitConverter.ToInt32(tab, end);
87 | }
88 | RemoveBytes(ref tab, start, end - start);
89 | }
90 |
91 | public static void DeleteFile(string path)
92 | {
93 | if (File.Exists(path))
94 | {
95 | File.Delete(path);
96 | }
97 | }
98 | }
99 | }
100 |
--------------------------------------------------------------------------------
/MultiConverter.Updater/MainForm.Designer.cs:
--------------------------------------------------------------------------------
1 | namespace MultiConverter.Updater
2 | {
3 | partial class MainForm
4 | {
5 | ///
6 | /// Required designer variable.
7 | ///
8 | private System.ComponentModel.IContainer components = null;
9 |
10 | ///
11 | /// Clean up any resources being used.
12 | ///
13 | /// true if managed resources should be disposed; otherwise, false.
14 | protected override void Dispose(bool disposing)
15 | {
16 | if (disposing && (components != null))
17 | {
18 | components.Dispose();
19 | }
20 | base.Dispose(disposing);
21 | }
22 |
23 | #region Windows Form Designer generated code
24 |
25 | ///
26 | /// Required method for Designer support - do not modify
27 | /// the contents of this method with the code editor.
28 | ///
29 | private void InitializeComponent()
30 | {
31 | this.boxChangelog = new System.Windows.Forms.RichTextBox();
32 | this.label1 = new System.Windows.Forms.Label();
33 | this.boxStatus = new System.Windows.Forms.RichTextBox();
34 | this.progressBar = new System.Windows.Forms.ProgressBar();
35 | this.SuspendLayout();
36 | //
37 | // boxChangelog
38 | //
39 | this.boxChangelog.Location = new System.Drawing.Point(12, 27);
40 | this.boxChangelog.Name = "boxChangelog";
41 | this.boxChangelog.ReadOnly = true;
42 | this.boxChangelog.Size = new System.Drawing.Size(268, 411);
43 | this.boxChangelog.TabIndex = 0;
44 | this.boxChangelog.Text = "";
45 | //
46 | // label1
47 | //
48 | this.label1.AutoSize = true;
49 | this.label1.Location = new System.Drawing.Point(12, 5);
50 | this.label1.Name = "label1";
51 | this.label1.Size = new System.Drawing.Size(68, 15);
52 | this.label1.TabIndex = 1;
53 | this.label1.Text = "Changelog:";
54 | //
55 | // boxStatus
56 | //
57 | this.boxStatus.Location = new System.Drawing.Point(286, 27);
58 | this.boxStatus.Name = "boxStatus";
59 | this.boxStatus.ReadOnly = true;
60 | this.boxStatus.Size = new System.Drawing.Size(435, 382);
61 | this.boxStatus.TabIndex = 2;
62 | this.boxStatus.Text = "";
63 | //
64 | // progressBar
65 | //
66 | this.progressBar.Location = new System.Drawing.Point(286, 415);
67 | this.progressBar.Name = "progressBar";
68 | this.progressBar.Size = new System.Drawing.Size(435, 23);
69 | this.progressBar.TabIndex = 3;
70 | //
71 | // MainForm
72 | //
73 | this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F);
74 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
75 | this.ClientSize = new System.Drawing.Size(728, 450);
76 | this.Controls.Add(this.progressBar);
77 | this.Controls.Add(this.boxStatus);
78 | this.Controls.Add(this.label1);
79 | this.Controls.Add(this.boxChangelog);
80 | this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedToolWindow;
81 | this.MaximizeBox = false;
82 | this.MinimizeBox = false;
83 | this.Name = "MainForm";
84 | this.Text = "MultiConverter - Updater";
85 | this.ResumeLayout(false);
86 | this.PerformLayout();
87 |
88 | }
89 |
90 | #endregion
91 |
92 | private System.Windows.Forms.RichTextBox boxChangelog;
93 | private System.Windows.Forms.Label label1;
94 | private System.Windows.Forms.RichTextBox boxStatus;
95 | private System.Windows.Forms.ProgressBar progressBar;
96 | }
97 | }
98 |
99 |
--------------------------------------------------------------------------------
/MultiConverter.Updater/MainForm.cs:
--------------------------------------------------------------------------------
1 | using MultiConverter.Updater.Updater;
2 | using Newtonsoft.Json;
3 | using System;
4 | using System.ComponentModel;
5 | using System.Diagnostics;
6 | using System.IO;
7 | using System.IO.Compression;
8 | using System.Net;
9 | using System.Threading;
10 | using System.Windows.Forms;
11 |
12 | namespace MultiConverter.Updater
13 | {
14 | public partial class MainForm : Form
15 | {
16 | private bool hasBeta = false;
17 | private BackgroundWorker updateWorker;
18 |
19 | public MainForm(string[] args)
20 | {
21 | InitializeComponent();
22 |
23 | // for (var i = 0; i < args.Length; ++i)
24 | // {
25 | // if (args[i] == "-b")
26 | // hasBeta = bool.Parse(args[++i]);
27 | // }
28 |
29 | boxChangelog.Text = UpdateManager.GetChangelog(hasBeta);
30 | DownloadUpdate();
31 | }
32 |
33 | private void DownloadUpdate()
34 | {
35 | updateWorker = new BackgroundWorker();
36 | updateWorker.WorkerReportsProgress = true;
37 | updateWorker.DoWork += UpdateWorker_DoWork;
38 | updateWorker.ProgressChanged += UpdateWorker_ProgressChanged;
39 | updateWorker.RunWorkerCompleted += UpdateWorker_RunWorkerCompleted;
40 |
41 | using (var webClient = new WebClient())
42 | {
43 | var reponseString = webClient.DownloadString(hasBeta ? UpdateManager.BetaUpdateUrl : UpdateManager.UpdateUrl);
44 | var update = JsonConvert.DeserializeObject(reponseString);
45 |
46 | update.WebClient = webClient;
47 |
48 | updateWorker.RunWorkerAsync(update);
49 | }
50 | }
51 |
52 | private void UpdateWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
53 | {
54 | Thread.Sleep(5000);
55 | Process.Start("MultiConverter.GUI.exe");
56 | Close();
57 | }
58 |
59 | private void UpdateWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
60 | {
61 | progressBar.Value = e.ProgressPercentage;
62 | boxStatus.AppendText($"[{DateTime.Now}] {e.UserState}\n");
63 | }
64 |
65 | private void UpdateWorker_DoWork(object sender, DoWorkEventArgs e)
66 | {
67 | // Let it load for a minute..
68 | Thread.Sleep(2000);
69 |
70 | var update = e.Argument as Update;
71 |
72 | updateWorker.ReportProgress(0, "Downloading update...");
73 |
74 | // https://github.com/MaxtorCoder/MultiConverter/releases/download/3.6.1/MultiConverter3.6.1.rar
75 | update.WebClient.DownloadFile($"{update.DownloadUrl}/{update.VersionString}/MultiConverter{update.VersionString}", "update.zip");
76 |
77 | updateWorker.ReportProgress(45, "Downloaded update.. Extracting update..");
78 |
79 | var zip = new ZipArchive(File.OpenRead("update.zip"));
80 |
81 | var currentIdx = 0;
82 | foreach (var file in zip.Entries)
83 | {
84 | updateWorker.ReportProgress(45 + (++currentIdx), $"Extracting file: {file.FullName}");
85 |
86 | File.Delete(file.FullName);
87 | using (var stream = file.Open())
88 | {
89 | var data = new byte[file.Length];
90 | stream.Read(data, 0, (int)file.Length);
91 |
92 | File.WriteAllBytes(file.FullName, data);
93 | }
94 | }
95 |
96 | zip.Dispose();
97 | File.Delete("update.zip");
98 |
99 | updateWorker.ReportProgress(100, "Done extracting update.. Closing this in 5 seconds!");
100 | }
101 | }
102 | }
103 |
--------------------------------------------------------------------------------
/MultiConverter.Updater/MainForm.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 | text/microsoft-resx
50 |
51 |
52 | 2.0
53 |
54 |
55 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
56 |
57 |
58 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
59 |
60 |
--------------------------------------------------------------------------------
/MultiConverter.Updater/MultiConverter.Updater.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | WinExe
5 | netcoreapp3.1
6 | true
7 |
8 |
9 |
10 | false
11 | false
12 |
13 |
14 |
15 | ..\bin\Debug\
16 |
17 |
18 | ..\bin\Release\
19 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/MultiConverter.Updater/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Threading.Tasks;
5 | using System.Windows.Forms;
6 |
7 | namespace MultiConverter.Updater
8 | {
9 | static class Program
10 | {
11 | ///
12 | /// The main entry point for the application.
13 | ///
14 | [STAThread]
15 | static void Main(string[] args)
16 | {
17 | Application.SetHighDpiMode(HighDpiMode.SystemAware);
18 | Application.EnableVisualStyles();
19 | Application.SetCompatibleTextRenderingDefault(false);
20 | Application.Run(new MainForm(args));
21 | }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/MultiConverter.Updater/Updater/Update.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Net;
3 |
4 | namespace MultiConverter.Updater.Updater
5 | {
6 | public class Update
7 | {
8 | public string VersionString { get; set; }
9 | public string DownloadUrl { get; set; }
10 | public string Changelog { get; set; }
11 |
12 | [NonSerialized]
13 | public WebClient WebClient;
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/MultiConverter.Updater/Updater/UpdateManager.cs:
--------------------------------------------------------------------------------
1 | using Newtonsoft.Json;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Diagnostics;
5 | using System.Net;
6 | using System.Text;
7 |
8 | namespace MultiConverter.Updater.Updater
9 | {
10 | public static class UpdateManager
11 | {
12 | public const string UpdateUrl = "https://raw.githubusercontent.com/MaxtorCoder/MultiConverter/master/update.json";
13 | public const string BetaUpdateUrl = "https://raw.githubusercontent.com/MaxtorCoder/MultiConverter/master/update_beta.json";
14 |
15 | public static (bool, string) HasUpdates(string versionString, bool hasBeta = false)
16 | {
17 | using (var webclient = new WebClient())
18 | {
19 | var reponseString = webclient.DownloadString(hasBeta ? BetaUpdateUrl : UpdateUrl);
20 |
21 | var update = JsonConvert.DeserializeObject(reponseString);
22 | if (update.VersionString == versionString)
23 | return (false, string.Empty);
24 |
25 | return (true, update.VersionString);
26 | }
27 | }
28 |
29 | public static string GetChangelog(bool hasBeta = false)
30 | {
31 | using (var webclient = new WebClient())
32 | {
33 | var reponseString = webclient.DownloadString(hasBeta ? BetaUpdateUrl : UpdateUrl);
34 |
35 | var update = JsonConvert.DeserializeObject(reponseString);
36 | return update.Changelog;
37 | }
38 | }
39 |
40 | public static void StartUpdater(bool hasBeta = false)
41 | {
42 | Process.Start("MultiConverter.Updater.exe", $"-b \"{(hasBeta ? true : false)}\"");
43 | }
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/MultiConverter.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 16
4 | VisualStudioVersion = 16.0.30014.187
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MultiConverter.GUI", "MultiConverter.GUI\MultiConverter.GUI.csproj", "{D338BB83-9455-4328-825E-4FD8A72F4B67}"
7 | EndProject
8 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MultiConverter.Lib", "MultiConverter.Lib\MultiConverter.Lib.csproj", "{00D3B1F6-46F1-4505-8E90-97B83DC436B6}"
9 | EndProject
10 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MultiConverter.Updater", "MultiConverter.Updater\MultiConverter.Updater.csproj", "{FF8E2C84-435D-468F-8958-A465588F8981}"
11 | EndProject
12 | Global
13 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
14 | Debug|Any CPU = Debug|Any CPU
15 | Release|Any CPU = Release|Any CPU
16 | EndGlobalSection
17 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
18 | {D338BB83-9455-4328-825E-4FD8A72F4B67}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
19 | {D338BB83-9455-4328-825E-4FD8A72F4B67}.Debug|Any CPU.Build.0 = Debug|Any CPU
20 | {D338BB83-9455-4328-825E-4FD8A72F4B67}.Release|Any CPU.ActiveCfg = Release|Any CPU
21 | {D338BB83-9455-4328-825E-4FD8A72F4B67}.Release|Any CPU.Build.0 = Release|Any CPU
22 | {00D3B1F6-46F1-4505-8E90-97B83DC436B6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
23 | {00D3B1F6-46F1-4505-8E90-97B83DC436B6}.Debug|Any CPU.Build.0 = Debug|Any CPU
24 | {00D3B1F6-46F1-4505-8E90-97B83DC436B6}.Release|Any CPU.ActiveCfg = Release|Any CPU
25 | {00D3B1F6-46F1-4505-8E90-97B83DC436B6}.Release|Any CPU.Build.0 = Release|Any CPU
26 | {FF8E2C84-435D-468F-8958-A465588F8981}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
27 | {FF8E2C84-435D-468F-8958-A465588F8981}.Debug|Any CPU.Build.0 = Debug|Any CPU
28 | {FF8E2C84-435D-468F-8958-A465588F8981}.Release|Any CPU.ActiveCfg = Release|Any CPU
29 | {FF8E2C84-435D-468F-8958-A465588F8981}.Release|Any CPU.Build.0 = Release|Any CPU
30 | EndGlobalSection
31 | GlobalSection(SolutionProperties) = preSolution
32 | HideSolutionNode = FALSE
33 | EndGlobalSection
34 | GlobalSection(ExtensibilityGlobals) = postSolution
35 | SolutionGuid = {0D3C26A0-0518-4F3B-98F8-A5C1B1B2CC18}
36 | EndGlobalSection
37 | EndGlobal
38 |
--------------------------------------------------------------------------------
/README.MD:
--------------------------------------------------------------------------------
1 | # Multiconverter - WoW 3.3.5a
2 | ## Information
3 | Originally written by [Adspartan](https://github.com/Adspartan "Adspartan's Github")
4 |
5 | ## Support
6 | For support please go to the Discord linked at the bottom, and go to the #support channel. 😄
7 |
8 | ## How To
9 | To use it just open it then drag and drop the files you want to convert (or a folder containing some, subfolder included) and click on "Fix", the files will be overwritten and it will delete the files that are unused on wotlk.
10 | If the .skin files are in the same folder they will be converted too.
11 |
12 | ## Requirements
13 | * Visual Studio 2019 (.NET Core 3.1)
14 |
15 | ## File Support
16 | | Format | BFA (Above 26629)| Shadowlands |
17 | |:--------:|:----------------:|:-----------:|
18 | | M2 | ✔️ |✔️ |
19 | | WMO | ✔️ |❌ |
20 | | ADT | ❌ |❌ |
21 | | WDT | ❌ |❌ |
22 |
23 | ## To-Do
24 | * Animation particles
25 | * Set WMOs liquid types that correspond when the ID is too high
26 | * Set fel liquid to green lava on adt for a better / more accurate look
27 | * ADT BFA support
28 | * WDT BFA support
29 |
30 | ## Links
31 | - [Discord](https://discord.gg/vcpwDVN)
32 | - [Model Changing](https://model-changing.net/)
33 |
--------------------------------------------------------------------------------
/update.json:
--------------------------------------------------------------------------------
1 | {"VersionString": "3.6.2.0","DownloadUrl": "https://github.com/MaxtorCoder/MultiConverter/releases/download/","Changelog": ""}
--------------------------------------------------------------------------------
/update_beta.json:
--------------------------------------------------------------------------------
1 | {"VersionString": "3.6.2.0","DownloadUrl": "https://github.com/MaxtorCoder/MultiConverter/releases/download/","Changelog": ""}
--------------------------------------------------------------------------------