<?xml version="1.0" encoding="utf-8"?>
<CheatTable CheatEngineTableVersion="46">
  <CheatEntries>
    <CheatEntry>
      <ID>13</ID>
      <Description>"God Mode"</Description>
      <VariableType>Auto Assembler Script</VariableType>
      <AssemblerScript>[ENABLE]

{$lua}
if syntaxcheck then return end

if LaunchMonoDataCollector() == 0 then
  error("Could not activate Mono. Make sure Valheim is fully loaded.")
end

{$asm}

define(ISPLAYER,Player:IsPlayer)
define(SETHEALTH,Character:SetHealth)

assert(ISPLAYER,48 83 EC 08 B8 01 00 00 00 48 83 C4 08 C3)
assert(SETHEALTH,55 48 8B EC 48 83 EC 40 48 89 75 F0 48 89 7D F8)

alloc(godmem,$1000)

label(playerHook)
label(healthHook)
label(normalHealth)
label(blockDamage)
label(playerPtr)

godmem:

playerPtr:
  dq 0

// Capture the Player object whenever Player:IsPlayer runs.
// Then reproduce the original function exactly.
playerHook:
  mov [playerPtr],rcx
  sub rsp,08
  mov eax,00000001
  add rsp,08
  ret

// Character:SetHealth entry:
// RCX  = Character object
// XMM1 = requested new health
healthHook:
  cmp rcx,[playerPtr]
  jne normalHealth

  // Current health is Character+524
  comiss xmm1,[rcx+524]

  // Proposed health is lower - block damage
  jb blockDamage

normalHealth:
  // Replay the 16 bytes replaced at Character:SetHealth
  push rbp
  mov rbp,rsp
  sub rsp,40
  mov [rbp-10],rsi
  mov [rbp-08],rdi

  jmp far SETHEALTH+10

blockDamage:
  ret

// Player:IsPlayer is exactly 14 bytes long
ISPLAYER:
  jmp far playerHook

// We overwrite the first 16 bytes of SetHealth
SETHEALTH:
  jmp far healthHook
  nop 2

registersymbol(playerPtr)

[DISABLE]

ISPLAYER:
  db 48 83 EC 08 B8 01 00 00 00 48 83 C4 08 C3

SETHEALTH:
  db 55 48 8B EC 48 83 EC 40 48 89 75 F0 48 89 7D F8

unregistersymbol(playerPtr)
dealloc(godmem)
</AssemblerScript>
    </CheatEntry>
    <CheatEntry>
      <ID>27</ID>
      <Description>"Max Health (125)"</Description>
      <VariableType>Auto Assembler Script</VariableType>
      <AssemblerScript>[ENABLE]

{$lua}
if syntaxcheck then return end

if LaunchMonoDataCollector() == 0 then
  error("Could not activate Mono. Make sure Valheim is fully loaded.")
end

{$asm}

define(MAXHEALTH,Player:SetMaxHealth)

assert(MAXHEALTH+F,F3 0F 11 4D F0)

alloc(maxhealthmem,$1000,MAXHEALTH+F)

label(return)
label(original)
label(minHealth)

maxhealthmem:

  // XMM1 = requested new max health
  // If Valheim wants less than 125, replace it with 125
  comiss xmm1,[minHealth]
  jae original

  movss xmm1,[minHealth]

original:
  // Original instruction
  movss [rbp-10],xmm1
  jmp return

minHealth:
  dd (float)125

MAXHEALTH+F:
  jmp maxhealthmem

return:


[DISABLE]

define(MAXHEALTH,Player:SetMaxHealth)

MAXHEALTH+F:
  db F3 0F 11 4D F0

dealloc(maxhealthmem)
</AssemblerScript>
    </CheatEntry>
    <CheatEntry>
      <ID>14</ID>
      <Description>"Infinite Stamina"</Description>
      <VariableType>Auto Assembler Script</VariableType>
      <AssemblerScript>[ENABLE]

{$lua}
if syntaxcheck then return end

if LaunchMonoDataCollector() == 0 then
  error("Could not activate Mono. Make sure Valheim is fully loaded.")
end

{$asm}

define(USESTAMINA,Player:RPC_UseStamina)

// Updated Valheim stamina field offset:
// Old: +988
// New: +990

assert(USESTAMINA+4C,F3 0F 11 AE 90 09 00 00)

// Original:
// movss [rsi+00000990],xmm5
//
// Prevent reduced stamina from being stored.

USESTAMINA+4C:
  db 90 90 90 90 90 90 90 90


[DISABLE]

define(USESTAMINA,Player:RPC_UseStamina)

// Restore original stamina instruction.

USESTAMINA+4C:
  db F3 0F 11 AE 90 09 00 00
</AssemblerScript>
    </CheatEntry>
    <CheatEntry>
      <ID>42</ID>
      <Description>"CarryWeight 1000"</Description>
      <VariableType>Auto Assembler Script</VariableType>
      <AssemblerScript>[ENABLE]

{$lua}
if syntaxcheck then return end

if LaunchMonoDataCollector() == 0 then
  error("Mono initialization failed")
end

local method = mono_findMethod("", "Player", "GetMaxCarryWeight")
if not method or method == 0 then
  error("GetMaxCarryWeight not found")
end

local compiled = mono_compile_method(method)
local ji = mono_getJitInfo(compiled)
if not ji then error("JIT info unavailable") end

local pattern = {
  0xF3,0x0F,0x10,0x45,0xF4,
  0xF3,0x0F,0x5A,0xC0,
  0xF2,0x0F,0x5A,0xC0
}

local data = readBytes(ji.code_start,ji.code_size,true)
if not data then error("Unable to read method") end

local addr = nil
for i=1,#data-#pattern+1 do
  local ok=true
  for j=1,#pattern do
    if data[i+j-1]~=pattern[j] then
      ok=false
      break
    end
  end
  if ok then
    addr=ji.code_start+i-1
    break
  end
end

if not addr then error("Carry-weight pattern not found") end

unregisterSymbol("CarryWeightHook")
registerSymbol("CarryWeightHook",addr)

{$asm}

alloc(CarryWeightCode,256,CarryWeightHook)
alloc(CarryWeightValue,4)

registersymbol(CarryWeightValue)

CarryWeightValue:
  dd 10000

CarryWeightCode:
  mov eax,[CarryWeightValue]
  cvtsi2ss xmm0,eax
  jmp CarryWeightHook+0D

CarryWeightHook:
  jmp CarryWeightCode
  nop 8

[DISABLE]

CarryWeightHook:
  db F3 0F 10 45 F4 F3 0F 5A C0 F2 0F 5A C0

unregistersymbol(CarryWeightValue)
unregistersymbol(CarryWeightHook)

dealloc(CarryWeightCode)
dealloc(CarryWeightValue)
</AssemblerScript>
    </CheatEntry>
    <CheatEntry>
      <ID>52</ID>
      <Description>"Run Speed"</Description>
      <Options moHideChildren="1"/>
      <GroupHeader>1</GroupHeader>
      <CheatEntries>
        <CheatEntry>
          <ID>48</ID>
          <Description>"1.5x Run Speed"</Description>
          <VariableType>Auto Assembler Script</VariableType>
          <AssemblerScript>[ENABLE]

{$lua}
if syntaxcheck then return end

if LaunchMonoDataCollector() == 0 then
  error("Could not activate Mono. Make sure Valheim is fully loaded.")
end

--------------------------------------------------
-- Find local Player
--------------------------------------------------

local playerClass = mono_findClass("", "Player")

if not playerClass or playerClass == 0 then
  error("Could not find Player class")
end

local playerFields = mono_class_enumFields(playerClass)
local localPlayerField = nil

for i = 1, #playerFields do
  if playerFields[i].name == "m_localPlayer"
     and playerFields[i].isStatic then
    localPlayerField = playerFields[i]
    break
  end
end

if not localPlayerField then
  error("Could not find Player.m_localPlayer")
end

local domains = mono_enumDomains()
local staticBase =
  mono_class_getStaticFieldAddress(domains[1], playerClass)

if not staticBase or staticBase == 0 then
  error("Could not resolve Player static fields")
end

local player =
  readPointer(staticBase + localPlayerField.offset)

if not player or player == 0 then
  error("Local player not found. Load into your world first.")
end

--------------------------------------------------
-- Find Character movement fields
--------------------------------------------------

local characterClass = mono_findClass("", "Character")

if not characterClass or characterClass == 0 then
  error("Could not find Character class")
end

local characterFields =
  mono_class_enumFields(characterClass)

local runOffset = nil
local swimOffset = nil

for i = 1, #characterFields do
  if characterFields[i].name == "m_runSpeed" then
    runOffset = characterFields[i].offset

  elseif characterFields[i].name == "m_swimSpeed" then
    swimOffset = characterFields[i].offset
  end
end

if not runOffset then
  error("Could not find Character.m_runSpeed")
end

if not swimOffset then
  error("Could not find Character.m_swimSpeed")
end

--------------------------------------------------
-- Save original speeds only once
--------------------------------------------------

local state = _G.ValheimMovementSpeedState

if not state
   or state.player ~= player
   or state.runOffset ~= runOffset
   or state.swimOffset ~= swimOffset then

  local baseRun = readFloat(player + runOffset)
  local baseSwim = readFloat(player + swimOffset)

  if baseRun == nil then
    error("Could not read original run speed")
  end

  if baseSwim == nil then
    error("Could not read original swim speed")
  end

  state = {
    player = player,
    runOffset = runOffset,
    swimOffset = swimOffset,
    baseRun = baseRun,
    baseSwim = baseSwim
  }

  _G.ValheimMovementSpeedState = state
end

--------------------------------------------------
-- Turn off other Movement Speed options
--------------------------------------------------

_G.ValheimMovementSpeedSwitching = true

local parent = memrec.Parent

if parent then
  for i = 0, parent.Count - 1 do
    local mr = parent.Child[i]

    if mr ~= memrec and mr.Active then
      mr.Active = false
    end
  end
end

--------------------------------------------------
-- Apply 1.5x
--------------------------------------------------

writeFloat(
  state.player + state.runOffset,
  state.baseRun * 1.5
)

writeFloat(
  state.player + state.swimOffset,
  state.baseSwim * 1.5
)

_G.ValheimMovementSpeedSwitching = false

{$asm}


[DISABLE]

{$lua}
if syntaxcheck then return end

if _G.ValheimMovementSpeedSwitching then
  return
end

local state = _G.ValheimMovementSpeedState

if state and state.player and state.player ~= 0 then
  writeFloat(
    state.player + state.runOffset,
    state.baseRun
  )

  writeFloat(
    state.player + state.swimOffset,
    state.baseSwim
  )
end

_G.ValheimMovementSpeedState = nil

{$asm}
</AssemblerScript>
        </CheatEntry>
        <CheatEntry>
          <ID>49</ID>
          <Description>"2x Run Speed"</Description>
          <VariableType>Auto Assembler Script</VariableType>
          <AssemblerScript>[ENABLE]

{$lua}
if syntaxcheck then return end

if LaunchMonoDataCollector() == 0 then
  error("Could not activate Mono. Make sure Valheim is fully loaded.")
end

--------------------------------------------------
-- Find local Player
--------------------------------------------------

local playerClass = mono_findClass("", "Player")

if not playerClass or playerClass == 0 then
  error("Could not find Player class")
end

local playerFields = mono_class_enumFields(playerClass)
local localPlayerField = nil

for i = 1, #playerFields do
  if playerFields[i].name == "m_localPlayer"
     and playerFields[i].isStatic then
    localPlayerField = playerFields[i]
    break
  end
end

if not localPlayerField then
  error("Could not find Player.m_localPlayer")
end

local domains = mono_enumDomains()
local staticBase =
  mono_class_getStaticFieldAddress(domains[1], playerClass)

if not staticBase or staticBase == 0 then
  error("Could not resolve Player static fields")
end

local player =
  readPointer(staticBase + localPlayerField.offset)

if not player or player == 0 then
  error("Local player not found. Load into your world first.")
end

--------------------------------------------------
-- Find Character movement fields
--------------------------------------------------

local characterClass = mono_findClass("", "Character")

if not characterClass or characterClass == 0 then
  error("Could not find Character class")
end

local characterFields =
  mono_class_enumFields(characterClass)

local runOffset = nil
local swimOffset = nil

for i = 1, #characterFields do
  if characterFields[i].name == "m_runSpeed" then
    runOffset = characterFields[i].offset

  elseif characterFields[i].name == "m_swimSpeed" then
    swimOffset = characterFields[i].offset
  end
end

if not runOffset then
  error("Could not find Character.m_runSpeed")
