ООП без трейтов - боль. Колхозим кастомизацию скиллов
Блин, как же в GDScript не хватает хотя бы трейтов.
То есть вот банально - есть у меня класс Action. Это базовый класс для всех действий.
Окей, какие-то действия являются атаками. Можно сделать класс Attack, унаследовать его от Action, и докинуть логику нанесения урона. Казалось бы, антибугурт.
Но некоторые скиллы в моей игре будут иметь таланты. Как у персонажей в доте - на каждой прокачке выбираешь одну из двух пассивок. Только у меня таланты будут на самих скиллах.
Поскольку наследоваться можно только от одного класса, а трейтов в GDScript нет, назревает очевидный вопрос - как мне это реализовать?
- ActionWithTalent + AttackWithTalent? А когда ещё одна фича появится, комбинаторный взрыв делать?
- Вшивать таланты в Action и добавлять флаг
has_talents
, раздувая его реализацию?
В итоге смастерил себе такой колхоз. Добавил в рут класса инстанс Traitor, в который под интересующими ключами добавляю инстансы специальных классов Trait. Traitor автоматически прокидывает в них инфу о юните + дёргает встроенные методы типа _physics_process
, когда таковые дёргаются в юните
То есть, если я хочу, чтобы какой-то Action был прокачиваемой атакой - я навешиваю на него AttackTrait + TalentTrait. В них своя техническая логика (типа ловли коллизий, события прокачки талантов итд), на которую я в дальнейшем могу подписаться в своём RogueHitAction
Правда, это нихрена не трейты на самом деле, так что, наверное, потом переименую. А может, и так оставлю, название мемасное
Только вот редактор эти созданные из кода инстансы классов, очевидно, не увидит. Придётся в этом же коде навешивать события, а не соединять их через GUI. Их не будет видно в дереве нод. И так далее. А ещё пришлось дополнительно дописать шортхэнды для проверок на наличие специфичных трейтов, потому что сделать Action is Attack
тут уже не прокатит
Вообще ООП парадигма в целом ещё со школьных времён вызывает только баттхёрт. Даже если бы тут и были трейты, то назрели бы другие проблемы - например, два трейта имеют один и тот же метод/свойство. Навесил оба - бах, перетёрлось. Или вообще не дало соединить. В итоге сидишь и вместо решения бизнес-задач вот такую шляпу разруливаешь
Гораздо проще работать с простыми статически типизированными объектами, трансформировать их через функции, а логику описывать декларативно через создания связей между событиями. Чо-то типа Effector
А с этими классами, которые вызывают или не вызывают родительские методы, которые нельзя расширить несколькими несвязанными друг с другом фичами, классо-интерфейсами-абстрактнымиклассами-трейтами - вот сколько не смотрел, везде сплошная монструозная еботня с сомнительной пользой, чесслово