Решили: награда носителю за парирование (ParryComponent._onParryReward, у дуэлянта — щит 200 на
3 сек) кладётся в момент открытия окна, вместе с гашением удара-триггера, а не по факту ответного
удара. Прибавка «в дуэли» стала отдельным компонентом DuelDamageBonusComponent, а не режимом
существующего AllyProximityDamageBonusComponent.
Почему: ответ парирующего — это рекаст, и его можно сорвать станом (так и задумано,
2026-07-31/10). Привяжи награду к ответу — и щит пропадал бы вместе с чужим контролем, хотя отбил
носитель уже в момент окна: платили бы дважды за одно попадание. Компонент отдельный по другой
причине: «Стая» даёт прибавку ЗА каждого союзника и растёт с числом, дуэль — одну прибавку ПО ПОРОГУ
по врагам. Общий компонент потребовал бы двух флагов («союзники или враги» × «за каждого или по
порогу») — четыре режима в одной точке вместо двух ясных правил.
Грабли: порог по врагам считается вокруг НОСИТЕЛЯ, и цель в счёт входит — значит «рядом только
один враг» это _maxEnemies = 1, а не 0. Ошибка тут не ломает бой, а тихо меняет кит: при пороге 0
бонус не включается никогда, при счёте вокруг цели он включался бы, когда дуэлянт в одиночку влез в
чужой строй — ровно наоборот к замыслу. Оба случая из боя не видны, поэтому инвариант ушёл в тест.
Второе: величину щита ищет не float, а ScalableValue — SetValue на поле роняет ассет-скрипт
исключением о типе, а не молча.
Владелец правды: ParryComponent.OnPreDamage (комментарий про момент награды),
DuelDamageBonusComponent, тест DuelBonusTests.