end

if not swimOffset then
  error("Could not find Character.m_swimSpeed")
end

--------------------------------------------------
-- Save original speeds only once
--------------------------------------------------

local state = _G.ValheimMovementSpeedState

if not state
   or state.player ~= player
   or state.runOffset ~= runOffset
   or state.swimOffset ~= swimOffset then

  local baseRun = readFloat(player + runOffset)
  local baseSwim = readFloat(player + swimOffset)

  if baseRun == nil then
    error("Could not read original run speed")
  end

  if baseSwim == nil then
    error("Could not read original swim speed")
  end

  state = {
    player = player,
    runOffset = runOffset,
    swimOffset = swimOffset,
    baseRun = baseRun,
    baseSwim = baseSwim
  }

  _G.ValheimMovementSpeedState = state
end

--------------------------------------------------
-- Turn off other Movement Speed options
--------------------------------------------------

_G.ValheimMovementSpeedSwitching = true

local parent = memrec.Parent

if parent then
  for i = 0, parent.Count - 1 do
    local mr = parent.Child[i]

    if mr ~= memrec and mr.Active then
      mr.Active = false
    end
  end
end

--------------------------------------------------
-- Apply 2x
--------------------------------------------------

writeFloat(
  state.player + state.runOffset,
  state.baseRun * 2.0
)

writeFloat(
  state.player + state.swimOffset,
  state.baseSwim * 2.0
)

_G.ValheimMovementSpeedSwitching = false

{$asm}


[DISABLE]

{$lua}
if syntaxcheck then return end

if _G.ValheimMovementSpeedSwitching then
  return
end

local state = _G.ValheimMovementSpeedState

if state and state.player and state.player ~= 0 then
  writeFloat(
    state.player + state.runOffset,
    state.baseRun
  )

  writeFloat(
    state.player + state.swimOffset,
    state.baseSwim
  )
end

_G.ValheimMovementSpeedState = nil

{$asm}
</AssemblerScript>
        </CheatEntry>
        <CheatEntry>
          <ID>50</ID>
          <Description>"3x Run Speed"</Description>
          <VariableType>Auto Assembler Script</VariableType>
          <AssemblerScript>[ENABLE]

{$lua}
if syntaxcheck then return end

if LaunchMonoDataCollector() == 0 then
  error("Could not activate Mono. Make sure Valheim is fully loaded.")
end

--------------------------------------------------
-- Find local Player
--------------------------------------------------

local playerClass = mono_findClass("", "Player")

if not playerClass or playerClass == 0 then
  error("Could not find Player class")
end

local playerFields = mono_class_enumFields(playerClass)
local localPlayerField = nil

for i = 1, #playerFields do
  if playerFields[i].name == "m_localPlayer"
     and playerFields[i].isStatic then
    localPlayerField = playerFields[i]
    break
  end
end

if not localPlayerField then
  error("Could not find Player.m_localPlayer")
end

local domains = mono_enumDomains()
local staticBase =
  mono_class_getStaticFieldAddress(domains[1], playerClass)

if not staticBase or staticBase == 0 then
  error("Could not resolve Player static fields")
end

local player =
  readPointer(staticBase + localPlayerField.offset)

if not player or player == 0 then
  error("Local player not found. Load into your world first.")
end

--------------------------------------------------
-- Find Character movement fields
--------------------------------------------------

local characterClass = mono_findClass("", "Character")

if not characterClass or characterClass == 0 then
  error("Could not find Character class")
end

local characterFields =
  mono_class_enumFields(characterClass)

local runOffset = nil
local swimOffset = nil

for i = 1, #characterFields do
  if characterFields[i].name == "m_runSpeed" then
    runOffset = characterFields[i].offset

  elseif characterFields[i].name == "m_swimSpeed" then
    swimOffset = characterFields[i].offset
  end
end

if not runOffset then
  error("Could not find Character.m_runSpeed")
end

if not swimOffset then
  error("Could not find Character.m_swimSpeed")
end

--------------------------------------------------
-- Save original speeds only once
--------------------------------------------------

local state = _G.ValheimMovementSpeedState

if not state
   or state.player ~= player
   or state.runOffset ~= runOffset
   or state.swimOffset ~= swimOffset then

  local baseRun = readFloat(player + runOffset)
  local baseSwim = readFloat(player + swimOffset)

  if baseRun == nil then
    error("Could not read original run speed")
  end

  if baseSwim == nil then
    error("Could not read original swim speed")
  end

  state = {
    player = player,
    runOffset = runOffset,
    swimOffset = swimOffset,
    baseRun = baseRun,
    baseSwim = baseSwim
  }

  _G.ValheimMovementSpeedState = state
end

--------------------------------------------------
-- Turn off other Movement Speed options
--------------------------------------------------

_G.ValheimMovementSpeedSwitching = true

local parent = memrec.Parent

if parent then
  for i = 0, parent.Count - 1 do
    local mr = parent.Child[i]

    if mr ~= memrec and mr.Active then
      mr.Active = false
    end
  end
end

--------------------------------------------------
-- Apply 3x
--------------------------------------------------

writeFloat(
  state.player + state.runOffset,
  state.baseRun * 3.0
)

writeFloat(
  state.player + state.swimOffset,
  state.baseSwim * 3.0
)

_G.ValheimMovementSpeedSwitching = false

{$asm}


[DISABLE]

{$lua}
if syntaxcheck then return end

if _G.ValheimMovementSpeedSwitching then
  return
end

local state = _G.ValheimMovementSpeedState

if state and state.player and state.player ~= 0 then
  writeFloat(
    state.player + state.runOffset,
    state.baseRun
  )

  writeFloat(
    state.player + state.swimOffset,
    state.baseSwim
  )
end

_G.ValheimMovementSpeedState = nil

{$asm}
</AssemblerScript>
        </CheatEntry>
        <CheatEntry>
          <ID>51</ID>
          <Description>"5x Runs Speed"</Description>
          <VariableType>Auto Assembler Script</VariableType>
          <AssemblerScript>[ENABLE]

{$lua}
if syntaxcheck then return end

if LaunchMonoDataCollector() == 0 then
  error("Could not activate Mono. Make sure Valheim is fully loaded.")
end

--------------------------------------------------
-- Find local Player
--------------------------------------------------

local playerClass = mono_findClass("", "Player")

if not playerClass or playerClass == 0 then
  error("Could not find Player class")
