Работа по указаниям 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>
410 lines
32 KiB
XML
410 lines
32 KiB
XML
<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>
|