Files
necromants-tome-7d2d-3-2/Config/entityclasses.xml
T
AlexCubeandClaude Opus 5 d97f83e972 ИИ питомцев переписан, добавлен Дух крысы, пороги разнесены по шкале
Работа по указаниям 2026-09-18. В релиз пока не выходит.

НОВЫЙ ПИТОМЕЦ "Дух крысы" (necroRatSpirit), Некромантия 3 (60 убийств):
модель зомбоволка в масштабе 0.28, урон 5, кроличьи звуки. Сам не нападает
никогда, держится справа-сзади в двух блоках, упёршись в препятствие проходит
СКВОЗЬ него и блоков не ломает. Укус замедляет, оставляет метку духа (видна на
компасе, +25% получаемого урона) и рвёт жилу. Обгрызая труп, лечится.

СВОЯ ЗАДАЧА ИИ. Задачи "иди за сущностью" в игре нет вовсе - проверены все 32
типа EAI*. Написана NecroFollowOwnerTask по образцу EAIApproachSpot: сектор
"3-6 часов" от хозяина, FindPath с canBreak:false, проход сквозь препятствие
через Entity.IsStuck. Вешается в рантайме, минуя Type.GetType.

ПРИКАЗ АТАКОВАТЬ. Повторное применение свитка при живом питомце натравливает
его на цель под прицелом: EntityPlayerLocal.HitInfo + ItemActionAttack.
GetEntityFromHit. Торговцы и игроки отсеяны. Нет цели - "Нет цели для атаки".

ЗОМБОЖИВОТНЫЕ ПРИВЕДЕНЫ К ТОМУ ЖЕ ОБРАЗЦУ. Сняты BreakBlock, Territorial,
ApproachSpot, Wander, BlockingTargetTask и поедание трупов; цель они больше не
выбирают сами. Лестница урона 20/35/45/60 плюс расчленение у Пса, Медведя и
Волка. Кровотечение всем, метка и ослабление - только у крысы.

УБИЙСТВА ПИТОМЦЕМ ЗАСЧИТЫВАЮТСЯ ВЛАДЕЛЬЦУ, включая добивание кровотечением.
Префикс на AwardKillXPServer подменяет убийцу владельцем; для смерти от баффа
заведена память укусов, потому что в DamageSource от баффа нет того, кто его
наложил. Зомби под Камнем духов это не задело - решение от 17.09 в силе.

ГРИФ откачен на летающую ветку EntityVulture и переименован в Могильного
стервятника: модель наконец соответствует имени. Держится у игрока сам, через
собственный механизм "дома" (setHomeArea), на время погони дом отвязывается.
Попытка натянуть птичий префаб на наземный класс провалилась и записана - так
делать нельзя.

ПРОЧЕЕ: призрачный вид распространён с торговцев на питомцев (у Пса, Медведя и
Волка выключен по указанию), у Пса светятся фиолетовые глаза, белая иконка
книги снята со всех свитков призыва, "Жуки Властелина" переименованы в "Рой
фараона" на всех 13 языках.

ПОРОГИ: крыса 60, стервятник 500, пёс 1300, медведь 2000, волк 4000.

ИСПРАВЛЕНО ПО ХОДУ ИГРОВЫХ ПРОВЕРОК: питомцы не призывались обычным кликом
(AnimWait требовал удержания), отзыв срабатывал не с первого раза (автомат
состояний ItemActionSpawnEntity), крыса проваливалась сквозь мир (IsStuck
отключает и пол), питомец подбрасывал хозяина (коллайдеры разводились до
появления модели).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-18 20:51:42 +03:00