end

local playerFields = mono_class_enumFields(playerClass)
local localPlayerField = nil

for i = 1, #playerFields do
  if playerFields[i].name == "m_localPlayer"
     and playerFields[i].isStatic then
    localPlayerField = playerFields[i]
    break
  end
end

if not localPlayerField then
  error("Could not find Player.m_localPlayer")
end

local domains = mono_enumDomains()
local staticBase =
  mono_class_getStaticFieldAddress(domains[1], playerClass)

if not staticBase or staticBase == 0 then
  error("Could not resolve Player static fields")
end

local player =
  readPointer(staticBase + localPlayerField.offset)

if not player or player == 0 then
  error("Local player not found. Load into your world first.")
end

--------------------------------------------------
-- Find Character movement fields
--------------------------------------------------

local characterClass = mono_findClass("", "Character")

if not characterClass or characterClass == 0 then
  error("Could not find Character class")
end

local characterFields =
  mono_class_enumFields(characterClass)

local runOffset = nil
local swimOffset = nil

for i = 1, #characterFields do
  if characterFields[i].name == "m_runSpeed" then
    runOffset = characterFields[i].offset

  elseif characterFields[i].name == "m_swimSpeed" then
    swimOffset = characterFields[i].offset
  end
end

if not runOffset then
  error("Could not find Character.m_runSpeed")
end

if not swimOffset then
  error("Could not find Character.m_swimSpeed")
end

--------------------------------------------------
-- Save original speeds only once
--------------------------------------------------

local state = _G.ValheimMovementSpeedState

if not state
   or state.player ~= player
   or state.runOffset ~= runOffset
   or state.swimOffset ~= swimOffset then

  local baseRun = readFloat(player + runOffset)
  local baseSwim = readFloat(player + swimOffset)

  if baseRun == nil then
    error("Could not read original run speed")
  end

  if baseSwim == nil then
    error("Could not read original swim speed")
  end

  state = {
    player = player,
    runOffset = runOffset,
    swimOffset = swimOffset,
    baseRun = baseRun,
    baseSwim = baseSwim
  }

  _G.ValheimMovementSpeedState = state
end

--------------------------------------------------
-- Turn off other Movement Speed options
--------------------------------------------------

_G.ValheimMovementSpeedSwitching = true

local parent = memrec.Parent

if parent then
  for i = 0, parent.Count - 1 do
    local mr = parent.Child[i]

    if mr ~= memrec and mr.Active then
      mr.Active = false
    end
  end
end

--------------------------------------------------
-- Apply 5x
--------------------------------------------------

writeFloat(
  state.player + state.runOffset,
  state.baseRun * 40.0
)

writeFloat(
  state.player + state.swimOffset,
  state.baseSwim * 40.0
)

_G.ValheimMovementSpeedSwitching = false

{$asm}


[DISABLE]

{$lua}
if syntaxcheck then return end

if _G.ValheimMovementSpeedSwitching then
  return
end

local state = _G.ValheimMovementSpeedState

if state and state.player and state.player ~= 0 then
  writeFloat(
    state.player + state.runOffset,
    state.baseRun
  )

  writeFloat(
    state.player + state.swimOffset,
    state.baseSwim
  )
end

_G.ValheimMovementSpeedState = nil

{$asm}
</AssemblerScript>
        </CheatEntry>
      </CheatEntries>
    </CheatEntry>
    <CheatEntry>
      <ID>40</ID>
      <Description>"Extra Damage"</Description>
      <VariableType>Auto Assembler Script</VariableType>
      <AssemblerScript>[ENABLE]

{$lua}
if syntaxcheck then return end

if LaunchMonoDataCollector() == 0 then
  error("Could not activate Mono. Make sure Valheim is fully loaded.")
end
{$asm}

define(MODDAMAGE,Attack:ModifyDamage)

// Original instructions from +16 through +26
assert(MODDAMAGE+16,F3 0F 11 55 E0 F3 0F 10 87 24 01 00 00 F3 0F 5A C0)

// Allocate anywhere - no nearby allocation required
alloc(damagemem,$1000)

label(normalDamage)
label(damageMultiplier)

damagemem:

  // Attack+90 = m_baseAI
  // AI attack -&gt; leave damage unchanged
  cmp qword ptr [rdi+90],00
  jne normalDamage

  // Player attack:
  // XMM2 contains damageFactor
  mulss xmm2,[damageMultiplier]

normalDamage:

  // Replay all instructions we replaced
  movss [rbp-20],xmm2
  movss xmm0,[rdi+00000124]
  cvtss2sd xmm0,xmm0

  // Continue original function
  jmp far MODDAMAGE+27


damageMultiplier:
  dd (float)10.0


MODDAMAGE+16:
  jmp far damagemem
  nop 3


[DISABLE]

define(MODDAMAGE,Attack:ModifyDamage)

MODDAMAGE+16:
  db F3 0F 11 55 E0
  db F3 0F 10 87 24 01 00 00
  db F3 0F 5A C0

dealloc(damagemem)
</AssemblerScript>
    </CheatEntry>
    <CheatEntry>
      <ID>23</ID>
      <Description>"Infinite Ammo"</Description>
      <VariableType>Auto Assembler Script</VariableType>
      <AssemblerScript>[ENABLE]

{$lua}
if syntaxcheck then return end

if LaunchMonoDataCollector() == 0 then
  error("Could not activate Mono. Make sure Valheim is fully loaded.")
end

{$asm}

define(USEAMMO,Attack:UseAmmo)

// Original:
// call r11
//
// r11 = Inventory:RemoveItem
assert(USEAMMO+298,41 FF D3)

// Prevent the ammo-removal call
USEAMMO+298:
  db 90 90 90


[DISABLE]

define(USEAMMO,Attack:UseAmmo)

USEAMMO+298:
  db 41 FF D3

</AssemblerScript>
    </CheatEntry>
    <CheatEntry>
      <ID>41</ID>
      <Description>"Durability"</Description>
      <Options moAlwaysHideChildren="1" moActivateChildrenAsWell="1" moDeactivateChildrenAsWell="1"/>
      <GroupHeader>1</GroupHeader>
      <CheatEntries>
        <CheatEntry>
          <ID>17</ID>
          <Description>"Melee Durability"</Description>
          <VariableType>Auto Assembler Script</VariableType>
          <AssemblerScript>[ENABLE]

