mirror of
https://github.com/xivdev/Penumbra.git
synced 2025-12-12 10:17:22 +01:00
Make EQP swaps also swap multi-slot items correctly.
This commit is contained in:
parent
f89eab8b2b
commit
2be5bd0611
4 changed files with 93 additions and 57 deletions
|
|
@ -1 +1 @@
|
||||||
Subproject commit 4a987167b665184d4c05fc9863993981c35a1d19
|
Subproject commit f6dff467c7dad6b1213a7d7b65d40a56450f0672
|
||||||
|
|
@ -27,31 +27,31 @@ public static class EquipmentSwap
|
||||||
: [];
|
: [];
|
||||||
}
|
}
|
||||||
|
|
||||||
public static EquipItem[] CreateTypeSwap(MetaFileManager manager, ObjectIdentification identifier, List<Swap> swaps,
|
public static HashSet<EquipItem> CreateTypeSwap(MetaFileManager manager, ObjectIdentification identifier, List<Swap> swaps,
|
||||||
Func<Utf8GamePath, FullPath> redirections, MetaDictionary manips,
|
Func<Utf8GamePath, FullPath> redirections, MetaDictionary manips,
|
||||||
EquipSlot slotFrom, EquipItem itemFrom, EquipSlot slotTo, EquipItem itemTo)
|
EquipSlot slotFrom, EquipItem itemFrom, EquipSlot slotTo, EquipItem itemTo)
|
||||||
{
|
{
|
||||||
LookupItem(itemFrom, out var actualSlotFrom, out var idFrom, out var variantFrom);
|
LookupItem(itemFrom, out var actualSlotFrom, out var idFrom, out var variantFrom);
|
||||||
LookupItem(itemTo, out var actualSlotTo, out var idTo, out var variantTo);
|
LookupItem(itemTo, out var actualSlotTo, out var idTo, out var variantTo);
|
||||||
if (actualSlotFrom != slotFrom.ToSlot() || actualSlotTo != slotTo.ToSlot())
|
if (actualSlotFrom != slotFrom.ToSlot() || actualSlotTo != slotTo.ToSlot())
|
||||||
throw new ItemSwap.InvalidItemTypeException();
|
throw new ItemSwap.InvalidItemTypeException();
|
||||||
|
|
||||||
var (imcFileFrom, variants, affectedItems) = GetVariants(manager, identifier, slotFrom, idFrom, idTo, variantFrom);
|
var (imcFileFrom, variants, affectedItems) = GetVariants(manager, identifier, slotFrom, idFrom, idTo, variantFrom);
|
||||||
var imcIdentifierTo = new ImcIdentifier(slotTo, idTo, variantTo);
|
var imcIdentifierTo = new ImcIdentifier(slotTo, idTo, variantTo);
|
||||||
var imcFileTo = new ImcFile(manager, imcIdentifierTo);
|
var imcFileTo = new ImcFile(manager, imcIdentifierTo);
|
||||||
var imcEntry = manips.TryGetValue(imcIdentifierTo, out var entry)
|
var imcEntry = manips.TryGetValue(imcIdentifierTo, out var entry)
|
||||||
? entry
|
? entry
|
||||||
: imcFileTo.GetEntry(imcIdentifierTo.EquipSlot, imcIdentifierTo.Variant);
|
: imcFileTo.GetEntry(imcIdentifierTo.EquipSlot, imcIdentifierTo.Variant);
|
||||||
var mtrlVariantTo = imcEntry.MaterialId;
|
var mtrlVariantTo = imcEntry.MaterialId;
|
||||||
var skipFemale = false;
|
var skipFemale = false;
|
||||||
var skipMale = false;
|
var skipMale = false;
|
||||||
foreach (var gr in Enum.GetValues<GenderRace>())
|
foreach (var gr in Enum.GetValues<GenderRace>())
|
||||||
{
|
{
|
||||||
switch (gr.Split().Item1)
|
switch (gr.Split().Item1)
|
||||||
{
|
{
|
||||||
case Gender.Male when skipMale: continue;
|
case Gender.Male when skipMale: continue;
|
||||||
case Gender.Female when skipFemale: continue;
|
case Gender.Female when skipFemale: continue;
|
||||||
case Gender.MaleNpc when skipMale: continue;
|
case Gender.MaleNpc when skipMale: continue;
|
||||||
case Gender.FemaleNpc when skipFemale: continue;
|
case Gender.FemaleNpc when skipFemale: continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -88,30 +88,40 @@ public static class EquipmentSwap
|
||||||
return affectedItems;
|
return affectedItems;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static EquipItem[] CreateItemSwap(MetaFileManager manager, ObjectIdentification identifier, List<Swap> swaps,
|
public static HashSet<EquipItem> CreateItemSwap(MetaFileManager manager, ObjectIdentification identifier, List<Swap> swaps,
|
||||||
Func<Utf8GamePath, FullPath> redirections, MetaDictionary manips, EquipItem itemFrom,
|
Func<Utf8GamePath, FullPath> redirections, MetaDictionary manips, EquipItem itemFrom,
|
||||||
EquipItem itemTo, bool rFinger = true, bool lFinger = true)
|
EquipItem itemTo, bool rFinger = true, bool lFinger = true)
|
||||||
{
|
{
|
||||||
// Check actual ids, variants and slots. We only support using the same slot.
|
// Check actual ids, variants and slots. We only support using the same slot.
|
||||||
LookupItem(itemFrom, out var slotFrom, out var idFrom, out var variantFrom);
|
LookupItem(itemFrom, out var slotFrom, out var idFrom, out var variantFrom);
|
||||||
LookupItem(itemTo, out var slotTo, out var idTo, out var variantTo);
|
LookupItem(itemTo, out var slotTo, out var idTo, out var variantTo);
|
||||||
if (slotFrom != slotTo)
|
if (slotFrom != slotTo)
|
||||||
throw new ItemSwap.InvalidItemTypeException();
|
throw new ItemSwap.InvalidItemTypeException();
|
||||||
|
|
||||||
var eqp = CreateEqp(manager, manips, slotFrom, idFrom, idTo);
|
HashSet<EquipItem> affectedItems = [];
|
||||||
|
var eqp = CreateEqp(manager, manips, slotFrom, idFrom, idTo);
|
||||||
if (eqp != null)
|
if (eqp != null)
|
||||||
|
{
|
||||||
swaps.Add(eqp);
|
swaps.Add(eqp);
|
||||||
|
// Add items affected through multi-slot EQP edits.
|
||||||
|
foreach (var child in eqp.ChildSwaps.SelectMany(c => c.WithChildren()).OfType<MetaSwap<EqpIdentifier, EqpEntryInternal>>())
|
||||||
|
{
|
||||||
|
affectedItems.UnionWith(identifier
|
||||||
|
.Identify(GamePaths.Equipment.Mdl.Path(idFrom, GenderRace.MidlanderMale, child.SwapFromIdentifier.Slot))
|
||||||
|
.Select(kvp => kvp.Value).OfType<IdentifiedItem>().Select(i => i.Item));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var gmp = CreateGmp(manager, manips, slotFrom, idFrom, idTo);
|
var gmp = CreateGmp(manager, manips, slotFrom, idFrom, idTo);
|
||||||
if (gmp != null)
|
if (gmp != null)
|
||||||
swaps.Add(gmp);
|
swaps.Add(gmp);
|
||||||
|
|
||||||
var affectedItems = Array.Empty<EquipItem>();
|
|
||||||
foreach (var slot in ConvertSlots(slotFrom, rFinger, lFinger))
|
foreach (var slot in ConvertSlots(slotFrom, rFinger, lFinger))
|
||||||
{
|
{
|
||||||
(var imcFileFrom, var variants, affectedItems) = GetVariants(manager, identifier, slot, idFrom, idTo, variantFrom);
|
var (imcFileFrom, variants, affectedItemsLocal) = GetVariants(manager, identifier, slot, idFrom, idTo, variantFrom);
|
||||||
|
affectedItems.UnionWith(affectedItemsLocal);
|
||||||
var imcIdentifierTo = new ImcIdentifier(slotTo, idTo, variantTo);
|
var imcIdentifierTo = new ImcIdentifier(slotTo, idTo, variantTo);
|
||||||
var imcFileTo = new ImcFile(manager, imcIdentifierTo);
|
var imcFileTo = new ImcFile(manager, imcIdentifierTo);
|
||||||
var imcEntry = manips.TryGetValue(imcIdentifierTo, out var entry)
|
var imcEntry = manips.TryGetValue(imcIdentifierTo, out var entry)
|
||||||
? entry
|
? entry
|
||||||
: imcFileTo.GetEntry(imcIdentifierTo.EquipSlot, imcIdentifierTo.Variant);
|
: imcFileTo.GetEntry(imcIdentifierTo.EquipSlot, imcIdentifierTo.Variant);
|
||||||
|
|
@ -122,18 +132,18 @@ public static class EquipmentSwap
|
||||||
{
|
{
|
||||||
EquipSlot.Head => EstType.Head,
|
EquipSlot.Head => EstType.Head,
|
||||||
EquipSlot.Body => EstType.Body,
|
EquipSlot.Body => EstType.Body,
|
||||||
_ => (EstType)0,
|
_ => (EstType)0,
|
||||||
};
|
};
|
||||||
|
|
||||||
var skipFemale = false;
|
var skipFemale = false;
|
||||||
var skipMale = false;
|
var skipMale = false;
|
||||||
foreach (var gr in Enum.GetValues<GenderRace>())
|
foreach (var gr in Enum.GetValues<GenderRace>())
|
||||||
{
|
{
|
||||||
switch (gr.Split().Item1)
|
switch (gr.Split().Item1)
|
||||||
{
|
{
|
||||||
case Gender.Male when skipMale: continue;
|
case Gender.Male when skipMale: continue;
|
||||||
case Gender.Female when skipFemale: continue;
|
case Gender.Female when skipFemale: continue;
|
||||||
case Gender.MaleNpc when skipMale: continue;
|
case Gender.MaleNpc when skipMale: continue;
|
||||||
case Gender.FemaleNpc when skipFemale: continue;
|
case Gender.FemaleNpc when skipFemale: continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -148,7 +158,7 @@ public static class EquipmentSwap
|
||||||
swaps.Add(eqdp);
|
swaps.Add(eqdp);
|
||||||
|
|
||||||
var ownMdl = eqdp?.SwapToModdedEntry.Model ?? false;
|
var ownMdl = eqdp?.SwapToModdedEntry.Model ?? false;
|
||||||
var est = ItemSwap.CreateEst(manager, redirections, manips, estType, gr, idFrom, idTo, ownMdl);
|
var est = ItemSwap.CreateEst(manager, redirections, manips, estType, gr, idFrom, idTo, ownMdl);
|
||||||
if (est != null)
|
if (est != null)
|
||||||
swaps.Add(est);
|
swaps.Add(est);
|
||||||
}
|
}
|
||||||
|
|
@ -176,6 +186,7 @@ public static class EquipmentSwap
|
||||||
|
|
||||||
return affectedItems;
|
return affectedItems;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static MetaSwap<EqdpIdentifier, EqdpEntryInternal>? CreateEqdp(MetaFileManager manager, Func<Utf8GamePath, FullPath> redirections,
|
public static MetaSwap<EqdpIdentifier, EqdpEntryInternal>? CreateEqdp(MetaFileManager manager, Func<Utf8GamePath, FullPath> redirections,
|
||||||
MetaDictionary manips, EquipSlot slot, GenderRace gr, PrimaryId idFrom, PrimaryId idTo, byte mtrlTo)
|
MetaDictionary manips, EquipSlot slot, GenderRace gr, PrimaryId idFrom, PrimaryId idTo, byte mtrlTo)
|
||||||
=> CreateEqdp(manager, redirections, manips, slot, slot, gr, idFrom, idTo, mtrlTo);
|
=> CreateEqdp(manager, redirections, manips, slot, slot, gr, idFrom, idTo, mtrlTo);
|
||||||
|
|
@ -185,9 +196,9 @@ public static class EquipmentSwap
|
||||||
PrimaryId idTo, byte mtrlTo)
|
PrimaryId idTo, byte mtrlTo)
|
||||||
{
|
{
|
||||||
var eqdpFromIdentifier = new EqdpIdentifier(idFrom, slotFrom, gr);
|
var eqdpFromIdentifier = new EqdpIdentifier(idFrom, slotFrom, gr);
|
||||||
var eqdpToIdentifier = new EqdpIdentifier(idTo, slotTo, gr);
|
var eqdpToIdentifier = new EqdpIdentifier(idTo, slotTo, gr);
|
||||||
var eqdpFromDefault = new EqdpEntryInternal(ExpandedEqdpFile.GetDefault(manager, eqdpFromIdentifier), slotFrom);
|
var eqdpFromDefault = new EqdpEntryInternal(ExpandedEqdpFile.GetDefault(manager, eqdpFromIdentifier), slotFrom);
|
||||||
var eqdpToDefault = new EqdpEntryInternal(ExpandedEqdpFile.GetDefault(manager, eqdpToIdentifier), slotTo);
|
var eqdpToDefault = new EqdpEntryInternal(ExpandedEqdpFile.GetDefault(manager, eqdpToIdentifier), slotTo);
|
||||||
var meta = new MetaSwap<EqdpIdentifier, EqdpEntryInternal>(i => manips.TryGetValue(i, out var e) ? e : null, eqdpFromIdentifier,
|
var meta = new MetaSwap<EqdpIdentifier, EqdpEntryInternal>(i => manips.TryGetValue(i, out var e) ? e : null, eqdpFromIdentifier,
|
||||||
eqdpFromDefault, eqdpToIdentifier,
|
eqdpFromDefault, eqdpToIdentifier,
|
||||||
eqdpToDefault);
|
eqdpToDefault);
|
||||||
|
|
@ -216,7 +227,7 @@ public static class EquipmentSwap
|
||||||
? GamePaths.Accessory.Mdl.Path(idFrom, gr, slotFrom)
|
? GamePaths.Accessory.Mdl.Path(idFrom, gr, slotFrom)
|
||||||
: GamePaths.Equipment.Mdl.Path(idFrom, gr, slotFrom);
|
: GamePaths.Equipment.Mdl.Path(idFrom, gr, slotFrom);
|
||||||
var mdlPathTo = slotTo.IsAccessory() ? GamePaths.Accessory.Mdl.Path(idTo, gr, slotTo) : GamePaths.Equipment.Mdl.Path(idTo, gr, slotTo);
|
var mdlPathTo = slotTo.IsAccessory() ? GamePaths.Accessory.Mdl.Path(idTo, gr, slotTo) : GamePaths.Equipment.Mdl.Path(idTo, gr, slotTo);
|
||||||
var mdl = FileSwap.CreateSwap(manager, ResourceType.Mdl, redirections, mdlPathFrom, mdlPathTo);
|
var mdl = FileSwap.CreateSwap(manager, ResourceType.Mdl, redirections, mdlPathFrom, mdlPathTo);
|
||||||
|
|
||||||
foreach (ref var fileName in mdl.AsMdl()!.Materials.AsSpan())
|
foreach (ref var fileName in mdl.AsMdl()!.Materials.AsSpan())
|
||||||
{
|
{
|
||||||
|
|
@ -238,16 +249,17 @@ public static class EquipmentSwap
|
||||||
variant = i.Variant;
|
variant = i.Variant;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static (ImcFile, Variant[], EquipItem[]) GetVariants(MetaFileManager manager, ObjectIdentification identifier, EquipSlot slotFrom,
|
private static (ImcFile, Variant[], HashSet<EquipItem>) GetVariants(MetaFileManager manager, ObjectIdentification identifier,
|
||||||
|
EquipSlot slotFrom,
|
||||||
PrimaryId idFrom, PrimaryId idTo, Variant variantFrom)
|
PrimaryId idFrom, PrimaryId idTo, Variant variantFrom)
|
||||||
{
|
{
|
||||||
var ident = new ImcIdentifier(slotFrom, idFrom, variantFrom);
|
var ident = new ImcIdentifier(slotFrom, idFrom, variantFrom);
|
||||||
var imc = new ImcFile(manager, ident);
|
var imc = new ImcFile(manager, ident);
|
||||||
EquipItem[] items;
|
HashSet<EquipItem> items;
|
||||||
Variant[] variants;
|
Variant[] variants;
|
||||||
if (idFrom == idTo)
|
if (idFrom == idTo)
|
||||||
{
|
{
|
||||||
items = identifier.Identify(idFrom, 0, variantFrom, slotFrom).ToArray();
|
items = identifier.Identify(idFrom, 0, variantFrom, slotFrom).ToHashSet();
|
||||||
variants = [variantFrom];
|
variants = [variantFrom];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -256,7 +268,7 @@ public static class EquipmentSwap
|
||||||
? GamePaths.Equipment.Mdl.Path(idFrom, GenderRace.MidlanderMale, slotFrom)
|
? GamePaths.Equipment.Mdl.Path(idFrom, GenderRace.MidlanderMale, slotFrom)
|
||||||
: GamePaths.Accessory.Mdl.Path(idFrom, GenderRace.MidlanderMale, slotFrom))
|
: GamePaths.Accessory.Mdl.Path(idFrom, GenderRace.MidlanderMale, slotFrom))
|
||||||
.Select(kvp => kvp.Value).OfType<IdentifiedItem>().Select(i => i.Item)
|
.Select(kvp => kvp.Value).OfType<IdentifiedItem>().Select(i => i.Item)
|
||||||
.ToArray();
|
.ToHashSet();
|
||||||
variants = Enumerable.Range(0, imc.Count + 1).Select(i => (Variant)i).ToArray();
|
variants = Enumerable.Range(0, imc.Count + 1).Select(i => (Variant)i).ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -270,9 +282,9 @@ public static class EquipmentSwap
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
var manipFromIdentifier = new GmpIdentifier(idFrom);
|
var manipFromIdentifier = new GmpIdentifier(idFrom);
|
||||||
var manipToIdentifier = new GmpIdentifier(idTo);
|
var manipToIdentifier = new GmpIdentifier(idTo);
|
||||||
var manipFromDefault = ExpandedGmpFile.GetDefault(manager, manipFromIdentifier);
|
var manipFromDefault = ExpandedGmpFile.GetDefault(manager, manipFromIdentifier);
|
||||||
var manipToDefault = ExpandedGmpFile.GetDefault(manager, manipToIdentifier);
|
var manipToDefault = ExpandedGmpFile.GetDefault(manager, manipToIdentifier);
|
||||||
return new MetaSwap<GmpIdentifier, GmpEntry>(i => manips.TryGetValue(i, out var e) ? e : null, manipFromIdentifier, manipFromDefault,
|
return new MetaSwap<GmpIdentifier, GmpEntry>(i => manips.TryGetValue(i, out var e) ? e : null, manipFromIdentifier, manipFromDefault,
|
||||||
manipToIdentifier, manipToDefault);
|
manipToIdentifier, manipToDefault);
|
||||||
}
|
}
|
||||||
|
|
@ -287,9 +299,9 @@ public static class EquipmentSwap
|
||||||
Variant variantFrom, Variant variantTo, ImcFile imcFileFrom, ImcFile imcFileTo)
|
Variant variantFrom, Variant variantTo, ImcFile imcFileFrom, ImcFile imcFileTo)
|
||||||
{
|
{
|
||||||
var manipFromIdentifier = new ImcIdentifier(slotFrom, idFrom, variantFrom);
|
var manipFromIdentifier = new ImcIdentifier(slotFrom, idFrom, variantFrom);
|
||||||
var manipToIdentifier = new ImcIdentifier(slotTo, idTo, variantTo);
|
var manipToIdentifier = new ImcIdentifier(slotTo, idTo, variantTo);
|
||||||
var manipFromDefault = imcFileFrom.GetEntry(ImcFile.PartIndex(slotFrom), variantFrom);
|
var manipFromDefault = imcFileFrom.GetEntry(ImcFile.PartIndex(slotFrom), variantFrom);
|
||||||
var manipToDefault = imcFileTo.GetEntry(ImcFile.PartIndex(slotTo), variantTo);
|
var manipToDefault = imcFileTo.GetEntry(ImcFile.PartIndex(slotTo), variantTo);
|
||||||
var imc = new MetaSwap<ImcIdentifier, ImcEntry>(i => manips.TryGetValue(i, out var e) ? e : null, manipFromIdentifier, manipFromDefault,
|
var imc = new MetaSwap<ImcIdentifier, ImcEntry>(i => manips.TryGetValue(i, out var e) ? e : null, manipFromIdentifier, manipFromDefault,
|
||||||
manipToIdentifier, manipToDefault);
|
manipToIdentifier, manipToDefault);
|
||||||
|
|
||||||
|
|
@ -328,7 +340,7 @@ public static class EquipmentSwap
|
||||||
var vfxPathFrom = GamePaths.Equipment.Avfx.Path(idFrom, vfxId);
|
var vfxPathFrom = GamePaths.Equipment.Avfx.Path(idFrom, vfxId);
|
||||||
vfxPathFrom = ItemSwap.ReplaceType(vfxPathFrom, slotFrom, slotTo, idFrom);
|
vfxPathFrom = ItemSwap.ReplaceType(vfxPathFrom, slotFrom, slotTo, idFrom);
|
||||||
var vfxPathTo = GamePaths.Equipment.Avfx.Path(idTo, vfxId);
|
var vfxPathTo = GamePaths.Equipment.Avfx.Path(idTo, vfxId);
|
||||||
var avfx = FileSwap.CreateSwap(manager, ResourceType.Avfx, redirections, vfxPathFrom, vfxPathTo);
|
var avfx = FileSwap.CreateSwap(manager, ResourceType.Avfx, redirections, vfxPathFrom, vfxPathTo);
|
||||||
|
|
||||||
foreach (ref var filePath in avfx.AsAvfx()!.Textures.AsSpan())
|
foreach (ref var filePath in avfx.AsAvfx()!.Textures.AsSpan())
|
||||||
{
|
{
|
||||||
|
|
@ -339,18 +351,42 @@ public static class EquipmentSwap
|
||||||
return avfx;
|
return avfx;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static MetaSwap<EqpIdentifier, EqpEntryInternal>? CreateEqp(MetaFileManager manager, MetaDictionary manips,
|
public static MetaSwap<EqpIdentifier, EqpEntryInternal>? CreateEqp(MetaFileManager manager, MetaDictionary manips, EquipSlot slot,
|
||||||
EquipSlot slot, PrimaryId idFrom, PrimaryId idTo)
|
PrimaryId idFrom, PrimaryId idTo)
|
||||||
{
|
{
|
||||||
if (slot.IsAccessory())
|
if (slot.IsAccessory())
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
var manipFromIdentifier = new EqpIdentifier(idFrom, slot);
|
var manipFromIdentifier = new EqpIdentifier(idFrom, slot);
|
||||||
var manipToIdentifier = new EqpIdentifier(idTo, slot);
|
var manipToIdentifier = new EqpIdentifier(idTo, slot);
|
||||||
var manipFromDefault = new EqpEntryInternal(ExpandedEqpFile.GetDefault(manager, idFrom), slot);
|
var manipFromDefault = new EqpEntryInternal(ExpandedEqpFile.GetDefault(manager, idFrom), slot);
|
||||||
var manipToDefault = new EqpEntryInternal(ExpandedEqpFile.GetDefault(manager, idTo), slot);
|
var manipToDefault = new EqpEntryInternal(ExpandedEqpFile.GetDefault(manager, idTo), slot);
|
||||||
return new MetaSwap<EqpIdentifier, EqpEntryInternal>(i => manips.TryGetValue(i, out var e) ? e : null, manipFromIdentifier,
|
var swap = new MetaSwap<EqpIdentifier, EqpEntryInternal>(i => manips.TryGetValue(i, out var e) ? e : null, manipFromIdentifier,
|
||||||
manipFromDefault, manipToIdentifier, manipToDefault);
|
manipFromDefault, manipToIdentifier, manipToDefault);
|
||||||
|
var entry = swap.SwapToModdedEntry.ToEntry(slot);
|
||||||
|
// Add additional EQP entries if the swapped item is a multi-slot item,
|
||||||
|
// because those take the EQP entries of their other model-set slots when used.
|
||||||
|
switch (slot)
|
||||||
|
{
|
||||||
|
case EquipSlot.Body:
|
||||||
|
if (!entry.HasFlag(EqpEntry.BodyShowLeg)
|
||||||
|
&& CreateEqp(manager, manips, EquipSlot.Legs, idFrom, idTo) is { } legChild)
|
||||||
|
swap.ChildSwaps.Add(legChild);
|
||||||
|
if (!entry.HasFlag(EqpEntry.BodyShowHead)
|
||||||
|
&& CreateEqp(manager, manips, EquipSlot.Head, idFrom, idTo) is { } headChild)
|
||||||
|
swap.ChildSwaps.Add(headChild);
|
||||||
|
if (!entry.HasFlag(EqpEntry.BodyShowHand)
|
||||||
|
&& CreateEqp(manager, manips, EquipSlot.Hands, idFrom, idTo) is { } handChild)
|
||||||
|
swap.ChildSwaps.Add(handChild);
|
||||||
|
break;
|
||||||
|
case EquipSlot.Legs:
|
||||||
|
if (!entry.HasFlag(EqpEntry.LegsShowFoot)
|
||||||
|
&& CreateEqp(manager, manips, EquipSlot.Feet, idFrom, idTo) is { } footChild)
|
||||||
|
swap.ChildSwaps.Add(footChild);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return swap;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static FileSwap? CreateMtrl(MetaFileManager manager, Func<Utf8GamePath, FullPath> redirections, EquipSlot slot, PrimaryId idFrom,
|
public static FileSwap? CreateMtrl(MetaFileManager manager, Func<Utf8GamePath, FullPath> redirections, EquipSlot slot, PrimaryId idFrom,
|
||||||
|
|
@ -380,7 +416,7 @@ public static class EquipmentSwap
|
||||||
|
|
||||||
if (newFileName != fileName)
|
if (newFileName != fileName)
|
||||||
{
|
{
|
||||||
fileName = newFileName;
|
fileName = newFileName;
|
||||||
dataWasChanged = true;
|
dataWasChanged = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -405,13 +441,13 @@ public static class EquipmentSwap
|
||||||
EquipSlot slotTo, PrimaryId idFrom, PrimaryId idTo, ref MtrlFile.Texture texture, ref bool dataWasChanged)
|
EquipSlot slotTo, PrimaryId idFrom, PrimaryId idTo, ref MtrlFile.Texture texture, ref bool dataWasChanged)
|
||||||
{
|
{
|
||||||
var addedDashes = GamePaths.Tex.HandleDx11Path(texture, out var path);
|
var addedDashes = GamePaths.Tex.HandleDx11Path(texture, out var path);
|
||||||
var newPath = ItemSwap.ReplaceAnyId(path, prefix, idFrom);
|
var newPath = ItemSwap.ReplaceAnyId(path, prefix, idFrom);
|
||||||
newPath = ItemSwap.ReplaceSlot(newPath, slotTo, slotFrom, slotTo != slotFrom);
|
newPath = ItemSwap.ReplaceSlot(newPath, slotTo, slotFrom, slotTo != slotFrom);
|
||||||
newPath = ItemSwap.ReplaceType(newPath, slotFrom, slotTo, idFrom);
|
newPath = ItemSwap.ReplaceType(newPath, slotFrom, slotTo, idFrom);
|
||||||
newPath = ItemSwap.AddSuffix(newPath, ".tex", $"_{Path.GetFileName(texture.Path).GetStableHashCode():x8}");
|
newPath = ItemSwap.AddSuffix(newPath, ".tex", $"_{Path.GetFileName(texture.Path).GetStableHashCode():x8}");
|
||||||
if (newPath != path)
|
if (newPath != path)
|
||||||
{
|
{
|
||||||
texture.Path = addedDashes ? newPath.Replace("--", string.Empty) : newPath;
|
texture.Path = addedDashes ? newPath.Replace("--", string.Empty) : newPath;
|
||||||
dataWasChanged = true;
|
dataWasChanged = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -429,8 +465,8 @@ public static class EquipmentSwap
|
||||||
PrimaryId idFrom, ref string filePath, ref bool dataWasChanged)
|
PrimaryId idFrom, ref string filePath, ref bool dataWasChanged)
|
||||||
{
|
{
|
||||||
var oldPath = filePath;
|
var oldPath = filePath;
|
||||||
filePath = ItemSwap.AddSuffix(filePath, ".atex", $"_{Path.GetFileName(filePath).GetStableHashCode():x8}");
|
filePath = ItemSwap.AddSuffix(filePath, ".atex", $"_{Path.GetFileName(filePath).GetStableHashCode():x8}");
|
||||||
filePath = ItemSwap.ReplaceType(filePath, slotFrom, slotTo, idFrom);
|
filePath = ItemSwap.ReplaceType(filePath, slotFrom, slotTo, idFrom);
|
||||||
dataWasChanged = true;
|
dataWasChanged = true;
|
||||||
|
|
||||||
return FileSwap.CreateSwap(manager, ResourceType.Atex, redirections, filePath, oldPath, oldPath);
|
return FileSwap.CreateSwap(manager, ResourceType.Atex, redirections, filePath, oldPath, oldPath);
|
||||||
|
|
|
||||||
|
|
@ -127,7 +127,7 @@ public class ItemSwapContainer
|
||||||
? new MetaDictionary(cache)
|
? new MetaDictionary(cache)
|
||||||
: _appliedModData.Manipulations;
|
: _appliedModData.Manipulations;
|
||||||
|
|
||||||
public EquipItem[] LoadEquipment(EquipItem from, EquipItem to, ModCollection? collection = null, bool useRightRing = true,
|
public HashSet<EquipItem> LoadEquipment(EquipItem from, EquipItem to, ModCollection? collection = null, bool useRightRing = true,
|
||||||
bool useLeftRing = true)
|
bool useLeftRing = true)
|
||||||
{
|
{
|
||||||
Swaps.Clear();
|
Swaps.Clear();
|
||||||
|
|
@ -138,7 +138,7 @@ public class ItemSwapContainer
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
public EquipItem[] LoadTypeSwap(EquipSlot slotFrom, EquipItem from, EquipSlot slotTo, EquipItem to, ModCollection? collection = null)
|
public HashSet<EquipItem> LoadTypeSwap(EquipSlot slotFrom, EquipItem from, EquipSlot slotTo, EquipItem to, ModCollection? collection = null)
|
||||||
{
|
{
|
||||||
Swaps.Clear();
|
Swaps.Clear();
|
||||||
Loaded = false;
|
Loaded = false;
|
||||||
|
|
|
||||||
|
|
@ -180,7 +180,7 @@ public class ItemSwapTab : IDisposable, ITab, IUiService
|
||||||
private bool _useLeftRing = true;
|
private bool _useLeftRing = true;
|
||||||
private bool _useRightRing = true;
|
private bool _useRightRing = true;
|
||||||
|
|
||||||
private EquipItem[]? _affectedItems;
|
private HashSet<EquipItem>? _affectedItems;
|
||||||
|
|
||||||
private void UpdateState()
|
private void UpdateState()
|
||||||
{
|
{
|
||||||
|
|
@ -541,11 +541,11 @@ public class ItemSwapTab : IDisposable, ITab, IUiService
|
||||||
|
|
||||||
_dirty |= selector.Draw("##itemTarget", selector.CurrentSelection.Item.Name, string.Empty, InputWidth * 2 * UiHelpers.Scale,
|
_dirty |= selector.Draw("##itemTarget", selector.CurrentSelection.Item.Name, string.Empty, InputWidth * 2 * UiHelpers.Scale,
|
||||||
ImGui.GetTextLineHeightWithSpacing());
|
ImGui.GetTextLineHeightWithSpacing());
|
||||||
if (_affectedItems is not { Length: > 1 })
|
if (_affectedItems is not { Count: > 1 })
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ImGui.SameLine();
|
ImGui.SameLine();
|
||||||
ImGuiUtil.DrawTextButton($"which will also affect {_affectedItems.Length - 1} other Items.", Vector2.Zero,
|
ImGuiUtil.DrawTextButton($"which will also affect {_affectedItems.Count - 1} other Items.", Vector2.Zero,
|
||||||
Colors.PressEnterWarningBg);
|
Colors.PressEnterWarningBg);
|
||||||
if (ImGui.IsItemHovered())
|
if (ImGui.IsItemHovered())
|
||||||
ImGui.SetTooltip(string.Join('\n', _affectedItems.Where(i => !ReferenceEquals(i.Name, selector.CurrentSelection.Item.Name))
|
ImGui.SetTooltip(string.Join('\n', _affectedItems.Where(i => !ReferenceEquals(i.Name, selector.CurrentSelection.Item.Name))
|
||||||
|
|
@ -602,11 +602,11 @@ public class ItemSwapTab : IDisposable, ITab, IUiService
|
||||||
_dirty |= ImGui.Checkbox("Swap Left Ring", ref _useLeftRing);
|
_dirty |= ImGui.Checkbox("Swap Left Ring", ref _useLeftRing);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_affectedItems is not { Length: > 1 })
|
if (_affectedItems is not { Count: > 1 })
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ImGui.SameLine();
|
ImGui.SameLine();
|
||||||
ImGuiUtil.DrawTextButton($"which will also affect {_affectedItems.Length - 1} other Items.", Vector2.Zero,
|
ImGuiUtil.DrawTextButton($"which will also affect {_affectedItems.Count - 1} other Items.", Vector2.Zero,
|
||||||
Colors.PressEnterWarningBg);
|
Colors.PressEnterWarningBg);
|
||||||
if (ImGui.IsItemHovered())
|
if (ImGui.IsItemHovered())
|
||||||
ImGui.SetTooltip(string.Join('\n', _affectedItems.Where(i => !ReferenceEquals(i.Name, targetSelector.CurrentSelection.Item.Name))
|
ImGui.SetTooltip(string.Join('\n', _affectedItems.Where(i => !ReferenceEquals(i.Name, targetSelector.CurrentSelection.Item.Name))
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue