diff --git a/HarmonySrc/PetFollowPatch.cs b/HarmonySrc/PetFollowPatch.cs index eb8139a..ba36c48 100644 --- a/HarmonySrc/PetFollowPatch.cs +++ b/HarmonySrc/PetFollowPatch.cs @@ -460,6 +460,7 @@ namespace NecromancerTome // ВЫШЕ проверки на пустой список питомцев намеренно: трупы помечает Нож некроманта, // и к тому, есть ли у игрока сейчас призванный питомец, они отношения не имеют. CorpseLoot.RetryPendingTints(world); + Patch_ItemActionSpawnEntity_Spawn_PetLimit.RemoveOrphans(world); if (TrackedPets.Count == 0) { diff --git a/HarmonySrc/SummonPatch.cs b/HarmonySrc/SummonPatch.cs index 63b26d7..b94df85 100644 --- a/HarmonySrc/SummonPatch.cs +++ b/HarmonySrc/SummonPatch.cs @@ -517,6 +517,57 @@ namespace NecromancerTome return best; } + /// Ничейных питомцев - убрать (указание 13.10: «лучше чистить таких непривязанных»; стервятник + /// 14620 из старого сейва летал у игрока без хозяина). Раз в OrphanSweepInterval, только на сервере + /// (в одиночной игре он же), и не раньше OrphanGrace после появления игрока: до того список владения + /// игрока может быть ещё не прочитан из сейва, и под удаление попали бы все свои. + public static void RemoveOrphans(World _world) + { + if (!ConnectionManager.Instance.IsServer || _world.GetPrimaryPlayer() == null && _world.Players.list.Count == 0) + { + _orphanSweepAt = 0f; + return; + } + if (_orphanSweepAt == 0f) + { + _orphanSweepAt = Time.time + OrphanGrace; + return; + } + if (Time.time < _orphanSweepAt) + { + return; + } + _orphanSweepAt = Time.time + OrphanSweepInterval; + if (_orphanClassIds == null) + { + _orphanClassIds = new HashSet(); + foreach (string name in LimitedPets.Keys) + { + int id = EntityClass.GetId(name); + if (id != -1) + { + _orphanClassIds.Add(id); + } + } + } + for (int i = _world.EntityAlives.Count - 1; i >= 0; i--) + { + EntityAlive e = _world.EntityAlives[i]; + if (e == null || e.IsDead() || !_orphanClassIds.Contains(e.entityClass) || Possession.IsPossessed(e) || + OwnedByAnyPlayer(_world, e.entityId, e.entityClass)) + { + continue; + } + Debug.Log("[NecromancerTome] SummonPatch: ничейный питомец " + e.EntityName + " (" + e.entityId + ") убран"); + // WolfBag.DropFrom здесь нельзя: сумка одна на игрока, ничейный волк вывалил бы сумку своего. + _world.RemoveEntity(e.entityId, EnumRemoveEntityReason.Killed); + } + } + + public const float OrphanGrace = 20f, OrphanSweepInterval = 5f; + static float _orphanSweepAt; + static HashSet _orphanClassIds; + static bool OwnedByAnyPlayer(World _world, int _entityId, int _classId) { foreach (EntityPlayer p in _world.Players.list)