<?xml version="1.0" encoding="utf-8"?>
<CheatTable CheatEngineTableVersion="42">
  <CheatEntries>
    <CheatEntry>
      <ID>0</ID>
      <Description>"Compact Mode"</Description>
      <VariableType>Auto Assembler Script</VariableType>
      <AssemblerScript>[ENABLE]
--https://forum.cheatengine.org/viewtopic.php?t=570055
LuaCall(function cycleFullCompact(sender,force) local state = not(compactmenuitem.Caption == 'Compact View Mode'); if force~=nil then state = not force end; compactmenuitem.Caption = state and 'Compact View Mode' or 'Full View Mode'; getMainForm().Splitter1.Visible = state; getMainForm().Panel4.Visible    = state; getMainForm().Panel5.Visible    = state; end; function addCompactMenu() if compactmenualreadyexists then return end; local parent = getMainForm().Menu.Items; compactmenuitem = createMenuItem(parent); parent.add(compactmenuitem); compactmenuitem.Caption = 'Compact View Mode'; compactmenuitem.OnClick = cycleFullCompact; compactmenualreadyexists = 'yes'; end; addCompactMenu(); cycleFullCompact(nil,true))

[DISABLE]
LuaCall(cycleFullCompact(nil,false))

</AssemblerScript>
    </CheatEntry>
    <CheatEntry>
      <ID>1</ID>
      <Description>"Enable"</Description>
      <Options moHideChildren="1" moDeactivateChildrenAsWell="1"/>
      <VariableType>Auto Assembler Script</VariableType>
      <AssemblerScript>[ENABLE]
{$lua}
if syntaxcheck then
    return
end
if process == nil then
    ShowMessage("Process is not selected.")
elseif readInteger(process) == 0 then
    ShowMessage("Process cannot be opened.")
else
    if monopipe ~= nil and monopipe.ProcessID ~= getOpenedProcessID() then
        monopipe.destroy()
        monopipe = nil
    end
    if monopipe == nil then
        LaunchMonoDataCollector()
    end
end


{$asm}
define(ResourceManagerClearItemCountsProc, "ResourceManager.ClearItemCounts")
define(ResidenceUpdateFirewoodProc, "Residence.UpdateFirewood")
define(ResidenceUpdateWaterProc, "Residence.UpdateWater")
define(VillagerEatIfNecessaryProc, "Villager.EatIfNecessary")
define(ItemStorageRemoveItemsProc, "ItemStorage.RemoveItems")

//Residence.UpdateFirewood
//GameAssembly.dll+80E9DC

//Residence.UpdateWater GameAssembly.dll+80EE42
//GameAssembly.dll+80EF60 (11E)

//Villager.EatIfNecessary
//GameAssembly.dll+5A64EF - 41 B8 01000000        - mov r8d,00000001

//Villager.CalculateToolWear   GameAssembly.dll+5A4CD0
//GameAssembly.dll+5A4E49


//ItemStorage.RemoveItems  GameAssembly.dll+938C74



registersymbol(ResourceManagerClearItemCountsProc)
registersymbol(ResidenceUpdateFirewoodProc)
registersymbol(ResidenceUpdateWaterProc)
registersymbol(VillagerEatIfNecessaryProc)
registersymbol(ItemStorageRemoveItemsProc)

[DISABLE]
{$lua}
if syntaxcheck then return end;if not syntaxcheck and monopipe then monopipe=nil,monopipe.Destroy()end

{$asm}
unregistersymbol(*)

</AssemblerScript>
      <CheatEntries>
        <CheatEntry>
          <ID>2</ID>
          <Description>"Enable twice: 1st: waiting for IL2CPP to complete, then re-enable again"</Description>
          <Color>8000FF</Color>
          <GroupHeader>1</GroupHeader>
        </CheatEntry>
        <CheatEntry>
          <ID>18</ID>
          <Description>"Item gather number multiplier"</Description>
          <Options moHideChildren="1"/>
          <VariableType>Auto Assembler Script</VariableType>
          <AssemblerScript>{ Game   : Farthest Frontier.exe
  Version: 
  Date   : 2023-01-04
  Author : bbfox@https://opencheattables.com
}

