Quantcast
Jump to content
Search In
  • More options...
Find results that contain...
Find results in...
    1. Welcome to GTAForums!

    1. Red Dead Redemption 2

      1. PC
      2. Gameplay
      3. Missions
      4. Help & Support
    2. Red Dead Online

      1. Gameplay
      2. Find Lobbies & Outlaws
      3. Help & Support
      4. Frontier Pursuits
    1. Crews & Posses

      1. Recruitment
    2. Events

    1. GTA Online

      1. Diamond Casino & Resort
      2. DLC
      3. Find Lobbies & Players
      4. Guides & Strategies
      5. Vehicles
      6. Content Creator
      7. Help & Support
    2. Grand Theft Auto Series

    3. GTA 6

    4. GTA V

      1. PC
      2. Guides & Strategies
      3. Help & Support
    5. GTA IV

      1. Episodes from Liberty City
      2. Multiplayer
      3. Guides & Strategies
      4. Help & Support
      5. GTA IV Mods
    6. GTA Chinatown Wars

    7. GTA Vice City Stories

    8. GTA Liberty City Stories

    9. GTA San Andreas

      1. Guides & Strategies
      2. Help & Support
      3. GTA SA Mods
    10. GTA Vice City

      1. Guides & Strategies
      2. Help & Support
      3. GTA VC Mods
    11. GTA III

      1. Guides & Strategies
      2. Help & Support
      3. GTA III Mods
    12. Top Down Games

      1. GTA Advance
      2. GTA 2
      3. GTA
    13. Wiki

      1. Merchandising
    1. GTA Modding

      1. GTA V
      2. GTA IV
      3. GTA III, VC & SA
      4. Tutorials
    2. Mod Showroom

      1. Scripts & Plugins
      2. Maps
      3. Total Conversions
      4. Vehicles
      5. Textures
      6. Characters
      7. Tools
      8. Other
      9. Workshop
    3. Featured Mods

      1. DYOM
      2. OpenIV
      3. GTA: Underground
      4. GTA: Liberty City
      5. GTA: State of Liberty
    1. Red Dead Redemption

    2. Rockstar Games

    1. Off-Topic

      1. General Chat
      2. Gaming
      3. Technology
      4. Programming
      5. Movies & TV
      6. Music
      7. Sports
      8. Vehicles
    2. Expression

      1. Graphics / Visual Arts
      2. GFX Requests & Tutorials
      3. Writers' Discussion
      4. Debates & Discussion
    1. News

    2. Forum Support

    3. Site Suggestions

Sign in to follow this  
FaTony

[C++|ASM] Alter damage received

Recommended Posts

FaTony

Hello there.

 

I would like to be able to alter damage received by Niko. For example, to be able to survive explosion or high fall but still take some damage.

 

Obviously, I can monitor player health very frequently, but this won't block 1-hit kills as player will already be dead when I would check him.

 

I'm good at C++ but bad at reverse engineering, so if anyone would kindly provide C prototype and address to patch or at least some clues of where to look, it would be greatly appreciated.

Share this post


Link to post
Share on other sites
LMS

Since you are talking about Niko, I assume you are using GTA IV and Patch #7.

 

Have a look at sub_0ABB170, it handles damaging peds. When immediately returning all peds are invincible. The first param is the ped, so you could check if ped is player and then alter the damage value.

Share this post


Link to post
Share on other sites
FaTony

Ok, how exactly do I do this? I'm familiar with jump hooking but that completely overrides function, but I only need to change the value of argument. It looks like there are 23 calls to that function, should I patch those to use the address of my function and then call original function in the body of mine?

 

Some code would be appreciated.

 

And just to be sure that I've found the correct function, here's the prototype IDA gives me:

 

int __stdcall sub_ABB170(int, float);

 

Share this post


Link to post
Share on other sites
Fantaseb

 

Ok, how exactly do I do this? I'm familiar with jump hooking but that completely overrides function, but I only need to change the value of argument. It looks like there are 23 calls to that function, should I patch those to use the address of my function and then call original function in the body of mine?

 

Some code would be appreciated.

 

And just to be sure that I've found the correct function, here's the prototype IDA gives me:

 

int __stdcall sub_ABB170(int, float);

 

ASM is ScoToolBox right? Why not just a a key board button, which would be like

 

:Label6791PushD 41 //Look whatever key you wantCall Native SET_PLAYER_INIVINCIBLE 2 0Var3PushD 41

 

 

Something like that cant remember that much or just in c++ the same native but it would be like this if using scocl:

 

 

SET_PLAYER_INIVINCIBLE (pid, TRUE);

 

 

Is this what you mean, that would make the player not take any damage, or just go into the Weaponfile.xml and change the pedplayer (Or whatever it is called) to 0 and same for networkpedplayer, and add in fall etc and just everything from UZI_DRIVEBY etc. I dont know much about the c++ aru thing, i only know about Scocl (high level compiler) or the scotoolbox, hope this helped smile.gif

Edited by Fantaseb

Share this post


Link to post
Share on other sites
FaTony

 

ASM is ScoToolBox right?

 

No, I mean x86 assembly language.

 

Anyway, I was googling on hooking and made up some code:

 

DWORD dwLoadOffset = ((DWORD)GetModuleHandle(NULL) - 0x400000);DWORD address = 0;BYTE originalcode[6];BYTE patchedcode[6] = { 0xE9, 0x90, 0x90, 0x90, 0x90, 0xC3 };typedef int (__stdcall *ABB170)(int, float);ABB170 func;void InstallHooks(void){address = 0xABB170 + dwLoadOffset;func = (ABB170)address;DWORD addressdiff = ((DWORD)&my_ABB170 - (address + 5));memcpy(patchedcode + 1, &addressdiff, sizeof(DWORD));DWORD oldp;   VirtualProtect((LPVOID)address, 6, PAGE_EXECUTE_READWRITE, &oldp);memcpy(originalcode, (void *)address, 6);memcpy((void *)address, patchedcode, 6);}int __stdcall my_ABB170(int ped, float damage){memcpy((void *)address, originalcode, 6);int ret = func(ped, damage);memcpy((void *)address, patchedcode, 6);return ret;}

 

 

It crashes at

int ret = func(ped, damage);

 

 

Looking through a debugger, damage has an insane value. Wrong prototype?

 

Hex-Rays decompiler gives me this:

 

void __userpurge sub_ABB170(int a1<ecx>, double a2<st0>, __m128i a3<xmm2>, __m128d a4<xmm3>, __int128 a5<xmm4>, __m128i a6<xmm7>, int a7, int a8);

 

Edited by FaTony

Share this post


Link to post
Share on other sites
LMS

This should work (untested though):

 

 

#include "PedDamageHook.h"#include "Helper.h"#include "Detour.h"static DWORD dwRealFunction;// Max damage player can takestatic float fMaxValue = 2;void PedDamageHook::HookPedDamage(){// Calculate function addressDWORD dwFunc = Helper::GetGameBase() + 0xABB170;// Place jmp instruction and overwrite first 8 bytes (so we destroy no opcodes).// Note: To simplify matters I'll put the first 8 bytes at the end of the codecave, so you can better follow my code// Note2: This function returns the first parameter (so dwFunc) + the bytes to overwrite (so 8), so we can jump back right after our hookdwRealFunction = (DWORD)DetourFunction((PBYTE)dwFunc, (PBYTE)PedDamageHook::Hooked_damagePed, 8);}// Naked so we have no prolog/epilog code__declspec( naked ) int __stdcall PedDamageHook::Hooked_damagePed(void* ped, float damage){// Simple asm code, which checks if the ped is the local player ped and if so ensures that damage isn't greater than 2_asm{ push  eax push  ecx push  esi // 08788D0 is the function that returns the ped associated to the player call  Helper::GetGameBase add  	eax, 08788D0h push  0 // player index call  eax add  	esp, 04 mov  	esi, ped cmp  	esi, eax jnz  	NotLocalPlayer // Read and compare damage value movss  xmm0, [ecx+4h] comiss  	xmm0, fMaxValue jbe  	ValueOk // Adjust damage value movss  xmm0, fMaxValue movss  [ecx+4h], xmm0ValueOk:NotLocalPlayer: pop  	esi pop  	ecx pop  	eax// Code from '0ABB170', 8 ovewritten bytes sub  esp, 10h push	ebp mov  ebp, [esp+1Ch] jmp  	dwRealFunction}}

 

 

 

DWORD Helper::GetGameBase(){if(m_dwGameBase == NULL){ m_dwGameBase = ((DWORD)GetModuleHandle(NULL) - 0x400000);}return m_dwGameBase;}

 

 

Edit: Works fine on EFLC 1.1.2.0 (changed offsets of course)

Edited by LMS

Share this post


Link to post
Share on other sites
FaTony

Nice one! Except I'm really bad at assembly. By writing the whole function in assembly you're able to preserve the stack, which was not in my case.

 

So, if I'm using C++ ScriptHook, can I compare that void * to Scripting::Ped that ScriptHook returns? What about the stack, can this inline assembly be redone into C++ code? And, of course, what's the offset for EFLC?

Share this post


Link to post
Share on other sites
LMS

I prefer assembly for simple functions like this, especially when hooking so I know what's going on there and don't have C++ possibly crash my code because of prolog or epilog code fails.

void* ped is a pointer to the actual ped class iv uses internally while Scripting::Ped is only a wrapper around a handle, so no you can't compare them. But when you look at my asm code I simply called an internal function that returns the player ped associated to the player index to check if it's the local player we are handling. It can be redone in C++ of course, I'd suggest you to use a library like MS Detours then, which also saves the bytes the hook overwrites so you don't have to place them at the end of your function like I did. EFLC offset is: sub_0AE2B30 and sub_0846EA0 to get the local player ped.

 

BTW: The code was just a quick mockup I wrote and will limit all damage. Since you are looking for falling damage, you should set a bp on the first instruction in the function, fall down somewhere and then trace back the call. You could then do something like, before the fall code calls the damage code, set a static var like "damageType = FallingDamage" and then in your damage code hook you can check for the damage source. Just an idea though.

Share this post


Link to post
Share on other sites
FaTony

Ok, I'm trying to use MS detours:

 

#include <windows.h>#include <detours.h>DWORD dwLoadOffset = ((DWORD)GetModuleHandle(NULL) - 0x400000);DWORD realaddress = 0;typedef int (__stdcall *ABB170)(void *, float);ABB170 realfunc;void InstallHooks(void){realaddress = 0xABB170 + dwLoadOffset;realfunc = (ABB170)realaddress;DetourTransactionBegin();DetourUpdateThread(GetCurrentThread());DetourAttach(&(PVOID&)realfunc, &my_ABB170);DetourTransactionCommit();}int __stdcall my_ABB170(void *ped, float damage){return realfunc(ped, damage);}

 

 

Damage value is still strange in the debugger. I tried to follow the code into disassembly and it looks like MS detours correctly patch memory so the flow goes just right after the jmp to ABB178, then it jumps into sub_AB94C0 and in it goes to

00AB94C8  mov         eax,dword ptr [edi+0Ch]

 

and then crashes with: Unhandled exception at 0x00ab94c8 in GTAIV.exe: 0xC0000005: Access violation reading location 0x0000000c.

 

I guess I messed up the value of edi. It's 0 in my case but should contain a pointer to some valid memory, right?

 

Any help?

Edited by FaTony

Share this post


Link to post
Share on other sites
LMS

Please post the assembly code of ABB170 (like the first 20bytes), your detour and where your detour jumps to (where the overwritten bytes are saved).

Share this post


Link to post
Share on other sites
FaTony

Here's patched code:

 

00ABB16C  int         3  00ABB170  jmp         my_ABB170 (24E1636h)  00ABB175  int         3  00ABB176  int         3  00ABB177  int         3  00ABB178  mov         al,byte ptr [ebp+4]  00ABB17B  test        al,1  00ABB17D  push        edi  00ABB17E  mov         edi,ecx  00ABB180  jne         00ABB692  00ABB186  xorps       xmm0,xmm0  00ABB189  and         al,0C1h  00ABB18B  or          al,1  00ABB18D  push        esi  00ABB18E  mov         esi,dword ptr [esp+20h]etc. 

 

 

Here's my function:

 

int __stdcall my_ABB170(void *ped, float damage){024E5900  push        ebp  024E5901  mov         ebp,esp  024E5903  sub         esp,0C0h  024E5909  push        ebx  024E590A  push        esi  024E590B  push        edi  024E590C  lea         edi,[ebp-0C0h]  024E5912  mov         ecx,30h  024E5917  mov         eax,0CCCCCCCCh  024E591C  rep stos    dword ptr es:[edi]  return realfunc(ped, damage);024E591E  mov         esi,esp  024E5920  push        ecx  024E5921  fld         dword ptr [damage]  024E5924  fstp        dword ptr [esp]  024E5927  mov         eax,dword ptr [ped]  024E592A  push        eax  024E592B  call        dword ptr [func (24F5290h)]  024E5931  cmp         esi,esp  024E5933  call        @ILT+1125(__RTC_CheckEsp) (24E146Ah)  }024E5938  pop         edi  024E5939  pop         esi  024E593A  pop         ebx  024E593B  add         esp,0C0h  024E5941  cmp         ebp,esp  024E5943  call        @ILT+1125(__RTC_CheckEsp) (24E146Ah)  024E5948  mov         esp,ebp  024E594A  pop         ebp  024E594B  ret         8  

 

 

