Berserker, спасибо - нашёл. Но не работает в бою.]
Нашёл ещё интересную вещь:
В БОЮ!
TAB: вводим сообщение;
ESC; до отправки
TAB; сообщение остаётся.
Тут у Игрика нужно спросить, какой функцией отослать сообщение элементу управления. Сам диалог получить не сложно из менеджера игры.
Мне уже ничего не надо - я для себя всё сделал.
Вопрос с left/right ctrl+alf+shift уже прорабатывается, процентов 70 кода написал, работает. Реализовал и отключение обработки клавиш при наличии фокуса в любом поле ввода.
А если на полном серьёзе 2 года мало, то как тогда в события скрипты включить - механика карты то не позволяет?
fatsawhorse, сама игра большегода уже может не выдержать
(12.01.2021 18:44)Raistlin Wrote: [ -> ]Основная функция:
Code:
void __stdcall MArena(TEvent* e)
{
ExecErmCmd("HE-1:P?y1/?y2/?y3");
ExecErmCmd("OBy1/y2/y3:U?y4");
//Изначально я хотел переделать все с нуля на ERM, но нафига козе баян, если можно просто пропатчить пару мест и оставить оригинальный код :)
if (y[4] == 1) //Если подтип 1, измненяем на Арену Магов
{
Magic->WriteByte(0x49E4C6, 0x22); //Картинки
Magic->WriteByte(0x49E4CC, 0x21);
Magic->WriteByte(0x49E4F6, 0x78); //Смещение до первого навыка при проверке лимита
Magic->WriteByte(0x49E512, 0x79); //Смещение до второго навыка при проверке лимита
Magic->WriteByte(0x49E538, 0x78); //Смещение до первого навыка
Magic->WriteByte(0x49E546, 0x78); //Смещение до первого навыка
}
else //Возвращаем все как было, если игрок зашел на нормальную арену
{
Magic->WriteByte(0x49E4C6, 0x20); //Картинки
Magic->WriteByte(0x49E4CC, 0x1F);
Magic->WriteByte(0x49E4F6, 0x76); //Смещение до первого навыка при проверке лимита
Magic->WriteByte(0x49E512, 0x77); //Смещение до второго навыка при проверке лимита
Magic->WriteByte(0x49E538, 0x76); //Смещение до первого навыка
Magic->WriteByte(0x49E546, 0x76); //Смещение до первого навыка
}
}
//Magic, если кто не понял, - это моя PatсherInstance
В DllMain также должно стоять вот это:
Code:
RegisterHandler(MArena, "OnBeforeVisitObject 4/-1");
Такие кастыли нужно оставлять на ERM, ибо это очень плохой код. По-нормальному, если уж делаешь плагином, то хуком кейса соответствующей функции посещения объекта карты и написанием полноценной функции посещения арены магов (т.е. как в MoP, без воговщины). Если тырите из хоты, то и код тоже тащите от туда, без кастыльной самодеятельности.
Code:
char __thiscall AdvMng_4_Arena(void *AvdMng, int hero, int obj, char xyz)
{
_AdvMgr_ *AvdMan; // esi
char result; // al
signed int v6; // ebx
char v7; // al
signed int v8; // ecx
signed int v9; // eax
AvdMan = AvdMng;
if ( !sub_004E5630(hero, obj) )
{
v6 = 0;
if ( xyz )
{
AdvMgr_SetTimer(AvdMan, 0, -1);
AdvMgr_UpdateInfoPanel(AvdMan, 0, 1, 1);
b_MsgBox(*o_Advevent_TXT->GetString, 10, -1, -1, 31, 2, 32, 2, -1, 0, -1, 0);
if ( o_WndMgr->ResultItemId == 30729 )
{
v6 = 0;
}
else if ( o_WndMgr->ResultItemId == 30730 )
{
LABEL_20:
v6 = 1;
goto LABEL_21;
}
LABEL_21:
*(v6 + hero + 1142) += 2;
return sub_004E5650(hero, obj);
}
v7 = *(hero + 1142);
if ( v7 <= 99 )
{
if ( v7 <= 0 )
v8 = 0;
else
v8 = v7;
}
else
{
v8 = 99;
}
LOBYTE(v9) = *(hero + 1143);
if ( v9 <= 99 )
{
if ( v9 <= 0 )
v9 = 0;
else
v9 = v9;
}
else
{
v9 = 99;
}
if ( v8 <= v9 )
goto LABEL_21;
goto LABEL_20;
}
result = xyz;
if ( xyz )
result = b_MsgBox(*(o_Advevent_TXT->GetString + 4), 1, -1, -1, -1, 0, -1, 0, -1, 0, -1, 0);
return result;
}
Если честно, мне не кажется что тут стоит что-то хукать, а удобнее просто изменить 6 значений. Из хоты мы тырим только идеи и графику, код я пишу сам. Вообще, я безусловно благодарен Вам за замечание - у меня по-прежнему не так уж и много опыта, по сути я пока только учусь, и типичные ошибки в реализации мне не знакомы.
(12.01.2021 21:39)Raistlin Wrote: [ -> ]
Code:
char __thiscall AdvMng_4_Arena(void *AvdMng, int hero, int obj, char xyz)
{
_AdvMgr_ *AvdMan; // esi
char result; // al
signed int v6; // ebx
char v7; // al
signed int v8; // ecx
signed int v9; // eax
AvdMan = AvdMng;
if ( !sub_004E5630(hero, obj) )
{
v6 = 0;
if ( xyz )
{
AdvMgr_SetTimer(AvdMan, 0, -1);
AdvMgr_UpdateInfoPanel(AvdMan, 0, 1, 1);
b_MsgBox(*o_Advevent_TXT->GetString, 10, -1, -1, 31, 2, 32, 2, -1, 0, -1, 0);
if ( o_WndMgr->ResultItemId == 30729 )
{
v6 = 0;
}
else if ( o_WndMgr->ResultItemId == 30730 )
{
LABEL_20:
v6 = 1;
goto LABEL_21;
}
LABEL_21:
*(v6 + hero + 1142) += 2;
return sub_004E5650(hero, obj);
}
v7 = *(hero + 1142);
if ( v7 <= 99 )
{
if ( v7 <= 0 )
v8 = 0;
else
v8 = v7;
}
else
{
v8 = 99;
}
LOBYTE(v9) = *(hero + 1143);
if ( v9 <= 99 )
{
if ( v9 <= 0 )
v9 = 0;
else
v9 = v9;
}
else
{
v9 = 99;
}
if ( v8 <= v9 )
goto LABEL_21;
goto LABEL_20;
}
result = xyz;
if ( xyz )
result = b_MsgBox(*(o_Advevent_TXT->GetString + 4), 1, -1, -1, -1, 0, -1, 0, -1, 0, -1, 0);
return result;
}
Для сравнения это же самое, но уже из MoP 2.19:
Code:
CPU Disasm
Address Hex dump Command Comments
0049E3BC /$ 55 PUSH EBP ; MoP.0049E3BC(guessed Arg1,Arg2,Arg3)
0049E3BD |. 8BEC MOV EBP,ESP
0049E3BF |. 8B55 0C MOV EDX,DWORD PTR SS:[ARG.2]
0049E3C2 |. 33C0 XOR EAX,EAX
0049E3C4 |. 40 INC EAX
0049E3C5 |. 57 PUSH EDI
0049E3C6 |. 8B0A MOV ECX,DWORD PTR DS:[EDX]
0049E3C8 |. 8B7D 08 MOV EDI,DWORD PTR SS:[ARG.1]
0049E3CB |. D3E0 SHL EAX,CL
0049E3CD |. 8547 73 TEST DWORD PTR DS:[EDI+73],EAX
0049E3D0 |. 8A4D 10 MOV CL,BYTE PTR SS:[ARG.3]
0049E3D3 |. 75 60 JNZ SHORT 0049E435
0049E3D5 |. 0947 73 OR DWORD PTR DS:[EDI+73],EAX
0049E3D8 |. 84C9 TEST CL,CL
0049E3DA |. 74 4E JZ SHORT 0049E42A
0049E3DC |. A1 686A6900 MOV EAX,DWORD PTR DS:[696A68]
0049E3E1 |. 6A 02 PUSH 2 ; /Arg6 = 2
0049E3E3 |. 6A 20 PUSH 20 ; |Arg5 = 20
0049E3E5 |. 6A 02 PUSH 2 ; |Arg4 = 2
0049E3E7 |. 8B48 20 MOV ECX,DWORD PTR DS:[EAX+20] ; |
0049E3EA |. 6A 1F PUSH 1F ; |Arg3 = 1F
0049E3EC |. 6A 07 PUSH 7 ; |Arg2 = 7
0049E3EE |. FF31 PUSH DWORD PTR DS:[ECX] ; |Arg1
0049E3F0 |. E8 EBC62A00 CALL 0074AAE0 ; \MoP.0074AAE0
0049E3F5 |. 83C0 07 ADD EAX,7
0049E3F8 |> 50 PUSH EAX
0049E3F9 |. A1 14399A02 MOV EAX,DWORD PTR DS:[29A3914]
0049E3FE |. 8BCF MOV ECX,EDI
0049E400 |. E8 4469F6FF CALL 00404D49
0049E405 |. 59 POP ECX
0049E406 |. 8988 A0030000 MOV DWORD PTR DS:[EAX+3A0],ECX
0049E40C |. C780 A4030000 02000000 MOV DWORD PTR DS:[EAX+3A4],2
0049E416 |> 81C1 6E040000 ADD ECX,46E
0049E41C |. 8A040F MOV AL,BYTE PTR DS:[ECX+EDI]
0049E41F |. 3C 7E CMP AL,7E
0049E421 |. 7D 1B JGE SHORT 0049E43E
0049E423 |. 04 02 ADD AL,2
0049E425 |. 88040F MOV BYTE PTR DS:[ECX+EDI],AL
0049E428 |. EB 14 JMP SHORT 0049E43E
0049E42A |> 33C9 XOR ECX,ECX
0049E42C |. B1 08 MOV CL,8
0049E42E |> E8 326BF6FF CALL 00404F65
0049E433 |.^ EB E1 JMP SHORT 0049E416
0049E435 |> 84C9 TEST CL,CL
0049E437 |. 74 05 JZ SHORT 0049E43E
0049E439 |. E8 4E69F6FF CALL 00404D8C
0049E43E |> 5F POP EDI
0049E43F |. 5D POP EBP
0049E440 |. C2 0C00 RETN 0C
Code:
CPU Disasm
Address Hex dump Command Comments
0049E4E8 /$ 55 PUSH EBP ; MoP.0049E4E8(guessed Arg1,Arg2,Arg3)
0049E4E9 |. 8BEC MOV EBP,ESP
0049E4EB |. 8B55 0C MOV EDX,DWORD PTR SS:[ARG.2]
0049E4EE |. 33C0 XOR EAX,EAX
0049E4F0 |. 40 INC EAX
0049E4F1 |. 57 PUSH EDI
0049E4F2 |. 8B0A MOV ECX,DWORD PTR DS:[EDX]
0049E4F4 |. 8B7D 08 MOV EDI,DWORD PTR SS:[ARG.1]
0049E4F7 |. D3E0 SHL EAX,CL
0049E4F9 |. 8547 7F TEST DWORD PTR DS:[EDI+7F],EAX
0049E4FC |. 8A4D 10 MOV CL,BYTE PTR SS:[ARG.3]
0049E4FF |.^ 0F85 30FFFFFF JNZ 0049E435
0049E505 |. 0947 7F OR DWORD PTR DS:[EDI+7F],EAX
0049E508 |. 84C9 TEST CL,CL
0049E50A |. 74 22 JZ SHORT 0049E52E
0049E50C |. A1 686A6900 MOV EAX,DWORD PTR DS:[696A68]
0049E511 |. 6A 02 PUSH 2 ; /Arg6 = 2
0049E513 |. 6A 22 PUSH 22 ; |Arg5 = 22
0049E515 |. 6A 02 PUSH 2 ; |Arg4 = 2
0049E517 |. 8B48 20 MOV ECX,DWORD PTR DS:[EAX+20] ; |
0049E51A |. 6A 21 PUSH 21 ; |Arg3 = 21
0049E51C |. 6A 07 PUSH 7 ; |Arg2 = 7
0049E51E |. FF71 50 PUSH DWORD PTR DS:[ECX+50] ; |Arg1
0049E521 |. E8 BAC52A00 CALL 0074AAE0 ; \MoP.0074AAE0
0049E526 |. 83C0 09 ADD EAX,9
0049E529 |.^ E9 CAFEFFFF JMP 0049E3F8
0049E52E |> 33C9 XOR ECX,ECX
0049E530 |. B1 0A MOV CL,0A
0049E532 \.^ E9 F7FEFFFF JMP 0049E42E
Такой вот коддинг на Ассемблере
(12.01.2021 21:39)Raistlin Wrote: [ -> ]Если честно, мне не кажется что тут стоит что-то хукать, а удобнее просто изменить 6 значений.
Из моей практики - такие вот "обезьяньи патчи" при накоплении их в коде программы приводят к путанице и последующим бесконтрольным ошибкам. Недавно вроде б в закрытом чате эту тему затрагивали, вот даже на вики кто-то ссылку кидал:
https://ru.wikipedia.org/wiki/Monkey_patch . Вроде б все сошлись на том, что на Си это зло (да и на Ассемблере тоже), требующее полного искоренения (хотя и Тифон немного грешит этим, потому что мне просто было лень затаскивать огромные содовские функции в dll).
(13.01.2021 00:44)XEPOMAHT Wrote: [ -> ]Такой вот коддинг на Ассемблере 
Я пока что ни разу не писал код на чистом ассемблере, но я похоже понял принцип работы основных команд. Я могу читать код, но "думаю" я пока только на высокоуровневых языках
Скажу честно, мне очень хочется разобраться и в этом, Вы не будете против, если я задам Вам несколько вопросов лично?
(13.01.2021 00:44)XEPOMAHT Wrote: [ -> ]Из моей практики - такие вот "обезьяньи патчи" при накоплении их в коде программы приводят к путанице и последующим бесконтрольным ошибкам. Недавно вроде б в закрытом чате эту тему затрагивали, вот даже на вики кто-то ссылку кидал: https://ru.wikipedia.org/wiki/Monkey_patch . Вроде б все сошлись на том, что на Си это зло (да и на Ассемблере тоже), требующее полного искоренения (хотя и Тифон немного грешит этим, потому что мне просто было лень затаскивать огромные содовские функции в dll).
У меня более тысячи строк кода, и это первый раз, когда я пропатчил что-то таким образом. Всего 6 изменённых значений + к каждому дан комментарий (все остальное, кстати, тоже прокомментировано) - путаницу это точно не создаст, ведь решение простое и рабочее. Написал и забыл.

