Иногда картоделы нуждаются в возможности дать какому-либо юнита способность, но при этом не показывать команду на панели приказов.
К сожалению, игра не предоставляет такую возможность, так что приходится идти на хитрости.
К сожалению, игра не предоставляет такую возможность, так что приходится идти на хитрости.
Особые координаты
У каждой способности есть настраиваемые координаты для кнопки.
Обычно их значения находятся в диапазоне 0..3 для X и 0..2 для Y.
Если выйти за их пределы, то игра начнет лазить по памяти за пределами массива кнопок и обычно это приводит к крашу, а если не повезёт, то к трудноуловимым багам.
Обычно их значения находятся в диапазоне 0..3 для X и 0..2 для Y.
Если выйти за их пределы, то игра начнет лазить по памяти за пределами массива кнопок и обычно это приводит к крашу, а если не повезёт, то к трудноуловимым багам.
Но нашлись такие значения, который позволяют скрыть кнопку и при этом не приводят к крашу. Среди них есть и такие, которые обычно работают правильно, но иногда приводят к проблемам.
Тестировалось на версии игры 1.26a. На других версиях поведение может отличаться.
0, -11
При Y равным -11 игра отнимает от указателя на массив рядов (каждый ряд это объект-список, содержащий указатели на CSimpleFrame) число 0xA8. В моем случае, получился указатель на начало региона памяти, в котором содержался этот самый массив (сигнатура региона ".?AV?$TSGrowableArray@PAVCSimpleFrame@@@@:-2").
Там находятся служебные данные менеджера памяти.
Думая, что там указатель на массив указателей на кнопки, игра считывает первое число (но на самом деле это указатель на следующий регион памяти, в моём случае ".\CGameUI.cpp:370", содержащий память для экземпляров класса CPortraitButton)
Думая, что там указатель на массив указателей на кнопки, игра считывает первое число (но на самом деле это указатель на следующий регион памяти, в моём случае ".\CGameUI.cpp:370", содержащий память для экземпляров класса CPortraitButton)
Если координата X равна 0, то берется первый элемент этого "массива", которым опять оказывается указатель на следующий регион памяти (у меня попался ".\SprAnimList.cpp:88", содержащий память для экземпляров класса CAnimList).
Игра работает с заголовком этого региона как с кнопкой.
По смещению 0x94 в кнопке находится поле Visible, которое и проверяет игра.
Если кнопку видно, то она начинает искать следующую, но видя кривые координаты отказывается что либо показывать и завершает выполнение функции.
Если же кнопку не видно (значение поля равняется нулю), то игра поместит в неё требуемую команду, перезаписав для этого все необходимые поля, но беда в том, что не кнопка это, а случайная память, изменение которой приведет к непредсказуемым последствиям.
По смещению 0x94 в кнопке находится поле Visible, которое и проверяет игра.
Если кнопку видно, то она начинает искать следующую, но видя кривые координаты отказывается что либо показывать и завершает выполнение функции.
Если же кнопку не видно (значение поля равняется нулю), то игра поместит в неё требуемую команду, перезаписав для этого все необходимые поля, но беда в том, что не кнопка это, а случайная память, изменение которой приведет к непредсказуемым последствиям.
При чтении поля CCommandButton.Visible, на самом деле читалось поле CAnimList.HashNode1.Previous, которое указывало на другой узел связного списка по адресу 0x0B0001FC. Так как это значение отлично от нуля, то интерпретировалось игрой как TRUE.
На этот раз пронесло, но при каждом перезапуске игры есть шанс, что случится беда.
И вовсе необязательно произойдет немедленный краш, вполне возможно, что повреждение случайной памяти приведет к возникновению самых разных багов в карте.
И вовсе необязательно произойдет немедленный краш, вполне возможно, что повреждение случайной памяти приведет к возникновению самых разных багов в карте.
-2147483648, -2147483648
Эти координаты приводят игру к первой кнопке (слева сверху, координаты 0, 0).
Если этот слот не занят, то кнопка помещается туда, а иначе идёт поиск другого свободного слота, но там как координаты кривые, то цикл сразу завершается и команда не показывается.
Если этот слот не занят, то кнопка помещается туда, а иначе идёт поиск другого свободного слота, но там как координаты кривые, то цикл сразу завершается и команда не показывается.
Смотрится безопаснее предыдущего варианта, но даже если на моей версии игры это работает, то кто знает, что может случиться в прошлых, будущих или даже в моей текущей, если будет установлен какой-нибудь мод, модифицирующий участок кода игры, отвечающий за показ кнопок — он может оказаться не готовым к таким значениям координат.
Страдания игроков
Так как уже могло успеть появиться много карт, использующих кривые координаты, то их игрокам придется столкнуться со сложностями.
Чтобы предотвратить возможные проблемы, я сделал мод, который добавляет фильтр на панель приказов, который игнорирует все команды, координаты которых выходят за допустимые пределы.
Чтобы предотвратить возможные проблемы, я сделал мод, который добавляет фильтр на панель приказов, который игнорирует все команды, координаты которых выходят за допустимые пределы.
Предлагается добавить их к себе в варик через Mix?
Только другие то игроки не будут себе это добавлять и какой тогда в этом смысл?))
А если собираться играть компанией, то можно договориться заранее всем поставить этот мод.
Можно скрыть только Мув и патруль. При других ситуациях возникают краши.
Обидно, досадно, но ничего не поделаешь!
Ред. makkad
Ред. SсRealm
Кроме того для каждой новой такой карты нужен отдельный микс с файлами, что вообще никому не интересно!