Архитектурный косяк или как я забыл, что один скилл может иметь несколько зон поражения
Столкнулся с одной проблемой и удивился, как до сих пор на это не напоролся
Если вкратце, то у скиллов/перков есть сущность TargetStore
- В него добавляются юниты, которые попадают в зону поражения (ну или по любому другому условию)
- В этом же сторе прописывается условие, каких юнитов фильтровать (например, только врагов, или юнитов с меткой)
- После чего
TargetStoreтриггерит события о добавлении/удалении юнитов, и на них уже навешиваются всякие эффекты (например, нанести демедж, повесить статус итд)
Так вот, я сделал скилл наподобие Ирдена из Ведьмака. Он спавнит зону. Вошедшие в неё юниты получают замедление, которое снимается по выходу, либо по окончанию действия зоны
Дальше я захотел сделать перк, который понижает откат настолько, что одновременно может быть две зоны
Но вот незадача - TargetStore один на скилл. И когда зона деспавнится, вычищаются в том числе и юниты, стоящие в другой зоне))
В итоге перепиливаю этот кусок так, чтобы TargetStore принадлежал зонам, а не скиллам/перкам, но пока что выглядит оно костыльно
Вообще это довольно печальный момент. Потому что я до этого понаписал кучу декларативных пресетов, из которых легко собирались скиллы любой конфигурации
Вот, например, скилл-милишная тычка:
- Скорость атаки (с отдельным таймером на длительность, на промежуток между атаками и даже на подготовительную АоЕшку, если нужно). Полностью кастомизируется по необходимости
- Зона поражения, которая трекает только юнитов, враждебных к конкретному
- Отдельная сущность для нанесения урона, с возможностью декларативно модифицировать урон и подписываться на события нанесения/убийства/итд
Каждый пресет под капотом создаёт нужные подписки на события и дёргает методы
Например, вот пресет для соединения скорости атаки с активатором скилла:
Как видите, из 5 пресетов в этом скилле 3 относятся к TargetStore
С его переносом из скилла в зону будет менее изящно. Как бы вся эта декларативная красота не рухнула от необходимости где-то в рантайме подписку создать
UPD: Actually, обошлось малой кровью. И получилось даже меньше кода, чем на первом скрине. Ибо в скиллах удалился HitAreaPreset.StoresTargets и TargetPreset.CleanupOnFinish
Теперь, раз TargetStore лежит в зоне, она же и будет автоматически заполнять/очищать стор
Да, здесь теряется возможность "придержать" список юнитов после отключения/деспавна зоны. Но, в то же время, ничто не мешает создать для такой задачи ещё один TargetStore уже внутри скилла. Но тут мы вернёмся к изначальной проблеме "один стор на все зоны"))
Это уже, конечно, overthinking. Не думаю, что такие случаи вообще появятся. К тому же, всегда можно подкорректировать гейм-дизайн
Например, в самом первом прототипе у роги должен был быть перк, с которым тычка критует в спину
Но, поскольку ассеты в игре чисто с видом сбоку, а юниты могут смотреть на 360, вопрос "а что есть спина" был неочевидным
По итогу "криты в спину" заменились на "дэш через моба навешивает оглушение" + "тычка критует по оглушению". С точки зрения действий игрока - результат по сути тот же. С точки зрения реализации - совсем другое
Есть один неприятный момент. При клонировании ноды с зоной, к сожалению, создаётся чистый TargetStore, а не клон того, который в ней был до этого
Это плохо, поскольку я хотел статично навешивать на "родительский" стор все нужные пресеты, и надеялся, что при клонировании оно всё продублируется
К счастью,DSubscribe умеет принимать не только DEvent напрямую, но и любой DTrigger, который при вызове вернёт DEvent. Как-то это в ФП по-умному называется, но вертел я, честно говоря, эти термины
Посему я просто сделал пресет, который подписывается на спавн зоны, вытаскивает из ноды тамошний таргет стор и создаёт подписки на все интересующие ивенты:
Этот пресет сохранит декларативность в скиллах, когда мы создаём простую подписку
Но, к сожалению, с пресатами такое не прокатит
С пресетами придётся подписываться на спавн уже в самом скилле и докидывать интересующие пресеты внутри функции:
Но, в целом, не так уж и страшно
Вообще, можно было бы параметр TargetStore сделать триггером, и тогда была бы возможна вот такая запись:
Но тогда придётся переписать все пресеты, которые относятся к TargetStore
Так что пока придётся смириться с коллбеком в декларации
Спасибо, что дочитал до конца! Лови пару скриншотов: