<?xml version="1.0" encoding="utf-8"?>
<CheatTable UsesMono="1" CheatEngineTableVersion="52">
  <CheatEntries>
    <CheatEntry>
      <ID>0</ID>
      <Description>"SiNiSistar 2 cheats"</Description>
      <GroupHeader>1</GroupHeader>
      <CheatEntries>
        <CheatEntry>
          <ID>1</ID>
          <Description>"Capture PlayerStatusManager (enable first)"</Description>
          <Options moHideChildren="1"/>
          <VariableType>Auto Assembler Script</VariableType>
          <AssemblerScript>[ENABLE]
alloc(newmem,2048,GameAssembly.dll+1A76570)
label(return)
label(psmInstance)
registersymbol(psmInstance)

newmem:
  mov [psmInstance],rcx
  push rbx
  sub rsp,20
  jmp return

psmInstance:
  dq 0

GameAssembly.dll+1A76570:
  jmp newmem
  nop
return:

[DISABLE]
GameAssembly.dll+1A76570:
  db 40 53 48 83 EC 20

unregistersymbol(psmInstance)
dealloc(newmem)
</AssemblerScript>
          <CheatEntries>
            <CheatEntry>
              <ID>6</ID>
              <Description>"Godmode (HP cannot decrease)"</Description>
              <VariableType>Auto Assembler Script</VariableType>
              <AssemblerScript>[ENABLE]
{$lua}
if syntaxcheck then return end
godTimer = createTimer(nil)
godTimer.Interval = 300
godTimer.OnTimer = function(t)
  local inst = readQword('psmInstance')
  if inst == nil or inst == 0 then return end
  local obj = readQword(inst + 0x60)
  if obj ~= nil and obj ~= 0 then writeBytes(obj + 0x34, 1) end
end
{$asm}
[DISABLE]
{$lua}
if godTimer ~= nil then godTimer.destroy() godTimer = nil end
local inst = readQword('psmInstance')
if inst ~= nil and inst ~= 0 then
  local obj = readQword(inst + 0x60)
  if obj ~= nil and obj ~= 0 then writeBytes(obj + 0x34, 0) end
end
</AssemblerScript>
            </CheatEntry>
            <CheatEntry>
              <ID>7</ID>
              <Description>"Infinite MP (MP cannot decrease)"</Description>
              <VariableType>Auto Assembler Script</VariableType>
              <AssemblerScript>[ENABLE]
{$lua}
if syntaxcheck then return end
mpTimer = createTimer(nil)
mpTimer.Interval = 300
mpTimer.OnTimer = function(t)
  local inst = readQword('psmInstance')
  if inst == nil or inst == 0 then return end
  local obj = readQword(inst + 0x68)
  if obj ~= nil and obj ~= 0 then writeBytes(obj + 0x34, 1) end
end
{$asm}
[DISABLE]
{$lua}
if mpTimer ~= nil then mpTimer.destroy() mpTimer = nil end
local inst = readQword('psmInstance')
if inst ~= nil and inst ~= 0 then
  local obj = readQword(inst + 0x68)
  if obj ~= nil and obj ~= 0 then writeBytes(obj + 0x34, 0) end
end
</AssemblerScript>
            </CheatEntry>
            <CheatEntry>
              <ID>11</ID>
              <Description>"Relics (money)"</Description>
              <VariableType>4 Bytes</VariableType>
              <Address>psmInstance</Address>
              <Offsets>
                <Offset>10</Offset>
                <Offset>178</Offset>
              </Offsets>
            </CheatEntry>
            <CheatEntry>
              <ID>12</ID>
              <Description>"Attack Lv"</Description>
              <VariableType>4 Bytes</VariableType>
              <Address>psmInstance</Address>
              <Offsets>
                <Offset>10</Offset>
                <Offset>148</Offset>
              </Offsets>
            </CheatEntry>
            <CheatEntry>
              <ID>13</ID>
              <Description>"HP Lv"</Description>
              <VariableType>4 Bytes</VariableType>
              <Address>psmInstance</Address>
              <Offsets>
                <Offset>10</Offset>
                <Offset>158</Offset>
              </Offsets>
            </CheatEntry>
            <CheatEntry>
              <ID>14</ID>
              <Description>"MP Lv"</Description>
              <VariableType>4 Bytes</VariableType>
              <Address>psmInstance</Address>
              <Offsets>
                <Offset>10</Offset>
                <Offset>168</Offset>
              </Offsets>
            </CheatEntry>
            <CheatEntry>
              <ID>19</ID>
              <Description>"No Defilement, Parasite"</Description>
              <Options moHideChildren="1" moActivateChildrenAsWell="1" moDeactivateChildrenAsWell="1"/>
              <GroupHeader>1</GroupHeader>
              <CheatEntries>
                <CheatEntry>
                  <ID>4</ID>
                  <Description>"No Defilement + No Parasite (block gain, safe) [spare id slots abnBlockId3/4]"</Description>
                  <VariableType>Auto Assembler Script</VariableType>
                  <AssemblerScript>[ENABLE]
alloc(newmem,$100,GameAssembly.dll+1A57910)
label(return)
label(doblock)
label(orig)
label(abnBlockId1)
label(abnBlockId2)
label(abnBlockId3)
label(abnBlockId4)
label(abnBlockHits)
registersymbol(abnBlockId1)
registersymbol(abnBlockId2)
registersymbol(abnBlockId3)
registersymbol(abnBlockId4)
registersymbol(abnBlockHits)

newmem:
  test rdx,rdx
  je orig
  push rax
  mov eax,[rdx+18]
  cmp eax,[abnBlockId1]
  je doblock
  cmp eax,[abnBlockId2]
  je doblock
  cmp eax,[abnBlockId3]
  je doblock
  cmp eax,[abnBlockId4]
  je doblock
  pop rax
orig:
  push rbx
  push rbp
  push r12
  jmp return

doblock:
  pop rax
  inc dword ptr [abnBlockHits]
  ret

abnBlockId1:
  dd 39393433
abnBlockId2:
  dd 61313133
abnBlockId3:
  dd 0
abnBlockId4:
  dd 0
abnBlockHits:
  dd 0

GameAssembly.dll+1A57910:
  jmp newmem
return:

[DISABLE]
GameAssembly.dll+1A57910:
  db 40 53 55 41 54

unregistersymbol(abnBlockId1)
unregistersymbol(abnBlockId2)
unregistersymbol(abnBlockId3)
unregistersymbol(abnBlockId4)
unregistersymbol(abnBlockHits)
dealloc(newmem)
</AssemblerScript>
                </CheatEntry>
                <CheatEntry>
                  <ID>18</ID>
                  <Description>"Fix: skip level-0 statuses in UpdateGachaRate (crash guard)"</Description>
                  <VariableType>Auto Assembler Script</VariableType>
                  <AssemblerScript>[ENABLE]
GameAssembly.dll+1A59E35:
  db 0F 84 B5 FF FF FF
GameAssembly.dll+1A59E65:
  db 74 89

[DISABLE]
GameAssembly.dll+1A59E35:
  db 0F 84 97 00 00 00
GameAssembly.dll+1A59E65:
  db 74 75
</AssemblerScript>
                </CheatEntry>
              </CheatEntries>
            </CheatEntry>
          </CheatEntries>
        </CheatEntry>
        <CheatEntry>
          <ID>30</ID>
          <Description>"Grabbed = Death Portrait (show enemy death picture while grabbed)"</Description>
          <VariableType>Auto Assembler Script</VariableType>
          <AssemblerScript>[ENABLE]
alloc(gdpRefresh,$200,GameAssembly.dll+1A76576)
alloc(gdpCtl,$40)
alloc(gdpCap,$100,GameAssembly.dll+18F8570)
registersymbol(gdpCtl)
label(gdpOrig)
label(gdpSkip)

gdpCtl:
  dq 0
  dq 0
  dq 0
  dq 0

gdpRefresh:
  cmp byte ptr [gdpCtl],1
  jne gdpOrig
  mov byte ptr [gdpCtl],0
  push rax
  push rcx
  push rdx
  push r8
  push r9
  push r10
  push r11
  sub rsp,28
  mov rcx,[gdpCtl+8]
  test rcx,rcx
  je gdpSkip
  cmp qword ptr [gdpCtl+10],0
  je gdpSkip
  call qword ptr [gdpCtl+10]
gdpSkip:
  add rsp,28
  pop r11
  pop r10
  pop r9
  pop r8
  pop rdx
  pop rcx
  pop rax
gdpOrig:
  cmp byte ptr [GameAssembly.dll+3154C70],00
  jmp GameAssembly.dll+1A7657D

gdpCap:
  mov [gdpCtl+18],rcx
  mov [rsp+08],rbx
  jmp GameAssembly.dll+18F8575

GameAssembly.dll+1A76576:
  jmp gdpRefresh
  nop 2

GameAssembly.dll+18F8570:
  jmp gdpCap

