|
 |
|
|
|
|
|
GTA Modification Forums
[C++|ASM] Alter damage received
 |
|
 |
| |
FaTony  |
|
C++ guy

Group: Members
Joined: Aug 12, 2011

|
Oh man, I can't describe how I'm thankful to you. I just did | CODE | void OnPedDamage(void* unknown, void* target) { float damage = ReadDamage(); damage *= 0.3f; SetDamage(damage); } |
and had a best GTA4 cop shootout in my life! That protection disabler actually works in the end. Ok, now it's time for some improvements. For example I don't like that that OnPedDamage heavily relies on contents of registers. xmm0 at least. What if I call a function inside OnPedDamage that modifies xmm0 during it's internal workings? My proposition is to modify Hooked_damagePed as follows: - Save all valuable registers into a safe place (stack?).
- Do a clean call of C++ function. (All relevant pushing and register values).
- Restore all valuable registers from the safe place and modify xmm0 to the value from C++ function.
I see you already doing this with ecx (does this mean we are hooking __thiscall?). To help you out with assembly, I've written this small program: | CODE | void OnPedDamage(const void *victim, const void *attacker, float &damage) { damage *= 2.0f; }
int main() { void *ptr1 = (void *)1; void *ptr2 = (void *)2; float fl3 = 1.0f; OnPedDamage(ptr1, ptr2, fl3); fl3 += 42.0f; return 0; } |
When compiled and disassembled, it gives following code: | CODE | .text:004113C0; int __cdecl main() .text:004113C0 _main proc near ; CODE XREF: j__mainj .text:004113C0 .text:004113C0 var_E4 = byte ptr -0E4h .text:004113C0 fl3 = dword ptr -20h .text:004113C0 ptr2 = dword ptr -14h .text:004113C0 ptr1 = dword ptr -8 .text:004113C0 .text:004113C0 push ebp .text:004113C1 mov ebp, esp .text:004113C3 sub esp, 0E4h .text:004113C9 push ebx .text:004113CA push esi .text:004113CB push edi .text:004113CC lea edi, [ebp+var_E4] .text:004113D2 mov ecx, 39h .text:004113D7 mov eax, 0CCCCCCCCh .text:004113DC rep stosd .text:004113DE mov [ebp+ptr1], 1 .text:004113E5 mov [ebp+ptr2], 2 .text:004113EC fld1 .text:004113EE fstp [ebp+fl3] .text:004113F1 lea eax, [ebp+fl3] .text:004113F4 push eax ; damage .text:004113F5 mov ecx, [ebp+ptr2] .text:004113F8 push ecx ; attacker .text:004113F9 mov edx, [ebp+ptr1] .text:004113FC push edx ; victim .text:004113FD call j_?OnPedDamage@@YAXPBX0AAM@Z; OnPedDamage(void const *,void const *,float &) .text:00411402 add esp, 0Ch .text:00411405 fld [ebp+fl3] .text:00411408 fadd ds:__real@4045000000000000 .text:0041140E fstp [ebp+fl3] .text:00411411 xor eax, eax .text:00411413 push edx .text:00411414 mov ecx, ebp ; frame .text:00411416 push eax .text:00411417 lea edx, v ; v .text:0041141D call j_@_RTC_CheckStackVars@8; _RTC_CheckStackVars(x,x) .text:00411422 pop eax .text:00411423 pop edx .text:00411424 pop edi .text:00411425 pop esi .text:00411426 pop ebx .text:00411427 add esp, 0E4h .text:0041142D cmp ebp, esp .text:0041142F call j___RTC_CheckEsp .text:00411434 mov esp, ebp .text:00411436 pop ebp .text:00411437 retn ------------------------------------------------------------------------------------------------------ .text:00411380; void __cdecl OnPedDamage(const void *victim, const void *attacker, float *damage) .text:00411380 ?OnPedDamage@@YAXPBX0AAM@Z proc near ; CODE XREF: .text:00411082j .text:00411380 ; .text:004111C2j ... .text:00411380 .text:00411380 var_C0 = byte ptr -0C0h .text:00411380 victim = dword ptr 8 .text:00411380 attacker = dword ptr 0Ch .text:00411380 damage = dword ptr 10h .text:00411380 .text:00411380 push ebp .text:00411381 mov ebp, esp .text:00411383 sub esp, 0C0h .text:00411389 push ebx .text:0041138A push esi .text:0041138B push edi .text:0041138C lea edi, [ebp+var_C0] .text:00411392 mov ecx, 30h .text:00411397 mov eax, 0CCCCCCCCh .text:0041139C rep stosd .text:0041139E mov eax, [ebp+damage] .text:004113A1 fld dword ptr [eax] .text:004113A3 fadd st, st .text:004113A5 mov ecx, [ebp+damage] .text:004113A8 fstp dword ptr [ecx] .text:004113AA pop edi .text:004113AB pop esi .text:004113AC pop ebx .text:004113AD mov esp, ebp .text:004113AF pop ebp .text:004113B0 retn .text:004113B0 ?OnPedDamage@@YAXPBX0AAM@Z endp
|
|
|
|
|
|
 |
|
 |
 |
|
 |
| |
FaTony  |
|
C++ guy

Group: Members
Joined: Aug 12, 2011

|
I want to change prototype of C++ function from void func(void*, void*) where 1st argument is useless and there needs to be 2 function calls to alter the damage and inline assembly to get the attacker to void func(const void*, const void*, float&) which is const-correct, have 3 valuable arguments and doesn't need any function calls to alter the damage. EDIT: If we wrap your functions: | CODE | void OnPedDamage(void *unknown, void *victim) { float damage = ReadDamage(); void* attacker = 0; _asm { push eax mov eax, [ebp+14h] mov attacker, eax pop eax } Wrapper2(victim, attacker, damage); SetDamage(damage); } |
But it's it a bit ugly? This post has been edited by FaTony on Sunday, Apr 1 2012, 23:46
|
|
|
|
|
 |
|
 |
 |
|
 |
| |
LMS  |
|
Punk-ass Bitch

Group: Members
Joined: Jun 30, 2005


|
Ok I see, but still there no need for you to touch the asm code since you have a C++ function where you don't have to mess around with registers and such. Like: | CODE | void PedDamageHook::OnPedDamage(void* unknown, void* target) { // Read damage value float damage = PedDamageHook::ReadDamage(); // Get damage source void* source = 0; _asm { push eax mov eax, [ebp+14h] mov source, eax pop eax } PedDamageHook::SetDamage(PedDamageHook::AdjustDamage(target, source, damage)); }
float PedDamageHook::AdjustDamage(void* target, void* source, float damage) { void* playerPed = PedDamageHook::GetPlayerPed(0);
if (playerPed == target) { return 1; }
// If damage is dealt by player, multiply by 10 if (source == playerPed) { return damage * 20; } } |
Edit: Yeah, just like your wrapper.
|
|
|
|
|
 |
|
 |
 |
|
 |
| |
FaTony  |
|
C++ guy

Group: Members
Joined: Aug 12, 2011

|
EDIT: Ok. After quite a few assembly related articles I managed to do this: | CODE | const DWORD GetPlayerPedFuncAddress = 0x008788D0;
typedef void *(__cdecl *GetPlayerPedFunc)(int);
GetPlayerPedFunc GetPlayerPed;
void InstallHooks(void) { GetPlayerPed = (GetPlayerPedFunc)(GetPlayerPedFuncAddress + dwLoadOffset); //Other code }
__declspec(naked) int __stdcall PedDamageHook(void *attacker, void *victim) { _asm { // Function prolog // Create new stack frame push ebp mov ebp, esp
// Save relevant registers // Save ecx push ecx
// Call C++ function // Push damage lea eax, [ecx + 4h] push eax // Push attacker push [ebp + 10h] // Push victim push [ebp + 14h] // Call function call OnPedDamage // Clean stack add esp, 12
// Restore relevant registers // Restore ecx pop ecx
// Function epilog // Restore previous stack frame mov esp, ebp pop ebp
// Code from '0x00ABB170', 8 ovewritten bytes sub esp, 10h push ebp mov ebp, [esp+1Ch] jmp jmpaddress } }
void OnPedDamage(const void *victim, const void *attacker, float &damage) { void *player = GetPlayerPed(0); if (victim == player) { damage *= 0.1f; } else if (attacker == player) { damage *= 10.0f; } } |
The problem is, it looks like all peds have 2 ped classes associated with them. One is the "old school ped" that is used during gun fights and another is "Euphoria ped" with is used with physics and ragdolls. Old school peds have addresses in the range of 5xxxxxx. Euphoria peds have addresses in the range of 6xxxxxx. GetPlayerPed returns old school ped. So, for example, when I throw a molotov and get caught by it's fire, attacker will be my old school ped and victim will be my Euphoria ped. As a result, I will get 10x damage. That's no good. Can you help me find a function that returns Euphoria peds? This post has been edited by FaTony on Tuesday, Apr 3 2012, 01:57
|
|
|
|
|
 |
|
 |
 |
|
 |
| |
0 User(s) are reading this topic (0 Guests and 0 Anonymous Users)
0 Members:
Pages:
(2) 1 [2]
Track this topic
Receive email notification when a reply has been made to this topic and you are not active on the board.
Subscribe to this forum
Receive email notification when a new topic is posted in this forum and you are not active on the board.
Download / Print this Topic
Download this topic in different formats or view a printer friendly version.
| |
 |
|
 |
|
|
|
|