410 lines
32 KiB
XML
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<config>
<!-- СЧЁТ УБИЙСТВ ПЕРЕЕХАЛ В КОД 2026-09-16. Здесь СОЗНАТЕЛЬНО ничего нет, и вернуть это
обратно нельзя - см. HarmonySrc/NecromancyKillCreditPatch.cs.
Тут стоял append на zombieTemplateMale с двумя onOtherKilledSelf-эффектами
(ModifyCVar necroZombieKillsCVar и AddProgressionLevel craftingNecroNecromancy) под общим
требованием EntityTagCompare target="other" tags="player". Он был сломан дважды:
1. Один класс - не все зомби. Пять зомби-ЗВЕРЕЙ наследуют животную ветку и до
zombieTemplateMale не доходят вовсе (animalZombieBear extends animalBear,
animalZombieBoar extends animalBoar, animalZombieDog extends animalWolf,
animalZombieVulture extends animalTemplateHostile, animalZombieVultureRadiated).
Убийство зомбопса, зомбомедведя, зомбокабана и зомбоворона не считалось никак.
2. target="other" - это БУКВАЛЬНЫЙ убийца, а не тот, кому ваниль зачла убийство.
Робомолот, кровотечение и питомцы требование tags="player" не проходят, хотя опыт
игрок за них получает: ваниль определяет получателя по DamageSource, в
EntityAlive.AwardKillXPServer.
Требование было одно на оба эффекта, поэтому вместе со скиллом недосчитывался и
necroZombieKillsCVar - то есть занижался урон Ножа некроманта (items.xml: Damage =
necroZombieKillsCVar / 10).
ОБА эффекта теперь делает Postfix на EntityPlayer.AddKillXP - единственной точке, где
ваниль уже решила, чей это фраг. ЕСЛИ ВЕРНУТЬ ЭТОТ append НА МЕСТО, убийство своей рукой
будет засчитано ДВАЖДЫ: и здесь, и в патче. Ровно это и проверять, если уровень вдруг
начнёт расти по два за труп. -->
<!-- "Зомбособака" (Zombie Dog pet): BACKLOG.md item 3. Extends the vanilla hostile
animalZombieDog (same prefab/physics/sounds - a real zombie dog model, not a reskinned
wolf) but flips it to fight FOR the player instead of against them:
- EntityFlags drops "zombie": EntityAlive.DamageEntity has a hardcoded rule that two
entities BOTH flagged EntityFlags.Zombie can never damage each other (see
HarmonySrc/DamagePatch.cs for the same rule affecting charmed zombies) - keeping our
pet flagged "zombie" would make it literally unable to hurt real zombies. Dropping the
flag sidesteps that block entirely; no Harmony damage patch needed here, unlike the
charmed-zombie case (which can't drop the flag without breaking its own zombie-side
kill-counter/quest logic - our pet has none of that to worry about).
- Tags drops "zombie"/"hostile" (kept "entity,animal,dog"), IsEnemyEntity="false" - same
shape vanilla's own player-owned entityJunkDrone uses for "friendly to the player".
- AITask-3/AITarget-1/AITarget-4 retarget from EntityPlayer/EntityBandit to EntityZombie -
purely data-driven, same AI task types animalZombieDog already used, just pointed at a
different class. This is also exactly how HarmonySrc/CharmPatch.cs flips a charmed
zombie's allegiance at runtime - confirmed here that the underlying AI system doesn't
care whether the retarget happens via live Harmony rewrite or via XML at spawn time.
Spawned by HarmonySrc/SummonPatch.cs via item bookSummonZombieDog (items.xml) - see that
file for the ownership/one-pet-limit logic (mirrors vanilla's own drone: EntityDrone.
isValidForPlayer() blocks summoning a second one while you already own one, rather than
replacing the old one - SummonPatch.cs does the same check via ownedEntities). -->
<append xpath="/entity_classes">
<entity_class name="necroZombieDog" extends="animalZombieDog">
<property name="EntityFlags" value="animal"/>
<property name="Tags" value="entity,animal,dog"/>
<property name="IsEnemyEntity" value="false"/>
<property name="Faction" value="none"/>
<!-- User request 2026-08-28: bite applies buffInjurySlow, same debuff the Insect Swarm
originally had before its own rework - see necroMeleeHandZombieDog in items.xml. -->
<property name="HandItem" value="necroMeleeHandZombieDog"/>
<!-- ИИ ПЕРЕПИСАН 2026-09-18 ПОД ОБРАЗЕЦ ДУХА КРЫСЫ, прямое указание: "поведение
других призванных животных зомби тоже подгони под крысу. По сути это те же
крысы, но размер модели оригинальный, урон нарастает от зомбособаки до
зомбоволка". Правка стоит здесь, у necroZombieDog, и этого достаточно:
Зомбомедведь, Зомбоволк и Зомбогриф расширяют именно его и унаследуют всё.
БЫЛО (и разобрано в BACKLOG.md 18.09 как "питомцы унаследовали ИИ враждебной
твари"): AITask-3 переопределял только погоню, а от animalZombieDog оставались
BreakBlock (грыз базу игрока), Territorial (держался точки призыва, а не
хозяина), ApproachSpot и Wander (бродил сам по себе), BlockingTargetTask и
SetNearestCorpseAsTarget (бросал хозяина ради ближайшего трупа), а
SetNearestEntityAsTarget заставлял его самому лезть в драку в 22 метрах.
СТАЛО, ровно как у крысы:
- AITask-3 пустой обрывает перебор, поэтому BreakBlock/Territorial/ApproachSpot/
Wander не грузятся вовсе (CopyPropertiesFromEntityClass идёт по индексам и
встаёт на первом пустом);
- AITarget-2 пустой так же убирает BlockingTargetTask и поедание трупов;
- цель НЕ ВЫБИРАЕТСЯ самостоятельно никогда: SetNearestEntityAsTarget больше
нет. Цель приходит только приказом игрока (PetCommandPatch.cs);
- AITarget-1 остаётся только как ответ на удар, и список классов без
EntityPlayer: питомец огрызается на зомби и враждебных зверей, но никогда на
хозяина;
- class=EntityAlive в AITask-1 - это разрешение задаче подхватить ту цель,
которую ей ДАЛИ, а не "бей всё живое" (EAIApproachAndAttackTarget.CanExecute
сверяет тип цели со списком и без совпадения не запускается). Кого можно
назначать, решает PetCommandPatch.cs, и торговец там отсеян.
Задача следования (NecroFollowOwnerTask) вешается в рантайме из SummonPatch.cs -
всем, у кого UsesFollowTask, то есть теперь и этим четверым. -->
<property name="AITask-1" value="ApproachAndAttackTarget" data="class=EntityAlive,0"/>
<property name="AITask-2" value="Look"/>
<property name="AITask-3" value=""/>
<property name="AITarget-1" value="SetAsTargetIfHurt" data="class=EntityZombie,EntityEnemyAnimal"/>
<property name="AITarget-2" value=""/>
</entity_class>
</append>
<!-- "Жуки Властелина" (insect swarm pet): user request 2026-08-28, alongside the Zombie Dog
bugfix (see items.xml). Extends vanilla's own animalInsectSwarm (same prefab/sounds/
tanky-vs-melee stats - PhysicalDamageResist 75% vs non-ranged inherits unchanged, a nice
free defensive fit for something meant to be swarmed by zombie melee).
BUG FIXED 2026-08-28 (swarm attacked the PLAYER, not zombies): the original version here
overrode AITask-1/AITarget-1, mirroring animalInsectSwarm's own choice to blank those two
indices - but animalInsectSwarm extends animalTemplateHostile, and re-reading THAT
template (Data/Config/entityclasses.xml) shows the actual player-attacking task/target
live at DIFFERENT indices: AITask-2 ("ApproachAndAttackTarget" class=EntityPlayer,...) and
AITarget-4 ("SetNearestEntityAsTarget" class=EntityPlayer,...). animalInsectSwarm's
AITask-1/AITarget-1 blanking only wipes animalTemplateHostile's harmless AITask-1
(BreakBlock) and AITarget-1 (SetAsTargetIfHurt, generic) - the real player-hunting
behavior at index 2/4 was never touched by that blanking, and my override at index 1
just sat next to it as a no-op extra task while the REAL one kept targeting players.
Fixed by overriding the actual indices (2 and 4) instead. AITask-1/AITarget-1 are left
alone now - they inherit animalInsectSwarm's own blank override, same as vanilla.
BEHAVIOR CHANGE 2026-08-28 (user request): no longer deals real damage + slows zombies -
it stings a zombie once and that zombie becomes a Deviator-charmed ally, same buff as the
Spirit Stone/Grimoire (buffNecroDeviatorCharm - see necroMeleeHandInsectSwarm in
items.xml). Search range widened (22/20 -> 40/30) per "ищут всех зомби в радиусе", though
that number turned out not to matter much either - see below.
TARGETING IS NOT ACTUALLY DRIVEN BY THESE AITask/AITarget PROPERTIES AT ALL, despite the
fix above (found out the hard way 2026-08-28, after that fix didn't stop the swarm from
attacking the player): animalInsectSwarm's own Class="EntitySwarm" extends EntityVulture,
which has entirely hardcoded C# target-finding (World.GetClosestPlayerSeen/GetClosestPlayer,
literally typed to EntityPlayer) - it never consults the declarative AITask/AITarget system
ground creatures like the Dog use. The AITask-2/AITarget-4 overrides above are harmless but
functionally dead for this entity_class. The real fix is HarmonySrc/SwarmTargetPatch.cs,
patching EntityAlive.SetAttackTarget to redirect player-targeting to the nearest zombie -
see that file. It also skips zombies that already carry buffNecroDeviatorCharm (added after
a second user report that the swarm would fly off in wide loops instead of moving straight
to an uncharmed zombie standing right next to the one it had just charmed - re-targeting
the same just-charmed zombie over and over, because it was still the nearest one, was
exactly what caused that).
EntityFlags/EntityType: parent sets EntityFlags="animal,zombie" and EntityType="Zombie" -
same DamageEntity zombie-vs-zombie block as the dog (see that entry above and
HarmonySrc/DamagePatch.cs) would otherwise stop it stinging real zombies at all, so both
get dropped to plain "animal". -->
<append xpath="/entity_classes">
<entity_class name="necroInsectSwarm" extends="animalInsectSwarm">
<property name="EntityFlags" value="animal"/>
<property name="EntityType" value="Animal"/>
<property name="Tags" value="entity,noHead"/>
<property name="IsEnemyEntity" value="false"/>
<property name="Faction" value="none"/>
<property name="HandItem" value="necroMeleeHandInsectSwarm"/>
<property name="AITask-2" value="ApproachAndAttackTarget" data="class=EntityZombie,20"/>
<property name="AITarget-4" value="SetNearestEntityAsTarget" data="class=EntityZombie,40,30"/>
</entity_class>
</append>
<!-- Three more summon-pet zombies, BACKLOG.md item 4a. REPLACED AGAIN 2026-08-29, THIRD
APPROACH, per the user's own direct suggestion after the second approach's Bear/Wolf
fixes still didn't work ("почему нельзя взять зомбособаку, но добавить её ХП и силы
атаки, и заменить ей модельку на медведя?"). Correct call - stop re-deriving AI/targeting
data from each different vanilla template's own quirky format (full pipe-string vs
indexed properties, different index numbering, etc.) and instead extend the Dog's OWN
entity_class (necroZombieDog, defined above) directly. necroZombieDog already has
EntityFlags/Tags/IsEnemyEntity/Faction AND the AITask-3/AITarget-1/AITarget-4 zombie-
targeting overrides all confirmed working correctly in-game across multiple test rounds -
none of that has to be re-verified or re-derived per creature any more, it's inherited
unchanged. Bear/Wolf below only override what's actually cosmetic/stat-related: Prefab
(swap the visible model), PhysicsBody/Mass (match the new model's real size so
collision/knockback look right), HandItem (reuse the REAL vanilla hand-item for that
creature - meleeHandAnimalZombieBear/meleeHandAnimalDireWolf, both real items with their
own already-tuned damage - 60 each, vs. the Dog's own 8), and HealthMax (bumped up to
match, see each entity's own comment for the exact vanilla reference number used).
Griffin NOT converted this way (left on the previous animalZombieVulture-based approach,
unchanged) - flagged as a real, separate risk, not just left out by oversight: Bear/Wolf
share the Dog's own quadruped body plan/animation rig, so swapping just the Prefab is
low-risk (same skeleton shape, same generic AvatarAnimalController). A vulture is a
bird - almost certainly a structurally different skeleton/rig - forcing that Prefab onto
necroZombieDog's own ground-quadruped C# class (EntityZombieDog, no flight code at all)
risks either a broken/distorted-looking model (mismatched bone names) or, best case, a
"walking bird" that never actually flies. Worth a real decision, not a silent guess -
see BACKLOG.md for the open question. -->
<append xpath="/entity_classes">
<entity_class name="necroZombieBear" extends="necroZombieDog">
<!-- Real vanilla animalZombieBear's own Prefab/PhysicsBody/Mass (the same asset a
genuine zombie bear uses) - not re-deriving AI from it any more, just borrowing
its look and physical size so collision/knockback scale correctly for a
bear-sized model sitting on the Dog's skeleton/rig. -->
<property name="Prefab" value="@:Entities/Animals/Bear/animalBearZombiePrefab.prefab"/>
<property name="PrefabCombined" value="true"/>
<property name="PhysicsBody" value="bear"/>
<property name="Mass" value="600"/>
<!-- 80% от ванильного, указание 2026-09-18. У animalZombieBear своего SizeScale нет,
то есть ванильный размер - единица, отсюда 0.8. -->
<property name="SizeScale" value="0.8"/>
<property name="Tags" value="entity,animal,bear"/>
<!-- FIXED 2026-08-30 (user report: "зомбомедведь лает" - swapping the Prefab only
changes the visible model, sound properties are a totally separate set of
properties and stayed inherited from necroZombieDog/animalZombieDog (dog barks)
the whole time - same oversight needed fixing on Wolf/Griffin below too, not
just this one. Real animalBear's own sound set (animalZombieBear itself doesn't
override any of these, confirmed by reading it directly - it inherits animalBear's). -->
<property name="SoundRandom" value="bearroam"/>
<property name="SoundAlert" value="bearalert"/>
<property name="SoundHurt" value="bearpain"/>
<property name="SoundDeath" value="beardeath"/>
<property name="SoundAttack" value="bearattack"/>
<property name="SoundSense" value="bearsense"/>
<property name="SoundGiveUp" value="beargiveup"/>
<property name="SoundStepType" value="animalhvystep"/>
<!-- Real vanilla hand item (claw damage 60, vs. the Dog's own bite at 8) - reused
as-is, not customized further (no slow debuff etc. - not asked for). -->
<property name="HandItem" value="necroMeleeHandZombieBear"/>
<effect_group name="Base Effects">
<!-- 1500 is a guess between the Dog's 200 and real animalZombieBear's own 4000 -
a tough pet, not necessarily boss-tier tanky. Say if it should be higher/lower. -->
<passive_effect name="HealthMax" operation="base_set" value="1500"/>
</effect_group>
</entity_class>
</append>
<append xpath="/entity_classes">
<entity_class name="necroZombieWolf" extends="necroZombieDog">
<!-- Real vanilla animalDireWolf's own Prefab/PhysicsBody/Mass/SizeScale. -->
<property name="Prefab" value="@:Entities/Animals/DireWolf/animalDireWolfPrefab.prefab"/>
<property name="PrefabCombined" value="true"/>
<property name="PhysicsBody" value="AWolf"/>
<property name="Mass" value="180"/>
<!-- 1.12 = 80% от ванильных 1.4 у animalDireWolf, указание 2026-09-18. -->
<property name="SizeScale" value="1.12"/>
<property name="Tags" value="entity,animal,wolf"/>
<!-- FIXED 2026-08-30, same oversight as the Bear above (see its comment) - real
animalDireWolf's own sound set. -->
<property name="SoundRandom" value="wolfdireroam"/>
<property name="SoundAlert" value="wolfdirealert"/>
<property name="SoundHurt" value="wolfdirepain"/>
<property name="SoundDeath" value="wolfdiredeath"/>
<property name="SoundAttack" value="wolfdireattack"/>
<property name="SoundSense" value="wolfdiresense"/>
<property name="SoundGiveUp" value="wolfdiregiveup"/>
<property name="SoundStepType" value="animalpawstep"/>
<!-- Real vanilla hand item (bite damage 60, vs. the Dog's own 8). -->
<property name="HandItem" value="necroMeleeHandZombieWolf"/>
<effect_group name="Base Effects">
<!-- 1200 is a guess between the Dog's 200 and real animalDireWolf's own 3000 -
slightly below the Bear, faster/leaner theme. Say if it should be different. -->
<passive_effect name="HealthMax" operation="base_set" value="1200"/>
</effect_group>
</entity_class>
</append>
<!-- "Зомбогриф" ОТКАЧЕН 2026-09-18 К ЛЕТАЮЩЕЙ ВЕТКЕ.
История у него длинная, и важно не потерять её конец. До 29.08 он расширял
animalZombieVulture и просто бестолково летал ("летает где-то в небе, и зомби его вообще
не интересуют") - тогда его перевели на necroZombieDog, то есть сделали наземным со
сменённой моделью. 18.09 пользователь заметил результат прямо: "зомбогриф у тебя это серая
пума". Попробовали натянуть на тот же наземный класс префаб стервятника - вышло хуже
всего: "выглядит жутко, прозрачное только туловище и голова, по земле он ползёт на
крыльях". Это и был ответ на висевший с 29.08 вопрос, можно ли подменить ОДИН префаб:
нельзя, птичья модель на аниматоре наземного квадрупа не работает.
Указание: "зомбогрифа откати, пусть ведёт себя как раньше и не делай его прозрачным.
Пусть пока бестолково летает как раньше, но с возможностью нацелить его на противника...
Потом сделаем грифа как надо. Но потом."
Поэтому здесь снова ванильная ЛЕТАЮЩАЯ ветка со всем, что к ней прилагается, и это
сознательный шаг назад до отдельной работы над ним (замысел разведдрона - BACKLOG.md).
ЧТО ПРИШЛОСЬ СНЯТЬ И ПОЧЕМУ:
- EntityFlags и EntityType уходят с "animal,zombie"/"Zombie" на чистое "animal"/"Animal".
Иначе EntityAlive.DamageEntity не даст ему бить зомби вовсе: там жёсткое правило, что
две сущности с флагом Zombie не могут повредить друг другу. Тот же приём и по той же
причине применён к Рою жуков выше.
- Tags теряют zombie/hostile, IsEnemyEntity=false, Faction=none - форма "свой игроку",
как у всех остальных питомцев.
- AITask/AITarget НЕ ЗАДАЮТСЯ ВОВСЕ, и это не упущение: Class="EntityVulture" не
использует систему AITask ни в каком виде, у него собственный захардкоженный поиск
целей на C# (см. HarmonySrc/SwarmTargetPatch.cs, там это разобрано целиком). Писать
сюда задачи - ровно та ошибка, которую уже совершали 28.08 с Роем.
ЧТОБЫ НЕ АТАКОВАЛ ХОЗЯИНА, он добавлен в SwarmTargetPatch.SpeciesByName: префикс на
EntityAlive.SetAttackTarget подменяет игрока ближайшим зомби. Это единственная точка, через
которую проходят все цели EntityVulture.
ПРИКАЗ АТАКОВАТЬ у него остаётся (CommandsAttack в SummonPatch.cs), но с оговоркой:
EntityVulture перебирает цели сам, своим циклом, и может сбросить наш приказ. Задачу
следования ему НЕ вешаем - она наземная и с полётом только подерётся. -->
<append xpath="/entity_classes">
<entity_class name="necroZombieGriffin" extends="animalZombieVulture">
<property name="EntityFlags" value="animal"/>
<property name="EntityType" value="Animal"/>
<property name="Tags" value="entity,animal,vulture"/>
<property name="IsEnemyEntity" value="false"/>
<property name="Faction" value="none"/>
<property name="HandItem" value="necroMeleeHandZombieGriffin"/>
<effect_group name="Base Effects">
<!-- У ванильного зомбостервятника 30 HP - для питомца, которого не отозвать до
следующего призыва, это ничто. 750 оставлено с прежней, наземной версии. -->
<passive_effect name="HealthMax" operation="base_set" value="750"/>
</effect_group>
</entity_class>
</append>
<!-- "Дух крысы" (Rat Spirit) - питомец начального уровня, указание 2026-09-18. Первый
питомец, у которого поведение задано НАМЕРЕННО, а не унаследовано: на нём и отлаживается
ИИ питомцев вообще (см. разбор в BACKLOG.md от 2026-09-18).
МОДЕЛЬ. Extends necroZombieWolf, то есть тот же самый ванильный префаб лютоволка, только
SizeScale с 1.4 на 0.28 - "уменьшить в 5 раз". Хитбокс отдельно задавать НЕ НАДО и брать
кроличий НЕЛЬЗЯ: коллайдеры в physicsbodies.xml привязаны к костям по имени пути, а риг
кролика с волчьим не совпадает (у кролика корпус Hips/LowerBack/Spine1 и голова под
Spine2/Neck/Head, у волка Hips/LowerBack/Spine/Spine1/Spine2 и голова под Neck/Neck1/Head)
- кроличье тело нашло бы на волчьей модели только таз и ноги, а корпус и голова остались
бы вообще без хитбокса. Унаследованный PhysicsBody="AWolf" при этом ужимается сам:
Entity.SetScale ставит ModelTransform.localScale, а костяные коллайдеры лежат внутри него.
ЗВУКИ - кроличьи ("он тоже грызун"). На АТАКУ поставлен rabbitpain: это буквально вопль
кролика от боли, и он же остаётся на SoundHurt - крыса вопит и когда кусает, и когда бьют
её. Остальные звуки ГЛУШАТСЯ ПУСТЫМИ НАМЕРЕННО: у animalRabbit нет ни roam, ни alert, ни
sense, ни giveup, и если их не погасить, крыса унаследует волчьи от necroZombieWolf -
ровно те грабли, что дали "зомбомедведь лает" (см. necroZombieBear выше). Дух рыщет молча.
ИИ. Здесь снято ВСЁ, что питомцы до сих пор тащили от враждебного зомбопса:
- нет BreakBlock и BlockingTargetTask - крыса физически не может грызть блоки, и это же
продублировано в коде (EAINecroFollowOwner зовёт FindPath с canBreak:false). Упёршись
в препятствие, дух проходит СКВОЗЬ него - см. Entity.IsStuck в PetFollowTask.cs;
- нет Territorial, ApproachSpot и Wander - крыса не бродит сама, она ходит за хозяином
(задача следования добавляется в рантайме из SummonPatch.cs, отдельным классом, потому
что задачи "иди за сущностью" в игре нет вовсе - все 32 типа EAI* проверены);
- нет SetNearestCorpseAsTarget - она не бросает хозяина ради ближайшего трупа;
- AITarget-1 оставлен ТОЛЬКО как ответ на удар, и список классов без EntityPlayer:
крыса огрызается на зомби и враждебных зверей, но никогда на хозяина, даже если он
заденет её в свалке (прямое указание 2026-09-18).
Сама она цель не ВЫБИРАЕТ никогда: SetNearestEntityAsTarget здесь нет, а AITarget-2
пустой обрывает перебор (CopyPropertiesFromEntityClass идёт по индексам и встаёт на первом
пустом - тем же приёмом ваниль глушит задачи у animalInsectSwarm). Цель приходит снаружи:
по команде игрока из PetCommandPatch.cs.
class=EntityAlive в AITask-1 - это НЕ "бей всё живое" само по себе, а разрешение задаче
подхватить ту цель, которую ей дали (EAIApproachAndAttackTarget.CanExecute сверяет тип
цели с этим списком и без совпадения просто не запускается). Кого можно назначить целью,
решает PetCommandPatch.cs, и торговец там отсеян. -->
<append xpath="/entity_classes">
<entity_class name="necroRatSpirit" extends="necroZombieWolf">
<property name="SizeScale" value="0.28"/>
<property name="Mass" value="33"/>
<property name="Weight" value="11"/>
<property name="Tags" value="entity,animal,rat"/>
<property name="HandItem" value="necroMeleeHandRatSpirit"/>
<property name="SoundRandom" value=""/>
<property name="SoundAlert" value=""/>
<property name="SoundSense" value=""/>
<property name="SoundGiveUp" value=""/>
<property name="SoundHurt" value="rabbitpain"/>
<property name="SoundDeath" value="rabbitdeath"/>
<property name="SoundAttack" value="rabbitpain"/>
<property name="SoundStepType" value="animallightstep"/>
<!-- Жёлтая метка на карте и компасе - указание 2026-09-18. Класс метки наш,
Config/nav_objects.xml; ванильные animaltracking_* не подошли, они завязаны
на перк следопыта, а не на прямое назначение. -->
<property name="NavObject" value="necroRatSpiritPet"/>
<property name="AITask-1" value="ApproachAndAttackTarget" data="class=EntityAlive,0"/>
<property name="AITask-2" value="Look"/>
<property name="AITask-3" value=""/>
<property name="AITarget-1" value="SetAsTargetIfHurt" data="class=EntityZombie,EntityEnemyAnimal"/>
<property name="AITarget-2" value=""/>
<effect_group name="Base Effects">
<!-- Дух-разведчик, а не танк: меньше собаки (200). Урон у неё и так 5. -->
<passive_effect name="HealthMax" operation="base_set" value="120"/>
</effect_group>
</entity_class>
</append>
<!-- "Жертва" loot bag - BACKLOG.md item 5, Necromancer's Knife. Same shape as vanilla's own
EntityLootContainerStrong ("BLUE")/EntityLootContainerBoss ("RED") right above these in
Data/Config/entityclasses.xml - only the Mesh and LootList differ.
BUG FIXED 2026-08-28 ("зомби погиб с бафом, гарантированный дроп запустился, но лута
нет"): Mesh was a guess, zpackGreenPrefab.prefab - confirmed by the in-game test itself
that it doesn't exist as a real asset. VictimPatch.cs's own warning fired: "created entity
for 'EntityLootContainerVictim' wasn't an EntityLootContainer" - EntityFactory.CreateEntity
didn't produce a usable entity at all once its mesh failed to resolve, so nothing ever
got spawned, guaranteed roll or not. Reverted to zpackPrefab.prefab (the default/yellow
mesh, confirmed to exist - every other loot container variant in vanilla config either
uses this one directly or one of the three OTHER confirmed variants, blue/red/gold) per
the fallback plan agreed on before this was ever guessed at - not visually distinct from a
normal zombie drop, but a real, working bag with the right guaranteed contents.
Force-spawned by HarmonySrc/VictimPatch.cs when a zombie with buffNecroVictim dies -
never rolled by the normal LootDropProb/LootDropEntityClass system (not referenced from
any zombie's own entity_class), so its own IsEnemyEntity/Faction/etc. just mirror the
other loot containers for consistency, not because anything reads them via that path. -->
<append xpath="/entity_classes">
<entity_class name="EntityLootContainerVictim">
<property name="Class" value="EntityLootContainer"/>
<property name="UserSpawnType" value="Console"/>
<property name="Mesh" value="@:Entities/LootContainers/zpackPrefab.prefab"/>
<property name="ModelType" value="Custom"/>
<property name="Prefab" value="Backpack"/>
<property name="Parent" value="Backpack"/>
<property name="IsEnemyEntity" value="false"/>
<property name="TimeStayAfterDeath" value="3600"/>
<property name="LootList" value="zPackVictim"/>
<property name="Faction" value="none"/>
</entity_class>
</append>
</config>