And here's trampoline that patched realfunc points to:

 

 

40AA00D8  sub         esp,10h  40AA00DB  push        ebp  40AA00DC  mov         ebp,dword ptr [esp+1Ch]  40AA00E0  jmp         00ABB178  

 

 

 

Share this post


Link to post
Share on other sites
LMS

I suspect the prototype is just wrong/incomplete, but I'm not sure how the real prototype looks like. Any chance you can use a little inline assembler to read/write the value?

 

int __stdcall my_ABB170(void *ped, float damage){float dmg;_asm{ // Read value into dmg movss	xmm0, [ecx+4h] movss	dmg, xmm0 // Write changed value back movss	xmm0, dmg movss	[ecx+4h], xmm0}}

 

Share this post


Link to post
Share on other sites
FaTony

Maybe you can just modify the asm code you wrote a few posts back to call my function?

 

So my_ABB170 will be naked in asm and it will call another function such as void OnDamage(void *ped, float &damage) that will be written in C++.

 

I don't know how to call C functions from asm (all those calling conventions and stack, ugh), so I'll need your help. Also, what's the prototype of function to get player ped, void *func(void)?

 

Thanks for your help so far.

Share this post


Link to post
Share on other sites
LMS

I did some more work on this and wrapped all asm calls in C++ functions. This should work fine on IV 1.0.7.0. Simply place your C++ code in "OnPedDamage".

 

 

#include "PedDamageHook.h"#include "Helper.h"#include "Detour.h"static DWORD dwRealFunction;// Max damage player can takestatic float fMaxValue = 2;void PedDamageHook::HookPedDamage(){// Calculate function addressDWORD dwFunc = Helper::GetGameBase() + 0xABB170;// Place jmp instruction and overwrite first 8 bytes (so we destroy no opcodes).// Note: To simplify matters I'll put the first 8 bytes at the end of the codecave, so you can better follow my code// Note2: This function returns the first parameter (so dwFunc) + the bytes to overwrite (so 8), so we can jump back right after our hookdwRealFunction = (DWORD)DetourFunction((PBYTE)dwFunc, (PBYTE)PedDamageHook::Hooked_damagePed, 8);}DWORD dwECX;void* PedDamageHook::GetPlayerPed(int index){void* ped;_asm{ // 08788D0 is the function that returns the ped associated to the player call  Helper::GetGameBase add  	eax, 08788D0h push  index // player index call  eax add  	esp, 04 mov  	ped, eax}return ped;}float PedDamageHook::ReadDamage(){float value = 0.0f;_asm{ push  ecx mov  	ecx, dwECX movss  xmm0, [ecx+4h] movss  value, xmm0 pop  	ecx}return value;}void PedDamageHook::SetDamage(float damage){_asm{ push	ecx mov  ecx, dwECX movss	xmm0, damage movss	[ecx+4h], xmm0 pop  ecx}}__declspec( naked ) int __stdcall PedDamageHook::Hooked_damagePed(void* unknown, void* target){_asm { // Save ecx mov  dwECX, ecx	 // Call function call	OnPedDamage // Restore ecx mov  ecx, dwECX jmp  dwRealFunction}}void PedDamageHook::OnPedDamage(void* unknown, void* target){// Read damage valuefloat damage = PedDamageHook::ReadDamage();// Modify if neededif (damage > 10){ void* playerPed = PedDamageHook::GetPlayerPed(0); if (playerPed == target) { 	PedDamageHook::SetDamage(1.0f); }}}

 

 

I hope this helps you a little.

 

Edit: Works fine on EFLC.

 

Edit2: Found a way to get the ped that is dealing the damage, check this out:

 

 

void* source = 0;_asm{ push	eax mov  eax, [ebp+14h] mov  source, eax pop  eax}// If damage is dealt by player, multiply by 20if (source == playerPed){ PedDamageHook::SetDamage(damage * 20);}

 

Edited by LMS

Share this post


Link to post
Share on other sites
FaTony

I'm currently copying your code, but I wonder where did you put the first 8 bytes of original function?

Share this post


Link to post
Share on other sites
LMS
I'm currently copying your code, but I wonder where did you put the first 8 bytes of original function?

My own hook functions saves the bytes and will execute them before returning to the real function (just like MS detours does).

Share this post


Link to post
Share on other sites
FaTony

Do you use Xliveless?

 

I'm halfway through copying and it doesn't crash when peds get damaged, but it randomly crashes after few minutes in the game.

 

EDIT: Ok, it looks like I've triggered GFWL protection. It doesn't load now.

Edited by FaTony

Share this post


Link to post
Share on other sites
LMS

Yeah, you should switch to xliveless for memory patching.

Share this post


Link to post
Share on other sites
FaTony

Oh well, thanks a lot for your help. I'm not ready to switch to Xliveless yet.

 

I'm going to stop here now and hope someone will make this thread into nice Xliveless-compatible trainer.

 

Thanks again.

Share this post


Link to post
Share on other sites
LMS

Check this out: http://www.gtaforums.com/index.php?showtopic=419908 - This will disable the xlive code that is checking your memory for changes.

No problem, after all these "omg how to use scripthook!!111 help!11" topics here, it was a real pleasure to actually help someone coding something that does not consist of two .NET calls. Good luck with your project and I'd recommend you to give assembly a shot, it's worth it when it comes down to reversing.

Share this post


Link to post
Share on other sites
FaTony

Looks outdated. I've attached debugger to GTAIV.exe and it crashed after a few seconds with callstack inside xlive.dll. I think I'll have dig into the source code of Xliveless...

Share this post


Link to post
Share on other sites
LMS

I didn't say it allows you to attach a debugger smile.gif You are able to alter the game memory without crashes, but attaching a debugger still requires xliveless.

Share this post


Link to post
Share on other sites
FaTony

Oh man, I can't describe how I'm thankful to you. I just did

 

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:

 

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:

 

.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    [email protected]@[email protected]; OnPedDamage(void const *,void const *,float &).text:00411402                 add     esp, 0Ch.text:00411405                 fld     [ebp+fl3].text:00411408                 fadd    ds:[email protected]: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    [email protected][email protected]; _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 [email protected]@[email protected] 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 [email protected]@[email protected] endp

 

Share this post


Link to post
Share on other sites
LMS

Take a closer look at my code, it only depends on ECX. I only use xmm0 to temporarily store the value to be able to either read it from c++ or to set it from c++, but only [ecx+4h] is changed. Also there's no need to safe the registers, your C++ function will take care of this. Your assembly code is an excellent example for this, notice how it pushes ebx, esi and edi because it needs some registers to work with and later pops them again. So in the end when the function returns all registers will be set to their initial value. I'm glad I could help you smile.gif

Share this post


Link to post
Share on other sites
FaTony

Ok, improvising, correct me if I'm wrong:

 

__declspec( naked ) int __stdcall PedDamageHook::Hooked_damagePed(void* unknown, void* target){_asm{// Save ecxpush ecx// Save stackpush ebxpush esipush edi//Prepare callpush [ecx+4h] //damagepush [ebp+14h] //attackerpush [???] //victim// Call functioncall OnPedDamage//Pop arguments (assuming _cdecl)pop ???...//Restore stackpop     edipop     esipop     ebx// Restore ecxpop  ecxjmp  dwRealFunction}}

 

Share this post


Link to post
Share on other sites
LMS

There's no need for you to change the code. Your C++ function will save the stack before using it and later pop it again. You don't have to do it! On top of that you don't have to push the arguments for OnPedDamage again, in the naked function there is no stack activity and thus the arguments are still on the top. Also why do you dislike the idea of storing ecx in a global? Trust me, you don't have to touch the code.

Share this post


Link to post
Share on other sites
FaTony

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:

 

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?

Edited by FaTony

Share this post


Link to post
Share on other sites
LMS

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:

 

 

void PedDamageHook::OnPedDamage(void* unknown, void* target){// Read damage valuefloat damage = PedDamageHook::ReadDamage();// Get damage sourcevoid* 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 10if (source == playerPed){ return damage * 20;}}

 

 

Edit: Yeah, just like your wrapper.

Share this post


Link to post
Share on other sites
FaTony

But wouldn't it be fun to call AdjustDamage from naked function? Looking at your prototype, I see you don't like references. wink.gif

 

I'm going to use wrapper, but will try to get rid of it when I'll have more knowledge of asm.

Share this post


Link to post
Share on other sites
LMS

Sure it would be cleaner, but it would also result in more asm code and more unnecessary work tounge.gif But I think it's a great idea to do this when you have more knowledge of asm. And yeah, thanks to .NET I don't like references and try to avoid them whenever I can. But imho returning the new damage value seems ok when you call the function AdjustDamage.

Share this post


Link to post
Share on other sites
Guest
This topic is now closed to further replies.
Sign in to follow this  

  • 1 User Currently Viewing
    0 members, 0 Anonymous, 1 Guest

×
×
  • Create New...

Important Information

By using GTAForums.com, you agree to our Terms of Use and Privacy Policy.