Неужели кто-то вспомнил о Messages.dll? А ведь эта библиотека всю дорогу шла вместе с Buttons.dll. И исходники их тоже рядышком лежали. И в инструкции по использованию эта длл упоминалась и расписывалась.
LIBRARY Messages;
{!INFO
MODULENAME = 'Messages'
VERSION = '1'
AUTHOR = 'Master Of Puppets'
DESCRIPTION = 'DLL для использования пользовательских картинок в сообщений Героев 3'
}
USES Win;
CONST
(* HookCode constants *)
C_HOOKTYPE_JUMP = FALSE;
C_HOOKTYPE_CALL = TRUE;
C_OPCODE_JUMP = $E9;
C_OPCODE_CALL = $E8;
C_UNIHOOK_SIZE = 5;
C_MOP_DLLNAME = 'Messages.dll';
TYPE
THookRec = RECORD Opcode: BYTE; Ofs: INTEGER;
END; // .record THookRec
VAR
hMessages: Win.THandle; // Дескриптор библиотеки
TxtName: STRING = 'TypeMsgs.txt'; //название используемого текстового ресурса
PointerOfTable: INTEGER; //используется для хранения указателя на загруженный текстовик
Temp: INTEGER; //универсальная временная переменная
PROCEDURE WriteAtCode(P: POINTER; Buf: POINTER; Count: INTEGER);
BEGIN
Win.VirtualProtect(P, Count, PAGE_READWRITE, @Temp);
Win.CopyMemory(P, Buf, Count);
Win.VirtualProtect(P, Count, Temp, NIL);
END; // .procedure WriteAtCode
PROCEDURE HookCode(P: POINTER; NewAddr: POINTER; UseCall: BOOLEAN);
VAR
HookRec: THookRec;
BEGIN
IF UseCall THEN BEGIN HookRec.Opcode:=C_OPCODE_CALL;
END // .if
ELSE BEGIN HookRec.Opcode:=C_OPCODE_JUMP;
END; // .else
HookRec.Ofs:=INTEGER(NewAddr)-INTEGER(P)-C_UNIHOOK_SIZE;
WriteAtCode(P, @HookRec, 5);
END; // .procedure HookCode
//Функция загрузки текстовика
PROCEDURE MSGTABLE; ASSEMBLER;
ASM
MOV ECX, TxtName //название текстовика
MOV EAX, $55C2B0
CALL EAX
TEST EAX, EAX
JNZ @@TRUE
XOR AL, AL
RET
@@TRUE:
MOV ECX, [EAX+$20]
MOV [PointerOfTable], ECX
MOV AL, 1
END; // .PROCEDURE MSGTABLE
PROCEDURE TXTLoad; ASSEMBLER;
ASM
JE @@Error //случай ошибки загрузки предыдущего текстовика
CALL MSGTABLE //вызов функции загрузки текстовика
TEST AL, AL
JNZ @@Continuation //файл успешно загружен
@@Error: //ошибка загрузки
PUSH $4EE006 // прыжок на вывод сообщения об ошибке
RET
@@Continuation:
PUSH $4EDEF0 //возврат в код игры
END; // .PROCEDURE TXTLoad
PROCEDURE MainMessages; ASSEMBLER;
ASM
JNZ @@OK
PUSH $4F6388
RET
@@OK:
CMP EDI, 100
JE @@OK2
PUSH $4F558A
RET
@@OK2:
PUSH 1
MOV ECX, [PointerOfTable]
MOV ECX, [ECX+EAX*4+4]
MOV ECX, [ECX+4]
MOV ESI, [ECX+8] //текст под картинкой
OR ECX, $FFFFFFFF
XOR EAX,EAX
MOV EDI,ESI
LEA EDX,DWORD PTR DS:[EBX+$18]
REPNE SCASB
NOT ECX
DEC ECX
MOV [EBP+8],ECX
PUSH ECX
MOV ECX,EDX
MOV EAX, $404A40
CALL EAX
TEST AL,AL
JE @@trampam
MOV ECX, [EBP+8]
MOV EDI, [EBX+$1C]
LEA EAX, [EBX+$18]
MOV EDX,ECX
SHR ECX,2
REP MOVSD
MOV ECX,EDX
AND ECX,3
REP MOVSD
MOV ECX,EDX
PUSH ECX
MOV ECX,EAX
MOV EAX, $404A20
CALL EAX
@@trampam:
MOV EDI, [EBX+4]
MOV ECX, [PointerOfTable]
MOV ECX, [ECX+EDI*4+4]
MOV ECX, [ECX+4]
MOV EDI, [ECX] //деф
OR ECX, $FFFFFFFF
XOR EAX,EAX
LEA EDX,[EBX+8]
REPNE SCASB
NOT ECX
DEC ECX
PUSH 1
MOV [EBP+8],ECX
PUSH ECX
MOV ECX,EDX
MOV EAX, $404A40
CALL EAX
TEST AL,AL
JE @@LALA
MOV ESI, [EBX+4]
MOV ECX, [PointerOfTable]
MOV ECX, [ECX+ESI*4+4]
MOV ECX, [ECX+4]
MOV ESI, [ECX] //деф
MOV ECX, [EBP+8]
MOV EDI, [EBX+$C]
LEA EAX, [EBX+8]
MOV EDX,ECX
SHR ECX,2
REP MOVSD
MOV ECX,EDX
AND ECX,3
REP MOVSD
MOV ECX,EDX
PUSH ECX
MOV ECX,EAX
MOV EAX, $404A20
CALL EAX
@@LALA:
MOV ESI,[EBX+4]
MOV ECX, [PointerOfTable]
MOV ECX, [ECX+ESI*4+4]
MOV ECX, [ECX+4]
PUSH DWORD [ECX+4] //Номер кадра в дефе
MOV EAX, $77D3D7
CALL EAX
MOV EDX,EAX
PUSH $4F6226
RET
END; // .PROCEDURE MainMessages
PROCEDURE Messages_hints; ASSEMBLER;
ASM
MOV EAX, [ecx+$38]
CMP EAX, 100
JE @@OK
CMP EAX, $24
PUSH $4F11E7
RET
@@OK:
MOV ECX, [ECX+$3C]
MOV EDX, [PointerOfTable]
MOV EDX, [EDX+ECX*4+4]
MOV EDX, [EDX+4]
MOV ECX, [EDX+12] //текст подсказки
PUSH 0
PUSH -1
PUSH $4F1206
END; // .PROCEDURE Messages_hints
BEGIN
hMessages:=Win.GetModuleHandle(C_MOP_DLLNAME);
Win.DisableThreadLibraryCalls(hMessages);
HookCode(POINTER($4EDEEA), @TXTLoad, C_HOOKTYPE_JUMP); //загрузка текстовика
HookCode(POINTER($4F5584), @MainMessages, C_HOOKTYPE_JUMP); //обработка типа
HookCode(POINTER($4F11E1), @Messages_hints, C_HOOKTYPE_JUMP); //обработка подсказки по ПКМ
END. Впрочем, кому нужна эта громоздкая хрень, которая, к тому же, не поддерживает сообщения с более чем тремя картинками (преодолено только в третьей версии MoP).
Проще названия дефов в памяти заменить на время показа сообщения.
Ну а анимация дефов в MoP работает только в DL-диалогах. Желающие могут попытаться разобраться в прекрасно упорядоченном и, не побоюсь этого слова, величественном исходнике бинарника DL.txt, где, помимо сего, представлена не менее превосходная и качественная реализация других прелестных вещей.
Circle of destruction, hammer comes crushing
Powerhouse of energy
Whipping up a fury, dominating flurry
We create the battery
(This post was last modified: 03.05.2019 16:40 by MOP.)
|