Решили: въездной замах (старт за границей досягаемости, кадр контакта на входе в неё) выдаётся
КАЖДОМУ подбегающему мили-юниту, а не только набравшему разбег. Признак въезда — своё поле
RuntimeUnit.ChargingIn, отдельное от ChargedSwing. Заряд удара с разбега гаснет при прибытии.
Почему: механизм существовал, но стоял за условием ChargedAttackReady, поэтому работал у
меньшинства: остальные добегали, тормозили и начинали замах уже стоя — удар опаздывал на всю длину
замаха относительно момента, когда дистанции хватило. Альтернатива «чинить только показ, механику
не трогать» отвергнута Максом: она оставила бы расхождение между картинкой и расчётом.
Два поля вместо одного — потому что вопросы разные. ChargingIn отвечает «когда случается удар»
(и по нему движение снимает рут с замаха), ChargedSwing — «каким он выходит» (клип рывка,
укороченный замах). Если бы рут снимался по ChargedSwing, все неразогнавшиеся въезжали бы
зарутованными, то есть замахивались бы в пустоту в двух шагах от цели — ровно тот баг, ради
которого рут когда-то и снимали.
Грабли: StopSprint и AbortSprint различались одним полем — переживает ли заряд конец
разбега. После решения «прибытие тратит заряд» разница исчезла, и два глагола на одно действие
пришлось слить обратно в один: пока их было два, выбор между ними в каждой ветке был молчаливым
решением о механике.
Цена изменения — боевая, а не косметическая: мили начинают бить раньше на длину замаха. Заведено на замер как BAL-019, потому что коридоры DPS считались при старом тайминге.
Владелец правды: AutoAttackSystem.ChargesIntoReach / EnterWindup, RuntimeUnit.ChargingIn,
MovementSystem (рут замаха), тесты ChargeAttackTests —
PlainRunner_AlsoStartsItsWindupOutsideReach и StandingUnit_StaysRooted.