{$lua}
if syntaxcheck then return end
-- Grabbed=Death-Portrait watcher v5
-- v5: scan filter keys on the base-layer sprite name prefix "dead" instead
--     of the exact event label "GameOver" — later areas use variant labels
--     (GameOver_Broken2 demihuman, GameOver_Spear villager, Down2NeckGameOver
--     woman, GameOver_Scythe priest, HoldEndDown slug, RedFlash tree boss...)
--     that the old filter silently discarded.
-- v4: defer gdpCtl resolution to the first timer tick. Inside a table AA
--     script's {$lua} block the script's own registersymbol is NOT yet
--     visible and getAddress returns 0 without error, so v3 armed address
--     0 -&gt; forced refreshes + hook capture silently dead in any fresh CE
--     session enabled purely from the table.
-- v2: instant pair discovery via UpdatePortrait capture hook (gdpCtl+0x18),
--     CPP cache pre-warm on new portrait, retry-until-applied grab handling.
-- v3: concatenation fallback in the matcher (class FlyBug = words fly+bug,
--     but sprite token is the single word "flybug"; 3-char words can never
--     fuzzy-match, so compare the joined name too when per-word score is 0).
if _G.GrabDeathPortrait and _G.GrabDeathPortrait.timer then _G.GrabDeathPortrait.timer.destroy() end
local S = {}
_G.GrabDeathPortrait = S
if monopipe == nil then pcall(LaunchMonoDataCollector) end
if monopipe == nil then pcall(LaunchMonoDataCollector) end
if monopipe == nil then error("mono data collector unavailable") end
local wantK = { Portrait="SiNiSistar2.UI", Lelia="SiNiSistar2.Obj", Bind="SiNiSistar2.Obj", ChangePortraitParameter="SiNiSistar2.UI" }
local found = {}
for _, d in ipairs(mono_enumDomains() or {}) do
  for _, a in ipairs(mono_enumAssemblies(d) or {}) do
    local img = mono_getImageFromAssembly(a)
    if (mono_image_get_name(img) or "") == "SiNiSistar2.dll" then
      for _, c in ipairs(mono_image_enumClasses(img) or {}) do
        local nm = c.classname or ""
        if wantK[nm] ~= nil and (c.namespace or "") == wantK[nm] then found[nm] = c.class end
      end
    end
  end
end
if not (found.Portrait and found.Lelia and found.Bind and found.ChangePortraitParameter) then
  error("failed to resolve game classes")
end
S.kPortrait, S.kLelia, S.kBind, S.kCPP = found.Portrait, found.Lelia, found.Bind, found.ChangePortraitParameter
S.refCtl = nil -- resolved lazily by ensureArmed(): not visible to {$lua} during enable
S.cur, S.cppCache, S.bound, S.applied, S.rescanUsed = nil, nil, 0, false, false
S.lastPairScan, S.log, S.t0 = 0, {}, os.clock()
local function note(s)
  table.insert(S.log, string.format("[%7.1fs] %s", os.clock() - S.t0, s))
  if #S.log &gt; 200 then table.remove(S.log, 1) end
end
S.note = note
local function rq(a) local ok, v = pcall(readQword, a); return ok and v or nil end
local function isObj(o, k) return o and o &gt; 0x10000 and rq(o) == k end
local function alive(o) local c = rq(o + 0x10); return c and c ~= 0 end
local function qAOB(v)
  local b = {}
  for i = 1, 8 do table.insert(b, string.format("%02X", v % 256)); v = math.floor(v / 256) end
  return table.concat(b, " ")
end
local function csStr(so)
  if not so or so &lt; 0x10000 then return nil end
  local ok, len = pcall(readInteger, so + 0x10)
  if not ok or not len or len &lt;= 0 or len &gt; 100 then return nil end
  local ok2, s = pcall(readString, so + 0x14, len * 2, true)
  return ok2 and s or nil
end
local function klassName(o)
  local k = rq(o); if not k then return nil end
  local np = rq(k + 0x10); if not np or np &lt; 0x10000 then return nil end
  local ok, s = pcall(readString, np, 48)
  return ok and s and s:match("^[%w_]+") or nil
end
local function spriteNameOfCPP(cpp)
  local ps = rq(cpp + 0x30); if not ps or ps == 0 then return nil end
  local base = rq(ps + 0x10); if not base or base == 0 then return nil end
  local nat = rq(base + 0x10); if not nat or nat == 0 then return nil end
  local np = rq(nat + 0x30); if not np or np &lt; 0x10000 then return nil end
  local ok, s = pcall(readString, np, 48)
  return ok and s and s:match("^[%w_%-%.]+") or nil
end
local function ed1(a, b)
  if a == b then return true end
  local la, lb = #a, #b
  if math.abs(la - lb) &gt; 1 then return false end
  if la == lb then
    local diff = 0
    for i = 1, la do if a:sub(i,i) ~= b:sub(i,i) then diff = diff + 1 end end
    return diff &lt;= 1
  end
  if la &gt; lb then a, b, la, lb = b, a, lb, la end
  local i, j, skipped = 1, 1, false
  while i &lt;= la and j &lt;= lb do
    if a:sub(i,i) == b:sub(j,j) then i = i + 1; j = j + 1
    elseif not skipped then skipped = true; j = j + 1
    else return false end
  end
  return true
end
local function tokMatch(a, b)
  if a == b then return true end
  if #a &gt;= 4 and #b &gt;= 4 and (a:sub(1, #b) == b or b:sub(1, #a) == a) then return true end
  if #a &gt;= 4 and #b &gt;= 4 and ed1(a, b) then return true end
  return false
end
local function enemyWords(name)
  local w = {}
  for word in name:gmatch("%u%l+") do table.insert(w, word:lower()) end
  if #w == 0 then table.insert(w, name:lower()) end
  return w
end
local stopTok = { dead=true, base=true, front=true, back=true }
local function spriteTokens(sprite)
  local t = {}
  for tok in sprite:lower():gmatch("%w+") do
    if not stopTok[tok] then table.insert(t, tok) end
  end
  return t
end
S.scanPairs = function()
  local res = AOBScan(qAOB(S.kPortrait), "+W", 0, 8)
  local out = {}
  if res then
    for i = 0, res.Count - 1 do
      local p = tonumber(res[i], 16)
      local l = rq(p + 0xD0)
      if isObj(l, S.kLelia) and alive(p) and alive(l) then
        table.insert(out, {portrait = p, lelia = l})
      end
    end
    res.destroy()
  end
  return out
end
S.scanCPPs = function()
  local res = AOBScan(qAOB(S.kCPP), "+W", 0, 8)
  local out, seen = {}, {}
  if res then
    for i = 0, res.Count - 1 do
      local c = tonumber(res[i], 16)
      local sn = spriteNameOfCPP(c)
      if sn and sn:sub(1, 4) == "dead" and not seen[sn] then
        seen[sn] = true
        table.insert(out, {addr = c, sprite = sn})
      end
    end
    res.destroy()
  end
  return out
