(11.11.2025 21:09)daemon_n Wrote: [ -> ] (11.11.2025 12:25)XEPOMAHT Wrote: [ -> ]Так же у тебя отсутствует получение максимального количества героев в игре, т.е. данный код с Тифоном несовместим:
Code:
if (heroID >= 0 && heroID < 156)
Как именно (откуда и когда) предлагаешь получать число героев?
В теме базовой адресации можно узнать:
(03.12.2021 23:32)XEPOMAHT Wrote: [ -> ]2. Структура героев:
* Базовый адрес - не потребуется, т.к. в рамках совместимости с плагинами он сохранён неизменным.
* Количество героев в игре = [4BD145h]
Считывать адрес можно после триггера AfterWog, но не в самом триггере, т.к. Тифон все патчи ставит после эровского AfterWog.
(11.11.2025 12:25)XEPOMAHT Wrote: [ -> ]текст сообщения
Всё исправил, но "полуросликов" заменил на
Code:
if (Era::IsCommanderId(stack->creature_id))
{
// может иметь двойную атаку
c->return_address = 0x441BB1;
}
UPD: Сборка обновлена:
Вот ссылка на файл .dll:
game bug fixes extended.dll
Вот ссылка на файл .dbgmap:
game bug fixes extended.dbgmap
(13.11.2025 06:31)daemon_n Wrote: [ -> ] if (Era::IsCommanderId(stack->creature_id))
Спасибо, теперь осталось узнать у Берсеркера, откуда он берёт IsCommanderId, т.к. в исходниках ЭРЫ я ничего об этом не нашёл. В ERA+ командиры имеют индексы 174..186 (левосторонние) и 256..268 (правосторонние), ну и в Тифоне командиры тоже никак не помечены аналогично ВоГ-у.
(13.11.2025 06:31)daemon_n Wrote: [ -> ]Сборка обновлена:
Спасибо за поддерку!
Code:
function IsCommanderId (MonId: integer): TInt32Bool; stdcall;
function SetIsCommanderIdFunc (NewImpl: TIsCommanderIdFunc): {n} TIsCommanderIdFunc; stdcall;
function IsCommanderId (MonId: integer): TInt32Bool; stdcall;
begin
result := IsCommanderIdFunc(MonId);
end;
function SetIsCommanderIdFunc (NewImpl: TIsCommanderIdFunc): {n} TIsCommanderIdFunc; stdcall;
begin
result := @IsCommanderIdFunc;
IsCommanderIdFunc := @NewImpl;
end;
function ImplIsCommanderId (MonId: integer): TInt32Bool; stdcall;
begin
result := ord((MonId >= Heroes.MON_COMMANDER_FIRST_A) and (MonId <= Heroes.MON_COMMANDER_LAST_D));
end;
Это функция, которую можно заменить на свою, вызвав SetIsCommanderIdFunc и передав адрес новой функции с тем же соглашением вызова (stdcall).
По умолчанию сравнивает ИД монстра с начальным и конечным ИД командиров в вог 3.58. Но моды-расширения могут её заменить.
Так же последняя версия плагина "wog native dialogs.era" начала терять текст в команде "!!IF:D#/$1/$2/$3/$4/$5/$6/$7/$8/$9/$10/$11/$12/$13/$14/$15", а именно здесь:
Code:
$12 – выбор 1 (окно ввода) – текст кнопки
$13 – выбор 2 (окно ввода) – текст кнопки
$14 – выбор 3 (окно ввода) – текст кнопки
$15 – выбор 4 (окно ввода) – текст кнопки
Пример ERM-команды, в которой плагин теряет текст (не с 1 раза, а обычно с 3 при вызове команды в разных местах, если вызывать в 1, т.е. один и тот же по нескольку раз, то вылета нет):
Code:
!!IF:D99/z100040/0/z100041/^Zmap%X2.pcx^/0/0/0/z1/0/0/0/z100042/z100043/z100044/z100045 E1/99;
К сожалению, старую версию плагина от Игрика последняя ЭРА не грузит без объяснения причин (старая ЭРА ругалась при фаталити в загрузке плагина, новая - предательски молчит), поэтому проверить эту утечку памяти там невозможно (но на моей памяти версия от Игрика с такой ошибкой не вылетала).
Без плагина (т.е. через zvslib1.dll) текст не теряется.
По итогу, "wog native dialogs.era" не может выгрузить текстовые переменные и падает:
Failed to read data at 5.
EIP: H3era.005BCB11. Code: C0000005
> Game context: [Adventure Map] dialog
> Registers
EAX: 00000001 (int: 1)
ECX: 0EBFDFD0 (int: 247455696, pint: 0x00000001)
EDX: 00000054 (int: 84)
EBX: 11529650 (int: 290625104, pint: 0x05AC0770 = 95160176)
ESP: 00223AF0 (int: 2243312, pint: 0x03663D70 = 57032048)
EBP: 00223B04 (int: 2243332, pint: 0x00223B10 = 2243344)
ESI: 03663D70 (int: 57032048, pint: 0x00643CA0 = 6569120)
EDI: 0F1708EC (int: 253167852, pint: 0x03663D70 = 57032048)
> Callstack
H3era.005BCABB
H3era.005FFAEE
Wog native dialogs.B58A
Wog native dialogs.B992
03081204
Era.5164D
Era.96E92
0364A407
Era.94CE0
036C73B5
H3era.0074CE60
Era.9997F
0364A65F
H3era.007493CC
Era.94CE0
036C73B5
H3era.0074D616
Typhon.10ABD
Artguard.142A
44000000
8BFC2083
> Stack
00223ADC: 00000000 (int: 0)
00223AE0: 00000000 (int: 0)
00223AE4: 00000000 (int: 0)
00223AE8: 00000000 (int: 0)
00223AEC: 00000000 (int: 0)
00223AF0*: 03663D70 (int: 57032048, pint: 0x00643CA0 = 6569120)
00223AF4: 03663D70 (int: 57032048, pint: 0x00643CA0 = 6569120)
00223AF8: 00223BC4 (int: 2243524, pint: 0x00223E88 = 2244232)
00223AFC: H3era.00635303 (int: 6509315, pint: 0x656E10B8 = 1701712056)
00223B00: FFFFFFFF (int: -1)
00223B04: 00223B10 (int: 2243344, pint: 0x00223B28 = 2243368)
00223B08: H3era.005BCABB (int: 6015675, pint: 0x010845F6 = 17319414)
00223B0C: 11529650 (int: 290625104, pint: 0x05AC0770 = 95160176)
00223B10: 00223B28 (int: 2243368, pint: 0x00223BD0 = 2243536)
00223B14: H3era.005FFAEE (int: 6290158, pint: 0x8338468B)
00223B18: 00000001 (int: 1)
00223B1C: 00223BE8 (int: 2243560, pint: 0x03BD7BA8 = 62749608)
00223B20: 03663798 (int: 57030552, pint: 0x00642DF8 = 6565368)
00223B24: 11529650 (int: 290625104, pint: 0x05AC0770 = 95160176)
00223B28: 00223BD0 (int: 2243536, pint: 0x00223E4C = 2244172)
00223B2C: Wog native dialogs.B58A (int: 95008138, pint: 0xCB8B038B)
00223B30: 4D852AE8 (int: 1300572904)
00223B34: 00000001 (int: 1)
00223B38: H3era.0050CEA0 (int: 5295776, pint: 0xB9833FE9)
00223B3C: 00223EB4 (int: 2244276, pint: 0x039165A0 = 59860384)
00223B40: 00000000 (int: 0)
00223B44: 000000C8 (int: 200)
00223B48: 00223B58 (int: 2243416, pint: 0x00000010 = 16)
00223B4C: 00000190 (int: 400)
00223B50: 00000087 (int: 135)
00223B54: Era.357BEC (int: 62749676, pint: 0xE5E3E0CB, str: "Лагерь Беженцев\x00")
00223B58: 00000010 (int: 16)
00223B5C: 00000004 (int: 4)
00223B60: 036E6530 (int: 57566512, pint: 0x00000000)
00223B64: 00000064 (int: 100)
00223B68: 00000001 (int: 1)
00223B6C: 00000001 (int: 1)
00223B70: 000000DF (int: 223)
00223B74: 00000017 (int: 23)
00223B78: 000001EE (int: 494)
Посмотрел по исходному коду плагина.
Данный код, с проверкой на itemText, работает всегда:
Code:
itemText = (_DlgStaticTextPcx8ed_*)dlg->GetItem(19+i);
if (itemText)
{
itemText->font = (int)smalfont2;
itemText->color = 1;
}
}
А дальше - код фигачит изменения шрифта и цвета уже без проверки на существование самого текста:
Code:
((_DlgStaticTextPcx8ed_*)dlg->GetItem(msg->item_id +4))->font = (int)medfont2;
((_DlgStaticTextPcx8ed_*)dlg->GetItem(msg->item_id +4))->color = 7;
По крайней мере мне это кажется подозрительным, ибо я не могу найти причину пропадания текста при клике мыши по кнопке диалога и вылете при попытке выгрузить воговский диалог из "wog native dialogs.era". Вылетает, даже если просто ничего не выделять и нажать отмену, но там по крэшлогу - уже чистая утечка памяти в какое-то молоко.
XEPOMAHT, проблема с этим диалогом вскрылась, когда я исправил утечку памяти, вызванную отсутствием удаления виджетов при закрытии диалогов. Без этого исправления текст просто не удалялся из-за памяти, а потому и казалось, что всё нормально. Сейчас посмотрю, что вызывает описанное тобой поведение. Спасибо за наводки