[ENABLE]
//ItemBundle.AddItems #2
aobscanmodule(INJECT_MASS_ADD,GameAssembly.dll,01 41 20 41 83 F8 65) // should be unique
alloc(newmem,$1000,INJECT_MASS_ADD)

label(code)
label(return)
label(vf_item_add_multi)

newmem:
  cmp eax, 0
  je code
  cvtsi2ss xmm15, eax
  vmovss xmm14, [vf_item_add_multi]
  vmulss xmm15, xmm15, xmm14
  vcvtss2si eax, xmm15

code:
  add [rcx+20],eax
  cmp r8d,65
  jmp return
align 10 cc
  vf_item_add_multi:
  dd (float)10
  db EB 3B 54 68 69 73 20 74 61 62 6C 65 20 63 6F 6D 65 73 20 66 72 6F 6D 20 68 74 74 70 73 3A 2F
  db 2F 6F 70 65 6E 63 68 65 61 74 74 61 62 6C 65 73 2E 63 6F 6D 20 2F 20 43 45 20 37 2E 34 2B

INJECT_MASS_ADD:
  jmp newmem
  nop 2
return:
registersymbol(INJECT_MASS_ADD)
registersymbol(vf_item_add_multi)

[DISABLE]

INJECT_MASS_ADD:
  db 01 41 20 41 83 F8 65

unregistersymbol(*)
dealloc(newmem)

{
// ORIGINAL CODE - INJECTION POINT: GameAssembly.dll+4B0855

GameAssembly.dll+4B0832: 4A 8D 0C 80           - lea rcx,[rax+r8*4]
GameAssembly.dll+4B0836: 48 85 D2              - test rdx,rdx
GameAssembly.dll+4B0839: 74 28                 - je GameAssembly.dll+4B0863
GameAssembly.dll+4B083B: 48 8B 82 98 00 00 00  - mov rax,[rdx+00000098]
GameAssembly.dll+4B0842: 48 85 C0              - test rax,rax
GameAssembly.dll+4B0845: 74 1C                 - je GameAssembly.dll+4B0863
GameAssembly.dll+4B0847: 44 3B 40 18           - cmp r8d,[rax+18]
GameAssembly.dll+4B084B: 73 1C                 - jae GameAssembly.dll+4B0869
GameAssembly.dll+4B084D: 42 8B 44 80 20        - mov eax,[rax+r8*4+20]
GameAssembly.dll+4B0852: 41 FF C0              - inc r8d
// ---------- INJECTING HERE ----------
GameAssembly.dll+4B0855: 01 41 20              - add [rcx+20],eax
// ---------- DONE INJECTING  ----------
GameAssembly.dll+4B0858: 41 83 F8 65           - cmp r8d,65
GameAssembly.dll+4B085C: 72 C2                 - jb GameAssembly.dll+4B0820
GameAssembly.dll+4B085E: 48 83 C4 28           - add rsp,28
GameAssembly.dll+4B0862: C3                    - ret 
GameAssembly.dll+4B0863: E8 38 75 D5 FF        - call GameAssembly.dll+207DA0
GameAssembly.dll+4B0868: CC                    - int 3 
GameAssembly.dll+4B0869: E8 42 71 D5 FF        - call GameAssembly.dll+2079B0
GameAssembly.dll+4B086E: 48 8B C8              - mov rcx,rax
GameAssembly.dll+4B0871: 33 D2                 - xor edx,edx
GameAssembly.dll+4B0873: E8 E8 74 D5 FF        - call GameAssembly.dll+207D60
}
</AssemblerScript>
          <CheatEntries>
            <CheatEntry>
              <ID>19</ID>
              <Description>"Multiplier"</Description>
              <ShowAsSigned>0</ShowAsSigned>
              <Color>C08000</Color>
              <VariableType>Float</VariableType>
              <Address>vf_item_add_multi</Address>
            </CheatEntry>
          </CheatEntries>
        </CheatEntry>
        <CheatEntry>
          <ID>27</ID>
          <Description>"Experimental"</Description>
          <Options moHideChildren="1"/>
          <GroupHeader>1</GroupHeader>
          <CheatEntries>
            <CheatEntry>
              <ID>11</ID>
              <Description>"Selected resource"</Description>
              <Options moHideChildren="1"/>
              <VariableType>Auto Assembler Script</VariableType>
              <AssemblerScript Async="1">{ Game   : Farthest Frontier.exe
  Version: 
  Date   : 2023-01-03
  Author : bbfox@https://opencheattables.com
}

