Some fixes.

This commit is contained in:
Ottermandias 2022-07-05 23:28:14 +02:00
parent 8fd9569508
commit abce14dfdd
8 changed files with 50 additions and 148 deletions

View file

@ -72,25 +72,7 @@ public partial class ModCollection
? c.Index ? c.Index
: Default.Index : Default.Index
: -1, : -1,
CollectionType.Yourself => _specialCollections[ ( int )collectionType ]?.Index ?? Default.Index, _ when collectionType.IsSpecial() => _specialCollections[ ( int )collectionType ]?.Index ?? Default.Index,
CollectionType.PlayerCharacter => _specialCollections[ ( int )collectionType ]?.Index ?? Default.Index,
CollectionType.NonPlayerCharacter => _specialCollections[ ( int )collectionType ]?.Index ?? Default.Index,
CollectionType.Midlander => _specialCollections[ ( int )collectionType ]?.Index ?? Default.Index,
CollectionType.Highlander => _specialCollections[ ( int )collectionType ]?.Index ?? Default.Index,
CollectionType.Wildwood => _specialCollections[ ( int )collectionType ]?.Index ?? Default.Index,
CollectionType.Duskwight => _specialCollections[ ( int )collectionType ]?.Index ?? Default.Index,
CollectionType.Plainsfolk => _specialCollections[ ( int )collectionType ]?.Index ?? Default.Index,
CollectionType.Dunesfolk => _specialCollections[ ( int )collectionType ]?.Index ?? Default.Index,
CollectionType.SeekerOfTheSun => _specialCollections[ ( int )collectionType ]?.Index ?? Default.Index,
CollectionType.KeeperOfTheMoon => _specialCollections[ ( int )collectionType ]?.Index ?? Default.Index,
CollectionType.Seawolf => _specialCollections[ ( int )collectionType ]?.Index ?? Default.Index,
CollectionType.Hellsguard => _specialCollections[ ( int )collectionType ]?.Index ?? Default.Index,
CollectionType.Raen => _specialCollections[ ( int )collectionType ]?.Index ?? Default.Index,
CollectionType.Xaela => _specialCollections[ ( int )collectionType ]?.Index ?? Default.Index,
CollectionType.Helion => _specialCollections[ ( int )collectionType ]?.Index ?? Default.Index,
CollectionType.Lost => _specialCollections[ ( int )collectionType ]?.Index ?? Default.Index,
CollectionType.Rava => _specialCollections[ ( int )collectionType ]?.Index ?? Default.Index,
CollectionType.Veena => _specialCollections[ ( int )collectionType ]?.Index ?? Default.Index,
_ => -1, _ => -1,
}; };
@ -146,28 +128,7 @@ public partial class ModCollection
// Create a special collection if it does not exist and set it to Empty. // Create a special collection if it does not exist and set it to Empty.
public bool CreateSpecialCollection( CollectionType collectionType ) public bool CreateSpecialCollection( CollectionType collectionType )
{ {
switch( collectionType ) if( !collectionType.IsSpecial() || _specialCollections[( int )collectionType] != null )
{
case CollectionType.Yourself:
case CollectionType.PlayerCharacter:
case CollectionType.NonPlayerCharacter:
case CollectionType.Midlander:
case CollectionType.Highlander:
case CollectionType.Wildwood:
case CollectionType.Duskwight:
case CollectionType.Plainsfolk:
case CollectionType.Dunesfolk:
case CollectionType.SeekerOfTheSun:
case CollectionType.KeeperOfTheMoon:
case CollectionType.Seawolf:
case CollectionType.Hellsguard:
case CollectionType.Raen:
case CollectionType.Xaela:
case CollectionType.Helion:
case CollectionType.Lost:
case CollectionType.Rava:
case CollectionType.Veena:
if( _specialCollections[ ( int )collectionType ] != null )
{ {
return false; return false;
} }
@ -175,43 +136,23 @@ public partial class ModCollection
_specialCollections[ ( int )collectionType ] = Empty; _specialCollections[ ( int )collectionType ] = Empty;
CollectionChanged.Invoke( collectionType, null, Empty, null ); CollectionChanged.Invoke( collectionType, null, Empty, null );
return true; return true;
default: return false;
}
} }
// Remove a special collection if it exists // Remove a special collection if it exists
public void RemoveSpecialCollection( CollectionType collectionType ) public void RemoveSpecialCollection( CollectionType collectionType )
{ {
switch( collectionType ) if( !collectionType.IsSpecial() )
{ {
case CollectionType.Yourself: return;
case CollectionType.PlayerCharacter: }
case CollectionType.NonPlayerCharacter:
case CollectionType.Midlander:
case CollectionType.Highlander:
case CollectionType.Wildwood:
case CollectionType.Duskwight:
case CollectionType.Plainsfolk:
case CollectionType.Dunesfolk:
case CollectionType.SeekerOfTheSun:
case CollectionType.KeeperOfTheMoon:
case CollectionType.Seawolf:
case CollectionType.Hellsguard:
case CollectionType.Raen:
case CollectionType.Xaela:
case CollectionType.Helion:
case CollectionType.Lost:
case CollectionType.Rava:
case CollectionType.Veena:
var old = _specialCollections[ ( int )collectionType ]; var old = _specialCollections[ ( int )collectionType ];
if( old != null ) if( old != null )
{ {
_specialCollections[ ( int )collectionType ] = null; _specialCollections[ ( int )collectionType ] = null;
CollectionChanged.Invoke( collectionType, old, null, null ); CollectionChanged.Invoke( collectionType, old, null, null );
} }
return;
}
} }
// Create a new character collection. Returns false if the character name already has a collection. // Create a new character collection. Returns false if the character name already has a collection.