end
S.matchCPP = function(enemy, allowRescan)
  local ename = klassName(enemy) or ""
  local ew = enemyWords(ename)
  local function best()
    if not S.cppCache then return nil end
    for _, e in ipairs(S.cppCache) do
      if rq(e.addr) ~= S.kCPP then S.cppCache = nil; return nil end
    end
    local top, topScore, topUnmatched = nil, 0, 99
    for _, e in ipairs(S.cppCache) do
      local st = spriteTokens(e.sprite)
      local score, matchedT = 0, {}
      for _, w in ipairs(ew) do
        for ti, t in ipairs(st) do
          if tokMatch(w, t) then score = score + 1; matchedT[ti] = true; break end
        end
      end
      if score == 0 then
        -- concatenation fallbacks: FlyBug vs dead_base_flybug and the reverse
        local joined = table.concat(ew, "")
        for ti, t in ipairs(st) do
          if tokMatch(joined, t) then score = #ew; matchedT[ti] = true; break end
        end
        if score == 0 and #st &gt; 1 then
          local sj = table.concat(st, "")
          for _, w in ipairs(ew) do
            if tokMatch(w, sj) then score = 1; for ti = 1, #st do matchedT[ti] = true end; break end
          end
        end
      end
      local unmatched = 0
      for ti = 1, #st do if not matchedT[ti] then unmatched = unmatched + 1 end end
      if score &gt; topScore or (score == topScore and score &gt; 0 and unmatched &lt; topUnmatched) then
        top, topScore, topUnmatched = e, score, unmatched
      end
    end
    if topScore &gt; 0 then return top end
    return nil
  end
  local hit = best()
  if not hit and allowRescan then
    S.rescanUsed = true
    S.cppCache = S.scanCPPs()
    note("cpp rescan: "..#S.cppCache)
    hit = best()
  end
  if hit then
    note(string.format("match [%s] -&gt; %s (%X)", ename, hit.sprite, hit.addr))
    return hit.addr
  end
  if allowRescan then note(string.format("NO MATCH for [%s](words:%s)", ename, table.concat(ew, ","))) end
  return nil
end
local function fireRefresh(portrait)
  writeQword(S.refCtl + 8, portrait)
  writeBytes(S.refCtl, 1)
end
local function ensureArmed()
  if S.refCtl and S.refCtl ~= 0 then return true end
  local ok, a = pcall(getAddress, "gdpCtl")
  if not ok or not a or a == 0 then return false end
  S.refCtl = a
  writeQword(a + 0x10, getAddress("GameAssembly.dll") + 0x18F8570)
  note(string.format("armed refCtl=%X", a))
  return true
end
local function validLelia(p)
  if not p or p &lt; 0x10000 then return nil end
  if rq(p) ~= S.kPortrait or not alive(p) then return nil end
  local l = rq(p + 0xD0)
  if not isObj(l, S.kLelia) or not alive(l) then return nil end
  return l
end
local function adopt(p, l, how)
  S.cur = {portrait = p, lelia = l}
  S.bound, S.applied, S.rescanUsed = 0, false, false
  note(string.format("adopted portrait %X (%s)", p, how))
  S.cppCache = S.scanCPPs()
  note("prewarm cpps="..#S.cppCache)
end
S.timer = createTimer(nil)
S.timer.Interval = 100
S.timer.OnTimer = function()
  if S.busy then return end
  S.busy = true
  local ok, err = pcall(function()
    if not ensureArmed() then return end
    -- validate current pair
    if S.cur then
      local l = validLelia(S.cur.portrait)
      if not l or l ~= S.cur.lelia then S.cur = nil; note("pair invalidated") end
    end
    -- adopt hook-captured portrait if new
    local cap = rq(S.refCtl + 0x18)
    if cap and cap &gt; 0x10000 and (not S.cur or S.cur.portrait ~= cap) then
      local l = validLelia(cap)
      if l then adopt(cap, l, "captured") end
    end
    -- cold-start fallback: AOB scan until the hook has captured something
    if not S.cur then
      if os.clock() - S.lastPairScan &gt; 5 then
        S.lastPairScan = os.clock()
        local prs = S.scanPairs()
        if #prs &gt; 0 then adopt(prs[1].portrait, prs[1].lelia, "aob fallback") end
      end
      if not S.cur then return end
    end
    -- grab state machine (level-triggered: retry until applied)
    local bind = rq(S.cur.lelia + 0x200)
    if not isObj(bind, S.kBind) then return end
    local rp = rq(bind + 0x10)
    local bound = 0
    if rp and rp &gt; 0x10000 then
      local ok2, b = pcall(readBytes, rp + 0x10, 1)
      if ok2 and b == 1 then bound = 1 end
    end
    if bound == 1 then
      if not S.applied then
        local enemy = rq(bind + 0x28)
        if enemy and enemy &gt; 0x10000 then
          local cpp = S.matchCPP(enemy, not S.rescanUsed)
          if cpp then
            writeQword(S.cur.portrait + 0xC8, cpp)
            fireRefresh(S.cur.portrait)
            S.applied = true
            note(string.format("APPLIED cpp %X to portrait %X", cpp, S.cur.portrait))
          end
        end
      end
    else
      if S.bound == 1 then
        writeQword(S.cur.portrait + 0xC8, 0)
        fireRefresh(S.cur.portrait)
        note("released -&gt; cleared param")
      end
      S.applied, S.rescanUsed = false, false
    end
    S.bound = bound
  end)
  if not ok then note("tick error: "..tostring(err)) end
  S.busy = false
end
S.timer.Enabled = true
note("watcher v5 started")
{$asm}

[DISABLE]
{$lua}
if syntaxcheck then return end
if _G.GrabDeathPortrait then
  if _G.GrabDeathPortrait.timer then _G.GrabDeathPortrait.timer.destroy() end
  _G.GrabDeathPortrait = nil
end
{$asm}
GameAssembly.dll+1A76576:
  db 80 3D F3 E6 6D 01 00
GameAssembly.dll+18F8570:
  db 48 89 5C 24 08

unregistersymbol(gdpCtl)
dealloc(gdpRefresh)
dealloc(gdpCtl)
dealloc(gdpCap)
</AssemblerScript>
        </CheatEntry>
        <CheatEntry>
          <ID>31</ID>
          <Description>"Portrait Look: Big Breasts"</Description>
          <VariableType>Auto Assembler Script</VariableType>
          <AssemblerScript>[ENABLE]
{$lua}
if syntaxcheck then return end
if not _G.SS2Abn or (_G.SS2Abn.version or 0) &lt; 3 then
  local OLD = _G.SS2Abn
  local E = {}
  _G.SS2Abn = E
  E.version = 3
  E.TYPES = { Breast = 926037814, Pregnant = 959721780, Blessing = 825765986 }
  E.OFF = { site = 0x1A76595, ret = 0x1A7659C, mgrGet = 0x1970460, psmGet = 0x1970BA0,
            tryget = 0x1815AC0, load = 0x1815610, add = 0x1A57FD0, remove = 0x1A590D0,
            addData = 0x1A57910 }
  E.SITE_ORIG = { 0x48, 0x8B, 0x0D, 0xCC, 0x72, 0x4D, 0x01 }
  -- v3: ownership set keyed by table-entry id; wanted looks derived fresh each
  -- tick and reconciled against checkbox state (no leakable refcounts)
  E.owners, E.log = {}, {}
  E.removedBlessing, E.hadBlessing, E.gateInstalled = false, nil, false
  E.landedKey, E.failStreak, E.busy, E.stuck = {}, 0, false, 0

  function E.wanted()
    local w = {}
    for _, list in pairs(E.owners) do
      for _, name in ipairs(list) do w[name] = true end
    end
    return w
  end

  function E.note(s)
    table.insert(E.log, os.date("%H:%M:%S ") .. s)
    if #E.log &gt; 120 then table.remove(E.log, 1) end
  end
  function E.status() return table.concat(E.log, "\n") end

  function E.call(fn, a, b, c, d)
    local ctl = getAddressSafe("ssabnCtl")
    if not ctl or not fn then return nil end
    local ok, res = pcall(function()
      -- v2: never rewrite a pending call; the old clear-then-rearm could race the
      -- game thread mid-pickup (mixed args crashed the game). Wait for idle instead,
      -- with stuck-flag recovery after repeated sightings.
      local t0 = os.clock()
      while readBytes(ctl, 1) ~= 0 do
        if os.clock() - t0 &gt; 0.4 then
          E.stuck = (E.stuck or 0) + 1
          if E.stuck &gt;= 5 then E.stuck = 0 writeBytes(ctl, 0) end
          return nil
        end
      end
      E.stuck = 0
      writeQword(ctl + 0x08, fn)
      writeQword(ctl + 0x10, a or 0)
      writeQword(ctl + 0x18, b or 0)
      writeQword(ctl + 0x20, c or 0)
      writeQword(ctl + 0x28, d or 0)
      writeQword(ctl + 0x30, 0)
      writeBytes(ctl, 1)
      t0 = os.clock()
      while readBytes(ctl, 1) ~= 0 do
        if os.clock() - t0 &gt; 0.5 then return nil end
      end
      return readQword(ctl + 0x30)
    end)
    if ok then return res end
    return nil
  end

  function E.installGate()
    local ga = getAddressSafe("GameAssembly.dll")
    if not ga then return false, "game not attached" end
    E.ga = ga
    local site = ga + E.OFF.site
    local b = readBytes(site, 7, true)
    if not b then return false, "hook site unreadable" end
    local pristine = true
    for i = 1, 7 do if b[i] ~= E.SITE_ORIG[i] then pristine = false end end
    if not pristine then
      if b[1] == 0xE9 then
        local g = getAddressSafe("ssabnGate")
        if g then
          local rel = b[2] + b[3] * 256 + b[4] * 65536 + b[5] * 16777216
          if rel &gt;= 0x80000000 then rel = rel - 0x100000000 end
          if site + 5 + rel == g then E.gateInstalled = true return true end
        end
      end
      return false, "unexpected bytes at hook site"
    end
    local disp = b[4] + b[5] * 256 + b[6] * 65536 + b[7] * 16777216
    local loadTarget = site + 7 + disp
    local script = string.format([[
alloc(ssabnGate,$100,GameAssembly.dll+%X)
alloc(ssabnCtl,$60)
registersymbol(ssabnCtl)
registersymbol(ssabnGate)
label(ssabnOrig)

ssabnCtl:
  dq 0
  dq 0
  dq 0
  dq 0
  dq 0
  dq 0
  dq 0
  dq 0
  dq 0
  dq 0
  dq 0
  dq 0

ssabnGate:
  cmp byte ptr [ssabnCtl],1
  jne ssabnOrig
  mov byte ptr [ssabnCtl],2
  push rax
  push rbx
  push rcx
  push rdx
  push r8
  push r9
  push r10
  push r11
  mov rbx,rsp
  and rsp,-10
  sub rsp,20
  mov rcx,[ssabnCtl+10]
  mov rdx,[ssabnCtl+18]
  mov r8,[ssabnCtl+20]
  mov r9,[ssabnCtl+28]
  call qword ptr [ssabnCtl+8]
  mov [ssabnCtl+30],rax
  mov rsp,rbx
  pop r11
  pop r10
  pop r9
  pop r8
  pop rdx
  pop rcx
  pop rbx
  pop rax
  mov byte ptr [ssabnCtl],0
ssabnOrig:
  mov rax,%X
  mov rcx,[rax]
  jmp GameAssembly.dll+%X
]], E.OFF.site, loadTarget, E.OFF.ret)
    local ok = autoAssemble(script)
    if not ok then return false, "stub assemble failed" end
    local gate = getAddressSafe("ssabnGate")
    if not gate then return false, "gate symbol missing" end
    local sb = readBytes(gate, 0x100, true)
    local found = false
    for i = 1, 0xF0 do
      if sb[i] == 0x48 and sb[i + 1] == 0xB8 then
        local v = 0
        for j = 9, 2, -1 do v = v * 256 + sb[i + j] end
        if v == loadTarget then found = true end
        break
      end
    end
    if not found then return false, "stub verification failed" end
    local rel = gate - (site + 5)
    if rel &lt; 0 then rel = rel + 0x100000000 end
    local r1 = rel % 256; rel = (rel - r1) / 256
    local r2 = rel % 256; rel = (rel - r2) / 256
    local r3 = rel % 256; rel = (rel - r3) / 256
    local r4 = rel % 256
    pause()
    writeBytes(site, 0xE9, r1, r2, r3, r4, 0x66, 0x90)
    local nb = readBytes(site, 7, true)
    local good = nb and nb[1] == 0xE9 and nb[2] == r1 and nb[3] == r2 and nb[4] == r3 and nb[5] == r4 and nb[6] == 0x66 and nb[7] == 0x90
    if not good then
      writeBytes(site, 0x48, 0x8B, 0x0D, 0xCC, 0x72, 0x4D, 0x01)
      unpause()
      return false, "site patch verification failed, reverted"
    end
    unpause()
    E.gateInstalled = true
    E.note(string.format("gate installed, stub=%X", gate))
    return true
  end

  function E.uninstallGate()
    pcall(function()
      local ga = getAddressSafe("GameAssembly.dll")
      local gate = getAddressSafe("ssabnGate")
      if ga and gate then
        local site = ga + E.OFF.site
        local b = readBytes(site, 5, true)
        if b and b[1] == 0xE9 then
          local rel = b[2] + b[3] * 256 + b[4] * 65536 + b[5] * 16777216
          if rel &gt;= 0x80000000 then rel = rel - 0x100000000 end
          if site + 5 + rel == gate then
            pause()
            writeBytes(site, 0x48, 0x8B, 0x0D, 0xCC, 0x72, 0x4D, 0x01)
            unpause()
            E.note("gate uninstalled")
          end
        end
      end
    end)
    pcall(unregisterSymbol, "ssabnCtl")
    pcall(unregisterSymbol, "ssabnGate")
    E.gateInstalled = false
    E.alist = nil
  end

  function E.readAdded(alist)
    if not alist or alist &lt; 0x10000 then return nil end
    local ok, res = pcall(function()
      local arr = readQword(alist + 0x48)
      if not arr or arr &lt; 0x10000 then return nil end
      local n = readInteger(arr + 0x18)
      if not n or n &lt; 0 or n &gt; 64 then return nil end
      local m = {}
      for i = 0, n - 1 do
        local d = readQword(arr + 0x20 + i * 8)
        if d and d &gt; 0x10000 then
          local t = readInteger(d + 0x18)
          if t then m[t] = d end
        end
      end
      return m
    end)
    if ok then return res end
    return nil
  end

  function E.has(added, tv)
    if added[tv] then return true end
    local pk = E.landedKey[tv]
    if pk and added[pk] then return true end
    return false
  end

  function E.ensureLoaded(tv)
    local ctl = getAddressSafe("ssabnCtl")
    if not ctl or not E.ga then return false end
    local mgr = E.call(E.ga + E.OFF.mgrGet, 0)
    if not mgr or mgr &lt; 0x10000 then return false end
    local scratch = ctl + 0x40
    writeQword(scratch, 0)
    E.call(E.ga + E.OFF.tryget, mgr, tv, scratch, 0)
    local d = readQword(scratch)
    if d and d &gt; 0x10000 then return true end
    E.call(E.ga + E.OFF.load, ctl + 0x50, mgr, tv, 0)
    writeQword(scratch, 0)
    E.call(E.ga + E.OFF.tryget, mgr, tv, scratch, 0)
    d = readQword(scratch)
    if d and d &gt; 0x10000 then return true end
    return false
  end

  function E.blockerSlots()
    -- entry 4 "No Defilement + No Parasite" hooks AddAbnormal(data)'s first
    -- instruction and eats types listed in abnBlockId1..4; detect it here
    if not E.ga then return nil end
    local head = readBytes(E.ga + E.OFF.addData, 1, true)
    if not head or head[1] ~= 0xE9 then return nil end
    local slots = {}
    for i = 1, 4 do
      local a = getAddressSafe("abnBlockId" .. i)
      if not a or a == 0 then return nil end
      slots[i] = { addr = a, val = readInteger(a) or 0 }
    end
    return slots
  end

  function E.bypassBlockerAdd(alist, tv)
    local slots = E.blockerSlots()
    if not slots then return false, "not the blocker; add rejected by game" end
    local before = E.readAdded(alist) or {}
    for _, s in ipairs(slots) do writeInteger(s.addr, 0) end
    E.call(E.ga + E.OFF.add, alist, tv, 0, 0)
    for _, s in ipairs(slots) do writeInteger(s.addr, s.val) end
    local after = E.readAdded(alist) or {}
    if after[tv] then
      E.landedKey[tv] = nil
      return true, "blocker bypassed"
    end
    -- stale/poisoned game data can make the condition land under a different
    -- type id; a key that is new right after our own add is ours - adopt it
    for k in pairs(after) do
      if not before[k] then
        E.landedKey[tv] = k
        return true, string.format("blocker bypassed, landed as type %d", k)
      end
    end
    return false, "blocker bypassed but nothing landed"
  end

  function E.refreshPortrait()
    -- fire one UpdatePortrait through the death-portrait cheat's machinery
    -- (entry 30); harmless no-op when that cheat is off / portrait not captured
    pcall(function()
      local ctl = getAddressSafe("gdpCtl")
      if not ctl or ctl == 0 then return end
      if readBytes(ctl, 1) ~= 0 then return end
      local portrait = readQword(ctl + 0x18)
      local fn = readQword(ctl + 0x10)
      if not portrait or portrait &lt; 0x10000 then return end
      if not fn or fn &lt; 0x10000 then return end
      local cached = readQword(portrait + 0x10)
      if not cached or cached == 0 then return end
      writeQword(ctl + 0x8, portrait)
      writeBytes(ctl, 1)
    end)
  end

  function E.removeLook(alist, name)
    local tv = E.TYPES[name]
    E.call(E.ga + E.OFF.remove, alist, tv)
    local pk = E.landedKey[tv]
    if pk and pk ~= tv then
      E.call(E.ga + E.OFF.remove, alist, pk)
      E.landedKey[tv] = nil
    end
  end

  function E.reconcile()
    -- drop owners whose table entry got unchecked without our disable running
    -- (missed/failed [DISABLE] used to leak refcounts and make looks immortal)
    local al = getAddressList()
    local dropped = nil
    for id in pairs(E.owners) do
      local mr = al.getMemoryRecordByID(id)
      if mr and not mr.Active then
        dropped = dropped or {}
        dropped[#dropped + 1] = id
      end
    end
    if not dropped then return end
    for _, id in ipairs(dropped) do
      local list = E.owners[id]
      E.owners[id] = nil
      local w = E.wanted()
      local alist = E.alist
      if alist and alist &gt; 0x10000 then
        for _, name in ipairs(list) do
          if not w[name] then E.removeLook(alist, name) end
        end
        E.refreshPortrait()
      end
      E.note("reconciled: entry " .. id .. " is unchecked, released its looks")
    end
    if next(E.owners) == nil then
      if E.timer then pcall(function() E.timer.destroy() end) E.timer = nil end
      E.uninstallGate()
    end
  end

  function E.tick()
    if E.busy then return end
    E.busy = true
    local ok, err = pcall(function()
      if E.cooldown and os.clock() &lt; E.cooldown then return end
      E.reconcile()
      local wantList, wantPregnant = {}, false
      for name in pairs(E.wanted()) do
        wantList[#wantList + 1] = name
        if name == "Pregnant" then wantPregnant = true end
      end
      if #wantList == 0 then return end
      if not E.gateInstalled then
        local ok2 = E.installGate()
        if not ok2 then E.cooldown = os.clock() + 3 return end
      end
      local added = E.readAdded(E.alist)
      if added then
        local pending = false
        for _, name in ipairs(wantList) do
          if not E.has(added, E.TYPES[name]) then pending = true end
        end
        if wantPregnant and added[E.TYPES.Blessing] then pending = true end
        if not pending then return end
      end
      local psm = E.call(E.ga + E.OFF.psmGet, 0)
      if not psm or psm &lt; 0x10000 then
        E.failCount = (E.failCount or 0) + 1
        if E.failCount &gt;= 5 then
          E.note("gate unresponsive, resetting (game restarted?)")
          E.uninstallGate()
          E.failCount = 0
        end
        E.cooldown = os.clock() + 2
        return
      end
      E.failCount = 0
      local alist = readQword(psm + 0x50)
      if not alist or alist &lt; 0x10000 then E.cooldown = os.clock() + 2 return end
      E.alist = alist
      added = E.readAdded(alist) or {}
      if wantPregnant and added[E.TYPES.Blessing] then
        if E.hadBlessing == nil then E.hadBlessing = true end
        E.removedBlessing = true
        E.call(E.ga + E.OFF.remove, alist, E.TYPES.Blessing)
        E.note("removed InfertilityBlessing (will restore on disable)")
        return
      end
      if wantPregnant and E.hadBlessing == nil then E.hadBlessing = false end
      for _, name in ipairs(wantList) do
        local tv = E.TYPES[name]
        if not E.has(added, tv) then
          if E.ensureLoaded(tv) then
            E.call(E.ga + E.OFF.add, alist, tv, 0, 0)
            local a2 = E.readAdded(alist) or {}
            if a2[tv] then
              E.landedKey[tv] = nil
              E.failStreak = 0
              E.note("added " .. name)
              E.refreshPortrait()
            else
              local okb, how = E.bypassBlockerAdd(alist, tv)
              if okb then
                E.failStreak = 0
                E.note("added " .. name .. " (" .. how .. ")")
                E.refreshPortrait()
              else
                -- a game event can leave the condition half-removed (gone from
                -- the visible array, still in the internal dict) which no-ops
                -- every re-add; a full remove clears both, retry next tick
                E.call(E.ga + E.OFF.remove, alist, tv)
                E.failStreak = E.failStreak + 1
                E.note("add " .. name .. " did not land (" .. how .. "); cleared half-state, retrying")
                if E.failStreak &gt;= 10 then
                  E.note("10 consecutive failures, pausing 5s")
                  E.cooldown = os.clock() + 5
                  E.failStreak = 0
                end
              end
            end
          else
            E.note("waiting for " .. name .. " data to load")
          end
        end
      end
    end)
    if not ok then E.note("tick error: " .. tostring(err)) end
    E.busy = false
  end

  function E.enable(id, list)
    local ga = getAddressSafe("GameAssembly.dll")
    if not ga then error("SiNiSistar2 is not attached") end
    if not E.gateInstalled then
      local ok, err = E.installGate()
      if not ok then error("gate install failed: " .. tostring(err)) end
    end
    E.owners[id] = list
    E.cooldown, E.failCount, E.failStreak = nil, 0, 0
    if not E.timer then
      E.timer = createTimer(nil)
      E.timer.Interval = 300
      E.timer.OnTimer = E.tick
      E.timer.Enabled = true
    end
    E.note("enabled " .. id .. ": " .. table.concat(list, "+"))
  end

  function E.disable(id, list)
    E.owners[id] = nil
    pcall(function()
      if not E.gateInstalled or not E.ga then return end
      local psm = E.call(E.ga + E.OFF.psmGet, 0)
      local alist = nil
      if psm and psm &gt; 0x10000 then alist = readQword(psm + 0x50) end
      if alist and alist &gt; 0x10000 then
        local w = E.wanted()
        local changed = false
        for _, name in ipairs(list) do
          if not w[name] then
            E.removeLook(alist, name)
            E.note("removed " .. name)
            changed = true
          end
        end
        if changed then E.refreshPortrait() end
        if not w.Pregnant and E.removedBlessing then
          if E.hadBlessing and E.ensureLoaded(E.TYPES.Blessing) then
            E.call(E.ga + E.OFF.add, alist, E.TYPES.Blessing, 0, 0)
            E.note("restored InfertilityBlessing")
          end
          E.removedBlessing = false
          E.hadBlessing = nil
        end
      end
    end)
    if next(E.owners) == nil then
      if E.timer then pcall(function() E.timer.destroy() end) E.timer = nil end
      E.uninstallGate()
    end
    E.note("disabled " .. id .. ": " .. table.concat(list, "+"))
  end

  if OLD then
    E.log = OLD.log or E.log
    E.hadBlessing = OLD.hadBlessing
    E.removedBlessing = OLD.removedBlessing or false
    E.gateInstalled = OLD.gateInstalled or false
    E.ga = OLD.ga
    E.alist = OLD.alist
    E.timer = OLD.timer
    if E.timer then E.timer.OnTimer = E.tick end
    -- v2 refcounts (OLD.want) are untrusted (they leaked); owners start empty
    -- and each entry's enable line below re-registers itself
    E.note("engine upgraded to v3 (owner-set model)")
  end
end

_G.SS2Abn.enable(31, {"Breast"})
{$asm}

[DISABLE]
{$lua}
if syntaxcheck then return end
if _G.SS2Abn then _G.SS2Abn.disable(31, {"Breast"}) end
{$asm}
</AssemblerScript>
        </CheatEntry>
        <CheatEntry>
          <ID>32</ID>
          <Description>"Portrait Look: Pregnant"</Description>
          <VariableType>Auto Assembler Script</VariableType>
          <AssemblerScript>[ENABLE]
{$lua}
if syntaxcheck then return end
if not _G.SS2Abn or (_G.SS2Abn.version or 0) &lt; 3 then
  local OLD = _G.SS2Abn
  local E = {}
  _G.SS2Abn = E
  E.version = 3
  E.TYPES = { Breast = 926037814, Pregnant = 959721780, Blessing = 825765986 }
  E.OFF = { site = 0x1A76595, ret = 0x1A7659C, mgrGet = 0x1970460, psmGet = 0x1970BA0,
            tryget = 0x1815AC0, load = 0x1815610, add = 0x1A57FD0, remove = 0x1A590D0,
            addData = 0x1A57910 }
  E.SITE_ORIG = { 0x48, 0x8B, 0x0D, 0xCC, 0x72, 0x4D, 0x01 }
  -- v3: ownership set keyed by table-entry id; wanted looks derived fresh each
  -- tick and reconciled against checkbox state (no leakable refcounts)
  E.owners, E.log = {}, {}
  E.removedBlessing, E.hadBlessing, E.gateInstalled = false, nil, false
  E.landedKey, E.failStreak, E.busy, E.stuck = {}, 0, false, 0

  function E.wanted()
    local w = {}
    for _, list in pairs(E.owners) do
      for _, name in ipairs(list) do w[name] = true end
    end
    return w
  end

  function E.note(s)
    table.insert(E.log, os.date("%H:%M:%S ") .. s)
    if #E.log &gt; 120 then table.remove(E.log, 1) end
  end
  function E.status() return table.concat(E.log, "\n") end

  function E.call(fn, a, b, c, d)
    local ctl = getAddressSafe("ssabnCtl")
    if not ctl or not fn then return nil end
    local ok, res = pcall(function()
      -- v2: never rewrite a pending call; the old clear-then-rearm could race the
      -- game thread mid-pickup (mixed args crashed the game). Wait for idle instead,
      -- with stuck-flag recovery after repeated sightings.
      local t0 = os.clock()
      while readBytes(ctl, 1) ~= 0 do
        if os.clock() - t0 &gt; 0.4 then
          E.stuck = (E.stuck or 0) + 1
          if E.stuck &gt;= 5 then E.stuck = 0 writeBytes(ctl, 0) end
          return nil
        end
      end
      E.stuck = 0
      writeQword(ctl + 0x08, fn)
      writeQword(ctl + 0x10, a or 0)
      writeQword(ctl + 0x18, b or 0)
      writeQword(ctl + 0x20, c or 0)
      writeQword(ctl + 0x28, d or 0)
      writeQword(ctl + 0x30, 0)
      writeBytes(ctl, 1)
      t0 = os.clock()
      while readBytes(ctl, 1) ~= 0 do
        if os.clock() - t0 &gt; 0.5 then return nil end
      end
      return readQword(ctl + 0x30)
    end)
    if ok then return res end
    return nil
  end

  function E.installGate()
    local ga = getAddressSafe("GameAssembly.dll")
    if not ga then return false, "game not attached" end
    E.ga = ga
    local site = ga + E.OFF.site
    local b = readBytes(site, 7, true)
    if not b then return false, "hook site unreadable" end
    local pristine = true
    for i = 1, 7 do if b[i] ~= E.SITE_ORIG[i] then pristine = false end end
    if not pristine then
      if b[1] == 0xE9 then
        local g = getAddressSafe("ssabnGate")
        if g then
          local rel = b[2] + b[3] * 256 + b[4] * 65536 + b[5] * 16777216
          if rel &gt;= 0x80000000 then rel = rel - 0x100000000 end
          if site + 5 + rel == g then E.gateInstalled = true return true end
        end
      end
      return false, "unexpected bytes at hook site"
    end
    local disp = b[4] + b[5] * 256 + b[6] * 65536 + b[7] * 16777216
    local loadTarget = site + 7 + disp
    local script = string.format([[
alloc(ssabnGate,$100,GameAssembly.dll+%X)
alloc(ssabnCtl,$60)
registersymbol(ssabnCtl)
registersymbol(ssabnGate)
label(ssabnOrig)

ssabnCtl:
  dq 0
  dq 0
  dq 0
  dq 0
  dq 0
  dq 0
  dq 0
  dq 0
  dq 0
  dq 0
  dq 0
  dq 0

ssabnGate:
  cmp byte ptr [ssabnCtl],1
  jne ssabnOrig
  mov byte ptr [ssabnCtl],2
  push rax
  push rbx
  push rcx
  push rdx
  push r8
  push r9
  push r10
  push r11
  mov rbx,rsp
  and rsp,-10
  sub rsp,20
  mov rcx,[ssabnCtl+10]
  mov rdx,[ssabnCtl+18]
  mov r8,[ssabnCtl+20]
  mov r9,[ssabnCtl+28]
  call qword ptr [ssabnCtl+8]
  mov [ssabnCtl+30],rax
  mov rsp,rbx
  pop r11
  pop r10
  pop r9
  pop r8
  pop rdx
  pop rcx
  pop rbx
  pop rax
  mov byte ptr [ssabnCtl],0
ssabnOrig:
  mov rax,%X
  mov rcx,[rax]
  jmp GameAssembly.dll+%X
]], E.OFF.site, loadTarget, E.OFF.ret)
    local ok = autoAssemble(script)
    if not ok then return false, "stub assemble failed" end
    local gate = getAddressSafe("ssabnGate")
    if not gate then return false, "gate symbol missing" end
    local sb = readBytes(gate, 0x100, true)
    local found = false
    for i = 1, 0xF0 do
      if sb[i] == 0x48 and sb[i + 1] == 0xB8 then
        local v = 0
        for j = 9, 2, -1 do v = v * 256 + sb[i + j] end
        if v == loadTarget then found = true end
        break
      end
    end
    if not found then return false, "stub verification failed" end
    local rel = gate - (site + 5)
    if rel &lt; 0 then rel = rel + 0x100000000 end
    local r1 = rel % 256; rel = (rel - r1) / 256
    local r2 = rel % 256; rel = (rel - r2) / 256
    local r3 = rel % 256; rel = (rel - r3) / 256
    local r4 = rel % 256
    pause()
    writeBytes(site, 0xE9, r1, r2, r3, r4, 0x66, 0x90)
    local nb = readBytes(site, 7, true)
    local good = nb and nb[1] == 0xE9 and nb[2] == r1 and nb[3] == r2 and nb[4] == r3 and nb[5] == r4 and nb[6] == 0x66 and nb[7] == 0x90
    if not good then
      writeBytes(site, 0x48, 0x8B, 0x0D, 0xCC, 0x72, 0x4D, 0x01)
      unpause()
      return false, "site patch verification failed, reverted"
    end
    unpause()
    E.gateInstalled = true
    E.note(string.format("gate installed, stub=%X", gate))
    return true
  end

  function E.uninstallGate()
    pcall(function()
      local ga = getAddressSafe("GameAssembly.dll")
      local gate = getAddressSafe("ssabnGate")
      if ga and gate then
        local site = ga + E.OFF.site
        local b = readBytes(site, 5, true)
        if b and b[1] == 0xE9 then
          local rel = b[2] + b[3] * 256 + b[4] * 65536 + b[5] * 16777216
          if rel &gt;= 0x80000000 then rel = rel - 0x100000000 end
          if site + 5 + rel == gate then
            pause()
            writeBytes(site, 0x48, 0x8B, 0x0D, 0xCC, 0x72, 0x4D, 0x01)
            unpause()
            E.note("gate uninstalled")
          end
        end
      end
    end)
    pcall(unregisterSymbol, "ssabnCtl")
    pcall(unregisterSymbol, "ssabnGate")
    E.gateInstalled = false
    E.alist = nil
  end

  function E.readAdded(alist)
    if not alist or alist &lt; 0x10000 then return nil end
    local ok, res = pcall(function()
      local arr = readQword(alist + 0x48)
      if not arr or arr &lt; 0x10000 then return nil end
      local n = readInteger(arr + 0x18)
      if not n or n &lt; 0 or n &gt; 64 then return nil end
      local m = {}
      for i = 0, n - 1 do
        local d = readQword(arr + 0x20 + i * 8)
        if d and d &gt; 0x10000 then
          local t = readInteger(d + 0x18)
          if t then m[t] = d end
        end
      end
      return m
    end)
    if ok then return res end
    return nil
  end

  function E.has(added, tv)
    if added[tv] then return true end
    local pk = E.landedKey[tv]
    if pk and added[pk] then return true end
    return false
  end

  function E.ensureLoaded(tv)
    local ctl = getAddressSafe("ssabnCtl")
    if not ctl or not E.ga then return false end
    local mgr = E.call(E.ga + E.OFF.mgrGet, 0)
    if not mgr or mgr &lt; 0x10000 then return false end
    local scratch = ctl + 0x40
    writeQword(scratch, 0)
    E.call(E.ga + E.OFF.tryget, mgr, tv, scratch, 0)
    local d = readQword(scratch)
    if d and d &gt; 0x10000 then return true end
    E.call(E.ga + E.OFF.load, ctl + 0x50, mgr, tv, 0)
    writeQword(scratch, 0)
    E.call(E.ga + E.OFF.tryget, mgr, tv, scratch, 0)
    d = readQword(scratch)
    if d and d &gt; 0x10000 then return true end
    return false
  end

  function E.blockerSlots()
    -- entry 4 "No Defilement + No Parasite" hooks AddAbnormal(data)'s first
    -- instruction and eats types listed in abnBlockId1..4; detect it here
    if not E.ga then return nil end
    local head = readBytes(E.ga + E.OFF.addData, 1, true)
    if not head or head[1] ~= 0xE9 then return nil end
    local slots = {}
    for i = 1, 4 do
      local a = getAddressSafe("abnBlockId" .. i)
      if not a or a == 0 then return nil end
      slots[i] = { addr = a, val = readInteger(a) or 0 }
    end
    return slots
  end

  function E.bypassBlockerAdd(alist, tv)
    local slots = E.blockerSlots()
    if not slots then return false, "not the blocker; add rejected by game" end
    local before = E.readAdded(alist) or {}
    for _, s in ipairs(slots) do writeInteger(s.addr, 0) end
    E.call(E.ga + E.OFF.add, alist, tv, 0, 0)
    for _, s in ipairs(slots) do writeInteger(s.addr, s.val) end
    local after = E.readAdded(alist) or {}
    if after[tv] then
      E.landedKey[tv] = nil
      return true, "blocker bypassed"
    end
    -- stale/poisoned game data can make the condition land under a different
    -- type id; a key that is new right after our own add is ours - adopt it
    for k in pairs(after) do
      if not before[k] then
        E.landedKey[tv] = k
        return true, string.format("blocker bypassed, landed as type %d", k)
      end
    end
    return false, "blocker bypassed but nothing landed"
  end

  function E.refreshPortrait()
    -- fire one UpdatePortrait through the death-portrait cheat's machinery
    -- (entry 30); harmless no-op when that cheat is off / portrait not captured
    pcall(function()
      local ctl = getAddressSafe("gdpCtl")
      if not ctl or ctl == 0 then return end
      if readBytes(ctl, 1) ~= 0 then return end
      local portrait = readQword(ctl + 0x18)
      local fn = readQword(ctl + 0x10)
      if not portrait or portrait &lt; 0x10000 then return end
      if not fn or fn &lt; 0x10000 then return end
      local cached = readQword(portrait + 0x10)
      if not cached or cached == 0 then return end
      writeQword(ctl + 0x8, portrait)
      writeBytes(ctl, 1)
    end)
  end

  function E.removeLook(alist, name)
    local tv = E.TYPES[name]
    E.call(E.ga + E.OFF.remove, alist, tv)
    local pk = E.landedKey[tv]
    if pk and pk ~= tv then
      E.call(E.ga + E.OFF.remove, alist, pk)
      E.landedKey[tv] = nil
    end
  end

  function E.reconcile()
    -- drop owners whose table entry got unchecked without our disable running
    -- (missed/failed [DISABLE] used to leak refcounts and make looks immortal)
    local al = getAddressList()
    local dropped = nil
    for id in pairs(E.owners) do
      local mr = al.getMemoryRecordByID(id)
      if mr and not mr.Active then
        dropped = dropped or {}
        dropped[#dropped + 1] = id
      end
    end
    if not dropped then return end
    for _, id in ipairs(dropped) do
      local list = E.owners[id]
      E.owners[id] = nil
      local w = E.wanted()
      local alist = E.alist
      if alist and alist &gt; 0x10000 then
        for _, name in ipairs(list) do
          if not w[name] then E.removeLook(alist, name) end
        end
        E.refreshPortrait()
      end
      E.note("reconciled: entry " .. id .. " is unchecked, released its looks")
    end
    if next(E.owners) == nil then
      if E.timer then pcall(function() E.timer.destroy() end) E.timer = nil end
      E.uninstallGate()
    end
  end

  function E.tick()
    if E.busy then return end
    E.busy = true
    local ok, err = pcall(function()
      if E.cooldown and os.clock() &lt; E.cooldown then return end
      E.reconcile()
      local wantList, wantPregnant = {}, false
      for name in pairs(E.wanted()) do
        wantList[#wantList + 1] = name
        if name == "Pregnant" then wantPregnant = true end
      end
      if #wantList == 0 then return end
      if not E.gateInstalled then
        local ok2 = E.installGate()
        if not ok2 then E.cooldown = os.clock() + 3 return end
      end
      local added = E.readAdded(E.alist)
      if added then
        local pending = false
        for _, name in ipairs(wantList) do
          if not E.has(added, E.TYPES[name]) then pending = true end
        end
        if wantPregnant and added[E.TYPES.Blessing] then pending = true end
        if not pending then return end
      end
      local psm = E.call(E.ga + E.OFF.psmGet, 0)
      if not psm or psm &lt; 0x10000 then
        E.failCount = (E.failCount or 0) + 1
        if E.failCount &gt;= 5 then
          E.note("gate unresponsive, resetting (game restarted?)")
          E.uninstallGate()
          E.failCount = 0
        end
        E.cooldown = os.clock() + 2
        return
      end
      E.failCount = 0
      local alist = readQword(psm + 0x50)
      if not alist or alist &lt; 0x10000 then E.cooldown = os.clock() + 2 return end
      E.alist = alist
      added = E.readAdded(alist) or {}
      if wantPregnant and added[E.TYPES.Blessing] then
        if E.hadBlessing == nil then E.hadBlessing = true end
        E.removedBlessing = true
        E.call(E.ga + E.OFF.remove, alist, E.TYPES.Blessing)
        E.note("removed InfertilityBlessing (will restore on disable)")
        return
      end
      if wantPregnant and E.hadBlessing == nil then E.hadBlessing = false end
      for _, name in ipairs(wantList) do
        local tv = E.TYPES[name]
        if not E.has(added, tv) then
          if E.ensureLoaded(tv) then
            E.call(E.ga + E.OFF.add, alist, tv, 0, 0)
            local a2 = E.readAdded(alist) or {}
            if a2[tv] then
              E.landedKey[tv] = nil
              E.failStreak = 0
              E.note("added " .. name)
              E.refreshPortrait()
            else
              local okb, how = E.bypassBlockerAdd(alist, tv)
              if okb then
                E.failStreak = 0
                E.note("added " .. name .. " (" .. how .. ")")
                E.refreshPortrait()
              else
                -- a game event can leave the condition half-removed (gone from
                -- the visible array, still in the internal dict) which no-ops
                -- every re-add; a full remove clears both, retry next tick
                E.call(E.ga + E.OFF.remove, alist, tv)
                E.failStreak = E.failStreak + 1
                E.note("add " .. name .. " did not land (" .. how .. "); cleared half-state, retrying")
                if E.failStreak &gt;= 10 then
                  E.note("10 consecutive failures, pausing 5s")
                  E.cooldown = os.clock() + 5
                  E.failStreak = 0
                end
              end
            end
          else
            E.note("waiting for " .. name .. " data to load")
          end
        end
      end
    end)
    if not ok then E.note("tick error: " .. tostring(err)) end
    E.busy = false
  end

  function E.enable(id, list)
    local ga = getAddressSafe("GameAssembly.dll")
    if not ga then error("SiNiSistar2 is not attached") end
    if not E.gateInstalled then
      local ok, err = E.installGate()
      if not ok then error("gate install failed: " .. tostring(err)) end
    end
    E.owners[id] = list
    E.cooldown, E.failCount, E.failStreak = nil, 0, 0
    if not E.timer then
      E.timer = createTimer(nil)
      E.timer.Interval = 300
      E.timer.OnTimer = E.tick
      E.timer.Enabled = true
    end
    E.note("enabled " .. id .. ": " .. table.concat(list, "+"))
  end

  function E.disable(id, list)
    E.owners[id] = nil
    pcall(function()
      if not E.gateInstalled or not E.ga then return end
      local psm = E.call(E.ga + E.OFF.psmGet, 0)
      local alist = nil
      if psm and psm &gt; 0x10000 then alist = readQword(psm + 0x50) end
      if alist and alist &gt; 0x10000 then
        local w = E.wanted()
        local changed = false
        for _, name in ipairs(list) do
          if not w[name] then
            E.removeLook(alist, name)
            E.note("removed " .. name)
            changed = true
          end
        end
        if changed then E.refreshPortrait() end
        if not w.Pregnant and E.removedBlessing then
          if E.hadBlessing and E.ensureLoaded(E.TYPES.Blessing) then
            E.call(E.ga + E.OFF.add, alist, E.TYPES.Blessing, 0, 0)
            E.note("restored InfertilityBlessing")
          end
          E.removedBlessing = false
          E.hadBlessing = nil
        end
      end
    end)
    if next(E.owners) == nil then
      if E.timer then pcall(function() E.timer.destroy() end) E.timer = nil end
      E.uninstallGate()
    end
    E.note("disabled " .. id .. ": " .. table.concat(list, "+"))
  end

  if OLD then
    E.log = OLD.log or E.log
    E.hadBlessing = OLD.hadBlessing
    E.removedBlessing = OLD.removedBlessing or false
    E.gateInstalled = OLD.gateInstalled or false
    E.ga = OLD.ga
    E.alist = OLD.alist
    E.timer = OLD.timer
    if E.timer then E.timer.OnTimer = E.tick end
    -- v2 refcounts (OLD.want) are untrusted (they leaked); owners start empty
    -- and each entry's enable line below re-registers itself
    E.note("engine upgraded to v3 (owner-set model)")
  end
end

_G.SS2Abn.enable(32, {"Pregnant"})
{$asm}

[DISABLE]
{$lua}
if syntaxcheck then return end
if _G.SS2Abn then _G.SS2Abn.disable(32, {"Pregnant"}) end
{$asm}
</AssemblerScript>
        </CheatEntry>
        <CheatEntry>
          <ID>33</ID>
          <Description>"Portrait Look: Both (Breast + Pregnant)"</Description>
          <VariableType>Auto Assembler Script</VariableType>
          <AssemblerScript>[ENABLE]
{$lua}
if syntaxcheck then return end
if not _G.SS2Abn or (_G.SS2Abn.version or 0) &lt; 3 then
  local OLD = _G.SS2Abn
  local E = {}
  _G.SS2Abn = E
  E.version = 3
  E.TYPES = { Breast = 926037814, Pregnant = 959721780, Blessing = 825765986 }
  E.OFF = { site = 0x1A76595, ret = 0x1A7659C, mgrGet = 0x1970460, psmGet = 0x1970BA0,
            tryget = 0x1815AC0, load = 0x1815610, add = 0x1A57FD0, remove = 0x1A590D0,
            addData = 0x1A57910 }
  E.SITE_ORIG = { 0x48, 0x8B, 0x0D, 0xCC, 0x72, 0x4D, 0x01 }
  -- v3: ownership set keyed by table-entry id; wanted looks derived fresh each
  -- tick and reconciled against checkbox state (no leakable refcounts)
  E.owners, E.log = {}, {}
  E.removedBlessing, E.hadBlessing, E.gateInstalled = false, nil, false
  E.landedKey, E.failStreak, E.busy, E.stuck = {}, 0, false, 0

  function E.wanted()
    local w = {}
    for _, list in pairs(E.owners) do
      for _, name in ipairs(list) do w[name] = true end
    end
    return w
  end

  function E.note(s)
    table.insert(E.log, os.date("%H:%M:%S ") .. s)
    if #E.log &gt; 120 then table.remove(E.log, 1) end
  end
  function E.status() return table.concat(E.log, "\n") end

  function E.call(fn, a, b, c, d)
    local ctl = getAddressSafe("ssabnCtl")
    if not ctl or not fn then return nil end
    local ok, res = pcall(function()
      -- v2: never rewrite a pending call; the old clear-then-rearm could race the
      -- game thread mid-pickup (mixed args crashed the game). Wait for idle instead,
      -- with stuck-flag recovery after repeated sightings.
      local t0 = os.clock()
      while readBytes(ctl, 1) ~= 0 do
        if os.clock() - t0 &gt; 0.4 then
          E.stuck = (E.stuck or 0) + 1
          if E.stuck &gt;= 5 then E.stuck = 0 writeBytes(ctl, 0) end
          return nil
        end
      end
      E.stuck = 0
      writeQword(ctl + 0x08, fn)
      writeQword(ctl + 0x10, a or 0)
      writeQword(ctl + 0x18, b or 0)
      writeQword(ctl + 0x20, c or 0)
      writeQword(ctl + 0x28, d or 0)
      writeQword(ctl + 0x30, 0)
      writeBytes(ctl, 1)
      t0 = os.clock()
      while readBytes(ctl, 1) ~= 0 do
        if os.clock() - t0 &gt; 0.5 then return nil end
      end
      return readQword(ctl + 0x30)
    end)
    if ok then return res end
    return nil
  end

  function E.installGate()
    local ga = getAddressSafe("GameAssembly.dll")
    if not ga then return false, "game not attached" end
    E.ga = ga
    local site = ga + E.OFF.site
    local b = readBytes(site, 7, true)
    if not b then return false, "hook site unreadable" end
    local pristine = true
    for i = 1, 7 do if b[i] ~= E.SITE_ORIG[i] then pristine = false end end
    if not pristine then
      if b[1] == 0xE9 then
        local g = getAddressSafe("ssabnGate")
        if g then
          local rel = b[2] + b[3] * 256 + b[4] * 65536 + b[5] * 16777216
          if rel &gt;= 0x80000000 then rel = rel - 0x100000000 end
          if site + 5 + rel == g then E.gateInstalled = true return true end
        end
      end
      return false, "unexpected bytes at hook site"
    end
    local disp = b[4] + b[5] * 256 + b[6] * 65536 + b[7] * 16777216
    local loadTarget = site + 7 + disp
    local script = string.format([[
alloc(ssabnGate,$100,GameAssembly.dll+%X)
alloc(ssabnCtl,$60)
registersymbol(ssabnCtl)
registersymbol(ssabnGate)
label(ssabnOrig)

ssabnCtl:
  dq 0
  dq 0
  dq 0
  dq 0
  dq 0
  dq 0
  dq 0
  dq 0
  dq 0
  dq 0
  dq 0
  dq 0

ssabnGate:
  cmp byte ptr [ssabnCtl],1
  jne ssabnOrig
  mov byte ptr [ssabnCtl],2
  push rax
  push rbx
  push rcx
  push rdx
  push r8
  push r9
  push r10
  push r11
  mov rbx,rsp
  and rsp,-10
  sub rsp,20
  mov rcx,[ssabnCtl+10]
  mov rdx,[ssabnCtl+18]
  mov r8,[ssabnCtl+20]
  mov r9,[ssabnCtl+28]
  call qword ptr [ssabnCtl+8]
  mov [ssabnCtl+30],rax
  mov rsp,rbx
  pop r11
  pop r10
  pop r9
  pop r8
  pop rdx
  pop rcx
  pop rbx
  pop rax
  mov byte ptr [ssabnCtl],0
ssabnOrig:
  mov rax,%X
  mov rcx,[rax]
  jmp GameAssembly.dll+%X
]], E.OFF.site, loadTarget, E.OFF.ret)
    local ok = autoAssemble(script)
    if not ok then return false, "stub assemble failed" end
    local gate = getAddressSafe("ssabnGate")
    if not gate then return false, "gate symbol missing" end
    local sb = readBytes(gate, 0x100, true)
    local found = false
    for i = 1, 0xF0 do
      if sb[i] == 0x48 and sb[i + 1] == 0xB8 then
        local v = 0
        for j = 9, 2, -1 do v = v * 256 + sb[i + j] end
        if v == loadTarget then found = true end
        break
      end
    end
    if not found then return false, "stub verification failed" end
    local rel = gate - (site + 5)
    if rel &lt; 0 then rel = rel + 0x100000000 end
    local r1 = rel % 256; rel = (rel - r1) / 256
    local r2 = rel % 256; rel = (rel - r2) / 256
    local r3 = rel % 256; rel = (rel - r3) / 256
    local r4 = rel % 256
    pause()
    writeBytes(site, 0xE9, r1, r2, r3, r4, 0x66, 0x90)
    local nb = readBytes(site, 7, true)
    local good = nb and nb[1] == 0xE9 and nb[2] == r1 and nb[3] == r2 and nb[4] == r3 and nb[5] == r4 and nb[6] == 0x66 and nb[7] == 0x90
    if not good then
      writeBytes(site, 0x48, 0x8B, 0x0D, 0xCC, 0x72, 0x4D, 0x01)
      unpause()
      return false, "site patch verification failed, reverted"
    end
    unpause()
    E.gateInstalled = true
    E.note(string.format("gate installed, stub=%X", gate))
    return true
  end

  function E.uninstallGate()
    pcall(function()
      local ga = getAddressSafe("GameAssembly.dll")
      local gate = getAddressSafe("ssabnGate")
      if ga and gate then
        local site = ga + E.OFF.site
        local b = readBytes(site, 5, true)
        if b and b[1] == 0xE9 then
          local rel = b[2] + b[3] * 256 + b[4] * 65536 + b[5] * 16777216
          if rel &gt;= 0x80000000 then rel = rel - 0x100000000 end
          if site + 5 + rel == gate then
            pause()
            writeBytes(site, 0x48, 0x8B, 0x0D, 0xCC, 0x72, 0x4D, 0x01)
            unpause()
            E.note("gate uninstalled")
          end
        end
      end
    end)
    pcall(unregisterSymbol, "ssabnCtl")
    pcall(unregisterSymbol, "ssabnGate")
    E.gateInstalled = false
    E.alist = nil
  end

  function E.readAdded(alist)
    if not alist or alist &lt; 0x10000 then return nil end
    local ok, res = pcall(function()
      local arr = readQword(alist + 0x48)
      if not arr or arr &lt; 0x10000 then return nil end
      local n = readInteger(arr + 0x18)
      if not n or n &lt; 0 or n &gt; 64 then return nil end
      local m = {}
      for i = 0, n - 1 do
        local d = readQword(arr + 0x20 + i * 8)
        if d and d &gt; 0x10000 then
          local t = readInteger(d + 0x18)
          if t then m[t] = d end
        end
      end
      return m
    end)
    if ok then return res end
    return nil
  end

  function E.has(added, tv)
    if added[tv] then return true end
    local pk = E.landedKey[tv]
    if pk and added[pk] then return true end
    return false
  end

  function E.ensureLoaded(tv)
    local ctl = getAddressSafe("ssabnCtl")
    if not ctl or not E.ga then return false end
    local mgr = E.call(E.ga + E.OFF.mgrGet, 0)
    if not mgr or mgr &lt; 0x10000 then return false end
    local scratch = ctl + 0x40
    writeQword(scratch, 0)
    E.call(E.ga + E.OFF.tryget, mgr, tv, scratch, 0)
    local d = readQword(scratch)
    if d and d &gt; 0x10000 then return true end
    E.call(E.ga + E.OFF.load, ctl + 0x50, mgr, tv, 0)
    writeQword(scratch, 0)
    E.call(E.ga + E.OFF.tryget, mgr, tv, scratch, 0)
    d = readQword(scratch)
    if d and d &gt; 0x10000 then return true end
    return false
  end

  function E.blockerSlots()
    -- entry 4 "No Defilement + No Parasite" hooks AddAbnormal(data)'s first
    -- instruction and eats types listed in abnBlockId1..4; detect it here
    if not E.ga then return nil end
    local head = readBytes(E.ga + E.OFF.addData, 1, true)
    if not head or head[1] ~= 0xE9 then return nil end
    local slots = {}
    for i = 1, 4 do
      local a = getAddressSafe("abnBlockId" .. i)
      if not a or a == 0 then return nil end
      slots[i] = { addr = a, val = readInteger(a) or 0 }
    end
    return slots
  end

  function E.bypassBlockerAdd(alist, tv)
    local slots = E.blockerSlots()
    if not slots then return false, "not the blocker; add rejected by game" end
    local before = E.readAdded(alist) or {}
    for _, s in ipairs(slots) do writeInteger(s.addr, 0) end
    E.call(E.ga + E.OFF.add, alist, tv, 0, 0)
    for _, s in ipairs(slots) do writeInteger(s.addr, s.val) end
    local after = E.readAdded(alist) or {}
    if after[tv] then
      E.landedKey[tv] = nil
      return true, "blocker bypassed"
    end
    -- stale/poisoned game data can make the condition land under a different
    -- type id; a key that is new right after our own add is ours - adopt it
    for k in pairs(after) do
      if not before[k] then
        E.landedKey[tv] = k
        return true, string.format("blocker bypassed, landed as type %d", k)
      end
    end
    return false, "blocker bypassed but nothing landed"
  end

  function E.refreshPortrait()
    -- fire one UpdatePortrait through the death-portrait cheat's machinery
    -- (entry 30); harmless no-op when that cheat is off / portrait not captured
    pcall(function()
      local ctl = getAddressSafe("gdpCtl")
      if not ctl or ctl == 0 then return end
      if readBytes(ctl, 1) ~= 0 then return end
      local portrait = readQword(ctl + 0x18)
      local fn = readQword(ctl + 0x10)
      if not portrait or portrait &lt; 0x10000 then return end
      if not fn or fn &lt; 0x10000 then return end
      local cached = readQword(portrait + 0x10)
      if not cached or cached == 0 then return end
      writeQword(ctl + 0x8, portrait)
      writeBytes(ctl, 1)
    end)
  end

  function E.removeLook(alist, name)
    local tv = E.TYPES[name]
    E.call(E.ga + E.OFF.remove, alist, tv)
    local pk = E.landedKey[tv]
    if pk and pk ~= tv then
      E.call(E.ga + E.OFF.remove, alist, pk)
      E.landedKey[tv] = nil
    end
  end

  function E.reconcile()
    -- drop owners whose table entry got unchecked without our disable running
    -- (missed/failed [DISABLE] used to leak refcounts and make looks immortal)
    local al = getAddressList()
    local dropped = nil
    for id in pairs(E.owners) do
      local mr = al.getMemoryRecordByID(id)
      if mr and not mr.Active then
        dropped = dropped or {}
        dropped[#dropped + 1] = id
      end
    end
    if not dropped then return end
    for _, id in ipairs(dropped) do
      local list = E.owners[id]
      E.owners[id] = nil
      local w = E.wanted()
      local alist = E.alist
      if alist and alist &gt; 0x10000 then
        for _, name in ipairs(list) do
          if not w[name] then E.removeLook(alist, name) end
        end
        E.refreshPortrait()
      end
      E.note("reconciled: entry " .. id .. " is unchecked, released its looks")
    end
    if next(E.owners) == nil then
      if E.timer then pcall(function() E.timer.destroy() end) E.timer = nil end
      E.uninstallGate()
    end
  end

  function E.tick()
    if E.busy then return end
    E.busy = true
    local ok, err = pcall(function()
      if E.cooldown and os.clock() &lt; E.cooldown then return end
      E.reconcile()
      local wantList, wantPregnant = {}, false
      for name in pairs(E.wanted()) do
        wantList[#wantList + 1] = name
        if name == "Pregnant" then wantPregnant = true end
      end
      if #wantList == 0 then return end
      if not E.gateInstalled then
        local ok2 = E.installGate()
        if not ok2 then E.cooldown = os.clock() + 3 return end
      end
      local added = E.readAdded(E.alist)
      if added then
        local pending = false
        for _, name in ipairs(wantList) do
          if not E.has(added, E.TYPES[name]) then pending = true end
        end
        if wantPregnant and added[E.TYPES.Blessing] then pending = true end
        if not pending then return end
      end
      local psm = E.call(E.ga + E.OFF.psmGet, 0)
      if not psm or psm &lt; 0x10000 then
        E.failCount = (E.failCount or 0) + 1
        if E.failCount &gt;= 5 then
          E.note("gate unresponsive, resetting (game restarted?)")
          E.uninstallGate()
          E.failCount = 0
        end
        E.cooldown = os.clock() + 2
        return
      end
      E.failCount = 0
      local alist = readQword(psm + 0x50)
      if not alist or alist &lt; 0x10000 then E.cooldown = os.clock() + 2 return end
      E.alist = alist
      added = E.readAdded(alist) or {}
      if wantPregnant and added[E.TYPES.Blessing] then
        if E.hadBlessing == nil then E.hadBlessing = true end
        E.removedBlessing = true
        E.call(E.ga + E.OFF.remove, alist, E.TYPES.Blessing)
        E.note("removed InfertilityBlessing (will restore on disable)")
        return
      end
      if wantPregnant and E.hadBlessing == nil then E.hadBlessing = false end
      for _, name in ipairs(wantList) do
        local tv = E.TYPES[name]
        if not E.has(added, tv) then
          if E.ensureLoaded(tv) then
            E.call(E.ga + E.OFF.add, alist, tv, 0, 0)
            local a2 = E.readAdded(alist) or {}
            if a2[tv] then
              E.landedKey[tv] = nil
              E.failStreak = 0
              E.note("added " .. name)
              E.refreshPortrait()
            else
              local okb, how = E.bypassBlockerAdd(alist, tv)
              if okb then
                E.failStreak = 0
                E.note("added " .. name .. " (" .. how .. ")")
                E.refreshPortrait()
              else
                -- a game event can leave the condition half-removed (gone from
                -- the visible array, still in the internal dict) which no-ops
                -- every re-add; a full remove clears both, retry next tick
                E.call(E.ga + E.OFF.remove, alist, tv)
                E.failStreak = E.failStreak + 1
                E.note("add " .. name .. " did not land (" .. how .. "); cleared half-state, retrying")
                if E.failStreak &gt;= 10 then
                  E.note("10 consecutive failures, pausing 5s")
                  E.cooldown = os.clock() + 5
                  E.failStreak = 0
                end
              end
            end
          else
            E.note("waiting for " .. name .. " data to load")
          end
        end
      end
    end)
    if not ok then E.note("tick error: " .. tostring(err)) end
    E.busy = false
  end

  function E.enable(id, list)
    local ga = getAddressSafe("GameAssembly.dll")
    if not ga then error("SiNiSistar2 is not attached") end
    if not E.gateInstalled then
      local ok, err = E.installGate()
      if not ok then error("gate install failed: " .. tostring(err)) end
    end
    E.owners[id] = list
    E.cooldown, E.failCount, E.failStreak = nil, 0, 0
    if not E.timer then
      E.timer = createTimer(nil)
      E.timer.Interval = 300
      E.timer.OnTimer = E.tick
      E.timer.Enabled = true
    end
    E.note("enabled " .. id .. ": " .. table.concat(list, "+"))
  end

  function E.disable(id, list)
    E.owners[id] = nil
    pcall(function()
      if not E.gateInstalled or not E.ga then return end
      local psm = E.call(E.ga + E.OFF.psmGet, 0)
      local alist = nil
      if psm and psm &gt; 0x10000 then alist = readQword(psm + 0x50) end
      if alist and alist &gt; 0x10000 then
        local w = E.wanted()
        local changed = false
        for _, name in ipairs(list) do
          if not w[name] then
            E.removeLook(alist, name)
            E.note("removed " .. name)
            changed = true
          end
        end
        if changed then E.refreshPortrait() end
        if not w.Pregnant and E.removedBlessing then
          if E.hadBlessing and E.ensureLoaded(E.TYPES.Blessing) then
            E.call(E.ga + E.OFF.add, alist, E.TYPES.Blessing, 0, 0)
            E.note("restored InfertilityBlessing")
          end
          E.removedBlessing = false
          E.hadBlessing = nil
        end
      end
    end)
    if next(E.owners) == nil then
      if E.timer then pcall(function() E.timer.destroy() end) E.timer = nil end
      E.uninstallGate()
    end
    E.note("disabled " .. id .. ": " .. table.concat(list, "+"))
  end

  if OLD then
    E.log = OLD.log or E.log
    E.hadBlessing = OLD.hadBlessing
    E.removedBlessing = OLD.removedBlessing or false
    E.gateInstalled = OLD.gateInstalled or false
    E.ga = OLD.ga
    E.alist = OLD.alist
    E.timer = OLD.timer
    if E.timer then E.timer.OnTimer = E.tick end
    -- v2 refcounts (OLD.want) are untrusted (they leaked); owners start empty
    -- and each entry's enable line below re-registers itself
    E.note("engine upgraded to v3 (owner-set model)")
  end
end

_G.SS2Abn.enable(33, {"Breast","Pregnant"})
{$asm}

[DISABLE]
{$lua}
if syntaxcheck then return end
if _G.SS2Abn then _G.SS2Abn.disable(33, {"Breast","Pregnant"}) end
{$asm}
</AssemblerScript>
        </CheatEntry>
      </CheatEntries>
    </CheatEntry>
  </CheatEntries>
  <UserdefinedSymbols/>
  <LuaScript>
</LuaScript>
</CheatTable>