XEPOMAHT, а ведь репорт говорит о двойном удалении картинок, судя по всему.
Попробую убрать "лишнее" удаление.
UPD: проблему удалось воспроизвести -- исследую
UPD:
UPD: В общем, дело в том, что
igrik прописал переназначение шрифта на уже загруженный образец, хранимый в памяти, но с новой (корректной) функцией очистки памяти уже загруженный шрифт (который постоянно должен быть в памяти) удалялся, но не занулялся (хотя ни то, ни другое не должно происходить).
Я решил проблему добавлением метода установки шрифта, хотя есть и вариант просто сохранять ссылки на оригинальный (созданный в конструкторе диалога), а в деструкторе возвращать ссылки на них, но то дольше кодить. Так что будем "жрать" оперативу при каждом клике по элементу с выбором
Code:
void inline SetFont(char* font_name)
{
if (font && (!font_name || CALL_2(int, __cdecl , 0x6197C0, font->name , font_name))) // сравниваем имена шрифтов, если таковые имеются (__strcmpi)
{
font->DerefOrDestruct();
font = NULL;
}
if (!font && font_name)
{
font = _Fnt_::Load(font_name);
}
}
Code:
if (msg->item_id >= 15 && msg->item_id <= 18)
{
_DlgItem_* item;
_DlgStaticTextPcx8ed_* itemText;
for (int i = 0; i < 4; i++)
{
item = dlg->GetItem(25+i);
if (item) { item->SendCommand(6, 4); }
itemText = (_DlgStaticTextPcx8ed_*)dlg->GetItem(19+i);
if (itemText)
{
itemText->SetFont(n_SmallFont);
itemText->color = 1;
}
}
dlg->GetItem(msg->item_id +10)->SendCommand(5, 4);
_DlgStaticTextPcx8ed_* selectedText = (_DlgStaticTextPcx8ed_*)dlg->GetItem(msg->item_id + 4);
if (selectedText)
{
selectedText->SetFont(n_MedFont);
selectedText->color = 7;
}
o_Sphinx1->SelItm = msg->item_id -14;
dlg->GetItem(DIID_OK)->SetEnabled(1);
dlg->Redraw();
}
P.S.: теоретически такая же проблема должна возникать и в меню WoG-опций,
но я пока не встречал.
АХАХАХ. ДА!!! Если закрыть диалог, когда мышка наведена на элемент меню (отображается не родной шрифт), текст так же пропадёт, а игра вылетит через пару раз.
В общем, это тоже
исправлю сейчас исправил (дел на 1 минуту)
P.P.S.:
XEPOMAHT, ты просто красавчик -- отличная находка и подсказка