{$lua}
if syntaxcheck then return end

if LaunchMonoDataCollector() == 0 then
  error("Could not activate Mono. Make sure Valheim is fully loaded.")
end

{$asm}

define(MELEEDURABILITY,Attack:DoMeleeAttack)

assert(MELEEDURABILITY+5B32,F3 0F 11 68 3C)

// Original:
// movss [rax+3C],xmm5
//
// Prevent melee weapon/tool durability loss
MELEEDURABILITY+5B32:
  db 90 90 90 90 90


[DISABLE]

define(MELEEDURABILITY,Attack:DoMeleeAttack)

MELEEDURABILITY+5B32:
  db F3 0F 11 68 3C

</AssemblerScript>
        </CheatEntry>
        <CheatEntry>
          <ID>20</ID>
          <Description>"Ranged Durability"</Description>
          <VariableType>Auto Assembler Script</VariableType>
          <AssemblerScript>[ENABLE]

{$lua}
if syntaxcheck then return end

if LaunchMonoDataCollector() == 0 then
  error("Could not activate Mono. Make sure Valheim is fully loaded.")
end

{$asm}

define(PROJECTILEDURABILITY,Attack:ProjectileAttackTriggered)

assert(PROJECTILEDURABILITY+418,F3 0F 11 68 3C)

// Original:
// movss [rax+3C],xmm5
//
// Prevent bow / projectile weapon durability loss
PROJECTILEDURABILITY+418:
  db 90 90 90 90 90


[DISABLE]

define(PROJECTILEDURABILITY,Attack:ProjectileAttackTriggered)

PROJECTILEDURABILITY+418:
  db F3 0F 11 68 3C
</AssemblerScript>
        </CheatEntry>
        <CheatEntry>
          <ID>29</ID>
          <Description>"Armour Durability"</Description>
          <VariableType>Auto Assembler Script</VariableType>
          <AssemblerScript>[ENABLE]

{$lua}
if syntaxcheck then return end

if LaunchMonoDataCollector() == 0 then
  error("Could not activate Mono. Make sure Valheim is fully loaded.")
end

{$asm}

define(ARMORDURABILITY,Player:DamageArmorDurability)

assert(ARMORDURABILITY+3B4,F3 41 0F 11 6F 3C)

// Original:
// movss [r15+3C],xmm5
//
// Prevent armour durability loss
ARMORDURABILITY+3B4:
  db 90 90 90 90 90 90


[DISABLE]

define(ARMORDURABILITY,Player:DamageArmorDurability)

ARMORDURABILITY+3B4:
  db F3 41 0F 11 6F 3C

</AssemblerScript>
        </CheatEntry>
        <CheatEntry>
          <ID>46</ID>
          <Description>"Hammer Durability"</Description>
          <VariableType>Auto Assembler Script</VariableType>
          <AssemblerScript>[ENABLE]

{$lua}
if syntaxcheck then return end

if LaunchMonoDataCollector() == 0 then
  error("Could not activate Mono. Make sure Valheim is fully loaded.")
end

local p = getAddressSafe("Player:UpdatePlacement")

if not p then
  error("Could not find Player:UpdatePlacement")
end

-- Follow the DMD jump
local firstByte = readBytes(p,1,false)

if firstByte ~= 0xE9 then
  error("Player:UpdatePlacement is not using the expected DMD jump")
end

local rel = readInteger(p+1)

if rel &gt;= 0x80000000 then
  rel = rel - 0x100000000
end

local dmd = p + 5 + rel
local addr = dmd + 0xF55

-- Original:
-- F3 41 0F 11 6F 3C
-- movss [r15+3C],xmm5

local original = {
  0xF3,0x41,0x0F,0x11,0x6F,0x3C
}

local current = readBytes(addr,6,true)

if not current then
  error("Could not read hammer durability instruction")
end

for i=1,6 do
  if current[i] ~= original[i] then
    error("Hammer Durability: expected original bytes were not found")
  end
end

_G.ValheimHammerDurabilityPatch = addr

-- Prevent durability from being written
writeBytes(addr,
  0x90,0x90,0x90,0x90,0x90,0x90
)

{$asm}


[DISABLE]

{$lua}
if syntaxcheck then return end

local addr = _G.ValheimHammerDurabilityPatch

if addr then
  writeBytes(addr,
    0xF3,0x41,0x0F,0x11,0x6F,0x3C
  )
end

_G.ValheimHammerDurabilityPatch = nil

{$asm}

</AssemblerScript>
        </CheatEntry>
        <CheatEntry>
          <ID>55</ID>
          <Description>"Shield"</Description>
          <VariableType>Auto Assembler Script</VariableType>
          <AssemblerScript>[ENABLE]

{$lua}
if syntaxcheck then return end

if LaunchMonoDataCollector() == 0 then
  error("Could not activate Mono. Make sure Valheim is fully loaded.")
end

{$asm}

define(SHIELDDURABILITY,Humanoid:BlockAttack)

assert(SHIELDDURABILITY+CE6,F3 41 0F 11 6E 3C)

// Original:
// movss [r14+3C],xmm5
//
// Prevent shield durability loss when blocking

SHIELDDURABILITY+CE6:
  db 90 90 90 90 90 90


[DISABLE]

define(SHIELDDURABILITY,Humanoid:BlockAttack)

SHIELDDURABILITY+CE6:
  db F3 41 0F 11 6E 3C

</AssemblerScript>
        </CheatEntry>
      </CheatEntries>
    </CheatEntry>
    <CheatEntry>
      <ID>31</ID>
      <Description>"Skill Multiplier"</Description>
      <Options moHideChildren="1"/>
      <GroupHeader>1</GroupHeader>
      <CheatEntries>
        <CheatEntry>
          <ID>30</ID>
          <Description>"Skill Multiplier x5"</Description>
          <VariableType>Auto Assembler Script</VariableType>
          <AssemblerScript>[ENABLE]

{$lua}
if syntaxcheck then return end

-- Only allow one Skill Multiplier child to be active
local parent = memrec.Parent

if parent then
  for i = 0, parent.Count - 1 do
    local mr = parent.Child[i]

    if mr ~= memrec and mr.Active then
      mr.Active = false
    end
  end
end

if LaunchMonoDataCollector() == 0 then
  error("Could not activate Mono. Make sure Valheim is fully loaded.")
end
{$asm}

define(RAISESKILL,Skills:RaiseSkill)

assert(RAISESKILL+1D,F3 0F 11 55 C8)

alloc(skillmem,$1000,RAISESKILL+1D)

label(return)
label(xpMultiplier)

skillmem:

  // XMM2 = normal skill XP factor
  mulss xmm2,[xpMultiplier]

  // Original instruction
  movss [rbp-38],xmm2

  jmp return

xpMultiplier:
  dd (float)5.0


RAISESKILL+1D:
  jmp skillmem

return:


[DISABLE]

define(RAISESKILL,Skills:RaiseSkill)

RAISESKILL+1D:
  db F3 0F 11 55 C8

dealloc(skillmem)

</AssemblerScript>
        </CheatEntry>
        <CheatEntry>
          <ID>32</ID>
          <Description>"Skill Multiplier x10"</Description>
          <VariableType>Auto Assembler Script</VariableType>
          <AssemblerScript>[ENABLE]

{$lua}
if syntaxcheck then return end

-- Only allow one Skill Multiplier child to be active
local parent = memrec.Parent

if parent then
  for i = 0, parent.Count - 1 do
    local mr = parent.Child[i]

    if mr ~= memrec and mr.Active then
      mr.Active = false
    end
  end
end

if LaunchMonoDataCollector() == 0 then
  error("Could not activate Mono. Make sure Valheim is fully loaded.")
end
{$asm}

define(RAISESKILL,Skills:RaiseSkill)

assert(RAISESKILL+1D,F3 0F 11 55 C8)

alloc(skillmem,$1000,RAISESKILL+1D)

label(return)
label(xpMultiplier)

skillmem:

  // XMM2 = normal skill XP factor
  mulss xmm2,[xpMultiplier]

  // Original instruction
  movss [rbp-38],xmm2

  jmp return

xpMultiplier:
  dd (float)10.0


RAISESKILL+1D:
  jmp skillmem

return:


[DISABLE]

define(RAISESKILL,Skills:RaiseSkill)

RAISESKILL+1D:
  db F3 0F 11 55 C8

dealloc(skillmem)

</AssemblerScript>
        </CheatEntry>
        <CheatEntry>
          <ID>33</ID>
          <Description>"Skill Multiplier x25"</Description>
          <VariableType>Auto Assembler Script</VariableType>
          <AssemblerScript>[ENABLE]

{$lua}
if syntaxcheck then return end

-- Only allow one Skill Multiplier child to be active
local parent = memrec.Parent

if parent then
  for i = 0, parent.Count - 1 do
    local mr = parent.Child[i]

    if mr ~= memrec and mr.Active then
      mr.Active = false
    end
  end
end

if LaunchMonoDataCollector() == 0 then
  error("Could not activate Mono. Make sure Valheim is fully loaded.")
end
{$asm}

define(RAISESKILL,Skills:RaiseSkill)

assert(RAISESKILL+1D,F3 0F 11 55 C8)

alloc(skillmem,$1000,RAISESKILL+1D)

label(return)
label(xpMultiplier)

skillmem:

  // XMM2 = normal skill XP factor
  mulss xmm2,[xpMultiplier]

  // Original instruction
  movss [rbp-38],xmm2

  jmp return

xpMultiplier:
  dd (float)25.0


RAISESKILL+1D:
  jmp skillmem

return:


[DISABLE]

define(RAISESKILL,Skills:RaiseSkill)

RAISESKILL+1D:
  db F3 0F 11 55 C8

dealloc(skillmem)

</AssemblerScript>
        </CheatEntry>
        <CheatEntry>
          <ID>34</ID>
          <Description>"Skill Multiplier x50"</Description>
          <VariableType>Auto Assembler Script</VariableType>
          <AssemblerScript>[ENABLE]

{$lua}
if syntaxcheck then return end

-- Only allow one Skill Multiplier child to be active
local parent = memrec.Parent

if parent then
  for i = 0, parent.Count - 1 do
    local mr = parent.Child[i]

    if mr ~= memrec and mr.Active then
      mr.Active = false
    end
  end
end

if LaunchMonoDataCollector() == 0 then
  error("Could not activate Mono. Make sure Valheim is fully loaded.")
end
{$asm}

define(RAISESKILL,Skills:RaiseSkill)

assert(RAISESKILL+1D,F3 0F 11 55 C8)

alloc(skillmem,$1000,RAISESKILL+1D)

label(return)
label(xpMultiplier)

skillmem:

  // XMM2 = normal skill XP factor
  mulss xmm2,[xpMultiplier]

  // Original instruction
  movss [rbp-38],xmm2

  jmp return

xpMultiplier:
  dd (float)50.0


RAISESKILL+1D:
  jmp skillmem

return:


[DISABLE]

define(RAISESKILL,Skills:RaiseSkill)

RAISESKILL+1D:
  db F3 0F 11 55 C8

dealloc(skillmem)

</AssemblerScript>
        </CheatEntry>
        <CheatEntry>
          <ID>35</ID>
          <Description>"Skill Multiplier x100"</Description>
          <VariableType>Auto Assembler Script</VariableType>
          <AssemblerScript>[ENABLE]

{$lua}
if syntaxcheck then return end

-- Only allow one Skill Multiplier child to be active
local parent = memrec.Parent

if parent then
  for i = 0, parent.Count - 1 do
    local mr = parent.Child[i]

    if mr ~= memrec and mr.Active then
      mr.Active = false
    end
  end
end

if LaunchMonoDataCollector() == 0 then
  error("Could not activate Mono. Make sure Valheim is fully loaded.")
end
{$asm}

define(RAISESKILL,Skills:RaiseSkill)

assert(RAISESKILL+1D,F3 0F 11 55 C8)

alloc(skillmem,$1000,RAISESKILL+1D)

label(return)
label(xpMultiplier)

skillmem:

  // XMM2 = normal skill XP factor
  mulss xmm2,[xpMultiplier]

  // Original instruction
  movss [rbp-38],xmm2

  jmp return

xpMultiplier:
  dd (float)1000.0


RAISESKILL+1D:
  jmp skillmem

return:


[DISABLE]

define(RAISESKILL,Skills:RaiseSkill)

RAISESKILL+1D:
  db F3 0F 11 55 C8

dealloc(skillmem)

