<?xml version="1.0" encoding="utf-8"?>
<CheatTable CheatEngineTableVersion="46">
  <CheatEntries>
    <CheatEntry>
      <ID>10</ID>
      <Description>"Lua Hook"</Description>
      <Options moHideChildren="1"/>
      <VariableType>Auto Assembler Script</VariableType>
      <AssemblerScript>{ Lua State Hijack - GravityCircuit x64 - runs on game's own thread }

[ENABLE]
alloc(newmem,$400)
alloc(stateStore,8)
alloc(cmd,1024)
alloc(doit,8)
registersymbol(stateStore)
registersymbol(cmd)
registersymbol(doit)
registersymbol(gettopHook)

stateStore:
  dq 0
doit:
  dq 0
cmd:
  db 'a=1',0

label(gettopHook)
label(code)
label(skip)

newmem:
  mov [stateStore],rcx
  cmp qword ptr [doit],0
  je skip
  push rbp
  mov rbp,rsp
  and rsp,-10
  sub rsp,20
  mov qword ptr [doit],0
  mov rcx,[stateStore]
  lea rdx,[cmd]
  call lua51.luaL_loadstring
  mov rcx,[stateStore]
  xor edx,edx
  mov r8d,0FFFFFFFF
  xor r9d,r9d
  call lua51.lua_pcall
  mov rsp,rbp
  pop rbp
skip:
  mov rcx,[stateStore]
code:
  mov rax,[rcx+28]
  sub rax,[rcx+20]
  sar rax,03
  ret

lua51.lua_gettop:
gettopHook:
  jmp newmem

[DISABLE]
lua51.lua_gettop:
  db 48 8B 41 28 48 2B 41 20 48 C1 F8 03 C3
unregistersymbol(stateStore)
unregistersymbol(cmd)
unregistersymbol(doit)
unregistersymbol(gettopHook)
dealloc(cmd)
dealloc(doit)
dealloc(stateStore)
dealloc(newmem)
</AssemblerScript>
      <CheatEntries>
        <CheatEntry>
          <ID>11</ID>
          <Description>"Hacks"</Description>
          <VariableType>Auto Assembler Script</VariableType>
          <AssemblerScript>{ Gravity Circuit Trainer
  Requires the lua_gettop hijack hook ENABLED first.
  Z = rise   X = descend   V = toggle hover
  Numpad 0 = money to 0   1 = +100   2 = +1000   3 = -100   4 = -1000 }

[ENABLE]
{$lua}
if syntaxcheck then return end

__GC_kick = createTimer(getMainForm())
__GC_kick.Interval = 1
__GC_kick.OnTimer = function()
  __GC_kick.destroy(); __GC_kick = nil

  local mf = getMainForm()
  if __GC_timer then __GC_timer.destroy() end
  if __GC_money then for _,h in ipairs(__GC_money) do h.destroy() end end
  __GC_money = {}
  __GC_infhp = true
  __GC_hover, __GC_hoverSet, __GC_lastHK = false, false, false

  local RISE, FALL = 5, 5      -- fly speed per tick

  local function run(s)
    local cmdA, doitA = getAddress("cmd"), getAddress("doit")
    if readQword(doitA) ~= 0 then return false end
    writeString(cmdA, s); writeByte(cmdA + #s, 0); writeQword(doitA, 1)
    return true
  end

  __GC_timer = createTimer(mf)
  __GC_timer.Interval = 16
  __GC_timer.OnTimer = function()
    local hk = isKeyPressed(0x56)
    if hk and not __GC_lastHK then __GC_hover = not __GC_hover; __GC_hoverSet = false end
    __GC_lastHK = hk

    local parts = {"local a=GetActor(1) if a then"}
    if __GC_infhp then
      parts[#parts+1] = "a.INFINITE_HEALTH_ENABLED=true a.health=a.maxhealth"
    end

    local killgrav = "if a.velocity and a.velocity.vertical then a.velocity.vertical.current=0 end"

    local dy = 0
    if isKeyPressed(0x5A) then dy = -RISE end
    if isKeyPressed(0x58) then dy =  FALL end

    if dy ~= 0 then
      parts[#parts+1] = string.format("a:setY(a:getY()+(%d)) %s", dy, killgrav)
      if __GC_hover then parts[#parts+1] = "__hoverY=a:getY()" end
    elseif __GC_hover then
      if not __GC_hoverSet then parts[#parts+1]="__hoverY=a:getY()"; __GC_hoverSet=true end
      parts[#parts+1] = "if __hoverY then a:setY(__hoverY) "..killgrav.." end"
    end
    parts[#parts+1] = "end"

    local cmdA, doitA = getAddress("cmd"), getAddress("doit")
    if readQword(doitA) == 0 then
      local s = table.concat(parts, " ")
      writeString(cmdA, s); writeByte(cmdA + #s, 0); writeQword(doitA, 1)
    end
  end

  local function bind(vk, luastr)
    __GC_money[#__GC_money+1] = createHotkey(function() run(luastr) end, vk)
  end
  bind(0x60, "local c=Money.get() Money.remove(c)")
  bind(0x61, "Money.add(100)")
  bind(0x62, "Money.add(1000)")
  bind(0x63, "Money.remove(100)")
  bind(0x64, "Money.remove(1000)")

  print("[trainer] running -- Z=up X=down V=hover | Num0/1/2/3/4 money")
end
return true
{$asm}

[DISABLE]
{$lua}
if syntaxcheck then return end
if __GC_kick  then __GC_kick.destroy();  __GC_kick=nil  end
if __GC_timer then __GC_timer.destroy(); __GC_timer=nil end
if __GC_money then for _,h in ipairs(__GC_money) do h.destroy() end __GC_money=nil end
local cmdA, doitA = getAddress("cmd"), getAddress("doit")
local s="local a=GetActor(1) if a then a.INFINITE_HEALTH_ENABLED=false end"
writeString(cmdA,s); writeByte(cmdA+#s,0); writeQword(doitA,1)
return true
{$asm}
</AssemblerScript>
        </CheatEntry>
      </CheatEntries>
    </CheatEntry>
  </CheatEntries>
  <UserdefinedSymbols/>
</CheatTable>