[ENABLE]

aobscanmodule(INJECT_SELECTED_OBJECT,GameAssembly.dll,8B 44 88 20 89 44 8A 20 FF) // should be unique
alloc(newmem,$1000,INJECT_SELECTED_OBJECT)

label(code)
label(return)
label(i_base_sel_object_addr1)
label(i_base_sel_object_addr2)
label(i_base_sel_object_addr3)
label(i_base_sel_object_addr4)
label(i_base_sel_object_addr5)
label(is_reset_data1)

newmem:
  cmp dword ptr [is_reset_data1], 1
  jne do_start
  mov qword ptr [i_base_sel_object_addr1], 0
  mov qword ptr [i_base_sel_object_addr2], 0
  mov qword ptr [i_base_sel_object_addr3], 0
  mov qword ptr [i_base_sel_object_addr4], 0
  mov qword ptr [i_base_sel_object_addr5], 0
  mov dword ptr [is_reset_data1], 0

do_start:
  push r15

  lea r15, [rax+rcx*4+20]
  cmp [r15], 0
  je endp

check1:
  cmp [i_base_sel_object_addr1], r15
  je endp

  cmp qword ptr [i_base_sel_object_addr1], 0
  jne check2
  mov [i_base_sel_object_addr1], r15
  jmp endp

check2:
  cmp [i_base_sel_object_addr2], r15
  je endp

  cmp qword ptr [i_base_sel_object_addr2], 0
  jne check3
  mov [i_base_sel_object_addr2], r15
  jmp endp

check3:
  cmp [i_base_sel_object_addr3], r15
  je endp

  cmp qword ptr [i_base_sel_object_addr3], 0
  jne check4
  mov [i_base_sel_object_addr3], r15
  jmp endp

check4:
  cmp [i_base_sel_object_addr4], r15
  je endp

  cmp qword ptr [i_base_sel_object_addr4], 0
  jne check5
  mov [i_base_sel_object_addr4], r15
  jmp endp

check5:
  cmp [i_base_sel_object_addr5], r15
  je endp

  cmp qword ptr [i_base_sel_object_addr5], 0
  jne endp
  mov [i_base_sel_object_addr5], r15
  jmp endp


endp:

  pop r15

code:
  mov eax,[rax+rcx*4+20]
  mov [rdx+rcx*4+20],eax
  jmp return
align 10 cc
  i_base_sel_object_addr1:
  dq 0
  i_base_sel_object_addr2:
  dq 0
  i_base_sel_object_addr3:
  dq 0
  i_base_sel_object_addr4:
  dq 0
  i_base_sel_object_addr5:
  dq 0
  is_reset_data1:
  dd 0


INJECT_SELECTED_OBJECT:
  jmp newmem
  nop 3
return:
registersymbol(INJECT_SELECTED_OBJECT)
registersymbol(i_base_sel_object_addr1)
registersymbol(i_base_sel_object_addr2)
registersymbol(i_base_sel_object_addr3)
registersymbol(i_base_sel_object_addr4)
registersymbol(i_base_sel_object_addr5)
registersymbol(is_reset_data1)

[DISABLE]

INJECT_SELECTED_OBJECT:
  db 8B 44 88 20 89 44 8A 20

unregistersymbol(*)
dealloc(newmem)

