Ничейные питомцы чистятся при призыве и отзыве, не по таймеру
Уборка раз в 5 с снята. RemoveOrphans зовут призыв (после записи нового во владение) и отзыв; E с книгой без своего питомца убирает ничейных. Поиск ближайшего ничейного для отзыва убран. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
74bd9eb2a1
commit
5e1d30d7d0
@@ -460,7 +460,6 @@ namespace NecromancerTome
|
||||
// ВЫШЕ проверки на пустой список питомцев намеренно: трупы помечает Нож некроманта,
|
||||
// и к тому, есть ли у игрока сейчас призванный питомец, они отношения не имеют.
|
||||
CorpseLoot.RetryPendingTints(world);
|
||||
Patch_ItemActionSpawnEntity_Spawn_PetLimit.RemoveOrphans(world);
|
||||
|
||||
if (TrackedPets.Count == 0)
|
||||
{
|
||||
|
||||
+16
-58
@@ -467,18 +467,14 @@ namespace NecromancerTome
|
||||
return;
|
||||
}
|
||||
List<OwnedEntityData> owned = holdingEntity.GetOwnedEntities(petClassId);
|
||||
EntityAlive orphan;
|
||||
if (owned.Count > 0)
|
||||
{
|
||||
RecallPet(holdingEntity, owned[0].Id, tooltips.RecalledKey, tooltips.ConsumesBook ? tooltips.SummonItemName : null);
|
||||
}
|
||||
else if ((orphan = NearestOrphan(holdingEntity, petClassId)) != null)
|
||||
else if (holdingEntity.world != null && RemoveOrphans(holdingEntity.world) > 0)
|
||||
{
|
||||
// Питомец без хозяина (13.10: «летает могильный стервятник, которого я не могу отозвать» - 14620 из
|
||||
// старого сейва, за игроком не записан): отзываем ближайшего ничейного того же вида.
|
||||
Debug.Log("[NecromancerTome] SummonPatch: отзыв ничейного " + orphan.EntityName + " (" + orphan.entityId + "), " +
|
||||
(orphan.position - holdingEntity.position).magnitude.ToString("F0") + " м");
|
||||
RecallPet(holdingEntity, orphan.entityId, tooltips.RecalledKey, null);
|
||||
// Своего нет, но ничейные были и убраны (13.10: стервятник 14620 из старого сейва) - для игрока это отзыв.
|
||||
GameManager.ShowTooltip(GameManager.Instance.World.GetPrimaryPlayer(), tooltips.RecalledKey);
|
||||
}
|
||||
else if (holdingEntity.world != null)
|
||||
{
|
||||
@@ -486,58 +482,17 @@ namespace NecromancerTome
|
||||
}
|
||||
}
|
||||
|
||||
public const float OrphanRecallRange = 60f;
|
||||
|
||||
/// <summary>Ближайший живой питомец этого вида не дальше OrphanRecallRange, которого нет в списке владения
|
||||
/// ни у одного игрока.</summary>
|
||||
static EntityAlive NearestOrphan(EntityAlive _holder, int _classId)
|
||||
/// <summary>Ничейных питомцев - убрать (указание 13.10: «при призыве нового питомца и при отзыве старого пусть
|
||||
/// проверяются все остальные питомцы и вычищаются»; стервятник 14620 из старого сейва летал у игрока без
|
||||
/// хозяина). Ничейный - питомец нашего вида, которого нет в списке владения ни у одного игрока. Зовут только
|
||||
/// призыв (CreateEntity, после записи владения) и отзыв - не по таймеру. Только на сервере (в одиночной
|
||||
/// игре он же). Возвращает, сколько убрано.</summary>
|
||||
public static int RemoveOrphans(World _world)
|
||||
{
|
||||
World world = _holder.world;
|
||||
if (world == null)
|
||||
if (_world == null || !ConnectionManager.Instance.IsServer)
|
||||
{
|
||||
return null;
|
||||
return 0;
|
||||
}
|
||||
EntityAlive best = null;
|
||||
float bestSq = OrphanRecallRange * OrphanRecallRange;
|
||||
for (int i = 0; i < world.EntityAlives.Count; i++)
|
||||
{
|
||||
EntityAlive e = world.EntityAlives[i];
|
||||
if (e == null || e.entityClass != _classId || e.IsDead())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
float sq = (e.position - _holder.position).sqrMagnitude;
|
||||
if (sq > bestSq || OwnedByAnyPlayer(world, e.entityId, _classId))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
best = e;
|
||||
bestSq = sq;
|
||||
}
|
||||
return best;
|
||||
}
|
||||
|
||||
/// <summary>Ничейных питомцев - убрать (указание 13.10: «лучше чистить таких непривязанных»; стервятник
|
||||
/// 14620 из старого сейва летал у игрока без хозяина). Раз в OrphanSweepInterval, только на сервере
|
||||
/// (в одиночной игре он же), и не раньше OrphanGrace после появления игрока: до того список владения
|
||||
/// игрока может быть ещё не прочитан из сейва, и под удаление попали бы все свои.</summary>
|
||||
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<int>();
|
||||
@@ -550,6 +505,7 @@ namespace NecromancerTome
|
||||
}
|
||||
}
|
||||
}
|
||||
int removed = 0;
|
||||
for (int i = _world.EntityAlives.Count - 1; i >= 0; i--)
|
||||
{
|
||||
EntityAlive e = _world.EntityAlives[i];
|
||||
@@ -561,11 +517,11 @@ namespace NecromancerTome
|
||||
Debug.Log("[NecromancerTome] SummonPatch: ничейный питомец " + e.EntityName + " (" + e.entityId + ") убран");
|
||||
// WolfBag.DropFrom здесь нельзя: сумка одна на игрока, ничейный волк вывалил бы сумку своего.
|
||||
_world.RemoveEntity(e.entityId, EnumRemoveEntityReason.Killed);
|
||||
removed++;
|
||||
}
|
||||
return removed;
|
||||
}
|
||||
|
||||
public const float OrphanGrace = 20f, OrphanSweepInterval = 5f;
|
||||
static float _orphanSweepAt;
|
||||
static HashSet<int> _orphanClassIds;
|
||||
|
||||
static bool OwnedByAnyPlayer(World _world, int _entityId, int _classId)
|
||||
@@ -601,6 +557,7 @@ namespace NecromancerTome
|
||||
}
|
||||
owner.RemoveOwnedEntity(petEntityId);
|
||||
PetFollowPatch.Unregister(petEntityId);
|
||||
RemoveOrphans(world);
|
||||
if (summonItemName != null)
|
||||
{
|
||||
GiveBackSummonItem(owner, summonItemName);
|
||||
@@ -853,6 +810,7 @@ namespace NecromancerTome
|
||||
}
|
||||
|
||||
owner.AddOwnedEntity(__result);
|
||||
Patch_ItemActionSpawnEntity_Spawn_PetLimit.RemoveOrphans(world); // призыв тоже чистит ничейных (13.10)
|
||||
// Рой из плевка одержимого ранчера - не свиток: без !Possession.Active плевок списывал предмет, который
|
||||
// держит тело игрока (тест 13.10).
|
||||
if (petInfo.ConsumesBook && !Possession.Active && owner.inventory != null)
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user