diff --git a/Penumbra/Interop/PathResolving/CollectionResolver.cs b/Penumbra/Interop/PathResolving/CollectionResolver.cs
index cb271d7e..65fc0771 100644
--- a/Penumbra/Interop/PathResolving/CollectionResolver.cs
+++ b/Penumbra/Interop/PathResolving/CollectionResolver.cs
@@ -31,7 +31,7 @@ public unsafe class CollectionResolver
private readonly CutsceneService _cutscenes;
private readonly Configuration _config;
- private readonly CollectionManager _collectionManager;
+ private readonly CollectionManager _collectionManager;
private readonly TempCollectionManager _tempCollections;
private readonly DrawObjectState _drawObjectState;
@@ -65,9 +65,10 @@ public unsafe class CollectionResolver
?? _collectionManager.Default;
var player = _actors.AwaitedService.GetCurrentPlayer();
+ var _ = false;
return CollectionByIdentifier(player)
?? CheckYourself(player, gameObject)
- ?? CollectionByAttributes(gameObject)
+ ?? CollectionByAttributes(gameObject, ref _)
?? _collectionManager.Default;
}
@@ -101,7 +102,7 @@ public unsafe class CollectionResolver
/// Identify the correct collection for the last created game object.
public ResolveData IdentifyLastGameObjectCollection(bool useCache)
- => IdentifyCollection((GameObject*)_drawObjectState.LastGameObject, useCache);
+ => IdentifyCollection((GameObject*)_drawObjectState.LastGameObject, useCache);
/// Identify the correct collection for a draw object.
public ResolveData IdentifyCollection(DrawObject* drawObject, bool useCache)
@@ -126,7 +127,7 @@ public unsafe class CollectionResolver
/// Actors are also not named. So use Yourself > Players > Racial > Default.
///
private bool LoginScreen(GameObject* gameObject, out ResolveData ret)
- {
+ {
// Also check for empty names because sometimes named other characters
// might be loaded before being officially logged in.
if (_clientState.IsLoggedIn || gameObject->Name[0] != '\0')
@@ -135,10 +136,11 @@ public unsafe class CollectionResolver
return false;
}
- var collection2 = _collectionManager.ByType(CollectionType.Yourself)
- ?? CollectionByAttributes(gameObject)
+ var notYetReady = false;
+ var collection = _collectionManager.ByType(CollectionType.Yourself)
+ ?? CollectionByAttributes(gameObject, ref notYetReady)
?? _collectionManager.Default;
- ret = _cache.Set(collection2, ActorIdentifier.Invalid, gameObject);
+ ret = notYetReady ? collection.ToResolveData(gameObject) : _cache.Set(collection, ActorIdentifier.Invalid, gameObject);
return true;
}
@@ -151,12 +153,13 @@ public unsafe class CollectionResolver
return false;
}
- var player = _actors.AwaitedService.GetCurrentPlayer();
- var collection2 = (player.IsValid ? CollectionByIdentifier(player) : null)
+ var player = _actors.AwaitedService.GetCurrentPlayer();
+ var notYetReady = false;
+ var collection = (player.IsValid ? CollectionByIdentifier(player) : null)
?? _collectionManager.ByType(CollectionType.Yourself)
- ?? CollectionByAttributes(gameObject)
+ ?? CollectionByAttributes(gameObject, ref notYetReady)
?? _collectionManager.Default;
- ret = _cache.Set(collection2, ActorIdentifier.Invalid, gameObject);
+ ret = notYetReady ? collection.ToResolveData(gameObject) : _cache.Set(collection, ActorIdentifier.Invalid, gameObject);
return true;
}
@@ -174,13 +177,14 @@ public unsafe class CollectionResolver
return _cache.Set(ModCollection.Empty, identifier, gameObject);
}
+ var notYetReady = false;
var collection = CollectionByIdentifier(identifier)
?? CheckYourself(identifier, gameObject)
- ?? CollectionByAttributes(gameObject)
- ?? CheckOwnedCollection(identifier, owner)
+ ?? CollectionByAttributes(gameObject, ref notYetReady)
+ ?? CheckOwnedCollection(identifier, owner, ref notYetReady)
?? _collectionManager.Default;
- return _cache.Set(collection, identifier, gameObject);
+ return notYetReady ? collection.ToResolveData(gameObject) : _cache.Set(collection, identifier, gameObject);
}
/// Check both temporary and permanent character collections. Temporary first.
@@ -201,8 +205,8 @@ public unsafe class CollectionResolver
return null;
}
- /// Check special collections given the actor.
- private ModCollection? CollectionByAttributes(GameObject* actor)
+ /// Check special collections given the actor. Returns notYetReady if the customize array is not filled.
+ private ModCollection? CollectionByAttributes(GameObject* actor, ref bool notYetReady)
{
if (!actor->IsCharacter())
return null;
@@ -212,6 +216,12 @@ public unsafe class CollectionResolver
if (!IsModelHuman((uint)character->ModelCharaId))
return null;
+ if (character->CustomizeData[0] == 0)
+ {
+ notYetReady = true;
+ return null;
+ }
+
var bodyType = character->CustomizeData[2];
var collection = bodyType switch
{
@@ -233,7 +243,7 @@ public unsafe class CollectionResolver
}
/// Get the collection applying to the owner if it is available.
- private ModCollection? CheckOwnedCollection(ActorIdentifier identifier, GameObject* owner)
+ private ModCollection? CheckOwnedCollection(ActorIdentifier identifier, GameObject* owner, ref bool notYetReady)
{
if (identifier.Type != IdentifierType.Owned || !_config.UseOwnerNameForCharacterCollection || owner == null)
return null;
@@ -242,7 +252,7 @@ public unsafe class CollectionResolver
ObjectKind.None,
uint.MaxValue);
return CheckYourself(id, owner)
- ?? CollectionByAttributes(owner);
+ ?? CollectionByAttributes(owner, ref notYetReady);
}
///