</AssemblerScript>
        </CheatEntry>
      </CheatEntries>
    </CheatEntry>
    <CheatEntry>
      <ID>39</ID>
      <Description>"Free Build (No Resources)"</Description>
      <VariableType>Auto Assembler Script</VariableType>
      <AssemblerScript>[ENABLE]

{$lua}
if syntaxcheck then return end

------------------------------------------------------------
-- VALHEIM FREE BUILDING
--
-- Patches:
--
--   ALL Player:HaveRequirements overloads -&gt; TRUE
--   Player:HaveRequirementItems           -&gt; TRUE
--   Player:ConsumeResources               -&gt; RETURN
--
------------------------------------------------------------

if LaunchMonoDataCollector() == 0 then
  error(
    "Could not activate Mono. Make sure Valheim is fully loaded."
  )
end

------------------------------------------------------------
-- Don't allow accidental double-enable
------------------------------------------------------------

if _G.ValheimFreeBuild then
  error(
    "Free Building patch is already active"
  )
end

------------------------------------------------------------
-- Find Player class
------------------------------------------------------------

local playerClass =
  mono_findClass("", "Player")

if not playerClass or playerClass == 0 then
  error("Could not find Player class")
end

------------------------------------------------------------
-- Enumerate Player methods
------------------------------------------------------------

local methods =
  mono_class_enumMethods(playerClass)

if not methods then
  error("Could not enumerate Player methods")
end

------------------------------------------------------------
-- Patch storage
------------------------------------------------------------

local patches = {}

------------------------------------------------------------
-- Resolve exact Mono method
------------------------------------------------------------

local function getJitAddress(method)

  local compiled =
    mono_compile_method(method)

  if not compiled or compiled == 0 then
    return nil,nil
  end

  local ji =
    mono_getJitInfo(compiled)

  if not ji then
    return nil,nil
  end

  return ji.code_start,ji.code_size

end

------------------------------------------------------------
-- Save a patch
------------------------------------------------------------

local function savePatch(
  name,
  method,
  address,
  size,
  patchBytes
)

  local original =
    readBytes(
      address,
      #patchBytes,
      true
    )

  if not original then
    error(
      "Could not save original bytes for "..name
    )
  end

  ----------------------------------------------------------
  -- Safety:
  --
  -- Current methods should start:
  --
  -- 55
  -- 48 8B EC
  --
  -- push rbp
  -- mov rbp,rsp
  ----------------------------------------------------------

  if original[1] ~= 0x55 then
    error(
      name..
      ": unexpected method entry byte"
    )
  end

  table.insert(
    patches,
    {
      name = name,
      method = method,
      address = address,
      size = size,
      original = original,
      patch = patchBytes
    }
  )

end

------------------------------------------------------------
-- Find every relevant method
------------------------------------------------------------

local requirementCount = 0
local requirementItemsCount = 0
local consumeCount = 0

for _,m in ipairs(methods) do

  local name =
    m.name or ""

  local method =
    m.method

  if method and method ~= 0 then

    --------------------------------------------------------
    -- ALL HaveRequirements overloads
    --------------------------------------------------------

    if name == "HaveRequirements" then

      local addr,size =
        getJitAddress(method)

      if addr then

        requirementCount =
          requirementCount + 1

        print(string.format(
          "[Free Building] HaveRequirements #%d: %X size=%X",
          requirementCount,
          addr,
          size
        ))

        ----------------------------------------------------
        -- mov eax,1
        -- ret
        ----------------------------------------------------

        savePatch(
          "HaveRequirements #"..
          requirementCount,
          method,
          addr,
          size,
          {
            0xB8,
            0x01,0x00,0x00,0x00,
            0xC3
          }
        )

      end

    --------------------------------------------------------
    -- HaveRequirementItems
    --------------------------------------------------------

    elseif name == "HaveRequirementItems" then

      local addr,size =
        getJitAddress(method)

      if addr then

        requirementItemsCount =
          requirementItemsCount + 1

        print(string.format(
          "[Free Building] HaveRequirementItems #%d: %X size=%X",
          requirementItemsCount,
          addr,
          size
        ))

        savePatch(
          "HaveRequirementItems #"..
          requirementItemsCount,
          method,
          addr,
          size,
          {
            0xB8,
            0x01,0x00,0x00,0x00,
            0xC3
          }
        )

      end

    --------------------------------------------------------
    -- ConsumeResources
    --------------------------------------------------------

    elseif name == "ConsumeResources" then

      local addr,size =
        getJitAddress(method)

      if addr then

        consumeCount =
          consumeCount + 1

        print(string.format(
          "[Free Building] ConsumeResources #%d: %X size=%X",
          consumeCount,
          addr,
          size
        ))

        ----------------------------------------------------
        -- ret
        ----------------------------------------------------

        savePatch(
          "ConsumeResources #"..
          consumeCount,
          method,
          addr,
          size,
          {
            0xC3
          }
        )

      end

    end

  end

end

------------------------------------------------------------
-- Sanity checks BEFORE changing anything
------------------------------------------------------------

if requirementCount == 0 then
  error(
    "No HaveRequirements methods found"
  )
end

if requirementItemsCount == 0 then
  error(
    "No HaveRequirementItems methods found"
  )
end

if consumeCount == 0 then
  error(
    "No ConsumeResources methods found"
  )
end

print("")
print(string.format(
  "[Free Building] Found %d HaveRequirements overload(s)",
  requirementCount
))

print(string.format(
  "[Free Building] Found %d HaveRequirementItems method(s)",
  requirementItemsCount
))

print(string.format(
  "[Free Building] Found %d ConsumeResources method(s)",
  consumeCount
))

------------------------------------------------------------
-- Apply patches
------------------------------------------------------------

for _,p in ipairs(patches) do

  writeBytes(
    p.address,
    table.unpack(p.patch)
  )

  print(string.format(
    "[Free Building] Patched %s at %X",
    p.name,
    p.address
  ))

end

------------------------------------------------------------
-- Store everything for DISABLE
------------------------------------------------------------

_G.ValheimFreeBuild =
  patches

print("")
print(
  "[Free Building] SUCCESS"
)

print(
  "[Free Building] All requirement checks forced TRUE"
)

print(
  "[Free Building] Resource consumption disabled"
)

{$asm}


[DISABLE]

{$lua}
if syntaxcheck then return end

local patches =
  _G.ValheimFreeBuild

