mirror of
https://github.com/xivdev/Penumbra.git
synced 2026-02-23 16:27:47 +01:00
Add some improvements to game path stuff, move the race inheritance tree to game data, etc.
This commit is contained in:
parent
b50ed4b99a
commit
f1b495dff4
8 changed files with 607 additions and 320 deletions
|
|
@ -78,9 +78,9 @@ public unsafe partial class PathResolver
|
|||
|
||||
private void OnModelLoadCompleteDetour( IntPtr drawObject )
|
||||
{
|
||||
var collection = GetResolveData( drawObject );
|
||||
using var eqp = collection.ModCollection.TemporarilySetEqpFile();
|
||||
using var eqdp = ResolveEqdpData( collection.ModCollection, GetDrawObjectGenderRace( drawObject ), true, true );
|
||||
var collection = GetResolveData( drawObject );
|
||||
using var eqp = collection.ModCollection.TemporarilySetEqpFile();
|
||||
using var eqdp = ResolveEqdpData( collection.ModCollection, GetDrawObjectGenderRace( drawObject ), true, true );
|
||||
_onModelLoadCompleteHook.Original.Invoke( drawObject );
|
||||
}
|
||||
|
||||
|
|
@ -98,9 +98,9 @@ public unsafe partial class PathResolver
|
|||
return;
|
||||
}
|
||||
|
||||
var collection = GetResolveData( drawObject );
|
||||
using var eqp = collection.ModCollection.TemporarilySetEqpFile();
|
||||
using var eqdp = ResolveEqdpData( collection.ModCollection, GetDrawObjectGenderRace( drawObject ), true, true );
|
||||
var collection = GetResolveData( drawObject );
|
||||
using var eqp = collection.ModCollection.TemporarilySetEqpFile();
|
||||
using var eqdp = ResolveEqdpData( collection.ModCollection, GetDrawObjectGenderRace( drawObject ), true, true );
|
||||
_updateModelsHook.Original.Invoke( drawObject );
|
||||
}
|
||||
|
||||
|
|
@ -187,75 +187,27 @@ public unsafe partial class PathResolver
|
|||
_inChangeCustomize = true;
|
||||
var resolveData = GetResolveData( human );
|
||||
using var cmp = resolveData.ModCollection.TemporarilySetCmpFile();
|
||||
using var decals = new CharacterUtility.DecalReverter( resolveData.ModCollection, DrawObjectState.UsesDecal( 0, data ) );
|
||||
var ret = _changeCustomize.Original( human, data, skipEquipment );
|
||||
using var decals = new CharacterUtility.DecalReverter( resolveData.ModCollection, DrawObjectState.UsesDecal( 0, data ) );
|
||||
var ret = _changeCustomize.Original( human, data, skipEquipment );
|
||||
_inChangeCustomize = false;
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static DisposableContainer ResolveEqdpData( ModCollection collection, GenderRace race, bool equipment, bool accessory )
|
||||
{
|
||||
DisposableContainer Convert( params GenderRace[] races )
|
||||
var races = race.Dependencies();
|
||||
if( races.Length == 0 )
|
||||
{
|
||||
var equipmentEnumerable =
|
||||
equipment
|
||||
? races.Select( r => collection.TemporarilySetEqdpFile( r, false ) )
|
||||
: Array.Empty< IDisposable? >().AsEnumerable();
|
||||
var accessoryEnumerable =
|
||||
accessory
|
||||
? races.Select( r => collection.TemporarilySetEqdpFile( r, true ) )
|
||||
: Array.Empty< IDisposable? >().AsEnumerable();
|
||||
return new DisposableContainer( equipmentEnumerable.Concat( accessoryEnumerable ) );
|
||||
return DisposableContainer.Empty;
|
||||
}
|
||||
|
||||
return race switch
|
||||
{
|
||||
// @formatter:off
|
||||
MidlanderMale => Convert( MidlanderMale ),
|
||||
HighlanderMale => Convert( MidlanderMale, HighlanderMale ),
|
||||
ElezenMale => Convert( MidlanderMale, ElezenMale ),
|
||||
MiqoteMale => Convert( MidlanderMale, MiqoteMale ),
|
||||
RoegadynMale => Convert( MidlanderMale, RoegadynMale ),
|
||||
LalafellMale => Convert( MidlanderMale, LalafellMale ),
|
||||
AuRaMale => Convert( MidlanderMale, AuRaMale ),
|
||||
HrothgarMale => Convert( MidlanderMale, RoegadynMale, HrothgarMale ),
|
||||
VieraMale => Convert( MidlanderMale, VieraMale ),
|
||||
|
||||
MidlanderFemale => Convert( MidlanderMale, MidlanderFemale ),
|
||||
HighlanderFemale => Convert( MidlanderMale, MidlanderFemale, HighlanderFemale ),
|
||||
ElezenFemale => Convert( MidlanderMale, MidlanderFemale, ElezenFemale ),
|
||||
MiqoteFemale => Convert( MidlanderMale, MidlanderFemale, MiqoteFemale ),
|
||||
RoegadynFemale => Convert( MidlanderMale, MidlanderFemale, RoegadynFemale ),
|
||||
LalafellFemale => Convert( MidlanderMale, LalafellMale, LalafellFemale ),
|
||||
AuRaFemale => Convert( MidlanderMale, MidlanderFemale, AuRaFemale ),
|
||||
HrothgarFemale => Convert( MidlanderMale, MidlanderFemale, RoegadynFemale, HrothgarFemale ),
|
||||
VieraFemale => Convert( MidlanderMale, MidlanderFemale, VieraFemale ),
|
||||
|
||||
MidlanderMaleNpc => Convert( MidlanderMale, MidlanderMaleNpc ),
|
||||
HighlanderMaleNpc => Convert( MidlanderMale, MidlanderMaleNpc, HighlanderMale, HighlanderMaleNpc ),
|
||||
ElezenMaleNpc => Convert( MidlanderMale, MidlanderMaleNpc, ElezenMale, ElezenMaleNpc ),
|
||||
MiqoteMaleNpc => Convert( MidlanderMale, MidlanderMaleNpc, MiqoteMale, MiqoteMaleNpc ),
|
||||
RoegadynMaleNpc => Convert( MidlanderMale, MidlanderMaleNpc, RoegadynMale, RoegadynMaleNpc ),
|
||||
LalafellMaleNpc => Convert( MidlanderMale, MidlanderMaleNpc, LalafellMale, LalafellMaleNpc ),
|
||||
AuRaMaleNpc => Convert( MidlanderMale, MidlanderMaleNpc, AuRaMale, AuRaMaleNpc ),
|
||||
HrothgarMaleNpc => Convert( MidlanderMale, MidlanderMaleNpc, RoegadynMaleNpc, RoegadynMale, HrothgarMale, HrothgarMaleNpc ),
|
||||
VieraMaleNpc => Convert( MidlanderMale, MidlanderMaleNpc, VieraMale, VieraMaleNpc ),
|
||||
|
||||
MidlanderFemaleNpc => Convert( MidlanderMale, MidlanderMaleNpc, MidlanderFemale, MidlanderFemaleNpc ),
|
||||
HighlanderFemaleNpc => Convert( MidlanderMale, MidlanderMaleNpc, MidlanderFemale, MidlanderFemaleNpc, HighlanderFemale, HighlanderFemaleNpc ),
|
||||
ElezenFemaleNpc => Convert( MidlanderMale, MidlanderMaleNpc, MidlanderFemale, MidlanderFemaleNpc, ElezenFemale, ElezenFemaleNpc ),
|
||||
MiqoteFemaleNpc => Convert( MidlanderMale, MidlanderMaleNpc, MidlanderFemale, MidlanderFemaleNpc, MiqoteFemale, MiqoteFemaleNpc ),
|
||||
RoegadynFemaleNpc => Convert( MidlanderMale, MidlanderMaleNpc, MidlanderFemale, MidlanderFemaleNpc, RoegadynFemale, RoegadynFemaleNpc ),
|
||||
LalafellFemaleNpc => Convert( MidlanderMale, MidlanderMaleNpc, LalafellMale, LalafellMaleNpc, LalafellFemale, LalafellFemaleNpc ),
|
||||
AuRaFemaleNpc => Convert( MidlanderMale, MidlanderMaleNpc, MidlanderFemale, MidlanderFemaleNpc, AuRaFemale, AuRaFemaleNpc ),
|
||||
HrothgarFemaleNpc => Convert( MidlanderMale, MidlanderMaleNpc, MidlanderFemale, MidlanderFemaleNpc, RoegadynFemale, RoegadynFemaleNpc, HrothgarFemale, HrothgarFemaleNpc ),
|
||||
VieraFemaleNpc => Convert( MidlanderMale, MidlanderMaleNpc, MidlanderFemale, MidlanderFemaleNpc, VieraFemale, VieraFemaleNpc ),
|
||||
|
||||
UnknownMaleNpc => Convert( MidlanderMale, MidlanderMaleNpc, UnknownMaleNpc ),
|
||||
UnknownFemaleNpc => Convert( MidlanderMale, MidlanderMaleNpc, MidlanderFemale, MidlanderFemaleNpc, UnknownFemaleNpc ),
|
||||
_ => DisposableContainer.Empty,
|
||||
// @formatter:on
|
||||
};
|
||||
var equipmentEnumerable = equipment
|
||||
? races.Select( r => collection.TemporarilySetEqdpFile( r, false ) )
|
||||
: Array.Empty< IDisposable? >().AsEnumerable();
|
||||
var accessoryEnumerable = accessory
|
||||
? races.Select( r => collection.TemporarilySetEqdpFile( r, true ) )
|
||||
: Array.Empty< IDisposable? >().AsEnumerable();
|
||||
return new DisposableContainer( equipmentEnumerable.Concat( accessoryEnumerable ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2,6 +2,7 @@ using System;
|
|||
using System.Numerics;
|
||||
using Newtonsoft.Json;
|
||||
using Penumbra.GameData.Enums;
|
||||
using Penumbra.GameData.Structs;
|
||||
using Penumbra.Interop.Structs;
|
||||
using Penumbra.Meta.Manipulations;
|
||||
using Penumbra.String.Classes;
|
||||
|
|
@ -9,52 +10,6 @@ using Penumbra.String.Functions;
|
|||
|
||||
namespace Penumbra.Meta.Files;
|
||||
|
||||
public readonly struct ImcEntry : IEquatable< ImcEntry >
|
||||
{
|
||||
public byte MaterialId { get; init; }
|
||||
public byte DecalId { get; init; }
|
||||
public readonly ushort AttributeAndSound;
|
||||
public byte VfxId { get; init; }
|
||||
public byte MaterialAnimationId { get; init; }
|
||||
|
||||
public ushort AttributeMask
|
||||
{
|
||||
get => ( ushort )( AttributeAndSound & 0x3FF );
|
||||
init => AttributeAndSound = ( ushort )( ( AttributeAndSound & ~0x3FF ) | ( value & 0x3FF ) );
|
||||
}
|
||||
|
||||
public byte SoundId
|
||||
{
|
||||
get => ( byte )( AttributeAndSound >> 10 );
|
||||
init => AttributeAndSound = ( ushort )( AttributeMask | ( value << 10 ) );
|
||||
}
|
||||
|
||||
public bool Equals( ImcEntry other )
|
||||
=> MaterialId == other.MaterialId
|
||||
&& DecalId == other.DecalId
|
||||
&& AttributeAndSound == other.AttributeAndSound
|
||||
&& VfxId == other.VfxId
|
||||
&& MaterialAnimationId == other.MaterialAnimationId;
|
||||
|
||||
public override bool Equals( object? obj )
|
||||
=> obj is ImcEntry other && Equals( other );
|
||||
|
||||
public override int GetHashCode()
|
||||
=> HashCode.Combine( MaterialId, DecalId, AttributeAndSound, VfxId, MaterialAnimationId );
|
||||
|
||||
[JsonConstructor]
|
||||
public ImcEntry( byte materialId, byte decalId, ushort attributeMask, byte soundId, byte vfxId, byte materialAnimationId )
|
||||
{
|
||||
MaterialId = materialId;
|
||||
DecalId = decalId;
|
||||
AttributeAndSound = 0;
|
||||
VfxId = vfxId;
|
||||
MaterialAnimationId = materialAnimationId;
|
||||
AttributeMask = attributeMask;
|
||||
SoundId = soundId;
|
||||
}
|
||||
}
|
||||
|
||||
public class ImcException : Exception
|
||||
{
|
||||
public readonly ImcManipulation Manipulation;
|
||||
|
|
@ -212,8 +167,11 @@ public unsafe class ImcFile : MetaBaseFile
|
|||
}
|
||||
|
||||
public static ImcEntry GetDefault( Utf8GamePath path, EquipSlot slot, int variantIdx, out bool exists )
|
||||
=> GetDefault( path.ToString(), slot, variantIdx, out exists );
|
||||
|
||||
public static ImcEntry GetDefault( string path, EquipSlot slot, int variantIdx, out bool exists )
|
||||
{
|
||||
var file = Dalamud.GameData.GetFile( path.ToString() );
|
||||
var file = Dalamud.GameData.GetFile( path );
|
||||
exists = false;
|
||||
if( file == null )
|
||||
{
|
||||
|
|
|
|||
|
|
@ -2,7 +2,9 @@ using System;
|
|||
using System.Runtime.InteropServices;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Converters;
|
||||
using Penumbra.GameData.Data;
|
||||
using Penumbra.GameData.Enums;
|
||||
using Penumbra.GameData.Structs;
|
||||
using Penumbra.Interop.Structs;
|
||||
using Penumbra.Meta.Files;
|
||||
using Penumbra.String.Classes;
|
||||
|
|
@ -130,25 +132,12 @@ public readonly struct ImcManipulation : IMetaManipulation< ImcManipulation >
|
|||
{
|
||||
return ObjectType switch
|
||||
{
|
||||
ObjectType.Accessory => Utf8GamePath.FromString( $"chara/accessory/a{PrimaryId:D4}/a{PrimaryId:D4}.imc", out var p )
|
||||
? p
|
||||
: Utf8GamePath.Empty,
|
||||
ObjectType.Equipment => Utf8GamePath.FromString( $"chara/equipment/e{PrimaryId:D4}/e{PrimaryId:D4}.imc", out var p )
|
||||
? p
|
||||
: Utf8GamePath.Empty,
|
||||
ObjectType.DemiHuman => Utf8GamePath.FromString(
|
||||
$"chara/demihuman/d{PrimaryId:D4}/obj/equipment/e{SecondaryId:D4}/e{SecondaryId:D4}.imc", out var p )
|
||||
? p
|
||||
: Utf8GamePath.Empty,
|
||||
ObjectType.Monster => Utf8GamePath.FromString( $"chara/monster/m{PrimaryId:D4}/obj/body/b{SecondaryId:D4}/b{SecondaryId:D4}.imc",
|
||||
out var p )
|
||||
? p
|
||||
: Utf8GamePath.Empty,
|
||||
ObjectType.Weapon => Utf8GamePath.FromString( $"chara/weapon/w{PrimaryId:D4}/obj/body/b{SecondaryId:D4}/b{SecondaryId:D4}.imc",
|
||||
out var p )
|
||||
? p
|
||||
: Utf8GamePath.Empty,
|
||||
_ => throw new NotImplementedException(),
|
||||
ObjectType.Accessory => Utf8GamePath.FromString( GamePaths.Accessory.Imc.Path( PrimaryId ), out var p ) ? p : Utf8GamePath.Empty,
|
||||
ObjectType.Equipment => Utf8GamePath.FromString( GamePaths.Equipment.Imc.Path( PrimaryId ), out var p ) ? p : Utf8GamePath.Empty,
|
||||
ObjectType.DemiHuman => Utf8GamePath.FromString( GamePaths.DemiHuman.Imc.Path( PrimaryId, SecondaryId ), out var p ) ? p : Utf8GamePath.Empty,
|
||||
ObjectType.Monster => Utf8GamePath.FromString( GamePaths.Monster.Imc.Path( PrimaryId, SecondaryId ), out var p ) ? p : Utf8GamePath.Empty,
|
||||
ObjectType.Weapon => Utf8GamePath.FromString( GamePaths.Weapon.Imc.Path( PrimaryId, SecondaryId ), out var p ) ? p : Utf8GamePath.Empty,
|
||||
_ => throw new NotImplementedException(),
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue