Skip to content

Commit 0a27270

Browse files
committed
Update 2.3.1.6
2 parents 77058fb + 04ad415 commit 0a27270

File tree

3 files changed

+123
-41
lines changed

3 files changed

+123
-41
lines changed

xivModdingFramework/Materials/FileTypes/Mtrl.cs

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1116,7 +1116,62 @@ public string GetMtrlFolder(XivDependencyRootInfo root, int materialSet = -1)
11161116

11171117
}
11181118

1119+
/// <summary>
1120+
/// Hair is extremely annoying and uses literal hard-coded paths for things based on hair ID.
1121+
/// </summary>
1122+
/// <param name="root"></param>
1123+
/// <returns></returns>
1124+
public static XivDependencyRootInfo GetHairMaterialRoot(XivDependencyRootInfo root)
1125+
{
1126+
if(root.PrimaryType != XivItemType.human || root.SecondaryType != XivItemType.hair)
1127+
{
1128+
throw new InvalidDataException("Cannot get hair material info for non-hair root.");
1129+
}
11191130

1131+
if(root.SecondaryId < 101)
1132+
{
1133+
// Racial uniques.
1134+
return root;
1135+
} else if (root.SecondaryId < 116)
1136+
{
1137+
// 101-115 have Midlander M/F, and Miqo M/F
1138+
if (root.PrimaryId == 701 || root.PrimaryId == 801)
1139+
{
1140+
return root;
1141+
}
1142+
else
1143+
{
1144+
var isFemale = ((root.PrimaryId / 100) % 2) == 0;
1145+
return new XivDependencyRootInfo()
1146+
{
1147+
PrimaryId = isFemale ? 201 : 101,
1148+
PrimaryType = root.PrimaryType,
1149+
SecondaryType = root.SecondaryType,
1150+
SecondaryId = root.SecondaryId,
1151+
Slot = root.Slot
1152+
};
1153+
}
1154+
1155+
} else if (root.SecondaryId < 201)
1156+
{
1157+
// These have just Midlander M/F
1158+
var isFemale = ((root.PrimaryId / 100) % 2) == 0;
1159+
return new XivDependencyRootInfo()
1160+
{
1161+
PrimaryId = isFemale ? 201 : 101,
1162+
PrimaryType = root.PrimaryType,
1163+
SecondaryType = root.SecondaryType,
1164+
SecondaryId = root.SecondaryId,
1165+
Slot = root.Slot
1166+
};
1167+
1168+
} else
1169+
{
1170+
// Back to uniques.
1171+
return root;
1172+
}
1173+
1174+
}
11201175
public void Dipose()
11211176
{
11221177
_semaphoreSlim?.Dispose();

xivModdingFramework/Models/DataContainers/EquipmentParameter.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,7 @@ public enum EquipmentParameterFlag
183183
BodyHideGorget = 7,
184184

185185
// Byte 1 - Body
186-
BodyShowLeg = 8, // When turned off, Leg hiding data is resolved from this same set, rather than the set of the equipped piece.
186+
BodyShowLeg = 8, // When turned off, Leg hiding data is resolved from this same set, rather than the set of the equipped piece.
187187
BodyShowHand = 9, // When turned off, Hand hiding data is resolved from this same set, rather than the set of the equipped piece.
188188
BodyShowHead = 10, // When turned off, Head hiding data is resolved from this same set, rather than the set of the equipped piece.
189189
BodyShowNecklace = 11,
@@ -194,9 +194,9 @@ public enum EquipmentParameterFlag
194194

195195
// Byte 2 - Leg
196196
EnableLegFlags = 16,
197-
Bit17 = 17,
198-
LegHideShortBoot = 18,
199-
LegHideHalfBoot = 19,
197+
LegHideKneePads = 17, // atr_lpd
198+
LegHideShortBoot = 18, // atr_leg
199+
LegHideHalfBoot = 19, // atr_leg
200200
Bit20 = 20,
201201
LegShowFoot = 21,
202202
Bit22 = 22,

xivModdingFramework/Mods/RootCloner.cs

Lines changed: 64 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
using System.Text.RegularExpressions;
88
using System.Threading.Tasks;
99
using xivModdingFramework.Cache;
10+
using xivModdingFramework.General.Enums;
1011
using xivModdingFramework.Helpers;
1112
using xivModdingFramework.Items.Enums;
1213
using xivModdingFramework.Materials.FileTypes;
@@ -30,7 +31,7 @@ public static class RootCloner
3031
/// <param name="Destination">Destination root to copy to.</param>
3132
/// <param name="ApplicationSource">Application to list as the source for the resulting mod entries.</param>
3233
/// <returns></returns>
33-
public static async Task CloneRoot(XivDependencyRoot Source, XivDependencyRoot Destination, string ApplicationSource, int singleVariant = -1, IProgress<string> ProgressReporter = null)
34+
public static async Task CloneRoot(XivDependencyRoot Source, XivDependencyRoot Destination, string ApplicationSource, int singleVariant = -1, string saveDirectory = null, IProgress<string> ProgressReporter = null)
3435
{
3536

3637
if (ProgressReporter != null)
@@ -408,8 +409,8 @@ public static async Task CloneRoot(XivDependencyRoot Source, XivDependencyRoot D
408409
modlist = await _modding.GetModListAsync();
409410

410411

411-
412-
var modPack = new ModPack() { author = "System", name = "Item Copy - " + srcItem.Name + " -> " + iName, url = "", version = "1.0" };
412+
var modPack = new ModPack() { author = "System", name = "Item Copy - " + srcItem.Name + " to " + iName, url = "", version = "1.0" };
413+
List<Mod> mods = new List<Mod>();
413414
foreach (var mod in modlist.Mods)
414415
{
415416
if (allFiles.Contains(mod.fullPath))
@@ -419,6 +420,8 @@ public static async Task CloneRoot(XivDependencyRoot Source, XivDependencyRoot D
419420
mod.category = iCat;
420421
mod.source = ApplicationSource;
421422
mod.modPack = modPack;
423+
424+
mods.Add(mod);
422425
}
423426
}
424427

@@ -427,6 +430,43 @@ public static async Task CloneRoot(XivDependencyRoot Source, XivDependencyRoot D
427430

428431
_modding.SaveModList(modlist);
429432

433+
if(saveDirectory != null)
434+
{
435+
436+
ProgressReporter.Report("Creating TTMP File...");
437+
var desc = "Item Converter Modpack - " + srcItem.Name + " -> " + iName + "\nCreated at: " + DateTime.Now.ToString();
438+
// Time to save the modlist to file.
439+
var dir = new DirectoryInfo(saveDirectory);
440+
var _ttmp = new TTMP(dir, ApplicationSource);
441+
var smpd = new SimpleModPackData()
442+
{
443+
Author = modPack.author,
444+
Description = desc,
445+
Url = modPack.url,
446+
Version = new Version(1, 0, 0),
447+
Name = modPack.name,
448+
SimpleModDataList = new List<SimpleModData>()
449+
};
450+
451+
foreach(var mod in mods)
452+
{
453+
var size = await _dat.GetCompressedFileSize(mod.data.modOffset, df);
454+
var smd = new SimpleModData()
455+
{
456+
Name = iName,
457+
FullPath = mod.fullPath,
458+
DatFile = df.GetDataFileName(),
459+
Category = iCat,
460+
IsDefault = false,
461+
ModSize = size,
462+
ModOffset = mod.data.modOffset
463+
};
464+
smpd.SimpleModDataList.Add(smd);
465+
}
466+
467+
await _ttmp.CreateSimpleModPack(smpd, XivCache.GameInfo.GameDirectory, null, true);
468+
}
469+
430470
if (ProgressReporter != null)
431471
{
432472
ProgressReporter.Report("Root copy complete.");
@@ -463,25 +503,19 @@ private static string UpdateFolder(XivDependencyRoot Source, XivDependencyRoot D
463503
{
464504
if(Destination.Info.PrimaryType == XivItemType.human && Destination.Info.SecondaryType == XivItemType.hair && Path.GetExtension(path) == ".mtrl")
465505
{
466-
// Hair material paths are actually hard-coded into the game, so there's some wild stuff that has to go on here.
467-
if (Destination.Info.SecondaryId > 115 && Destination.Info.SecondaryId <= 200)
468-
{
469-
// Hairs between 115 and 200 have forced material path sharing enabled.
470-
var digit3 = Destination.Info.SecondaryId / 100;
471-
var race = digit3 % 2 == 0 ? 101 : 201;
506+
var hairRoot = Mtrl.GetHairMaterialRoot(Destination.Info);
472507

473-
// Force the race code to the appropriate one.
474-
var raceReplace = new Regex("/c[0-9]{4}");
475-
path = raceReplace.Replace(path, "/c" + race.ToString().PadLeft(4, '0'));
508+
// Force the race code to the appropriate one.
509+
var raceReplace = new Regex("/c[0-9]{4}");
510+
path = raceReplace.Replace(path, "/c" + hairRoot.PrimaryId.ToString().PadLeft(4, '0'));
476511

477-
var hairReplace= new Regex("/h[0-9]{4}");
478-
path = hairReplace.Replace(path, "/h" + Destination.Info.SecondaryId.ToString().PadLeft(4, '0'));
512+
var hairReplace= new Regex("/h[0-9]{4}");
513+
path = hairReplace.Replace(path, "/h" + hairRoot.SecondaryId.ToString().PadLeft(4, '0'));
479514

480-
// Hairs between 115 and 200 have forced material path sharing enabled.
481-
path = Path.GetDirectoryName(path);
482-
path = path.Replace('\\', '/');
483-
return path;
484-
}
515+
// Hairs between 115 and 200 have forced material path sharing enabled.
516+
path = Path.GetDirectoryName(path);
517+
path = path.Replace('\\', '/');
518+
return path;
485519
}
486520

487521
// So first off, just copy anything from the old root folder to the new one.
@@ -511,28 +545,21 @@ private static string UpdateFileName(XivDependencyRoot Source, XivDependencyRoot
511545

512546
if (Destination.Info.PrimaryType == XivItemType.human && Destination.Info.SecondaryType == XivItemType.hair && Path.GetExtension(path) == ".mtrl")
513547
{
514-
// Hair material paths are actually hard-coded into the game, so there's some wild stuff that has to go on here.
515-
if (Destination.Info.SecondaryId > 115 && Destination.Info.SecondaryId <= 200)
516-
{
517-
// Hairs between 115 and 200 have forced material path sharing enabled.
518-
var digit3 = Destination.Info.SecondaryId / 100;
519-
var race = digit3 % 2 == 0 ? 101 : 201;
548+
var hairRoot = Mtrl.GetHairMaterialRoot(Destination.Info);
520549

521-
// Force the race code to the appropriate one.
522-
var raceReplace = new Regex("^mt_c[0-9]{4}h[0-9]{4}");
523-
file = raceReplace.Replace(file, "mt_c" + race.ToString().PadLeft(4, '0') + "h" + Destination.Info.SecondaryId.ToString().PadLeft(4, '0'));
550+
// Force replace the root information to the correct one for this target hair.
551+
var raceReplace = new Regex("^mt_c[0-9]{4}h[0-9]{4}");
552+
file = raceReplace.Replace(file, "mt_c" + hairRoot.PrimaryId.ToString().PadLeft(4, '0') + "h" + hairRoot.SecondaryId.ToString().PadLeft(4, '0'));
524553

525-
// So for these, the first half of the filename is hard-coded locked (the c#### part)
526-
// We have to get gimmicky and play around with the suffixing.
527-
var initialPartRex = new Regex("^(mt_c[0-9]{4}h[0-9]{4})(?:_c[0-9]{4})?(.+)$");
528-
var m = initialPartRex.Match(file);
554+
// Jam in a suffix into the MTRL to make it unique/non-colliding.
555+
var initialPartRex = new Regex("^(mt_c[0-9]{4}h[0-9]{4})(?:_c[0-9]{4})?(.+)$");
556+
var m = initialPartRex.Match(file);
529557

530-
// ???
531-
if (!m.Success) return file;
558+
// ???
559+
if (!m.Success) return file;
532560

533-
file = m.Groups[1].Value + "_c" + Destination.Info.PrimaryId.ToString().PadLeft(4, '0') + m.Groups[2].Value;
534-
return file;
535-
}
561+
file = m.Groups[1].Value + "_c" + Destination.Info.PrimaryId.ToString().PadLeft(4, '0') + m.Groups[2].Value;
562+
return file;
536563
}
537564

538565
var rex = new Regex("[a-z][0-9]{4}([a-z][0-9]{4})");

0 commit comments

Comments
 (0)