Так как я не понимаю смысла вашего действа - зашёл просто спросить)))
А зачем удалять шрифт из памяти и постоянно его грузит/удалять?
Я грузил его один раз при старте игры, чтобы не заниматься постоянной загрузкой/выгрузкой. Причём я брал пример с того, как это делается с оригинальными игровыми шрифтами
Code:
int __stdcall Y_Hook_MainLoop(LoHook* h, HookContext* c)
{
n_BigFont = GetEraJSON("wnd.fonts.big_font");
n_MedFont = GetEraJSON("wnd.fonts.med_font");
n_SmallFont = GetEraJSON("wnd.fonts.small_font");
// загружаем необходимые русскоязычные игровые шрифты
bigfont2 = _Fnt_::Load(n_BigFont);
medfont2 = _Fnt_::Load(n_MedFont);
smalfont2 = _Fnt_::Load(n_SmallFont);
}
igrik, с того, что закрытие диалога подразумевает удаление из памяти и виджетов, и загруженных ими ассетов.
Ранее виджеты не удалялись из памяти, поэтому эта проблема не возникала (утечка памяти).
Помещённые указатели на шрифт в глобальных переменных никто и не удаляет – это происходило автоматически, когда эти указатели помещались в виджеты временных диалогов.
Оригинальный код подразумевает загрузку шрифта каждый раз, когда создаётся текстовый элемент, и выгрузку — при удалении. Так что при смене одного ассета на другой должны корректно и последовательно выполняться обе эти операции (касается смены любых ассетов. Хорошо видно на примере смены def/wav у стеков в битве)
Тем более, что удаление — это просто уменьшение счётчика.
И потому проблема возникала не сразу (не после первой замены указателя на шрифт). Счётчик не того шрифта обнулялся, и происходило удаление ресурса из памяти.