View file

@ -30,22 +30,12 @@ public unsafe class CharacterUtility : IDisposable
// The defines are set in the project configuration. // The defines are set in the project configuration.
public static readonly int[] RelevantIndices public static readonly int[] RelevantIndices
= Array.Empty< int >() = Array.Empty< int >()
#if USE_EQP
.Append( Structs.CharacterUtility.EqpIdx ) .Append( Structs.CharacterUtility.EqpIdx )
#endif
#if USE_GMP
.Append( Structs.CharacterUtility.GmpIdx ) .Append( Structs.CharacterUtility.GmpIdx )
#endif
#if USE_EQDP
.Concat( Enumerable.Range( Structs.CharacterUtility.EqdpStartIdx, Structs.CharacterUtility.NumEqdpFiles ) .Concat( Enumerable.Range( Structs.CharacterUtility.EqdpStartIdx, Structs.CharacterUtility.NumEqdpFiles )
.Where( i => i != 17 ) ) // TODO: Female Hrothgar .Where( i => i != 17 ) ) // TODO: Female Hrothgar
#endif
#if USE_CMP
.Append( Structs.CharacterUtility.HumanCmpIdx ) .Append( Structs.CharacterUtility.HumanCmpIdx )
#endif
#if USE_EST
.Concat( Enumerable.Range( Structs.CharacterUtility.FaceEstIdx, 4 ) ) .Concat( Enumerable.Range( Structs.CharacterUtility.FaceEstIdx, 4 ) )
#endif
.ToArray(); .ToArray();
public static readonly int[] ReverseIndices public static readonly int[] ReverseIndices

View file

@ -26,10 +26,8 @@ public unsafe class MetaFileManager : IDisposable
// Allocate in the games space for file storage. // Allocate in the games space for file storage.
// We only need this if using any meta file. // We only need this if using any meta file.
#if USE_IMC || USE_CMP || USE_EQDP || USE_EQP || USE_EST || USE_GMP
[Signature( "E8 ?? ?? ?? ?? 41 B9 ?? ?? ?? ?? 4C 8B C0" )] [Signature( "E8 ?? ?? ?? ?? 41 B9 ?? ?? ?? ?? 4C 8B C0" )]
public IntPtr GetFileSpaceAddress; public IntPtr GetFileSpaceAddress;
#endif
public IMemorySpace* GetFileSpace() public IMemorySpace* GetFileSpace()
=> ( ( delegate* unmanaged< IMemorySpace* > )GetFileSpaceAddress )(); => ( ( delegate* unmanaged< IMemorySpace* > )GetFileSpaceAddress )();
@ -41,10 +39,8 @@ public unsafe class MetaFileManager : IDisposable
// We only need this for IMC files, since we need to hook their cleanup function. // We only need this for IMC files, since we need to hook their cleanup function.
#if USE_IMC
[Signature( "48 8D 05 ?? ?? ?? ?? 48 8B 8B ?? ?? ?? ?? 48 89 03", ScanType = ScanType.StaticAddress )] [Signature( "48 8D 05 ?? ?? ?? ?? 48 8B 8B ?? ?? ?? ?? 48 89 03", ScanType = ScanType.StaticAddress )]
public IntPtr* DefaultResourceHandleVTable; public IntPtr* DefaultResourceHandleVTable;
#endif
public delegate void ClearResource( ResourceHandle* resource ); public delegate void ClearResource( ResourceHandle* resource );
public Hook< ClearResource > ClearDefaultResourceHook = null!; public Hook< ClearResource > ClearDefaultResourceHook = null!;
@ -67,7 +63,6 @@ public unsafe class MetaFileManager : IDisposable
} }
// Called when a new IMC is manipulated to store its data. // Called when a new IMC is manipulated to store its data.
[Conditional( "USE_IMC" )]
public void AddImcFile( ResourceHandle* resource, IntPtr data, int length ) public void AddImcFile( ResourceHandle* resource, IntPtr data, int length )
{ {
PluginLog.Debug( "Storing data 0x{Data:X} of Length {Length} for {$Name:l} (0x{Resource:X}).", ( ulong )data, length, PluginLog.Debug( "Storing data 0x{Data:X} of Length {Length} for {$Name:l} (0x{Resource:X}).", ( ulong )data, length,
@ -76,14 +71,12 @@ public unsafe class MetaFileManager : IDisposable
} }
// Initialize the hook at VFunc 25, which is called when default resources (and IMC resources do not overwrite it) destroy their data. // Initialize the hook at VFunc 25, which is called when default resources (and IMC resources do not overwrite it) destroy their data.
[Conditional( "USE_IMC" )]
private void InitImc() private void InitImc()
{ {
ClearDefaultResourceHook = new Hook< ClearResource >( DefaultResourceHandleVTable[ 25 ], ClearDefaultResourceDetour ); ClearDefaultResourceHook = new Hook< ClearResource >( DefaultResourceHandleVTable[ 25 ], ClearDefaultResourceDetour );
ClearDefaultResourceHook.Enable(); ClearDefaultResourceHook.Enable();
} }
[Conditional( "USE_IMC" )]
private void DisposeImc() private void DisposeImc()
{ {
ClearDefaultResourceHook.Disable(); ClearDefaultResourceHook.Disable();

View file

@ -297,7 +297,7 @@ public unsafe partial class PathResolver
// Housing Retainers // Housing Retainers
if( Penumbra.Config.UseDefaultCollectionForRetainers if( Penumbra.Config.UseDefaultCollectionForRetainers
&& gameObject->ObjectKind == ( byte )ObjectKind.EventNpc && gameObject->ObjectKind == ( byte )ObjectKind.EventNpc
&& gameObject->DataID is 1011832 or 1011021 ) // cf. "E8 ?? ?? ?? ?? 0F B6 F8 88 45" && gameObject->DataID is 1011832 or 1011021 ) // cf. "E8 ?? ?? ?? ?? 0F B6 F8 88 45", male or female retainer
{ {
return Penumbra.CollectionManager.Default; return Penumbra.CollectionManager.Default;
} }

View file

@ -127,19 +127,11 @@ public unsafe partial class PathResolver
private void EnableMetaHooks() private void EnableMetaHooks()
{ {
#if USE_EQP
GetEqpIndirectHook?.Enable(); GetEqpIndirectHook?.Enable();
#endif
#if USE_EQP || USE_EQDP
UpdateModelsHook?.Enable(); UpdateModelsHook?.Enable();
OnModelLoadCompleteHook?.Enable(); OnModelLoadCompleteHook?.Enable();
#endif
#if USE_GMP
SetupVisorHook?.Enable(); SetupVisorHook?.Enable();
#endif
#if USE_CMP
RspSetupCharacterHook?.Enable(); RspSetupCharacterHook?.Enable();
#endif
} }
private void DisableMetaHooks() private void DisableMetaHooks()
@ -196,30 +188,23 @@ public unsafe partial class PathResolver
public static MetaChanger ChangeEqp( ModCollection collection ) public static MetaChanger ChangeEqp( ModCollection collection )
{ {
#if USE_EQP
collection.SetEqpFiles(); collection.SetEqpFiles();
return new MetaChanger( MetaManipulation.Type.Eqp ); return new MetaChanger( MetaManipulation.Type.Eqp );
#else
return new MetaChanger( MetaManipulation.Type.Unknown );
#endif
} }
public static MetaChanger ChangeEqp( PathResolver resolver, IntPtr drawObject ) public static MetaChanger ChangeEqp( PathResolver resolver, IntPtr drawObject )
{ {
#if USE_EQP
var collection = resolver.GetCollection( drawObject ); var collection = resolver.GetCollection( drawObject );
if( collection != null ) if( collection != null )
{ {
return ChangeEqp( collection ); return ChangeEqp( collection );
} }
#endif
return new MetaChanger( MetaManipulation.Type.Unknown ); return new MetaChanger( MetaManipulation.Type.Unknown );
} }
// We only need to change anything if it is actually equipment here. // We only need to change anything if it is actually equipment here.
public static MetaChanger ChangeEqdp( PathResolver resolver, IntPtr drawObject, uint modelType ) public static MetaChanger ChangeEqdp( PathResolver resolver, IntPtr drawObject, uint modelType )
{ {
#if USE_EQDP
if( modelType < 10 ) if( modelType < 10 )
{ {
var collection = resolver.GetCollection( drawObject ); var collection = resolver.GetCollection( drawObject );
@ -228,43 +213,34 @@ public unsafe partial class PathResolver
return ChangeEqdp( collection ); return ChangeEqdp( collection );
} }
} }
#endif
return new MetaChanger( MetaManipulation.Type.Unknown ); return new MetaChanger( MetaManipulation.Type.Unknown );
} }
public static MetaChanger ChangeEqdp( ModCollection collection ) public static MetaChanger ChangeEqdp( ModCollection collection )
{ {
#if USE_EQDP
collection.SetEqdpFiles(); collection.SetEqdpFiles();
return new MetaChanger( MetaManipulation.Type.Eqdp ); return new MetaChanger( MetaManipulation.Type.Eqdp );
#else
return new MetaChanger( MetaManipulation.Type.Unknown );
#endif
} }
public static MetaChanger ChangeGmp( PathResolver resolver, IntPtr drawObject ) public static MetaChanger ChangeGmp( PathResolver resolver, IntPtr drawObject )
{ {
#if USE_GMP
var collection = resolver.GetCollection( drawObject ); var collection = resolver.GetCollection( drawObject );
if( collection != null ) if( collection != null )
{ {
collection.SetGmpFiles(); collection.SetGmpFiles();
return new MetaChanger( MetaManipulation.Type.Gmp ); return new MetaChanger( MetaManipulation.Type.Gmp );
} }
#endif
return new MetaChanger( MetaManipulation.Type.Unknown ); return new MetaChanger( MetaManipulation.Type.Unknown );
} }
public static MetaChanger ChangeEst( PathResolver resolver, IntPtr drawObject ) public static MetaChanger ChangeEst( PathResolver resolver, IntPtr drawObject )
{ {
#if USE_EST
var collection = resolver.GetCollection( drawObject ); var collection = resolver.GetCollection( drawObject );
if( collection != null ) if( collection != null )
{ {
collection.SetEstFiles(); collection.SetEstFiles();
return new MetaChanger( MetaManipulation.Type.Est ); return new MetaChanger( MetaManipulation.Type.Est );
} }
#endif
return new MetaChanger( MetaManipulation.Type.Unknown ); return new MetaChanger( MetaManipulation.Type.Unknown );
} }
@ -273,13 +249,11 @@ public unsafe partial class PathResolver
if( resolver.LastGameObject != null ) if( resolver.LastGameObject != null )
{ {
collection = IdentifyCollection( resolver.LastGameObject ); collection = IdentifyCollection( resolver.LastGameObject );
#if USE_CMP
if( collection != Penumbra.CollectionManager.Default && collection.HasCache ) if( collection != Penumbra.CollectionManager.Default && collection.HasCache )
{ {
collection.SetCmpFiles(); collection.SetCmpFiles();
return new MetaChanger( MetaManipulation.Type.Rsp ); return new MetaChanger( MetaManipulation.Type.Rsp );
} }
#endif
} }
else else
{ {
@ -291,14 +265,12 @@ public unsafe partial class PathResolver
public static MetaChanger ChangeCmp( PathResolver resolver, IntPtr drawObject ) public static MetaChanger ChangeCmp( PathResolver resolver, IntPtr drawObject )
{ {
#if USE_CMP
var collection = resolver.GetCollection( drawObject ); var collection = resolver.GetCollection( drawObject );
if( collection != null ) if( collection != null )
{ {
collection.SetCmpFiles(); collection.SetCmpFiles();
return new MetaChanger( MetaManipulation.Type.Rsp ); return new MetaChanger( MetaManipulation.Type.Rsp );
} }
#endif
return new MetaChanger( MetaManipulation.Type.Unknown ); return new MetaChanger( MetaManipulation.Type.Unknown );
} }

View file

@ -87,9 +87,11 @@ public partial class MetaManager
public bool RevertMod( ImcManipulation m ) public bool RevertMod( ImcManipulation m )
{ {
#if USE_IMC if( !_imcManipulations.Remove( m ) )
if( _imcManipulations.Remove( m ) )
{ {
return false;
}
var path = m.GamePath(); var path = m.GamePath();
if( !_imcFiles.TryGetValue( path, out var file ) ) if( !_imcFiles.TryGetValue( path, out var file ) )
{ {
@ -111,9 +113,6 @@ public partial class MetaManager
return true; return true;
} }
#endif
return false;
}
public void DisposeImc() public void DisposeImc()
{ {

View file

@ -10,7 +10,7 @@ using Penumbra.Mods;
namespace Penumbra.Meta.Manager; namespace Penumbra.Meta.Manager;
public partial class MetaManager : IDisposable, IEnumerable<KeyValuePair<MetaManipulation, IMod>> public partial class MetaManager : IDisposable, IEnumerable< KeyValuePair< MetaManipulation, IMod > >
{ {
private readonly Dictionary< MetaManipulation, IMod > _manipulations = new(); private readonly Dictionary< MetaManipulation, IMod > _manipulations = new();
private readonly ModCollection _collection; private readonly ModCollection _collection;
@ -25,7 +25,7 @@ public partial class MetaManager : IDisposable, IEnumerable<KeyValuePair<MetaMan
=> _manipulations.Keys; => _manipulations.Keys;
public IEnumerator<KeyValuePair<MetaManipulation, IMod>> GetEnumerator() public IEnumerator< KeyValuePair< MetaManipulation, IMod > > GetEnumerator()
=> _manipulations.GetEnumerator(); => _manipulations.GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() IEnumerator IEnumerable.GetEnumerator()
@ -135,6 +135,12 @@ public partial class MetaManager : IDisposable, IEnumerable<KeyValuePair<MetaMan
}; };
} }
if( Penumbra.CollectionManager.Default == _collection )
{
SetFiles();
Penumbra.ResidentResources.Reload();
}
Penumbra.CharacterUtility.LoadingFinished -= ApplyStoredManipulations; Penumbra.CharacterUtility.LoadingFinished -= ApplyStoredManipulations;
} }

View file

@ -250,7 +250,8 @@ public partial class ConfigWindow
} }
foreach( var collection in Penumbra.CollectionManager foreach( var collection in Penumbra.CollectionManager
.Where( c => Penumbra.CollectionManager.Current.CheckValidInheritance( c ) == ModCollection.ValidInheritance.Valid ) ) .Where( c => Penumbra.CollectionManager.Current.CheckValidInheritance( c ) == ModCollection.ValidInheritance.Valid )
.OrderBy( c => c.Name ))
{ {
if( ImGui.Selectable( collection.Name, _newInheritance == collection ) ) if( ImGui.Selectable( collection.Name, _newInheritance == collection ) )
{ {