Решили: при переходе авто-атаки на несколько контактов в одном свинге рефанд кулдауна
(AttackCooldownTicks = 0 в Interrupt) положен только свингу, который не нанёс ни одного
контакта. Как только хотя бы один контакт разрешён, прерывание рефанда не даёт — кулдаун идёт от
первого контакта свинга. Промах по ушедшей цели (Evade) считается состоявшимся контактом.
Почему: иначе микростан становится ускорителем. Первый контакт нанесён, свинг рвётся, кулдаун обнуляется — и новый свинг начинается заново с первого контакта, то есть частота первого удара падает с интервала до «стан + замах». Альтернативу «пусть кулдаун тикает и под станом» отвергли: она делает короткие станы бесплатными по темпу и обесценивает контроль как механику. Второй отвергнутый вариант — считать промах пустым свингом: тогда рефанд получал бы кайт, и убегающий ускорял бы того, от кого убегает.
Грабли: инвариант выглядит уже соблюдённым и потому кажется не требующим теста. Сегодня он
держится случайно — стан после удара попадает в ветку Recovery, где кулдаун замирает, а не
рефандится; ветка Interrupt с рефандом при одиночном контакте безобидна. Сломается ровно в тот
момент, когда серия появится, и без guard-теста это пройдёт незамеченным: DPS уползёт только у тех
китов, по кому спамят контроль.
Вторая грабля — из той же темы, но про размещение контактов: правилом авторинга её не закрыть.
Свинг сжимается (attackDurationTicks = min(MaxAttackAnimTicks, intervalTicks)), а скорость
атаки — рантайм-величина, её крутят баффы, поэтому любые два маркера при достаточном сжатии
схлопнутся в один тик, и валидатор клипа в редакторе этого не увидит. Позиции контактов считаются в
нормированном времени клипа × длительность свинга, затем раздвигаются до зазора в один тик; отсюда
потолок атак/сек ≤ TickRate / N для кита с N контактами.
Владелец правды: тест WindupAutoAttackTests.Stun_AfterHit_DoesNotRushNextAttack,
<remarks> у ClipMarkers, реестр звеньев и вердикты — tech/00-meta/tech-debt §3.9.