{
// ORIGINAL CODE - INJECTION POINT: GameAssembly.dll+4B1845

GameAssembly.dll+4B1823: 48 8B 86 98 00 00 00  - mov rax,[rsi+00000098]
GameAssembly.dll+4B182A: 48 85 C0              - test rax,rax
GameAssembly.dll+4B182D: 74 4D                 - je GameAssembly.dll+4B187C
GameAssembly.dll+4B182F: 3B 48 18              - cmp ecx,[rax+18]
GameAssembly.dll+4B1832: 73 5E                 - jae GameAssembly.dll+4B1892
GameAssembly.dll+4B1834: 48 8B 97 98 00 00 00  - mov rdx,[rdi+00000098]
GameAssembly.dll+4B183B: 48 85 D2              - test rdx,rdx
GameAssembly.dll+4B183E: 74 3C                 - je GameAssembly.dll+4B187C
GameAssembly.dll+4B1840: 3B 4A 18              - cmp ecx,[rdx+18]
GameAssembly.dll+4B1843: 73 3D                 - jae GameAssembly.dll+4B1882
// ---------- INJECTING HERE ----------
GameAssembly.dll+4B1845: 8B 44 88 20           - mov eax,[rax+rcx*4+20]
// ---------- DONE INJECTING  ----------
GameAssembly.dll+4B1849: 89 44 8A 20           - mov [rdx+rcx*4+20],eax
GameAssembly.dll+4B184D: FF C1                 - inc ecx
GameAssembly.dll+4B184F: 83 F9 65              - cmp ecx,65
GameAssembly.dll+4B1852: 7C CF                 - jl GameAssembly.dll+4B1823
GameAssembly.dll+4B1854: 8B 86 A0 00 00 00     - mov eax,[rsi+000000A0]
GameAssembly.dll+4B185A: 48 8B 5C 24 38        - mov rbx,[rsp+38]
GameAssembly.dll+4B185F: 89 87 A0 00 00 00     - mov [rdi+000000A0],eax
GameAssembly.dll+4B1865: 8B 86 A4 00 00 00     - mov eax,[rsi+000000A4]
GameAssembly.dll+4B186B: 48 8B 74 24 40        - mov rsi,[rsp+40]
GameAssembly.dll+4B1870: 89 87 A4 00 00 00     - mov [rdi+000000A4],eax
}
</AssemblerScript>
              <CheatEntries>
                <CheatEntry>
                  <ID>20</ID>
                  <Description>"1. Pause game"</Description>
                  <Color>8000FF</Color>
                  <GroupHeader>1</GroupHeader>
                </CheatEntry>
                <CheatEntry>
                  <ID>21</ID>
                  <Description>"2. Restart script for each different resource spot"</Description>
                  <Color>8000FF</Color>
                  <GroupHeader>1</GroupHeader>
                </CheatEntry>
                <CheatEntry>
                  <ID>26</ID>
                  <Description>"Reset data?"</Description>
                  <DropDownList DisplayValueAsItem="1">0:No
