No time to clean this up, but here's a simple teleport script. Using the PlayerXYZ struct from SunBeam's table and snooping around code near fireundubh's find of the WorldMap functions.
Enable 'INJECT_PlayerXYZ' to find the structure with player coordinates you can modify. Then enable 'INJECT_SetMapMarker' to hook that function. Finally set the final entry 'bTeleportWhenSettingMarker' to 1. When you set a map marker it will change the player's X and Y to that position and Z to a high value.
Unfortunately the map marker doesn't seem to know the height, and if it's too low you fall through the world and go back to where you were (or last save?), so ENABLE GOD MODE SOMEHOW so the fall doesn't kill you.
Code: Select all
<?xml version="1.0" encoding="utf-8"?>
<CheatTable>
<CheatEntries>
<CheatEntry>
<ID>124</ID>
<Description>"INJECT_PlayerXYZ"</Description>
<LastState Activated="1"/>
<VariableType>Auto Assembler Script</VariableType>
<AssemblerScript>{ Game : HorizonZeroDawn.exe
Version:
Date : 2020-08-10
Author : jason (Thanks SunBeam!)
This accesses the pointer to PlayerXYZ (found using SunBeam's awesome analysis)
This pointer (loaded into rax here) has player location that can be modified
at +70, +74, +78
rsi is therefore PhysicsCharacterMoveProxy
}
[ENABLE]
aobscanmodule(INJECT_PlayerXYZ,HorizonZeroDawn.exe,48 8B 86 E0 00 00 00 48 8D 8E) // should be unique
alloc(newmem,$1000,"HorizonZeroDawn.exe"+671883)
label(code)
label(return)
label(pPlayerXYZ)
newmem:
code:
mov rax,[rsi+000000E0]
mov [pPlayerXYZ],rax
jmp return
align 10
pPlayerXYZ:
dq 0
INJECT_PlayerXYZ:
jmp newmem
nop 2
return:
registersymbol(INJECT_PlayerXYZ)
registersymbol(pPlayerXYZ)
[DISABLE]
INJECT_PlayerXYZ:
db 48 8B 86 E0 00 00 00
unregistersymbol(INJECT_PlayerXYZ)
unregistersymbol(pPlayerXYZ)
dealloc(newmem)
{
// ORIGINAL CODE - INJECTION POINT: "HorizonZeroDawn.exe"+671883
"HorizonZeroDawn.exe"+67185A: 57 - push rdi
"HorizonZeroDawn.exe"+67185B: 48 83 EC 20 - sub rsp,20
"HorizonZeroDawn.exe"+67185F: 48 8B F1 - mov rsi,rcx
"HorizonZeroDawn.exe"+671862: 48 8B FA - mov rdi,rdx
"HorizonZeroDawn.exe"+671865: 48 81 C1 00 01 00 00 - add rcx,00000100
"HorizonZeroDawn.exe"+67186C: FF 15 56 70 3D 01 - call qword ptr [HorizonZeroDawn.exe+1A488C8]
"HorizonZeroDawn.exe"+671872: 84 C0 - test al,al
"HorizonZeroDawn.exe"+671874: 75 0D - jne HorizonZeroDawn.exe+671883
"HorizonZeroDawn.exe"+671876: 48 8D 8E 00 01 00 00 - lea rcx,[rsi+00000100]
"HorizonZeroDawn.exe"+67187D: FF 15 55 70 3D 01 - call qword ptr [HorizonZeroDawn.exe+1A488D8]
// ---------- INJECTING HERE ----------
"HorizonZeroDawn.exe"+671883: 48 8B 86 E0 00 00 00 - mov rax,[rsi+000000E0]
// ---------- DONE INJECTING ----------
"HorizonZeroDawn.exe"+67188A: 48 8D 8E 00 01 00 00 - lea rcx,[rsi+00000100]
"HorizonZeroDawn.exe"+671891: 48 85 C0 - test rax,rax
"HorizonZeroDawn.exe"+671894: 74 14 - je HorizonZeroDawn.exe+6718AA
"HorizonZeroDawn.exe"+671896: C5 FB 10 80 A0 00 00 00 - vmovsd xmm0,[rax+000000A0]
"HorizonZeroDawn.exe"+67189E: C4 E3 79 21 80 A8 00 00 00 20 - unknown avx 0F3A 21 xmm0,xmm0,[rax+000000A8],20
"HorizonZeroDawn.exe"+6718A8: EB 04 - jmp HorizonZeroDawn.exe+6718AE
"HorizonZeroDawn.exe"+6718AA: C5 F8 57 C0 - vxorps xmm0,xmm0,xmm0
"HorizonZeroDawn.exe"+6718AE: C5 F8 11 07 - vmovups [rdi],xmm0
"HorizonZeroDawn.exe"+6718B2: FF 15 30 70 3D 01 - call qword ptr [HorizonZeroDawn.exe+1A488E8]
"HorizonZeroDawn.exe"+6718B8: 48 8B 5C 24 30 - mov rbx,[rsp+30]
}
</AssemblerScript>
<CheatEntries>
<CheatEntry>
<ID>125</ID>
<Description>"pPlayerXYZ"</Description>
<LastState Value="" RealAddress="7FF6758F0020"/>
<GroupHeader>1</GroupHeader>
<Address>pPlayerXYZ</Address>
<CheatEntries>
<CheatEntry>
<ID>126</ID>
<Description>"X"</Description>
<LastState Value="-45.26934814" RealAddress="218CEC6DDA0"/>
<VariableType>Float</VariableType>
<Address>+0</Address>
<Offsets>
<Offset>70</Offset>
</Offsets>
</CheatEntry>
<CheatEntry>
<ID>128</ID>
<Description>"Y"</Description>
<LastState Value="-572.49646" RealAddress="218CEC6DDA4"/>
<VariableType>Float</VariableType>
<Address>+0</Address>
<Offsets>
<Offset>74</Offset>
</Offsets>
</CheatEntry>
<CheatEntry>
<ID>127</ID>
<Description>"Z"</Description>
<LastState Value="213.5658875" RealAddress="218CEC6DDA8"/>
<VariableType>Float</VariableType>
<Address>+0</Address>
<Offsets>
<Offset>78</Offset>
</Offsets>
</CheatEntry>
</CheatEntries>
</CheatEntry>
<CheatEntry>
<ID>113</ID>
<Description>"INJECT_SetMapMarker"</Description>
<LastState Activated="1"/>
<VariableType>Auto Assembler Script</VariableType>
<AssemblerScript>{ Game : HorizonZeroDawn.exe
Version:
Date : 2020-08-10
Author : jason
This script does blah blah blah
}
[ENABLE]
aobscanmodule(INJECT_SetMapMarker,HorizonZeroDawn.exe,8F C8 00 00 00 C5 FA 10 50 08) // should be unique
alloc(newmem,$1000,"HorizonZeroDawn.exe"+1297DE2)
label(code)
label(return)
label(pWorldMap)
label(bTeleportWhenSettingMarker)
newmem:
code:
mov [pWorldMap],rdi
mov [pWorldMap+8],rcx
mov ecx,[rax]
mov [pWorldMap+28],ecx
mov ecx,[rax+4]
mov [pWorldMap+2C],ecx
mov ecx,[rax+8]
mov [pWorldMap+30],ecx
// now we need to find the static pointer
// the address is relative to the next instruction, which is HorizonZeroDawn.exe+1297DA1
// that is return-48
// offset is 32 bits at [return-4c]
// NOT going to worry about that for now, just do it manually
mov rcx,HorizonZeroDawn.exe+71271A0
mov [pWorldMap+10],rcx
mov rcx,[rcx]
mov [pWorldMap+18],rcx
mov rcx,[rcx+940]
mov [pWorldMap+20],rcx
// now for teleport cheat
cmp byte ptr [bTeleportWhenSettingMarker],1
jne @f
mov byte ptr [bTeleportWhenSettingMarker],0
push rbx
push rdx
mov rbx,[pPlayerXYZ]
mov edx,[rax]
mov [rbx+70],edx // x
mov edx,[rax+4]
mov [rbx+74],edx // y
mov edx,(float)300.0 // high value for z so you don't fall through the world (I hope)
mov [rbx+78],edx // z
pop rdx
pop rbx
@@:
mov rcx,[rdi+000000C8] // previous instructino because we mess with rcx
vmovss xmm2,[rax+08] // original code
jmp return
align 10
pWorldMap:
dq 0 // should be pWorldMap, rcx when proc called, saved in rdi
dq 0 // some sort of map pointer? at [rdi+c8], used as argument to function after I think loading xmm0-xmm2 with a location
dq 0 // static pointer, should be HorizonZeroDawn.exe+71271A0
dq 0 // value at HorizonZeroDawn.exe+71271A0
dq 0 // rbx (value at [rax+940]), i.e. [[HorizonZeroDawn.exe+71271A0]+940]
dd 0 0 0 // the location data accessed in these instructions
bTeleportWhenSettingMarker:
dd 0 // set to 1 to enable transport when setting map marker
INJECT_SetMapMarker+05:
jmp newmem
return:
registersymbol(INJECT_SetMapMarker)
registersymbol(pWorldMap)
registersymbol(bTeleportWhenSettingMarker)
[DISABLE]
INJECT_SetMapMarker+05:
db C5 FA 10 50 08
unregistersymbol(INJECT_SetMapMarker)
unregistersymbol(pWorldMap)
unregistersymbol(bTeleportWhenSettingMarker)
dealloc(newmem)
{
// ORIGINAL CODE - INJECTION POINT: "HorizonZeroDawn.exe"+1297DE2
"HorizonZeroDawn.exe"+1297DAB: 48 85 DB - test rbx,rbx
"HorizonZeroDawn.exe"+1297DAE: 0F 84 AD 00 00 00 - je HorizonZeroDawn.exe+1297E61
"HorizonZeroDawn.exe"+1297DB4: 48 8B 89 C8 00 00 00 - mov rcx,[rcx+000000C8]
"HorizonZeroDawn.exe"+1297DBB: 48 85 C9 - test rcx,rcx
"HorizonZeroDawn.exe"+1297DBE: 0F 84 9D 00 00 00 - je HorizonZeroDawn.exe+1297E61
"HorizonZeroDawn.exe"+1297DC4: 80 B9 75 03 00 00 00 - cmp byte ptr [rcx+00000375],00
"HorizonZeroDawn.exe"+1297DCB: 0F 85 90 00 00 00 - jne HorizonZeroDawn.exe+1297E61
"HorizonZeroDawn.exe"+1297DD1: 48 8D 54 24 20 - lea rdx,[rsp+20]
"HorizonZeroDawn.exe"+1297DD6: E8 A5 E5 F7 FF - call HorizonZeroDawn.exe+1216380
"HorizonZeroDawn.exe"+1297DDB: 48 8B 8F C8 00 00 00 - mov rcx,[rdi+000000C8]
// ---------- INJECTING HERE ----------
"HorizonZeroDawn.exe"+1297DE2: C5 FA 10 50 08 - vmovss xmm2,[rax+08]
// ---------- DONE INJECTING ----------
"HorizonZeroDawn.exe"+1297DE7: C5 FA 10 48 04 - vmovss xmm1,[rax+04]
"HorizonZeroDawn.exe"+1297DEC: C5 FA 10 00 - vmovss xmm0,[rax]
"HorizonZeroDawn.exe"+1297DF0: C5 EA 5A D2 - vcvtss2sd xmm2,xmm2,xmm2
"HorizonZeroDawn.exe"+1297DF4: C5 F2 5A C9 - vcvtss2sd xmm1,xmm1,xmm1
"HorizonZeroDawn.exe"+1297DF8: C5 FA 5A C0 - vcvtss2sd xmm0,xmm0,xmm0
"HorizonZeroDawn.exe"+1297DFC: C5 FB 11 44 24 30 - vmovsd [rsp+30],xmm0
"HorizonZeroDawn.exe"+1297E02: C5 FB 11 4C 24 38 - vmovsd [rsp+38],xmm1
"HorizonZeroDawn.exe"+1297E08: C5 FB 11 54 24 40 - vmovsd [rsp+40],xmm2
"HorizonZeroDawn.exe"+1297E0E: E8 4D E5 F7 FF - call HorizonZeroDawn.exe+1216360
"HorizonZeroDawn.exe"+1297E13: 48 8B 5B 28 - mov rbx,[rbx+28]
Full routine:
HorizonZeroDawn.exe+1297D90 - 48 89 5C 24 08 - mov [rsp+08],rbx
HorizonZeroDawn.exe+1297D95 - 57 - push rdi
HorizonZeroDawn.exe+1297D96 - 48 83 EC 50 - sub rsp,50
HorizonZeroDawn.exe+1297D9A - 48 8B 05 FFF3E805 - mov rax,[HorizonZeroDawn.exe+71271A0]
HorizonZeroDawn.exe+1297DA1 - 48 8B F9 - mov rdi,rcx
HorizonZeroDawn.exe+1297DA4 - 48 8B 98 40090000 - mov rbx,[rax+00000940]
HorizonZeroDawn.exe+1297DAB - 48 85 DB - test rbx,rbx
HorizonZeroDawn.exe+1297DAE - 0F84 AD000000 - je HorizonZeroDawn.exe+1297E61
HorizonZeroDawn.exe+1297DB4 - 48 8B 89 C8000000 - mov rcx,[rcx+000000C8]
HorizonZeroDawn.exe+1297DBB - 48 85 C9 - test rcx,rcx
HorizonZeroDawn.exe+1297DBE - 0F84 9D000000 - je HorizonZeroDawn.exe+1297E61
HorizonZeroDawn.exe+1297DC4 - 80 B9 75030000 00 - cmp byte ptr [rcx+00000375],00
HorizonZeroDawn.exe+1297DCB - 0F85 90000000 - jne HorizonZeroDawn.exe+1297E61
HorizonZeroDawn.exe+1297DD1 - 48 8D 54 24 20 - lea rdx,[rsp+20]
HorizonZeroDawn.exe+1297DD6 - E8 A5E5F7FF - call HorizonZeroDawn.exe+1216380
HorizonZeroDawn.exe+1297DDB - 48 8B 8F C8000000 - mov rcx,[rdi+000000C8]
HorizonZeroDawn.exe+1297DE2 - C5FA1050 08 - vmovss xmm2,[rax+08]
HorizonZeroDawn.exe+1297DE7 - C5FA1048 04 - vmovss xmm1,[rax+04]
HorizonZeroDawn.exe+1297DEC - C5FA1000 - vmovss xmm0,[rax]
HorizonZeroDawn.exe+1297DF0 - C5EA5AD2 - vcvtss2sd xmm2,xmm2,xmm2
HorizonZeroDawn.exe+1297DF4 - C5F25AC9 - vcvtss2sd xmm1,xmm1,xmm1
HorizonZeroDawn.exe+1297DF8 - C5FA5AC0 - vcvtss2sd xmm0,xmm0,xmm0
HorizonZeroDawn.exe+1297DFC - C5FB1144 24 30 - vmovsd [rsp+30],xmm0
HorizonZeroDawn.exe+1297E02 - C5FB114C 24 38 - vmovsd [rsp+38],xmm1
HorizonZeroDawn.exe+1297E08 - C5FB1154 24 40 - vmovsd [rsp+40],xmm2
HorizonZeroDawn.exe+1297E0E - E8 4DE5F7FF - call HorizonZeroDawn.exe+1216360
HorizonZeroDawn.exe+1297E13 - 48 8B 5B 28 - mov rbx,[rbx+28]
HorizonZeroDawn.exe+1297E17 - 48 8B CB - mov rcx,rbx
HorizonZeroDawn.exe+1297E1A - 48 85 C0 - test rax,rax
HorizonZeroDawn.exe+1297E1D - 74 13 - je HorizonZeroDawn.exe+1297E32
HorizonZeroDawn.exe+1297E1F - 48 8B D0 - mov rdx,rax
HorizonZeroDawn.exe+1297E22 - E8 D9352300 - call HorizonZeroDawn.exe+14CB400
HorizonZeroDawn.exe+1297E27 - 48 8B 5C 24 60 - mov rbx,[rsp+60]
HorizonZeroDawn.exe+1297E2C - 48 83 C4 50 - add rsp,50
HorizonZeroDawn.exe+1297E30 - 5F - pop rdi
HorizonZeroDawn.exe+1297E31 - C3 - ret
HorizonZeroDawn.exe+1297E32 - 48 8B 87 C8000000 - mov rax,[rdi+000000C8]
HorizonZeroDawn.exe+1297E39 - 48 8D 54 24 30 - lea rdx,[rsp+30]
HorizonZeroDawn.exe+1297E3E - 48 8B B8 00060000 - mov rdi,[rax+00000600]
HorizonZeroDawn.exe+1297E45 - 4C 8B C7 - mov r8,rdi
HorizonZeroDawn.exe+1297E48 - E8 D3572200 - call HorizonZeroDawn.exe+14BD620
HorizonZeroDawn.exe+1297E4D - 84 C0 - test al,al
HorizonZeroDawn.exe+1297E4F - 74 10 - je HorizonZeroDawn.exe+1297E61
HorizonZeroDawn.exe+1297E51 - 4C 8B C7 - mov r8,rdi
HorizonZeroDawn.exe+1297E54 - 48 8D 54 24 30 - lea rdx,[rsp+30]
HorizonZeroDawn.exe+1297E59 - 48 8B CB - mov rcx,rbx
HorizonZeroDawn.exe+1297E5C - E8 BF312300 - call HorizonZeroDawn.exe+14CB020
HorizonZeroDawn.exe+1297E61 - 48 8B 5C 24 60 - mov rbx,[rsp+60]
HorizonZeroDawn.exe+1297E66 - 48 83 C4 50 - add rsp,50
HorizonZeroDawn.exe+1297E6A - 5F - pop rdi
HorizonZeroDawn.exe+1297E6B - C3 - ret
}
</AssemblerScript>
<CheatEntries>
<CheatEntry>
<ID>114</ID>
<Description>"pWorldMap"</Description>
<LastState Value="0000021865F74260" RealAddress="7FF6758E00A0"/>
<ShowAsHex>1</ShowAsHex>
<VariableType>8 Bytes</VariableType>
<Address>pWorldMap</Address>
</CheatEntry>
<CheatEntry>
<ID>115</ID>
<Description>"pWorldMap+8 (some ptr)"</Description>
<LastState Value="0000021867A8D680" RealAddress="7FF6758E00A8"/>
<ShowAsHex>1</ShowAsHex>
<VariableType>8 Bytes</VariableType>
<Address>pWorldMap+8</Address>
</CheatEntry>
<CheatEntry>
<ID>116</ID>
<Description>"pWorldMap+10 (static ptr address)"</Description>
<LastState Value="00007FF67CA271A0" RealAddress="7FF6758E00B0"/>
<ShowAsHex>1</ShowAsHex>
<VariableType>8 Bytes</VariableType>
<Address>pWorldMap+10</Address>
</CheatEntry>
<CheatEntry>
<ID>117</ID>
<Description>"pWorldMap+18 (static ptr value)"</Description>
<LastState Value="00000212C586EC00" RealAddress="7FF6758E00B8"/>
<ShowAsHex>1</ShowAsHex>
<VariableType>8 Bytes</VariableType>
<Address>pWorldMap+18</Address>
</CheatEntry>
<CheatEntry>
<ID>118</ID>
<Description>"pWorldMap+20 ([[static]+940])"</Description>
<LastState Value="00000217DA3E52F0" RealAddress="7FF6758E00C0"/>
<ShowAsHex>1</ShowAsHex>
<VariableType>8 Bytes</VariableType>
<Address>pWorldMap+20</Address>
</CheatEntry>
<CheatEntry>
<ID>119</ID>
<Description>"Marker X?"</Description>
<LastState Value="2971.700684" RealAddress="7FF6758E00C8"/>
<VariableType>Float</VariableType>
<Address>pWorldMap+28</Address>
</CheatEntry>
<CheatEntry>
<ID>120</ID>
<Description>"Marker Y?"</Description>
<LastState Value="-1828.267822" RealAddress="7FF6758E00CC"/>
<VariableType>Float</VariableType>
<Address>pWorldMap+2c</Address>
</CheatEntry>
<CheatEntry>
<ID>121</ID>
<Description>"Marker Z?"</Description>
<LastState Value="184.7215729" RealAddress="7FF6758E00D0"/>
<VariableType>Float</VariableType>
<Address>pWorldMap+30</Address>
</CheatEntry>
<CheatEntry>
<ID>131</ID>
<Description>"bTeleportWhenSettingMarker"</Description>
<LastState Value="0" RealAddress="7FF6758E00D4"/>
<VariableType>Byte</VariableType>
<Address>bTeleportWhenSettingMarker</Address>
</CheatEntry>
</CheatEntries>
</CheatEntry>
</CheatEntries>
</CheatEntry>
</CheatEntries>
</CheatTable>
I was hoping it would be easy to hook and call those functions, but RCX going into this seems to be an instance of MapTag, not WorldMap. If I had the function that performs fast travel... Also the map marker doesn't have the correct Z location that I can see, but it is possible because the map structure has the correct Z location for the center of the screen for some reason....