fix: disable PlaceAtMe spawning, use pre-placed proxies instead
ROOT CAUSE IDENTIFIED: User found that pre-placed CK proxy HAS AI while spawned proxies DON'T. This explains ALL the issues: - Move() calls don't work without AIProcess - No animations play (AI drives animation state) - Movement is jerky (no character controller velocity management) - AI goes neutral (proxy was never properly alive as NPC) THE ISSUE: PlaceAtMe spawned actors don't get proper AIProcess initialization. They are shells without AI. THE SOLUTION: Disable PlaceAtMe spawning (kUsePlaceAtMeBackedRuntimeProxySpawn = false) Use pre-placed proxy references from the Creation Kit instead. These have full AI, character controllers, and can run naturally. EXPECTED RESULT: - ✅ Proxies have active AI - ✅ Move() will work properly (AI + character controller) - ✅ Smooth animations (velocity updates trigger animation graph) - ✅ Natural NPC behavior (aggro state is maintained) - ✅ No more jerky movement (continuous character controller) NEXT: The plugin will search for pre-placed proxy refs in the cell. If none exist, needs fallback or user must place proxies in CK. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -46,7 +46,10 @@ namespace
|
|||||||
constexpr bool kDebugUsePlaceAtMeCandidateIsolation = true;
|
constexpr bool kDebugUsePlaceAtMeCandidateIsolation = true;
|
||||||
constexpr float kDebugPlaceAtMePostSpawnSettleSeconds = 2.0F;
|
constexpr float kDebugPlaceAtMePostSpawnSettleSeconds = 2.0F;
|
||||||
constexpr float kDebugPlaceAtMeCandidateSearchSeconds = 5.0F;
|
constexpr float kDebugPlaceAtMeCandidateSearchSeconds = 5.0F;
|
||||||
constexpr bool kUsePlaceAtMeBackedRuntimeProxySpawn = true;
|
// CRITICAL FIX: PlaceAtMe spawned actors don't have proper AIProcess!
|
||||||
|
// Use pre-placed proxy references from CK instead (they have full AI).
|
||||||
|
// This is why the CK-placed proxy has animations but spawned ones don't.
|
||||||
|
constexpr bool kUsePlaceAtMeBackedRuntimeProxySpawn = false;
|
||||||
constexpr bool kDebugPlaceAtMeSpawnUseCustomProxyBase = true;
|
constexpr bool kDebugPlaceAtMeSpawnUseCustomProxyBase = true;
|
||||||
constexpr bool kDebugPlaceAtMeSpawnFallbackToCodsworth = true;
|
constexpr bool kDebugPlaceAtMeSpawnFallbackToCodsworth = true;
|
||||||
constexpr float kPlaceAtMeProxySettleSeconds = 2.0F;
|
constexpr float kPlaceAtMeProxySettleSeconds = 2.0F;
|
||||||
@@ -4633,6 +4636,14 @@ namespace
|
|||||||
const RE::PlayerCharacter& a_player,
|
const RE::PlayerCharacter& a_player,
|
||||||
bool a_sameCellPassed)
|
bool a_sameCellPassed)
|
||||||
{
|
{
|
||||||
|
// CRITICAL: Ensure proxy has active AIProcess
|
||||||
|
// PlaceAtMe-spawned actors may not have proper AI initialized
|
||||||
|
if (!a_proxy.currentProcess) {
|
||||||
|
LogWarningWithLocalPlayerPrefix(std::format(
|
||||||
|
"MoveSlotProxyToRemotePlayer: Proxy {:08X} has NO AIProcess! Movement may be jerky.",
|
||||||
|
a_proxy.GetFormID()));
|
||||||
|
}
|
||||||
|
|
||||||
RE::NiPoint3 targetPosition = a_proxy.GetPosition();
|
RE::NiPoint3 targetPosition = a_proxy.GetPosition();
|
||||||
targetPosition.x = a_remotePlayer.x;
|
targetPosition.x = a_remotePlayer.x;
|
||||||
targetPosition.y = a_remotePlayer.y;
|
targetPosition.y = a_remotePlayer.y;
|
||||||
|
|||||||
Reference in New Issue
Block a user