1:Yes
</DropDownList>
                  <ShowAsSigned>0</ShowAsSigned>
                  <VariableType>4 Bytes</VariableType>
                  <Address>is_reset_data1</Address>
                </CheatEntry>
                <CheatEntry>
                  <ID>12</ID>
                  <Description>"Number 1"</Description>
                  <ShowAsSigned>0</ShowAsSigned>
                  <Color>FF8080</Color>
                  <VariableType>4 Bytes</VariableType>
                  <Address>i_base_sel_object_addr1</Address>
                  <Offsets>
                    <Offset>0</Offset>
                  </Offsets>
                </CheatEntry>
                <CheatEntry>
                  <ID>23</ID>
                  <Description>"Number 2"</Description>
                  <ShowAsSigned>0</ShowAsSigned>
                  <Color>FF8080</Color>
                  <VariableType>4 Bytes</VariableType>
                  <Address>i_base_sel_object_addr2</Address>
                  <Offsets>
                    <Offset>0</Offset>
                  </Offsets>
                </CheatEntry>
                <CheatEntry>
                  <ID>22</ID>
                  <Description>"Number 3"</Description>
                  <ShowAsSigned>0</ShowAsSigned>
                  <Color>FF8080</Color>
                  <VariableType>4 Bytes</VariableType>
                  <Address>i_base_sel_object_addr3</Address>
                  <Offsets>
                    <Offset>0</Offset>
                  </Offsets>
                </CheatEntry>
                <CheatEntry>
                  <ID>24</ID>
                  <Description>"Number 4"</Description>
                  <ShowAsSigned>0</ShowAsSigned>
                  <Color>FF8080</Color>
                  <VariableType>4 Bytes</VariableType>
                  <Address>i_base_sel_object_addr4</Address>
                  <Offsets>
                    <Offset>0</Offset>
                  </Offsets>
                </CheatEntry>
                <CheatEntry>
                  <ID>25</ID>
                  <Description>"Number 5"</Description>
                  <ShowAsSigned>0</ShowAsSigned>
                  <Color>FF8080</Color>
                  <VariableType>4 Bytes</VariableType>
                  <Address>i_base_sel_object_addr5</Address>
                  <Offsets>
                    <Offset>0</Offset>
                  </Offsets>
                </CheatEntry>
              </CheatEntries>
            </CheatEntry>
          </CheatEntries>
        </CheatEntry>
      </CheatEntries>
    </CheatEntry>
    <CheatEntry>
      <ID>28</ID>
      <Description>"Farthest Frontier v0.8.0  /  https://opencheattables.com  /  CE 7.4+"</Description>
      <GroupHeader>1</GroupHeader>
    </CheatEntry>
  </CheatEntries>
  <UserdefinedSymbols/>
  <LuaScript>--[[
from https://forum.cheatengine.org/viewtopic.php?p=5659739&amp;sid=72bd2d145c30bf0d344304bce17ea990#5659739
FauDrei
--]]
function toHex(num)
    if num == 0 then
        return '0'
    end
    local neg = false
    if num &lt; 0 then
        neg = true
        num = num * -1
    end
    local hexstr = "0123456789ABCDEF"
    local result = ""
    while num &gt; 0 do
        local n = math.mod(num, 16)
        result = string.sub(hexstr, n + 1, n + 1) .. result
        num = math.floor(num / 16)
    end
    if neg then
        result = '-' .. result
    end
    return result
end


function reEscape(s)
  local escPatChars = [[().%+-*?[^]]
  s = s:gsub('.',function(c) if escPatChars:find(c,1,true) then return '%'..c end end)
  return s
end

function findMethodAddrBySignature(namespace,classname,methodname,signature,check)
  local meth = findMethodBySignature(namespace,classname,methodname,signature,check)
  if meth~=nil and meth&gt;0 then
    return mono_compile_method(meth)
  end
end

function findMethodBySignature(namespace,classname,methodname,signature,check)
  assert(type(signature)=='string',"invalid signature")
  signature="^"..reEscape(signature:gsub(";",","))
  local class = mono_findClass(namespace,classname)
  if type(class)~='number' or class==0 then return nil end
  local methods=mono_class_enumMethods(class)
  if type(methods)~='table' or #methods&lt;1 then return nil end
  if check then  print('check:'..methodname..": &lt;"..signature.."&gt; vs ") end
  for i=1,#methods do
   if methodname == methods[i].name then
     local sign = mono_method_getSignature(methods[i].method)
     if check then  print("  &gt;&gt; &lt;"..sign..'&gt;') end
     if sign:match(signature) then
       return methods[i].method
     end
   end
  end
end

--registerLuaFunctionHighlight('tohex')
registerLuaFunctionHighlight('toHex')
registerLuaFunctionHighlight('reEscape')
registerLuaFunctionHighlight('findMethodAddrBySignature')
registerLuaFunctionHighlight('findMethodBySignature')

</LuaScript>
</CheatTable>
