Смысл в том, что главная функция dll aka DLLMain вызывается при присоединении DLL к процессу, выгрузке из процесса, создании и удалении каждого потока. Событий много, а инициализацию нужно выполнить в самый первый раз.
Заменённая главная DLLMain:
Code:
_OnAfterWoG db 'OnAfterWoG', 0
_OnCustomDialogEvent db 'OnCustomDialogEvent', 0
_OnBeforeBattleAction db 'OnBeforeBattleAction', 0
_OnAfterBattleAction db 'OnAfterBattleAction', 0
DLL_PROCESS_ATTACH = 1
match =FALSE, COPYMODE
{
proc TYPHON, hDll, Reason, Reserved
; только при подключении dll к процессу, не к потокам
.if dword [Reason] = DLL_PROCESS_ATTACH
; регистрируем обработчики событий
stdcall [RegisterHandler], OnAfterWoG, _OnAfterWoG
stdcall [RegisterHandler], OnCustomDialogEvent, _OnCustomDialogEvent
stdcall [RegisterHandler], OnBeforeBattleAction, _OnBeforeBattleAction
stdcall [RegisterHandler], OnAfterBattleAction, _OnAfterBattleAction
mov dword [761381h], 39859587; Заглушить вог-функцию ResetMonTable,
mov dword [761385h], 3271623302; мешающую редактору существ
mov dword [71180Fh+1], LoadCreatures
.endif
; возвращаем успех инициализации dll
xor eax, eax
inc eax
ret
endp
}
Заменённая процедура установки хуков и патчей:
Code:
; ГЛАВНАЯ ПРОЦЕДУРА
proc OnAfterWoG uses esi edi ebx, Event ; после инициализации WoG
; ставим хуки
mov esi, Table_Hooks
...
; Возврат:
ret
endp
Хук на ProcessErm рушит вообще всё ядро интерпретатора (ускорение, поддержку циклов, !!re, работу с контекстом). Потому его заменил на нормальные три обработчика событий:
Code:
proc OnCustomDialogEvent uses esi edi ebx, Event
.if dword [27F9964h] = 1986; диалог №1986
mov eax, dword [27F9968h]
.if signed eax > 4 & signed eax < 9 & dword [27F996Ch] <> 13
sub eax, 5
mov ecx, [Адрес_параметров_альтерветки_для_диалога_постройки_альтерветок]
mov eax, [eax * 4 + ecx]
xor ecx, ecx
xor edx, edx
inc edx
cmp dword [27F996Ch], 12
jnz .правый_клик
xchg ecx, edx
.правый_клик:
stdcall OpenCreatureWindow, eax, 119, 20, ecx, edx
.elseif (eax = 11 | eax = 13) & dword [27F996Ch] = 13
mov dword [887658h], 1; CloseDialog
.endif
.endif
ret
endp
proc OnBeforeBattleAction uses esi edi ebx, Event
mov ebx, dword [699420h]; COMBAT_MANAGER; ebx теперь хранит CombatManager
mov eax, [ebx + 3Ch]; Тип_действия
mov [Тип_действия_в_бою], eax
call Получить_адрес_структуры_стека_совершающего_действие
mov [Адрес_структуры_стека_совершающего_действие], eax
call Получить_адрес_структуры_стека_на_которого_направлено_действие
mov [Адрес_структуры_стека_на_которого_направлено_действие], eax
ret
endp
proc OnAfterBattleAction uses esi edi ebx, Event
mov ebx, dword [699420h]; COMBAT_MANAGER; ebx теперь хранит CombatManager
mov edi, [Адрес_структуры_стека_совершающего_действие]
mov esi, [Адрес_структуры_стека_на_которого_направлено_действие]
.if [Тип_действия_в_бою] = 7 & signed esi > -1 & signed [esi + Структура_стека.Текущее_количество] > 0 & [edi + Структура_стека.Тип_существа] <> 149; CR_Стрелковая_Башня
mov eax, [esi + Структура_стека.Тип_существа]
cmp byte [eax + RangeRetaliation_Table], 0
je .нет_способности
.есть_способность:
push 0
mov ecx, esi
mov eax, 442610h; проверка возможности стрельбы
call eax
test al, al
je .нет_способности
push edi
mov ecx, esi
mov eax, 43F620h; Стрельба_отряда_по_отряду
call eax
; фикс бага стрельбы уже в мёртвом состоянии, если стеку выпала Мораль
.if signed [edi + Структура_стека.Текущее_количество] < 1; стек убит
bt [edi + Структура_стека.Флаги], 24; Флаг_Отряду_выпала_Мораль; проверка на выпавшую мораль
jnb .нет_Морали
mov dword [ebx + 3Ch], 12; Отмена_действия_отряда
.нет_Морали:
.endif
.нет_способности:
.endif
ret
endp
Скачать Герои 3 Эра и всё, что с ней связано / ERA 2.46f для старых модов
Поддержать проект
|