Решили: фокус авто-атаки стал частью боевой ФОРМЫ. AttackStance несёт свой TargetingMode,
стойка кладёт его в RuntimeUnit.StanceTargeting, а ProfileBrain читает оттуда, предпочитая
профилю кита. Добавлен режим TargetingMode.HighestArmor (сумма физической и магической брони).
Заодно формы стали видны карточке: компонент объявляет свои типы урона через новый
IDeclaresDamageTypes, и чипы кита со стойками больше не показывают одну форму из двух.
Почему: мозг читает AIProfile один раз при сборке, поэтому «в упор бью самого бронированного»
через профиль невыразимо в принципе — это было записано долгом с самого разведения форм. Поле на
бойце выбрано nullable, а не полным снимком рядом с типом урона и доставкой: те части формы читает
боевой пайплайн и боец обязан нести их сам, а фокус читает только мозг, у которого профиль уже есть.
Сделай его полным снимком — и каждый, кто собирает бойца руками (стенд, тесты), обязан был бы
продублировать фокус из профиля, а забыв, молча получил бы «ближайшего» вместо заявленного.
HighestArmor считает обе школы разом: режим общий для всех китов, и привязка к физброне сделала бы
его личным для одного шреда Десятины.
Грабли: правило «спящих не выбираем» спрашивало режим у профиля (HuntsSleepers), и с приходом
формы оно бы смотрело не на тот режим, по которому идёт выбор цели, — теперь принимает действующий.
И снятие стойки обязано гасить её фокус: иначе боец без формы продолжил бы выбирать цель по правилу
формы, которой на нём больше нет.
Владелец правды: AttackStanceComponent.AttackStance.Targeting, RuntimeUnit.StanceTargeting,
ProfileBrain.Decide, IDeclaresDamageTypes, тесты AttackStanceTests.FocusFollowsTheForm_AndBeatsTheKitProfile,
UnitTagResolverTests.Resolve_StanceForms_BothTypesReachTheCard.