1.7.0: охрана питомцами, один питомец за раз, прицел книг, гео-оссуарий

Питомцы:
- охрана хозяина: враг ближе 20 м (в режиме змеи - к телу) атакуется сам,
  поводок 40 м, охраняют все кроме крысы; приказ прицелом охрана не перебивает
- IsFoe исключает существ мода (necro*): питомец выбирал целью себя
- призыв нового спутника отзывает прежнего
- прицел книг призыва - как у арбалета, краснеет на годной цели

Гео-оссуарий (necroGeoOssuary): станция добычи на кровавой сфере
- основа - коллектор росы; в 3 ячейки модов любой из 5 ресурсов
  (камень, уголь, селитра, железо, сланец), 1 сфера = стак 6000 за 5-8 ч
- работает без открытого неба; верстак, Подмастерье (ур. 25)
- своя модель (бандл necroossuary): кости, корни, сосуды, клыки, черепа
  с глазами-углями; шейдер и теги коллайдера берутся у ванильного коллектора

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
AlexCube
2026-10-01 00:36:45 +03:00
co-authored by Claude Opus 5.5
parent b737dd43d0
commit f2dfeed126
15 changed files with 657 additions and 26 deletions
+12 -1
View File
@@ -495,12 +495,23 @@ namespace NecromancerTome
/// <summary>Враг для змеи: живой EntityEnemy, не питомец (призрачный) и не девиант - зомби под
/// баффом Девиатора на стороне некроманта (указание 28.09: «если под бафом девианта, то это
/// не враг»). Общее для тревоги у тела и для прицела.</summary>
static bool IsFoe(EntityAlive _e, EntityAlive _snake)
public static bool IsFoe(EntityAlive _e, EntityAlive _snake)
{
return _e != null && _e != _snake && _e is EntityEnemy && !_e.IsDead() &&
!IsNecroEntity(_e) &&
!GhostTraderPatch.ShouldBeGhost(_e) && !NecroCharmSide.IsCharmed(_e);
}
/// <summary>Питомцы и змея мода - тоже EntityEnemy (зомби-основа), и без этой проверки
/// охрана выбирала целью самого питомца: он ближе всех к хозяину (тест 30.09, лог
/// «pet 3838 идёт на 3838»). Все наши классы сущностей начинаются с necro.</summary>
public static bool IsNecroEntity(EntityAlive _e)
{
EntityClass cls;
return EntityClass.list.TryGetValue(_e.entityClass, out cls) && cls != null &&
cls.entityClassName != null && cls.entityClassName.StartsWith("necro");
}
/// <summary>Раз в полсекунды: есть ли живой враг ближе BodyDangerRange к телу игрока.</summary>
static void CheckBody(World _world, EntityPlayerLocal _player, EntityAlive _snake, float _dt)
{