if patches then

  ----------------------------------------------------------
  -- Restore every patched method
  ----------------------------------------------------------

  for _,p in ipairs(patches) do

    if p.address and
       p.original then

      writeBytes(
        p.address,
        table.unpack(p.original)
      )

      print(string.format(
        "[Free Building] Restored %s at %X",
        p.name,
        p.address
      ))

    end

  end

end

_G.ValheimFreeBuild = nil

print(
  "[Free Building] Original methods restored"
)

{$asm}
</AssemblerScript>
    </CheatEntry>
    <CheatEntry>
      <ID>56</ID>
      <Description>"Guaranteed Forge of Potential"</Description>
      <VariableType>Auto Assembler Script</VariableType>
      <AssemblerScript>[ENABLE]

{$lua}
if syntaxcheck then return end

if LaunchMonoDataCollector() == 0 then
  error("Could not activate Mono")
end

if _G.ForgeRollPatch then
  error("Forge roll patch is already active")
end

local method = mono_findMethod("", "InventoryGui", "DoCrafting")
if not method or method == 0 then
  error("InventoryGui:DoCrafting not found")
end

local compiled = mono_compile_method(method)
local ji = mono_getJitInfo(compiled)
if not ji then error("JIT information unavailable") end

local pattern = {
  0xF3,0x0F,0x11,0xAD,0x2C,0xFD,0xFF,0xFF
}

local data = readBytes(ji.code_start,ji.code_size,true)
if not data then error("Could not read method") end

local matches = {}

for i=1,#data-#pattern+1 do
  local ok=true
  for j=1,#pattern do
    if data[i+j-1]~=pattern[j] then
      ok=false
      break
    end
  end
  if ok then
    table.insert(matches,ji.code_start+i-1)
  end
end

if #matches ~= 1 then
  error("Expected one roll-storage instruction; found "..#matches)
end

local addr = matches[1]

-- xorps xmm5,xmm5
-- movss [rbp-000002D4],xmm5
-- Requires 11 bytes, so patch the preceding conversion
-- and the store as one contiguous block.

local start = addr-5

local original = readBytes(start,13,true)
if not original then error("Could not save original bytes") end

local expected = {
  0xF2,0x0F,0x5A,0xE8,
  0xF3,0x0F,0x11,0xAD,0x2C,0xFD,0xFF,0xFF
}

-- Verify the exact conversion/store sequence.
-- The conversion starts 4 bytes before the store.
start = addr-4
original = readBytes(start,12,true)

for i=1,#expected do
  if original[i]~=expected[i] then
    error("Unexpected conversion/store bytes; no patch applied")
  end
end

local replacement = {
  0x0F,0x57,0xED, -- xorps xmm5,xmm5
  0x90,           -- nop
  0xF3,0x0F,0x11,0xAD,0x2C,0xFD,0xFF,0xFF
}

local unpackBytes=table.unpack or unpack

if not writeBytes(start,unpackBytes(replacement)) then
  error("Failed to patch roll")
end

_G.ForgeRollPatch={
  address=start,
  original=original
}

print(string.format(
  "[Forge] Roll forced to zero at %X",
  start
))

{$asm}

[DISABLE]

{$lua}
if syntaxcheck then return end

local patch=_G.ForgeRollPatch

if patch then
  local unpackBytes=table.unpack or unpack
  writeBytes(patch.address,unpackBytes(patch.original))
  _G.ForgeRollPatch=nil
  print("[Forge] Original roll restored")
end

{$asm}
</AssemblerScript>
    </CheatEntry>
    <CheatEntry>
      <ID>57</ID>
      <Description>"Auto Assemble script"</Description>
      <VariableType>Auto Assembler Script</VariableType>
      <AssemblerScript>[ENABLE]

{$lua}
if syntaxcheck then return "" end

if LaunchMonoDataCollector() == 0 then
  error("Mono initialization failed")
end

local function resolve(className, methodName)
  local method = mono_findMethod("", className, methodName)
  assert(method and method ~= 0, methodName .. " not found")

  local compiled = mono_compile_method(method)
  local ji = mono_getJitInfo(compiled)
  assert(ji, "JIT information unavailable: " .. methodName)

  return ji.code_start, ji.code_size
end

local consumed, size = resolve("Tameable", "OnConsumedItem")
local tame = resolve("Tameable", "Tame")

assert(size &gt;= 0x1E5, "Unexpected OnConsumedItem size")

local hook = consumed + 0x1DB

local expected = {
  0x48,0x8B,0x75,0xF8,
  0x48,0x8D,0x65,0x00
}

local actual = readBytes(hook, 8, true)
assert(actual, "Cannot read hook bytes")

for i = 1, 8 do
  assert(
    actual[i] == expected[i],
    string.format("Unexpected hook byte at position %d", i)
  )
end

print(string.format(
  "Instant Taming | Hook: %X | Tame: %X",
  hook, tame
))

return string.format([[
alloc(instantTameCode,512,%X)
label(instantTameReturn)

instantTameCode:
  // Preserve nonvolatile RBX and original stack.
  push rbx
  mov rbx,rsp

  // Align stack for Windows x64 calling convention.
  and rsp,FFFFFFFFFFFFFFF0
  sub rsp,20

  // Call Tameable:Tame(this).
  // RSI contains the current creature instance.
  mov rcx,rsi
  mov rax,%X
  call rax

  // Restore original stack.
  mov rsp,rbx
  pop rbx

  // Original instructions.
  mov rsi,[rbp-08]
  lea rsp,[rbp+00]

  jmp instantTameReturn

%X:
  jmp instantTameCode
  nop 3

instantTameReturn:

]], hook, tame, hook)

{$asm}

[DISABLE]

{$lua}
if syntaxcheck then return "" end

LaunchMonoDataCollector()

local method = mono_findMethod("", "Tameable", "OnConsumedItem")
assert(method and method ~= 0, "OnConsumedItem not found")

local compiled = mono_compile_method(method)
local ji = mono_getJitInfo(compiled)
assert(ji, "JIT information unavailable")

local hook = ji.code_start + 0x1DB

return string.format([[
%X:
  db 48 8B 75 F8 48 8D 65 00

dealloc(instantTameCode)
]], hook)

{$asm}
</AssemblerScript>
    </CheatEntry>
  </CheatEntries>
  <UserdefinedSymbols>
    <SymbolEntry>
      <Name>CarryWeightHook</Name>
      <Address>1E90A1F198B</Address>
    </SymbolEntry>
  </UserdefinedSymbols>
</CheatTable>
