-
Постов
2 999 -
Зарегистрирован
-
Победитель дней
129
Тип контента
Профили
Форумы
Загрузки
Блоги
Сообщения, опубликованные MasterGH
-
-
Попробуй сделать и узнаешь правильно ли это
-
Я что-то потерялся в дебрях вызовов и упёрся в аргумент функции "location_manager().update_positions". Эта функция постоянно работает с позициями.... Внизу есть другая функция, которая может вызывать "подставляемые" функции. Одну функцию может вызвать для бота и совершенно другую для пользователя. По какому принципу это делается нет времени разбирать, т.к. похоже это надолго. Всё-таки надо было ставить бряк на изменение курсора или на клик. Но для этого париться с хуками directX, на это тоже надо какое-то время.
Но у меня есть не плохие новости. Есть же уже готовая таблица Recifense - ещё тот Гуру по таким случаям.
===========================================
Total War - Shogun 2
Game Version : 1.00
Script Version: 1.0
CE Version : 6.0
GM, Ammo, Gold, MP, MSO
23-Mar-2011
By Recifense
===========================================
Total War - Shogun 2
Game Version : 1.00
Script Version: 1.0
CE Version : 6.0
GM, Ammo, Gold, MP, MSO
23-Mar-2011
By Recifense
===========================================
1) God Mode: For all Units and Ships
2) Unlimited Ammo (Arrows, Bombs, etc)
3) Unlimited Movement Points (Army on campaign)
4) Recover troop size when Army moves (Army on campaign)
5) Minimum Gold (On campaign)
6) Player's Current Gold (On campaign)
7) Skill points of selected army's general (On Campaign)
}
[ENABLE]
//=========================================
// Check if script is compatible to this game version
// If false the script will not be loaded
assert(Shogun2.dll+00a63e50,55 8b ec 83 e4 f8)
assert(Shogun2.dll+00c7e770,55 8b ec 83 e4 f8)
assert(Shogun2.dll+01199dc3,8b b7 34 01 00 00)
assert(Shogun2.dll+009e7af3,f3 0f 11 86 40 0f 00 00)
assert(Shogun2.dll+00cf54e0,51 8b 8f a0 03 00 00)
assert(Shogun2.dll+011cb77d,89 8e b0 00 00 00)
assert(Shogun2.dll+00b560d7,8b 43 40)
assert(Shogun2.dll+0046df80,?? ?? 6c 04 00 00)
assert(Shogun2.dll+011ad6bc,?? ?? 0c 1c 00 00)
//=========================================
alloc(MyCode,1024)
//=========================================
// Declaration section
label(_GodMode)
label(_GodM00)
label(_GodM01)
label(_BackGM)
label(_ExitGM)
label(_GodMode1)
label(_GodM10)
label(_GodM11)
label(_BackGM1)
label(_ExitGM1)
label(_MonSel)
label(_BackMS)
label(_MonAmmo)
label(_MonA0)
label(_MonA1)
label(_BackMA)
label(_ExitMA)
label(_GodModeS)
label(_BackGMS)
label(_ExitGMS)
label(_MonSelShip)
label(_BackMSS)
label(_ExitMSS)
label(_GodModeSH)
label(_BackGMSH)
label(_ExitGMSH)
label(_MonGold)
label(_BackMG)
label(_ExitMG)
label(_MonMP)
label(_MonM0)
label(_BackMM)
label(_ExitMM)
label(_MonSelOfficer)
label(_BackMSO)
label(_ExitMSO)
label(pSel)
label(pGold)
label(pOfficer)
label(iEnableGM)
label(iEnableGM1)
label(iEnableGM2)
label(iEnableGMS)
label(iEnableMA)
label(iEnableQR)
label(iEnableMG)
label(iEnableMM)
label(iEnableMTS)
label(iPlayerID)
label(iMinGold)
label(iEAX)
label(iCount0)
label(iCount1)
label(iCount2)
label(iCount3)
label(iCountS)
registersymbol(MyCode)
registersymbol(pSel)
registersymbol(pGold)
registersymbol(pOfficer)
registersymbol(iEnableGM)
registersymbol(iEnableGM1)
registersymbol(iEnableGM2)
registersymbol(iEnableGMS)
registersymbol(iEnableMA)
registersymbol(iEnableQR)
registersymbol(iEnableMG)
registersymbol(iEnableMM)
registersymbol(iEnableMTS)
registersymbol(iMinGold)
registersymbol(iPlayerID)
registersymbol(iCount0)
registersymbol(iCount1)
registersymbol(iCount2)
registersymbol(iCount3)
registersymbol(iCountS)
//=========================================
MyCode:
//=========================================
_GodMode:
mov [iEAX],eax // Save EAX
mov eax,[esp+04] // Get Unit
mov eax,[eax+00000204] // Get pTroop
test eax,eax
jnz _GodM00 // Jump if the pointer is null
mov eax,[eax+0000020c] // Get pShip
test eax,eax
jz _ExitGM // Jump if the pointer is null
mov al,[eax+0000111f] // Get pCommon
cmp al,[iPlayerID] // Is it a Player's Troop ?
jne _ExitGM // Jump if false
inc dword ptr [iCount0]
cmp dword ptr [iEnableGM],0
je _ExitGM // Jump if feature is disabled
jmp _GodM01
//=====
_GodM00:
mov eax,[eax+00000294] // Get pPlayerInfo
test eax,eax
jz _ExitGM // Jump if the pointer is null
mov eax,[eax+04] // Get playerID
cmp eax,[iPlayerID] // Is it a Player's Troop ?
jne _ExitGM // Jump if false
inc dword ptr [iCount1]
cmp dword ptr [iEnableGM],0
je _ExitGM // Jump if feature is disabled
_GodM01:
mov eax,[iEAX] // Restore EAX
ret 0004 // Avoid routine
//-----
_ExitGM:
mov eax,[iEAX] // Restore EAX
push ebp // Original code
mov ebp,esp // Original code
and esp,f8 // Original code
jmp _BackGM // Back to main code
//=========================================
_GodMode1:
mov [iEAX],eax // Save EAX
mov eax,[ecx+00000204] // Get pTroop
test eax,eax
jnz _GodM10 // Jump if the pointer is not null
mov eax,[ecx+0000020c] // Get pShip
test eax,eax
jz _ExitGM1 // Jump if the pointer is null
// Ship Crew
mov al,[eax+0000111f] // Get pCommon
cmp al,[iPlayerID] // Is it a Player's Troop ?
jne _ExitGM1 // Jump if false
inc dword ptr [iCount2]
cmp dword ptr [iEnableGM],0
je _ExitGM1 // Jump if feature is disabled
jmp _GodM11
//Land Soldiers
_GodM10:
mov eax,[eax+00000294] // Get pPlayerInfo
test eax,eax
jz _ExitGM1 // Jump if the pointer is null
mov eax,[eax+04] // Get playerID
cmp eax,[iPlayerID] // Is it a Player's Troop ?
jne _ExitGM1 // Jump if false
inc dword ptr [iCount3]
cmp dword ptr [iEnableGM],0
je _ExitGM1 // Jump if feature is disabled
_GodM11:
mov eax,[iEAX] // Restore EAX
ret 0004 // Avoid routine
//-----
_ExitGM1:
mov eax,[iEAX] // Restore EAX
push ebp // Original code
mov ebp,esp // Original code
and esp,f8 // Original code
jmp _BackGM1 // Back to main code
//=========================================
_MonSel:
mov esi,[edi+00000134] // Original code
mov [pSel],esi
jmp _BackMS // Back to main code
//=========================================
_MonAmmo:
mov eax,[esi+00000294] // Get pPlayerInfo
test eax,eax
jz _ExitMA // Jump if the pointer is null
mov eax,[eax+04] // Get playerID
cmp eax,[iPlayerID] // Is it a Player's Troop ?
jne _ExitMA // Jump if false
cmp dword ptr [iEnableMA],0
je _MonA0 // Jump if feature is disabled
cvtsi2ss xmm0,[esi+00000F44] // Get Maximum Ammo
_MonA0:
cmp dword ptr [iEnableQR],0
je _ExitMA // Jump if feature is disabled
cmp dword ptr [esi+00000dbc],#15
jle _MonA1
mov dword ptr [esi+00000dbc],#15
_MonA1:
cmp dword ptr [esi+00000dc0],#15
jle _ExitMA
mov dword ptr [esi+00000dc0],#15
_ExitMA:
comiss xmm1,xmm0 // Update EFLAGS
movss [esi+00000F40],xmm0 // Original code
jmp _BackMA // Back to main code
//=========================================
_GodModeS:
mov [iEAX],eax // Save EAX
mov eax,[edi+0000020c] // Get pShip
test eax,eax
jz _ExitGMS // Jump if the pointer is null
mov al,[eax+0000111f] // Get pCommon
cmp al,[iPlayerID] // Is it a Player's Troop ?
jne _ExitGMS // Jump if false
inc dword ptr [iCountS]
cmp dword ptr [iEnableGM],0
je _ExitGMS // Jump if feature is disabled
mov eax,[iEAX] // Restore EAX
ret // Avoid routine
//-----
_ExitGMS:
mov eax,[iEAX] // Restore EAX
push ecx // Original code
mov ecx,[edi+000003A0] // Original code
jmp _BackGMS // Back to main code
//=========================================
// Card under cursor
_MonSelShip:
mov [pSel],ecx
_ExitMSS:
mov [esi+000000B0],ecx // Original code
jmp _BackMSS // Back to main code
//=========================================
// Ship Hull
_GodModeSH:
mov eax,[ebx+24] // Get pShip
test eax,eax
jz _ExitGMSH // Jump if the pointer is null
mov al,[eax+0000111f] // Get pCommon
cmp al,[iPlayerID] // Is it a Player's Troop ?
jne _ExitGMSH // Jump if false
cmp dword ptr [iEnableGM],0
je _ExitGMSH // Jump if feature is disabled
mov eax,[ebx+1c] // Get max HP
mov [ebx+40],eax // Update cur HP
xor edi,edi // value2decrease = 0
_ExitGMSH:
mov eax,[ebx+40] // Original code
sub eax,edi // Original code
jmp _BackGMSH // Back to main code
//=========================================
// RTS Gold
_MonGold:
mov eax,[ecx+0000048c] // Get pointer to info
test eax,eax
jz _ExitMG // Jump if null pointer
mov eax,[eax+24] // Get pointer to uPlayerID
test eax,eax
jz _ExitMG // Jump if null pointer
mov eax,[eax]
cmp eax,006c0070
jne _ExitMG // Jump if it's an AI
mov eax,[ecx+00000470] // Get pointer to player
mov [pGold],eax
cmp dword ptr [iEnableMG],0
je _ExitMG // Jump if feature is disabled
mov eax,[iMinGold]
cmp eax,[ecx+0000046C]
jle _ExitMG
mov [ecx+0000046C],eax // Update gold
_ExitMG:
mov eax,[ecx+0000046C] // Original code
jmp _BackMG // Back to main code
//=========================================
// RTS Troop Movement Points/Size
_MonMP:
push ecx
mov ecx,[eax+44] // Get pointer to Owner
cmp ecx,[pGold] // Is it a player's troop?
jne _ExitMM
cmp dword ptr [iEnableMM],0
je _MonM0 // Jump if feature is disabled
xor edi,edi // value2decrease = 0
_MonM0:
cmp dword ptr [iEnableMTS],0
je _ExitMM // Jump if feature is disabled
mov ecx,[eax+50] // Get troop maximum size
mov [eax+4c],ecx // Update current size
_ExitMM:
pop ecx
sub edx,edi // Original code
mov [eax+6C],edx // Original code
jmp _BackMM // Back to main code
//=========================================
// RTS Selected Officer
_MonSelOfficer:
mov [pOfficer],eax
_ExitMSO:
cmp [eax+00001C0C],ebx // Original code
jmp _BackMSO // Back to main code
//=========================================
// Variables
iEnableGM:
dd 1
iEnableGM1:
dd 0
iEnableGM2:
dd 1
iEnableMA:
dd 1
iEnableQR:
dd 1
iEnableGMS:
dd 1
iEnableMG:
dd 1
iEnableMM:
dd 1
iEnableMTS:
dd 1
pSel:
dd 0
pGold:
dd 0
pOfficer:
dd 0
iPlayerID:
dd 1
iEAX:
dd 0
iCount0:
dd 0
iCount1:
dd 0
iCount2:
dd 0
iCount3:
dd 0
iCountS:
dd 0
iMinGold:
dd #50000
//=========================================
// Hacking Points
Shogun2.dll+00a63e50:
jmp _GodMode
nop
_BackGM:
Shogun2.dll+00c7e770:
jmp _GodMode1
nop
_BackGM1:
Shogun2.dll+01199dc3:
jmp _MonSel
nop
_BackMS:
Shogun2.dll+009e7af3:
jmp _MonAmmo
nop
nop
nop
_BackMA:
Shogun2.dll+00cf54e0:
jmp _GodModeS
nop
nop
_BackGMS:
Shogun2.dll+011cb77d:
jmp _MonSelShip
nop
_BackMSS:
Shogun2.dll+00b560d7:
jmp _GodModeSH
_BackGMSH:
Shogun2.dll+0046df80:
jmp _MonGold
nop
_BackMG:
Shogun2.dll+0026a5e0:
jmp _MonMP
_BackMM:
Shogun2.dll+011ad6bc:
jmp _MonSelOfficer
nop
_BackMSO:
//=========================================
// Original Codes
[DISABLE]
Shogun2.dll+00a63e50:
push ebp
mov ebp,esp
and esp,f8
Shogun2.dll+00c7e770:
push ebp
mov ebp,esp
and esp,f8
Shogun2.dll+01199dc3:
mov esi,[edi+00000134]
Shogun2.dll+009e7af3:
movss [esi+00000F40],xmm0
Shogun2.dll+00cf54e0:
push ecx
mov ecx,[edi+000003A0]
Shogun2.dll+011cb77d:
mov [esi+000000B0],ecx
Shogun2.dll+00b560d7:
mov eax,[ebx+40]
sub eax,edi
Shogun2.dll+0046df80:
mov eax,[ecx+0000046C]
Shogun2.dll+0026a5e0:
sub edx,edi
mov [eax+6C],edx
Shogun2.dll+011ad6bc:
cmp [eax+00001C0C],ebx
unregistersymbol(MyCode)
unregistersymbol(pSel)
unregistersymbol(pGold)
unregistersymbol(pOfficer)
unregistersymbol(iEnableGM)
unregistersymbol(iEnableGM1)
unregistersymbol(iEnableGM2)
unregistersymbol(iEnableGMS)
unregistersymbol(iEnableMA)
unregistersymbol(iEnableQR)
unregistersymbol(iEnableMG)
unregistersymbol(iEnableMM)
unregistersymbol(iEnableMTS)
unregistersymbol(iMinGold)
unregistersymbol(iPlayerID)
unregistersymbol(iCount0)
unregistersymbol(iCount1)
unregistersymbol(iCount2)
unregistersymbol(iCount3)
unregistersymbol(iCountS)
dealloc(MyCode){
Как видно по смещению +0x44, я об этом смещение уже писал почему-то указатель на pGold (вроде как золото) Пользователя является уже критерием принадлежности войскам. Вообще-то странно кажется это корявые названия указателей.
// RTS Troop Movement Points/Size
_MonMP:
push ecx
mov ecx,[eax+44] // Get pointer to Owner
cmp ecx,[pGold] // Is it a player's troop?
jne _ExitMM
cmp dword ptr [iEnableMM],0
je _MonM0 // Jump if feature is disabled
xor edi,edi // value2decrease = 0
_MonM0:
cmp dword ptr [iEnableMTS],0
je _ExitMM // Jump if feature is disabled
mov ecx,[eax+50] // Get troop maximum size
mov [eax+4c],ecx // Update current size
_ExitMM:
pop ecx
sub edx,edi // Original code
mov [eax+6C],edx // Original code
jmp _BackMM // Back to main codeНапоминаю, что это инъекция в эту функцию:
{
int result; // eax@1
char *v3; // ecx@1
int v4; // esi@1
int v5; // eax@2
int v6; // edx@2
v3 = (char *)this + 148;
v4 = *((_DWORD *)v3 + 5);
for ( result = v4 + 4 * *((_DWORD *)v3 + 4); // начальное значения для начала цикла
v4 != result; // условие выполнение цикла пока истино v4 != result
result = *((_DWORD *)v3 + 5) + 4 * *((_DWORD *)v3 + 4) ) // действие при каждой повторении цикла
{
v5 = **(_DWORD **)v4; // v5 = адрес группы (v5 теперь является подгруппой *this)
v6 = *(_DWORD *)(v5 + 0x6C); // v6 = разрешённых шагов для группы v5
if ( v6 <= a2 ) // если разрешённых шагов меньше например 3, когда попытка пойти на 5, то
*(_DWORD *)(v5 + 0x6C) = 0; // присвоить v5 перемещение 0
else // иначе
*(_DWORD *)(v5 + 0x6C) = v6 - a2; // присворить v5 разность между разршенными шагами и "сделанными"
*(_DWORD *)(v5 + 0x898) = -1; // какое-то интересное смещение +0x898, что означает точно не понятно.
// по карайне мере понятно, что оно стаиться в -1, когда v5 было установленно
// кол-во разрешённых шагов
v4 += 4; // перебираем следующую группу
}
return result;
}int __thiscall sub_10654450(void *this, int a2)
Всё-таки я выскажусь по этой таблице - громоздка, запутанная и неудобная. Надо было пользоваться обвёрткой Lua, как я это делал в теме по Lua...
-
Да, возможно, но будут трудности... )
-
Ликбез.
На карте Мира могут быть войска Пользователя и ботов. За Пользователя играет Пользователь, за остальных компьютер.
Все войска Пользователя разделим на Армии в составе которой есть руководитель. Именно Армии мы можем передвигать на карте Мира.
Армию можно делить на отряды по классам: конница, лучники и т.п.
Каждый отряд имеет коэффициент усталости. От него зависит дальность хода. Таким образом в Армии быстрые отряды не могут идти дальше чем медленные отряды.
Итак, когда Пользователь передвигает Армию, то код игры смотрит принадлежит ли Армия пользователю, если нет, то идти не разрешается, если да, то код игры перебирает отряды и двигает их на расстояние указанное пользователем с вычетом сделанных ходов ранее и вычитом усталости самого уставшего отряда. Если вы что-то не поняли или запутались просто поиграйте в игру и всё поймете. Конница не может оставить лучников в армии, если двигается вся армия...
Путь Вхождений моего героя из глубины вверх.
Три функции ниже связаны с объектом пользователя или бота и параметром а2 - шагов сколько Армия должна сделать. Именно Армия. При чём неавжно какая армия. И в этих трёх функция не определяется сравнение с Армией пользователя или Бота. Да и важно понимать, что псевдокод может отображать не все параметры передаваемые в функцию.
int __thiscall sub_10654450(void *this, int a2)
{
int result; // eax@1
char *v3; // ecx@1
int v4; // esi@1
int v5; // eax@2
int v6; // edx@2
v3 = (char *)this + 148;
v4 = *((_DWORD *)v3 + 5);
// цикл на запись ходо для отрядов
for ( result = v4 + 4 * *((_DWORD *)v3 + 4); v4 != result; result = *((_DWORD *)v3 + 5) + 4 * *((_DWORD *)v3 + 4) )
{
v5 = **(_DWORD **)v4; // v5 - отряд в Армии
v6 = *(_DWORD *)(v5 + 0x6C);
if ( v6 <= a2 )
*(_DWORD *)(v5 + 0x6C) = 0;
else
*(_DWORD *)(v5 + 0x6C) = v6 - a2; // Запись вычитанных шагов shogun2.dll+68DEB2
*(_DWORD *)(v5 + 0x898) = -1;
v4 += 4;
}
return result;
}
int __thiscall sub_1068B2D0(void *this, int a2)
{
int result; // eax@1
int i; // edi@1
int v4; // esi@1
void *v5; // edi@1
int v6; // eax@2
v5 = this;
(*(void (__stdcall **)(int))(*(_DWORD *)this + 152))(v5, a2); // MasterGH Вхождение 4 в sub_10654450 shogun2.dll+68B2e4
v4 = *((_DWORD *)v5 + 32);
result = *((_DWORD *)v5 + 31);
for ( i = v4 + 4 * result; v4 != i; v4 += 4 )
{
v6 = (*(int (**)(void))(***(_DWORD ***)v4 + 20))() - a2;
_ECX = 0;
__asm { sets cl }
result = (*(int (__stdcall **)(int))(***(_DWORD ***)v4 + 40))((_ECX - 1) & v6);
}
return result;
}
void __thiscall sub_103BB8B0(int this, int a2)
{
int v2; // edi@1
int v3; // esi@1
int v4; // eax@2
int v5; // ecx@5
int v6; // eax@7
v2 = a2;
v3 = this;
if ( a2 )
{
v4 = *(_DWORD *)(this + 700);
if ( v4 && *(_DWORD *)v4 )
{
if ( v4 )
v5 = *(_DWORD *)v4;
else
v5 = 0;
v6 = sub_104E7A10(v5);
if ( a2 >= 0 )
{
if ( v6 < a2 )
v2 = v6;
}
else
{
v2 = 0;
}
sub_1068B2D0(v3, v2); // MasterGh вхождение 3 (в sub_1068B2D0) shogun2.dll+3bb900
*(_DWORD *)(v3 + 28) = (*(int (__thiscall **)(int))(*(_DWORD *)v3 + 20))(v3);
}
else
{
sub_103670F0(a2);
}
}
}
int __thiscall sub_103D8D20(int this)
{
int result; // eax@1
int v2; // edi@1
__int16 v4; // cx@1
int v6; // eax@1
int v8; // eax@2
int v9; // ecx@2
int v10; // eax@2
_ESI = this;
v4 = *(_WORD *)(this + 60);
__asm { movq xmm0, qword ptr [esi+24h] }
v6 = *(_DWORD *)(_ESI + 44);
__asm
{
movq qword ptr [esi+40h], xmm0
xorps xmm0, xmm0
}
*(_WORD *)(_ESI + 76) = v4;
*(_DWORD *)(_ESI + 72) = v6;
__asm
{
movss dword ptr [esi+54h], xmm0
movss dword ptr [esi+50h], xmm0
}
result = sub_100E0B70(_ESI);
v2 = result;
if ( result )
{
// _ESI - это армия, а (result + 28) это расстояние хода при этом в структуре _ESI уже записаны координаты перемещения
(*(void (__stdcall **)(_DWORD))(*(_DWORD *)_ESI + 40))(*(_DWORD *)(_ESI, result + 28)); // MasterGH вхождение 2 ()sub_103BB8B0 shogun2.dll+3D8D61
(**(void (__thiscall ***)(_DWORD, _DWORD))v2)(v2, 1);
v10 = *(_DWORD *)(_ESI + 96);
v9 = *(_DWORD *)v10;
*(_DWORD *)v10 = **(_DWORD **)v10;
v8 = *(_DWORD *)(_ESI + 96);
if ( *(_DWORD *)v8 )
{
*(_DWORD *)(*(_DWORD *)v8 + 4) = v8;
result = sub_10F4F0A0(v9);
}
else
{
*(_DWORD *)(_ESI + 92) = v8;
result = sub_10F4F0A0(v9);
}
}
return result;
}
int __userpurge sub_10255060<eax>(int a1<ecx>, double a2<st0>, int a3, int a4, char a5)
{
int v5; // eax@1
char v7; // zf@4
int v8; // ecx@8
int v9; // ecx@10
char v10; // bl@12
int v11; // edi@14
int v12; // ecx@15
int v13; // ecx@17
void (__thiscall *v14)(_DWORD, _DWORD, _DWORD, _DWORD, _DWORD); // edx@17
int result; // eax@19
int v16; // eax@20
int v17; // edx@20
int v18; // ecx@20
int v19; // ebx@23
void (__thiscall *v20)(_DWORD, _DWORD, _DWORD, _DWORD, _DWORD); // edx@27
__int16 v26; // cx@28
__int16 v29; // dx@29
int v30; // eax@29
int v31; // ecx@29
int (__thiscall *v32)(_DWORD, _DWORD, _DWORD, _DWORD, _DWORD); // edx@30
char v33; // al@31
char v34; // zf@32
int v35; // ecx@38
int v36; // eax@40
char v37; // al@44
int v38; // ecx@44
int v39; // edx@44
int v40; // eax@44
int v42; // ecx@44
int v43; // edx@44
int v47; // eax@45
int v48; // ecx@49
int v49; // edx@49
int v50; // eax@49
int v52; // ecx@49
int v53; // edx@49
char v57; // al@52
int v58; // eax@63
char v59; // zf@63
int v60; // edi@64
int v61; // eax@70
int v62; // edi@74
int v63; // ecx@83
int v64; // ebx@83
int v65; // eax@90
int v66; // eax@91
int v68; // eax@94
int v69; // eax@95
int v70; // eax@97
int v71; // edi@97
int v72; // eax@100
int v73; // ebx@101
int v74; // eax@103
int v77; // eax@105
int v78; // ebx@105
int v79; // edi@105
int v80; // eax@108
int v81; // edx@108
int (__thiscall *v82)(_DWORD); // eax@108
int v83; // eax@108
int v86; // eax@110
int v90; // eax@116
int v91; // eax@117
int v92; // ecx@120
__int16 v94; // dx@120
int v95; // eax@120
int v96; // ecx@120
int v98; // ecx@121
void (__thiscall *v100)(_DWORD, _DWORD, _DWORD, _DWORD, _DWORD); // edx@121
int v101; // ecx@121
signed int v102; // ecx@122
signed int v107; // edi@134
int v112; // ecx@141
int *v113; // eax@145
int v114; // eax@146
int *v115; // eax@149
int v116; // eax@150
int v117; // eax@152
int v118; // edi@152
int v119; // eax@155
int v120; // ebx@156
int v121; // eax@158
int v122; // eax@160
int v123; // ebx@160
int v124; // edi@160
int v125; // eax@163
int v126; // edx@163
int (*v127)(void); // eax@163
int v128; // eax@163
int v129; // eax@164
int v134; // ecx@173
int v135; // eax@173
__int16 v136; // dx@173
int v137; // ecx@173
void (__thiscall *v138)(_DWORD, _DWORD, _DWORD, _DWORD, _DWORD); // edx@173
int v139; // ecx@173
int v144; // edi@176
int v150; // eax@177
int v151; // eax@178
int v152; // ecx@180
int v153; // ecx@181
int v154; // eax@184
int v155; // eax@185
int v156; // eax@188
int v157; // edx@189
int v158; // eax@191
int v159; // eax@191
int v160; // eax@192
int v161; // eax@194
char v162; // bl@197
void (__thiscall *v163)(_DWORD, _DWORD, _DWORD, _DWORD, _DWORD); // edx@201
int v164; // edi@202
int v165; // eax@202
int v166; // ecx@203
char v168; // zf@207
int v172; // eax@211
__int16 v174; // cx@211
int v175; // edx@211
int v176; // eax@211
int v178; // eax@213
__int16 v179; // cx@213
int v182; // eax@214
__int16 v183; // dx@214
int v189; // ecx@220
__int16 v190; // dx@220
char v191; // al@221
int v192; // ebx@221
int v194; // ecx@222
int v198; // eax@227
signed int v199; // edi@230
int v200; // eax@232
int v201; // ecx@233
int v202; // ecx@239
int v204; // edx@244
int v209; // edx@246
int v213; // ecx@247
int v214; // esi@251
void (__thiscall *v215)(_DWORD, _DWORD, _DWORD, _DWORD, _DWORD); // edx@255
char v219; // [sp-8h] [bp-B4h]@44
signed int v220; // [sp-4h] [bp-B0h]@27
char v221; // [sp+0h] [bp-ACh]@27
char v222; // [sp+4h] [bp-A8h]@44
__int64 v223; // [sp+8h] [bp-A4h]@27
__int64 v224; // [sp+10h] [bp-9Ch]@27
int *v225; // [sp+18h] [bp-94h]@44
__int64 v226; // [sp+28h] [bp-84h]@4
__int64 v227; // [sp+30h] [bp-7Ch]@28
__int64 v228; // [sp+38h] [bp-74h]@19
__int64 v229; // [sp+40h] [bp-6Ch]@27
__int64 v230; // [sp+48h] [bp-64h]@19
int v231; // [sp+50h] [bp-5Ch]@222
int v232; // [sp+54h] [bp-58h]@28
int v233[2]; // [sp+58h] [bp-54h]@34
int v234[2]; // [sp+60h] [bp-4Ch]@28
int v235; // [sp+68h] [bp-44h]@28
int v236; // [sp+6Ch] [bp-40h]@28
int v237; // [sp+70h] [bp-3Ch]@17
int v238; // [sp+74h] [bp-38h]@17
__int64 v239; // [sp+78h] [bp-34h]@28
int v240; // [sp+80h] [bp-2Ch]@29
__int64 v241; // [sp+84h] [bp-28h]@14
float v242; // [sp+8Ch] [bp-20h]@29
__int64 v243; // [sp+90h] [bp-1Ch]@93
int v244; // [sp+98h] [bp-14h]@93
__int64 v245; // [sp+9Ch] [bp-10h]@110
int v246; // [sp+A4h] [bp-8h]@110
int v247; // [sp+A8h] [bp-4h]@2
_ESI = a1;
v5 = *(_DWORD *)(*(_DWORD *)(a1 + 32) + 692);
if ( v5 )
v247 = *(_DWORD *)v5;
else
v247 = 0;
v7 = *(_BYTE *)(a1 + 124) == 0;
BYTE4(v226) = 0;
if ( !v7 )
{
if ( !(unsigned __int8)sub_1061F3E0(a1 + 128) )
{
BYTE4(v226) = 1;
*(_BYTE *)(_ESI + 124) = 0;
}
if ( *(_BYTE *)(_ESI + 124) )
{
v215 = *(void (__thiscall **)(_DWORD, _DWORD, _DWORD, _DWORD, _DWORD))(*(_DWORD *)_ESI + 32);
v232 = 0;
v233[0] = 0;
v215(_ESI, 2, &v232, 0, 0);
LOBYTE(v228) = 0;
HIDWORD(v228) = 0;
v230 = 17179869188i64;
result = a3;
*(_DWORD *)a3 = 2;
LABEL_256:
__asm
{
movq xmm0, [esp+90h+var_74]
movq qword ptr [eax+4], xmm0
}
v229 = 51539607552i64;
__asm
{
movq xmm0, [esp+90h+var_6C]
movq qword ptr [eax+0Ch], xmm0
movq xmm0, qword ptr [esp+2Ch]
movq qword ptr [eax+14h], xmm0
}
*(_DWORD *)(result + 28) = 15;
return result;
}
}
v8 = *(_DWORD *)(_ESI + 156);
if ( v8 )
(*(void (**)(void))(*(_DWORD *)v8 + 12))();
v9 = *(_DWORD *)(_ESI + 156);
v10 = v9 && !(unsigned __int8)(*(int (**)(void))(*(_DWORD *)v9 + 16))();
v11 = sub_100E0B70(_ESI);
LODWORD(v241) = v11;
if ( v10 )
{
sub_105B9910((char *)&v226 + 4, 0, 0);
v12 = *(_DWORD *)(_ESI + 156);
if ( v12 )
{
(**(void (***)(void))v12)();
sub_101B70A0(*(_DWORD *)(_ESI + 156));
}
*(_DWORD *)(_ESI + 156) = 0;
(*(void (__thiscall **)(int, _DWORD))(*(_DWORD *)_ESI + 28))(_ESI, 0);
v14 = *(void (__thiscall **)(_DWORD, _DWORD, _DWORD, _DWORD, _DWORD))(*(_DWORD *)_ESI + 32);
v237 = 0;
v238 = 0;
v14(_ESI, 1, &v237, 0, 0);
v13 = *(_DWORD *)(_ESI + 156);
if ( v13 )
{
(**(void (***)(void))v13)();
sub_101B70A0(*(_DWORD *)(_ESI + 156));
*(_DWORD *)(_ESI + 156) = 0;
}
LOBYTE(v228) = 0;
HIDWORD(v228) = 0;
v230 = 17179869188i64;
result = a3;
*(_DWORD *)a3 = 1;
goto LABEL_256;
}
v16 = *(_DWORD *)(_ESI + 92);
v18 = *(_DWORD *)(_ESI + 96);
v17 = 0;
if ( v16 == v18 )
goto LABEL_259;
do
{
v16 = *(_DWORD *)(v16 + 4);
++v17;
}
while ( v16 != v18 );
if ( v17 )
v19 = *(_DWORD *)(*(_DWORD *)(_ESI + 92) + 8);
else
LABEL_259:
v19 = 0;
if ( sub_100E0B70(_ESI) == v19 && !*(_DWORD *)(_ESI + 156) )
{
(*(void (__stdcall **)(_DWORD))(*(_DWORD *)_ESI + 28))(0);
v20 = *(void (__thiscall **)(_DWORD, _DWORD, _DWORD, _DWORD, _DWORD))(*(_DWORD *)_ESI + 32);
v237 = 0;
v238 = 0;
v20(_ESI, 1, &v237, 0, 0);
LOBYTE(v228) = 0;
HIDWORD(v228) = 0;
__asm { movq xmm0, [esp+90h+var_74] }
v230 = 17179869188i64;
_EAX = &v221;
__asm { movq qword ptr [eax], xmm0 }
v229 = 51539607552i64;
__asm
{
movq xmm0, [esp+0ACh+var_6C]
movq qword ptr [eax+8], xmm0
movq xmm0, qword ptr [esp+48h]
}
v220 = 1;
__asm { movq qword ptr [eax+10h], xmm0 }
sub_100E6380(a3, v220, *(__int64 *)&v221, v223, v224, 15);
return a3;
}
v26 = *(_WORD *)(_ESI + 60);
__asm { movq xmm0, qword ptr [esi+24h] }
_EBX = _ESI + 36;
v235 = *(_DWORD *)(_ESI + 44);
WORD2(v227) = v26;
__asm { movq qword ptr [esp+90h+var_4C], xmm0 }
(*(void (__thiscall **)(int, int *))(*(_DWORD *)v11 + 32))(v11, &v232);
HIDWORD(v239) = (*(int (__thiscall **)(int, _DWORD))(*(_DWORD *)v11 + 36))(v11, *(_DWORD *)(_ESI + 32));
BYTE3(v236) = 0;
if ( BYTE4(v226) )
{
__asm { movq xmm0, qword ptr [esi+80h] }
v29 = *(_WORD *)(_ESI + 140);
v30 = *(_DWORD *)(_ESI + 144);
v235 = *(_DWORD *)(_ESI + 136);
v31 = *(_DWORD *)(_ESI + 148);
__asm
{
movq qword ptr [esp+90h+var_4C], xmm0
movss xmm0, dword ptr [esi+98h]
}
WORD2(v227) = v29;
HIDWORD(v239) = v30;
__asm { movss [esp+90h+var_20], xmm0 }
v240 = v31;
}
else
{
v32 = *(int (__thiscall **)(_DWORD, _DWORD, _DWORD, _DWORD, _DWORD))(*(_DWORD *)v11 + 64);
++*(_DWORD *)(v11 + 36);
v240 = v32(v11, a4, v234, (char *)&v227 + 4, (char *)&v236 + 3);
(*(void (__thiscall **)(int))(*(_DWORD *)v11 + 44))(v11);
v242 = a2;
}
v33 = sub_10571DF0(v234, _ESI + 36);
if ( !v33 || (v34 = WORD2(v227) == *(_WORD *)(_ESI + 60), BYTE4(v241) = 0, !v34) )
BYTE4(v241) = 1;
v233[1] = 0;
BYTE4(v226) = HIDWORD(v239) != 12;
if ( !BYTE3(v236) )
goto LABEL_61;
if ( !(HIDWORD(v239) != 12) )
goto LABEL_68;
if ( v33 || v240 != 2 )
{
LABEL_61:
if ( !BYTE4(v226) || v240 == 3 )
goto LABEL_68;
goto LABEL_63;
}
v35 = *(_DWORD *)(_ESI + 32);
if ( *(_BYTE *)(v35 + 419) )
{
if ( *(_DWORD *)(*(_DWORD *)(*(_DWORD *)(*(_DWORD *)(v35 + 396) + 8) + 5420) + 160) == _ESI )
{
v36 = ((int (*)(void))sub_101F4F90)();
LOBYTE(v36) = !(_BYTE)v36 && (v36 = sub_1026C750(*(_DWORD *)(_ESI + 32)), !(_BYTE)v36);
v38 = *(_DWORD *)(_ESI + 32);
v39 = *(_DWORD *)(*(_DWORD *)(v38 + 396) + 8);
*(float *)&v225 = 3.402823466385289e38;
HIDWORD(v224) = v36;
v40 = sub_1042BF80(v38, v39);
__asm { movq xmm0, qword ptr [esp+98h+var_4C] }
v42 = v235;
v43 = *(_DWORD *)(_ESI + 44);
LODWORD(v224) = v40;
_EAX = &v222;
__asm
{
movq qword ptr [eax], xmm0
movq xmm0, qword ptr [ebx]
}
HIDWORD(v223) = v42;
_EAX = &v219;
__asm { movq qword ptr [eax], xmm0 }
v37 = sub_1060ADE0(v219, v220, v43, v222, v223, HIDWORD(v223), v224, HIDWORD(v224), (char)v225);
}
else
{
v47 = ((int (*)(void))sub_101F4F90)();
LOBYTE(v47) = !(_BYTE)v47 && (v47 = sub_1026C750(*(_DWORD *)(_ESI + 32)), !(_BYTE)v47);
v48 = *(_DWORD *)(_ESI + 32);
v49 = *(_DWORD *)(*(_DWORD *)(v48 + 396) + 8);
*(float *)&v225 = 3.402823466385289e38;
HIDWORD(v224) = v47;
v50 = sub_1042BF80(v48, v49);
__asm { movq xmm0, qword ptr [esp+98h+var_4C] }
v52 = v235;
v53 = *(_DWORD *)(_ESI + 44);
LODWORD(v224) = v50;
_EAX = &v222;
__asm
{
movq qword ptr [eax], xmm0
movq xmm0, qword ptr [ebx]
}
HIDWORD(v223) = v52;
_EAX = &v219;
__asm { movq qword ptr [eax], xmm0 }
v37 = sub_10157500(v219, v220, v53, v222, v223, HIDWORD(v223), v224, HIDWORD(v224), (char)v225);
}
BYTE4(v226) = v37;
if ( !v37 )
{
if ( v232 )
{
v57 = sub_10697F40(*(_DWORD *)(_ESI + 32), v232, 3.402823466385289e38);
}
else
{
if ( !v233[0] )
goto LABEL_68;
v57 = sub_10206660(*(_DWORD *)(_ESI + 32), v233[0], 3.402823466385289e38);
}
LABEL_60:
BYTE4(v226) = v57;
goto LABEL_61;
}
}
else
{
BYTE4(v226) = sub_106BA160(_ESI, _ESI + 36, (int)v234, 3.402823466385289e38);
if ( !BYTE4(v226) )
{
if ( v232 )
{
v57 = sub_103B31E0(_ESI, *(_DWORD *)(_ESI + 32), v232, 3.402823466385289e38);
}
else
{
if ( !v233[0] )
goto LABEL_68;
v57 = sub_10678EA0(_ESI, *(_DWORD *)(_ESI + 32), v233[0], 3.402823466385289e38);
}
goto LABEL_60;
}
}
LABEL_63:
v59 = (unsigned __int8)(*(int (**)(void))(*(_DWORD *)v241 + 4))() == 0;
v58 = *(_DWORD *)(_ESI + 156);
if ( v59 )
{
v225 = &v233[1];
HIDWORD(v224) = HIDWORD(v241);
}
else
{
v60 = HIDWORD(v241);
v237 = 0;
v238 = 0;
BYTE4(v226) = sub_10559C70(_ESI, v234, HIDWORD(v239), &v237, v58, SBYTE4(v241), &v233[1]);
if ( BYTE4(v226) )
goto LABEL_68;
v58 = *(_DWORD *)(_ESI + 156);
v225 = &v233[1];
HIDWORD(v224) = v60;
}
BYTE4(v226) = sub_10144A00(_ESI, v234, HIDWORD(v239), &v232, v58, HIDWORD(v224), v225);
LABEL_68:
if ( !BYTE4(v241) )
goto LABEL_221;
if ( (unsigned __int8)sub_10571DF0(v234, _ESI + 36) )
goto LABEL_114;
v61 = *(_DWORD *)(*(_DWORD *)(*(_DWORD *)(_ESI + 32) + 396) + 8);
if ( *(_DWORD *)(*(_DWORD *)(v61 + 5420) + 160) != _ESI )
{
if ( v233[1] == 3 )
{
v92 = v235;
__asm { movq xmm0, qword ptr [esp+90h+var_4C] }
v94 = WORD2(v227);
v95 = HIDWORD(v239);
__asm { movq qword ptr [esi+80h], xmm0 }
*(_DWORD *)(_ESI + 136) = v92;
v96 = v240;
*(_WORD *)(_ESI + 140) = v94;
*(_DWORD *)(_ESI + 144) = v95;
*(_DWORD *)(_ESI + 148) = v96;
LABEL_121:
__asm { movss xmm0, [esp+90h+var_20] }
v100 = *(void (__thiscall **)(_DWORD, _DWORD, _DWORD, _DWORD, _DWORD))(*(_DWORD *)_ESI + 32);
v225 = 0;
HIDWORD(v224) = 0;
LODWORD(v224) = &v232;
HIDWORD(v223) = 2;
v101 = _ESI;
*(_BYTE *)(_ESI + 124) = 1;
__asm { movss dword ptr [esi+98h], xmm0 }
v100(v101, HIDWORD(v223), v224, HIDWORD(v224), v225);
LOBYTE(v228) = 0;
HIDWORD(v228) = 0;
v98 = 0;
v230 = 17179869188i64;
_EAX = &v221;
v220 = 2;
goto LABEL_122;
}
if ( v233[1] != 1 && (v233[1] != 2 || (unsigned __int8)sub_106AC630(*(_DWORD *)(v61 + 5428))) )
goto LABEL_114;
__asm
{
movq xmm0, qword ptr [esp+90h+var_4C]
movq [esp+90h+var_1C], xmm0
}
v244 = v235;
if ( v233[1] == 1
&& !(unsigned __int8)(*(int (__thiscall **)(_DWORD, __int64 *))(*(_DWORD *)v241 + 60))(v241, &v243) )
{
BYTE4(v226) = 0;
goto LABEL_114;
}
v225 = *(int **)(_ESI + 32);
sub_103CCAB0(v225);
if ( *(_DWORD *)(*(_DWORD *)(*(_DWORD *)(*(_DWORD *)(*(_DWORD *)(_ESI + 32) + 396) + 8) + 5420) + 160)
|| v233[1] == 1 && !(unsigned __int8)sub_100C9AB0(&v243, HIDWORD(v239)) )
{
__asm { movq xmm0, qword ptr [esp+90h+var_4C] }
v134 = v235;
v135 = HIDWORD(v239);
v136 = WORD2(v227);
v225 = 0;
__asm
{
movq qword ptr [esi+80h], xmm0
movss xmm0, [esp+94h+var_20]
}
*(_DWORD *)(_ESI + 136) = v134;
v137 = v240;
*(_DWORD *)(_ESI + 144) = v135;
HIDWORD(v224) = 0;
*(_WORD *)(_ESI + 140) = v136;
v138 = *(void (__thiscall **)(_DWORD, _DWORD, _DWORD, _DWORD, _DWORD))(*(_DWORD *)_ESI + 32);
LODWORD(v224) = &v232;
*(_DWORD *)(_ESI + 148) = v137;
HIDWORD(v223) = 2;
v139 = _ESI;
*(_BYTE *)(_ESI + 124) = 1;
__asm { movss dword ptr [esi+98h], xmm0 }
v138(v139, HIDWORD(v223), v224, HIDWORD(v224), v225);
LOBYTE(v228) = 0;
HIDWORD(v228) = 0;
__asm { movq xmm0, [esp+90h+var_74] }
v229 = 51539607552i64;
v230 = 17179869188i64;
_EAX = &v221;
__asm
{
movq qword ptr [eax], xmm0
movq xmm0, [esp+0ACh+var_6C]
movq qword ptr [eax+8], xmm0
movq xmm0, qword ptr [esp+48h]
}
v220 = 2;
__asm { movq qword ptr [eax+10h], xmm0 }
sub_100E6380(a3, v220, *(__int64 *)&v221, v223, v224, 15);
sub_103D7930(v238);
return a3;
}
sub_103D7930(v238);
v107 = 2;
if ( v233[1] == 2 )
{
if ( v232 )
{
_EAX = sub_101FFC00(v232);
__asm
{
movq xmm0, qword ptr [eax]
movq [esp+90h+var_1C], xmm0
}
v244 = *(_DWORD *)(_EAX + 8);
}
else
{
if ( v233[0] )
{
_EAX = (*(int (**)(void))(*(_DWORD *)v233[0] + 72))();
__asm
{
movq xmm0, qword ptr [eax]
movq [esp+90h+var_1C], xmm0
}
v244 = *(_DWORD *)(_EAX + 8);
}
}
if ( (unsigned __int8)sub_101F4F90(*(_DWORD *)(_ESI + 32))
|| (unsigned __int8)sub_1026C750(*(_DWORD *)(_ESI + 32)) )
{
v112 = *(_DWORD *)(_ESI + 156);
if ( !v112 || (unsigned __int8)(*(int (**)(void))(*(_DWORD *)v112 + 44))() )
{
if ( !(dword_119076D8 & 2) )
{
dword_119076D8 |= 2u;
dword_119076BC = 0;
dword_119076C0 = 0;
dword_119076C4 = 0;
atexit(sub_11338E60);
}
v113 = *(int **)(*(_DWORD *)(_ESI + 32) + 692);
if ( v113 )
v114 = *v113;
else
v114 = 0;
v237 = v114;
sub_1008A5C0(&v237);
if ( v232 )
{
v115 = *(int **)(v232 + 692);
if ( v115 )
v116 = *v115;
else
v116 = 0;
v237 = v116;
sub_1008A5C0(&v237);
v118 = *(_DWORD *)(_ESI + 32);
v237 = v232;
v117 = *(_DWORD *)(v232 + 692);
if ( v117 )
LODWORD(v227) = *(_DWORD *)v117;
else
LODWORD(v227) = 0;
v119 = *(_DWORD *)(v118 + 692);
if ( v119 )
v120 = *(_DWORD *)v119;
else
v120 = 0;
v121 = (*(int (__thiscall **)(int))(*(_DWORD *)_ESI + 36))(_ESI);
sub_1061B980(v120, v227, v118, v237, &unk_119076B8, v121);
}
else
{
if ( v233[0] )
{
v237 = (*(int (**)(void))(*(_DWORD *)v233[0] + 16))();
sub_1008A5C0(&v237);
v124 = *(_DWORD *)(_ESI + 32);
v122 = *(_DWORD *)(v124 + 692);
v123 = v233[0];
if ( v122 )
LODWORD(v227) = *(_DWORD *)v122;
else
LODWORD(v227) = 0;
v125 = (*(int (__thiscall **)(int))(*(_DWORD *)_ESI + 36))(_ESI);
v126 = *(_DWORD *)v123;
v225 = (int *)v125;
v127 = *(int (**)(void))(v126 + 16);
HIDWORD(v224) = &unk_119076B8;
LODWORD(v224) = v123;
HIDWORD(v223) = v124;
v128 = v127();
sub_10505740(v227, v128, HIDWORD(v223), v224, HIDWORD(v224), v225);
}
}
v129 = *(_DWORD *)(_ESI + 156);
__asm
{
movq xmm0, qword ptr [esp+90h+var_4C]
movq [esp+90h+var_10], xmm0
}
v246 = v235;
if ( v129 )
{
if ( *(_DWORD *)(v129 + 8) )
{
_EAX = sub_10628480(&v237);
__asm
{
movq xmm0, qword ptr [eax]
movq [esp+90h+var_10], xmm0
}
v246 = *(_DWORD *)(_EAX + 8);
}
}
sub_10197970(&v243, &v245, &unk_119076B8);
dword_119076C0 = 0;
v107 = 2;
}
}
}
sub_1060F240(_ESI, &v243, v233[1]);
if ( !(unsigned __int8)(*(int (**)(void))(*(_DWORD *)v241 + 4))()
|| v233[1] != v107
|| (unsigned __int8)sub_101F4F90(*(_DWORD *)(_ESI + 32))
|| (unsigned __int8)sub_1026C750(*(_DWORD *)(_ESI + 32)) )
goto LABEL_114;
goto LABEL_172;
}
if ( !BYTE4(v226) )
goto LABEL_114;
if ( v233[1] == 3 || !v233[1] )
{
sub_100FF540(_ESI);
goto LABEL_114;
}
v62 = v241;
if ( (unsigned __int8)(*(int (__thiscall **)(_DWORD))(*(_DWORD *)v241 + 4))(v241) && v233[1] == 2 )
{
if ( (unsigned __int8)sub_101F4F90(*(_DWORD *)(_ESI + 32)) || (unsigned __int8)sub_1026C750(*(_DWORD *)(_ESI + 32)) )
{
if ( !(unsigned __int8)sub_105B8700(*(_DWORD *)(*(_DWORD *)(*(_DWORD *)(*(_DWORD *)(_ESI + 32) + 396) + 8) + 5428)) )
goto LABEL_81;
if ( sub_104034F0(*(_DWORD *)(*(_DWORD *)(*(_DWORD *)(*(_DWORD *)(_ESI + 32) + 396) + 8) + 5428)) != *(_DWORD *)(_ESI + 32) )
{
v62 = v241;
goto LABEL_81;
}
}
LABEL_172:
*(_BYTE *)(*(_DWORD *)(*(_DWORD *)(*(_DWORD *)(*(_DWORD *)(_ESI + 32) + 396) + 8) + 5420) + 180) = 1;
goto LABEL_114;
}
LABEL_81:
if ( (unsigned __int8)sub_101F4F90(*(_DWORD *)(_ESI + 32)) || (unsigned __int8)sub_1026C750(*(_DWORD *)(_ESI + 32)) )
{
v63 = *(_DWORD *)(_ESI + 156);
v64 = 0;
if ( !v63 || (unsigned __int8)(*(int (**)(void))(*(_DWORD *)v63 + 44))() )
{
if ( (v233[1] == 2 || (unsigned __int8)(*(int (__thiscall **)(int))(*(_DWORD *)v62 + 4))(v62))
&& (unsigned __int8)sub_105FD3D0(2) )
{
if ( !(dword_119076D8 & 1) )
{
dword_119076D8 |= 1u;
dword_119076CC = 0;
dword_119076D0 = 0;
dword_119076D4 = 0;
atexit(sub_11338E80);
}
v65 = *(_DWORD *)(*(_DWORD *)(_ESI + 32) + 692);
if ( v65 )
v66 = *(_DWORD *)v65;
else
v66 = 0;
LODWORD(v227) = v66;
sub_1008A5C0(&v227);
__asm
{
movq xmm0, qword ptr [esp+90h+var_4C]
movq [esp+90h+var_1C], xmm0
}
v244 = v235;
if ( v232 )
{
v68 = *(_DWORD *)(v232 + 692);
if ( v68 )
v69 = *(_DWORD *)v68;
else
v69 = 0;
LODWORD(v227) = v69;
sub_1008A5C0(&v227);
v71 = *(_DWORD *)(_ESI + 32);
v237 = v232;
v70 = *(_DWORD *)(v232 + 692);
if ( v70 )
LODWORD(v227) = *(_DWORD *)v70;
else
LODWORD(v227) = 0;
v72 = *(_DWORD *)(v71 + 692);
if ( v72 )
v73 = *(_DWORD *)v72;
else
v73 = 0;
v74 = (*(int (__thiscall **)(_DWORD))(*(_DWORD *)_ESI + 36))(_ESI);
sub_1061B980(v73, v227, v71, v237, &unk_119076C8, v74);
_EAX = sub_101FFC00(v232);
__asm
{
movq xmm0, qword ptr [eax]
movq [esp+90h+var_1C], xmm0
}
v244 = *(_DWORD *)(_EAX + 8);
}
else
{
if ( !v233[0] )
{
LABEL_110:
v86 = *(_DWORD *)(_ESI + 156);
__asm
{
movq xmm0, qword ptr [esp+90h+var_4C]
movq [esp+90h+var_10], xmm0
}
v246 = v235;
if ( v86 != v64 )
{
if ( *(_DWORD *)(v86 + 8) != v64 )
{
_EAX = sub_10628480(&v237);
__asm
{
movq xmm0, qword ptr [eax]
movq [esp+90h+var_10], xmm0
}
v246 = *(_DWORD *)(_EAX + 8);
}
}
sub_10197970(&v243, &v245, &unk_119076C8);
dword_119076D0 = v64;
goto LABEL_114;
}
v237 = (*(int (**)(void))(*(_DWORD *)v233[0] + 16))();
sub_1008A5C0(&v237);
v78 = *(_DWORD *)(_ESI + 32);
v77 = *(_DWORD *)(v78 + 692);
v79 = v233[0];
if ( v77 )
LODWORD(v227) = *(_DWORD *)v77;
else
LODWORD(v227) = 0;
v80 = (*(int (__thiscall **)(_DWORD))(*(_DWORD *)_ESI + 36))(_ESI);
v81 = *(_DWORD *)v79;
v225 = (int *)v80;
HIDWORD(v224) = &unk_119076C8;
LODWORD(v224) = v79;
v82 = *(int (__thiscall **)(_DWORD))(v81 + 16);
HIDWORD(v223) = v78;
v83 = v82(v79);
sub_10505740(v227, v83, HIDWORD(v223), v224, HIDWORD(v224), v225);
_EAX = (*(int (**)(void))(*(_DWORD *)v233[0] + 72))();
__asm
{
movq xmm0, qword ptr [eax]
movq [esp+90h+var_1C], xmm0
}
v244 = *(_DWORD *)(_EAX + 8);
}
v64 = 0;
goto LABEL_110;
}
}
}
LABEL_114:
if ( (unsigned __int8)(*(int (__thiscall **)(_DWORD))(*(_DWORD *)_ESI + 36))(_ESI) )
{
if ( !(unsigned __int8)sub_10571DF0(v234, _ESI + 36) )
{
v90 = *(_DWORD *)(*(_DWORD *)(_ESI + 32) + 692);
if ( v90 )
v91 = *(_DWORD *)v90;
else
v91 = 0;
if ( !(unsigned __int8)sub_10453D70(v91) )
{
__asm
{
movss xmm0, ds:dword_113C3980
cvtsi2ss xmm1, [esp+90h+var_4C+4]
mulss xmm1, xmm0
movss [esp+90h+var_3C], xmm1
cvtsi2ss xmm1, [esp+90h+var_44]
mulss xmm1, xmm0
movss [esp+90h+var_38], xmm1
}
v144 = sub_104CA9E0(&v237);
if ( v144 )
{
v150 = *(_DWORD *)(*(_DWORD *)(_ESI + 32) + 692);
if ( v150 )
v151 = *(_DWORD *)v150;
else
v151 = 0;
v152 = *(_DWORD *)(v144 + 248);
if ( v152 )
v153 = *(_DWORD *)v152;
else
v153 = 0;
if ( (unsigned __int8)sub_105DE830(v153, v151) )
{
v154 = *(_DWORD *)(v144 + 248);
if ( v154 )
v155 = *(_DWORD *)v154;
else
v155 = 0;
if ( !(unsigned __int8)sub_10453D70(v155) )
{
v156 = *(_DWORD *)(v144 + 248);
if ( v156 )
v157 = *(_DWORD *)v156;
else
v157 = 0;
v159 = sub_103573E0(v157);
sub_10643AA0(v159);
v158 = *(_DWORD *)(*(_DWORD *)(_ESI + 32) + 692);
if ( v158 )
v160 = *(_DWORD *)v158;
else
v160 = 0;
v161 = sub_103573E0(v160);
sub_10643AA0(v161);
}
}
}
}
}
}
v225 = *(int **)(_ESI + 32);
sub_105403B0(v225);
(*(void (__thiscall **)(int, _DWORD))(*(_DWORD *)_ESI + 28))(_ESI, 0);
LOBYTE(v227) = 0;
if ( (unsigned __int8)sub_101758E0(v234, _ESI) )
{
BYTE4(v226) = 0;
LOBYTE(v227) = 1;
}
v162 = 0;
if ( sub_10D28370(*(_DWORD *)(*(_DWORD *)(*(_DWORD *)(*(_DWORD *)(_ESI + 32) + 396) + 8) + 5428) + 84) != 1 )
{
if ( !BYTE4(v226) )
goto LABEL_200;
if ( (unsigned __int8)sub_1061F3E0(v234) )
{
v172 = v235;
__asm { movq xmm0, qword ptr [esp+90h+var_4C] }
v174 = WORD2(v227);
v175 = HIDWORD(v239);
__asm { movq qword ptr [esi+80h], xmm0 }
*(_DWORD *)(_ESI + 136) = v172;
v176 = v240;
*(_WORD *)(_ESI + 140) = v174;
*(_DWORD *)(_ESI + 144) = v175;
*(_DWORD *)(_ESI + 148) = v176;
goto LABEL_121;
}
if ( a5 )
{
__asm { movq xmm0, qword ptr [esi+24h] }
v178 = *(_DWORD *)(_ESI + 44);
*(float *)(_ESI + 84) = *(float *)(_ESI + 80);
v179 = *(_WORD *)(_ESI + 60);
__asm { movq qword ptr [esi+40h], xmm0 }
*(_DWORD *)(_ESI + 72) = v178;
*(_WORD *)(_ESI + 76) = v179;
}
__asm { movq xmm0, qword ptr [esp+90h+var_4C] }
v182 = v235;
v183 = WORD2(v227);
__asm
{
movq qword ptr [esi+24h], xmm0
movss xmm0, [esp+90h+var_20]
}
*(_DWORD *)(_ESI + 44) = v182;
*(_WORD *)(_ESI + 60) = v183;
*(_DWORD *)(_ESI + 172) = 0;
_EAX = *(_DWORD *)(_ESI + 156);
__asm { movss dword ptr [esi+50h], xmm0 }
if ( _EAX )
{
__asm { comiss xmm0, dword ptr [eax+0Ch] }
if ( !(_CF | _ZF) )
__asm { movss dword ptr [eax+0Ch], xmm0 }
}
if ( *(_BYTE *)(_ESI + 62) == 1 || v240 == 2 || v240 == 3 )
{
__asm { movq xmm0, qword ptr [esi+24h] }
v189 = *(_DWORD *)(_ESI + 44);
*(float *)(_ESI + 84) = *(float *)(_ESI + 80);
v190 = *(_WORD *)(_ESI + 60);
__asm { movq qword ptr [esi+40h], xmm0 }
*(_BYTE *)(_ESI + 62) = 0;
*(_DWORD *)(_ESI + 72) = v189;
*(_WORD *)(_ESI + 76) = v190;
}
LABEL_221:
v192 = v241;
v191 = (*(int (__thiscall **)(_DWORD))(*(_DWORD *)v241 + 4))(v241);
if ( v191 ) // MASTERGH возможно ключевой момент, возможно условия выделеная ли Армия пользователя?
{
while ( 1 ) //mastergh возможно цикл когда Выделена Армия пользователя
{
(*(void (__thiscall **)(int, __int64 *))(*(_DWORD *)v192 + 16))(v192, &v228);
__asm { movq xmm0, [esp+90h+var_74] }
v194 = v231;
_EAX = &v221;
__asm
{
movq qword ptr [eax], xmm0
movq xmm0, [esp+0ACh+var_6C]
movq qword ptr [eax+8], xmm0
movq xmm0, qword ptr [esp+48h]
movq qword ptr [eax+10h], xmm0
}
sub_10339480(v221, *(_DWORD *)&v222, v223, HIDWORD(v223), v224, HIDWORD(v224), v194);
if ( !HIDWORD(v230) )
{
v102 = v231;
_EAX = &v221;
v220 = 3;
goto LABEL_123;
}
if ( (_BYTE)v228 )
{
__asm { movq xmm0, [esp+90h+var_74] }
v204 = v231;
_EAX = &v221;
__asm
{
movq qword ptr [eax], xmm0
movq xmm0, [esp+0ACh+var_6C]
movq qword ptr [eax+8], xmm0
movq xmm0, qword ptr [esp+48h]
movq qword ptr [eax+10h], xmm0
}
v225 = (int *)v204;
v220 = 4;
goto LABEL_124; LABEL_230; // masterGH - выход на LABEL_124
}
if ( HIDWORD(v230) == 3 )
{
sub_103D8D20(_ESI); // mastergh - кщё функция
v102 = v231;
_EAX = &v221;
v220 = 5;
goto LABEL_123; // masterGH - выход на LABEL_123
}
if ( HIDWORD(v230) == 1 || HIDWORD(v229) != 12 )
break;
sub_103D8D20(_ESI); // mastergh (1 вхождение) (в sub_103D8D20) : shogun2.dll+25635e
v198 = sub_100E0B70(_ESI);
v192 = v198;
if ( v198 && !(unsigned __int8)(*(int (__thiscall **)(int))(*(_DWORD *)v198 + 4))(v198) )
{
v191 = v192 == sub_1031A3A0(_ESI);
goto LABEL_230; // masterGH - выход на LABEL_230
}
}
sub_103D8D20(_ESI); // mastergh функция
__asm { movq xmm0, [esp+90h+var_74] }
v209 = v231;
_EAX = &v221;
__asm
{
movq qword ptr [eax], xmm0
movq xmm0, [esp+0ACh+var_6C]
movq qword ptr [eax+8], xmm0
movq xmm0, qword ptr [esp+48h]
movq qword ptr [eax+10h], xmm0
}
v225 = (int *)v209;
v220 = 6;
goto LABEL_124; // mastergh выход на LABEL_124
}
LABEL_230:
v199 = 0;
if ( v191 )
v199 = 1;
v200 = sub_1031A3A0(_ESI);
if ( v192 == v200 )
{
v201 = *(_DWORD *)(_ESI + 156);
if ( v201 )
{
v200 = (*(int (**)(void))(*(_DWORD *)v201 + 20))();
if ( (_BYTE)v200 )
v199 = 1;
}
}
if ( BYTE4(v241) || v199 == 1 )
{
LOBYTE(v200) = BYTE4(v241) == 0;
(*(void (__thiscall **)(int, signed int, int *, int, _DWORD))(*(_DWORD *)_ESI + 32))(_ESI, v199, &v232, v200, 0);
}
v202 = *(_DWORD *)(_ESI + 156);
if ( v202 && (unsigned __int8)(*(int (**)(void))(*(_DWORD *)v202 + 4))() )
{
if ( (unsigned __int8)sub_101B70A0(*(_DWORD *)(_ESI + 156)) )
*(_DWORD *)(_ESI + 156) = 0;
}
else
{
v213 = *(_DWORD *)(_ESI + 156);
if ( !v213 || (unsigned __int8)(*(int (**)(void))(*(_DWORD *)v213 + 16))() )
{
if ( v192 == sub_1031A3A0(_ESI) )
{
v214 = *(_DWORD *)(_ESI + 156);
if ( v214 )
{
if ( (unsigned __int8)(*(int (__thiscall **)(int))(*(_DWORD *)v214 + 24))(v214) )
v199 = 1;
}
}
}
else
{
sub_101B70A0(*(_DWORD *)(_ESI + 156));
*(_DWORD *)(_ESI + 156) = 0;
}
}
HIDWORD(v228) = 0;
v98 = 0;
v230 = 17179869188i64;
_EAX = &v221;
LOBYTE(v228) = 0;
v220 = v199;
LABEL_122:
LODWORD(v229) = v98;
v102 = 15;
HIDWORD(v229) = 12;
LABEL_123:
__asm
{
movq xmm0, [esp+0B0h+var_74]
movq qword ptr [eax], xmm0
movq xmm0, [esp+0B0h+var_6C]
movq qword ptr [eax+8], xmm0
movq xmm0, qword ptr [esp+4Ch]
movq qword ptr [eax+10h], xmm0
}
*((_DWORD *)_EAX + 6) = v102;
LABEL_124:
sub_100E6380(a3, v220, *(__int64 *)&v221, v223, v224, v225);
return a3;
}
v162 = 1;
LABEL_200:
sub_1059DCD0(
(char *)&v226 + 4,
0,
v227,
*(_BYTE *)(*(_DWORD *)(*(_DWORD *)(*(_DWORD *)(*(_DWORD *)(_ESI + 32) + 396) + 8) + 5420) + 61),
0);
if ( BYTE5(v226) )
{
v163 = *(void (__thiscall **)(_DWORD, _DWORD, _DWORD, _DWORD, _DWORD))(*(_DWORD *)_ESI + 32);
v225 = 0;
HIDWORD(v224) = 0;
LODWORD(v224) = &v232;
HIDWORD(v223) = 0;
}
else
{
v164 = *(_DWORD *)_ESI + 32;
v165 = sub_105B8700(*(_DWORD *)(*(_DWORD *)(*(_DWORD *)(*(_DWORD *)(_ESI + 32) + 396) + 8) + 5428));
v163 = *(void (__thiscall **)(_DWORD, _DWORD, _DWORD, _DWORD, _DWORD))v164;
v225 = (int *)v165;
HIDWORD(v224) = 0;
LODWORD(v224) = &v232;
HIDWORD(v223) = 1;
}
v163(_ESI, HIDWORD(v223), v224, HIDWORD(v224), v225);
v166 = *(_DWORD *)(_ESI + 156);
if ( v166 )
(**(void (***)(void))v166)();
if ( !v162 )
{
v225 = *(int **)(_ESI + 32);
sub_100554B0(v225);
}
HIDWORD(v228) = 0;
LOBYTE(v228) = 0;
__asm { movq xmm0, [esp+90h+var_74] }
v168 = BYTE5(v226) == 0;
v229 = 51539607552i64;
v230 = 17179869188i64;
_EAX = &v221;
__asm
{
movq qword ptr [eax], xmm0
movq xmm0, [esp+0ACh+var_6C]
movq qword ptr [eax+8], xmm0
movq xmm0, qword ptr [esp+48h]
movq qword ptr [eax+10h], xmm0
}
v225 = (int *)15;
if ( v168 )
{
sub_100E6380(a3, 1, *(__int64 *)&v221, v223, v224, v225);
result = a3;
}
else
{
sub_100E6380(a3, 0, *(__int64 *)&v221, v223, v224, v225);
result = a3;
}
return result;
}Осталось только проверить в отладке моё предположение о том выделен лы был игрок. Но это я сделаю не сегодня.
-
Это в теории его должны применять в большинстве. На практике могут и не писать такую поддержку, а могут даже наоборот "перестараться" и добавить опцию включения и отключения аппаратного курсора для мышки. Насколько я предполагаю если эта поддержка выключения, то клики будут обрабатываться стандартно от сообщений обрабатываемых в функции привязанной к окну....
По теме...
Перевел я на псевдокод функцию уменьшающие шаги:
int __thiscall sub_10654450(void *this, int a2)
void *this - указатель на некоторую структуру Пользователя или бота
int a2 - кол-во шагов которое желает выполнить *this
return - наверно значение ошибки...
Функция перебирает группы привязанные к *this и отнимает шаги перемещения.
Эта функция находиться в окрестностях адреса вычитания очков перещения:
Shogun2.dll+68DEB2 - 89 50 6C - mov [eax+6C],edx
int __thiscall sub_10654450(void *this, int a2)
{
int result; // eax@1
char *v3; // ecx@1
int v4; // esi@1
int v5; // eax@2
int v6; // edx@2
v3 = (char *)this + 148;
v4 = *((_DWORD *)v3 + 5);
for ( result = v4 + 4 * *((_DWORD *)v3 + 4); // начальное значения для начала цикла
v4 != result; // условие выполнение цикла пока истино v4 != result
result = *((_DWORD *)v3 + 5) + 4 * *((_DWORD *)v3 + 4) ) // действие при каждой повторении цикла
{
v5 = **(_DWORD **)v4; // v5 = адрес группы (v5 теперь является подгруппой *this)
v6 = *(_DWORD *)(v5 + 0x6C); // v6 = разрешённых шагов для группы v5
if ( v6 <= a2 ) // если разрешённых шагов меньше например 3, когда попытка пойти на 5, то
*(_DWORD *)(v5 + 0x6C) = 0; // присвоить v5 перемещение 0
else // иначе
*(_DWORD *)(v5 + 0x6C) = v6 - a2; // присворить v5 разность между разршенными шагами и "сделанными"
*(_DWORD *)(v5 + 0x898) = -1; // какое-то интересное смещение +0x898, что означает точно не понятно.
// по карайне мере понятно, что оно стаиться в -1, когда v5 было установленно
// кол-во разрешённых шагов
v4 += 4; // перебираем следующую группу
}
return result;
}Переписываем функцию так, чтобы она давала шаги отряду вместо того чтобы забирать их.
int __thiscall Cheat_SetPointMove(void *unit, int a2)
{
int result; // eax@1
char *v3; // ecx@1
int v4; // esi@1
int v5; // eax@2
int v6; // edx@2
v3 = (char *)unit + 148;
v4 = *((_DWORD *)v3 + 5);
for ( result = v4 + 4 * *((_DWORD *)v3 + 4);
v4 != result;
result = *((_DWORD *)v3 + 5) + 4 * *((_DWORD *)v3 + 4) )
{
v5 = **(_DWORD **)v4;
v6 = *(_DWORD *)(v5 + 0x6C);
if ( v6 <= 1000000 )
*(_DWORD *)(v5 + 0x6C) = a2;
*(_DWORD *)(v5 + 0x898) = -1;
v4 += 4;
}
return result;
}Эта функция обязательно пригодиться, когда при инициализации чита нужно чтобы сарзу всем героям Пользователя дать необходимое кол-во очков например 500000.
void units = GetPlayerObjects();
Cheat_SetPointMove(void &units, 500000);
Дальше нужно не вызывать функцию sub_10654450 если units принадлежит не Player.
Для этого нужно изменить sub_10654450:
int __thiscall sub_10654450(void *this, int a2)
{
int result; // eax@1
char *v3; // ecx@1
int v4; // esi@1
int v5; // eax@2
int v6; // edx@2
// инъекция пвсевод-кода
void playerUnits = GetPlayerObjects();
if (playerUnits==this)
{
Cheat_SetPointMove(playerUnits,500000)
return;
}
//=====================
v3 = (char *)this + 148;
v4 = *((_DWORD *)v3 + 5);
for ( result = v4 + 4 * *((_DWORD *)v3 + 4); // начальное значения для начала цикла
v4 != result; // условие выполнение цикла пока истино v4 != result
result = *((_DWORD *)v3 + 5) + 4 * *((_DWORD *)v3 + 4) ) // действие при каждой повторении цикла
{
v5 = **(_DWORD **)v4; // v5 = адрес группы (v5 теперь является подгруппой *this)
v6 = *(_DWORD *)(v5 + 0x6C); // v6 = разрешённых шагов для группы v5
if ( v6 <= a2 ) // если разрешённых шагов меньше например 3, когда попытка пойти на 5, то
*(_DWORD *)(v5 + 0x6C) = 0; // присвоить v5 перемещение 0
else // иначе
*(_DWORD *)(v5 + 0x6C) = v6 - a2; // присворить v5 разность между разршенными шагами и "сделанными"
*(_DWORD *)(v5 + 0x898) = -1; // какое-то интересное смещение +0x898, что означает точно не понятно.
// по карайне мере понятно, что оно стаиться в -1, когда v5 было установленно
// кол-во разрешённых шагов
v4 += 4; // перебираем следующую группу
}
return result;
}Чтобы функцию перевести на машинныкод, лучше скопироват старую в машинном коде и изменить её.
Дальше исследовать пока нет времени. Надо идти вверх по call-ам и разобраться с указателем ecx передаваемым в функцию sub_10654450... Фактически мы должны дойти до развилки имеет ли право идти игрок. Там должен быть код определения игрока. Если это игрок, если его очки хода больше 0, то разрешить ему перемещение.
Возможно, будет сложно. Например, один поток который собирает сообщение от ДайректИнпут запишет некоторой новое событие в в некотурую очередь собщений о том что надо пердвинуть отряд, а другой поток будет читать эту очередь...
Ладно, дальше будет видно.
Что касается вопросов по OllyDbg.
OllyDbg видимо снёс Xipho. Поэтому этот вопрос прямо к нему
у нас была OllyShadow.
Иногда OllyDbg не может обрабатывать инструкции и неизбежно придётся перезагружать процесс игры. И это касается трейсинга. Возможно не повезло. А возможно стоит поставить игнор исключений в настройках. Долго об этом писать.
movq вообще интресная инструкция связанная с глюками. Если например она работать с адресом не кратным "как это говорят параграфу", то что-то будет нестабильное... Я думаю если можно как-то в трейсинге отметить что такой-то участок не трейсить, то предлагаю это сделать.
По пункту два. Это обычное явление... более прокомментировать как решить проблему с трассировкой не могу, т.к. без понятия.
-
Как написал Xipho по этому скрипту нет ответа почему именно такие смещения прибавляются к регистрам. Эти смещения я когда-то давно искал в отладчике реверсингом совместно со сканером памяти.
Суть в том что по выражению [[core.dll+00155744h]+350h]+43Ch находится указатель на адрес здоровья героя. И если этот адрес совпадает с eax на участке кода куда была сделана инъекция, то записать в этот адрес 250 очков здоровь. Если этого не сделать, то все игроки будут бессмертными.
Но что здесь неправильно, а то что имея полноценный указатель чуть более правильнее записывать в него данные без сравнения.
Именно эту запись нужно делать циклически
[[[core.dll+0x00155744]+0x350]+0x43C] = 250
Вот так...
push ebx
mov ebx,[core.dll+00155744]
mov ebx,[ebx+350]
mov byte ptr [ebx+43C],#250
pop ebx
originalcode:
mov ecx,[eax]
mov edx,[esp+04]
.... -
Откуда такая информация что в большинстве?
Лично я в Дисайплс 3 когда-то давно именно таким способом что-то делал и всё работало. На Чемаксе мои посты есть по этому поводу. И никаких хуков на ДайректИнпут я не ставил.
//bronis, по заданному вопросу отвечу позже
-
Может быть и нет разницы...
Какое у тебя сообщение вылазит из этих:
.rdata:1001C308 aUsingGameVer_0 db 'Using game version 1.0.1',0
.rdata:1001C308 ; DATA XREF: sub_100050D0:loc_10005176o
.rdata:1001C321 align 4
.rdata:1001C324 aInitialization db 'Initialization failed -- Unknown game version',0
.rdata:1001C324 ; DATA XREF: sub_100050D0+99o
.rdata:1001C352 align 4
.rdata:1001C354 ; char aFailedToDetect[]
.rdata:1001C354 aFailedToDetect db 'Failed to detect game version',0
.rdata:1001C354 ; DATA XREF: sub_100050D0:loc_10005152o
.rdata:1001C372 align 4
.rdata:1001C374 ; char aUsingGameVersi[]
.rdata:1001C374 aUsingGameVersi db 'Using game version 1.0.2',0
.rdata:1001C374 ; DATA XREF: sub_100050D0+5Bo
.rdata:1001C38D align 10h
.rdata:1001C390 ; char aAutoDetectingG[]
.rdata:1001C390 aAutoDetectingG db 'Auto detecting game version',0
.rdata:1001C390 ; DATA XREF: sub_100050D0+2Do
.rdata:1001C3AC ; char aProcessBaseAdd[]
.rdata:1001C3AC aProcessBaseAdd db 'Process base address: 0x%x',0Наверно, это "Failed to detect game version" ?
----------------
Меня что-то глюкнуло. Оказывается *.Lib файл это файл содержащий информацию экспорта и импорта относительно ScriptHook.dll описания. Файл нужен для компоновщика чтобы построить SampleCustom.dll корректно работающего с функциями ScriptHook.dll.
-
Сложно сказать в этом духе или в другом... Смотря как разработчики код игры написали. То что на видео, это сравнение данных структур. Можно не стесняться и брать мног структур. Своего героя, пару ботов из твоей команды и по паре ботов из двух других команд... Определяешь группы и ищешь чем они отличаются. Если найдёшь отличие, то сможешь сделать "фильтр" для совершения какого-то действия...
-
Приаттач твою SampleCustom.dll в архиве в посте. Что-то я свою SampleCustom.dll собрать не могу из-за ошибок в настройках проекта портированного на VS2010. Завтра я проверю её под отладкой.
---
Да и кстати в АА-скриптах CE есть команда "LOADLIBRARY(filename)". Попробуй её. Нужно заранее приаттачить процесс игры. В filename указать полный путь.
-
На видео вижу только адреса без указателей. Что конкретно не понятно?
-
По поводу указателей, которые ты привёл на картинке я знаю что они меняются с перезапуском игры. Я не акцентировал внимание на это. Это просто небольшая зацепка для дальнейших поисков статичных указателей и "постоянных фильтров". Но пока я не попробовал метод об определении кто свой, а кто чужой с помощью бряка на щелок мышки, лучше с фильтрами не возиться. Я попробую завтра.
Как ставить бряк на клик мышью?!
Тут полная статья о клике на кнопку, хотя не важно на что кликать... Но лучше чтобы я это сделал, потому что у меня опыта больше. Так что до завтра.
-
Пока ничем помочь не могу, может быть на недели попробую разобраться чтобы всё работало.
-
Если про GTAIV, то для компиляции своей dll-ки нужен файл "ScriptHook.lib", а ScriptHook.dll не требуется.
В примере проекта из SVN (на который я указывал ссылку) этот файл ScriptHook.libимеется.
Можно скомпилировать пример из SVN например SampleCustom, получится SampleCustom.dll. Её кладём в директории игры и используем асилоадер или просто загружаем эту SampleCustom.dll через Cheat Engine загрузчик без выполнения каких-либо определённых функций в ней. Активируем клавиши и играем со спавном. Разве не так должно быть? Просто я этого не делал, поэтому точно не знаю.
-
// Обработчик события клика мышки
void OnBtnClick(object sender, MouseArgs args)
{
GameObject gameObject = nil;
// Выбираем объект под курсором мышки
gameObject = GetObjectFromMouse(args.x, args.y, argz.z);
if (gameObject == nil) // если объекта нет, то проверить был ли выделен объект поьзователя
{
// Последний выделенныйобъект
gameObject = GetlastSelectGameObj();
// Если объект пользователя (!!! вот в этом месте определяется что групаа принадлежит пользователю)
if (IsUser(gameObject))
{
// то попытаться перенести объект, в данном случае "объект это отряд войска"
// в этой функции, где-то там будет проверка на оставшиеся ходы и вычет ходов из остальных отрядов
TryMove(gameObject,args.x, args.y, argz.z);
}
// Если объект не пользователя, то выход
return;
}
seelct(gameObject); // подсветка объекта
//...
}
void TryMove(gameObject,args.x, args.y, argz.z)
{
//...
group = gameObject as GroupClass;
//...
if (group.move(args.x, args.y, argz.z))
{
anyGroup = getGroups(group)
anyGroup.decreaseMove(group.lastMove)
}
// ...
}В отладчике надо найти то место, где я отметил восклицательными знаками. Там где выясняется может ли отряд ходить потому что принадлежит пользователю.
В OllyDbg надо поставить бряк на обработку щелчка мышки... один бряк поставить на запись очков передвижения... Сделать автоматический трейс по ретам до последнего бряка, и затем отпустить процесс чтобы узнать пересечение участков... и тогда должны выйти под call-ом. Посомтрим выше и должны увидеть код условия о передвижения отряда который принадлежит только нашему герою. написал в теории как смог... Я проверю эту теорию, когда выделю на это время...
-
Попробуй искать цепочку указателей свою и 2-х чужих машин, и затем сравнивать структуры указателей в Cheat Engine "dessect data" из меню дизассемблера. Как это делается есть в статье про Медал Тотал Вар на нашем сайте. Ещё поищи англоязычные статьи Geri по Cheat Engine. Вот одна. У него даже должно быть видео, вроде, по сравнениям структур.
-
О, неплохо ты в этом во всём шаришь...
Я установил эту игру, думал быстро разберусь, а не тут-то было (сейчас дел навалом, может быть на недели попробую копнуть).
Вот что я предполагаю:
Пользователь:
Группа1 юнитов на карте:
Unit_ID:
+ ..:
+44: одинаковый указатель для "Пользователя"
+6c: очки действия
// либо здесь конец структуры
_+B8: одинаковый указатель для "Пользователя"
// либо здесь конец структуры
Группа2 юнитов на карте:
Unit_ID:
+ ..:
+44: одинаковый указатель для "Пользователя"
+6c: очки действия
// либо здесь конец структуры
_+B8: одинаковый указатель для "Пользователя"
// либо здесь конец структуры
....
ГруппаN юнитов на карте:
Unit_ID:
+ ..:
+44: одинаковый указатель для "Пользователя"
+6c: очки действия
// либо здесь конец структуры
_+B8: одинаковый указатель для "Пользователя"
// либо здесь конец структуры
БотN:
Группа1 юнитов на карте:
Unit_ID:
+ ..:
+44: одинаковый указатель для БотN
+6c: очки действия
// либо здесь конец структуры
_+B8: одинаковый указатель для БотN
// либо здесь конец структуры
Группа2 юнитов на карте:
Unit_ID:
+ ..:
+44: одинаковый указатель для БотN
+6c: очки действия
// либо здесь конец структуры
_+B8: одинаковый указатель для БотN
// либо здесь конец структуры
....
ГруппаN юнитов на карте:
Unit_ID:
+ ..:
+44: одинаковый указатель для БотN
+6c: очки действия
// либо здесь конец структуры
_+B8: одинаковый указатель для БотN
// либо здесь конец структурыОдна инструкция
Shogun2.dll+68DEB2 - 89 50 6C - mov [eax+6C],edx
работает со всеми адресами ОД (очками действия). У меня много мыслей как поступить дальше, но пока я ничего писать не буду, т.к. могу запутать. Да, и предполагаю, что указатель в виде скобок написать не получиться, потому что его часть по идее может рассчитываться функцией с логическим условием. Например, перебирать такие-то элементы в пока не дойдём до конца массива и возвратить количество элементов в массиве.
Если одна группа сдвинулась на шаг, то очки хода у остальных отнимаются.
if (group.move)
{
anyGroup = getGroups(group)
anyGroup.decreaseMove(group.lastMove)
}Я уверен, что должен быть почти такой код, а это значит, что скорее всего надо больше внимания обращать на функции и её аргументы. Т.е. надо искать по всему стеку в моменты бряков такие функции , которые работают с группой после хода одной группы... Лучше не заморачиваться с указателямя, а заморачиваться с функциями в дереве вызовов...
-
-
local te_health = getTableEntry("health")
function CECheckbox1Change(sender)
if ( checkbox_getState(sender)== 1 ) then
memoryrecord_setValue(te_health, "100")
memoryrecord_freeze(te_health, 0)
else
memoryrecord_setValue(te_health, "99")
memoryrecord_unfreeze(te_health)
end
endПоглядывай сюда, тут могут быть подсказки о том какие функции тебе использовать. Тебе пригодиться. Когда я писал для тебя код я смотрел, только туда )
-
По поводу указателей на адреса патронов... Ты не читал мою статью, там даже скрипты есть.
Только сейчас увидел версии игр разные...
-
local te_health = getTableEntry("health")
function CECheckbox1Change(sender)
if ( checkbox_getState(sender) )
memoryrecord_freeze(te_health, 0) //0=freeze, 1=allow increase, 2=allow decrease
else
memoryrecord_unfreeze(te_health)
end
endВ этом примере предварительно нужно установить записываемое значение заморозки в главной таблице Cheat Engine. Будет ли этот код работать без ошибок не знаю, тебе надо проверить.
-
Чтобы побыстрее ответить я напишу кратко, а если будут вопросы, то задавай.
1. Сначала создаём форму в IDE Cheat Engine.
2. На неё бросаем чекБокс.
3. Заходим во вкладку Events и создаём событие напротив onchange двойным кликом по соседнему полю.
И ты увидишь:
function CECheckbox1Change(sender)
endЕсли задача записывать в адрес разные значения при активации и деактивации чексбокса, то написать надо следующее.
function CECheckbox1Change(sender)
if ( checkbox_getState(sender) )
// запись в адрес
else
// запись в адрес
end
endЗатем надо нажать Execute Script и закрыть IDE, закрыв панель инструментов. Так останется одна форма с чекбоксом. Ну а дальше проверяешь, работает или нет активируя чекбокс.
-
Ну, вот ещё информация. Поискал я ответы в Интернете и нашёл. Просто я знал, что моддинг к GTA очень развивается...
На странице SVN "проекта по созданию модов" есть функция создания машины.
Ссылка для скачивания для клиента SVN:
http://gta4modding.googlecode.com/svn/trunk/
static void CreateCar(u32 nameHash, f32 x, f32 y, f32 z, Vehicle *pVehicle, b8 unknownTrue) {
NativeInvoke::Invoke<scriptVoid>("CREATE_CAR", nameHash, x, y, z, pVehicle, unknownTrue);
}Эта функция как и другие, как очевидно, используются для модинга.
Ну и ещё есть одна:
static void GetCarModel(Vehicle vehicle, eModel *pValue) {
NativeInvoke::Invoke<NATIVE_GET_CAR_MODEL, ScriptVoid>(vehicle, pValue);
}Разберёмся, что требуется для создания машины и как работает GetCarModel. Т.е. мы разберём технологию спавна "на поверхности", но не так глубоко как хотелось бы. Пока мне не понятно как эта инфа была кем-то сотсавлена и изучена. Одно понятно, что этот человек действительно Гуру создания модов, а читов и подавно. Могу его только сильно уважать. Его никнейм Aru.
Все машины в первую очередь создаются по скриптам(на самом деле это что-то вроде своего языка программирования в опкодах), а затем уже машинным кодом.
Вот пример из GTAIV создания машины, скрипт декомпилирован из особых опкодов(составленных разработчиками игр) в текстовый формат:
.native HAS_MODEL_LOADED // in=1, out=1
.iftrue
PushD 8
Var
RefGet
PushD 9
Var
PushD 0
Add
RefGet
PushD 9
Var
PushD 4
Add
RefGet
PushD 9
Var
PushD 8
Add
RefGet
PushD 23
LocalVar
PushD 1
.native CREATE_CAR // in=6, out=0Вот более понятный вид,но уже из Санд-Андреас:
Загружаем модель машины, проверяем что она загрузилась, размещаем модель в игре:
:Createcar
wait 0
Model.Load(#SULTAN)
:Createcar_3
wait 100
if
Model.Available(#SULTAN).
jf @Createcar_3
$9 = Car.Create(#SULTAN, 2488.917, -1658.0735, 13.3549)
0229: set_car $9 color_to 31 0Функции ниже это обвертки C++ или Паскальные:
Разберём параметры функций (источник "Seemann")
static void GetCarModel(Vehicle vehicle, eModel *pValue) {
NativeInvoke::Invoke<NATIVE_GET_CAR_MODEL, ScriptVoid>(vehicle, pValue);
}
//Vehicle vehicle : хендл машины
//eModel *pValue : переменная-приемник, куда будет записано ID модели.значения параметров косвенно можно определить по названию функции. Если функция называется GetCarModel (в переводе получить модель машины), значит должно быть как минимум 2 параметра:
1. хендл машины и
2. переменная-приемник, куда будет записано ID модели.
Хендл машины - это переменная с ее "именем", позволяющим отличить от другой машины. Хендл получается как раз из следующей функции:
CreateCar. Её параметры можно понять по названию:
static void CreateCar(u32 nameHash, f32 x, f32 y, f32 z, Vehicle *pVehicle, b8 unknownTrue) {
NativeInvoke::Invoke<scriptVoid>("CREATE_CAR", nameHash, x, y, z, pVehicle, unknownTrue);
}
//u32 nameHash : хэш имени модели (http://www.gtamodding.com/index.php?title=List_of_models_hashes), например Например, для
//AMBULANCE хэш равен 1171614426 или 0x45D56ADA
//f32 x, f32 y, f32 z : это координаты места, где будет создана машина. Например, 100.10 -986.12 55.0
//Vehicle *pVehicle : Переменная с типом Vehicle, в которую будет записан хендл созданной машины (см. выше)
//b8 unknownTrue : Неизвестный параметр. В оригинальных скриптах всегда равен 1 или True.Пример вызова функций на Паскале:
var
_mycar:Vehicle;
_mymodel: u32;
CreateCar(1171614426, 100.10, -986.12, 55.0, _mycar, true);Можно догадаться чему будет равен результат теперь:
GetCarModel(_mycar; _mymodel);
Более подробно как я уже писал смотрим:
GTAModding.ru Wiki - ссылка
обсуждение вопроса создания машины (там в основном Паскаль): ссылка
хеши (или уникальные ID) моделей: здесь
------------
Вопрос о том можно ли подобное создать на Cheat Engine. Ответ да, можно... Есть сложные пути, а есть и простые. О сложных путях было написано уже до этого поста. А простой путь это найти необходииые Lua- модули с описанием CreateCar. Вызывать эту функцию из LUA-Engine...
-------------
А вот пример, от самого Aru (там есть и спавн машины и другие читы
#include "Scripting.h"
#include "../ScriptHook/Log.h"
#include <windows.h>
// Pull in all our scripting functions/types
using namespace Scripting;
CustomFiberThread::CustomFiberThread()
{
// Give your own name here!
SetName("CustomFiberThread");
}
// Some helper functions
Player CustomFiberThread::GetPlayer()
{
Player playerIndex = ConvertIntToPlayerIndex(GetPlayerId());
return playerIndex;
}
Scripting::Ped CustomFiberThread::GetPlayerPed()
{
Ped ped;
GetPlayerChar(GetPlayer(), &ped);
return ped;
}
void CustomFiberThread::SpawnCar(eModel model)
{
RequestModel(model);
while(!HasModelLoaded(model))
{
Wait(0);
}
LogInfo("Car model available... spawning it!");
Ped ped = GetPlayerPed();
Vehicle vehicle;
f32 x,y,z;
GetCharCoordinates(ped, &x, &y, &z);
CreateCar(model, x, y, z, &vehicle, true);
MarkModelAsNoLongerNeeded(model);
}
void CustomFiberThread::ChangePlayerSkin(eModel model)
{
RequestModel(model);
while(!HasModelLoaded(model))
{
Wait(0);
}
LogInfo("Skin model available... spawning it!");
eInteriorRoomKey roomKey;
GetKeyForCharInRoom(GetPlayerPed(), &roomKey);
ChangePlayerModel(GetPlayer(), model);
SetRoomForCharByKey(GetPlayerPed(), roomKey);
MarkModelAsNoLongerNeeded(model);
}
void CustomFiberThread::TeleportToWaypoint(Scripting::Ped &ped)
{
Blip b = GetFirstBlipInfoId(BLIP_WAYPOINT);
if(b.IsValid())
{
Vector3 v;
GetBlipCoords(b, &v);
LogInfo("Teleporting to %f, %f", v.X, v.Y);
// Thanks to Prince-Link for this magical Z coord detection code...
SetCharCoordinates(ped, v.X, v.Y, v.Z);
while(v.Z == 0.0f) // The chance that ground Z is 0.0 _exactly_ is really small
{
GetGroundZFor3DCoord(v.X, v.Y, 1000, &v.Z);
Wait(0);
}
SetCharCoordinates(ped, v.X, v.Y, v.Z);
}
else
{
LogError("No way point found to teleport to.");
}
}
// The real script
void CustomFiberThread::RunScript()
{
// This is a fiber thread, so we use an loop to run the contents of this script.
// The thread will terminate when we return from this function.
while(IsThreadAlive())
{
if ((GetAsyncKeyState(VK_F4) & 1) != 0)
{
LogInfo("Teleporting player to way point");
TeleportToWaypoint( GetPlayerPed() );
}
else if ((GetAsyncKeyState(VK_F5) & 1) != 0)
{
LogInfo("Spawning a random car");
Vehicle vehicle;
u32 modelHash;
ScriptAny unknown;
f32 x,y,z;
GetCharCoordinates(GetPlayerPed(), &x, &y, &z);
GetRandomCarModelInMemory(1, &modelHash, &unknown);
CreateCar(modelHash, x, y, z, &vehicle, true);
}
else if ((GetAsyncKeyState(VK_F6) & 1) != 0)
{
LogInfo("Granting player $1000");
AddScore(GetPlayer(), 1000);
}
else if ((GetAsyncKeyState(VK_F7) & 1) != 0)
{
LogInfo("Requested a MODEL_BANSHEE spawn");
SpawnCar(MODEL_BANSHEE);
}
else if ((GetAsyncKeyState(VK_F8) & 1) != 0)
{
LogInfo("Changing the player skin");
ChangePlayerSkin(MODEL_IG_JOHNNYBIKER);
}
else if ((GetAsyncKeyState(VK_F9) & 1) != 0)
{
LogInfo("Changing the player skin back to Niko's");
ChangePlayerSkin(MODEL_PLAYER);
}
// Call Wait() so we can process other scripts/game code
// You must call Wait(...) in your loop code for a fiber thread!
Wait(100);
}
}#include "CustomFiberThread.h"
Данный код компилируется в модуль dll. При аттаче этого модуля к процессу игры (можно сделать и с помощью Cheat Engine), можно активировать hot-keys и тем самым включать читы. Для спавна машины надо нажать F7. Скрипты Aru можно найти в Интернете.
{
RequestModel(model); // создать модель машины, укажите model - машины, например MODEL_BANSHEE, другие модели ищите в исходниках Aru
while(!HasModelLoaded(model)) // дождаться когда модель инициализируется
{
Wait(0);
}
LogInfo("Car model available... spawning it!"); // лог
Ped ped = GetPlayerPed(); // получить описатель главного героя
Vehicle vehicle; // создать какой-то описатель
f32 x,y,z; // координаты
GetCharCoordinates(ped, &x, &y, &z); // получить координаты героя
CreateCar(model, x, y, z, &vehicle, true); // создать машину и возвратить vehicle, если он пригодиться позже
MarkModelAsNoLongerNeeded(model); // с моделью машины уже отработали, надо её отметить как ненужную
}void CustomFiberThread::SpawnCar(eModel model)
-
А чем Вас видео не устроило : "Взлом денег Mafia 2 Обман денег и создание скрипта", а также "Devil May Cry 4 Бесконечное здоровье и убийство с одного удара." Может быть что-то не понятно или Вы просто не посмотрели? Все видео находится в соответствующем разделе форума. ZOCKIR-у, если увидит это сообщение за видео ещё раз спасибо лично от меня.
Как СЕ генерирует трейнеры
in Создание трейнеров в специальных студиях
Опубликовано
Akama, не уже ли ты не сможешь разобраться "методом тыка" как генерировать трейнер в CE 6.1, если уже есть таблица? Лучше задавай конкретные вопросы...
У тебя, наверно, есть один большой скрипт и несколько адресов активации. Ну в генерируемом трейнере укажи хот-кеи на большой скрипт - "клавиша Inc", на остальные - другие клавиши. И ничего сложного...