Тем не менее, в будущем я буду это учитывать.
(13.01.2021 01:52)Raistlin Wrote: [ -> ]Скажу честно, мне очень хочется разобраться и в этом, Вы не будете против, если я задам Вам несколько вопросов лично?
Можно и публично. Но Ассемблер я знаю так себе, на 3 с минусом.
(13.01.2021 01:52)Raistlin Wrote: [ -> ]путаницу это точно не создаст, ведь решение простое и рабочее. Написал и забыл.
Тем не менее, в будущем я буду это учитывать.
Лучше оставить это на ERM и не переводить на Си. Т.к. это решение приемлемо именно для ERM (правда, не факт, что в будущем может начать вылетать после обновления Эры, HD-мода или какого-нибудь плагина). На ERM всегда можно исправить руками любого игрока, знающего язык. На Си - всегда затруднительно, т.к. синтаксис там в разы сложнее и непонятнее для непрограммистов типа меня.
Для небольшой функции вроде посещения Колизея Магов надёжнее не использовать существующую содовскую функцию Арены, а написать свою (тем более, содовская функция написана не очень качественно, как будто Арену программировали наспех прямо перед релизом бета-версии Третьих Героев, например там и подсказку забыли добавить, и проверки на переполнение Атаки/Защиты нет, и лишние спецфункции для Арены зачем-то добавили, хотя остальные подобные объекты карты спокойно обходятся без них и т.д.).
(13.01.2021 02:20)XEPOMAHT Wrote: [ -> ]Можно и публично. Но Ассемблер я знаю так себе, на 3 с минусом.
Эх, мне бы Вашу скромность

