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
: Default.Index
: -1,
CollectionType.Yourself => _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,
_ when collectionType.IsSpecial() => _specialCollections[ ( int )collectionType ]?.Index ?? Default.Index,
_ => -1,
};
@ -146,71 +128,30 @@ public partial class ModCollection
// Create a special collection if it does not exist and set it to Empty.
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;
}
_specialCollections[ ( int )collectionType ] = Empty;
CollectionChanged.Invoke( collectionType, null, Empty, null );
return true;
default: return false;
return false;
}
_specialCollections[ ( int )collectionType ] = Empty;
CollectionChanged.Invoke( collectionType, null, Empty, null );
return true;
}
// Remove a special collection if it exists
public void RemoveSpecialCollection( CollectionType collectionType )
{
switch( collectionType )
if( !collectionType.IsSpecial() )
{
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:
var old = _specialCollections[ ( int )collectionType ];
if( old != null )
{
_specialCollections[ ( int )collectionType ] = null;
CollectionChanged.Invoke( collectionType, old, null, null );
}
return;
}
return;
var old = _specialCollections[ ( int )collectionType ];
if( old != null )
{
_specialCollections[ ( int )collectionType ] = null;
CollectionChanged.Invoke( collectionType, old, null, null );
}
}

View file

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

View file

@ -26,10 +26,8 @@ public unsafe class MetaFileManager : IDisposable
// Allocate in the games space for file storage.
// 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" )]
public IntPtr GetFileSpaceAddress;
#endif
public IMemorySpace* GetFileSpace()
=> ( ( 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.
#if USE_IMC
[Signature( "48 8D 05 ?? ?? ?? ?? 48 8B 8B ?? ?? ?? ?? 48 89 03", ScanType = ScanType.StaticAddress )]
public IntPtr* DefaultResourceHandleVTable;
#endif
public delegate void ClearResource( ResourceHandle* resource );
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.
[Conditional( "USE_IMC" )]
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,
@ -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.
[Conditional( "USE_IMC" )]
private void InitImc()
{
ClearDefaultResourceHook = new Hook< ClearResource >( DefaultResourceHandleVTable[ 25 ], ClearDefaultResourceDetour );
ClearDefaultResourceHook.Enable();
}
[Conditional( "USE_IMC" )]
private void DisposeImc()
{
ClearDefaultResourceHook.Disable();

View file

@ -297,7 +297,7 @@ public unsafe partial class PathResolver
// Housing Retainers
if( Penumbra.Config.UseDefaultCollectionForRetainers
&& 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;
}

View file

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

View file

@ -87,32 +87,31 @@ public partial class MetaManager
public bool RevertMod( ImcManipulation m )
{
#if USE_IMC
if( _imcManipulations.Remove( m ) )
if( !_imcManipulations.Remove( m ) )
{
var path = m.GamePath();
if( !_imcFiles.TryGetValue( path, out var file ) )
{
return false;
}
var def = ImcFile.GetDefault( path, m.EquipSlot, m.Variant, out _ );
var manip = m with { Entry = def };
if( !manip.Apply( file ) )
{
return false;
}
var fullPath = CreateImcPath( path );
if( _collection.HasCache )
{
_collection.ForceFile( path, fullPath );
}
return true;
return false;
}
#endif
return false;
var path = m.GamePath();
if( !_imcFiles.TryGetValue( path, out var file ) )
{
return false;
}
var def = ImcFile.GetDefault( path, m.EquipSlot, m.Variant, out _ );
var manip = m with { Entry = def };
if( !manip.Apply( file ) )
{
return false;
}
var fullPath = CreateImcPath( path );
if( _collection.HasCache )
{
_collection.ForceFile( path, fullPath );
}
return true;
}
public void DisposeImc()

View file

@ -10,7 +10,7 @@ using Penumbra.Mods;
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 ModCollection _collection;
@ -25,7 +25,7 @@ public partial class MetaManager : IDisposable, IEnumerable<KeyValuePair<MetaMan
=> _manipulations.Keys;
public IEnumerator<KeyValuePair<MetaManipulation, IMod>> GetEnumerator()
public IEnumerator< KeyValuePair< MetaManipulation, IMod > > GetEnumerator()
=> _manipulations.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;
}

View file

@ -250,7 +250,8 @@ public partial class ConfigWindow
}
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 ) )
{