<?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>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>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)

assert(USESTAMINA+4C,F3 0F 11 AE 88 09 00 00)

// Original:
// movss [rsi+00000988],xmm5
//
// Prevent reduced stamina from being stored.
USESTAMINA+4C:
  db 90 90 90 90 90 90 90 90

[DISABLE]

define(USESTAMINA,Player:RPC_UseStamina)

USESTAMINA+4C:
  db F3 0F 11 AE 88 09 00 00
</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>
      </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)100.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

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

-- Player:UpdatePlacement has been redirected by Harmony/DMD.
-- First byte should be E9 = relative JMP.
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

-- Building resource-consumption call discovered in our trace
local callsite = dmd + 0xDC0

local b1,b2,b3 = readBytes(callsite,3,false)

if b1 ~= 0x41 or b2 ~= 0xFF or b3 ~= 0xD3 then
  error("Free Building: expected Player:ConsumeResources call was not found")
end

-- Remember this session's address so DISABLE can restore it
_G.ValheimFreeBuildCall = callsite

-- Original: 41 FF D3 = call r11
-- Replace with 3 NOPs
writeBytes(callsite,0x90,0x90,0x90)

{$asm}


[DISABLE]

{$lua}
if syntaxcheck then return end

local callsite = _G.ValheimFreeBuildCall

if callsite then
  local b1,b2,b3 = readBytes(callsite,3,false)

  -- Only restore it if our NOP patch is still there
  if b1 == 0x90 and b2 == 0x90 and b3 == 0x90 then
    writeBytes(callsite,0x41,0xFF,0xD3)
  end
end

_G.ValheimFreeBuildCall = nil

{$asm}
</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("Could not activate Mono. Make sure Valheim is fully loaded.")
end

-- Find the normal Mono method
local p = getAddressSafe("Player:GetMaxCarryWeight")

if not p then
  error("Could not find Player:GetMaxCarryWeight")
end

-- In your game this method begins with:
-- E9 xx xx xx xx  = jump to the DMD/modded version
local firstByte = readBytes(p,1,false)

if firstByte ~= 0xE9 then
  error("GetMaxCarryWeight is not using the expected DMD jump")
end

-- Follow the relative E9 jump
local rel = readInteger(p+1)

if rel &gt;= 0x80000000 then
  rel = rel - 0x100000000
end

local dmd = p + 5 + rel

-- We confirmed the final return value starts at DMD + CB
local addr = dmd + 0xCB

local original = {
  0xF3,0x0F,0x10,0x45,0xF0,
  0xF3,0x0F,0x5A,0xC0,
  0xF2,0x0F,0x5A,0xC0
}

local current = readBytes(addr,13,true)

if not current then
  error("Could not read the carry-weight return code")
end

for i=1,13 do
  if current[i] ~= original[i] then
    error("Carry Weight: expected original bytes were not found")
  end
end

-- Save this session's address for DISABLE
_G.ValheimCarryWeightPatch = addr

-- 1000.0 float = 447A0000
--
-- mov eax,447A0000
-- movd xmm0,eax
-- nop x4
writeBytes(addr,
  0xB8,0x00,0x00,0x7A,0x44,
  0x66,0x0F,0x6E,0xC0,
  0x90,0x90,0x90,0x90
)

{$asm}


[DISABLE]

{$lua}
if syntaxcheck then return end

local addr = _G.ValheimCarryWeightPatch

if addr then
  writeBytes(addr,
    0xF3,0x0F,0x10,0x45,0xF0,
    0xF3,0x0F,0x5A,0xC0,
    0xF2,0x0F,0x5A,0xC0
  )
end

_G.ValheimCarryWeightPatch = nil

{$asm}
</AssemblerScript>
    </CheatEntry>
  </CheatEntries>
  <UserdefinedSymbols/>
</CheatTable>