Если Вы смогли создать Эру+ и MoP 2.18, то это уже как минимум 4. Насчёт плюсов и минусов пока ничего не скажу из-за нехватки опыта, но я готов с уверенностью заявить, что, если Вы можете применять свои знания в таком масштабе, то это совершенно точно не 3!
Спасибо за помощь, спасибо за советы и спасибо за открытость!
(13.01.2021 02:20)XEPOMAHT Wrote: [ -> ]Лучше оставить это на ERM и не переводить на Си. Т.к. это решение приемлемо именно для ERM (правда, не факт, что в будущем может начать вылетать после обновления Эры, HD-мода или какого-нибудь плагина). На ERM всегда можно исправить руками любого игрока, знающего язык. На Си - всегда затруднительно, т.к. синтаксис там в разы сложнее и непонятнее для непрограммистов типа меня.
Тут я с Вами полностью согласен, но только вот у ERM есть множество ограничений, а также всегда существует вероятность, что кто-то где-то возьмёт и использует какой-то индекс, который должен оставаться нетронутым. Как показывает мой опыт, комбинация Си с ERM наиболее удобна для разработки. Например, массивы, а также все, что связано с переменными, выглядит намного более логично и понятно, лично мне такой код читать намного удобнее. Также у меня, как у разработчика, сразу открывается множество новых возможностей вроде использования двумерных массивов (насколько я знаю, в обычных скриптах это делать нельзя).
(13.01.2021 02:20)XEPOMAHT Wrote: [ -> ]Для небольшой функции вроде посещения Колизея Магов надёжнее не использовать существующую содовскую функцию Арены, а написать свою (тем более, содовская функция написана не очень качественно, как будто Арену программировали наспех прямо перед релизом бета-версии Третьих Героев, например там и подсказку забыли добавить, и проверки на переполнение Атаки/Защиты нет, и лишние спецфункции для Арены зачем-то добавили, хотя остальные подобные объекты карты спокойно обходятся без них и т.д.).
Она явно уже давно переделана: проверка на переполнение, например, там есть, и я даже написал в теме про UN:C, как на нее можно влиять. Также в коде своей функции я модифицирую как раз эту самую проверку:
Code:
Magic->WriteByte(0x49E4F6, 0x78); //Смещение до первого навыка при проверке лимита
Magic->WriteByte(0x49E512, 0x79); //Смещение до второго навыка при проверке лимита
(13.01.2021 03:10)Raistlin Wrote: [ -> ] проверка на переполнение, например, там есть, и я даже написал в теме про UN:C, как на нее можно влиять.
Она ограничивает только сравнение значений атаки и защиты в выборе ИИ. И то, если атака будет > 99 и защита будет > 99, то ИИ будет всегда выбирать атаку для прокачки, пока она не уйдёт в минус. Т.е. по факту от этого ни жарко, ни холодно - только лишние проверки от какого-то не очень хорошо разбирающегося в коде игры программиста. Это очень хорошо видно в диассемблированном виде функции из IDA (и совершенно не видно в Си-подобном, по крайней мере в таком виде мне её читать затруднительно

).
В ветке функции для человека никаких проверок вообще нет - свободно можно уходить в минус по атаке и защите, ну а в MoP 2.19 уже так не получится как для человека, так и для ИИ (перед повышением значение атаки или защиты проверяется на лимит в 126).

А зависимость от артефактов учитывается?