Figured it out
![Wink ;)](./images/smilies/icon_e_wink.gif)
This is the spot where clip ammo quantity is subtracted before being written to clip inside that CALL:
Code: Select all
FC_m64.dll+AC814F8 - 29 DA - sub edx,ebx
FC_m64.dll+AC814FA - E8 11C308F7 - call FC_m64.dll+1D0D810
Now, I found this function from previous research in Far Cry: Primal:
Code: Select all
FC_m64.dll+A6A1020 - 48 8B 81 682A0000 - mov rax,[rcx+00002A68]
FC_m64.dll+A6A1027 - 80 B8 29070000 00 - cmp byte ptr [rax+00000729],00
FC_m64.dll+A6A102E - 74 08 - je FC_m64.dll+A6A1038
FC_m64.dll+A6A1030 - 0FB6 05 495F45FA - movzx eax,byte ptr [FC_m64.dll+4AF6F80] { [00000001] }
FC_m64.dll+A6A1037 - C3 - ret
FC_m64.dll+A6A1038 - 48 83 C1 08 - add rcx,08
FC_m64.dll+A6A103C - E9 4F1F4AF7 - jmp FC_m64.dll+1B42F90
...
Code: Select all
RCX == 0000026614379A98 ->
FC_m64.dll+A789638 - 48 8B 89 40020000 - mov rcx,[rcx+00000240]
->
RCX == 0000026629A516D0 ->
FC_m64.dll+A6971E0 - 48 8B 81 682A0000 - mov rax,[rcx+00002A68]
->
RAX == 0000026614378EA0
And if I run a "Find out what addresses this instruction accesses", just to be thorough in the demo, I get this:
![Image](https://i.imgur.com/7p3YH8c.png)
So here's my Unlimited Clip Ammo script
![Very Happy :D](./images/smilies/icon_e_biggrin.gif)
Code: Select all
[ENABLE]
aobscanmodule( _ClipAmmo, FC_m64.dll, 48895C2408574883EC2089D74889CB3B9188010000 )
registersymbol( _ClipAmmo )
alloc( ClipAmmo, 256, FC_m64.dll )
label( ClipAmmo_orig )
registersymbol( ClipAmmo_orig )
ClipAmmo:
push rax
push rbx
push rcx // psLaunch
push rdx
push r8
mov rax,[rcx+80]
mov rbx,[rax+10] // CPawnEntity
test rbx,rbx
je short @f
mov rcx,[rbx+C8] // CEntityArchetypeRes
test rcx,rcx
je short @f
lea rdx,[rbx+A8]
movsxd r8,dword ptr [rcx+20]
mov rax,[rdx]
mov rax,[rax+r8*8]
mov rax,[rax+2A68]
cmp byte ptr [rax+729],0 // IsPlayer
jne short @f
pop r8 // yes
pop rdx
pop rcx
pop rbx
pop rax
add edx,ebx // add back subtracted ammo
jmp short ClipAmmo_orig // exit
@@:
pop r8 // no
pop rdx
pop rcx
pop rbx
pop rax
ClipAmmo_orig:
readmem( _ClipAmmo, 5 )
jmp _ClipAmmo+5
_ClipAmmo:
jmp ClipAmmo
[DISABLE]
_ClipAmmo:
readmem( ClipAmmo_orig, 5 )
unregistersymbol( ClipAmmo_orig )
dealloc( ClipAmmo )
unregistersymbol( _ClipAmmo )
/*
FC_m64.dll+AADF710 - 48 89 5C 24 08 - mov [rsp+08],rbx <--
FC_m64.dll+AADF715 - 57 - push rdi
FC_m64.dll+AADF716 - 48 83 EC 20 - sub rsp,20
FC_m64.dll+AADF71A - 89 D7 - mov edi,edx
FC_m64.dll+AADF71C - 48 89 CB - mov rbx,rcx
FC_m64.dll+AADF71F - 3B 91 88010000 - cmp edx,[rcx+00000188]
FC_m64.dll+AADF725 - 74 3C - je FC_m64.dll+AADF763
FC_m64.dll+AADF727 - E8 244024F7 - call FC_m64.dll+1D23750
FC_m64.dll+AADF72C - 39 F8 - cmp eax,edi
FC_m64.dll+AADF72E - C6 83 C4000000 01 - mov byte ptr [rbx+000000C4],01
FC_m64.dll+AADF735 - 41 89 F8 - mov r8d,edi
FC_m64.dll+AADF738 - 44 0F4C C0 - cmovl r8d,eax
FC_m64.dll+AADF73C - 44 89 83 88010000 - mov [rbx+00000188],r8d
FC_m64.dll+AADF743 - 85 FF - test edi,edi
FC_m64.dll+AADF745 - 7E 07 - jle FC_m64.dll+AADF74E
FC_m64.dll+AADF747 - C6 83 D0010000 00 - mov byte ptr [rbx+000001D0],00
FC_m64.dll+AADF74E - 48 8B 8B E0010000 - mov rcx,[rbx+000001E0]
FC_m64.dll+AADF755 - 48 85 C9 - test rcx,rcx
FC_m64.dll+AADF758 - 74 09 - je FC_m64.dll+AADF763
FC_m64.dll+AADF75A - 48 8B 01 - mov rax,[rcx]
FC_m64.dll+AADF75D - FF 90 E8000000 - call qword ptr [rax+000000E8]
FC_m64.dll+AADF763 - 48 8B 5C 24 30 - mov rbx,[rsp+30]
FC_m64.dll+AADF768 - 48 83 C4 20 - add rsp,20
FC_m64.dll+AADF76C - 5F - pop rdi
FC_m64.dll+AADF76D - C3 - ret
*/
Sun
P.S.: You may use the condition in any other scripts, given you determine the register holding the pointer you'll use to get to CPawnPlayer
![Wink ;)](./images/smilies/icon_e_wink.gif)
How to use this cheat table?
- Install Cheat Engine
- Double-click the .CT file in order to open it.
- Click the PC icon in Cheat Engine in order to select the game process.
- Keep the list.
- Activate the trainer options by checking boxes or setting values from 0 to 1