Объявления |
---|
Друзья, если не получается зарегистрироваться, напишите на почту vdv_forever@bk.ru. Я оторву свою задницу от всех дел и обязательно Вас активирую! Добро пожаловать на геройский форум! |
Re: Как создать плагин для HD модаЛюбой подойдёт. Вот это - o_BattleMgr->hex[hex_id].GetCreature() - есть _BattleStack_*.
|
Re: Как создать плагин для HD модаВ общем написал я алгоритм (функция getHexId) отражения для площадных заклов. Плюс еще функцию проверки существ на площадные заклы (checkingTheSelectedTargetForAreaSpells).
Не зависимо от того, какое кол-во отрядов отразило - находится такой гекс для каста, который позволит захватить максимально возможное кол-во вражеских отрядов и ноль, либо как можно меньшее кол-во наших отрядов, если наложить так, чтобы не захватить наши отряды невозможно. Если подобных вариантов несколько, то выбирается такой вариант, где разница между суммарной боевой мощью максимальной группы вражеских отрядов, которую удается захватить, и минимальной группы дружественных отрядов максимальная. Что подобный алгоритм нам дает? Максимум профита. Например, один из наших отрядов, допустим, 10 Копейщиков, стоит между десятком вражеских Архангелов и десятком Титанов, которые стоят по рызные стороны от наших Копейщиков. Враг с приличным навыком СМ кастует на другой наш отряд, который под Зеркалом, Инферно. Если других более выгодных вариантов нет, то в итоге Инферно отразится так, чтобы задеть как Архангелов, так и Титанов. Если это будет возможно сделать так, чтобы не задеть наш отряд Копейщиков, то это будет сделано. Если это будет невозможно, то Инферно накроет и наш отряд, но тот доп урон, который будет нанесен, либо Архангелам, либо Титанам, будет гораздо больше и ценее чем наши 10 Копейщиков. Если же наш ценный отряд, например, в виде 10 Архангелов стоит между различными вражескими отрядами, то Инферно будет аккуратно выплясывать вокруг Архангелов и не задевая их уничтожать все вражеские отряды вокруг в порядке убывания их силы. Вообще интересный алгоритм получился. И как я его только написал... Вообще в эту функцию getHexId можно передавать вместе со спеллом еще и кол-во отрядов, которые отразили закл и вместо максимального значения по отрядам находить в готовом массиве именно нужное кол-во и после среди них (если вариант не один), находить наболее выгодный для атаки. Если будет невозможно развернуть закл на то кол-во вражеских отрядов, которое равно кол-ву отражений, то можно будет уменьшать на 1 отряд до тех пор пока не найдется такое, которое будет меньше нужного, но при этом максимально возможное. Кстати, проверять указатель на 0, было недостаточно, все равно вылетало. Только после того, как дабавил еще проверку на выход за границы поля боя, все стало ок. AlexSpl, а где у вас в функции areaReflection хранится кол-во отрядов, которые отразили направленный закл? 1) Функция проверки существ на площадные заклы checkingTheSelectedTargetForAreaSpells:
2) Функция отражения площадных заклов getHexId (вызывается прямо из areaReflection в вызове CALL_5):
Итоговый код с двумя новыми функциями (плюс мелкое исправление в checkingTheSelectedTarget, шло обращение к несуществующим элементам массива):
После тщательного тестирования имеющегося кода на данный момент обнаружил следующие баги: 1) Звук FIREBALL (Огненный шар) проигрывается уже после проигрывания самой анимации. А должен одновременно с анимацией проигрываться, как у других заклов. С другими ок. 2) Берсерк отражается не эффективно, все из-за отсутствия проверки на иммунитет существ к площадным заклам. Я написал функцию checkingTheSelectedTargetForAreaSpells на площадные заклы, подобно функции для обычных заклов, которая проверяет существ на иммунитет ко всем площадным заклам. Добавьте вызов этой функции в своей реализации Берсерка перед тем, как перенаправлять его на вражеские отряды, чтобы исключить из списка целей всех существ на которых этот закл попросту не наложится. Таким образом мы не будем терять отражения, а будем перенапрявлять их на других существ на которых он наложится (в порядке убывания силы оставшихся отрядов). 3) Дамажащие площадные заклы при касте на своих не отражаються на вражеские отряды, а отражаються обратно на свои. (При этом если у обеих сторон стоит Зеркало, то может быть так, что после отражения на вражеский стек, сам вражеский стек его также отразит, правда уже в никуда. Но тут спорно, а должен ли он его принимать хз. В оригинале, кстати, принимает. Но, думаю, в нашем плагине можно оставить и так). 4) Для Армагеддона нужно анимацию резиста и Зеркала сделать уже после анимации самого Армагеддона. Аналогично боевым площадным заклам. 5) Заклинания нейтралов (отрядов без героя) не отражает на самих же нейтралов. Надо бы сделать, чтобы отражало. AlexSpl писал(а): У Вас получилось его сохранить или могут быть проблемы? 6) Проблемы заметил следующие: Death Ripple - что-то не то со звуком. Звуковое сопровождение от другого закла. В оригинале у него звук другой. Общая СЕРЬЕЗНАЯ проблема Death Ripple и Destroy Undead: Вот здесь вообще забавная штука происходит. Короче, если одним из этих заклов отряд был полностью уничтожен, то картинка живого существа не заменятся на картинку мертвого. Просто исчезает количество и вместо трупака остается висеть якобы живое существо, но без количества. Прямо таки настоящая нежить. Клетка, которою занимал отряд становится свободной (на нее можно стать). AlexSpl писал(а): А это делали? AlexSpl, по свободе исправьте, пожалуйста, вышеперечисленные баги, протестируйте еще со своей стороны мои функции и алгоритмы, отпишитесь о результатах и опубликуйте уже готовый код для финального тестирования. |
Re: Как создать плагин для HD модаПройдусь на этой неделе ещё раз по всем хукам. Что-то уже представляю, как исправить, где-то нужно разбираться (например, с Death Ripple и Destroy Undead ситуация странная).
Цитата: Это сделал для героев AI. Там фишка была в том, что для синглкаста AI пропускается код отражения Magic Mirror. Нейтралов отдельно смотреть нужно, конечно. Цитата: Тут тоже смотреть нужно. В область действия могут попасть как свои, так и чужие отряды под Magic Mirror. Не отражать же два раза? Не знаю, как лучше сделать. Может, от дружественных всё-таки не отражать? |
Re: Как создать плагин для HD модаЦитата: Только тогда возникает вопрос, а что тогда делать с Берсерком? Ведь он то отражается от своих на вражеские отряды. Убирать у него это? Думаю все же, что от дружественных лучше тогда и не отражать. Просто игнор без отражения с проигрыванием анимации Зеркала. Я подобным образом сделал когда в армии кастующего остались существа с иммунитетом от направляемого закла. Можно конечно было сделать на них перенаправление, но смысла в этом нет, так как на них это не подействует, а отряды отразившего, которые могут находится рядом с нашим иммуным монстром могут получить урон. В ином же случае закл будет проигрываться на нулевом гексе (или на -1), что тоже не очень хорошо, особенно в случае с Инферно, так как в этой области также могут находится отряды отразившего. Поэтому пришлось сделать так:
|
Re: Как создать плагин для HD модаРешил взяться за оптимизацию кода и обратил внимание на то, что функции checkingTheSelectedTargetForAreaSpells() и сheckingTheSelectedTarget() проверяют, попадают ли существа в отряде в список монстров, иммунных к заклинанию. Но логичнее это делать с помощью игровой функции, которая чекает разные нюансы. Например, арты (сразу коварная связка Orb of Vulnerability + Black Dragons вспоминается), специализацию героев, террейн:
Функция возвращает число от 0 до 1. Чем меньше, тем лучше (мы уже использовали эту функцию в нашем плагине). 0 означает иммунитет или полную неуязвимость к урону от заклинания, 1 - полную беззащитность. Названия аргументов сами за себя говорят, кроме последних. Первая 1 для того, чтобы учесть сопротивление магии всех отрядов (а не только вражеских; если поставить 0, не будет, например, учитываться резист гномов к касту заклинаний собственного героя), вторую 1 лучше оставить по умолчанию (если я правильно понимаю, этот флаг определяет, для какой стороны считать резисты, 1 - это для casterSide), последний 0 лучше тоже не трогать: аргумент имеет отношение к заклинаниям Resurrection и Animate Dead). |
Re: Как создать плагин для HD модаОбщее исправление порядка анимации. Теперь первой идёт анимация заклинания, потом резиста, потом Magic Mirror. Логично показывать анимацию Magic Mirror в самом конце, так как именно после неё идёт перенаправление заклинания на вражеский отряд или в пустоту. А какую анимацию показывать первой - анимацию заклинания или резиста - в условиях отсутствия одновременной анимации, считаю, вопрос вкуса (всегда можно поменять: там просто блоки кода местами переставить).
Цитата: Сделал для дружественных отрядов, попавших в область действия площадного дамажащего заклинания, отражение в пустоту. Цитата: Решил, что пусть так будет для всех заклинаний. Цитата: Пишет, что проигрывает заклинание Death Ripple и звук Deathrip.wav Цитата: Исправил. Совсем забыл про последний аргумент в функции воспроизведения массового заклинания после того, как для остальных дамажащих заклинаний его изменение не потребовалось. Его установка приводит к тому, что при масскасте проигрывается анимация получения урона и гибели. Цитата: Я добавил функцию isImmune() для определения иммунитета отрядов и переписал две Ваши, которые делали то же самое. Её можно использовать и для Берсерка в функции getEnemyStackToRedirectTo(). Заклинания нейтралов пока не смотрел. Для Чародеев, проверил, отражает. UPD: Добавил в функцию magicMirrorLucky() проверку на иммунитет. Смысл такой: например, на Золотых драконов можно повесить Magic Mirror, но не Slow, поэтому отряд не должен отражать также и массовую версию Slow. Более яркий пример: кастанули Destroy Undead, копейщики не должны его отражать. * * * Rolex, а почему у Вас площадные заклинания на свои отряды отражаются? Функция поиска гекса - это Ваш участок кода. * * * Всё-таки вернул для массовых залинаний прежний порядок анимаций. Для площадных ударных сделал рандомное отражение пока. Где-то ошибка в Вашем коде, либо я напортачил при переносе. * * * Кажись, починил Что-то пошло не так при переносе. Есть ещё вопрос по Frost Ring. Дырку от бублика учитываете? Ага, вижу, порядком обхода гексов Для тех, кто не хочет собирать, но хочет присоединиться к тестированию: |
Re: Как создать плагин для HD модаAlexSpl писал(а): Такое могло быть и на это может быть 3 причины: 1) У Вас была безвыходная ситуация и ответить так, чтобы не задеть свой отряд было невозможно. 2) Ответ с атакой своего слабого отряда был выгоден в той ситуации, чтобы задеть дополнительно вражеский более сильный. 3) Вы столкнулись с багом двухклеточных сеществ над фиксом которого я работал последнее время. Вероятней всего из-за бага. Плюс там еще был баг связанный с гексами, которые находятся на двух невидимых вертикалях для боевых машин. Сейчас они не проверяються и не могут быть выбраны в качестве епицентра для закла. Ну а о проблеме двухклеточных существ я расскажу подробней. Уже на следующий день после публикации поста здесь с функцией getHexId, я обнаружил, что в некоторых сутуациях гекс для отражение выбирается не оптимально. Подобное происходило только в тех случаях, когда в область действия закла попадала только одна клетка, то есть половина двухклеточного существа. В первой версии getHexId для двухклеточных существ был реализован булевый переключатель, который считал только первое вхождение одной из частей двухклеточного существа и ставил флаг из false в true, а при повторном заходе ставил флаг в false. И это в принципе работало если двухклеточное существо полностю входило в область атаки или же наполовину входящим было только одно существо. В последнем случае булевый переключатель просто не закрывался, но он обнулялся в цикле на следующей итерации. Универсальное решение подобной задачи оказалось непростым и куда сложнее чем я ожидал. Сравнить позиции двух двухклеточных существ не прошло бы. Дело в том, что мы не знаем какая-часть существа у нас. И если допустим 2 двухклеточных одинаковых существа с одинаковых кол-вом стоят рядом друг с другом, то, например, тот же Метеоритный дождь своими двумя верхними гексами может цеплять вторую часть первого двухклеточго существа и первую часть второго. А мы принимает это за одно двухклеточное существо. Проверять соседние гексы не вариант, так как за уже имеющимися могут стоять в плотную такие же. Вот, например, в этих ситуациях первая версия getHexId выбирала не оптимальный гекс для атаки (оптимальный выделен). А вот безвыходная ситуация, где отряд сбоку будет задет Инферно в любом случае. Решение придумал следующее: Для горизонтали на которой находится проверямый гекс эпицентр, а также для двух горизонталей выше и для двух ниже я генерирую массив типа vector <pair<int, _BattleStack_*>>, где в first у нас хранится число, которое для каждого монстра на проверяемой горизонтале будет свое. Проверяються только двухклеточные существа, соответственно у каждого существа будет свой уникальный ID, но у каждого из них их будет два, под каждую клетку. Даже если существа имеют одинаковый CID, но это разные существа, которые находятся в разных позициях, то у каждого будет свой идентификатор. В second же мы складываем указатели на каждого монстра, чтобы потом без проблем получить CID, count и fight_value, так как мы храним и сравниваем еще и суммарную боевую мощь отрядов, которые попадают в область атаки. После чего уже проверяется соседные от эпицентра клетки по радиусу закла и считается кол-во именно разных. По сути максимальное значение и будет кол-вом разных, но так как нам еще нужна и сумма fight_value по каждому существу в заданной области, то приходится проходиться по всем отрядам в области и суммировать их силу. В общем теперь одноклеточные и двухклеточные и их боевая мощь считаються отдельно и по-разному, но в итоге результаты суммируються. Также подправил алгоритм выбора цели. Если в предыдущей версии при нескольких варинтах с одинаковым количеством предпочтение отдавалось той группе отрядов, которая не цепляет свой отряд или цепляет меньшее количество наших отрядов, то сейчас немного иначе. Сейчас, например, между вариантом 2 вражеских и 1 наш против просто 2 вражеских может быть выбран и первый варинт, но только в том случае, если он будет более выгодный чем второй с точки зрения суммарной разницы fight_value между вражескими отрядами и нашими отрядами, которые попадают в область атаки. Например, наши 10 Копейщиков стоят между вражескими Архангелами и Титанами и в тоже время есть еще один вариант для атаки 2 вражеских отрядов, который не требует атаки нашего отряда, это, например, два слабых отряда небольшого кол-ва Кентавры и Гномы. Так вот первая версия getHexId отдавала предпочтение второму варинту (после уже сравнивалась суммарная сила отрядов аналогичных вариантов). А вот в этой версии, если боевая мощь Титаны + Архангели - Копейщики с учетом их кол-ва в каждом отряде будет больше суммарной мощи отрядов Кентавров и Гномов, то будет выбран первый вариант с атакой нашего отряда, и только в ином случае второй вариант. В итоге код стал больше и сложнее, но главное, чтобы все работало правильно. Исправленная и протестированная функция getHexId:
|
Re: Как создать плагин для HD модаМожно легко посчитать кол-во отрядов, попадающих в область действия заклинания, если проверять гексы области слева направо и сверху вниз.
Здесь i - индекс гекса в массиве гексов, входящих в область заклинания. Т.е. в цикле мы инкрементируем i, а если заметили, что на гексе справа тот же стек, дополнительно икрементируем i. Тут даже [i + stack->side == 0 ? 1 : -1] не нужно (мы же слева направо идём). Просто [i + 1]. Последний раз редактировалось AlexSpl 30 мар 2021, 18:32, всего редактировалось 1 раз.
|
Re: Как создать плагин для HD модаAlexSpl писал(а): Можете оптимизировать код. Для меня главное, чтобы правильно работало. Свой я протестил уже. AlexSpl писал(а): А это правили? AlexSpl писал(а): Отключите все плагины и проверьте звук в оригинале. Там другой более резкий звук. Может их два. Или это баг оригинала. Но я как-то к тому привык. Этот вообще незаметен. Я проверю что за звук проигрывается и отпишусь. Rolex писал(а): Надо бы и это добивать уже. И уже после можно выкладывать на тестирование. |
Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 2