<?xml version='1.0' encoding='utf-8'?>
<CheatTable CheatEngineTableVersion="45">
  <CheatEntries><CheatEntry>
      <ID>1</ID>
      <Description>"[ATTACH / ALL OFF] Attach to ThreeKingdom.exe + disable everything"</Description>
      <Color>00A5FF</Color>
      <VariableType>Auto Assembler Script</VariableType>
      <AssemblerScript>

{ Game   : ThreeKingdom.exe
  Author : Black_wolf
　CheatVer:1.0.13-001-002

  Memo: ゲームバージョンは1.0.13 / Steam build 26159462
　　　　ゲームエンジンはUnity 2021.3.43f1c1（ビルドハッシュ fc9da3dccad9）
	スクリプト実行方式は、IL2CPP（global-metadata v31）
	GameAssembly.dll PE timestamp 0x6AD9EEC1 / image size 0x67DC000

　　　　Beebyteで難読化されてた。使ったのは3.13かな
	でもBeebyteってあんま意味ないよね。ラインセンス払って意味ないことしてもなー

	それより書き換えるところが多くて大変だったー。こんな大きなCT作ったの初めてだよ
	バージョンアップしても追従しないかも...

	ゲームのコードは起動時にすべてメモリに読み込まれているわけではなく、
	実行中に少しずつ読み込まれていく（使える状態になる）ことがわかったので、V2で対応した。

	1.0.4になってしまったが、作ったばかりだったのとAOB対策していたのであっという間にV3で対応できた
	コードが汚ちゃなくなったのでちょいと整理もした。VS Codeは便利だね

	すごい勢いでバージョンアップしている。が、診断機能つけているので何が動かないかの特定は早くなった
	関数も整理したので、解析後の変更はいうほど時間はかからない！
	https://steamdb.info/depot/3020511/manifests/

	いろいろバグやら改善しようとしている気概は買うが、開発者は落ち着け。バグ直そうとしてバグを生むとか品質が最悪だぞ
	もうあかんかもね。このまま品質を安定させられないならそっぽ向かれるぞ。そんなゲーム大量に見てきたよ

	とうとう更新履歴(1.0.11)とゲーム表記バージョン(1.0.10)が不一致になるという品質がどんどん落ちだしている
}

[ENABLE]
{$lua}
if syntaxcheck then return end
HV.oneShot(memrec, function() HV.disableAll(memrec) end)
{$asm}
[DISABLE]
</AssemblerScript>
    </CheatEntry>
    <CheatEntry>
      <ID>2</ID>
      <Description>"0. Settings &amp; README"</Description>
      <Options moManualExpandCollapse="1" />
      <Color>FFFF00</Color>
      <GroupHeader>1</GroupHeader>
      <CheatEntries>
        <CheatEntry>
          <ID>3</ID>
          <Description>"Language / 言語設定"</Description>
          <Options moManualExpandCollapse="1" />
          <Color>FFFF00</Color>
          <GroupHeader>1</GroupHeader>
          <CheatEntries>
            <CheatEntry>
              <ID>4</ID>
              <Description>"English (default)"</Description>
              <Color>00A5FF</Color>
              <VariableType>Auto Assembler Script</VariableType>
              <AssemblerScript>[ENABLE]
{$lua}
if syntaxcheck then return end
HV.oneShot(memrec, function() HV.setLang('en') end)
{$asm}
[DISABLE]
</AssemblerScript>
            </CheatEntry>
            <CheatEntry>
              <ID>5</ID>
              <Description>"日本語 / Japanese"</Description>
              <Color>00A5FF</Color>
              <VariableType>Auto Assembler Script</VariableType>
              <AssemblerScript>[ENABLE]
{$lua}
if syntaxcheck then return end
HV.oneShot(memrec, function() HV.setLang('ja') end)
{$asm}
[DISABLE]
</AssemblerScript>
            </CheatEntry>
          </CheatEntries>
        </CheatEntry>
        <CheatEntry>
          <ID>6</ID>
          <Description>"README"</Description>
          <Options moManualExpandCollapse="1" />
          <Color>FFFF00</Color>
          <GroupHeader>1</GroupHeader>
          <CheatEntries>
            <CheatEntry>
              <ID>7</ID>
              <Description>"1) Start the game, open this table (allow its Lua script), then run [ATTACH / ALL OFF] at the top."</Description>
              <GroupHeader>1</GroupHeader>
            <Options moManualExpandCollapse="1" /></CheatEntry>
            <CheatEntry>
              <ID>8</ID>
              <Description>"2) Made for game v1.0.13 (Steam build 26159462). Game code is located by AOB scan; on other builds a warning is shown and features whose code is not found are disabled."</Description>
              <GroupHeader>1</GroupHeader>
            <Options moManualExpandCollapse="1" /></CheatEntry>
            <CheatEntry>
              <ID>9</ID>
              <Description>"3) Orange = script (check to run / toggle), cyan = expandable group, no color = value (double-click to edit)."</Description>
              <GroupHeader>1</GroupHeader>
            <Options moManualExpandCollapse="1" /></CheatEntry>
            <CheatEntry>
              <ID>10</ID>
              <Description>"4) Messages appear in the Lua Engine window (0. &gt; Diagnostics &gt; Lua Engine)."</Description>
              <GroupHeader>1</GroupHeader>
            <Options moManualExpandCollapse="1" /></CheatEntry>
            <CheatEntry>
              <ID>11</ID>
              <Description>"5) Save your game before using editor / one-shot actions."</Description>
              <GroupHeader>1</GroupHeader>
            <Options moManualExpandCollapse="1" /></CheatEntry>
          </CheatEntries>
        </CheatEntry>
        <CheatEntry>
          <ID>12</ID>
          <Description>"Diagnostics (only when the table does not work)"</Description>
          <Options moManualExpandCollapse="1" />
          <Color>FFFF00</Color>
          <GroupHeader>1</GroupHeader>
          <CheatEntries>
            <CheatEntry>
              <ID>13</ID>
              <Description>"Lua Engine (check = open / uncheck = close)"</Description>
              <Color>00A5FF</Color>
              <VariableType>Auto Assembler Script</VariableType>
              <AssemblerScript>[ENABLE]
{$lua}
if syntaxcheck then return end
HV.openLuaEngine()
{$asm}
[DISABLE]
{$lua}
if syntaxcheck then return end
if HV then HV.closeLuaEngine() end
{$asm}
</AssemblerScript>
            </CheatEntry>
            <CheatEntry>
              <ID>14</ID>
              <Description>"AOB scan self-test (1-2 min, CE is busy; prints to Lua Engine)"</Description>
              <Color>00A5FF</Color>
              <VariableType>Auto Assembler Script</VariableType>
              <AssemblerScript>[ENABLE]
{$lua}
if syntaxcheck then return end
HV.oneShot(memrec, function() HV.scanSelfTest() end)
{$asm}
[DISABLE]
</AssemblerScript>
            </CheatEntry>
            <CheatEntry>
              <ID>15</ID>
              <Description>"Environment / connection info (CE, process, module, build)"</Description>
              <Color>00A5FF</Color>
              <VariableType>Auto Assembler Script</VariableType>
              <AssemblerScript>[ENABLE]
{$lua}
if syntaxcheck then return end
HV.oneShot(memrec, function() HV.envReport() end)
{$asm}
[DISABLE]
</AssemblerScript>
            </CheatEntry>
            <CheatEntry>
              <ID>16</ID>
              <Description>"Status: unresolved code / active hooks / active features"</Description>
              <Color>00A5FF</Color>
              <VariableType>Auto Assembler Script</VariableType>
              <AssemblerScript>[ENABLE]
{$lua}
if syntaxcheck then return end
HV.oneShot(memrec, function() HV.statusReport() end)
{$asm}
[DISABLE]
</AssemblerScript>
            </CheatEntry>
            <CheatEntry>
              <ID>17</ID>
              <Description>"Game code not loaded into memory yet (prints to Lua Engine)"</Description>
              <Color>00A5FF</Color>
              <VariableType>Auto Assembler Script</VariableType>
              <AssemblerScript>[ENABLE]
{$lua}
if syntaxcheck then return end
HV.oneShot(memrec, function() HV.pendingReport() end)
{$asm}
[DISABLE]
</AssemblerScript>
            </CheatEntry>
          </CheatEntries>
        </CheatEntry>
      </CheatEntries>
    </CheatEntry>
    <CheatEntry>
      <ID>100</ID>
      <Description>"01. Gameplay"</Description>
      <Options moManualExpandCollapse="1" />
      <Color>FFFF00</Color>
      <GroupHeader>1</GroupHeader>
      <CheatEntries>
        <CheatEntry>
          <ID>101</ID>
          <Description>"Self invincible (player hero: duel / debate / war)"</Description>
          <Color>00A5FF</Color>
          <VariableType>Auto Assembler Script</VariableType>
          <AssemblerScript>[ENABLE]
{$lua}
if syntaxcheck then return end
HV.feature('godSelf', true)
{$asm}
[DISABLE]
{$lua}
if syntaxcheck then return end
if HV then HV.feature('godSelf', false) end
{$asm}
</AssemblerScript>
        </CheatEntry>
        <CheatEntry>
          <ID>102</ID>
          <Description>"Infinite action (AP never decreases: my side in duel &amp; debate)"</Description>
          <Color>00A5FF</Color>
          <VariableType>Auto Assembler Script</VariableType>
          <AssemblerScript>[ENABLE]
{$lua}
if syntaxcheck then return end
HV.feature('infAP', true)
{$asm}
[DISABLE]
{$lua}
if syntaxcheck then return end
if HV then HV.feature('infAP', false) end
{$asm}
</AssemblerScript>
        </CheatEntry>
        <CheatEntry>
          <ID>103</ID>
          <Description>"Player status always max (stamina / mood, no drunk / poison)"</Description>
          <Color>00A5FF</Color>
          <VariableType>Auto Assembler Script</VariableType>
          <AssemblerScript>[ENABLE]
{$lua}
if syntaxcheck then return end
HV.feature('playerStat', true)
{$asm}
[DISABLE]
{$lua}
if syntaxcheck then return end
if HV then HV.feature('playerStat', false) end
{$asm}
</AssemblerScript>
        </CheatEntry>
        <CheatEntry>
          <ID>104</ID>
          <Description>"Max movement speed (world map, player)"</Description>
          <Options moHideChildren="1" />
          <Color>00A5FF</Color>
          <VariableType>Auto Assembler Script</VariableType>
          <AssemblerScript>[ENABLE]
{$lua}
if syntaxcheck then return end
HV.feature('speed', true)
{$asm}
[DISABLE]
{$lua}
if syntaxcheck then return end
if HV then HV.feature('speed', false) end
{$asm}
</AssemblerScript>
          <CheatEntries>
            <CheatEntry>
              <ID>105</ID>
              <Description>"Speed multiplier"</Description>
              <VariableType>Float</VariableType>
              <Address>hvVars+20</Address>
            </CheatEntry>
          </CheatEntries>
        </CheatEntry>
        <CheatEntry>
          <ID>106</ID>
          <Description>"Teleport (right-click destination = instant)"</Description>
          <Color>00A5FF</Color>
          <VariableType>Auto Assembler Script</VariableType>
          <AssemblerScript>[ENABLE]
{$lua}
if syntaxcheck then return end
HV.feature('teleport', true)
{$asm}
[DISABLE]
{$lua}
if syntaxcheck then return end
if HV then HV.feature('teleport', false) end
{$asm}
</AssemblerScript>
        </CheatEntry>
        </CheatEntries>
    </CheatEntry>
    <CheatEntry>
      <ID>7000</ID>
      <Description>"02. Player, heroes &amp; pets"</Description>
      <Options moManualExpandCollapse="1" />
      <Color>FFFF00</Color>
      <GroupHeader>1</GroupHeader>
      <CheatEntries>
        <CheatEntry>
          <ID>7001</ID>
          <Description>"Player editor"</Description>
          <Options moManualExpandCollapse="1" />
          <Color>FFFF00</Color>
          <GroupHeader>1</GroupHeader>
          <CheatEntries>
            <CheatEntry>
              <ID>7002</ID>
              <Description>"Basic"</Description>
              <Options moManualExpandCollapse="1" />
              <Color>FFFF00</Color>
              <GroupHeader>1</GroupHeader>
              <CheatEntries>
                <CheatEntry>
                  <ID>7003</ID>
                  <Description>"Money"</Description>
                  <VariableType>4 Bytes</VariableType>
                  <ShowAsSigned>1</ShowAsSigned>
                  <Address>hvPtrs+0</Address>
                  <Offsets>
                    <Offset>308</Offset>
                  </Offsets>
                </CheatEntry>
                <CheatEntry>
                  <ID>7004</ID>
                  <Description>"Age"</Description>
                  <VariableType>4 Bytes</VariableType>
                  <ShowAsSigned>1</ShowAsSigned>
                  <Address>hvPtrs+0</Address>
                  <Offsets>
                    <Offset>84</Offset>
                  </Offsets>
                </CheatEntry>
                <CheatEntry>
                  <ID>7005</ID>
                  <Description>"Lifespan"</Description>
                  <VariableType>4 Bytes</VariableType>
                  <ShowAsSigned>1</ShowAsSigned>
                  <Address>hvPtrs+0</Address>
                  <Offsets>
                    <Offset>80</Offset>
                  </Offsets>
                </CheatEntry>
                <CheatEntry>
                  <ID>7006</ID>
                  <Description>"Birth year"</Description>
                  <VariableType>4 Bytes</VariableType>
                  <ShowAsSigned>1</ShowAsSigned>
                  <Address>hvPtrs+0</Address>
                  <Offsets>
                    <Offset>78</Offset>
                  </Offsets>
                </CheatEntry>
                <CheatEntry>
                  <ID>7007</ID>
                  <Description>"Morality"</Description>
                  <VariableType>4 Bytes</VariableType>
                  <ShowAsSigned>1</ShowAsSigned>
                  <Address>hvPtrs+0</Address>
                  <Offsets>
                    <Offset>68</Offset>
                  </Offsets>
                </CheatEntry>
                <CheatEntry>
                  <ID>7008</ID>
                  <Description>"Righteousness (-50000..50000)"</Description>
                  <VariableType>4 Bytes</VariableType>
                  <ShowAsSigned>1</ShowAsSigned>
                  <Address>hvPtrs+8</Address>
                  <Offsets>
                    <Offset>F4</Offset>
                  </Offsets>
                </CheatEntry>
              </CheatEntries>
            </CheatEntry>
            <CheatEntry>
              <ID>7009</ID>
              <Description>"Condition"</Description>
              <Options moManualExpandCollapse="1" />
              <Color>FFFF00</Color>
              <GroupHeader>1</GroupHeader>
              <CheatEntries>
                <CheatEntry>
                  <ID>7010</ID>
                  <Description>"Stamina"</Description>
                  <VariableType>4 Bytes</VariableType>
                  <ShowAsSigned>1</ShowAsSigned>
                  <Address>hvPtrs+0</Address>
                  <Offsets>
                    <Offset>1A0</Offset>
                  </Offsets>
                </CheatEntry>
                <CheatEntry>
                  <ID>7011</ID>
                  <Description>"Stamina max bonus (max = 800 + bonus + 2*(force+will))"</Description>
                  <VariableType>4 Bytes</VariableType>
                  <ShowAsSigned>1</ShowAsSigned>
                  <Address>hvPtrs+0</Address>
                  <Offsets>
                    <Offset>1A4</Offset>
                  </Offsets>
                </CheatEntry>
                <CheatEntry>
                  <ID>7012</ID>
                  <Description>"Mood (0-1000)"</Description>
                  <VariableType>4 Bytes</VariableType>
                  <ShowAsSigned>1</ShowAsSigned>
                  <Address>hvPtrs+0</Address>
                  <Offsets>
                    <Offset>19C</Offset>
                  </Offsets>
                </CheatEntry>
                <CheatEntry>
                  <ID>7013</ID>
                  <Description>"Drunk (0-1000)"</Description>
                  <VariableType>4 Bytes</VariableType>
                  <ShowAsSigned>1</ShowAsSigned>
                  <Address>hvPtrs+0</Address>
                  <Offsets>
                    <Offset>194</Offset>
                  </Offsets>
                </CheatEntry>
                <CheatEntry>
                  <ID>7014</ID>
                  <Description>"Poison"</Description>
                  <VariableType>4 Bytes</VariableType>
                  <ShowAsSigned>1</ShowAsSigned>
                  <Address>hvPtrs+0</Address>
                  <Offsets>
                    <Offset>198</Offset>
                  </Offsets>
                </CheatEntry>
              </CheatEntries>
            </CheatEntry>
            <CheatEntry>
              <ID>7015</ID>
              <Description>"Abilities"</Description>
              <Options moManualExpandCollapse="1" />
              <Color>FFFF00</Color>
              <GroupHeader>1</GroupHeader>
              <CheatEntries>
                <CheatEntry>
                  <ID>7016</ID>
                  <Description>"Base attributes"</Description>
                  <Options moManualExpandCollapse="1" />
                  <Color>FFFF00</Color>
                  <GroupHeader>1</GroupHeader>
                  <CheatEntries>
                    <CheatEntry>
                      <ID>7017</ID>
                      <Description>"Leadership (rule)"</Description>
                      <VariableType>4 Bytes</VariableType>
                      <ShowAsSigned>1</ShowAsSigned>
                      <Address>hvPtrs+10</Address>
                      <Offsets>
                        <Offset>20</Offset>
                      </Offsets>
                    </CheatEntry>
                    <CheatEntry>
                      <ID>7018</ID>
                      <Description>"Force"</Description>
                      <VariableType>4 Bytes</VariableType>
                      <ShowAsSigned>1</ShowAsSigned>
                      <Address>hvPtrs+10</Address>
                      <Offsets>
                        <Offset>24</Offset>
                      </Offsets>
                    </CheatEntry>
                    <CheatEntry>
                      <ID>7019</ID>
                      <Description>"Intelligence (wise)"</Description>
                      <VariableType>4 Bytes</VariableType>
                      <ShowAsSigned>1</ShowAsSigned>
                      <Address>hvPtrs+10</Address>
                      <Offsets>
                        <Offset>28</Offset>
                      </Offsets>
                    </CheatEntry>
                    <CheatEntry>
                      <ID>7020</ID>
                      <Description>"Politics"</Description>
                      <VariableType>4 Bytes</VariableType>
                      <ShowAsSigned>1</ShowAsSigned>
                      <Address>hvPtrs+10</Address>
                      <Offsets>
                        <Offset>2C</Offset>
                      </Offsets>
                    </CheatEntry>
                    <CheatEntry>
                      <ID>7021</ID>
                      <Description>"Charm"</Description>
                      <VariableType>4 Bytes</VariableType>
                      <ShowAsSigned>1</ShowAsSigned>
                      <Address>hvPtrs+10</Address>
                      <Offsets>
                        <Offset>30</Offset>
                      </Offsets>
                    </CheatEntry>
                    <CheatEntry>
                      <ID>7022</ID>
                      <Description>"Will"</Description>
                      <VariableType>4 Bytes</VariableType>
                      <ShowAsSigned>1</ShowAsSigned>
                      <Address>hvPtrs+10</Address>
                      <Offsets>
                        <Offset>34</Offset>
                      </Offsets>
                    </CheatEntry>
                  </CheatEntries>
                </CheatEntry>
                <CheatEntry>
                  <ID>7023</ID>
                  <Description>"Attribute EXP"</Description>
                  <Options moManualExpandCollapse="1" />
                  <Color>FFFF00</Color>
                  <GroupHeader>1</GroupHeader>
                  <CheatEntries>
                    <CheatEntry>
                      <ID>7024</ID>
                      <Description>"Leadership (rule)"</Description>
                      <VariableType>4 Bytes</VariableType>
                      <ShowAsSigned>1</ShowAsSigned>
                      <Address>hvPtrs+18</Address>
                      <Offsets>
                        <Offset>20</Offset>
                      </Offsets>
                    </CheatEntry>
                    <CheatEntry>
                      <ID>7025</ID>
                      <Description>"Force"</Description>
                      <VariableType>4 Bytes</VariableType>
                      <ShowAsSigned>1</ShowAsSigned>
                      <Address>hvPtrs+18</Address>
                      <Offsets>
                        <Offset>24</Offset>
                      </Offsets>
                    </CheatEntry>
                    <CheatEntry>
                      <ID>7026</ID>
                      <Description>"Intelligence (wise)"</Description>
                      <VariableType>4 Bytes</VariableType>
                      <ShowAsSigned>1</ShowAsSigned>
                      <Address>hvPtrs+18</Address>
                      <Offsets>
                        <Offset>28</Offset>
                      </Offsets>
                    </CheatEntry>
                    <CheatEntry>
                      <ID>7027</ID>
                      <Description>"Politics"</Description>
                      <VariableType>4 Bytes</VariableType>
                      <ShowAsSigned>1</ShowAsSigned>
                      <Address>hvPtrs+18</Address>
                      <Offsets>
                        <Offset>2C</Offset>
                      </Offsets>
                    </CheatEntry>
                    <CheatEntry>
                      <ID>7028</ID>
                      <Description>"Charm"</Description>
                      <VariableType>4 Bytes</VariableType>
                      <ShowAsSigned>1</ShowAsSigned>
                      <Address>hvPtrs+18</Address>
                      <Offsets>
                        <Offset>30</Offset>
                      </Offsets>
                    </CheatEntry>
                    <CheatEntry>
                      <ID>7029</ID>
                      <Description>"Will"</Description>
                      <VariableType>4 Bytes</VariableType>
                      <ShowAsSigned>1</ShowAsSigned>
                      <Address>hvPtrs+18</Address>
                      <Offsets>
                        <Offset>34</Offset>
                      </Offsets>
                    </CheatEntry>
                  </CheatEntries>
                </CheatEntry>
                <CheatEntry>
                  <ID>7030</ID>
                  <Description>"Aptitude (talent)"</Description>
                  <Options moManualExpandCollapse="1" />
                  <Color>FFFF00</Color>
                  <GroupHeader>1</GroupHeader>
                  <CheatEntries>
                    <CheatEntry>
                      <ID>7031</ID>
                      <Description>"Leadership (rule)"</Description>
                      <VariableType>4 Bytes</VariableType>
                      <ShowAsSigned>1</ShowAsSigned>
                      <Address>hvPtrs+20</Address>
                      <Offsets>
                        <Offset>20</Offset>
                      </Offsets>
                    </CheatEntry>
                    <CheatEntry>
                      <ID>7032</ID>
                      <Description>"Force"</Description>
                      <VariableType>4 Bytes</VariableType>
                      <ShowAsSigned>1</ShowAsSigned>
                      <Address>hvPtrs+20</Address>
                      <Offsets>
                        <Offset>24</Offset>
                      </Offsets>
                    </CheatEntry>
                    <CheatEntry>
                      <ID>7033</ID>
                      <Description>"Intelligence (wise)"</Description>
                      <VariableType>4 Bytes</VariableType>
                      <ShowAsSigned>1</ShowAsSigned>
                      <Address>hvPtrs+20</Address>
                      <Offsets>
                        <Offset>28</Offset>
                      </Offsets>
                    </CheatEntry>
                    <CheatEntry>
                      <ID>7034</ID>
                      <Description>"Politics"</Description>
                      <VariableType>4 Bytes</VariableType>
                      <ShowAsSigned>1</ShowAsSigned>
                      <Address>hvPtrs+20</Address>
                      <Offsets>
                        <Offset>2C</Offset>
                      </Offsets>
                    </CheatEntry>
                    <CheatEntry>
                      <ID>7035</ID>
                      <Description>"Charm"</Description>
                      <VariableType>4 Bytes</VariableType>
                      <ShowAsSigned>1</ShowAsSigned>
                      <Address>hvPtrs+20</Address>
                      <Offsets>
                        <Offset>30</Offset>
                      </Offsets>
                    </CheatEntry>
                    <CheatEntry>
                      <ID>7036</ID>
                      <Description>"Will"</Description>
                      <VariableType>4 Bytes</VariableType>
                      <ShowAsSigned>1</ShowAsSigned>
                      <Address>hvPtrs+20</Address>
                      <Offsets>
                        <Offset>34</Offset>
                      </Offsets>
                    </CheatEntry>
                  </CheatEntries>
                </CheatEntry>
              </CheatEntries>
            </CheatEntry>
            <CheatEntry>
              <ID>7037</ID>
              <Description>"Professions"</Description>
              <Options moManualExpandCollapse="1" />
              <Color>FFFF00</Color>
              <GroupHeader>1</GroupHeader>
              <CheatEntries>
                <CheatEntry>
                  <ID>7038</ID>
                  <Description>"Martial (7)"</Description>
                  <Options moManualExpandCollapse="1" />
                  <Color>FFFF00</Color>
                  <GroupHeader>1</GroupHeader>
                  <CheatEntries>
                    <CheatEntry>
                      <ID>7039</ID>
                      <Description>"Sword level"</Description>
                      <VariableType>4 Bytes</VariableType>
                      <ShowAsSigned>1</ShowAsSigned>
                      <Address>hvPtrs+28</Address>
                      <Offsets>
                        <Offset>20</Offset>
                      </Offsets>
                    </CheatEntry>
                    <CheatEntry>
                      <ID>7040</ID>
                      <Description>"Sword EXP"</Description>
                      <VariableType>4 Bytes</VariableType>
                      <ShowAsSigned>1</ShowAsSigned>
                      <Address>hvPtrs+30</Address>
                      <Offsets>
                        <Offset>20</Offset>
                      </Offsets>
                    </CheatEntry>
                    <CheatEntry>
                      <ID>7041</ID>
                      <Description>"Spear level"</Description>
                      <VariableType>4 Bytes</VariableType>
                      <ShowAsSigned>1</ShowAsSigned>
                      <Address>hvPtrs+28</Address>
                      <Offsets>
                        <Offset>24</Offset>
                      </Offsets>
                    </CheatEntry>
                    <CheatEntry>
                      <ID>7042</ID>
                      <Description>"Spear EXP"</Description>
                      <VariableType>4 Bytes</VariableType>
                      <ShowAsSigned>1</ShowAsSigned>
                      <Address>hvPtrs+30</Address>
                      <Offsets>
                        <Offset>24</Offset>
                      </Offsets>
                    </CheatEntry>
                    <CheatEntry>
                      <ID>7043</ID>
                      <Description>"Cavalry level"</Description>
                      <VariableType>4 Bytes</VariableType>
                      <ShowAsSigned>1</ShowAsSigned>
                      <Address>hvPtrs+28</Address>
                      <Offsets>
                        <Offset>28</Offset>
                      </Offsets>
                    </CheatEntry>
                    <CheatEntry>
                      <ID>7044</ID>
                      <Description>"Cavalry EXP"</Description>
                      <VariableType>4 Bytes</VariableType>
                      <ShowAsSigned>1</ShowAsSigned>
                      <Address>hvPtrs+30</Address>
                      <Offsets>
                        <Offset>28</Offset>
                      </Offsets>
                    </CheatEntry>
                    <CheatEntry>
                      <ID>7045</ID>
                      <Description>"Archer level"</Description>
                      <VariableType>4 Bytes</VariableType>
                      <ShowAsSigned>1</ShowAsSigned>
                      <Address>hvPtrs+28</Address>
                      <Offsets>
                        <Offset>2C</Offset>
                      </Offsets>
                    </CheatEntry>
                    <CheatEntry>
                      <ID>7046</ID>
                      <Description>"Archer EXP"</Description>
                      <VariableType>4 Bytes</VariableType>
                      <ShowAsSigned>1</ShowAsSigned>
                      <Address>hvPtrs+30</Address>
                      <Offsets>
                        <Offset>2C</Offset>
                      </Offsets>
                    </CheatEntry>
                    <CheatEntry>
                      <ID>7047</ID>
                      <Description>"Machine level"</Description>
                      <VariableType>4 Bytes</VariableType>
                      <ShowAsSigned>1</ShowAsSigned>
                      <Address>hvPtrs+28</Address>
                      <Offsets>
                        <Offset>30</Offset>
                      </Offsets>
                    </CheatEntry>
                    <CheatEntry>
                      <ID>7048</ID>
                      <Description>"Machine EXP"</Description>
                      <VariableType>4 Bytes</VariableType>
                      <ShowAsSigned>1</ShowAsSigned>
                      <Address>hvPtrs+30</Address>
                      <Offsets>
                        <Offset>30</Offset>
                      </Offsets>
                    </CheatEntry>
                    <CheatEntry>
                      <ID>7049</ID>
                      <Description>"Marine level"</Description>
                      <VariableType>4 Bytes</VariableType>
                      <ShowAsSigned>1</ShowAsSigned>
                      <Address>hvPtrs+28</Address>
                      <Offsets>
                        <Offset>34</Offset>
                      </Offsets>
                    </CheatEntry>
                    <CheatEntry>
                      <ID>7050</ID>
                      <Description>"Marine EXP"</Description>
                      <VariableType>4 Bytes</VariableType>
                      <ShowAsSigned>1</ShowAsSigned>
                      <Address>hvPtrs+30</Address>
                      <Offsets>
                        <Offset>34</Offset>
                      </Offsets>
                    </CheatEntry>
                    <CheatEntry>
                      <ID>7051</ID>
                      <Description>"Military level"</Description>
                      <VariableType>4 Bytes</VariableType>
                      <ShowAsSigned>1</ShowAsSigned>
                      <Address>hvPtrs+28</Address>
                      <Offsets>
                        <Offset>38</Offset>
                      </Offsets>
                    </CheatEntry>
                    <CheatEntry>
                      <ID>7052</ID>
                      <Description>"Military EXP"</Description>
                      <VariableType>4 Bytes</VariableType>
                      <ShowAsSigned>1</ShowAsSigned>
                      <Address>hvPtrs+30</Address>
                      <Offsets>
                        <Offset>38</Offset>
                      </Offsets>
                    </CheatEntry>
                  </CheatEntries>
                </CheatEntry>
                <CheatEntry>
                  <ID>7053</ID>
                  <Description>"Domestic (8)"</Description>
                  <Options moManualExpandCollapse="1" />
                  <Color>FFFF00</Color>
                  <GroupHeader>1</GroupHeader>
                  <CheatEntries>
                    <CheatEntry>
                      <ID>7054</ID>
                      <Description>"Commerce level"</Description>
                      <VariableType>4 Bytes</VariableType>
                      <ShowAsSigned>1</ShowAsSigned>
                      <Address>hvPtrs+28</Address>
                      <Offsets>
                        <Offset>3C</Offset>
                      </Offsets>
                    </CheatEntry>
                    <CheatEntry>
                      <ID>7055</ID>
                      <Description>"Commerce EXP"</Description>
                      <VariableType>4 Bytes</VariableType>
                      <ShowAsSigned>1</ShowAsSigned>
                      <Address>hvPtrs+30</Address>
                      <Offsets>
                        <Offset>3C</Offset>
                      </Offsets>
                    </CheatEntry>
                    <CheatEntry>
                      <ID>7056</ID>
                      <Description>"Agriculture level"</Description>
                      <VariableType>4 Bytes</VariableType>
                      <ShowAsSigned>1</ShowAsSigned>
                      <Address>hvPtrs+28</Address>
                      <Offsets>
                        <Offset>40</Offset>
                      </Offsets>
                    </CheatEntry>
                    <CheatEntry>
                      <ID>7057</ID>
                      <Description>"Agriculture EXP"</Description>
                      <VariableType>4 Bytes</VariableType>
                      <ShowAsSigned>1</ShowAsSigned>
                      <Address>hvPtrs+30</Address>
                      <Offsets>
                        <Offset>40</Offset>
                      </Offsets>
                    </CheatEntry>
                    <CheatEntry>
                      <ID>7058</ID>
                      <Description>"Construct level"</Description>
                      <VariableType>4 Bytes</VariableType>
                      <ShowAsSigned>1</ShowAsSigned>
                      <Address>hvPtrs+28</Address>
                      <Offsets>
                        <Offset>44</Offset>
                      </Offsets>
                    </CheatEntry>
                    <CheatEntry>
                      <ID>7059</ID>
                      <Description>"Construct EXP"</Description>
                      <VariableType>4 Bytes</VariableType>
                      <ShowAsSigned>1</ShowAsSigned>
                      <Address>hvPtrs+30</Address>
                      <Offsets>
                        <Offset>44</Offset>
                      </Offsets>
                    </CheatEntry>
                    <CheatEntry>
                      <ID>7060</ID>
                      <Description>"Conscript level"</Description>
                      <VariableType>4 Bytes</VariableType>
                      <ShowAsSigned>1</ShowAsSigned>
                      <Address>hvPtrs+28</Address>
                      <Offsets>
                        <Offset>48</Offset>
                      </Offsets>
                    </CheatEntry>
                    <CheatEntry>
                      <ID>7061</ID>
                      <Description>"Conscript EXP"</Description>
                      <VariableType>4 Bytes</VariableType>
                      <ShowAsSigned>1</ShowAsSigned>
                      <Address>hvPtrs+30</Address>
                      <Offsets>
                        <Offset>48</Offset>
                      </Offsets>
                    </CheatEntry>
                    <CheatEntry>
                      <ID>7062</ID>
                      <Description>"Train level"</Description>
                      <VariableType>4 Bytes</VariableType>
                      <ShowAsSigned>1</ShowAsSigned>
                      <Address>hvPtrs+28</Address>
                      <Offsets>
                        <Offset>4C</Offset>
                      </Offsets>
                    </CheatEntry>
                    <CheatEntry>
                      <ID>7063</ID>
                      <Description>"Train EXP"</Description>
                      <VariableType>4 Bytes</VariableType>
                      <ShowAsSigned>1</ShowAsSigned>
                      <Address>hvPtrs+30</Address>
                      <Offsets>
                        <Offset>4C</Offset>
                      </Offsets>
                    </CheatEntry>
                    <CheatEntry>
                      <ID>7064</ID>
                      <Description>"Security level"</Description>
                      <VariableType>4 Bytes</VariableType>
                      <ShowAsSigned>1</ShowAsSigned>
                      <Address>hvPtrs+28</Address>
                      <Offsets>
                        <Offset>50</Offset>
                      </Offsets>
                    </CheatEntry>
                    <CheatEntry>
                      <ID>7065</ID>
                      <Description>"Security EXP"</Description>
                      <VariableType>4 Bytes</VariableType>
                      <ShowAsSigned>1</ShowAsSigned>
                      <Address>hvPtrs+30</Address>
                      <Offsets>
                        <Offset>50</Offset>
                      </Offsets>
                    </CheatEntry>
                    <CheatEntry>
                      <ID>7066</ID>
                      <Description>"Patrol level"</Description>
                      <VariableType>4 Bytes</VariableType>
                      <ShowAsSigned>1</ShowAsSigned>
                      <Address>hvPtrs+28</Address>
                      <Offsets>
                        <Offset>54</Offset>
                      </Offsets>
                    </CheatEntry>
                    <CheatEntry>
                      <ID>7067</ID>
                      <Description>"Patrol EXP"</Description>
                      <VariableType>4 Bytes</VariableType>
                      <ShowAsSigned>1</ShowAsSigned>
                      <Address>hvPtrs+30</Address>
                      <Offsets>
                        <Offset>54</Offset>
                      </Offsets>
                    </CheatEntry>
                    <CheatEntry>
                      <ID>7068</ID>
                      <Description>"Wall level"</Description>
                      <VariableType>4 Bytes</VariableType>
                      <ShowAsSigned>1</ShowAsSigned>
                      <Address>hvPtrs+28</Address>
                      <Offsets>
                        <Offset>58</Offset>
                      </Offsets>
                    </CheatEntry>
                    <CheatEntry>
                      <ID>7069</ID>
                      <Description>"Wall EXP"</Description>
                      <VariableType>4 Bytes</VariableType>
                      <ShowAsSigned>1</ShowAsSigned>
                      <Address>hvPtrs+30</Address>
                      <Offsets>
                        <Offset>58</Offset>
                      </Offsets>
                    </CheatEntry>
                  </CheatEntries>
                </CheatEntry>
                <CheatEntry>
                  <ID>7070</ID>
                  <Description>"Special (9)"</Description>
                  <Options moManualExpandCollapse="1" />
                  <Color>FFFF00</Color>
                  <GroupHeader>1</GroupHeader>
                  <CheatEntries>
                    <CheatEntry>
                      <ID>7071</ID>
                      <Description>"Explore level"</Description>
                      <VariableType>4 Bytes</VariableType>
                      <ShowAsSigned>1</ShowAsSigned>
                      <Address>hvPtrs+28</Address>
                      <Offsets>
                        <Offset>5C</Offset>
                      </Offsets>
                    </CheatEntry>
                    <CheatEntry>
                      <ID>7072</ID>
                      <Description>"Explore EXP"</Description>
                      <VariableType>4 Bytes</VariableType>
                      <ShowAsSigned>1</ShowAsSigned>
                      <Address>hvPtrs+30</Address>
                      <Offsets>
                        <Offset>5C</Offset>
                      </Offsets>
                    </CheatEntry>
                    <CheatEntry>
                      <ID>7073</ID>
                      <Description>"Diplomacy level"</Description>
                      <VariableType>4 Bytes</VariableType>
                      <ShowAsSigned>1</ShowAsSigned>
                      <Address>hvPtrs+28</Address>
                      <Offsets>
                        <Offset>60</Offset>
                      </Offsets>
                    </CheatEntry>
                    <CheatEntry>
                      <ID>7074</ID>
                      <Description>"Diplomacy EXP"</Description>
                      <VariableType>4 Bytes</VariableType>
                      <ShowAsSigned>1</ShowAsSigned>
                      <Address>hvPtrs+30</Address>
                      <Offsets>
                        <Offset>60</Offset>
                      </Offsets>
                    </CheatEntry>
                    <CheatEntry>
                      <ID>7075</ID>
                      <Description>"Persuade level"</Description>
                      <VariableType>4 Bytes</VariableType>
                      <ShowAsSigned>1</ShowAsSigned>
                      <Address>hvPtrs+28</Address>
                      <Offsets>
                        <Offset>64</Offset>
                      </Offsets>
                    </CheatEntry>
                    <CheatEntry>
                      <ID>7076</ID>
                      <Description>"Persuade EXP"</Description>
                      <VariableType>4 Bytes</VariableType>
                      <ShowAsSigned>1</ShowAsSigned>
                      <Address>hvPtrs+30</Address>
                      <Offsets>
                        <Offset>64</Offset>
                      </Offsets>
                    </CheatEntry>
                    <CheatEntry>
                      <ID>7077</ID>
                      <Description>"Hide level"</Description>
                      <VariableType>4 Bytes</VariableType>
                      <ShowAsSigned>1</ShowAsSigned>
                      <Address>hvPtrs+28</Address>
                      <Offsets>
                        <Offset>68</Offset>
                      </Offsets>
                    </CheatEntry>
                    <CheatEntry>
                      <ID>7078</ID>
                      <Description>"Hide EXP"</Description>
                      <VariableType>4 Bytes</VariableType>
                      <ShowAsSigned>1</ShowAsSigned>
                      <Address>hvPtrs+30</Address>
                      <Offsets>
                        <Offset>68</Offset>
                      </Offsets>
                    </CheatEntry>
                    <CheatEntry>
                      <ID>7079</ID>
                      <Description>"Tech level"</Description>
                      <VariableType>4 Bytes</VariableType>
                      <ShowAsSigned>1</ShowAsSigned>
                      <Address>hvPtrs+28</Address>
                      <Offsets>
                        <Offset>6C</Offset>
                      </Offsets>
                    </CheatEntry>
                    <CheatEntry>
                      <ID>7080</ID>
                      <Description>"Tech EXP"</Description>
                      <VariableType>4 Bytes</VariableType>
                      <ShowAsSigned>1</ShowAsSigned>
                      <Address>hvPtrs+30</Address>
                      <Offsets>
                        <Offset>6C</Offset>
                      </Offsets>
                    </CheatEntry>
                    <CheatEntry>
                      <ID>7081</ID>
                      <Description>"Cure level"</Description>
                      <VariableType>4 Bytes</VariableType>
                      <ShowAsSigned>1</ShowAsSigned>
                      <Address>hvPtrs+28</Address>
                      <Offsets>
                        <Offset>70</Offset>
                      </Offsets>
                    </CheatEntry>
                    <CheatEntry>
                      <ID>7082</ID>
                      <Description>"Cure EXP"</Description>
                      <VariableType>4 Bytes</VariableType>
                      <ShowAsSigned>1</ShowAsSigned>
                      <Address>hvPtrs+30</Address>
                      <Offsets>
                        <Offset>70</Offset>
                      </Offsets>
                    </CheatEntry>
                    <CheatEntry>
                      <ID>7083</ID>
                      <Description>"Drink level"</Description>
                      <VariableType>4 Bytes</VariableType>
                      <ShowAsSigned>1</ShowAsSigned>
                      <Address>hvPtrs+28</Address>
                      <Offsets>
                        <Offset>74</Offset>
                      </Offsets>
                    </CheatEntry>
                    <CheatEntry>
                      <ID>7084</ID>
                      <Description>"Drink EXP"</Description>
                      <VariableType>4 Bytes</VariableType>
                      <ShowAsSigned>1</ShowAsSigned>
                      <Address>hvPtrs+30</Address>
                      <Offsets>
                        <Offset>74</Offset>
                      </Offsets>
                    </CheatEntry>
                    <CheatEntry>
                      <ID>7085</ID>
                      <Description>"Travel level"</Description>
                      <VariableType>4 Bytes</VariableType>
                      <ShowAsSigned>1</ShowAsSigned>
                      <Address>hvPtrs+28</Address>
                      <Offsets>
                        <Offset>78</Offset>
                      </Offsets>
                    </CheatEntry>
                    <CheatEntry>
                      <ID>7086</ID>
                      <Description>"Travel EXP"</Description>
                      <VariableType>4 Bytes</VariableType>
                      <ShowAsSigned>1</ShowAsSigned>
                      <Address>hvPtrs+30</Address>
                      <Offsets>
                        <Offset>78</Offset>
                      </Offsets>
                    </CheatEntry>
                    <CheatEntry>
                      <ID>7087</ID>
                      <Description>"Tame level"</Description>
                      <VariableType>4 Bytes</VariableType>
                      <ShowAsSigned>1</ShowAsSigned>
                      <Address>hvPtrs+28</Address>
                      <Offsets>
                        <Offset>7C</Offset>
                      </Offsets>
                    </CheatEntry>
                    <CheatEntry>
                      <ID>7088</ID>
                      <Description>"Tame EXP"</Description>
                      <VariableType>4 Bytes</VariableType>
                      <ShowAsSigned>1</ShowAsSigned>
                      <Address>hvPtrs+30</Address>
                      <Offsets>
                        <Offset>7C</Offset>
                      </Offsets>
                    </CheatEntry>
                  </CheatEntries>
                </CheatEntry>
              </CheatEntries>
            </CheatEntry>
            <CheatEntry>
              <ID>7089</ID>
              <Description>"Souls"</Description>
              <Options moManualExpandCollapse="1" />
              <Color>FFFF00</Color>
              <GroupHeader>1</GroupHeader>
              <CheatEntries>
                <CheatEntry>
                  <ID>7090</ID>
                  <Description>"Army soul"</Description>
                  <VariableType>4 Bytes</VariableType>
                  <ShowAsSigned>1</ShowAsSigned>
                  <Address>hvPtrs+38</Address>
                  <Offsets>
                    <Offset>20</Offset>
                  </Offsets>
                </CheatEntry>
                <CheatEntry>
                  <ID>7091</ID>
                  <Description>"Martial soul"</Description>
                  <VariableType>4 Bytes</VariableType>
                  <ShowAsSigned>1</ShowAsSigned>
                  <Address>hvPtrs+38</Address>
                  <Offsets>
                    <Offset>24</Offset>
                  </Offsets>
                </CheatEntry>
                <CheatEntry>
                  <ID>7092</ID>
                  <Description>"Wisdom soul"</Description>
                  <VariableType>4 Bytes</VariableType>
                  <ShowAsSigned>1</ShowAsSigned>
                  <Address>hvPtrs+38</Address>
                  <Offsets>
                    <Offset>28</Offset>
                  </Offsets>
                </CheatEntry>
              </CheatEntries>
            </CheatEntry>
            <CheatEntry>
              <ID>7093</ID>
              <Description>"Status &amp; reputation"</Description>
              <Options moManualExpandCollapse="1" />
              <Color>FFFF00</Color>
              <GroupHeader>1</GroupHeader>
              <CheatEntries>
                <CheatEntry>
                  <ID>7094</ID>
                  <Description>"Loyalty"</Description>
                  <VariableType>4 Bytes</VariableType>
                  <ShowAsSigned>1</ShowAsSigned>
                  <Address>hvPtrs+8</Address>
                  <Offsets>
                    <Offset>E8</Offset>
                  </Offsets>
                </CheatEntry>
                <CheatEntry>
                  <ID>7095</ID>
                  <Description>"Reputation (base)"</Description>
                  <VariableType>4 Bytes</VariableType>
                  <ShowAsSigned>1</ShowAsSigned>
                  <Address>hvPtrs+8</Address>
                  <Offsets>
                    <Offset>F0</Offset>
                  </Offsets>
                </CheatEntry>
                <CheatEntry>
                  <ID>7096</ID>
                  <Description>"Influence (current power; player only)"</Description>
                  <VariableType>Float</VariableType>
                  <Address>hvPtrs+C0</Address>
                  <Offsets>
                    <Offset>0</Offset>
                  </Offsets>
                </CheatEntry>
                <CheatEntry>
                  <ID>7097</ID>
                  <Description>"Rank"</Description>
                  <VariableType>4 Bytes</VariableType>
                  <ShowAsSigned>1</ShowAsSigned>
                  <Address>hvPtrs+8</Address>
                  <Offsets>
                    <Offset>F8</Offset>
                  </Offsets>
                </CheatEntry>
                <CheatEntry>
                  <ID>7098</ID>
                  <Description>"Merit"</Description>
                  <VariableType>Float</VariableType>
                  <Address>hvPtrs+8</Address>
                  <Offsets>
                    <Offset>FC</Offset>
                  </Offsets>
                </CheatEntry>
                <CheatEntry>
                  <ID>7099</ID>
                  <Description>"Seasonal merit"</Description>
                  <VariableType>Float</VariableType>
                  <Address>hvPtrs+0</Address>
                  <Offsets>
                    <Offset>190</Offset>
                  </Offsets>
                </CheatEntry>
              </CheatEntries>
            </CheatEntry>
            <CheatEntry>
              <ID>7100</ID>
              <Description>"Duel bonus"</Description>
              <Options moManualExpandCollapse="1" />
              <Color>FFFF00</Color>
              <GroupHeader>1</GroupHeader>
              <CheatEntries>
                <CheatEntry>
                  <ID>7101</ID>
                  <Description>"Duel HP max bonus"</Description>
                  <VariableType>4 Bytes</VariableType>
                  <ShowAsSigned>1</ShowAsSigned>
                  <Address>hvPtrs+0</Address>
                  <Offsets>
                    <Offset>188</Offset>
                  </Offsets>
                </CheatEntry>
                <CheatEntry>
                  <ID>7102</ID>
                  <Description>"Duel MP max bonus"</Description>
                  <VariableType>4 Bytes</VariableType>
                  <ShowAsSigned>1</ShowAsSigned>
                  <Address>hvPtrs+0</Address>
                  <Offsets>
                    <Offset>18C</Offset>
                  </Offsets>
                </CheatEntry>
              </CheatEntries>
            </CheatEntry>
            <CheatEntry>
              <ID>7103</ID>
              <Description>"Records"</Description>
              <Options moManualExpandCollapse="1" />
              <Color>FFFF00</Color>
              <GroupHeader>1</GroupHeader>
              <CheatEntries>
                <CheatEntry>
                  <ID>7104</ID>
                  <Description>"Battle wins"</Description>
                  <VariableType>4 Bytes</VariableType>
                  <ShowAsSigned>1</ShowAsSigned>
                  <Address>hvPtrs+0</Address>
                  <Offsets>
                    <Offset>1DC</Offset>
                  </Offsets>
                </CheatEntry>
                <CheatEntry>
                  <ID>7105</ID>
                  <Description>"Debate wins"</Description>
                  <VariableType>4 Bytes</VariableType>
                  <ShowAsSigned>1</ShowAsSigned>
                  <Address>hvPtrs+0</Address>
                  <Offsets>
                    <Offset>1E0</Offset>
                  </Offsets>
                </CheatEntry>
                <CheatEntry>
                  <ID>7106</ID>
                  <Description>"Mock-war wins"</Description>
                  <VariableType>4 Bytes</VariableType>
                  <ShowAsSigned>1</ShowAsSigned>
                  <Address>hvPtrs+0</Address>
                  <Offsets>
                    <Offset>1E4</Offset>
                  </Offsets>
                </CheatEntry>
                <CheatEntry>
                  <ID>7107</ID>
                  <Description>"Battle losses"</Description>
                  <VariableType>4 Bytes</VariableType>
                  <ShowAsSigned>1</ShowAsSigned>
                  <Address>hvPtrs+0</Address>
                  <Offsets>
                    <Offset>1E8</Offset>
                  </Offsets>
                </CheatEntry>
                <CheatEntry>
                  <ID>7108</ID>
                  <Description>"Debate losses"</Description>
                  <VariableType>4 Bytes</VariableType>
                  <ShowAsSigned>1</ShowAsSigned>
                  <Address>hvPtrs+0</Address>
                  <Offsets>
                    <Offset>1EC</Offset>
                  </Offsets>
                </CheatEntry>
                <CheatEntry>
                  <ID>7109</ID>
                  <Description>"Mock-war losses"</Description>
                  <VariableType>4 Bytes</VariableType>
                  <ShowAsSigned>1</ShowAsSigned>
                  <Address>hvPtrs+0</Address>
                  <Offsets>
                    <Offset>1F0</Offset>
                  </Offsets>
                </CheatEntry>
              </CheatEntries>
            </CheatEntry>
          </CheatEntries>
        </CheatEntry>
        <CheatEntry>
          <ID>7110</ID>
          <Description>"Hero editor (select a hero)"</Description>
          <Options moManualExpandCollapse="1" />
          <Color>FFFF00</Color>
          <GroupHeader>1</GroupHeader>
          <CheatEntries>
            <CheatEntry>
              <ID>7111</ID>
              <Description>"Select: hero shown in Hero Info window"</Description>
              <Color>00A5FF</Color>
              <VariableType>Auto Assembler Script</VariableType>
              <AssemblerScript>[ENABLE]
{$lua}
if syntaxcheck then return end
HV.oneShot(memrec, function() HV.selectHeroUI() end)
{$asm}
[DISABLE]
</AssemblerScript>
            </CheatEntry>
            <CheatEntry>
              <ID>7112</ID>
              <Description>"Select: search by name"</Description>
              <Color>00A5FF</Color>
              <VariableType>Auto Assembler Script</VariableType>
              <AssemblerScript>[ENABLE]
{$lua}
if syntaxcheck then return end
HV.oneShot(memrec, function() HV.selectHeroSearch() end)
{$asm}
[DISABLE]
</AssemblerScript>
            </CheatEntry>
            <CheatEntry>
              <ID>7113</ID>
              <Description>"Select: player"</Description>
              <Color>00A5FF</Color>
              <VariableType>Auto Assembler Script</VariableType>
              <AssemblerScript>[ENABLE]
{$lua}
if syntaxcheck then return end
HV.oneShot(memrec, function() HV.selectPlayerAsSel() end)
{$asm}
[DISABLE]
</AssemblerScript>
            </CheatEntry>
            <CheatEntry>
              <ID>7114</ID>
              <Description>"Selected hero: all profession levels max"</Description>
              <Color>00A5FF</Color>
              <VariableType>Auto Assembler Script</VariableType>
              <AssemblerScript>[ENABLE]
{$lua}
if syntaxcheck then return end
HV.oneShot(memrec, function() HV.maxProfession('sel') end)
{$asm}
[DISABLE]
</AssemblerScript>
            </CheatEntry>
            <CheatEntry>
              <ID>7115</ID>
              <Description>"Selected hero: base attributes = 100"</Description>
              <Color>00A5FF</Color>
              <VariableType>Auto Assembler Script</VariableType>
              <AssemblerScript>[ENABLE]
{$lua}
if syntaxcheck then return end
HV.oneShot(memrec, function() HV.maxAttr('sel',100) end)
{$asm}
[DISABLE]
</AssemblerScript>
            </CheatEntry>
            <CheatEntry>
              <ID>7116</ID>
              <Description>"Selected hero: relation with player MAX (friendship/family, respect, gratitude, acknowledgement)"</Description>
              <Color>00A5FF</Color>
              <VariableType>Auto Assembler Script</VariableType>
              <AssemblerScript>[ENABLE]
{$lua}
if syntaxcheck then return end
HV.oneShot(memrec, function() HV.relMax('sel') end)
{$asm}
[DISABLE]
</AssemblerScript>
            </CheatEntry>
            <CheatEntry>
              <ID>7117</ID>
              <Description>"Selected hero: loyalty MAX (game max)"</Description>
              <Color>00A5FF</Color>
              <VariableType>Auto Assembler Script</VariableType>
              <AssemblerScript>[ENABLE]
{$lua}
if syntaxcheck then return end
HV.oneShot(memrec, function() HV.loyaltyMax('sel') end)
{$asm}
[DISABLE]
</AssemblerScript>
            </CheatEntry>
            <CheatEntry>
              <ID>7118</ID>
              <Description>"Basic"</Description>
              <Options moManualExpandCollapse="1" />
              <Color>FFFF00</Color>
              <GroupHeader>1</GroupHeader>
              <CheatEntries>
                <CheatEntry>
                  <ID>7119</ID>
                  <Description>"Money"</Description>
                  <VariableType>4 Bytes</VariableType>
                  <ShowAsSigned>1</ShowAsSigned>
                  <Address>hvPtrs+40</Address>
                  <Offsets>
                    <Offset>308</Offset>
                  </Offsets>
                </CheatEntry>
                <CheatEntry>
                  <ID>7120</ID>
                  <Description>"Age"</Description>
                  <VariableType>4 Bytes</VariableType>
                  <ShowAsSigned>1</ShowAsSigned>
                  <Address>hvPtrs+40</Address>
                  <Offsets>
                    <Offset>84</Offset>
                  </Offsets>
                </CheatEntry>
                <CheatEntry>
                  <ID>7121</ID>
                  <Description>"Lifespan"</Description>
                  <VariableType>4 Bytes</VariableType>
                  <ShowAsSigned>1</ShowAsSigned>
                  <Address>hvPtrs+40</Address>
                  <Offsets>
                    <Offset>80</Offset>
                  </Offsets>
                </CheatEntry>
                <CheatEntry>
                  <ID>7122</ID>
                  <Description>"Birth year"</Description>
                  <VariableType>4 Bytes</VariableType>
                  <ShowAsSigned>1</ShowAsSigned>
                  <Address>hvPtrs+40</Address>
                  <Offsets>
                    <Offset>78</Offset>
                  </Offsets>
                </CheatEntry>
                <CheatEntry>
                  <ID>7123</ID>
                  <Description>"Morality"</Description>
                  <VariableType>4 Bytes</VariableType>
                  <ShowAsSigned>1</ShowAsSigned>
                  <Address>hvPtrs+40</Address>
                  <Offsets>
                    <Offset>68</Offset>
                  </Offsets>
                </CheatEntry>
                <CheatEntry>
                  <ID>7124</ID>
                  <Description>"Righteousness (-50000..50000)"</Description>
                  <VariableType>4 Bytes</VariableType>
                  <ShowAsSigned>1</ShowAsSigned>
                  <Address>hvPtrs+48</Address>
                  <Offsets>
                    <Offset>F4</Offset>
                  </Offsets>
                </CheatEntry>
              </CheatEntries>
            </CheatEntry>
            <CheatEntry>
              <ID>7125</ID>
              <Description>"Condition"</Description>
              <Options moManualExpandCollapse="1" />
              <Color>FFFF00</Color>
              <GroupHeader>1</GroupHeader>
              <CheatEntries>
                <CheatEntry>
                  <ID>7126</ID>
                  <Description>"Stamina"</Description>
                  <VariableType>4 Bytes</VariableType>
                  <ShowAsSigned>1</ShowAsSigned>
                  <Address>hvPtrs+40</Address>
                  <Offsets>
                    <Offset>1A0</Offset>
                  </Offsets>
                </CheatEntry>
                <CheatEntry>
                  <ID>7127</ID>
                  <Description>"Stamina max bonus (max = 800 + bonus + 2*(force+will))"</Description>
                  <VariableType>4 Bytes</VariableType>
                  <ShowAsSigned>1</ShowAsSigned>
                  <Address>hvPtrs+40</Address>
                  <Offsets>
                    <Offset>1A4</Offset>
                  </Offsets>
                </CheatEntry>
                <CheatEntry>
                  <ID>7128</ID>
                  <Description>"Mood (0-1000)"</Description>
                  <VariableType>4 Bytes</VariableType>
                  <ShowAsSigned>1</ShowAsSigned>
                  <Address>hvPtrs+40</Address>
                  <Offsets>
                    <Offset>19C</Offset>
                  </Offsets>
                </CheatEntry>
                <CheatEntry>
                  <ID>7129</ID>
                  <Description>"Drunk (0-1000)"</Description>
                  <VariableType>4 Bytes</VariableType>
                  <ShowAsSigned>1</ShowAsSigned>
                  <Address>hvPtrs+40</Address>
                  <Offsets>
                    <Offset>194</Offset>
                  </Offsets>
                </CheatEntry>
                <CheatEntry>
                  <ID>7130</ID>
                  <Description>"Poison"</Description>
                  <VariableType>4 Bytes</VariableType>
                  <ShowAsSigned>1</ShowAsSigned>
                  <Address>hvPtrs+40</Address>
                  <Offsets>
                    <Offset>198</Offset>
                  </Offsets>
                </CheatEntry>
              </CheatEntries>
            </CheatEntry>
            <CheatEntry>
              <ID>7131</ID>
              <Description>"Abilities"</Description>
              <Options moManualExpandCollapse="1" />
              <Color>FFFF00</Color>
              <GroupHeader>1</GroupHeader>
              <CheatEntries>
                <CheatEntry>
                  <ID>7132</ID>
                  <Description>"Base attributes"</Description>
                  <Options moManualExpandCollapse="1" />
                  <Color>FFFF00</Color>
                  <GroupHeader>1</GroupHeader>
                  <CheatEntries>
                    <CheatEntry>
                      <ID>7133</ID>
                      <Description>"Leadership (rule)"</Description>
                      <VariableType>4 Bytes</VariableType>
                      <ShowAsSigned>1</ShowAsSigned>
                      <Address>hvPtrs+50</Address>
                      <Offsets>
                        <Offset>20</Offset>
                      </Offsets>
                    </CheatEntry>
                    <CheatEntry>
                      <ID>7134</ID>
                      <Description>"Force"</Description>
                      <VariableType>4 Bytes</VariableType>
                      <ShowAsSigned>1</ShowAsSigned>
                      <Address>hvPtrs+50</Address>
                      <Offsets>
                        <Offset>24</Offset>
                      </Offsets>
                    </CheatEntry>
                    <CheatEntry>
                      <ID>7135</ID>
                      <Description>"Intelligence (wise)"</Description>
                      <VariableType>4 Bytes</VariableType>
                      <ShowAsSigned>1</ShowAsSigned>
                      <Address>hvPtrs+50</Address>
                      <Offsets>
                        <Offset>28</Offset>
                      </Offsets>
                    </CheatEntry>
                    <CheatEntry>
                      <ID>7136</ID>
                      <Description>"Politics"</Description>
                      <VariableType>4 Bytes</VariableType>
                      <ShowAsSigned>1</ShowAsSigned>
                      <Address>hvPtrs+50</Address>
                      <Offsets>
                        <Offset>2C</Offset>
                      </Offsets>
                    </CheatEntry>
                    <CheatEntry>
                      <ID>7137</ID>
                      <Description>"Charm"</Description>
                      <VariableType>4 Bytes</VariableType>
                      <ShowAsSigned>1</ShowAsSigned>
                      <Address>hvPtrs+50</Address>
                      <Offsets>
                        <Offset>30</Offset>
                      </Offsets>
                    </CheatEntry>
                    <CheatEntry>
                      <ID>7138</ID>
                      <Description>"Will"</Description>
                      <VariableType>4 Bytes</VariableType>
                      <ShowAsSigned>1</ShowAsSigned>
                      <Address>hvPtrs+50</Address>
                      <Offsets>
                        <Offset>34</Offset>
                      </Offsets>
                    </CheatEntry>
                  </CheatEntries>
                </CheatEntry>
                <CheatEntry>
                  <ID>7139</ID>
                  <Description>"Attribute EXP"</Description>
                  <Options moManualExpandCollapse="1" />
                  <Color>FFFF00</Color>
                  <GroupHeader>1</GroupHeader>
                  <CheatEntries>
                    <CheatEntry>
                      <ID>7140</ID>
                      <Description>"Leadership (rule)"</Description>
                      <VariableType>4 Bytes</VariableType>
                      <ShowAsSigned>1</ShowAsSigned>
                      <Address>hvPtrs+58</Address>
                      <Offsets>
                        <Offset>20</Offset>
                      </Offsets>
                    </CheatEntry>
                    <CheatEntry>
                      <ID>7141</ID>
                      <Description>"Force"</Description>
                      <VariableType>4 Bytes</VariableType>
                      <ShowAsSigned>1</ShowAsSigned>
                      <Address>hvPtrs+58</Address>
                      <Offsets>
                        <Offset>24</Offset>
                      </Offsets>
                    </CheatEntry>
                    <CheatEntry>
                      <ID>7142</ID>
                      <Description>"Intelligence (wise)"</Description>
                      <VariableType>4 Bytes</VariableType>
                      <ShowAsSigned>1</ShowAsSigned>
                      <Address>hvPtrs+58</Address>
                      <Offsets>
                        <Offset>28</Offset>
                      </Offsets>
                    </CheatEntry>
                    <CheatEntry>
                      <ID>7143</ID>
                      <Description>"Politics"</Description>
                      <VariableType>4 Bytes</VariableType>
                      <ShowAsSigned>1</ShowAsSigned>
                      <Address>hvPtrs+58</Address>
                      <Offsets>
                        <Offset>2C</Offset>
                      </Offsets>
                    </CheatEntry>
                    <CheatEntry>
                      <ID>7144</ID>
                      <Description>"Charm"</Description>
                      <VariableType>4 Bytes</VariableType>
                      <ShowAsSigned>1</ShowAsSigned>
                      <Address>hvPtrs+58</Address>
                      <Offsets>
                        <Offset>30</Offset>
                      </Offsets>
                    </CheatEntry>
                    <CheatEntry>
                      <ID>7145</ID>
                      <Description>"Will"</Description>
                      <VariableType>4 Bytes</VariableType>
                      <ShowAsSigned>1</ShowAsSigned>
                      <Address>hvPtrs+58</Address>
                      <Offsets>
                        <Offset>34</Offset>
                      </Offsets>
                    </CheatEntry>
                  </CheatEntries>
                </CheatEntry>
                <CheatEntry>
                  <ID>7146</ID>
                  <Description>"Aptitude (talent)"</Description>
                  <Options moManualExpandCollapse="1" />
                  <Color>FFFF00</Color>
                  <GroupHeader>1</GroupHeader>
                  <CheatEntries>
                    <CheatEntry>
                      <ID>7147</ID>
                      <Description>"Leadership (rule)"</Description>
                      <VariableType>4 Bytes</VariableType>
                      <ShowAsSigned>1</ShowAsSigned>
                      <Address>hvPtrs+60</Address>
                      <Offsets>
                        <Offset>20</Offset>
                      </Offsets>
                    </CheatEntry>
                    <CheatEntry>
                      <ID>7148</ID>
                      <Description>"Force"</Description>
                      <VariableType>4 Bytes</VariableType>
                      <ShowAsSigned>1</ShowAsSigned>
                      <Address>hvPtrs+60</Address>
                      <Offsets>
                        <Offset>24</Offset>
                      </Offsets>
                    </CheatEntry>
                    <CheatEntry>
                      <ID>7149</ID>
                      <Description>"Intelligence (wise)"</Description>
                      <VariableType>4 Bytes</VariableType>
                      <ShowAsSigned>1</ShowAsSigned>
                      <Address>hvPtrs+60</Address>
                      <Offsets>
                        <Offset>28</Offset>
                      </Offsets>
                    </CheatEntry>
                    <CheatEntry>
                      <ID>7150</ID>
                      <Description>"Politics"</Description>
                      <VariableType>4 Bytes</VariableType>
                      <ShowAsSigned>1</ShowAsSigned>
                      <Address>hvPtrs+60</Address>
                      <Offsets>
                        <Offset>2C</Offset>
                      </Offsets>
                    </CheatEntry>
                    <CheatEntry>
                      <ID>7151</ID>
                      <Description>"Charm"</Description>
                      <VariableType>4 Bytes</VariableType>
                      <ShowAsSigned>1</ShowAsSigned>
                      <Address>hvPtrs+60</Address>
                      <Offsets>
                        <Offset>30</Offset>
                      </Offsets>
                    </CheatEntry>
                    <CheatEntry>
                      <ID>7152</ID>
                      <Description>"Will"</Description>
                      <VariableType>4 Bytes</VariableType>
                      <ShowAsSigned>1</ShowAsSigned>
                      <Address>hvPtrs+60</Address>
                      <Offsets>
                        <Offset>34</Offset>
                      </Offsets>
                    </CheatEntry>
                  </CheatEntries>
                </CheatEntry>
              </CheatEntries>
            </CheatEntry>
            <CheatEntry>
              <ID>7153</ID>
              <Description>"Professions"</Description>
              <Options moManualExpandCollapse="1" />
              <Color>FFFF00</Color>
              <GroupHeader>1</GroupHeader>
              <CheatEntries>
                <CheatEntry>
                  <ID>7154</ID>
                  <Description>"Martial (7)"</Description>
                  <Options moManualExpandCollapse="1" />
                  <Color>FFFF00</Color>
                  <GroupHeader>1</GroupHeader>
                  <CheatEntries>
                    <CheatEntry>
                      <ID>7155</ID>
                      <Description>"Sword level"</Description>
                      <VariableType>4 Bytes</VariableType>
                      <ShowAsSigned>1</ShowAsSigned>
                      <Address>hvPtrs+68</Address>
                      <Offsets>
                        <Offset>20</Offset>
                      </Offsets>
                    </CheatEntry>
                    <CheatEntry>
                      <ID>7156</ID>
                      <Description>"Sword EXP"</Description>
                      <VariableType>4 Bytes</VariableType>
                      <ShowAsSigned>1</ShowAsSigned>
                      <Address>hvPtrs+70</Address>
                      <Offsets>
                        <Offset>20</Offset>
                      </Offsets>
                    </CheatEntry>
                    <CheatEntry>
                      <ID>7157</ID>
                      <Description>"Spear level"</Description>
                      <VariableType>4 Bytes</VariableType>
                      <ShowAsSigned>1</ShowAsSigned>
                      <Address>hvPtrs+68</Address>
                      <Offsets>
                        <Offset>24</Offset>
                      </Offsets>
                    </CheatEntry>
                    <CheatEntry>
                      <ID>7158</ID>
                      <Description>"Spear EXP"</Description>
                      <VariableType>4 Bytes</VariableType>
                      <ShowAsSigned>1</ShowAsSigned>
                      <Address>hvPtrs+70</Address>
                      <Offsets>
                        <Offset>24</Offset>
                      </Offsets>
                    </CheatEntry>
                    <CheatEntry>
                      <ID>7159</ID>
                      <Description>"Cavalry level"</Description>
                      <VariableType>4 Bytes</VariableType>
                      <ShowAsSigned>1</ShowAsSigned>
                      <Address>hvPtrs+68</Address>
                      <Offsets>
                        <Offset>28</Offset>
                      </Offsets>
                    </CheatEntry>
                    <CheatEntry>
                      <ID>7160</ID>
                      <Description>"Cavalry EXP"</Description>
                      <VariableType>4 Bytes</VariableType>
                      <ShowAsSigned>1</ShowAsSigned>
                      <Address>hvPtrs+70</Address>
                      <Offsets>
                        <Offset>28</Offset>
                      </Offsets>
                    </CheatEntry>
                    <CheatEntry>
                      <ID>7161</ID>
                      <Description>"Archer level"</Description>
                      <VariableType>4 Bytes</VariableType>
                      <ShowAsSigned>1</ShowAsSigned>
                      <Address>hvPtrs+68</Address>
                      <Offsets>
                        <Offset>2C</Offset>
                      </Offsets>
                    </CheatEntry>
                    <CheatEntry>
                      <ID>7162</ID>
                      <Description>"Archer EXP"</Description>
                      <VariableType>4 Bytes</VariableType>
                      <ShowAsSigned>1</ShowAsSigned>
                      <Address>hvPtrs+70</Address>
                      <Offsets>
                        <Offset>2C</Offset>
                      </Offsets>
                    </CheatEntry>
                    <CheatEntry>
                      <ID>7163</ID>
                      <Description>"Machine level"</Description>
                      <VariableType>4 Bytes</VariableType>
                      <ShowAsSigned>1</ShowAsSigned>
                      <Address>hvPtrs+68</Address>
                      <Offsets>
                        <Offset>30</Offset>
                      </Offsets>
                    </CheatEntry>
                    <CheatEntry>
                      <ID>7164</ID>
                      <Description>"Machine EXP"</Description>
                      <VariableType>4 Bytes</VariableType>
                      <ShowAsSigned>1</ShowAsSigned>
                      <Address>hvPtrs+70</Address>
                      <Offsets>
                        <Offset>30</Offset>
                      </Offsets>
                    </CheatEntry>
                    <CheatEntry>
                      <ID>7165</ID>
                      <Description>"Marine level"</Description>
                      <VariableType>4 Bytes</VariableType>
                      <ShowAsSigned>1</ShowAsSigned>
                      <Address>hvPtrs+68</Address>
                      <Offsets>
                        <Offset>34</Offset>
                      </Offsets>
                    </CheatEntry>
                    <CheatEntry>
                      <ID>7166</ID>
                      <Description>"Marine EXP"</Description>
                      <VariableType>4 Bytes</VariableType>
                      <ShowAsSigned>1</ShowAsSigned>
                      <Address>hvPtrs+70</Address>
                      <Offsets>
                        <Offset>34</Offset>
                      </Offsets>
                    </CheatEntry>
                    <CheatEntry>
                      <ID>7167</ID>
                      <Description>"Military level"</Description>
                      <VariableType>4 Bytes</VariableType>
                      <ShowAsSigned>1</ShowAsSigned>
                      <Address>hvPtrs+68</Address>
                      <Offsets>
                        <Offset>38</Offset>
                      </Offsets>
                    </CheatEntry>
                    <CheatEntry>
                      <ID>7168</ID>
                      <Description>"Military EXP"</Description>
                      <VariableType>4 Bytes</VariableType>
                      <ShowAsSigned>1</ShowAsSigned>
                      <Address>hvPtrs+70</Address>
                      <Offsets>
                        <Offset>38</Offset>
                      </Offsets>
                    </CheatEntry>
                  </CheatEntries>
                </CheatEntry>
                <CheatEntry>
                  <ID>7169</ID>
                  <Description>"Domestic (8)"</Description>
                  <Options moManualExpandCollapse="1" />
                  <Color>FFFF00</Color>
                  <GroupHeader>1</GroupHeader>
                  <CheatEntries>
                    <CheatEntry>
                      <ID>7170</ID>
                      <Description>"Commerce level"</Description>
                      <VariableType>4 Bytes</VariableType>
                      <ShowAsSigned>1</ShowAsSigned>
                      <Address>hvPtrs+68</Address>
                      <Offsets>
                        <Offset>3C</Offset>
                      </Offsets>
                    </CheatEntry>
                    <CheatEntry>
                      <ID>7171</ID>
                      <Description>"Commerce EXP"</Description>
                      <VariableType>4 Bytes</VariableType>
                      <ShowAsSigned>1</ShowAsSigned>
                      <Address>hvPtrs+70</Address>
                      <Offsets>
                        <Offset>3C</Offset>
                      </Offsets>
                    </CheatEntry>
                    <CheatEntry>
                      <ID>7172</ID>
                      <Description>"Agriculture level"</Description>
                      <VariableType>4 Bytes</VariableType>
                      <ShowAsSigned>1</ShowAsSigned>
                      <Address>hvPtrs+68</Address>
                      <Offsets>
                        <Offset>40</Offset>
                      </Offsets>
                    </CheatEntry>
                    <CheatEntry>
                      <ID>7173</ID>
                      <Description>"Agriculture EXP"</Description>
                      <VariableType>4 Bytes</VariableType>
                      <ShowAsSigned>1</ShowAsSigned>
                      <Address>hvPtrs+70</Address>
                      <Offsets>
                        <Offset>40</Offset>
                      </Offsets>
                    </CheatEntry>
                    <CheatEntry>
                      <ID>7174</ID>
                      <Description>"Construct level"</Description>
                      <VariableType>4 Bytes</VariableType>
                      <ShowAsSigned>1</ShowAsSigned>
                      <Address>hvPtrs+68</Address>
                      <Offsets>
                        <Offset>44</Offset>
                      </Offsets>
                    </CheatEntry>
                    <CheatEntry>
                      <ID>7175</ID>
                      <Description>"Construct EXP"</Description>
                      <VariableType>4 Bytes</VariableType>
                      <ShowAsSigned>1</ShowAsSigned>
                      <Address>hvPtrs+70</Address>
                      <Offsets>
                        <Offset>44</Offset>
                      </Offsets>
                    </CheatEntry>
                    <CheatEntry>
                      <ID>7176</ID>
                      <Description>"Conscript level"</Description>
                      <VariableType>4 Bytes</VariableType>
                      <ShowAsSigned>1</ShowAsSigned>
                      <Address>hvPtrs+68</Address>
                      <Offsets>
                        <Offset>48</Offset>
                      </Offsets>
                    </CheatEntry>
                    <CheatEntry>
                      <ID>7177</ID>
                      <Description>"Conscript EXP"</Description>
                      <VariableType>4 Bytes</VariableType>
                      <ShowAsSigned>1</ShowAsSigned>
                      <Address>hvPtrs+70</Address>
                      <Offsets>
                        <Offset>48</Offset>
                      </Offsets>
                    </CheatEntry>
                    <CheatEntry>
                      <ID>7178</ID>
                      <Description>"Train level"</Description>
                      <VariableType>4 Bytes</VariableType>
                      <ShowAsSigned>1</ShowAsSigned>
                      <Address>hvPtrs+68</Address>
                      <Offsets>
                        <Offset>4C</Offset>
                      </Offsets>
                    </CheatEntry>
                    <CheatEntry>
                      <ID>7179</ID>
                      <Description>"Train EXP"</Description>
                      <VariableType>4 Bytes</VariableType>
                      <ShowAsSigned>1</ShowAsSigned>
                      <Address>hvPtrs+70</Address>
                      <Offsets>
                        <Offset>4C</Offset>
                      </Offsets>
                    </CheatEntry>
                    <CheatEntry>
                      <ID>7180</ID>
                      <Description>"Security level"</Description>
                      <VariableType>4 Bytes</VariableType>
                      <ShowAsSigned>1</ShowAsSigned>
                      <Address>hvPtrs+68</Address>
                      <Offsets>
                        <Offset>50</Offset>
                      </Offsets>
                    </CheatEntry>
                    <CheatEntry>
                      <ID>7181</ID>
                      <Description>"Security EXP"</Description>
                      <VariableType>4 Bytes</VariableType>
                      <ShowAsSigned>1</ShowAsSigned>
                      <Address>hvPtrs+70</Address>
                      <Offsets>
                        <Offset>50</Offset>
                      </Offsets>
                    </CheatEntry>
                    <CheatEntry>
                      <ID>7182</ID>
                      <Description>"Patrol level"</Description>
                      <VariableType>4 Bytes</VariableType>
                      <ShowAsSigned>1</ShowAsSigned>
                      <Address>hvPtrs+68</Address>
                      <Offsets>
                        <Offset>54</Offset>
                      </Offsets>
                    </CheatEntry>
                    <CheatEntry>
                      <ID>7183</ID>
                      <Description>"Patrol EXP"</Description>
                      <VariableType>4 Bytes</VariableType>
                      <ShowAsSigned>1</ShowAsSigned>
                      <Address>hvPtrs+70</Address>
                      <Offsets>
                        <Offset>54</Offset>
                      </Offsets>
                    </CheatEntry>
                    <CheatEntry>
                      <ID>7184</ID>
                      <Description>"Wall level"</Description>
                      <VariableType>4 Bytes</VariableType>
                      <ShowAsSigned>1</ShowAsSigned>
                      <Address>hvPtrs+68</Address>
                      <Offsets>
                        <Offset>58</Offset>
                      </Offsets>
                    </CheatEntry>
                    <CheatEntry>
                      <ID>7185</ID>
                      <Description>"Wall EXP"</Description>
                      <VariableType>4 Bytes</VariableType>
                      <ShowAsSigned>1</ShowAsSigned>
                      <Address>hvPtrs+70</Address>
                      <Offsets>
                        <Offset>58</Offset>
                      </Offsets>
                    </CheatEntry>
                  </CheatEntries>
                </CheatEntry>
                <CheatEntry>
                  <ID>7186</ID>
                  <Description>"Special (9)"</Description>
                  <Options moManualExpandCollapse="1" />
                  <Color>FFFF00</Color>
                  <GroupHeader>1</GroupHeader>
                  <CheatEntries>
                    <CheatEntry>
                      <ID>7187</ID>
                      <Description>"Explore level"</Description>
                      <VariableType>4 Bytes</VariableType>
                      <ShowAsSigned>1</ShowAsSigned>
                      <Address>hvPtrs+68</Address>
                      <Offsets>
                        <Offset>5C</Offset>
                      </Offsets>
                    </CheatEntry>
                    <CheatEntry>
                      <ID>7188</ID>
                      <Description>"Explore EXP"</Description>
                      <VariableType>4 Bytes</VariableType>
                      <ShowAsSigned>1</ShowAsSigned>
                      <Address>hvPtrs+70</Address>
                      <Offsets>
                        <Offset>5C</Offset>
                      </Offsets>
                    </CheatEntry>
                    <CheatEntry>
                      <ID>7189</ID>
                      <Description>"Diplomacy level"</Description>
                      <VariableType>4 Bytes</VariableType>
                      <ShowAsSigned>1</ShowAsSigned>
                      <Address>hvPtrs+68</Address>
                      <Offsets>
                        <Offset>60</Offset>
                      </Offsets>
                    </CheatEntry>
                    <CheatEntry>
                      <ID>7190</ID>
                      <Description>"Diplomacy EXP"</Description>
                      <VariableType>4 Bytes</VariableType>
                      <ShowAsSigned>1</ShowAsSigned>
                      <Address>hvPtrs+70</Address>
                      <Offsets>
                        <Offset>60</Offset>
                      </Offsets>
                    </CheatEntry>
                    <CheatEntry>
                      <ID>7191</ID>
                      <Description>"Persuade level"</Description>
                      <VariableType>4 Bytes</VariableType>
                      <ShowAsSigned>1</ShowAsSigned>
                      <Address>hvPtrs+68</Address>
                      <Offsets>
                        <Offset>64</Offset>
                      </Offsets>
                    </CheatEntry>
                    <CheatEntry>
                      <ID>7192</ID>
                      <Description>"Persuade EXP"</Description>
                      <VariableType>4 Bytes</VariableType>
                      <ShowAsSigned>1</ShowAsSigned>
                      <Address>hvPtrs+70</Address>
                      <Offsets>
                        <Offset>64</Offset>
                      </Offsets>
                    </CheatEntry>
                    <CheatEntry>
                      <ID>7193</ID>
                      <Description>"Hide level"</Description>
                      <VariableType>4 Bytes</VariableType>
                      <ShowAsSigned>1</ShowAsSigned>
                      <Address>hvPtrs+68</Address>
                      <Offsets>
                        <Offset>68</Offset>
                      </Offsets>
                    </CheatEntry>
                    <CheatEntry>
                      <ID>7194</ID>
                      <Description>"Hide EXP"</Description>
                      <VariableType>4 Bytes</VariableType>
                      <ShowAsSigned>1</ShowAsSigned>
                      <Address>hvPtrs+70</Address>
                      <Offsets>
                        <Offset>68</Offset>
                      </Offsets>
                    </CheatEntry>
                    <CheatEntry>
                      <ID>7195</ID>
                      <Description>"Tech level"</Description>
                      <VariableType>4 Bytes</VariableType>
                      <ShowAsSigned>1</ShowAsSigned>
                      <Address>hvPtrs+68</Address>
                      <Offsets>
                        <Offset>6C</Offset>
                      </Offsets>
                    </CheatEntry>
                    <CheatEntry>
                      <ID>7196</ID>
                      <Description>"Tech EXP"</Description>
                      <VariableType>4 Bytes</VariableType>
                      <ShowAsSigned>1</ShowAsSigned>
                      <Address>hvPtrs+70</Address>
                      <Offsets>
                        <Offset>6C</Offset>
                      </Offsets>
                    </CheatEntry>
                    <CheatEntry>
                      <ID>7197</ID>
                      <Description>"Cure level"</Description>
                      <VariableType>4 Bytes</VariableType>
                      <ShowAsSigned>1</ShowAsSigned>
                      <Address>hvPtrs+68</Address>
                      <Offsets>
                        <Offset>70</Offset>
                      </Offsets>
                    </CheatEntry>
                    <CheatEntry>
                      <ID>7198</ID>
                      <Description>"Cure EXP"</Description>
                      <VariableType>4 Bytes</VariableType>
                      <ShowAsSigned>1</ShowAsSigned>
                      <Address>hvPtrs+70</Address>
                      <Offsets>
                        <Offset>70</Offset>
                      </Offsets>
                    </CheatEntry>
                    <CheatEntry>
                      <ID>7199</ID>
                      <Description>"Drink level"</Description>
                      <VariableType>4 Bytes</VariableType>
                      <ShowAsSigned>1</ShowAsSigned>
                      <Address>hvPtrs+68</Address>
                      <Offsets>
                        <Offset>74</Offset>
                      </Offsets>
                    </CheatEntry>
                    <CheatEntry>
                      <ID>7200</ID>
                      <Description>"Drink EXP"</Description>
                      <VariableType>4 Bytes</VariableType>
                      <ShowAsSigned>1</ShowAsSigned>
                      <Address>hvPtrs+70</Address>
                      <Offsets>
                        <Offset>74</Offset>
                      </Offsets>
                    </CheatEntry>
                    <CheatEntry>
                      <ID>7201</ID>
                      <Description>"Travel level"</Description>
                      <VariableType>4 Bytes</VariableType>
                      <ShowAsSigned>1</ShowAsSigned>
                      <Address>hvPtrs+68</Address>
                      <Offsets>
                        <Offset>78</Offset>
                      </Offsets>
                    </CheatEntry>
                    <CheatEntry>
                      <ID>7202</ID>
                      <Description>"Travel EXP"</Description>
                      <VariableType>4 Bytes</VariableType>
                      <ShowAsSigned>1</ShowAsSigned>
                      <Address>hvPtrs+70</Address>
                      <Offsets>
                        <Offset>78</Offset>
                      </Offsets>
                    </CheatEntry>
                    <CheatEntry>
                      <ID>7203</ID>
                      <Description>"Tame level"</Description>
                      <VariableType>4 Bytes</VariableType>
                      <ShowAsSigned>1</ShowAsSigned>
                      <Address>hvPtrs+68</Address>
                      <Offsets>
                        <Offset>7C</Offset>
                      </Offsets>
                    </CheatEntry>
                    <CheatEntry>
                      <ID>7204</ID>
                      <Description>"Tame EXP"</Description>
                      <VariableType>4 Bytes</VariableType>
                      <ShowAsSigned>1</ShowAsSigned>
                      <Address>hvPtrs+70</Address>
                      <Offsets>
                        <Offset>7C</Offset>
                      </Offsets>
                    </CheatEntry>
                  </CheatEntries>
                </CheatEntry>
              </CheatEntries>
            </CheatEntry>
            <CheatEntry>
              <ID>7205</ID>
              <Description>"Souls"</Description>
              <Options moManualExpandCollapse="1" />
              <Color>FFFF00</Color>
              <GroupHeader>1</GroupHeader>
              <CheatEntries>
                <CheatEntry>
                  <ID>7206</ID>
                  <Description>"Army soul"</Description>
                  <VariableType>4 Bytes</VariableType>
                  <ShowAsSigned>1</ShowAsSigned>
                  <Address>hvPtrs+78</Address>
                  <Offsets>
                    <Offset>20</Offset>
                  </Offsets>
                </CheatEntry>
                <CheatEntry>
                  <ID>7207</ID>
                  <Description>"Martial soul"</Description>
                  <VariableType>4 Bytes</VariableType>
                  <ShowAsSigned>1</ShowAsSigned>
                  <Address>hvPtrs+78</Address>
                  <Offsets>
                    <Offset>24</Offset>
                  </Offsets>
                </CheatEntry>
                <CheatEntry>
                  <ID>7208</ID>
                  <Description>"Wisdom soul"</Description>
                  <VariableType>4 Bytes</VariableType>
                  <ShowAsSigned>1</ShowAsSigned>
                  <Address>hvPtrs+78</Address>
                  <Offsets>
                    <Offset>28</Offset>
                  </Offsets>
                </CheatEntry>
              </CheatEntries>
            </CheatEntry>
            <CheatEntry>
              <ID>7209</ID>
              <Description>"Status &amp; reputation"</Description>
              <Options moManualExpandCollapse="1" />
              <Color>FFFF00</Color>
              <GroupHeader>1</GroupHeader>
              <CheatEntries>
                <CheatEntry>
                  <ID>7210</ID>
                  <Description>"Loyalty"</Description>
                  <VariableType>4 Bytes</VariableType>
                  <ShowAsSigned>1</ShowAsSigned>
                  <Address>hvPtrs+48</Address>
                  <Offsets>
                    <Offset>E8</Offset>
                  </Offsets>
                </CheatEntry>
                <CheatEntry>
                  <ID>7211</ID>
                  <Description>"Reputation (base)"</Description>
                  <VariableType>4 Bytes</VariableType>
                  <ShowAsSigned>1</ShowAsSigned>
                  <Address>hvPtrs+48</Address>
                  <Offsets>
                    <Offset>F0</Offset>
                  </Offsets>
                </CheatEntry>
                <CheatEntry>
                  <ID>7212</ID>
                  <Description>"Rank"</Description>
                  <VariableType>4 Bytes</VariableType>
                  <ShowAsSigned>1</ShowAsSigned>
                  <Address>hvPtrs+48</Address>
                  <Offsets>
                    <Offset>F8</Offset>
                  </Offsets>
                </CheatEntry>
                <CheatEntry>
                  <ID>7213</ID>
                  <Description>"Merit"</Description>
                  <VariableType>Float</VariableType>
                  <Address>hvPtrs+48</Address>
                  <Offsets>
                    <Offset>FC</Offset>
                  </Offsets>
                </CheatEntry>
                <CheatEntry>
                  <ID>7214</ID>
                  <Description>"Seasonal merit"</Description>
                  <VariableType>Float</VariableType>
                  <Address>hvPtrs+40</Address>
                  <Offsets>
                    <Offset>190</Offset>
                  </Offsets>
                </CheatEntry>
              </CheatEntries>
            </CheatEntry>
            <CheatEntry>
              <ID>7215</ID>
              <Description>"Duel bonus"</Description>
              <Options moManualExpandCollapse="1" />
              <Color>FFFF00</Color>
              <GroupHeader>1</GroupHeader>
              <CheatEntries>
                <CheatEntry>
                  <ID>7216</ID>
                  <Description>"Duel HP max bonus"</Description>
                  <VariableType>4 Bytes</VariableType>
                  <ShowAsSigned>1</ShowAsSigned>
                  <Address>hvPtrs+40</Address>
                  <Offsets>
                    <Offset>188</Offset>
                  </Offsets>
                </CheatEntry>
                <CheatEntry>
                  <ID>7217</ID>
                  <Description>"Duel MP max bonus"</Description>
                  <VariableType>4 Bytes</VariableType>
                  <ShowAsSigned>1</ShowAsSigned>
                  <Address>hvPtrs+40</Address>
                  <Offsets>
                    <Offset>18C</Offset>
                  </Offsets>
                </CheatEntry>
              </CheatEntries>
            </CheatEntry>
            <CheatEntry>
              <ID>7218</ID>
              <Description>"Records"</Description>
              <Options moManualExpandCollapse="1" />
              <Color>FFFF00</Color>
              <GroupHeader>1</GroupHeader>
              <CheatEntries>
                <CheatEntry>
                  <ID>7219</ID>
                  <Description>"Battle wins"</Description>
                  <VariableType>4 Bytes</VariableType>
                  <ShowAsSigned>1</ShowAsSigned>
                  <Address>hvPtrs+40</Address>
                  <Offsets>
                    <Offset>1DC</Offset>
                  </Offsets>
                </CheatEntry>
                <CheatEntry>
                  <ID>7220</ID>
                  <Description>"Debate wins"</Description>
                  <VariableType>4 Bytes</VariableType>
                  <ShowAsSigned>1</ShowAsSigned>
                  <Address>hvPtrs+40</Address>
                  <Offsets>
                    <Offset>1E0</Offset>
                  </Offsets>
                </CheatEntry>
                <CheatEntry>
                  <ID>7221</ID>
                  <Description>"Mock-war wins"</Description>
                  <VariableType>4 Bytes</VariableType>
                  <ShowAsSigned>1</ShowAsSigned>
                  <Address>hvPtrs+40</Address>
                  <Offsets>
                    <Offset>1E4</Offset>
                  </Offsets>
                </CheatEntry>
                <CheatEntry>
                  <ID>7222</ID>
                  <Description>"Battle losses"</Description>
                  <VariableType>4 Bytes</VariableType>
                  <ShowAsSigned>1</ShowAsSigned>
                  <Address>hvPtrs+40</Address>
                  <Offsets>
                    <Offset>1E8</Offset>
                  </Offsets>
                </CheatEntry>
                <CheatEntry>
                  <ID>7223</ID>
                  <Description>"Debate losses"</Description>
                  <VariableType>4 Bytes</VariableType>
                  <ShowAsSigned>1</ShowAsSigned>
                  <Address>hvPtrs+40</Address>
                  <Offsets>
                    <Offset>1EC</Offset>
                  </Offsets>
                </CheatEntry>
                <CheatEntry>
                  <ID>7224</ID>
                  <Description>"Mock-war losses"</Description>
                  <VariableType>4 Bytes</VariableType>
                  <ShowAsSigned>1</ShowAsSigned>
                  <Address>hvPtrs+40</Address>
                  <Offsets>
                    <Offset>1F0</Offset>
                  </Offsets>
                </CheatEntry>
              </CheatEntries>
            </CheatEntry>
            <CheatEntry>
              <ID>7225</ID>
              <Description>"Relation toward player"</Description>
              <Options moManualExpandCollapse="1" />
              <Color>FFFF00</Color>
              <GroupHeader>1</GroupHeader>
              <CheatEntries>
                <CheatEntry>
                  <ID>7226</ID>
                  <Description>"Friendship (relation value)"</Description>
                  <VariableType>4 Bytes</VariableType>
                  <ShowAsSigned>1</ShowAsSigned>
                  <Address>hvPtrs+40</Address>
                  <Offsets>
                    <Offset>298</Offset>
                  </Offsets>
                </CheatEntry>
                <CheatEntry>
                  <ID>7227</ID>
                  <Description>"Respect"</Description>
                  <VariableType>4 Bytes</VariableType>
                  <ShowAsSigned>1</ShowAsSigned>
                  <Address>hvPtrs+40</Address>
                  <Offsets>
                    <Offset>29C</Offset>
                  </Offsets>
                </CheatEntry>
                <CheatEntry>
                  <ID>7228</ID>
                  <Description>"Gratitude"</Description>
                  <VariableType>4 Bytes</VariableType>
                  <ShowAsSigned>1</ShowAsSigned>
                  <Address>hvPtrs+40</Address>
                  <Offsets>
                    <Offset>2A0</Offset>
                  </Offsets>
                </CheatEntry>
                <CheatEntry>
                  <ID>7229</ID>
                  <Description>"Acknowledgement"</Description>
                  <VariableType>4 Bytes</VariableType>
                  <ShowAsSigned>1</ShowAsSigned>
                  <Address>hvPtrs+40</Address>
                  <Offsets>
                    <Offset>2A4</Offset>
                  </Offsets>
                </CheatEntry>
                <CheatEntry>
                  <ID>7230</ID>
                  <Description>"Fear"</Description>
                  <VariableType>4 Bytes</VariableType>
                  <ShowAsSigned>1</ShowAsSigned>
                  <Address>hvPtrs+40</Address>
                  <Offsets>
                    <Offset>2A8</Offset>
                  </Offsets>
                </CheatEntry>
                <CheatEntry>
                  <ID>7231</ID>
                  <Description>"Relation stage"</Description>
                  <VariableType>4 Bytes</VariableType>
                  <ShowAsSigned>1</ShowAsSigned>
                  <Address>hvPtrs+40</Address>
                  <Offsets>
                    <Offset>2AC</Offset>
                  </Offsets>
                </CheatEntry>
              </CheatEntries>
            </CheatEntry>
            <CheatEntry>
              <ID>7232</ID>
              <Description>"Social (chat screen)"</Description>
              <Options moManualExpandCollapse="1" />
              <Color>FFFF00</Color>
              <GroupHeader>1</GroupHeader>
              <CheatEntries>
                <CheatEntry>
                  <ID>7233</ID>
                  <Description>"Social Will (current; max 2-5 by relation level)"</Description>
                  <VariableType>4 Bytes</VariableType>
                  <ShowAsSigned>1</ShowAsSigned>
                  <Address>hvPtrs+40</Address>
                  <Offsets>
                    <Offset>2B8</Offset>
                  </Offsets>
                </CheatEntry>
                <CheatEntry>
                  <ID>7234</ID>
                  <Description>"Awe +1 layer"</Description>
                  <Color>00A5FF</Color>
                  <VariableType>Auto Assembler Script</VariableType>
                  <AssemblerScript>[ENABLE]
{$lua}
if syntaxcheck then return end
HV.oneShot(memrec, function() HV.addSocialStatus(1) end)
{$asm}
[DISABLE]
</AssemblerScript>
                </CheatEntry>
                <CheatEntry>
                  <ID>7235</ID>
                  <Description>"Obligation +1 layer"</Description>
                  <Color>00A5FF</Color>
                  <VariableType>Auto Assembler Script</VariableType>
                  <AssemblerScript>[ENABLE]
{$lua}
if syntaxcheck then return end
HV.oneShot(memrec, function() HV.addSocialStatus(2) end)
{$asm}
[DISABLE]
</AssemblerScript>
                </CheatEntry>
                <CheatEntry>
                  <ID>7236</ID>
                  <Description>"Roused +1 layer"</Description>
                  <Color>00A5FF</Color>
                  <VariableType>Auto Assembler Script</VariableType>
                  <AssemblerScript>[ENABLE]
{$lua}
if syntaxcheck then return end
HV.oneShot(memrec, function() HV.addSocialStatus(3) end)
{$asm}
[DISABLE]
</AssemblerScript>
                </CheatEntry>
                <CheatEntry>
                  <ID>7237</ID>
                  <Description>"Romantic +1 layer"</Description>
                  <Color>00A5FF</Color>
                  <VariableType>Auto Assembler Script</VariableType>
                  <AssemblerScript>[ENABLE]
{$lua}
if syntaxcheck then return end
HV.oneShot(memrec, function() HV.addSocialStatus(0) end)
{$asm}
[DISABLE]
</AssemblerScript>
                </CheatEntry>
                <CheatEntry>
                  <ID>7238</ID>
                  <Description>"Awe / Obligation / Roused / Romantic (enable to list: layers, days left)"</Description>
                  <Options moManualExpandCollapse="1" />
                  <Color>FFFF00</Color>
                  <VariableType>Auto Assembler Script</VariableType>
                  <AssemblerScript>[ENABLE]
{$lua}
if syntaxcheck then return end
HV.userRun(function() HV.refreshSocialStatus(memrec) end)
{$asm}
[DISABLE]
{$lua}
if syntaxcheck then return end
if HV then HV.clearChildren(memrec) end
{$asm}
</AssemblerScript>
                </CheatEntry>
                <CheatEntry>
                  <ID>7239</ID>
                  <Description>"Fix Social Effects (%)"</Description>
                  <Options moHideChildren="1" />
                  <Color>00A5FF</Color>
                  <VariableType>Auto Assembler Script</VariableType>
                  <AssemblerScript>[ENABLE]
{$lua}
if syntaxcheck then return end
HV.feature('socialEff', true)
{$asm}
[DISABLE]
{$lua}
if syntaxcheck then return end
if HV then HV.feature('socialEff', false) end
{$asm}
</AssemblerScript>
                  <CheatEntries>
                    <CheatEntry>
                      <ID>7240</ID>
                      <Description>"Social Effects (%)"</Description>
                      <VariableType>4 Bytes</VariableType>
                      <ShowAsSigned>1</ShowAsSigned>
                      <Address>hvVars+28</Address>
                    </CheatEntry>
                  </CheatEntries>
                </CheatEntry>
              </CheatEntries>
            </CheatEntry>
          <CheatEntry><ID>14100</ID><Description>"Family (no family selected)"</Description><GroupHeader>1</GroupHeader><Options moManualExpandCollapse="1" moHideChildren="1" /><Color>FFFF00</Color><CheatEntries><CheatEntry><ID>14101</ID><Description>"Start year"</Description><VariableType>4 Bytes</VariableType><ShowAsSigned>1</ShowAsSigned><Address>hvPtrs+D8</Address><Offsets><Offset>28</Offset></Offsets></CheatEntry><CheatEntry><ID>14102</ID><Description>"End year"</Description><VariableType>4 Bytes</VariableType><ShowAsSigned>1</ShowAsSigned><Address>hvPtrs+D8</Address><Offsets><Offset>2C</Offset></Offsets></CheatEntry><CheatEntry><ID>14103</ID><Description>"Military talent"</Description><VariableType>4 Bytes</VariableType><ShowAsSigned>1</ShowAsSigned><Address>hvPtrs+D8</Address><Offsets><Offset>40</Offset></Offsets></CheatEntry><CheatEntry><ID>14104</ID><Description>"Commerce talent"</Description><VariableType>4 Bytes</VariableType><ShowAsSigned>1</ShowAsSigned><Address>hvPtrs+D8</Address><Offsets><Offset>44</Offset></Offsets></CheatEntry><CheatEntry><ID>14105</ID><Description>"Politics talent"</Description><VariableType>4 Bytes</VariableType><ShowAsSigned>1</ShowAsSigned><Address>hvPtrs+D8</Address><Offsets><Offset>48</Offset></Offsets></CheatEntry><CheatEntry><ID>14106</ID><Description>"Members (double-click a name to open hero editor)"</Description><VariableType>Auto Assembler Script</VariableType><Color>00A5FF</Color><AssemblerScript>[ENABLE]
{$lua}
if syntaxcheck then return end
HV.oneShot(memrec,function() HV.openEntityList('familyMembers',HV.T('Family members','家族の構成武将')) end)
{$asm}
[DISABLE]
</AssemblerScript></CheatEntry></CheatEntries></CheatEntry></CheatEntries>
        </CheatEntry>
      <CheatEntry><ID>12021</ID><Description>"Hero actions &amp; relationships"</Description><Options moManualExpandCollapse="1" /><Color>FFFF00</Color><GroupHeader>1</GroupHeader><CheatEntries><CheatEntry>
          <ID>107</ID>
          <Description>"Player: all profession levels max"</Description>
          <Color>00A5FF</Color>
          <VariableType>Auto Assembler Script</VariableType>
          <AssemblerScript>[ENABLE]
{$lua}
if syntaxcheck then return end
HV.oneShot(memrec, function() HV.maxProfession('player') end)
{$asm}
[DISABLE]
</AssemblerScript>
        </CheatEntry>
        <CheatEntry>
          <ID>108</ID>
          <Description>"Player: base attributes = 100"</Description>
          <Color>00A5FF</Color>
          <VariableType>Auto Assembler Script</VariableType>
          <AssemblerScript>[ENABLE]
{$lua}
if syntaxcheck then return end
HV.oneShot(memrec, function() HV.maxAttr('player',100) end)
{$asm}
[DISABLE]
</AssemblerScript>
        </CheatEntry>
        <CheatEntry>
          <ID>109</ID>
          <Description>"Own power heroes: relation with player MAX (friendship/family, respect, gratitude, acknowledgement)"</Description>
          <Color>00A5FF</Color>
          <VariableType>Auto Assembler Script</VariableType>
          <AssemblerScript>[ENABLE]
{$lua}
if syntaxcheck then return end
HV.oneShot(memrec, function() HV.relMax('own') end)
{$asm}
[DISABLE]
</AssemblerScript>
        </CheatEntry>
        <CheatEntry>
          <ID>113</ID>
          <Description>"All existing heroes: relation with player MAX (friendship/family, respect, gratitude, acknowledgement)"</Description>
          <Color>00A5FF</Color>
          <VariableType>Auto Assembler Script</VariableType>
          <AssemblerScript>[ENABLE]
{$lua}
if syntaxcheck then return end
HV.oneShot(memrec, function() HV.relMax('all') end)
{$asm}
[DISABLE]
</AssemblerScript>
        </CheatEntry>
        <CheatEntry>
          <ID>116</ID>
          <Description>"Hero conversation: show the developer test menu (***Test***; others unchanged)"</Description>
          <Color>00A5FF</Color>
          <VariableType>Auto Assembler Script</VariableType>
          <AssemblerScript>[ENABLE]
{$lua}
if syntaxcheck then return end
if not HV.userRun(function() HV.talkTest(true) end) then HV.oneShot(memrec, function() end) end
{$asm}
[DISABLE]
{$lua}
if syntaxcheck then return end
if HV then HV.talkTest(false) end
{$asm}
</AssemblerScript>
        </CheatEntry>
        <CheatEntry>
          <ID>110</ID>
          <Description>"Own power heroes: loyalty MAX (game max per hero)"</Description>
          <Color>00A5FF</Color>
          <VariableType>Auto Assembler Script</VariableType>
          <AssemblerScript>[ENABLE]
{$lua}
if syntaxcheck then return end
HV.oneShot(memrec, function() HV.loyaltyMax('own') end)
{$asm}
[DISABLE]
</AssemblerScript>
        </CheatEntry>
        <CheatEntry>
          <ID>111</ID>
          <Description>"Own power hero: transfer to a city (select hero -&gt; own city)"</Description>
          <Color>00A5FF</Color>
          <VariableType>Auto Assembler Script</VariableType>
          <AssemblerScript>[ENABLE]
{$lua}
if syntaxcheck then return end
HV.oneShot(memrec, function() HV.heroMove() end)
{$asm}
[DISABLE]
</AssemblerScript>
        </CheatEntry>
        <CheatEntry>
          <ID>114</ID>
          <Description>"All spouses: create a child now (one spouse at a time; name each child in game)"</Description>
          <Color>00A5FF</Color>
          <VariableType>Auto Assembler Script</VariableType>
          <AssemblerScript>[ENABLE]
{$lua}
if syntaxcheck then return end
HV.oneShot(memrec, function() HV.childAll() end)
{$asm}
[DISABLE]
</AssemblerScript>
        </CheatEntry>
        <CheatEntry>
          <ID>115</ID>
          <Description>"Stop pending child creation"</Description>
          <Color>00A5FF</Color>
          <VariableType>Auto Assembler Script</VariableType>
          <AssemblerScript>[ENABLE]
{$lua}
if syntaxcheck then return end
HV.oneShot(memrec, function() HV.childStop() end)
{$asm}
[DISABLE]
</AssemblerScript>
        </CheatEntry>
        <CheatEntry>
          <ID>112</ID>
          <Description>"Xianyun points (used in Xianyun Exchange with Nandou)"</Description>
          <VariableType>4 Bytes</VariableType>
          <ShowAsSigned>1</ShowAsSigned>
          <Address>hvPtrs+A0</Address>
          <Offsets>
            <Offset>244</Offset>
          </Offsets>
        </CheatEntry>
      </CheatEntries></CheatEntry><CheatEntry>
      <ID>900</ID>
      <Description>"Pets"</Description>
      <Options moManualExpandCollapse="1" />
      <Color>FFFF00</Color>
      <GroupHeader>1</GroupHeader>
      <CheatEntries>
        <CheatEntry>
          <ID>901</ID>
          <Description>"Pet list (enable to list; auto refresh while enabled; value = double-click to edit)"</Description>
          <Options moManualExpandCollapse="1" />
          <Color>FFFF00</Color>
          <VariableType>Auto Assembler Script</VariableType>
          <AssemblerScript>[ENABLE]
{$lua}
if syntaxcheck then return end
HV.userRun(function() HV.refreshPetList(memrec) end)
{$asm}
[DISABLE]
{$lua}
if syntaxcheck then return end
if HV then HV.clearChildren(memrec) end
{$asm}
</AssemblerScript>
        </CheatEntry>
      </CheatEntries>
    </CheatEntry>
    </CheatEntries>
    </CheatEntry>
    <CheatEntry>
      <ID>400</ID>
      <Description>"03. Battles, war &amp; troops"</Description>
      <Options moManualExpandCollapse="1" />
      <Color>FFFF00</Color>
      <GroupHeader>1</GroupHeader>
      <CheatEntries><CheatEntry>
      <ID>200</ID>
      <Description>"Duel &amp; cockfight"</Description>
      <Options moManualExpandCollapse="1" />
      <Color>FFFF00</Color>
      <GroupHeader>1</GroupHeader>
      <CheatEntries>
        <CheatEntry>
          <ID>201</ID>
          <Description>"Duel invincible (my side + allies)"</Description>
          <Color>00A5FF</Color>
          <VariableType>Auto Assembler Script</VariableType>
          <AssemblerScript>[ENABLE]
{$lua}
if syntaxcheck then return end
HV.feature('fiGodSide', true)
{$asm}
[DISABLE]
{$lua}
if syntaxcheck then return end
if HV then HV.feature('fiGodSide', false) end
{$asm}
</AssemblerScript>
        </CheatEntry>
        <CheatEntry>
          <ID>202</ID>
          <Description>"Duel one-hit kill (enemies)"</Description>
          <Color>00A5FF</Color>
          <VariableType>Auto Assembler Script</VariableType>
          <AssemblerScript>[ENABLE]
{$lua}
if syntaxcheck then return end
HV.feature('fiOneHit', true)
{$asm}
[DISABLE]
{$lua}
if syntaxcheck then return end
if HV then HV.feature('fiOneHit', false) end
{$asm}
</AssemblerScript>
        </CheatEntry>
        <CheatEntry>
          <ID>203</ID>
          <Description>"Cockfight invincible (my rooster + allied roosters)"</Description>
          <Color>00A5FF</Color>
          <VariableType>Auto Assembler Script</VariableType>
          <AssemblerScript>[ENABLE]
{$lua}
if syntaxcheck then return end
HV.feature('cockGod', true)
{$asm}
[DISABLE]
{$lua}
if syntaxcheck then return end
if HV then HV.feature('cockGod', false) end
{$asm}
</AssemblerScript>
        </CheatEntry>
        <CheatEntry>
          <ID>204</ID>
          <Description>"Cockfight one-hit kill (enemy roosters)"</Description>
          <Color>00A5FF</Color>
          <VariableType>Auto Assembler Script</VariableType>
          <AssemblerScript>[ENABLE]
{$lua}
if syntaxcheck then return end
HV.feature('cockOneHit', true)
{$asm}
[DISABLE]
{$lua}
if syntaxcheck then return end
if HV then HV.feature('cockOneHit', false) end
{$asm}
</AssemblerScript>
        </CheatEntry>
        <CheatEntry>
          <ID>205</ID>
          <Description>"Duel units (enable to list)"</Description>
          <Options moManualExpandCollapse="1" />
          <Color>FFFF00</Color>
          <VariableType>Auto Assembler Script</VariableType>
          <AssemblerScript>[ENABLE]
{$lua}
if syntaxcheck then return end
HV.userRun(function() HV.refreshDuelUnits(memrec) end)
{$asm}
[DISABLE]
{$lua}
if syntaxcheck then return end
if HV then HV.clearChildren(memrec) end
{$asm}
</AssemblerScript>
        </CheatEntry>
      </CheatEntries>
    </CheatEntry>
    <CheatEntry>
      <ID>300</ID>
      <Description>"Debate"</Description>
      <Options moManualExpandCollapse="1" />
      <Color>FFFF00</Color>
      <GroupHeader>1</GroupHeader>
      <CheatEntries>
        <CheatEntry>
          <ID>301</ID>
          <Description>"Debate invincible (my side + allies)"</Description>
          <Color>00A5FF</Color>
          <VariableType>Auto Assembler Script</VariableType>
          <AssemblerScript>[ENABLE]
{$lua}
if syntaxcheck then return end
HV.feature('deGodSide', true)
{$asm}
[DISABLE]
{$lua}
if syntaxcheck then return end
if HV then HV.feature('deGodSide', false) end
{$asm}
</AssemblerScript>
        </CheatEntry>
        <CheatEntry>
          <ID>302</ID>
          <Description>"Debate one-hit kill (enemies)"</Description>
          <Color>00A5FF</Color>
          <VariableType>Auto Assembler Script</VariableType>
          <AssemblerScript>[ENABLE]
{$lua}
if syntaxcheck then return end
HV.feature('deOneHit', true)
{$asm}
[DISABLE]
{$lua}
if syntaxcheck then return end
if HV then HV.feature('deOneHit', false) end
{$asm}
</AssemblerScript>
        </CheatEntry>
        <CheatEntry>
          <ID>303</ID>
          <Description>"Debate units (enable to list)"</Description>
          <Options moManualExpandCollapse="1" />
          <Color>FFFF00</Color>
          <VariableType>Auto Assembler Script</VariableType>
          <AssemblerScript>[ENABLE]
{$lua}
if syntaxcheck then return end
HV.userRun(function() HV.refreshDebateUnits(memrec) end)
{$asm}
[DISABLE]
{$lua}
if syntaxcheck then return end
if HV then HV.clearChildren(memrec) end
{$asm}
</AssemblerScript>
        </CheatEntry>
      </CheatEntries>
    </CheatEntry>
    <CheatEntry><ID>12031</ID><Description>"War"</Description><Options moManualExpandCollapse="1" /><Color>FFFF00</Color><GroupHeader>1</GroupHeader><CheatEntries><CheatEntry>
          <ID>401</ID>
          <Description>"Protect my side"</Description>
          <Options moManualExpandCollapse="1" />
          <Color>FFFF00</Color>
          <GroupHeader>1</GroupHeader>
          <CheatEntries>
            <CheatEntry>
              <ID>402</ID>
              <Description>"Battle invincible (my coalition takes no damage)"</Description>
              <Color>00A5FF</Color>
              <VariableType>Auto Assembler Script</VariableType>
              <AssemblerScript>[ENABLE]
{$lua}
if syntaxcheck then return end
HV.feature('warInv', true)
{$asm}
[DISABLE]
{$lua}
if syntaxcheck then return end
if HV then HV.feature('warInv', false) end
{$asm}
</AssemblerScript>
            </CheatEntry>
            <CheatEntry>
              <ID>403</ID>
              <Description>"My soldiers do not decrease"</Description>
              <Color>00A5FF</Color>
              <VariableType>Auto Assembler Script</VariableType>
              <AssemblerScript>[ENABLE]
{$lua}
if syntaxcheck then return end
HV.feature('warNoLoss', true)
{$asm}
[DISABLE]
{$lua}
if syntaxcheck then return end
if HV then HV.feature('warNoLoss', false) end
{$asm}
</AssemblerScript>
            </CheatEntry>
            <CheatEntry>
              <ID>404</ID>
              <Description>"My morale does not decrease"</Description>
              <Color>00A5FF</Color>
              <VariableType>Auto Assembler Script</VariableType>
              <AssemblerScript>[ENABLE]
{$lua}
if syntaxcheck then return end
HV.feature('warMorale', true)
{$asm}
[DISABLE]
{$lua}
if syntaxcheck then return end
if HV then HV.feature('warMorale', false) end
{$asm}
</AssemblerScript>
            </CheatEntry>
            <CheatEntry>
              <ID>405</ID>
              <Description>"My food does not decrease"</Description>
              <Color>00A5FF</Color>
              <VariableType>Auto Assembler Script</VariableType>
              <AssemblerScript>[ENABLE]
{$lua}
if syntaxcheck then return end
HV.feature('warFood', true)
{$asm}
[DISABLE]
{$lua}
if syntaxcheck then return end
if HV then HV.feature('warFood', false) end
{$asm}
</AssemblerScript>
            </CheatEntry>
          </CheatEntries>
        </CheatEntry>
        <CheatEntry>
          <ID>406</ID>
          <Description>"Boost my side"</Description>
          <Options moManualExpandCollapse="1" />
          <Color>FFFF00</Color>
          <GroupHeader>1</GroupHeader>
          <CheatEntries>
            <CheatEntry>
              <ID>407</ID>
              <Description>"Infinite morale (keep my morale at max)"</Description>
              <Color>00A5FF</Color>
              <VariableType>Auto Assembler Script</VariableType>
              <AssemblerScript>[ENABLE]
{$lua}
if syntaxcheck then return end
HV.feature('warMoraleMax', true)
{$asm}
[DISABLE]
{$lua}
if syntaxcheck then return end
if HV then HV.feature('warMoraleMax', false) end
{$asm}
</AssemblerScript>
            </CheatEntry>
            <CheatEntry>
              <ID>408</ID>
              <Description>"Infinite food (my deploy teams 99999)"</Description>
              <Color>00A5FF</Color>
              <VariableType>Auto Assembler Script</VariableType>
              <AssemblerScript>[ENABLE]
{$lua}
if syntaxcheck then return end
HV.feature('warFoodMax', true)
{$asm}
[DISABLE]
{$lua}
if syntaxcheck then return end
if HV then HV.feature('warFoodMax', false) end
{$asm}
</AssemblerScript>
            </CheatEntry>
            <CheatEntry>
              <ID>409</ID>
              <Description>"Unlimited skill use (cost 0, no use limit)"</Description>
              <Color>00A5FF</Color>
              <VariableType>Auto Assembler Script</VariableType>
              <AssemblerScript>[ENABLE]
{$lua}
if syntaxcheck then return end
HV.feature('warSkill', true)
{$asm}
[DISABLE]
{$lua}
if syntaxcheck then return end
if HV then HV.feature('warSkill', false) end
{$asm}
</AssemblerScript>
            </CheatEntry>
          </CheatEntries>
        </CheatEntry>
        <CheatEntry>
          <ID>410</ID>
          <Description>"Against enemies"</Description>
          <Options moManualExpandCollapse="1" />
          <Color>FFFF00</Color>
          <GroupHeader>1</GroupHeader>
          <CheatEntries>
            <CheatEntry>
              <ID>411</ID>
              <Description>"War one-hit kill (enemy armies)"</Description>
              <Color>00A5FF</Color>
              <VariableType>Auto Assembler Script</VariableType>
              <AssemblerScript>[ENABLE]
{$lua}
if syntaxcheck then return end
HV.feature('warOneHit', true)
{$asm}
[DISABLE]
{$lua}
if syntaxcheck then return end
if HV then HV.feature('warOneHit', false) end
{$asm}
</AssemblerScript>
            </CheatEntry>
            <CheatEntry>
              <ID>412</ID>
              <Description>"Freeze enemy armies (no move / attack / skills)"</Description>
              <Color>00A5FF</Color>
              <VariableType>Auto Assembler Script</VariableType>
              <AssemblerScript>[ENABLE]
{$lua}
if syntaxcheck then return end
HV.feature('warFreeze', true)
{$asm}
[DISABLE]
{$lua}
if syntaxcheck then return end
if HV then HV.feature('warFreeze', false) end
{$asm}
</AssemblerScript>
            </CheatEntry>
            <CheatEntry>
              <ID>413</ID>
              <Description>"Enemy soldiers = 0"</Description>
              <Color>00A5FF</Color>
              <VariableType>Auto Assembler Script</VariableType>
              <AssemblerScript>[ENABLE]
{$lua}
if syntaxcheck then return end
HV.oneShot(memrec, function() HV.enemyWar('soldier') end)
{$asm}
[DISABLE]
</AssemblerScript>
            </CheatEntry>
            <CheatEntry>
              <ID>414</ID>
              <Description>"Enemy morale = 0"</Description>
              <Color>00A5FF</Color>
              <VariableType>Auto Assembler Script</VariableType>
              <AssemblerScript>[ENABLE]
{$lua}
if syntaxcheck then return end
HV.oneShot(memrec, function() HV.enemyWar('morale') end)
{$asm}
[DISABLE]
</AssemblerScript>
            </CheatEntry>
            <CheatEntry>
              <ID>415</ID>
              <Description>"Enemy food = 0"</Description>
              <Color>00A5FF</Color>
              <VariableType>Auto Assembler Script</VariableType>
              <AssemblerScript>[ENABLE]
{$lua}
if syntaxcheck then return end
HV.oneShot(memrec, function() HV.enemyWar('food') end)
{$asm}
[DISABLE]
</AssemblerScript>
            </CheatEntry>
          </CheatEntries>
        </CheatEntry>
        <CheatEntry>
          <ID>416</ID>
          <Description>"Strategy points"</Description>
          <Options moManualExpandCollapse="1" />
          <Color>FFFF00</Color>
          <GroupHeader>1</GroupHeader>
          <CheatEntries>
            <CheatEntry>
              <ID>417</ID>
              <Description>"My strategy points"</Description>
              <VariableType>Float</VariableType>
              <Address>hvPtrs+B0</Address>
              <Offsets>
                <Offset>17C</Offset>
              </Offsets>
            </CheatEntry>
            <CheatEntry>
              <ID>418</ID>
              <Description>"My strategy points max"</Description>
              <VariableType>4 Bytes</VariableType>
              <ShowAsSigned>1</ShowAsSigned>
              <Address>hvPtrs+B0</Address>
              <Offsets>
                <Offset>178</Offset>
              </Offsets>
            </CheatEntry>
            <CheatEntry>
              <ID>419</ID>
              <Description>"Ally strategy points"</Description>
              <VariableType>Float</VariableType>
              <Address>hvPtrs+B0</Address>
              <Offsets>
                <Offset>180</Offset>
              </Offsets>
            </CheatEntry>
            <CheatEntry>
              <ID>420</ID>
              <Description>"Enemy strategy points"</Description>
              <VariableType>Float</VariableType>
              <Address>hvPtrs+B0</Address>
              <Offsets>
                <Offset>190</Offset>
              </Offsets>
            </CheatEntry>
          </CheatEntries>
        </CheatEntry>
        <CheatEntry>
          <ID>421</ID>
          <Description>"War armies (enable to list)"</Description>
          <Options moManualExpandCollapse="1" />
          <Color>FFFF00</Color>
          <VariableType>Auto Assembler Script</VariableType>
          <AssemblerScript>[ENABLE]
{$lua}
if syntaxcheck then return end
HV.userRun(function() HV.refreshWarUnits(memrec) end)
{$asm}
[DISABLE]
{$lua}
if syntaxcheck then return end
if HV then HV.clearChildren(memrec) end
{$asm}
</AssemblerScript>
        </CheatEntry>
      </CheatEntries></CheatEntry><CheatEntry>
      <ID>1000</ID>
      <Description>"Accompanying troops"</Description>
      <Options moManualExpandCollapse="1" />
      <Color>FFFF00</Color>
      <GroupHeader>1</GroupHeader>
      <CheatEntries>
        <CheatEntry>
          <ID>1002</ID>
          <Description>"Add an accompanying team from the mercenary list (choose the mercenary, then soldiers)"</Description>
          <Color>00A5FF</Color>
          <VariableType>Auto Assembler Script</VariableType>
          <AssemblerScript>[ENABLE]
{$lua}
if syntaxcheck then return end
HV.oneShot(memrec, function() HV.teamAdd() end)
{$asm}
[DISABLE]
</AssemblerScript>
        </CheatEntry>
        <CheatEntry>
          <ID>1001</ID>
          <Description>"Accompanying team list (enable to list; auto refresh while enabled; value = double-click to edit)"</Description>
          <Options moManualExpandCollapse="1" />
          <Color>FFFF00</Color>
          <VariableType>Auto Assembler Script</VariableType>
          <AssemblerScript>[ENABLE]
{$lua}
if syntaxcheck then return end
HV.userRun(function() HV.refreshTeamList(memrec) end)
{$asm}
[DISABLE]
{$lua}
if syntaxcheck then return end
if HV then HV.clearChildren(memrec) end
{$asm}
</AssemblerScript>
        </CheatEntry>
      </CheatEntries>
    </CheatEntry>
  <CheatEntry><ID>12032</ID><Description>"City troops / private troops"</Description><Options moManualExpandCollapse="1" /><Color>FFFF00</Color><GroupHeader>1</GroupHeader><CheatEntries><CheatEntry>
          <ID>501</ID>
          <Description>"Select city"</Description>
          <Options moManualExpandCollapse="1" />
          <Color>FFFF00</Color>
          <GroupHeader>1</GroupHeader>
          <CheatEntries>
            <CheatEntry>
              <ID>502</ID>
              <Description>"Select: city the player is in (default)"</Description>
              <Color>00A5FF</Color>
              <VariableType>Auto Assembler Script</VariableType>
              <AssemblerScript>[ENABLE]
{$lua}
if syntaxcheck then return end
HV.oneShot(memrec, function() HV.selectCity('cur') end)
{$asm}
[DISABLE]
</AssemblerScript>
            </CheatEntry>
            <CheatEntry>
              <ID>503</ID>
              <Description>"Select: city shown in City Info window"</Description>
              <Color>00A5FF</Color>
              <VariableType>Auto Assembler Script</VariableType>
              <AssemblerScript>[ENABLE]
{$lua}
if syntaxcheck then return end
HV.oneShot(memrec, function() HV.selectCity('ui') end)
{$asm}
[DISABLE]
</AssemblerScript>
            </CheatEntry>
            <CheatEntry>
              <ID>504</ID>
              <Description>"Select: search by name"</Description>
              <Color>00A5FF</Color>
              <VariableType>Auto Assembler Script</VariableType>
              <AssemblerScript>[ENABLE]
{$lua}
if syntaxcheck then return end
HV.oneShot(memrec, function() HV.selectCity('search') end)
{$asm}
[DISABLE]
</AssemblerScript>
            </CheatEntry>
          </CheatEntries>
        </CheatEntry>
        <CheatEntry>
          <ID>527</ID>
          <Description>"Garrison troops"</Description>
          <Options moManualExpandCollapse="1" />
          <Color>FFFF00</Color>
          <GroupHeader>1</GroupHeader>
          <CheatEntries>
            <CheatEntry>
              <ID>528</ID>
              <Description>"Troop list (enable to list; auto refresh while enabled)"</Description>
              <Options moManualExpandCollapse="1" />
              <Color>FFFF00</Color>
              <VariableType>Auto Assembler Script</VariableType>
              <AssemblerScript>[ENABLE]
{$lua}
if syntaxcheck then return end
HV.userRun(function() HV.refreshTroopList(memrec) end)
{$asm}
[DISABLE]
{$lua}
if syntaxcheck then return end
if HV then HV.clearChildren(memrec) end
{$asm}
</AssemblerScript>
            </CheatEntry>
            <CheatEntry>
              <ID>529</ID>
              <Description>"Garrison: soldiers to cap, wounded 0, EXP 100, morale max"</Description>
              <Color>00A5FF</Color>
              <VariableType>Auto Assembler Script</VariableType>
              <AssemblerScript>[ENABLE]
{$lua}
if syntaxcheck then return end
HV.oneShot(memrec, function() HV.troopsMax() end)
{$asm}
[DISABLE]
</AssemblerScript>
            </CheatEntry>
            <CheatEntry>
              <ID>530</ID>
              <Description>"Garrison: change army kind (select troop, then kind)"</Description>
              <Color>00A5FF</Color>
              <VariableType>Auto Assembler Script</VariableType>
              <AssemblerScript>[ENABLE]
{$lua}
if syntaxcheck then return end
HV.oneShot(memrec, function() HV.troopKind() end)
{$asm}
[DISABLE]
</AssemblerScript>
            </CheatEntry>
            <CheatEntry>
              <ID>531</ID>
              <Description>"Garrison: add a new troop (select army kind, then soldiers; EXP 100)"</Description>
              <Color>00A5FF</Color>
              <VariableType>Auto Assembler Script</VariableType>
              <AssemblerScript>[ENABLE]
{$lua}
if syntaxcheck then return end
HV.oneShot(memrec, function() HV.troopAdd() end)
{$asm}
[DISABLE]
</AssemblerScript>
            </CheatEntry>
            <CheatEntry>
              <ID>532</ID>
              <Description>"Garrison: add 5 troops of Hubao cavalry [11702], 10000 soldiers each, EXP 100"</Description>
              <Color>00A5FF</Color>
              <VariableType>Auto Assembler Script</VariableType>
              <AssemblerScript>[ENABLE]
{$lua}
if syntaxcheck then return end
HV.oneShot(memrec, function() HV.troopAddPreset('11702', 10000, 5) end)
{$asm}
[DISABLE]
</AssemblerScript>
            </CheatEntry>
          </CheatEntries>
        </CheatEntry>
        <CheatEntry>
          <ID>533</ID>
          <Description>"Private troops (Private Army screen; selected city)"</Description>
          <Options moManualExpandCollapse="1" />
          <Color>FFFF00</Color>
          <GroupHeader>1</GroupHeader>
          <CheatEntries>
            <CheatEntry>
              <ID>534</ID>
              <Description>"Private troop list (enable to list; auto refresh while enabled)"</Description>
              <Options moManualExpandCollapse="1" />
              <Color>FFFF00</Color>
              <VariableType>Auto Assembler Script</VariableType>
              <AssemblerScript>[ENABLE]
{$lua}
if syntaxcheck then return end
HV.userRun(function() HV.refreshPrivTroopList(memrec) end)
{$asm}
[DISABLE]
{$lua}
if syntaxcheck then return end
if HV then HV.clearChildren(memrec) end
{$asm}
</AssemblerScript>
            </CheatEntry>
            <CheatEntry>
              <ID>535</ID>
              <Description>"Private troops: soldiers to cap, wounded 0, EXP 100, morale max"</Description>
              <Color>00A5FF</Color>
              <VariableType>Auto Assembler Script</VariableType>
              <AssemblerScript>[ENABLE]
{$lua}
if syntaxcheck then return end
HV.oneShot(memrec, function() HV.troopsMax('prv') end)
{$asm}
[DISABLE]
</AssemblerScript>
            </CheatEntry>
          </CheatEntries>
        </CheatEntry>
      </CheatEntries></CheatEntry></CheatEntries></CheatEntry>
    <CheatEntry>
      <ID>800</ID>
      <Description>"04. Items"</Description>
      <Options moManualExpandCollapse="1" />
      <Color>FFFF00</Color>
      <GroupHeader>1</GroupHeader>
      <CheatEntries>
        <CheatEntry>
          <ID>801</ID>
          <Description>"Forge without required materials (Forge screen)"</Description>
          <Color>00A5FF</Color>
          <VariableType>Auto Assembler Script</VariableType>
          <AssemblerScript>[ENABLE]
{$lua}
if syntaxcheck then return end
HV.feature('forgeMat', true)
{$asm}
[DISABLE]
{$lua}
if syntaxcheck then return end
if HV then HV.feature('forgeMat', false) end
{$asm}
</AssemblerScript>
        </CheatEntry>
        <CheatEntry>
          <ID>802</ID>
          <Description>"Forge: learn all blueprints (all equipment that has a forge book)"</Description>
          <Color>00A5FF</Color>
          <VariableType>Auto Assembler Script</VariableType>
          <AssemblerScript>[ENABLE]
{$lua}
if syntaxcheck then return end
HV.oneShot(memrec, function() HV.forgeLearnAll() end)
{$asm}
[DISABLE]
</AssemblerScript>
        </CheatEntry>
        <CheatEntry>
          <ID>803</ID>
          <Description>"Add items (category / Ctrl+Shift selection / quantity)"</Description>
          <Color>00A5FF</Color>
          <VariableType>Auto Assembler Script</VariableType>
          <AssemblerScript>[ENABLE]
{$lua}
if syntaxcheck then return end
HV.oneShot(memrec, function() HV.itemAddPick() end)
{$asm}
[DISABLE]
</AssemblerScript>
        </CheatEntry>
        <CheatEntry>
          <ID>804</ID>
          <Description>"Get all map items x1 (map fragment / map / treasure map)"</Description>
          <Color>00A5FF</Color>
          <VariableType>Auto Assembler Script</VariableType>
          <AssemblerScript>[ENABLE]
{$lua}
if syntaxcheck then return end
HV.oneShot(memrec, function() HV.giveMaps() end)
{$asm}
[DISABLE]
</AssemblerScript>
        </CheatEntry>
        <CheatEntry>
          <ID>805</ID>
          <Description>"Get all "*精要" books x10 (Consumables / Other)"</Description>
          <Color>00A5FF</Color>
          <VariableType>Auto Assembler Script</VariableType>
          <AssemblerScript>[ENABLE]
{$lua}
if syntaxcheck then return end
HV.oneShot(memrec, function() HV.giveBooks() end)
{$asm}
[DISABLE]
</AssemblerScript>
        </CheatEntry>
        <CheatEntry>
          <ID>809</ID>
          <Description>"Get all skill books x1 (war / battle / debate skills)"</Description>
          <Color>00A5FF</Color>
          <VariableType>Auto Assembler Script</VariableType>
          <AssemblerScript>[ENABLE]
{$lua}
if syntaxcheck then return end
HV.oneShot(memrec, function() HV.giveSkillBooks() end)
{$asm}
[DISABLE]
</AssemblerScript>
        </CheatEntry>
        <CheatEntry>
          <ID>810</ID>
          <Description>"Get all title certificates x1 (Books &amp; certificates / Title certificate)"</Description>
          <Color>00A5FF</Color>
          <VariableType>Auto Assembler Script</VariableType>
          <AssemblerScript>[ENABLE]
{$lua}
if syntaxcheck then return end
HV.oneShot(memrec, function() HV.giveTitleCerts() end)
{$asm}
[DISABLE]
</AssemblerScript>
        </CheatEntry>
        <CheatEntry>
          <ID>811</ID>
          <Description>"Identify all unidentified items (player items + power storage)"</Description>
          <Color>00A5FF</Color>
          <VariableType>Auto Assembler Script</VariableType>
          <AssemblerScript>[ENABLE]
{$lua}
if syntaxcheck then return end
HV.oneShot(memrec, function() HV.identifyAll() end)
{$asm}
[DISABLE]
</AssemblerScript>
        </CheatEntry>
        <CheatEntry>
          <ID>806</ID>
          <Description>"Player item quantities (enable to edit)"</Description>
          <Options moManualExpandCollapse="1" />
          <Color>FFFF00</Color>
          <VariableType>Auto Assembler Script</VariableType>
          <AssemblerScript>[ENABLE]
{$lua}
if syntaxcheck then return end
HV.userRun(function() HV.refreshPlayerItems(memrec) end)
{$asm}
[DISABLE]
{$lua}
if syntaxcheck then return end
if HV then HV.clearChildren(memrec) end
{$asm}
</AssemblerScript>
        </CheatEntry>
        <CheatEntry>
          <ID>807</ID>
          <Description>"Selected hero items (enable to list; value = count)"</Description>
          <Options moManualExpandCollapse="1" />
          <Color>FFFF00</Color>
          <VariableType>Auto Assembler Script</VariableType>
          <AssemblerScript>[ENABLE]
{$lua}
if syntaxcheck then return end
HV.userRun(function() HV.refreshHeroItems(memrec) end)
{$asm}
[DISABLE]
{$lua}
if syntaxcheck then return end
if HV then HV.clearChildren(memrec) end
{$asm}
</AssemblerScript>
        </CheatEntry>
        <CheatEntry>
          <ID>808</ID>
          <Description>"Player power storage (enable to list; value = count)"</Description>
          <Options moManualExpandCollapse="1" />
          <Color>FFFF00</Color>
          <VariableType>Auto Assembler Script</VariableType>
          <AssemblerScript>[ENABLE]
{$lua}
if syntaxcheck then return end
HV.userRun(function() HV.refreshStorageItems(memrec) end)
{$asm}
[DISABLE]
{$lua}
if syntaxcheck then return end
if HV then HV.clearChildren(memrec) end
{$asm}
</AssemblerScript>
        </CheatEntry>
      </CheatEntries>
    </CheatEntry>
    <CheatEntry>
      <ID>500</ID>
      <Description>"05. Cities &amp; domestic affairs"</Description>
      <Options moManualExpandCollapse="1" />
      <Color>FFFF00</Color>
      <GroupHeader>1</GroupHeader>
      <CheatEntries>
        <CheatEntry><ID>12051</ID><Description>"Select city by name"</Description><Color>00A5FF</Color><VariableType>Auto Assembler Script</VariableType><AssemblerScript>[ENABLE]
{$lua}
if syntaxcheck then return end
HV.oneShot(memrec, function() HV.selectCity('search') end)
{$asm}
[DISABLE]
</AssemblerScript></CheatEntry><CheatEntry>
          <ID>505</ID>
          <Description>"Resources"</Description>
          <Options moManualExpandCollapse="1" />
          <Color>FFFF00</Color>
          <GroupHeader>1</GroupHeader>
          <CheatEntries>
            <CheatEntry>
              <ID>506</ID>
              <Description>"Money"</Description>
              <VariableType>4 Bytes</VariableType>
              <ShowAsSigned>1</ShowAsSigned>
              <Address>hvPtrs+88</Address>
              <Offsets>
                <Offset>28</Offset>
              </Offsets>
            </CheatEntry>
            <CheatEntry>
              <ID>507</ID>
              <Description>"Food"</Description>
              <VariableType>4 Bytes</VariableType>
              <ShowAsSigned>1</ShowAsSigned>
              <Address>hvPtrs+88</Address>
              <Offsets>
                <Offset>2C</Offset>
              </Offsets>
            </CheatEntry>
            <CheatEntry>
              <ID>508</ID>
              <Description>"Population"</Description>
              <VariableType>4 Bytes</VariableType>
              <ShowAsSigned>1</ShowAsSigned>
              <Address>hvPtrs+88</Address>
              <Offsets>
                <Offset>30</Offset>
              </Offsets>
            </CheatEntry>
            <CheatEntry>
              <ID>509</ID>
              <Description>"Security"</Description>
              <VariableType>Float</VariableType>
              <Address>hvPtrs+88</Address>
              <Offsets>
                <Offset>34</Offset>
              </Offsets>
            </CheatEntry>
          </CheatEntries>
        </CheatEntry>
        <CheatEntry>
          <ID>510</ID>
          <Description>"Popular support"</Description>
          <Options moManualExpandCollapse="1" />
          <Color>FFFF00</Color>
          <GroupHeader>1</GroupHeader>
          <CheatEntries>
            <CheatEntry>
              <ID>511</ID>
              <Description>"Popular support (owner power)"</Description>
              <VariableType>Float</VariableType>
              <Address>hvPtrs+98</Address>
              <Offsets>
                <Offset>0</Offset>
              </Offsets>
            </CheatEntry>
            <CheatEntry>
              <ID>512</ID>
              <Description>"Popular support max (game constant)"</Description>
              <VariableType>4 Bytes</VariableType>
              <ShowAsSigned>1</ShowAsSigned>
              <Address>hvPtrs+A8</Address>
              <Offsets>
                <Offset>4</Offset>
              </Offsets>
            </CheatEntry>
            <CheatEntry>
              <ID>513</ID>
              <Description>"Popular support MAX (owner power)"</Description>
              <Color>00A5FF</Color>
              <VariableType>Auto Assembler Script</VariableType>
              <AssemblerScript>[ENABLE]
{$lua}
if syntaxcheck then return end
HV.oneShot(memrec, function() HV.cityFeel('owner') end)
{$asm}
[DISABLE]
</AssemblerScript>
            </CheatEntry>
            <CheatEntry>
              <ID>514</ID>
              <Description>"Popular support MAX (all powers)"</Description>
              <Color>00A5FF</Color>
              <VariableType>Auto Assembler Script</VariableType>
              <AssemblerScript>[ENABLE]
{$lua}
if syntaxcheck then return end
HV.oneShot(memrec, function() HV.cityFeel('all') end)
{$asm}
[DISABLE]
</AssemblerScript>
            </CheatEntry>
            <CheatEntry>
              <ID>515</ID>
              <Description>"Popular support per power (enable to list)"</Description>
              <Options moManualExpandCollapse="1" />
              <Color>FFFF00</Color>
              <VariableType>Auto Assembler Script</VariableType>
              <AssemblerScript>[ENABLE]
{$lua}
if syntaxcheck then return end
HV.userRun(function() HV.refreshFeelList(memrec) end)
{$asm}
[DISABLE]
{$lua}
if syntaxcheck then return end
if HV then HV.clearChildren(memrec) end
{$asm}
</AssemblerScript>
            </CheatEntry>
          </CheatEntries>
        </CheatEntry>
        <CheatEntry>
          <ID>516</ID>
          <Description>"Development &amp; construction"</Description>
          <Options moManualExpandCollapse="1" />
          <Color>FFFF00</Color>
          <GroupHeader>1</GroupHeader>
          <CheatEntries>
            <CheatEntry>
              <ID>517</ID>
              <Description>"Scale (0 small - 3 huge)"</Description>
              <VariableType>4 Bytes</VariableType>
              <ShowAsSigned>1</ShowAsSigned>
              <Address>hvPtrs+80</Address>
              <Offsets>
                <Offset>78</Offset>
              </Offsets>
            </CheatEntry>
            <CheatEntry>
              <ID>518</ID>
              <Description>"Tech points (city data)"</Description>
              <VariableType>4 Bytes</VariableType>
              <ShowAsSigned>1</ShowAsSigned>
              <Address>hvPtrs+80</Address>
              <Offsets>
                <Offset>80</Offset>
              </Offsets>
            </CheatEntry>
            <CheatEntry>
              <ID>519</ID>
              <Description>"Expansion days left"</Description>
              <VariableType>4 Bytes</VariableType>
              <ShowAsSigned>1</ShowAsSigned>
              <Address>hvPtrs+80</Address>
              <Offsets>
                <Offset>2FC</Offset>
              </Offsets>
            </CheatEntry>
            <CheatEntry>
              <ID>520</ID>
              <Description>"Max commerce &amp; agriculture of all blocks (base max)"</Description>
              <Color>00A5FF</Color>
              <VariableType>Auto Assembler Script</VariableType>
              <AssemblerScript>[ENABLE]
{$lua}
if syntaxcheck then return end
HV.oneShot(memrec, function() HV.cityMaxDev() end)
{$asm}
[DISABLE]
</AssemblerScript>
            </CheatEntry>
            <CheatEntry>
              <ID>521</ID>
              <Description>"Repair all walls (defense max)"</Description>
              <Color>00A5FF</Color>
              <VariableType>Auto Assembler Script</VariableType>
              <AssemblerScript>[ENABLE]
{$lua}
if syntaxcheck then return end
HV.oneShot(memrec, function() HV.cityMaxWall() end)
{$asm}
[DISABLE]
</AssemblerScript>
            </CheatEntry>
            <CheatEntry>
              <ID>522</ID>
              <Description>"Instant construction (buildings in the city/village the player is in)"</Description>
              <Color>00A5FF</Color>
              <VariableType>Auto Assembler Script</VariableType>
              <AssemblerScript>[ENABLE]
{$lua}
if syntaxcheck then return end
HV.feature('buildHere', true)
{$asm}
[DISABLE]
{$lua}
if syntaxcheck then return end
if HV then HV.feature('buildHere', false) end
{$asm}
</AssemblerScript>
            </CheatEntry>
            <CheatEntry>
              <ID>523</ID>
              <Description>"Instant construction (all cities, incl. AI)"</Description>
              <Color>00A5FF</Color>
              <VariableType>Auto Assembler Script</VariableType>
              <AssemblerScript>[ENABLE]
{$lua}
if syntaxcheck then return end
HV.feature('buildAll', true)
{$asm}
[DISABLE]
{$lua}
if syntaxcheck then return end
if HV then HV.feature('buildAll', false) end
{$asm}
</AssemblerScript>
            </CheatEntry>
            <CheatEntry>
              <ID>524</ID>
              <Description>"Real estate: no plot-count limit when buying land / buildings"</Description>
              <Color>00A5FF</Color>
              <VariableType>Auto Assembler Script</VariableType>
              <AssemblerScript>[ENABLE]
{$lua}
if syntaxcheck then return end
HV.feature('estLimit', true)
{$asm}
[DISABLE]
{$lua}
if syntaxcheck then return end
if HV then HV.feature('estLimit', false) end
{$asm}
</AssemblerScript>
            </CheatEntry>
            <CheatEntry>
              <ID>525</ID>
              <Description>"Real estate: buy buildings outside the private area (use with care)"</Description>
              <Color>00A5FF</Color>
              <VariableType>Auto Assembler Script</VariableType>
              <AssemblerScript>[ENABLE]
{$lua}
if syntaxcheck then return end
HV.feature('estArea', true)
{$asm}
[DISABLE]
{$lua}
if syntaxcheck then return end
if HV then HV.feature('estArea', false) end
{$asm}
</AssemblerScript>
            </CheatEntry>
            <CheatEntry>
              <ID>526</ID>
              <Description>"Real estate / city: build anywhere (prefect: all blocks; private: all but government; re-enter the city after switching)"</Description>
              <Color>00A5FF</Color>
              <VariableType>Auto Assembler Script</VariableType>
              <AssemblerScript>[ENABLE]
{$lua}
if syntaxcheck then return end
HV.feature('estLand', true)
{$asm}
[DISABLE]
{$lua}
if syntaxcheck then return end
if HV then HV.feature('estLand', false) end
{$asm}
</AssemblerScript>
            </CheatEntry>
          </CheatEntries>
        </CheatEntry>
        <CheatEntry><ID>14000</ID><Description>"Power editor (selected from Lists)"</Description><GroupHeader>1</GroupHeader><Options moManualExpandCollapse="1" /><Color>FFFF00</Color><CheatEntries><CheatEntry><ID>14001</ID><Description>"Funds"</Description><VariableType>4 Bytes</VariableType><ShowAsSigned>1</ShowAsSigned><Address>hvPtrs+D0</Address><Offsets><Offset>108</Offset></Offsets></CheatEntry><CheatEntry><ID>14002</ID><Description>"Technology points"</Description><VariableType>4 Bytes</VariableType><ShowAsSigned>1</ShowAsSigned><Address>hvPtrs+D0</Address><Offsets><Offset>A0</Offset></Offsets></CheatEntry><CheatEntry><ID>14003</ID><Description>"Policy points"</Description><VariableType>4 Bytes</VariableType><ShowAsSigned>1</ShowAsSigned><Address>hvPtrs+D0</Address><Offsets><Offset>A4</Offset></Offsets></CheatEntry></CheatEntries></CheatEntry></CheatEntries>
    </CheatEntry>
    <CheatEntry>
      <ID>600</ID>
      <Description>"06. Technology, research &amp; policies"</Description>
      <Options moManualExpandCollapse="1" />
      <Color>FFFF00</Color>
      <GroupHeader>1</GroupHeader>
      <CheatEntries>
        <CheatEntry>
          <ID>601</ID>
          <Description>"Instant research"</Description>
          <Options moHideChildren="1" />
          <Color>00A5FF</Color>
          <VariableType>Auto Assembler Script</VariableType>
          <AssemblerScript>[ENABLE]
{$lua}
if syntaxcheck then return end
HV.feature('techInstant', true)
{$asm}
[DISABLE]
{$lua}
if syntaxcheck then return end
if HV then HV.feature('techInstant', false) end
{$asm}
</AssemblerScript>
          <CheatEntries>
            <CheatEntry>
              <ID>602</ID>
              <Description>"Research amount per day"</Description>
              <VariableType>4 Bytes</VariableType>
              <ShowAsSigned>1</ShowAsSigned>
              <Address>hvVars+24</Address>
            </CheatEntry>
          </CheatEntries>
        </CheatEntry>
        <CheatEntry>
          <ID>603</ID>
          <Description>"Infinite tech points (power + personal)"</Description>
          <Color>00A5FF</Color>
          <VariableType>Auto Assembler Script</VariableType>
          <AssemblerScript>[ENABLE]
{$lua}
if syntaxcheck then return end
HV.feature('techPts', true)
{$asm}
[DISABLE]
{$lua}
if syntaxcheck then return end
if HV then HV.feature('techPts', false) end
{$asm}
</AssemblerScript>
        </CheatEntry>
        <CheatEntry>
          <ID>604</ID>
          <Description>"Technology: max all (all layers, player power)"</Description>
          <Color>00A5FF</Color>
          <VariableType>Auto Assembler Script</VariableType>
          <AssemblerScript>[ENABLE]
{$lua}
if syntaxcheck then return end
HV.oneShot(memrec, function() HV.techAll('max','power') end)
{$asm}
[DISABLE]
</AssemblerScript>
        </CheatEntry>
        <CheatEntry>
          <ID>605</ID>
          <Description>"Technology: acquire all (first layer, player power)"</Description>
          <Color>00A5FF</Color>
          <VariableType>Auto Assembler Script</VariableType>
          <AssemblerScript>[ENABLE]
{$lua}
if syntaxcheck then return end
HV.oneShot(memrec, function() HV.techAll('acquire','power') end)
{$asm}
[DISABLE]
</AssemblerScript>
        </CheatEntry>
        <CheatEntry>
          <ID>606</ID>
          <Description>"Technology: max all (personal/family tech)"</Description>
          <Color>00A5FF</Color>
          <VariableType>Auto Assembler Script</VariableType>
          <AssemblerScript>[ENABLE]
{$lua}
if syntaxcheck then return end
HV.oneShot(memrec, function() HV.techAll('max','private') end)
{$asm}
[DISABLE]
</AssemblerScript>
        </CheatEntry>
        <CheatEntry>
          <ID>607</ID>
          <Description>"Power tech points"</Description>
          <VariableType>4 Bytes</VariableType>
          <ShowAsSigned>1</ShowAsSigned>
          <Address>hvPtrs+90</Address>
          <Offsets>
            <Offset>A0</Offset>
          </Offsets>
        </CheatEntry>
        <CheatEntry>
          <ID>608</ID>
          <Description>"Power treasury money (used for research)"</Description>
          <VariableType>4 Bytes</VariableType>
          <ShowAsSigned>1</ShowAsSigned>
          <Address>hvPtrs+90</Address>
          <Offsets>
            <Offset>108</Offset>
          </Offsets>
        </CheatEntry>
        <CheatEntry>
          <ID>609</ID>
          <Description>"Personal tech points"</Description>
          <VariableType>4 Bytes</VariableType>
          <ShowAsSigned>1</ShowAsSigned>
          <Address>hvPtrs+A0</Address>
          <Offsets>
            <Offset>98</Offset>
          </Offsets>
        </CheatEntry>
        <CheatEntry>
          <ID>610</ID>
          <Description>"Power policy points (strategy points)"</Description>
          <VariableType>4 Bytes</VariableType>
          <ShowAsSigned>1</ShowAsSigned>
          <Address>hvPtrs+90</Address>
          <Offsets>
            <Offset>A4</Offset>
          </Offsets>
        </CheatEntry>
        <CheatEntry>
          <ID>611</ID>
          <Description>"Family policy points (strategy points)"</Description>
          <VariableType>4 Bytes</VariableType>
          <ShowAsSigned>1</ShowAsSigned>
          <Address>hvPtrs+A0</Address>
          <Offsets>
            <Offset>3F0</Offset>
          </Offsets>
        </CheatEntry>
        <CheatEntry>
          <ID>617</ID>
          <Description>"Reset policy cooldowns (power + family; same effect as the policy 「諸策継続」)"</Description>
          <Color>00A5FF</Color>
          <VariableType>Auto Assembler Script</VariableType>
          <AssemblerScript>[ENABLE]
{$lua}
if syntaxcheck then return end
HV.oneShot(memrec, function() HV.policyCDReset() end)
{$asm}
[DISABLE]
</AssemblerScript>
        </CheatEntry>
        <CheatEntry>
          <ID>612</ID>
          <Description>"Family mastery EXP (family menu)"</Description>
          <Options moManualExpandCollapse="1" />
          <Color>FFFF00</Color>
          <GroupHeader>1</GroupHeader>
          <CheatEntries>
            <CheatEntry>
              <ID>613</ID>
              <Description>"Military mastery EXP (Family Military)"</Description>
              <VariableType>4 Bytes</VariableType>
              <ShowAsSigned>1</ShowAsSigned>
              <Address>hvPtrs+A0</Address>
              <Offsets>
                <Offset>36C</Offset>
              </Offsets>
            </CheatEntry>
            <CheatEntry>
              <ID>614</ID>
              <Description>"Commerce mastery EXP (Family Commerce)"</Description>
              <VariableType>4 Bytes</VariableType>
              <ShowAsSigned>1</ShowAsSigned>
              <Address>hvPtrs+A0</Address>
              <Offsets>
                <Offset>370</Offset>
              </Offsets>
            </CheatEntry>
            <CheatEntry>
              <ID>615</ID>
              <Description>"Governance mastery EXP (Family Governance)"</Description>
              <VariableType>4 Bytes</VariableType>
              <ShowAsSigned>1</ShowAsSigned>
              <Address>hvPtrs+A0</Address>
              <Offsets>
                <Offset>374</Offset>
              </Offsets>
            </CheatEntry>
          </CheatEntries>
        </CheatEntry>
        <CheatEntry>
          <ID>616</ID>
          <Description>"Profession EXP factor (global)"</Description>
          <VariableType>Float</VariableType>
          <Address>hvPtrs+A8</Address>
          <Offsets>
            <Offset>1AC</Offset>
          </Offsets>
        </CheatEntry>
      </CheatEntries>
    </CheatEntry>
    <CheatEntry><ID>13000</ID><Description>"07. Lists"</Description><GroupHeader>1</GroupHeader><Options moManualExpandCollapse="1" /><Color>FFFF00</Color><CheatEntries><CheatEntry><ID>13001</ID><Description>"All heroes"</Description><VariableType>Auto Assembler Script</VariableType><Color>00A5FF</Color><AssemblerScript>[ENABLE]
{$lua}
if syntaxcheck then return end
HV.oneShot(memrec,function() HV.openEntityList('heroes',HV.T("All heroes","全武将")) end)
{$asm}
[DISABLE]
</AssemblerScript></CheatEntry><CheatEntry><ID>13002</ID><Description>"Own-power heroes"</Description><VariableType>Auto Assembler Script</VariableType><Color>00A5FF</Color><AssemblerScript>[ENABLE]
{$lua}
if syntaxcheck then return end
HV.oneShot(memrec,function() HV.openEntityList('ownHeroes',HV.T("Own-power heroes","自勢力の武将")) end)
{$asm}
[DISABLE]
</AssemblerScript></CheatEntry><CheatEntry><ID>13003</ID><Description>"Family heroes"</Description><VariableType>Auto Assembler Script</VariableType><Color>00A5FF</Color><AssemblerScript>[ENABLE]
{$lua}
if syntaxcheck then return end
HV.oneShot(memrec,function() HV.openEntityList('familyHeroes',HV.T("Family heroes","家族の武将")) end)
{$asm}
[DISABLE]
</AssemblerScript></CheatEntry><CheatEntry><ID>13004</ID><Description>"All cities"</Description><VariableType>Auto Assembler Script</VariableType><Color>00A5FF</Color><AssemblerScript>[ENABLE]
{$lua}
if syntaxcheck then return end
HV.oneShot(memrec,function() HV.openEntityList('cities',HV.T("All cities","全都市")) end)
{$asm}
[DISABLE]
</AssemblerScript></CheatEntry><CheatEntry><ID>13005</ID><Description>"Own-power cities"</Description><VariableType>Auto Assembler Script</VariableType><Color>00A5FF</Color><AssemblerScript>[ENABLE]
{$lua}
if syntaxcheck then return end
HV.oneShot(memrec,function() HV.openEntityList('ownCities',HV.T("Own-power cities","自勢力の都市")) end)
{$asm}
[DISABLE]
</AssemblerScript></CheatEntry><CheatEntry><ID>13006</ID><Description>"Powers"</Description><VariableType>Auto Assembler Script</VariableType><Color>00A5FF</Color><AssemblerScript>[ENABLE]
{$lua}
if syntaxcheck then return end
HV.oneShot(memrec,function() HV.openEntityList('powers',HV.T("Powers","勢力")) end)
{$asm}
[DISABLE]
</AssemblerScript></CheatEntry><CheatEntry><ID>13007</ID><Description>"All families"</Description><VariableType>Auto Assembler Script</VariableType><Color>00A5FF</Color><AssemblerScript>[ENABLE]
{$lua}
if syntaxcheck then return end
HV.oneShot(memrec,function() HV.openEntityList('families',HV.T("All families","全家族")) end)
{$asm}
[DISABLE]
</AssemblerScript></CheatEntry><CheatEntry><ID>13008</ID><Description>"Own-power families"</Description><VariableType>Auto Assembler Script</VariableType><Color>00A5FF</Color><AssemblerScript>[ENABLE]
{$lua}
if syntaxcheck then return end
HV.oneShot(memrec,function() HV.openEntityList('ownFamilies',HV.T("Own-power families","自勢力の家族")) end)
{$asm}
[DISABLE]
</AssemblerScript></CheatEntry></CheatEntries></CheatEntry><CheatEntry><ID>1100</ID><Description>"08. Other"</Description><Options moManualExpandCollapse="1" /><Color>FFFF00</Color><GroupHeader>1</GroupHeader><CheatEntries><CheatEntry><ID>1101</ID><Description>"Unlock all Steam achievements"</Description><Color>00A5FF</Color><VariableType>Auto Assembler Script</VariableType><AssemblerScript>[ENABLE]
{$lua}
if syntaxcheck then return end
HV.oneShot(memrec, HV.steamUnlockAll)
{$asm}
[DISABLE]
</AssemblerScript></CheatEntry></CheatEntries></CheatEntry></CheatEntries><UserdefinedSymbols />
  <LuaScript>--[[ =====================================================================================
  Heroes' Vow: Three Kingdoms  -  Cheat Engine table  (namespace: HV, CE symbol prefix: hv)
  Built on GameTemplate.CT V01.  Target : Cheat Engine 7.5+ (64-bit)
  Layout : [ATTACH / ALL OFF]  -&gt;  0. Settings &amp; README  -&gt;  1..8 game categories
  Colors : expandable group = 0xFFFF00 (cyan, BGR) / script = 0x00A5FF (orange, BGR) / value row = none
  IDs    : 1 = ATTACH, 2 = "0." top group, 3..99 = inside "0.", category N uses N*100 .. N*100+99 (7: 7000..)
  Game code: Unity IL2CPP (GameAssembly.dll, il2cpp metadata v31). Every game address is located at run time
  by AOB pattern (HV.SIGS) and registered as the CE symbol hvA_&lt;name&gt;; nothing uses a fixed RVA.
===================================================================================== ]]
HV = HV or {}
local HV = HV
if HV.ParameterLists then for _,s in pairs(HV.ParameterLists.windows)do if not s.closed then s.destroy()end end end

----------------------------------------------------------------- [GAME] basic settings
HV.TAG      = 'HV'
HV.TITLE    = "Heroes' Vow: Three Kingdoms"
HV.EXE      = 'ThreeKingdom.exe'
HV.MODULE   = 'GameAssembly.dll'
HV.GAMEVER = '1.0.13'
HV.lang = 'en'
HV.ID_ATTACH = 1
-- shared memory page (allocated near GameAssembly.dll at attach, registered as CE symbols)
--   hvFlags +000..0FF : feature flag bytes 00..1F; +30..9F main-thread job slots read by the dispatcher hook
--   hvVars  +100..1FF : parameters (value rows / hook code)
--   hvPtrs  +200..3FF : pointer slots, 8 bytes each (pointer value rows "[hvPtrs+n]+offset")
--   hvUnits +400..9FF : unit pointer slots for the generated unit lists
--   +A00..FFF         : job argument buffer
HV.OFF_VARS, HV.OFF_PTRS = 0x100, 0x200
HV.C_GROUP = 0xFFFF00   -- cyan (BGR): expandable groups
HV.C_SCRIPT = 0x00A5FF  -- orange (BGR): scripts
-- Every game address is located at run time by AOB pattern scan (HV.SIGS, generated from this build) and
-- registered as the CE symbol hvA_&lt;name&gt;; nothing uses a fixed RVA.
HV.A = HV.A or {}          -- resolved addresses by name
HV.orig = HV.orig or {}    -- original bytes of hook sites, read before patching
HV.HOOKS = {
  fiHP = {
    {en=[==[alloc(hv_fihp0,$400,hvA_fihp0)
label(hv_fihp0_ret)
label(hv_fihp0_na)
label(hv_fihp0_side)
label(hv_fihp0_self)
label(hv_fihp0_zero)
label(hv_fihp0_en)
label(hv_fihp0_kill)
label(hv_fihp0_done)
label(hv_fihp0_o)
hv_fihp0:
  test edi,edi
  jns hv_fihp0_o
  push rax
  push rcx
  xor ecx,ecx
  mov rax,[rbx+18]
  test rax,rax
  je hv_fihp0_na
  mov rax,[rax]
  cmp rax,[hvA_ANIMAL]
  jne hv_fihp0_na
  mov ecx,1
hv_fihp0_na:
  mov eax,[rbx+28]
  cmp eax,1
  je hv_fihp0_en
  cmp byte ptr [hvFlags+1],0
  jne hv_fihp0_side
  test ecx,ecx
  je hv_fihp0_self
  cmp byte ptr [hvFlags+12],0
  je hv_fihp0_self
hv_fihp0_side:
  test eax,eax
  je hv_fihp0_zero
  cmp eax,3
  je hv_fihp0_zero
hv_fihp0_self:
  cmp byte ptr [hvFlags+0],0
  je hv_fihp0_done
  mov rax,[rbx+18]
  test rax,rax
  je hv_fihp0_done
  mov rcx,[hvA_NPC]
  cmp [rax],rcx
  jne hv_fihp0_done
  mov rcx,[hvA_OFFA]
  mov rcx,[rcx+B8]
  mov rcx,[rcx+30]
  cmp [rax+110],rcx
  jne hv_fihp0_done
hv_fihp0_zero:
  xor edi,edi
  jmp hv_fihp0_done
hv_fihp0_en:
  cmp byte ptr [hvFlags+2],0
  jne hv_fihp0_kill
  test ecx,ecx
  je hv_fihp0_done
  cmp byte ptr [hvFlags+13],0
  je hv_fihp0_done
hv_fihp0_kill:
  mov edi,[rbx+40]
  neg edi
hv_fihp0_done:
  pop rcx
  pop rax
hv_fihp0_o:
  mov ecx,[rbx+40]
  mov r8,[rbx+18]
  jmp hv_fihp0_ret
hvA_fihp0:
  jmp hv_fihp0
  nop 2
hv_fihp0_ret:
]==],
     sites={{'fihp0',7}}},
  },
  deHP = {
    {en=[==[alloc(hv_dehp0,$400,hvA_dehp0)
label(hv_dehp0_ret)
label(hv_dehp0_self)
label(hv_dehp0_zero)
label(hv_dehp0_en)
label(hv_dehp0_done)
label(hv_dehp0_o)
hv_dehp0:
  test edi,edi
  jns hv_dehp0_o
  push rax
  push rcx
  mov eax,[rbx+20]
  cmp eax,1
  je hv_dehp0_en
  cmp byte ptr [hvFlags+3],0
  je hv_dehp0_self
  test eax,eax
  je hv_dehp0_zero
  cmp eax,3
  je hv_dehp0_zero
hv_dehp0_self:
  cmp byte ptr [hvFlags+0],0
  je hv_dehp0_done
  mov rax,[rbx+10]
  test rax,rax
  je hv_dehp0_done
  mov rax,[rax+110]
  mov rcx,[hvA_OFFA]
  mov rcx,[rcx+B8]
  mov rcx,[rcx+30]
  cmp rax,rcx
  jne hv_dehp0_done
hv_dehp0_zero:
  xor edi,edi
  jmp hv_dehp0_done
hv_dehp0_en:
  cmp byte ptr [hvFlags+4],0
  je hv_dehp0_done
  mov edi,[rbx+28]
  neg edi
hv_dehp0_done:
  pop rcx
  pop rax
hv_dehp0_o:
  sub [rbx+000000EC],edi
  jmp hv_dehp0_ret
hvA_dehp0:
  jmp hv_dehp0
  nop 1
hv_dehp0_ret:
]==],
     sites={{'dehp0',6}}},
  },
  fiAP = {
    {en=[==[alloc(hv_fiap0,$400,hvA_fiap_1)
label(hv_fiap0_ret)
label(hv_fiap0_o)
hv_fiap0:
  test edx,edx
  jns hv_fiap0_o
  cmp byte ptr [hvFlags+5],0
  je hv_fiap0_o
  cmp dword ptr [rcx+28],0
  jne hv_fiap0_o
  xor edx,edx
hv_fiap0_o:
  mov [rsp+10],edx
  push rbx
  jmp hv_fiap0_ret
hvA_fiap_1:
  jmp hv_fiap0
hv_fiap0_ret:
]==],
     sites={{'fiap_1',5}}},
  },
  deAP = {
    {en=[==[alloc(hv_deap0,$400,hvA_deap01_1)
label(hv_deap0_ret)
label(hv_deap0_o)
hv_deap0:
  test edx,edx
  jns hv_deap0_o
  cmp byte ptr [hvFlags+5],0
  je hv_deap0_o
  cmp dword ptr [rcx+20],0
  jne hv_deap0_o
  xor edx,edx
hv_deap0_o:
  mov [rsp+10],edx
  push rbx
  jmp hv_deap0_ret
hvA_deap01_1:
  jmp hv_deap0
hv_deap0_ret:
]==],
     sites={{'deap01_1',5}}},
  },
  warDmg = {
    {en=[==[alloc(hv_wadmg,$400,hvA_wadmg)
label(hv_wadmg_ret)
label(hv_wadmg_c1)
label(hv_wadmg_en)
label(hv_wadmg_o)
hv_wadmg:
  push rcx
  cmp byte ptr [hvFlags+0],0
  je hv_wadmg_c1
  push rdx
  mov rdx,[hvA_OFFA]
  mov rdx,[rdx+B8]
  mov rdx,[rdx+30]
  cmp [rbx+18],rdx
  pop rdx
  jne hv_wadmg_c1
  pop rcx
  jmp hvA_wadmg_skip
hv_wadmg_c1:
  mov rcx,[rbx+20]
  test rcx,rcx
  je hv_wadmg_o
  cmp dword ptr [rcx+74],0
  jne hv_wadmg_en
  cmp byte ptr [hvFlags+6],0
  je hv_wadmg_o
  pop rcx
  jmp hvA_wadmg_skip
hv_wadmg_en:
  cmp byte ptr [hvFlags+7],0
  je hv_wadmg_o
  mov dword ptr [r14],(float)100000000.0
hv_wadmg_o:
  pop rcx
  cmp byte ptr [rax+000000D8],00
  jmp hv_wadmg_ret
hvA_wadmg:
  jmp hv_wadmg
  nop 2
hv_wadmg_ret:
]==],
     sites={{'wadmg',7}}},
  },
  warLoss = {
    {en=[==[alloc(hv_waloss,$400,hvA_waloss)
label(hv_waloss_ret)
label(hv_waloss_d)
label(hv_waloss_s)
hv_waloss:
  cmp byte ptr [hvFlags+8],0
  je hv_waloss_d
  cmp dword ptr [rcx+74],0
  je hv_waloss_s
hv_waloss_d:
  sub [rcx+50],esi
hv_waloss_s:
  cmp [rbx+48],dil
  jmp hv_waloss_ret
hvA_waloss:
  jmp hv_waloss
  nop 2
hv_waloss_ret:
]==],
     sites={{'waloss',7}}},
  },
  warMorale = {
    {en=[==[alloc(hv_wamor,$400,hvA_wamor)
label(hv_wamor_ret)
label(hv_wamor_r)
hv_wamor:
  xor r9d,r9d
  movaps xmm1,xmm6
  cmp byte ptr [hvFlags+9],0
  je hv_wamor_r
  cmp dword ptr [rcx+74],0
  jne hv_wamor_r
  push rax
  movd eax,xmm6
  test eax,eax
  pop rax
  jns hv_wamor_r
  xorps xmm1,xmm1
hv_wamor_r:
  jmp hv_wamor_ret
hvA_wamor:
  jmp hv_wamor
  nop 1
hv_wamor_ret:
]==],
     sites={{'wamor',6}}},
  },
  warFood = {
    {en=[==[alloc(hv_wafood,$400,hvA_wafood)
label(hv_wafood_ret)
label(hv_wafood_o)
label(hv_wafood_s)
hv_wafood:
  cmp byte ptr [hvFlags+A],0
  je hv_wafood_o
  push rax
  push rcx
  push rdx
  push r8
  push r9
  push r10
  push r11
  sub rsp,28
  mov rcx,rsi
  xor edx,edx
  call hvA_f_wafoodchk
  add rsp,28
  test al,al
  pop r11
  pop r10
  pop r9
  pop r8
  pop rdx
  pop rcx
  pop rax
  jne hv_wafood_s
hv_wafood_o:
  mov eax,[rax+00000150]
  sub eax,ebx
  mov [rsi+00000150],eax
hv_wafood_s:
  jmp hvA_wafood_back
hvA_wafood:
  jmp hv_wafood
  nop 9
hv_wafood_ret:
]==],
     sites={{'wafood',14}}},
  },
  warSkill = {
    {en=[==[alloc(hv_wacost,$400,hvA_wacost)
label(hv_wacost_ret)
label(hv_wacost_o)
hv_wacost:
  cmp byte ptr [hvFlags+B],0
  je hv_wacost_o
  mov rax,[rcx+20]
  test rax,rax
  je hv_wacost_o
  cmp dword ptr [rax+74],0
  jne hv_wacost_o
  xor eax,eax
  ret
hv_wacost_o:
  mov [rsp+18],rbx
  jmp hv_wacost_ret
hvA_wacost:
  jmp hv_wacost
hv_wacost_ret:
]==],
     sites={{'wacost',5}}},
    {en=[==[alloc(hv_wause,$400,hvA_wause)
label(hv_wause_ret)
label(hv_wause_o)
hv_wause:
  cmp byte ptr [hvFlags+C],0
  je hv_wause_o
  mov rax,[rcx+20]
  test rax,rax
  je hv_wause_o
  cmp dword ptr [rax+74],0
  jne hv_wause_o
  xor eax,eax
  ret
hv_wause_o:
  mov [rsp+08],rbx
  push rdi
  jmp hv_wause_ret
hvA_wause:
  jmp hv_wause
  nop 1
hv_wause_ret:
]==],
     sites={{'wause',6}}},
  },
  speed = {
    {en=[==[alloc(hv_speed,$400,hvA_speed)
label(hv_speed_ret)
label(hv_speed_o)
hv_speed:
  cmp byte ptr [hvFlags+D],0
  je hv_speed_o
  mulss xmm7,dword ptr [hvVars+20]
hv_speed_o:
  movss [rcx+000001A0],xmm7
  jmp hv_speed_ret
hvA_speed:
  jmp hv_speed
  nop 3
hv_speed_ret:
hvA_speed2:
  nop 4
]==],
     sites={{'speed',8},{'speed2',4}}},
  },
  teleport = {
    {en=[==[alloc(hv_tp,$400,hvA_tp)
label(hv_tp_ret)
label(hv_tp_s)
label(hv_tp_o)
hv_tp:
  cmp byte ptr [hvFlags+E],0
  je hv_tp_o
  push rcx
  push rdx
  sub rsp,38
  mov rdx,rcx
  // Build 26159462: +4D8 is GameObject; NPCCtrl is +4E0.
  mov rax,[hvA_OFFA]
  test rax,rax
  je hv_tp_s
  mov rax,[rax+B8]
  test rax,rax
  je hv_tp_s
  mov rcx,[rax+000004E0]
  test rcx,rcx
  je hv_tp_s
  mov rax,[hvA_NPC]
  test rax,rax
  je hv_tp_s
  cmp [rcx],rax
  jne hv_tp_s
  mov r8b,1
  xor r9d,r9d
  mov byte ptr [rsp+20],1
  mov qword ptr [rsp+28],0
  call hvA_f_tp
hv_tp_s:
  add rsp,38
  pop rdx
  pop rcx
hv_tp_o:
  mov [rsp+10],rbx
  mov [rsp+18],rdi
  jmp hv_tp_ret
hvA_tp:
  jmp hv_tp
  nop 5
hv_tp_ret:
]==],
     sites={{'tp',10}}},
  },
  tech = {
    {en=[==[alloc(hv_tech,$400,hvA_tech)
label(hv_tech_ret)
label(hv_tech_o)
hv_tech:
  mov eax,r15d
  cmp byte ptr [hvFlags+F],0
  je hv_tech_o
  mov eax,[hvVars+24]
hv_tech_o:
  jmp hvA_tech_tgt
hvA_tech:
  jmp hv_tech
  nop 3
hv_tech_ret:
]==],
     sites={{'tech',8}}},
  },
  build = {
    {en=[==[alloc(hv_build0,$400,hvA_build_1)
label(hv_build0_ret)
label(hv_build0_vil)
label(hv_build0_no)
label(hv_build0_yes)
label(hv_build0_do)
label(hv_build0_o)
hv_build0:
  cmp byte ptr [hvFlags+10],0
  jne hv_build0_do
  cmp byte ptr [hvFlags+11],0
  je hv_build0_o
  push rax
  push rcx
  push rdx
  mov rdx,[rbx+10]
  test rdx,rdx
  je hv_build0_no
  mov rcx,[hvA_OFFA]
  mov rcx,[rcx+B8]
  mov rax,[rdx+20]
  test rax,rax
  je hv_build0_vil
  cmp rax,[rcx+198]
  je hv_build0_yes
hv_build0_vil:
  mov rax,[rdx+28]
  test rax,rax
  je hv_build0_no
  cmp rax,[rcx+1A0]
  je hv_build0_yes
hv_build0_no:
  pop rdx
  pop rcx
  pop rax
  jmp hv_build0_o
hv_build0_yes:
  pop rdx
  pop rcx
  pop rax
hv_build0_do:
  movss xmm6,[rbx+48]
hv_build0_o:
  movss xmm1,[rbx+44]
  jmp hv_build0_ret
hvA_build_1:
  jmp hv_build0
hv_build0_ret:
]==], sites={{'build_1',5}}},
    {en=[==[alloc(hv_build1,$400,hvA_build_2)
label(hv_build1_ret)
label(hv_build1_vil)
label(hv_build1_no)
label(hv_build1_yes)
label(hv_build1_do)
label(hv_build1_o)
hv_build1:
  cmp byte ptr [hvFlags+10],0
  jne hv_build1_do
  cmp byte ptr [hvFlags+11],0
  je hv_build1_o
  push rax
  push rcx
  push rdx
  mov rdx,[rbx+10]
  test rdx,rdx
  je hv_build1_no
  mov rcx,[hvA_OFFA]
  mov rcx,[rcx+B8]
  mov rax,[rdx+20]
  test rax,rax
  je hv_build1_vil
  cmp rax,[rcx+198]
  je hv_build1_yes
hv_build1_vil:
  mov rax,[rdx+28]
  test rax,rax
  je hv_build1_no
  cmp rax,[rcx+1A0]
  je hv_build1_yes
hv_build1_no:
  pop rdx
  pop rcx
  pop rax
  jmp hv_build1_o
hv_build1_yes:
  pop rdx
  pop rcx
  pop rax
hv_build1_do:
  movss xmm6,[rbx+48]
hv_build1_o:
  movss xmm1,[rbx+44]
  jmp hv_build1_ret
hvA_build_2:
  jmp hv_build1
hv_build1_ret:
]==], sites={{'build_2',5}}},
    {en=[==[alloc(hv_build2,$400,hvA_build_3)
label(hv_build2_ret)
label(hv_build2_vil)
label(hv_build2_no)
label(hv_build2_yes)
label(hv_build2_do)
label(hv_build2_o)
hv_build2:
  cmp byte ptr [hvFlags+10],0
  jne hv_build2_do
  cmp byte ptr [hvFlags+11],0
  je hv_build2_o
  push rax
  push rcx
  push rdx
  mov rdx,[rbx+10]
  test rdx,rdx
  je hv_build2_no
  mov rcx,[hvA_OFFA]
  mov rcx,[rcx+B8]
  mov rax,[rdx+20]
  test rax,rax
  je hv_build2_vil
  cmp rax,[rcx+198]
  je hv_build2_yes
hv_build2_vil:
  mov rax,[rdx+28]
  test rax,rax
  je hv_build2_no
  cmp rax,[rcx+1A0]
  je hv_build2_yes
hv_build2_no:
  pop rdx
  pop rcx
  pop rax
  jmp hv_build2_o
hv_build2_yes:
  pop rdx
  pop rcx
  pop rax
hv_build2_do:
  movss xmm6,[rbx+48]
hv_build2_o:
  movss xmm1,[rbx+44]
  jmp hv_build2_ret
hvA_build_3:
  jmp hv_build2
hv_build2_ret:
]==], sites={{'build_3',5}}},
  },
  forgeMat = {
    {en=[==[hvA_forge:
  nop 6
]==],
     sites={{'forge',6}}},
  },
  estLimit = {
    {en=[==[hvA_estlim1:
  nop 2
]==],
     sites={{'estlim1',2}}},
    {en=[==[hvA_estlim2:
  nop 2
]==],
     sites={{'estlim2',2}}},
  },
  estArea = {
    {en=[==[hvA_estarea1:
  nop 6
]==],
     sites={{'estarea1',6}}},
    {en=[==[hvA_estarea2:
  nop 6
]==],
     sites={{'estarea2',6}}},
  },
  estForest = {
    {en=[==[alloc(hv_estforest,$400,hvA_estforest)
label(hv_estforest_ret)
label(hv_estforest_p)
label(hv_estforest_o)
hv_estforest:
  cmp byte ptr [hvFlags+17],0
  je hv_estforest_o
  push rax
  mov rax,[hvA_BUILDUI]
  mov rax,[rax+B8]
  mov eax,[rax]
  cmp eax,1
  pop rax
  jne hv_estforest_p
  cmp r14,0
  jmp hv_estforest_ret
hv_estforest_p:
  cmp dword ptr [r14+34],0
  je hv_estforest_o
  cmp r14,r14
  jmp hv_estforest_ret
hv_estforest_o:
  cmp dword ptr [r14+34],2
  jmp hv_estforest_ret
hvA_estforest:
  jmp hv_estforest
hv_estforest_ret:
]==],
     sites={{'estforest',5}}},
  },
  estPub = {
    {en=[==[alloc(hv_estpub1,$400,hvA_estpub1)
label(hv_estpub1_ret)
hv_estpub1:
  cmp dword ptr [rax+34],1
  jne hvA_estpub1+CE
  cmp byte ptr [hvFlags+17],0
  jne hvA_estpub1+CE
  jmp hv_estpub1_ret
hvA_estpub1:
  jmp hv_estpub1
  nop 5
hv_estpub1_ret:
]==],
     sites={{'estpub1',10}}},
    {en=[==[alloc(hv_estpub2,$400,hvA_estpub2)
label(hv_estpub2_ret)
label(hv_estpub2_orig)
hv_estpub2:
  cmp byte ptr [hvFlags+17],0
  je hv_estpub2_orig
  cmp r14d,1
  je hvA_estpub2+28
  cmp dword ptr [r15+34],0
  je hvA_estpub2+A1
  jmp hvA_estpub2+11
hv_estpub2_orig:
  cmp dword ptr [r15+34],1
  jne hvA_estpub2+11
  cmp r14d,1
  jne hvA_estpub2+A1
  jmp hvA_estpub2+11
hvA_estpub2:
  jmp hv_estpub2
  nop 2
hv_estpub2_ret:
]==],
     sites={{'estpub2',7}}},
  },
  warFreeze = {
    {en=[==[alloc(hv_frzmv,$400,hvA_frz_move)
label(hv_frzmv_ret)
label(hv_frzmv_o)
hv_frzmv:
  cmp byte ptr [hvFlags+14],0
  je hv_frzmv_o
  cmp dword ptr [rcx+AC],1
  jne hv_frzmv_o
  ret
hv_frzmv_o:
  mov [rsp+10],rbx
  jmp hv_frzmv_ret
hvA_frz_move:
  jmp hv_frzmv
hv_frzmv_ret:
]==],
     sites={{'frz_move',5}}},
    {en=[==[alloc(hv_frzat,$400,hvA_frz_atk)
label(hv_frzat_ret)
label(hv_frzat_o)
hv_frzat:
  cmp byte ptr [hvFlags+14],0
  je hv_frzat_o
  cmp dword ptr [rcx+AC],1
  jne hv_frzat_o
  ret
hv_frzat_o:
  mov rax,rsp
  mov [rax+08],rcx
  jmp hv_frzat_ret
hvA_frz_atk:
  jmp hv_frzat
  nop 2
hv_frzat_ret:
]==],
     sites={{'frz_atk',7}}},
    {en=[==[alloc(hv_frzma,$400,hvA_frz_matk)
label(hv_frzma_ret)
label(hv_frzma_o)
hv_frzma:
  cmp byte ptr [hvFlags+14],0
  je hv_frzma_o
  cmp dword ptr [rcx+AC],1
  jne hv_frzma_o
  ret
hv_frzma_o:
  mov rax,rsp
  push rbx
  push rsi
  jmp hv_frzma_ret
hvA_frz_matk:
  jmp hv_frzma
hv_frzma_ret:
]==],
     sites={{'frz_matk',5}}},
    {en=[==[alloc(hv_frzhs,$400,hvA_frz_hskill)
label(hv_frzhs_ret)
label(hv_frzhs_o)
hv_frzhs:
  cmp byte ptr [hvFlags+14],0
  je hv_frzhs_o
  cmp dword ptr [rcx+AC],1
  jne hv_frzhs_o
  xor eax,eax
  ret
hv_frzhs_o:
  mov [rsp+18],rbx
  jmp hv_frzhs_ret
hvA_frz_hskill:
  jmp hv_frzhs
hv_frzhs_ret:
]==],
     sites={{'frz_hskill',5}}},
    {en=[==[alloc(hv_frzas,$400,hvA_frz_askill)
label(hv_frzas_ret)
label(hv_frzas_o)
hv_frzas:
  cmp byte ptr [hvFlags+14],0
  je hv_frzas_o
  cmp dword ptr [rcx+AC],1
  jne hv_frzas_o
  ret
hv_frzas_o:
  mov [rsp+10],rsi
  jmp hv_frzas_ret
hvA_frz_askill:
  jmp hv_frzas
hv_frzas_ret:
]==],
     sites={{'frz_askill',5}}},
  },
  socialEff = {
    {en=[==[alloc(hv_seff,$400,hvA_socialEff)
label(hv_seff_ret)
label(hv_seff_o)
hv_seff:
  cmp byte ptr [hvFlags+15],0
  je hv_seff_o
  mov eax,[hvVars+28]
  ret
hv_seff_o:
  mov rax,rsp
  mov [rax+20],rsi
  jmp hv_seff_ret
hvA_socialEff:
  jmp hv_seff
  nop 2
hv_seff_ret:
]==],
     sites={{'socialEff',7}}},
  },
  relDisp = {
    {en=[==[alloc(hv_disp,$400,hvA_disp)
label(hv_disp_ret)
label(hv_disp_go)
label(hv_disp_loop)
label(hv_disp_next)
label(hv_disp_fin)
label(hv_disp_sloop)
label(hv_disp_sfin)
label(hv_disp_tdone)
label(hv_disp_tfin)
label(hv_disp_lloop)
label(hv_disp_lnext)
label(hv_disp_lfin)
label(hv_disp_gloop)
label(hv_disp_gfin)
label(hv_disp_o)
hv_disp:
  cmp dword ptr [hvFlags+30],0
  jne hv_disp_go
  cmp dword ptr [hvFlags+38],0
  jne hv_disp_go
  cmp dword ptr [hvFlags+50],0
  jne hv_disp_go
  cmp dword ptr [hvFlags+80],0
  jne hv_disp_go
  cmp dword ptr [hvFlags+90],0
  je hv_disp_o
hv_disp_go:
  push rcx
  push rdx
  push r8
  push r9
  push rbx
  push rsi
  sub rsp,28
  mov esi,[hvFlags+30]
  lea rbx,[hvFlags+A00]
hv_disp_loop:
  test esi,esi
  je hv_disp_fin
  mov rcx,[rbx]
  test rcx,rcx
  je hv_disp_next
  movss xmm1,dword ptr [hvFlags+34]
  mov r8d,1869F
  xor r9d,r9d
  mov qword ptr [rsp+20],0
  call hvA_f_rel1
  mov rcx,[rbx]
  xor edx,edx
  call hvA_f_rel2
hv_disp_next:
  add rbx,8
  dec esi
  jmp hv_disp_loop
hv_disp_fin:
  mov dword ptr [hvFlags+30],0
  mov esi,[hvFlags+38]
  test esi,esi
  je hv_disp_sfin
  lea rbx,[hvFlags+A00]
hv_disp_sloop:
  mov rcx,[hvFlags+40]
  mov rdx,[rbx]
  mov r8,[hvFlags+48]
  call hvA_f_listadd
  add rbx,8
  dec esi
  jne hv_disp_sloop
  mov dword ptr [hvFlags+38],0
hv_disp_sfin:
  cmp dword ptr [hvFlags+50],0
  je hv_disp_tfin
  mov rcx,[hvA_TI_TROOP]
  call hvA_f_objnew
  test rax,rax
  je hv_disp_tdone
  mov rbx,rax
  mov rcx,rbx
  xor edx,edx
  call hvA_f_trpctor
  mov rax,[hvFlags+58]
  mov [rbx+30],rax
  mov rax,[hvFlags+60]
  mov [rbx+20],rax
  mov rcx,rbx
  xor edx,edx
  call hvA_f_trpinit
  mov eax,[hvFlags+68]
  mov [rbx+50],eax
  mov dword ptr [rbx+58],64
  mov rcx,[hvFlags+70]
  mov rdx,rbx
  mov r8,[hvA_MI_TROOPADD]
  call hvA_f_listadd
  mov [hvFlags+78],rbx
hv_disp_tdone:
  mov dword ptr [hvFlags+50],0
hv_disp_tfin:
  mov esi,[hvFlags+80]
  test esi,esi
  je hv_disp_lfin
  lea rbx,[hvFlags+A00]
hv_disp_lloop:
  mov rcx,[rbx]
  test rcx,rcx
  je hv_disp_lnext
  mov edx,F4240
  xor r8d,r8d
  call hvA_f_loyal
hv_disp_lnext:
  add rbx,8
  dec esi
  jne hv_disp_lloop
  mov dword ptr [hvFlags+80],0
hv_disp_lfin:
  mov esi,[hvFlags+90]
  test esi,esi
  je hv_disp_gfin
  mov rbx,[hvFlags+98]
hv_disp_gloop:
  mov rcx,[rbx+08]
  mov rdx,[rbx+10]
  mov r8,[rbx+18]
  mov r9,[rbx+20]
  mov qword ptr [rsp+20],0
  call qword ptr [rbx]
  add rbx,28
  dec esi
  jne hv_disp_gloop
  mov dword ptr [hvFlags+90],0
hv_disp_gfin:
  add rsp,28
  pop rsi
  pop rbx
  pop r9
  pop r8
  pop rdx
  pop rcx
hv_disp_o:
  mov [rsp+08],rbx
  jmp hv_disp_ret
hvA_disp:
  jmp hv_disp
hv_disp_ret:
]==],
     sites={{'disp',5}}},
  },
}
HV.SIGS = {
  ANIMAL={['k']='rip',['il']=6,['dl']=2,['at']=44906947,['o']=0,['p']='8B 0D ?? ?? ?? ?? 83 B9 E0 00 00 00 00 75 ?? E8 ?? ?? ?? ?? 33 D2 48 8B CB E8 ?? ?? ?? ?? 48 89 47 48'},
  BCHI={['k']='rip',['p']='48 8D 0D 8B B0 87 05 E8 C6 97 B6 FF 48 8D 0D 87 AC 85 05 E8 BA 97 B6 FF',['at']=7565886,['o']=0,['dl']=3,['il']=7},
  BUILDUI={['k']='rip',['p']='48 8D 0D F1 12 81 05 E8 84 28 B3 FF 48 8D 0D CD 13 81 05 E8 78 28 B3 FF',['at']=7790976,['o']=0,['dl']=3,['il']=7},
  DEC={['k']='rip',['il']=6,['dl']=2,['at']=48756312,['o']=0,['p']='8B 05 ?? ?? ?? ?? 83 B8 E0 00 00 00 00 75 ?? 48 8B C8 E8 ?? ?? ?? ?? 48 8B 05 ?? ?? ?? ?? 48 8B 80 B8 00 00 00 80 78 6C 00 74 ?? F3 0F 58 F6'},
  FIC={['k']='rip',['il']=6,['dl']=2,['at']=26135503,['o']=0,['p']='8B 0D ?? ?? ?? ?? 44 39 A1 E0 00 00 00 75 ?? E8 ?? ?? ?? ?? 48 8B 0D ?? ?? ?? ?? 48 8B 89 B8 00 00 00 48 8B 43 18'},
  FMAF={['k']='rip',['il']=6,['dl']=2,['at']=22520840,['o']=0,['p']='8B 0D ?? ?? ?? ?? 48 8B D8 83 B9 E0 00 00 00 00 75 ?? E8 ?? ?? ?? ?? 48 8B 0D ?? ?? ?? ?? 48 8B 89 B8 00 00 00 48 8B 49 50 48 85 C9 0F 84 ?? ?? ?? ?? 4C 8B 05 ?? ?? ?? ?? 48 8B D3 E8 ?? ?? ?? ?? 4C 8B E8'},
  KJNF={['k']='rip',['p']='48 8D 0D D2 43 83 05 E8 9D 4B B3 FF 48 8D 0D 4E C9 87 05 E8 91 4B B3 FF',['at']=7781991,['o']=0,['dl']=3,['il']=7},
  MI_DICTSICLEAR={['k']='rip',['il']=6,['dl']=2,['at']=59011945,['o']=0,['p']='8B 15 ?? ?? ?? ?? E8 ?? ?? ?? ?? BE 06 00 00 00 BB 50 00 00 00'},
  MI_LSTRADD={['k']='rip',['il']=6,['dl']=2,['at']=7477997,['o']=0,['p']='8B 05 ?? ?? ?? ?? 48 8B 57 10 E8 ?? ?? ?? ?? 83 7F 58 01 0F 84 ?? ?? ?? ?? 48 8B 05 ?? ?? ?? ?? 83 B8 E0 00 00 00 00 75 ?? 48 8B C8 E8 ?? ?? ?? ?? 48 8B 05 ?? ?? ?? ?? 48 8B 80 B8 00 00 00 48 8B 88 C0 02 00 00'},
  MI_TEAMADD={['k']='rip',['il']=6,['dl']=2,['at']=22724283,['o']=0,['p']='8B 05 ?? ?? ?? ?? 49 8B D5 E8 ?? ?? ?? ?? 8B 84 24 10 01 00 00'},
  MI_TROOPADD={['k']='rip',['il']=6,['dl']=2,['at']=7506634,['o']=0,['p']='8B 05 ?? ?? ?? ?? 48 8B D3 E8 ?? ?? ?? ?? FF C6 E9 ?? ?? ?? ?? 48 8B 15 ?? ?? ?? ??'},
  NPC={['k']='rip',['il']=6,['dl']=2,['at']=10162277,['o']=0,['p']='8B 05 ?? ?? ?? ?? 48 8B 80 B8 00 00 00 48 8B 58 10 4C 8B 05 ?? ?? ?? ??'},
  OFFA={['k']='rip',['il']=6,['dl']=2,['at']=45035880,['o']=0,['p']='8B 05 ?? ?? ?? ?? 83 B8 E0 00 00 00 00 75 ?? 48 8B C8 E8 ?? ?? ?? ?? 48 8B 05 ?? ?? ?? ?? 48 8B 80 B8 00 00 00 48 8B 48 30 48 85 C9 74 ?? 33 D2 E8 ?? ?? ?? ?? 4C 8B 05 ?? ?? ?? ??'},
  OGEN={['k']='rip',['il']=6,['dl']=2,['at']=7459671,['o']=0,['p']='8B 05 ?? ?? ?? ?? 83 B8 E0 00 00 00 00 75 ?? 48 8B C8 E8 ?? ?? ?? ?? 48 8B 05 ?? ?? ?? ?? 48 8B 80 B8 00 00 00 48 8B 88 60 02 00 00 48 85 C9 0F 84 ?? ?? ?? ?? FF 41 1C'},
  TI_CHILDUI={['k']='rip',['il']=6,['dl']=2,['at']=47237486,['o']=0,['p']='8B 0D ?? ?? ?? ?? 48 8B 89 B8 00 00 00 E8 ?? ?? ?? ?? 45 8B E7'},
  TI_DCNI={['k']='rip',['il']=6,['dl']=2,['at']=48858992,['o']=0,['p']='8B 0D ?? ?? ?? ?? 0F B6 B0 C4 00 00 00 83 B9 E0 00 00 00 00'},
  TI_TEAM={['k']='rip',['il']=6,['dl']=2,['at']=22724212,['o']=0,['p']='8B 0D ?? ?? ?? ?? E8 ?? ?? ?? ?? 4C 8B E8 48 85 C0 0F 84 ?? ?? ?? ?? 33 D2 48 8B C8 E8 ?? ?? ?? ?? 45 33 C9'},
  TI_TROOP={['k']='rip',['il']=6,['dl']=2,['at']=7506497,['o']=0,['p']='8B 0D ?? ?? ?? ?? E8 ?? ?? ?? ?? 48 8B D8 48 85 C0 0F 84 ?? ?? ?? ?? 33 D2 48 8B C8 E8 ?? ?? ?? ?? 48 8B 05 ?? ?? ?? ?? 48 89 43 30'},
  UICITY={['k']='rip',['p']='48 8D 0D F2 9F 79 05 E8 05 84 A8 FF 48 8D 0D F6 E9 79 05 E8 F9 83 A8 FF',['at']=8488447,['o']=0,['dl']=3,['il']=7},
  UIHERO={['k']='rip',['il']=6,['dl']=2,['at']=9485458,['o']=0,['p']='8B 0D ?? ?? ?? ?? 48 8B 6C 24 38 83 B9 E0 00 00 00 00'},
  WAC={['k']='rip',['il']=6,['dl']=2,['at']=22612968,['o']=0,['p']='8B 0D ?? ?? ?? ?? 48 8B 81 B8 00 00 00 83 B8 54 01 00 00 03 0F 94 C0'},
  build={['k']='multi',['p']='F3 0F 10 4B 44 0F 28 C6 F3 0F 58 C1 48 C7 44 24 40 00 00 00 00 0F 2F 43 48 73 17 F3 0F 58 CE 0F 28 C6 F3 0F 11 4B 44 0F 28 74 24 20 48 83 C4 30 5B C3',['o']=0,['at']={37387333,37389173,37431397},['n']=3},
  deap01={['k']='multi',['p']='89 54 24 10 53 56 41 56 48 83 EC 40 80 3D 65 E9 1C 04 00 8B DA 48 89 6C',['at']={33039280},['o']=0,['n']=1},
  dehp0={['o']=0,['at']=33061028,['k']='code',['p']='29 BB EC 00 00 00 33 D2 01 7B 28 E8 ?? ?? ?? ?? 85 FF 79 ??'},
  disp={['o']=0,['at']=56069280,['k']='code',['p']='48 89 5C 24 08 57 48 81 EC 90 00 00 00 0F 29 B4 24 80 00 00 00 0F 29 7C 24 70'},
  estarea1={['o']=0,['at']=57435925,['k']='code',['p']='0F 85 ?? ?? ?? ?? 38 58 4C 0F 85 ?? ?? ?? ?? 39 58 78 0F 84 ?? ?? ?? ?? 48 8B 48 60 48 85 C9 0F 84 ?? ?? ?? ?? 48 8B 05 ?? ?? ?? ?? 8B B1 94 00 00 00 4C 89 BC 24 F8 00 00 00 44 8B B9 90 00 00 00 39 98 E0 00 00 00 75 ?? 48 8B C8 E8 ?? ?? ?? ?? 48 8B 05 ?? ?? ?? ?? 48 8B 0D ?? ?? ?? ?? 48 8B 80 B8 00 00 00 4C 8B B0 98 01 00 00'},
  estarea2={['o']=0,['at']=55984203,['k']='code',['p']='0F 85 ?? ?? ?? ?? 38 58 4C 0F 85 ?? ?? ?? ?? 39 58 78 0F 84 ?? ?? ?? ?? 48 8B 48 60 48 85 C9 0F 84 ?? ?? ?? ?? 48 8B 05 ?? ?? ?? ?? 8B B1 94 00 00 00 4C 89 BC 24 F8 00 00 00 44 8B B9 90 00 00 00 39 98 E0 00 00 00 75 ?? 48 8B C8 E8 ?? ?? ?? ?? 48 8B 05 ?? ?? ?? ?? 48 8B 0D ?? ?? ?? ?? 48 8B 80 B8 00 00 00 4C 8B B0 A0 01 00 00'},
  estforest={['k']='code',['p']='41 83 7E 34 02 48 8B 05 AB C2 70 03 74 25 83 B8 E0 00 00 00 00 75 0F 48',['at']=42414529,['o']=0},
  estlim1={['o']=0,['at']=52676474,['k']='code',['p']='7F ?? B0 01 48 8B 9C 24 20 01 00 00 48 81 C4 F0 00 00 00'},
  estlim2={['o']=0,['at']=52675174,['k']='code',['p']='7F ?? B0 01 48 8B 5C 24 40 48 8B 6C 24 50'},
  estpub1={['k']='code',['p']='83 78 34 01 0F 85 C4 00 00 00 33 D2 48 8B C8 E8 42 EB 01 FF 84 C0 0F 85',['at']=42436810,['o']=0},
  estpub2={['o']=0,['at']=42437248,['k']='code',['p']='41 83 7F 34 01 75 ?? 41 83 FE 01 0F 85 ?? ?? ?? ??'},
  f_additem={['o']=0,['at']=36978508,['k']='call',['p']='E8 ?? ?? ?? ?? 48 8B 15 ?? ?? ?? ?? 48 8B 82 B8 00 00 00 8B 88 44 02 00 00 83 C1 64'},
  f_addstatus={['o']=0,['at']=12481181,['k']='call',['p']='E8 ?? ?? ?? ?? 45 33 C9 45 33 C0 BA 14 00 00 00 48 8B CB'},
  f_birth={['o']=0,['at']=47236896,['k']='code',['p']='48 89 4C 24 08 53 56 57 41 54 41 55 41 56 41 57 48 81 EC 10 01 00 00 4C 8B E9 48 89 8C 24 E8 00 00 00'},
  f_conceive={['k']='code',['p']='48 89 74 24 10 57 48 83 EC 20 80 3D 3C E5 46 03 00 48 8B F2 48 8B F9 75',['at']=47080656,['o']=0},
  f_dictclear={['o']=0,['at']=3610312,['k']='call',['p']='E8 ?? ?? ?? ?? 4C 8B 05 ?? ?? ?? ?? 69 DB 11 03 CB FD 81 F3 38 7E EC B3'},
  f_heromove={['o']=0,['at']=27904225,['k']='call',['p']='E8 ?? ?? ?? ?? 48 8B 9F 18 01 00 00 48 85 DB 0F 84 ?? ?? ?? ?? 8B 5B 18'},
  f_listadd={['o']=0,['at']=3757387,['k']='call',['p']='E8 ?? ?? ?? ?? 41 FF C6 49 FF C5 E9 ?? ?? ?? ?? 80 BC 24 98 05 00 00 00'},
  f_loyal={['o']=0,['at']=22694656,['k']='call',['p']='E8 ?? ?? ?? ?? 45 33 C0 BA 2E 00 00 00 48 8B CF'},
  f_objnew={['o']=0,['at']=29207,['k']='call',['p']='E8 ?? ?? ?? ?? 48 8B 0D ?? ?? ?? ?? E8 ?? ?? ?? ?? 49 8B 4F 10 48 8B D0'},
  f_peff={['o']=0,['at']=15808605,['k']='call',['p']='E8 ?? ?? ?? ?? 45 38 77 7C 74 ?? 83 7E 20 02 7D ?? FF 46 20'},
  f_rel1={['k']='code',['p']='48 89 5C 24 20 56 57 41 57 48 83 EC 30 80 3D 3F A0 47 03 00 41 8B F0 0F',['at']=47032816,['o']=0},
  f_rel2={['o']=0,['at']=47258720,['k']='code',['p']='48 89 5C 24 08 48 89 6C 24 10 48 89 74 24 18 48 89 7C 24 20 41 56 48 83 EC 20 45 33 C0'},
  f_tp={['o']=0,['at']=14826704,['k']='code',['p']='48 8B C4 44 88 48 20 44 88 40 18 48 89 50 10 48 89 48 08 53 56 57 41 54 41 55 41 56 41 57 48 81 EC B0 00 00 00 0F 29 70 B8 45 0F B6 E8 4C 8B F2'},
  f_trpctor={['k']='code',['p']='48 89 5C 24 08 57 48 83 EC 20 80 3D D3 47 5C 05 00 48 8B D9 75 2B 48 8D',['at']=12085504,['o']=0},
  f_trpinit={['o']=0,['at']=7506579,['k']='call',['p']='E8 ?? ?? ?? ?? C7 43 50 88 13 00 00 48 8B 47 30'},
  f_wafoodchk={['o']=0,['at']=28248363,['k']='call',['p']='E8 ?? ?? ?? ?? B9 01 00 00 00 84 C0 48 0F 45 D9 48 8B 8F D0 00 00 00'},
  fiap={['k']='multi',['at']={26199408},['n']=1,['o']=0,['p']='89 54 24 10 53 56 41 56 48 83 EC 50 80 3D ?? ?? ?? ?? 00 8B DA 48 89 6C 24 70 48 8B F1 41 0F B6 E8 75 ?? 48 8D 0D ?? ?? ?? ?? E8 ?? ?? ?? ?? 48 8D 0D ?? ?? ?? ?? E8 ?? ?? ?? ?? 8B 5C 24 78 C6 05 ?? ?? ?? ?? 01 8B 4E 50 45 33 F6 03 CB 89 4E 50 78 ?? 8B D9 45 33 C0 48 8B CE 33 D2 E8 ?? ?? ?? ?? 3B D8 7E ?? 8B 5E 50 45 33 C0 48 89 BC 24 80 00 00 00 33 D2'},
  fihp0={['o']=0,['at']=26242544,['k']='code',['p']='8B 4B 40 4C 8B 43 18 03 CF 8B 73 30 89 4B 40 4D 85 C0 0F 84 ?? ?? ?? ?? 48 8B 15 ?? ?? ?? ?? 45 33 C9 48 89 AC 24 80 00 00 00 0F 29 74 24 50 66 0F 6E F1 B9 30 00 00 00 0F 5B F6 E8 ?? ?? ?? ??'},
  forge={['o']=0,['at']=38374903,['k']='code',['p']='0F 84 ?? ?? ?? ?? 48 8B 15 ?? ?? ?? ?? 83 BA E0 00 00 00 00 75 ?? 48 8B CA E8 ?? ?? ?? ?? 48 8B 15 ?? ?? ?? ?? 48 8B 92 B8 00 00 00 45 33 C0 48 8B 52 10 48 8B CE'},
  frz_askill={['k']='code',['p']='48 89 74 24 10 57 48 83 EC 40 80 3D 5E AB 31 04 00 8B F2 48 8B F9 75 73',['at']=31676784,['o']=0},
  frz_atk={['o']=0,['at']=31632736,['k']='code',['p']='48 8B C4 48 89 48 08 53 56 57 41 54 41 55 41 56 41 57 48 81 EC 90 02 00 00 0F 29 70 B8 0F 29 78 A8 44 0F 29 40 98 44 0F 29 48 88 44 0F 29 90 78 FF FF FF 44 0F 29 98 68 FF FF FF 44 0F 29 A0 58 FF FF FF 44 0F 29 A8 48 FF FF FF 44 0F 29 B0 38 FF FF FF 48 8B F9 4C 8B E9 48 89 8C 24 F0 00 00 00'},
  frz_hskill={['k']='code',['p']='48 89 5C 24 18 57 48 83 EC 50 80 3D B2 A6 31 04 00 8B DA 48 8B F9 75 67',['at']=31677920,['o']=0},
  frz_matk={['o']=0,['at']=31660512,['k']='code',['p']='48 8B C4 53 56 57 41 56 41 57 48 81 EC 30 01 00 00'},
  frz_move={['o']=0,['at']=31565552,['k']='code',['p']='48 89 5C 24 10 57 48 81 EC 90 00 00 00 80 3D ?? ?? ?? ?? 00 48 8B FA 48 8B D9 75 ?? 48 8D 0D ?? ?? ?? ?? E8 ?? ?? ?? ?? 48 8D 0D ?? ?? ?? ?? E8 ?? ?? ?? ?? 48 8D 0D ?? ?? ?? ?? E8 ?? ?? ?? ?? 48 8D 0D ?? ?? ?? ?? E8 ?? ?? ?? ?? C6 05 ?? ?? ?? ?? 01 F3 0F 10 47 04 F3 0F 10 17 F3 0F 10 4F 08 F3 0F 59 D2 F3 0F 59 C0 F3 0F 59 C9 F3 0F 58 D0 F2 0F 10 05 ?? ?? ?? ??'},
  socialEff={['o']=0,['at']=46825536,['k']='code',['p']='48 8B C4 48 89 70 20 57 48 81 EC 90 00 00 00'},
  speed={['o']=0,['at']=15285778,['k']='code',['p']='F3 0F 11 B9 A0 01 00 00 48 8B 05 ?? ?? ?? ?? 48 8B 88 B8 00 00 00'},
  speed2={['o']=0,['at']=14851812,['k']='code',['p']='45 0F 28 D3 F3 0F 59 FF 41 0F 28 C2 F3 45 0F 59 C0 F3 45 0F 59 C9 F3 41 0F 58 F8 F3 41 0F 59 C2 44 0F 28 84 24 C0 00 00 00 F3 41 0F 58 F9 44 0F 28 8C 24 B0 00 00 00 0F 2F C7 0F 28 BC 24 D0 00 00 00 0F 86 ?? ?? ?? ?? 48 8B 8B 98 01 00 00'},
  tech={['k']='code',['p']='41 8B C7 E9 79 FE FF FF E8 6C 29 82 FF 90 E8 66 29 82 FF 90 E8 F0 86 80',['at']=11002423,['o']=0},
  tp={['o']=0,['at']=15697776,['k']='code',['p']='48 89 5C 24 10 48 89 7C 24 18 55 48 8B EC 48 81 EC 80 00 00 00 80 3D ?? ?? ?? ?? 00 48 8B D9 75 ?? 48 8D 0D ?? ?? ?? ?? E8 ?? ?? ?? ?? 48 8D 0D ?? ?? ?? ?? E8 ?? ?? ?? ?? 48 8D 0D ?? ?? ?? ?? E8 ?? ?? ?? ?? 48 8D 0D ?? ?? ?? ??'},
  wacost={['o']=0,['at']=11797424,['k']='code',['p']='48 89 5C 24 18 48 89 6C 24 20 56 48 83 EC 20 80 3D ?? ?? ?? ?? 00 48 8B F2 48 8B D9 75 ?? 48 8D 0D ?? ?? ?? ?? E8 ?? ?? ?? ?? C6 05 ?? ?? ?? ?? 01 48 8B 83 E8 00 00 00 33 ED 48 89 7C 24 38 89 6C 24 30 48 85 C0 0F 84 ?? ?? ?? ?? 40 38 A8 93 00 00 00 0F 85 ?? ?? ?? ?? 48 85 F6 0F 84 ?? ?? ?? ?? 8B 8E 98 00 00 00 85 C9 74 ?? 83 E9 01 74 ?? 83 E9 01 74 ?? 83 E9 01 74 ?? 83 F9 01 75 ?? 40 38 A8 98 00 00 00 75 ??'},
  wadmg={['o']=0,['at']=11751555,['k']='code',['p']='80 B8 D8 00 00 00 00 0F 85 E8 04 00 00 F3 0F 10 4B 30 F3 41 0F 58 0E F3'},
  wadmg_skip={['o']=0,['at']=11752824,['k']='code',['p']='33 FF 41 89 3E 33 C0 EB ?? E8 ?? ?? ?? ?? CC E8 ?? ?? ?? ?? CC'},
  wafood={['o']=0,['at']=55775841,['k']='code',['p']='8B 80 50 01 00 00 2B C3 89 86 50 01 00 00 EB ?? 44 89 B8 50 01 00 00 EB ?? 48 8B 8E 60 01 00 00 48 85 C9 0F 84 ?? ?? ?? ?? 48 8B 15 ?? ?? ?? ?? E8 ?? ?? ?? ?? 48 85 C0 0F 84 ?? ?? ?? ?? 4C 8B 05 ?? ?? ?? ?? 48 8B D0 48 8D 8C 24 98 00 00 00 E8 ?? ?? ?? ?? 0F 10 84 24 98 00 00 00 0F 11 44 24 68 F2 0F 10 8C 24 A8 00 00 00 F2 0F 11 4C 24 78 4C 89 7C 24 40 48 8D 44 24 68 48 89 44 24 48 F3 0F 10 3D ?? ?? ?? ?? BF 64 00 00 00'},
  wafood_back={['o']=0,['at']=55775794,['k']='code',['p']='0F 28 B4 24 E0 00 00 00 0F 28 BC 24 D0 00 00 00 48 81 C4 F0 00 00 00 41 5F 41 5E 5F 5E 5B C3 48 8B 84 24 38 01 00 00 39 9E 50 01 00 00 7C ?? 8B 80 50 01 00 00 2B C3 89 86 50 01 00 00 EB ?? 44 89 B8 50 01 00 00 EB ?? 48 8B 8E 60 01 00 00 48 85 C9 0F 84 ?? ?? ?? ?? 48 8B 15 ?? ?? ?? ?? E8 ?? ?? ?? ?? 48 85 C0 0F 84 ?? ?? ?? ?? 4C 8B 05 ?? ?? ?? ?? 48 8B D0 48 8D 8C 24 98 00 00 00 E8 ?? ?? ?? ?? 0F 10 84 24 98 00 00 00 0F 11 44 24 68 F2 0F 10 8C 24 A8 00 00 00 F2 0F 11 4C 24 78 4C 89 7C 24 40 48 8D 44 24 68 48 89 44 24 48 F3 0F 10 3D ?? ?? ?? ?? BF 64 00 00 00'},
  waloss={['o']=0,['at']=11752190,['k']='code',['p']='29 71 50 40 38 7B 48 75 ?? 48 8B 4B 20'},
  wamor={['k']='code',['p']='45 33 C9 0F 28 CE E8 29 61 05 00 40 84 F6 0F 84 CE 01 00 00 48 83 BB 00',['at']=11727500,['o']=0},
  wause={['o']=0,['at']=11721616,['k']='code',['p']='48 89 5C 24 08 57 48 83 EC 20 80 3D ?? ?? ?? ?? 00 48 8B DA 48 8B F9 75 ?? 48 8D 0D ?? ?? ?? ?? E8 ?? ?? ?? ?? C6 05 ?? ?? ?? ?? 01 C7 44 24 38 00 00 00 00 48 85 DB 74 ?? 83 7B 6C 00 7E ?? 48 8B 8F F0 00 00 00 48 85 C9 74 ?? 4C 8B 0D ?? ?? ?? ?? 4C 8D 44 24 38 48 8B D3 E8 ?? ?? ?? ?? 84 C0 74 ?? 8B 43 6C 39 44 24 38 0F 9D C0'},
}
HV.BUILD = {ts=0x6AD9EEC1, size=0x67DC000}
HV.HOOKORIG = {
  [0xA7E237]='41 8B C7 E9 79 FE FF FF',
  [0xB2DB90]='48 89 5C 24 08 57',
  [0xB2F28C]='45 33 C9 0F 28 CE',
  [0xB35083]='80 B8 D8 00 00 00 00',
  [0xB352FE]='29 71 50 40 38 7B 48',
  [0xB403B0]='48 89 5C 24 18',
  [0xE29EE4]='45 0F 28 D3',
  [0xE93E12]='F3 0F 11 B9 A0 01 00 00',
  [0xEF8770]='48 89 5C 24 10 48 89 7C 24 18',
  [0x18FC570]='89 54 24 10 53',
  [0x1906DF0]='8B 4B 40 4C 8B 43 18',
  [0x1E1A6F0]='48 89 5C 24 10',
  [0x1E2AD60]='48 8B C4 48 89 48 08',
  [0x1E319E0]='48 8B C4 53 56',
  [0x1E35970]='48 89 74 24 10',
  [0x1E35DE0]='48 89 5C 24 18',
  [0x1F823B0]='89 54 24 10 53',
  [0x1F878A4]='29 BB EC 00 00 00',
  [0x23A7C45]='F3 0F 10 4B 44',
  [0x23A8375]='F3 0F 10 4B 44',
  [0x23B2865]='F3 0F 10 4B 44',
  [0x2498DF7]='0F 84 52 27 00 00',
  [0x28731C1]='41 83 7E 34 02',
  [0x28788CA]='83 78 34 01 0F 85 C4 00 00 00',
  [0x2878A80]='41 83 7F 34 01 75 0A',
  [0x2CA8040]='48 8B C4 48 89 70 20',
  [0x323C266]='7F 17',
  [0x323C77A]='7F 16',
  [0x3531261]='8B 80 50 01 00 00 2B C3 89 86 50 01 00 00',
  [0x356404B]='0F 85 47 03 00 00',
  [0x3578CA0]='48 89 5C 24 08',
  [0x36C6715]='0F 85 48 03 00 00',
}
HV.PEFF_STUB = [==[unregistersymbol(hvCallPeff)
alloc(hvCallPeff,$200,GameAssembly.dll)
registersymbol(hvCallPeff)
hvCallPeff:
  push rbx
  push rsi
  push rdi
  sub rsp,20
  mov rsi,rcx
  mov rdi,rdx
  call GameAssembly.il2cpp_domain_get
  mov rcx,rax
  call GameAssembly.il2cpp_thread_attach
  mov rbx,rax
  mov rcx,rsi
  mov rdx,rdi
  xor r8,r8
  call hvA_f_peff
  mov rcx,rbx
  call GameAssembly.il2cpp_thread_detach
  add rsp,20
  pop rdi
  pop rsi
  pop rbx
  ret
]==]

HV.NAMES = {
  [1]={"[ATTACH / ALL OFF] Attach to ThreeKingdom.exe + disable everything","【アタッチ／一括解除】ThreeKingdom.exeにアタッチ＋全機能オフ"},
  [2]={"0. Settings &amp; README","0. 設定・説明"},
  [3]={"Language / 言語設定","言語設定 / Language"},
  [4]={"English (default)","English（既定）"},
  [5]={"日本語 / Japanese","日本語 / Japanese"},
  [6]={"README","はじめに"},
  [7]={"1) Start the game, open this table (allow its Lua script), then run [ATTACH / ALL OFF] at the top.","1) ゲームを起動してこのテーブルを開き（Luaスクリプトの実行を許可）、先頭の【アタッチ／一括解除】を実行してください。"},
  [8]={"2) Made for game v1.0.13 (Steam build 26159462). Game code is located by AOB scan; on other builds a warning is shown and features whose code is not found are disabled.","2) 対応ゲームバージョンは 1.0.13 です（Steam ビルド 26159462）。ゲームコードはAOBスキャンで検出します。別ビルドでは警告を表示し、コードが見つからない機能は無効になります。"},
  [9]={"3) Orange = script (check to run / toggle), cyan = expandable group, no color = value (double-click to edit).","3) オレンジ＝スクリプト（チェックで実行／切替）、水色＝展開できるグループ、色なし＝値（ダブルクリックで直接入力）。"},
  [10]={"4) Messages appear in the Lua Engine window (0. &gt; Diagnostics &gt; Lua Engine).","4) メッセージはLua Engineウィンドウに表示されます（0. ＞ 診断 ＞ Lua Engine）。"},
  [11]={"5) Save your game before using editor / one-shot actions.","5) 書き換え系の操作の前にセーブしてください。"},
  [12]={"Diagnostics (only when the table does not work)","診断（動作しないときのみ）"},
  [13]={"Lua Engine (check = open / uncheck = close)","Lua Engine（チェックで開く／外すと閉じる）"},
  [14]={"AOB scan self-test (1-2 min, CE is busy; prints to Lua Engine)","AOBスキャンテスト（1～2分CEが応答しません。結果はLua Engineに表示）"},
  [15]={"Environment / connection info (CE, process, module, build)","環境・接続情報（CE・プロセス・モジュール・ビルド）"},
  [16]={"Status: unresolved code / active hooks / active features","状態：未検出コード／有効フック／有効機能"},
  [17]={"Game code not loaded into memory yet (prints to Lua Engine)","未読み込みのゲームコード（結果はLua Engineに表示）"},
  [100]={"1. Player hero","1. 主人公"},
  [101]={"Self invincible (player hero: duel / debate / war)","自分無敵（主人公: 決闘・討論・戦争）"},
  [102]={"Infinite action (AP never decreases: my side in duel &amp; debate)","無限行動（決闘・討論で自軍のAP減少なし）"},
  [103]={"Player status always max (stamina / mood, no drunk / poison)","状態常時最大（体力・心情、酒酔い・毒なし）"},
  [104]={"Max movement speed (world map, player)","移動速度最大（ワールドマップ・主人公）"},
  [105]={"Speed multiplier","速度倍率"},
  [106]={"Teleport (right-click destination = instant)","瞬間移動（右クリック移動先へ即時移動）"},
  [107]={"Player: all profession levels max","熟練度を全て最大"},
  [108]={"Player: base attributes = 100","基本能力を100に"},
  [109]={"Own power heroes: relation with player MAX (friendship/family, respect, gratitude, acknowledgement)","自勢力の全武将: 主人公との関係MAX（友情/親愛・敬意・感恩・共感）"},
  [110]={"Own power heroes: loyalty MAX (game max per hero)","自勢力の全武将: 忠誠MAX（武将ごとのゲーム上限）"},
  [111]={"Own power hero: transfer to a city (select hero -&gt; own city)","自勢力の武将を指定都市へ所属移動（武将→自勢力の都市）"},
  [112]={"Xianyun points (used in Xianyun Exchange with Nandou)","仙蘊ポイント（南斗の仙蘊交換で使用）"},
  [113]={"All existing heroes: relation with player MAX (friendship/family, respect, gratitude, acknowledgement)","存在する全武将: 主人公との関係MAX（友情/親愛・敬意・感恩・共感）"},
  [116]={"Hero conversation: show the developer test menu (***Test***; others unchanged)","武将との会話: 開発用テストメニュー（***テスト***）を表示（他の選択肢は通常どおり）"},
  [114]={"All spouses: create a child now (one spouse at a time; name each child in game)","全配偶者に子供を作成（1人ずつ・命名はゲーム画面で）"},
  [115]={"Stop pending child creation","子供作成の待機分を停止"},
  [200]={"2. Duel &amp; cockfight","2. 決闘・闘鶏"},
  [201]={"Duel invincible (my side + allies)","決闘無敵（自軍＋友軍）"},
  [202]={"Duel one-hit kill (enemies)","決闘一撃必殺（敵）"},
  [203]={"Cockfight invincible (my rooster + allied roosters)","闘鶏無敵（自軍＋友軍の鶏）"},
  [204]={"Cockfight one-hit kill (enemy roosters)","闘鶏一撃必殺（敵の鶏）"},
  [205]={"Duel units (enable to list)","決闘ユニット（有効化で一覧生成）"},
  [300]={"3. Debate","3. 討論（舌戦）"},
  [301]={"Debate invincible (my side + allies)","討論無敵（自軍＋友軍）"},
  [302]={"Debate one-hit kill (enemies)","討論一撃必殺（敵）"},
  [303]={"Debate units (enable to list)","討論ユニット（有効化で一覧生成）"},
  [400]={"4. War (army battle)","4. 戦争（軍団戦）"},
  [401]={"Protect my side","自軍保護"},
  [402]={"Battle invincible (my coalition takes no damage)","戦闘無敵（自軍側はダメージを受けない）"},
  [403]={"My soldiers do not decrease","自軍兵士減らない"},
  [404]={"My morale does not decrease","自軍士気減らない"},
  [405]={"My food does not decrease","自軍兵糧減らない"},
  [406]={"Boost my side","自軍強化"},
  [407]={"Infinite morale (keep my morale at max)","士気無限（自軍士気を常に最大）"},
  [408]={"Infinite food (my deploy teams 99999)","兵糧無限（自軍出陣部隊の兵糧99999）"},
  [409]={"Unlimited skill use (cost 0, no use limit)","スキル無限使用（消費0・回数制限なし）"},
  [410]={"Against enemies","敵への操作"},
  [411]={"War one-hit kill (enemy armies)","戦争一撃必殺（敵部隊）"},
  [412]={"Freeze enemy armies (no move / attack / skills)","敵部隊フリーズ（移動・攻撃・スキル停止）"},
  [413]={"Enemy soldiers = 0","敵兵士0"},
  [414]={"Enemy morale = 0","敵士気0"},
  [415]={"Enemy food = 0","敵兵糧0"},
  [416]={"Strategy points","策略点"},
  [417]={"My strategy points","自軍策略点"},
  [418]={"My strategy points max","自軍策略点上限"},
  [419]={"Ally strategy points","友軍策略点"},
  [420]={"Enemy strategy points","敵策略点"},
  [421]={"War armies (enable to list)","戦争部隊（有効化で一覧生成）"},
  [500]={"5. City &amp; domestic affairs","5. 都市・内政"},
  [501]={"Select city","都市の選択"},
  [502]={"Select: city the player is in (default)","選択: 主人公がいる都市（既定）"},
  [503]={"Select: city shown in City Info window","選択: 都市情報画面の都市"},
  [504]={"Select: search by name","選択: 名前で検索"},
  [505]={"Resources","資源"},
  [506]={"Money","資金"},
  [507]={"Food","兵糧"},
  [508]={"Population","人口"},
  [509]={"Security","治安"},
  [510]={"Popular support","民心"},
  [511]={"Popular support (owner power)","民心（所有勢力）"},
  [512]={"Popular support max (game constant)","民心上限（ゲーム定数）"},
  [513]={"Popular support MAX (owner power)","民心MAX（所有勢力）"},
  [514]={"Popular support MAX (all powers)","民心MAX（全勢力）"},
  [515]={"Popular support per power (enable to list)","勢力別の民心（有効化で一覧生成）"},
  [516]={"Development &amp; construction","開発・建築"},
  [517]={"Scale (0 small - 3 huge)","規模(0小～3巨大)"},
  [518]={"Tech points (city data)","技術点（都市データ）"},
  [519]={"Expansion days left","拡張残り日数"},
  [520]={"Max commerce &amp; agriculture of all blocks (base max)","全街区の商業・農業を最大に（基本上限）"},
  [521]={"Repair all walls (defense max)","城壁を全修復（城防最大）"},
  [522]={"Instant construction (buildings in the city/village the player is in)","建築即完成（主人公がいる都市・村の建物）"},
  [523]={"Instant construction (all cities, incl. AI)","建築即完成（全都市・AI含む）"},
  [524]={"Real estate: no plot-count limit when buying land / buildings","私産：土地・建物購入の区画数上限を解除"},
  [525]={"Real estate: buy buildings outside the private area (use with care)","私産：私有区以外の建物も購入可能（注意して使用）"},
  [526]={"Real estate / city: build anywhere (prefect: all blocks; private: all but government; re-enter the city after switching)","私産・都市：建設できる区域を拡大（太守の公共建設＝全区域、私産＝官府以外・切替後は都市に入り直す）"},
  [527]={"Garrison troops","保有部隊"},
  [528]={"Troop list (enable to list; refresh on collapse/reopen)","部隊一覧（有効化で一覧生成・閉じて開くと更新）"},
  [529]={"Garrison: soldiers to cap, wounded 0, EXP 100, morale max","兵士数を上限・負傷兵0・経験値100・士気最大"},
  [530]={"Garrison: change army kind (select troop, then kind)","兵種（兵装）を変更（部隊→兵種の順に選択）"},
  [531]={"Garrison: add a new troop (select army kind, then soldiers; EXP 100)","部隊を追加（兵種→兵士数の順に指定・経験値100）"},
  [532]={"Garrison: add 5 troops of Hubao cavalry [11702], 10000 soldiers each, EXP 100","虎豹騎 [11702] 兵士10000・経験値100を5部隊追加"},
  [533]={"Private troops (Private Army screen; selected city)","私兵部隊（私兵軍政・選択中の都市）"},
  [534]={"Private troop list (enable to list; refresh on collapse/reopen)","私兵部隊一覧（有効化で一覧生成・閉じて開くと更新）"},
  [535]={"Private troops: soldiers to cap, wounded 0, EXP 100, morale max","私兵：兵士数を上限・負傷兵0・経験値100・士気最大"},
  [600]={"6. Technology, research &amp; policy","6. 技術・研究・政策"},
  [601]={"Instant research","研究即完了"},
  [602]={"Research amount per day","1日あたり研究量"},
  [603]={"Infinite tech points (power + personal)","技術点無限（勢力＋個人）"},
  [604]={"Technology: max all (all layers, player power)","技術最大化（全段階・所属勢力）"},
  [605]={"Technology: acquire all (first layer, player power)","全技術取得（第1段階・所属勢力）"},
  [606]={"Technology: max all (personal/family tech)","技術最大化（個人・家族技術）"},
  [607]={"Power tech points","勢力技術点"},
  [608]={"Power treasury money (used for research)","国庫資金（研究に使用）"},
  [609]={"Personal tech points","個人技術点"},
  [610]={"Power policy points (strategy points)","勢力政策ポイント"},
  [611]={"Family policy points (strategy points)","家族政策ポイント"},
  [617]={"Reset policy cooldowns (power + family; same effect as the policy 「諸策継続」)","政策のクールタイムをリセット（勢力・家族。政策「諸策継続」と同じ効果）"},
  [612]={"Family mastery EXP (family menu)","家門の熟練度経験値（家族メニュー）"},
  [613]={"Military mastery EXP (Family Military)","軍事熟練度（従軍経験・家族従軍）"},
  [614]={"Commerce mastery EXP (Family Commerce)","商業熟練度（商業経験・家族商業）"},
  [615]={"Governance mastery EXP (Family Governance)","統治熟練度（政務経験・家族政務）"},
  [616]={"Profession EXP factor (global)","熟練経験倍率（全体）"},
  [7000]={"7. Hero editor","7. 武将エディタ"},
  [7001]={"Player (self)","主人公"},
  [7002]={"Basic","基本"},
  [7003]={"Money","所持金"},
  [7004]={"Age","年齢"},
  [7005]={"Lifespan","寿命"},
  [7006]={"Birth year","生年"},
  [7007]={"Morality","道徳"},
  [7008]={"Righteousness (-50000..50000)","正邪(-50000～50000)"},
  [7009]={"Condition","状態"},
  [7010]={"Stamina","体力(精力)"},
  [7011]={"Stamina max bonus (max = 800 + bonus + 2*(force+will))","体力上限ボーナス(上限=800+値+2×(武力+意志))"},
  [7012]={"Mood (0-1000)","心情(0-1000)"},
  [7013]={"Drunk (0-1000)","酒酔い(0-1000)"},
  [7014]={"Poison","毒"},
  [7015]={"Abilities","能力"},
  [7016]={"Base attributes","基本能力"},
  [7017]={"Leadership (rule)","統率"},
  [7018]={"Force","武力"},
  [7019]={"Intelligence (wise)","知力"},
  [7020]={"Politics","政治"},
  [7021]={"Charm","魅力"},
  [7022]={"Will","意志"},
  [7023]={"Attribute EXP","能力経験値"},
  [7024]={"Leadership (rule)","統率"},
  [7025]={"Force","武力"},
  [7026]={"Intelligence (wise)","知力"},
  [7027]={"Politics","政治"},
  [7028]={"Charm","魅力"},
  [7029]={"Will","意志"},
  [7030]={"Aptitude (talent)","資質"},
  [7031]={"Leadership (rule)","統率"},
  [7032]={"Force","武力"},
  [7033]={"Intelligence (wise)","知力"},
  [7034]={"Politics","政治"},
  [7035]={"Charm","魅力"},
  [7036]={"Will","意志"},
  [7037]={"Professions","熟練度"},
  [7038]={"Martial (7)","武芸系（7）"},
  [7039]={"Sword level","剣術 レベル"},
  [7040]={"Sword EXP","剣術 経験値"},
  [7041]={"Spear level","槍術 レベル"},
  [7042]={"Spear EXP","槍術 経験値"},
  [7043]={"Cavalry level","騎兵 レベル"},
  [7044]={"Cavalry EXP","騎兵 経験値"},
  [7045]={"Archer level","弓術 レベル"},
  [7046]={"Archer EXP","弓術 経験値"},
  [7047]={"Machine level","兵器 レベル"},
  [7048]={"Machine EXP","兵器 経験値"},
  [7049]={"Marine level","水軍 レベル"},
  [7050]={"Marine EXP","水軍 経験値"},
  [7051]={"Military level","軍略 レベル"},
  [7052]={"Military EXP","軍略 経験値"},
  [7053]={"Domestic (8)","内政系（8）"},
  [7054]={"Commerce level","商業 レベル"},
  [7055]={"Commerce EXP","商業 経験値"},
  [7056]={"Agriculture level","農業 レベル"},
  [7057]={"Agriculture EXP","農業 経験値"},
  [7058]={"Construct level","建築 レベル"},
  [7059]={"Construct EXP","建築 経験値"},
  [7060]={"Conscript level","徴兵 レベル"},
  [7061]={"Conscript EXP","徴兵 経験値"},
  [7062]={"Train level","訓練 レベル"},
  [7063]={"Train EXP","訓練 経験値"},
  [7064]={"Security level","治安 レベル"},
  [7065]={"Security EXP","治安 経験値"},
  [7066]={"Patrol level","巡察 レベル"},
  [7067]={"Patrol EXP","巡察 経験値"},
  [7068]={"Wall level","城壁 レベル"},
  [7069]={"Wall EXP","城壁 経験値"},
  [7070]={"Special (9)","特技系（9）"},
  [7071]={"Explore level","探索 レベル"},
  [7072]={"Explore EXP","探索 経験値"},
  [7073]={"Diplomacy level","外交 レベル"},
  [7074]={"Diplomacy EXP","外交 経験値"},
  [7075]={"Persuade level","説得 レベル"},
  [7076]={"Persuade EXP","説得 経験値"},
  [7077]={"Hide level","隠密 レベル"},
  [7078]={"Hide EXP","隠密 経験値"},
  [7079]={"Tech level","技術 レベル"},
  [7080]={"Tech EXP","技術 経験値"},
  [7081]={"Cure level","医術 レベル"},
  [7082]={"Cure EXP","医術 経験値"},
  [7083]={"Drink level","酒 レベル"},
  [7084]={"Drink EXP","酒 経験値"},
  [7085]={"Travel level","旅行 レベル"},
  [7086]={"Travel EXP","旅行 経験値"},
  [7087]={"Tame level","調教 レベル"},
  [7088]={"Tame EXP","調教 経験値"},
  [7089]={"Souls","魂"},
  [7090]={"Army soul","軍魂"},
  [7091]={"Martial soul","武魂"},
  [7092]={"Wisdom soul","智魂"},
  [7093]={"Status &amp; reputation","身分・名声"},
  [7094]={"Loyalty","忠誠"},
  [7095]={"Reputation (base)","名声(基本値)"},
  [7096]={"Influence (current power; player only)","発言力（所属勢力・主人公のみ）"},
  [7097]={"Rank","官位ランク"},
  [7098]={"Merit","功績"},
  [7099]={"Seasonal merit","季功績"},
  [7100]={"Duel bonus","決闘補正"},
  [7101]={"Duel HP max bonus","決闘HP上限ボーナス"},
  [7102]={"Duel MP max bonus","決闘MP上限ボーナス"},
  [7103]={"Records","戦績"},
  [7104]={"Battle wins","決闘勝利"},
  [7105]={"Debate wins","討論勝利"},
  [7106]={"Mock-war wins","模擬戦勝利"},
  [7107]={"Battle losses","決闘敗北"},
  [7108]={"Debate losses","討論敗北"},
  [7109]={"Mock-war losses","模擬戦敗北"},
  [7110]={"Selected hero","選択武将"},
  [7111]={"Select: hero shown in Hero Info window","選択: 武将情報画面の武将"},
  [7112]={"Select: search by name","選択: 名前で検索"},
  [7113]={"Select: player","選択: 主人公"},
  [7114]={"Selected hero: all profession levels max","選択武将: 熟練度を全て最大"},
  [7115]={"Selected hero: base attributes = 100","選択武将: 基本能力を100に"},
  [7116]={"Selected hero: relation with player MAX (friendship/family, respect, gratitude, acknowledgement)","選択武将: 主人公との関係MAX（友情/親愛・敬意・感恩・共感）"},
  [7117]={"Selected hero: loyalty MAX (game max)","選択武将: 忠誠MAX（ゲーム上限）"},
  [7118]={"Basic","基本"},
  [7119]={"Money","所持金"},
  [7120]={"Age","年齢"},
  [7121]={"Lifespan","寿命"},
  [7122]={"Birth year","生年"},
  [7123]={"Morality","道徳"},
  [7124]={"Righteousness (-50000..50000)","正邪(-50000～50000)"},
  [7125]={"Condition","状態"},
  [7126]={"Stamina","体力(精力)"},
  [7127]={"Stamina max bonus (max = 800 + bonus + 2*(force+will))","体力上限ボーナス(上限=800+値+2×(武力+意志))"},
  [7128]={"Mood (0-1000)","心情(0-1000)"},
  [7129]={"Drunk (0-1000)","酒酔い(0-1000)"},
  [7130]={"Poison","毒"},
  [7131]={"Abilities","能力"},
  [7132]={"Base attributes","基本能力"},
  [7133]={"Leadership (rule)","統率"},
  [7134]={"Force","武力"},
  [7135]={"Intelligence (wise)","知力"},
  [7136]={"Politics","政治"},
  [7137]={"Charm","魅力"},
  [7138]={"Will","意志"},
  [7139]={"Attribute EXP","能力経験値"},
  [7140]={"Leadership (rule)","統率"},
  [7141]={"Force","武力"},
  [7142]={"Intelligence (wise)","知力"},
  [7143]={"Politics","政治"},
  [7144]={"Charm","魅力"},
  [7145]={"Will","意志"},
  [7146]={"Aptitude (talent)","資質"},
  [7147]={"Leadership (rule)","統率"},
  [7148]={"Force","武力"},
  [7149]={"Intelligence (wise)","知力"},
  [7150]={"Politics","政治"},
  [7151]={"Charm","魅力"},
  [7152]={"Will","意志"},
  [7153]={"Professions","熟練度"},
  [7154]={"Martial (7)","武芸系（7）"},
  [7155]={"Sword level","剣術 レベル"},
  [7156]={"Sword EXP","剣術 経験値"},
  [7157]={"Spear level","槍術 レベル"},
  [7158]={"Spear EXP","槍術 経験値"},
  [7159]={"Cavalry level","騎兵 レベル"},
  [7160]={"Cavalry EXP","騎兵 経験値"},
  [7161]={"Archer level","弓術 レベル"},
  [7162]={"Archer EXP","弓術 経験値"},
  [7163]={"Machine level","兵器 レベル"},
  [7164]={"Machine EXP","兵器 経験値"},
  [7165]={"Marine level","水軍 レベル"},
  [7166]={"Marine EXP","水軍 経験値"},
  [7167]={"Military level","軍略 レベル"},
  [7168]={"Military EXP","軍略 経験値"},
  [7169]={"Domestic (8)","内政系（8）"},
  [7170]={"Commerce level","商業 レベル"},
  [7171]={"Commerce EXP","商業 経験値"},
  [7172]={"Agriculture level","農業 レベル"},
  [7173]={"Agriculture EXP","農業 経験値"},
  [7174]={"Construct level","建築 レベル"},
  [7175]={"Construct EXP","建築 経験値"},
  [7176]={"Conscript level","徴兵 レベル"},
  [7177]={"Conscript EXP","徴兵 経験値"},
  [7178]={"Train level","訓練 レベル"},
  [7179]={"Train EXP","訓練 経験値"},
  [7180]={"Security level","治安 レベル"},
  [7181]={"Security EXP","治安 経験値"},
  [7182]={"Patrol level","巡察 レベル"},
  [7183]={"Patrol EXP","巡察 経験値"},
  [7184]={"Wall level","城壁 レベル"},
  [7185]={"Wall EXP","城壁 経験値"},
  [7186]={"Special (9)","特技系（9）"},
  [7187]={"Explore level","探索 レベル"},
  [7188]={"Explore EXP","探索 経験値"},
  [7189]={"Diplomacy level","外交 レベル"},
  [7190]={"Diplomacy EXP","外交 経験値"},
  [7191]={"Persuade level","説得 レベル"},
  [7192]={"Persuade EXP","説得 経験値"},
  [7193]={"Hide level","隠密 レベル"},
  [7194]={"Hide EXP","隠密 経験値"},
  [7195]={"Tech level","技術 レベル"},
  [7196]={"Tech EXP","技術 経験値"},
  [7197]={"Cure level","医術 レベル"},
  [7198]={"Cure EXP","医術 経験値"},
  [7199]={"Drink level","酒 レベル"},
  [7200]={"Drink EXP","酒 経験値"},
  [7201]={"Travel level","旅行 レベル"},
  [7202]={"Travel EXP","旅行 経験値"},
  [7203]={"Tame level","調教 レベル"},
  [7204]={"Tame EXP","調教 経験値"},
  [7205]={"Souls","魂"},
  [7206]={"Army soul","軍魂"},
  [7207]={"Martial soul","武魂"},
  [7208]={"Wisdom soul","智魂"},
  [7209]={"Status &amp; reputation","身分・名声"},
  [7210]={"Loyalty","忠誠"},
  [7211]={"Reputation (base)","名声(基本値)"},
  [7212]={"Rank","官位ランク"},
  [7213]={"Merit","功績"},
  [7214]={"Seasonal merit","季功績"},
  [7215]={"Duel bonus","決闘補正"},
  [7216]={"Duel HP max bonus","決闘HP上限ボーナス"},
  [7217]={"Duel MP max bonus","決闘MP上限ボーナス"},
  [7218]={"Records","戦績"},
  [7219]={"Battle wins","決闘勝利"},
  [7220]={"Debate wins","討論勝利"},
  [7221]={"Mock-war wins","模擬戦勝利"},
  [7222]={"Battle losses","決闘敗北"},
  [7223]={"Debate losses","討論敗北"},
  [7224]={"Mock-war losses","模擬戦敗北"},
  [7225]={"Relation toward player","主人公との関係"},
  [7226]={"Friendship (relation value)","友情（関係値）"},
  [7227]={"Respect","敬意"},
  [7228]={"Gratitude","感恩"},
  [7229]={"Acknowledgement","共感"},
  [7230]={"Fear","恐怖"},
  [7231]={"Relation stage","関係段階（昇格）"},
  [7232]={"Social (chat screen)","社交（会話画面）"},
  [7233]={"Social Will (current; max 2-5 by relation level)","社交意欲（現在値。上限は関係レベルにより2～5）"},
  [7234]={"Awe +1 layer","畏敬を1層追加"},
  [7235]={"Obligation +1 layer","借りを1層追加"},
  [7236]={"Roused +1 layer","発奮を1層追加"},
  [7237]={"Romantic +1 layer","浪漫を1層追加"},
  [7238]={"Awe / Obligation / Roused / Romantic (enable to list: layers, days left)","畏敬・借り・発奮・浪漫（有効化で一覧生成: 層数・残り日数）"},
  [7239]={"Fix Social Effects (%)","社交効果を固定（％）"},
  [7240]={"Social Effects (%)","社交効果（％）"},
  [800]={"8. Items","8. アイテム"},
  [801]={"Forge without required materials (Forge screen)","製造: 必要素材なしで製造可能（製造画面）"},
  [802]={"Forge: learn all blueprints (all equipment that has a forge book)","製造: 設計図を一括記憶（製造書のある全装備）"},
  [803]={"Add item from list (category -&gt; item -&gt; count)","アイテムを一覧から追加（分類→アイテム→個数）"},
  [804]={"Get all map items x1 (map fragment / map / treasure map)","地図アイテムを一括入手（地図の断片・地図・宝の地図 各1個）"},
  [805]={"Get all \"*精要\" books x10 (Consumables / Other)","「〇〇精要」の本を一括入手（消耗品／その他、各10個）"},
  [806]={"Player items (enable to list; value = count)","主人公の所持品（有効化で一覧生成・値＝個数）"},
  [807]={"Selected hero items (enable to list; value = count)","選択武将の所持品（有効化で一覧生成・値＝個数）"},
  [808]={"Player power storage (enable to list; value = count)","所属勢力の所蔵品（有効化で一覧生成・値＝個数）"},
  [809]={"Get all skill books x1 (war / battle / debate skills)","全ての秘伝書を入手（軍技・武技・弁技 各1個）"},
  [810]={"Get all title certificates x1 (Books &amp; certificates / Title certificate)","全ての官職証書を入手（書物・証書／官職証書、各1個）"},
  [811]={"Identify all unidentified items (player items + power storage)","未鑑定品を一括で鑑定済みにする（主人公の所持品・勢力の所蔵品）"},
  [900]={"9. Pets","9. 保有ペット"},
  [901]={"Pet list (enable to list; refresh on collapse/reopen; value = double-click to edit)","保有ペット一覧（有効化で一覧生成・閉じて開くと更新・値はダブルクリックで編集）"},
  [1000]={"10. Accompanying teams","10. 同行部隊"},
  [1001]={"Accompanying team list (enable to list; refresh on collapse/reopen; value = double-click to edit)","同行部隊一覧（有効化で一覧生成・閉じて開くと更新・値はダブルクリックで編集）"},
  [1002]={"Add an accompanying team from the mercenary list (choose the mercenary, then soldiers)","同行部隊に傭兵を追加（一覧から傭兵→兵士数の順に指定）"},
}
HV.EXPGROUPS = {[806]='itp',[807]='its',[808]='itw',[528]='trp',[534]='prv',[901]='pet',[1001]='team'}
HV.ID_SELHERO = 7110
HV.ID_CITY = 500
HV.ID_TOP0 = 2
-- Re-entrancy guard for every timer of this table.
-- Changing an address-list record (Description, Active, create/destroy) and CE's sleep() let Windows
-- messages be processed, so a timer tick could start inside the previous tick (or inside a running action),
-- which started the next one inside it, and so on: the Lua C stack grew until "C stack overflow".
-- A guarded callback is skipped while another guarded callback or a user action is running.
HV.cbBusy=false
function HV.guard(fn)
  return function(...)
    if HV.pid and (HV.pid~=getOpenedProcessID() or not HV.processAlive()) then HV.forgetProcess() return end
    if HV.cbBusy or HV.inUser then return end
    HV.cbBusy=true
    local ok,e=pcall(fn,...)
    HV.cbBusy=false
    if not ok then print('[HV] '..tostring(e)) end
  end
end
-- One persistent dispatcher: never destroy a timer from its own modal callback.
HV.actionOff={}
if HV.actionTimer then HV.actionTimer.Enabled=false;HV.actionTimer.destroy() end
HV.actionTimer=createTimer(nil,false);HV.actionTimer.Interval=50
HV.actionTimer.OnTimer=function()
  if HV.inUser or HV.cbBusy then return end
  for id in pairs(HV.actionOff) do
    HV.actionOff[id]=nil
    local record=getAddressList().getMemoryRecordByID(id)
    if record then record.Active=false end
  end
  local job=HV.actionJob
  if not job then HV.actionTimer.Enabled=false;return end
  HV.actionJob=nil;HV.actionPending=false
  HV.actionName=job.name;HV.actionRecord=job.id
  local ok,e=pcall(HV.userRun,job.fn)
  HV.actionName=nil;HV.actionRecord=nil;HV.busyNotice=false
  HV.actionOff[job.id]=true
  if not ok then print('[HV] '..tostring(e)) end
end
function HV.oneShot(mr,fn)
  if HV.inUser or HV.actionPending then
    if not HV.busyNotice then HV.msg('An action is running. This click was not queued.','処理中のため、この操作は受け付けていません。待ち行列には追加しません。');HV.busyNotice=true end
    if mr.ID~=HV.actionRecord then HV.actionOff[mr.ID]=true end
    HV.actionTimer.Enabled=true;return
  end
  HV.actionJob={id=mr.ID,name=mr.Description,fn=fn};HV.actionPending=true
  HV.actionTimer.Enabled=true
end


----------------------------------------------------------------- helpers
local function rq(a) if not a or a==0 then return nil end local v=readQword(a) if v==0 then return nil end return v end
local function ri(a) if not a or a==0 then return nil end local v=readInteger(a) if v and v&gt;=0x80000000 then v=v-0x100000000 end return v end
HV.rq, HV.ri = rq, ri
function HV.T(en,ja) if HV.lang=='ja' then return ja or en end return en end
function HV.err(en,ja) error(HV.T(en,ja),0) end
function HV.msg(en,jp) print('[HV] '..HV.T(en,jp)) end

-- A cached module address/PID can survive process termination in CE.
function HV.processAlive()
  local pid=getOpenedProcessID()
  if not pid or pid==0 or getProcessIDFromProcessName(HV.EXE)~=pid then return false end
  local ga=getAddressSafe('GameAssembly.dll')
  return ga~=nil and readSmallInteger(ga)==0x5A4D
end
function HV.ga() if HV.processAlive() then return getAddressSafe('GameAssembly.dll') end end
function HV.st(key)
  local a=HV.A[key]; if not a then return nil end
  local ti=rq(a); if not ti then return nil end
  return rq(ti+0xB8)
end
function HV.klass(key) local a=HV.A[key]; if not a then return nil end return rq(a) end

function HV.utf16(p)
  if not p then return nil end
  local len=ri(p+0x10); if not len or len&lt;=0 or len&gt;512 then return nil end
  local b=readBytes(p+0x14,len*2,true); if not b then return nil end
  local out={} local i=1
  while i&lt;#b do
    local c=b[i]+b[i+1]*256; i=i+2
    if c&gt;=0xD800 and c&lt;=0xDBFF and i&lt;#b then local c2=b[i]+b[i+1]*256; i=i+2; c=0x10000+((c-0xD800)&lt;&lt;10)+(c2-0xDC00) end
    if c&lt;0x80 then out[#out+1]=string.char(c)
    elseif c&lt;0x800 then out[#out+1]=string.char(0xC0|(c&gt;&gt;6),0x80|(c&amp;0x3F))
    elseif c&lt;0x10000 then out[#out+1]=string.char(0xE0|(c&gt;&gt;12),0x80|((c&gt;&gt;6)&amp;0x3F),0x80|(c&amp;0x3F))
    else out[#out+1]=string.char(0xF0|(c&gt;&gt;18),0x80|((c&gt;&gt;12)&amp;0x3F),0x80|((c&gt;&gt;6)&amp;0x3F),0x80|(c&amp;0x3F)) end
  end
  return table.concat(out)
end
-- multilingual string holder: +10 zh-Hans, +18 zh-Hant, +20 en, +28 ja, +30 ko, +38 other
function HV.ml(p, all)
  if not p then return '' end
  if all then local t={} for _,o in ipairs({0x10,0x18,0x20,0x28}) do local s=HV.utf16(rq(p+o)) if s then t[#t+1]=s end end return table.concat(t,'|') end
  local order = (HV.lang=='ja') and {0x28,0x18,0x10,0x20} or {0x20,0x10,0x18,0x28}
  for _,o in ipairs(order) do local s=HV.utf16(rq(p+o)) if s and s~='' then return s end end
  return ''
end
function HV.heroName(h, all)
  if not h then return '?' end
  if all then return HV.ml(rq(h+0x10),true)..'/'..HV.ml(rq(h+0x18),true) end
  local s=HV.ml(rq(h+0x10)) local g=HV.ml(rq(h+0x18))
  if HV.lang=='en' and s~='' and g~='' and s:byte(1)&lt;0x80 then return s..' '..g end
  return s..g
end
function HV.listEach(l, cb)
  if not l then return end
  local items=rq(l+0x10); local n=ri(l+0x18) or 0
  if not items or n&lt;=0 or n&gt;100000 then return end
  for i=0,n-1 do local v=rq(items+0x20+i*8) if v then if cb(v,i)==false then return end end end
end
function HV.dictEach(d, cb)
  if not d then return end
  local ent=rq(d+0x18); local n=ri(d+0x20) or 0
  if not ent or n&lt;=0 or n&gt;200000 then return end
  for i=0,n-1 do
    local e=ent+0x20+i*0x18
    local h=ri(e)
    if h and h&gt;=0 then local k=rq(e+8) local v=rq(e+0x10) if v then if cb(k,v)==false then return end end end
  end
end

----------------------------------------------------------------- init / memory
function HV.init()
  if not HV.processAlive() then
    if HV.pid then HV.forgetProcess() end
    error(HV.T('Game is not running or not attached.','ゲームが起動していないか、未接続です。'),0)
  end
  HV.detached=false
  if HV.timer then HV.timer.Enabled=true end
  local pid=getOpenedProcessID()
  if not pid or pid==0 or not HV.ga() then error(HV.T('Not attached to ThreeKingdom.exe. Run [ATTACH / ALL OFF] at the top of the table first.','ThreeKingdom.exeにアタッチされていません。先にテーブル先頭の【アタッチ／一括解除】を実行してください。')) end
  if HV.pid==pid and getAddressSafe('hvFlags') then HV.updatePtrs();return true end
  HV.pid=pid; HV.hookState={}; HV.featOn={}
  HV.resolve()
  pcall(unregisterSymbol,'hvFlags'); pcall(unregisterSymbol,'hvVars'); pcall(unregisterSymbol,'hvPtrs'); pcall(unregisterSymbol,'hvUnits'); pcall(unregisterSymbol,'hvCallPeff')
  local ok=autoAssemble('alloc(hvFlags,$1000,GameAssembly.dll)\nregistersymbol(hvFlags)\n')
  if not ok then HV.err('Memory allocation failed (hvFlags).','メモリ確保に失敗しました（hvFlags）。') end
  local f=getAddress('hvFlags')
  registerSymbol('hvVars', f+HV.OFF_VARS, true)
  registerSymbol('hvPtrs', f+HV.OFF_PTRS, true)
  registerSymbol('hvUnits', f+0x400, true)
  pcall(unregisterSymbol,'hvJobs')
  if not autoAssemble('alloc(hvJobs,$3000,GameAssembly.dll)\nregistersymbol(hvJobs)\n') then HV.err('Memory allocation failed (hvJobs).','メモリ確保に失敗しました（hvJobs）。') end
  writeFloat(f+HV.OFF_VARS+0x20, 5.0)       -- speed multiplier
  writeInteger(f+HV.OFF_VARS+0x24, 100000)  -- research amount per day
  writeInteger(f+HV.OFF_VARS+0x28, 300)     -- social effect %
  HV.peffOK=nil
  HV.teamOK=nil
  HV.updatePtrs()
  return true
end
function HV.flagAddr(i) return getAddress('hvFlags')+i end

----------------------------------------------------------------- AOB resolver
-- Scanner: CE Auto Assembler "aobscanregion" (synchronous, the standard AOB mechanism of CE tables).
-- CE's multithreaded memscan (createMemScan/waitTillDone) and AOBScan are NOT used: called from the
-- table's GUI timer they returned incomplete results and could hang.
local function aaFind(pat, s, e)
  if e&lt;=s then return nil end
  pcall(unregisterSymbol,'hvScanTmp')
  local ok=autoAssemble(('aobscanregion(hvScanTmp,%X,%X,%s)\nregistersymbol(hvScanTmp)\n'):format(s,e,pat))
  if not ok then return nil end
  local a=getAddressSafe('hvScanTmp'); pcall(unregisterSymbol,'hvScanTmp')
  return a
end
-- all matches in [s,e), up to maxn
local function aobAll(pat, s, e, maxn)
  local r={}; local p=s
  while #r&lt;maxn do
    local a=aaFind(pat, p, e); if not a then break end
    r[#r+1]=a; p=a+1
  end
  return r
end
-- compare pattern with memory at a given address; returns ok, index of first mismatch
local function matchAt(a, pat)
  local toks={} for t in pat:gmatch('%S+') do toks[#toks+1]=t end
  local b=readBytes(a,#toks,true); if not b then return false,0 end
  for i,t in ipairs(toks) do if t~='??' and tonumber(t,16)~=b[i] then return false,i end end
  return true
end
local function dumpAt(name, a, pat)
  local ok,idx=matchAt(a,pat)
  local b=readBytes(a,48,true); local hx={}
  if b then for i=1,#b do hx[i]=string.format('%02X',b[i]) end end
  local prot='?'
  pcall(function() local ri2=getRegionInfo(a) if ri2 then prot=string.format('Protect=%X State=%X Type=%X',ri2.Protect or -1,ri2.State or -1,ri2.Type or -1) end end)
  print(('[HV] debug %s @GA+%X: match=%s firstMismatch=%s %s\n       mem=%s\n       pat=%s'):format(name,a-HV.ga(),tostring(ok),tostring(idx),prot,table.concat(hx,' '),pat))
end
-- self-test: scan every pattern with the AA scanner and compare with the known location of this build
function HV.scanSelfTest()
  HV.openLuaEngine(true)
  HV.init()
  local ga=HV.ga(); local size=getModuleSize and getModuleSize('GameAssembly.dll') or 0x7000000
  print(('[HV] self-test: GameAssembly.dll base=%X size=%X'):format(ga,size))
  local okn,bad=0,0
  local names={} for n in pairs(HV.SIGS) do names[#names+1]=n end table.sort(names)
  for _,name in ipairs(names) do
    local sg=HV.SIGS[name]
    local ats=(type(sg.at)=='table') and sg.at or {sg.at}
    local r=aobAll(sg.p, ga, ga+size, #ats+1)
    local same=(#r==#ats)
    if same then for i,x in ipairs(ats) do if r[i]~=ga+x then same=false end end end
    if same then okn=okn+1 else bad=bad+1
      local got={} for i,x in ipairs(r) do got[i]=string.format('GA+%X',x-ga) end
      print(('[HV]   %-12s expected %d at GA+%X, scanner found %d: %s  memMatch=%s'):format(name,#ats,ats[1],#r,table.concat(got,','),tostring(matchAt(ga+ats[1],sg.p))))
    end
  end
  HV.msg(('AOB self-test done: %d OK, %d NG.'):format(okn,bad),('AOBスキャンテスト完了: 正常 %d件、異常 %d件。'):format(okn,bad))
end
function HV.peTimestamp()
  local ga=HV.ga(); if not ga then return nil end
  local lf=ri(ga+0x3C); return lf and readInteger(ga+lf+8)
end
-- The game maps GameAssembly.dll into private memory and commits its code pages over time (observed:
-- MEM_PRIVATE regions with MEM_FREE holes that get filled while the game runs). A pattern whose page is
-- not committed yet cannot be found by any scanner; such signatures stay "pending" and are retried:
-- automatically (known locations, every few seconds) and whenever a feature needs them.
local function sigCands(sg) local c={sg} for _,x in ipairs(sg.alts or {}) do c[#c+1]=x end return c end
local function patLen(p) local n=0 for _ in p:gmatch('%S+') do n=n+1 end return n end
local function candTarget(c, m)
  local x=m+c.o
  if c.k=='code' then return x elseif c.k=='call' then return x+5+ri(x+1) end
  return x+c.il+ri(x+c.dl)
end
local HOOKSYMS  -- sym -&gt; length of hook site (for original bytes)
local function hookSyms()
  if HOOKSYMS then return HOOKSYMS end
  HOOKSYMS={}
  for _,list in pairs(HV.HOOKS) do for _,h in ipairs(list) do for _,st in ipairs(h.sites) do HOOKSYMS[st[1]]=st[2] end end end
  return HOOKSYMS
end
local function setA(k, x)
  rawset(HV.A, k, x); registerSymbol('hvA_'..k, x, true)
  local n=hookSyms()[k]; if n and not HV.orig[k] then HV.orig[k]=readBytes(x, n, true) end
  if k=='tech' then local t=x+8+ri(x+4) rawset(HV.A,'tech_tgt',t) registerSymbol('hvA_tech_tgt', t, true) end
end
-- base signature name of an HV.A key ('fiap_2' -&gt; 'fiap', 'tech_tgt' -&gt; 'tech')
local function sigOf(k)
  if HV.SIGS[k] then return k end
  if k=='tech_tgt' then return 'tech' end
  local b=k:match('^(.-)_%d+$'); if b and HV.SIGS[b] and HV.SIGS[b].k=='multi' then return b end
end
HV.sigOf=sigOf
-- hooks left behind by an earlier CE session: the pattern matches except at the hook site itself
local function toks(p) local t={} for x in p:gmatch('%S+') do t[#t+1]=x end return t end
local function matchSkip(a, pat, s, n)
  local t=toks(pat); local b=readBytes(a,#t,true); if not b then return false end
  local diff=false
  for i,x in ipairs(t) do
    local inSite=(i&gt;s and i&lt;=s+n)
    if inSite then if x~='??' and tonumber(x,16)~=b[i] then diff=true end
    elseif x~='??' and tonumber(x,16)~=b[i] then return false end
  end
  return diff
end
local function siteOrig(rva, n, pat, s)
  if HV.sameBuild and HV.HOOKORIG[rva] then
    local r={} for x in HV.HOOKORIG[rva]:gmatch('%x%x') do r[#r+1]=tonumber(x,16) end
    if #r==n then return r end
  end
  local t=toks(pat); local r={}
  for i=s+1,s+n do if not t[i] or t[i]=='??' then return nil end r[#r+1]=tonumber(t[i],16) end
  return r
end
local function markStale(k, orig) HV.orig[k]=orig; HV.stale[k]=true end
-- the bytes at a hook site look like a hook written by this table: "jmp" to code outside the module
-- (our alloc), or (same build only) a nop patch. Anything else is NOT treated as a leftover hook.
local function looksHooked(a, n)
  local b=readBytes(a, n, true); if not b then return false end
  local ga=HV.ga(); local size=getModuleSize and getModuleSize('GameAssembly.dll') or 0
  if b[1]==0xE9 then
    local rel=b[2]|(b[3]&lt;&lt;8)|(b[4]&lt;&lt;16)|(b[5]&lt;&lt;24); if rel&gt;=0x80000000 then rel=rel-0x100000000 end
    local t=a+5+rel
    return t&lt;ga or t&gt;=ga+size
  end
  if HV.sameBuild and (b[1]==0x90 or (b[1]==0x0F and b[2]==0x1F) or (b[1]==0x66 and (b[2]==0x90 or b[2]==0x0F))) then return true end
  return false
end
-- try to resolve one signature; allowScan: also run CE AOB scans (costly; used on other builds)
function HV.resolveSig(name, allowScan)
  local sg=HV.SIGS[name]; local ga=HV.ga(); if not sg or not ga then return false end
  local size=getModuleSize and getModuleSize('GameAssembly.dll') or 0x7000000
  HV.inResolve=true
  local ok=false
  if sg.k=='multi' then
    local ats=(type(sg.at)=='table') and sg.at or {sg.at}
    local r={}
    local sn=hookSyms()[name..'_1']; local st={}
    for _,x in ipairs(ats) do
      if matchAt(ga+x, sg.p) then r[#r+1]=ga+x
      elseif sn and matchSkip(ga+x, sg.p, 0, sn) and looksHooked(ga+x, sn) then local o=siteOrig(x, sn, sg.p, 0) if o then r[#r+1]=ga+x st[#r]=o end end
    end
    if #r~=#ats and allowScan then HV.scanned=(HV.scanned or 0)+1; r=aobAll(sg.p, ga, ga+size, sg.n+1); st={} end
    if #r&gt;=1 and #r&lt;=sg.n and (#r==#ats or allowScan) then
      for i,x in ipairs(r) do setA(name..'_'..i, x) if st[i] then markStale(name..'_'..i, st[i]) end end
      ok=true
    end
  else
    for _,c in ipairs(sigCands(sg)) do
      if matchAt(ga+c.at, c.p) then setA(name, candTarget(c, ga+c.at)) ok=true break end
    end
    local sn=(sg.k=='code') and hookSyms()[name]
    if not ok and sn and matchSkip(ga+sg.at, sg.p, sg.o, sn) and looksHooked(ga+sg.at+sg.o, sn) then
      local o=siteOrig(sg.at+sg.o, sn, sg.p, sg.o)
      if o then setA(name, ga+sg.at+sg.o) markStale(name, o) ok=true end
    end
    if not ok and allowScan then
      for _,c in ipairs(sigCands(sg)) do
        HV.scanned=(HV.scanned or 0)+1
        local r=aobAll(c.p, ga, ga+size, 2)
        if #r==1 then setA(name, candTarget(c, r[1])) ok=true break end
      end
    end
    if not ok and allowScan and sn then
      -- other build: the site may carry a leftover hook, so scan with the site bytes wildcarded;
      -- accept only when the site really looks like our hook (never "restore" bytes over unknown code)
      local t=toks(sg.p) for i=sg.o+1,sg.o+sn do t[i]='??' end
      HV.scanned=(HV.scanned or 0)+1
      local r=aobAll(table.concat(t,' '), ga, ga+size, 2)
      if #r==1 then
        local x=r[1]+sg.o
        if looksHooked(x, sn) then local o=siteOrig(x-ga, sn, sg.p, sg.o) if o then setA(name, x) markStale(name, o) ok=true end end
      end
    end
  end
  HV.inResolve=false
  if ok then HV.pend[name]=nil return true end
  -- not found: is the code there at all? (unreadable known location = page not committed yet)
  local nl,tot=0,0
  for _,c in ipairs(sigCands(sg)) do
    local ats=(type(c.at)=='table') and c.at or {c.at}
    for _,x in ipairs(ats) do tot=tot+1 if not readBytes(ga+x, patLen(c.p), true) then nl=nl+1 end end
  end
  HV.pend[name]={notLoaded=HV.sameBuild and nl==tot, unreadable=nl, total=tot, t=os.clock()}
  return false
end
-- HV.A[k] for a pending signature: retry once, remember it for the message shown after the action
local AMT={__index=function(t,k)
  if HV.inResolve or type(k)~='string' then return nil end
  local s=sigOf(k); if not s or not HV.pend or not HV.pend[s] then return nil end
  local p=HV.pend[s]
  local scan=(not HV.sameBuild) and HV.userAct and (os.clock()-(p.t or 0)&gt;20)
  if HV.resolveSig(s, scan) then HV.msg('Game code is now loaded: '..s, 'ゲームコードが読み込まれました: '..s) return rawget(t,k) end
  if HV.missNote then HV.missNote[s]=true end
  return nil
end}
function HV.resolve()
  if not HV.processAlive() then HV.forgetProcess() return end
  for k in pairs(HV.A) do pcall(unregisterSymbol,'hvA_'..k) end
  HV.A=setmetatable({}, AMT); HV.orig={}; HV.pend={}; HV.stale={}; HV.scanned=0
  local ga=HV.ga(); if not ga then return end
  HV.sameBuild=(HV.peTimestamp()==HV.BUILD.ts)
  if HV.sameBuild then print('[HV] '..HV.T('Checking game code (build matches this table)...','ゲームコードを確認中（このテーブル対応のビルドです）...'))
  else print('[HV] '..HV.T('Searching game code (AOB scan, other build)...','ゲームコードを検索中（AOBスキャン・別ビルド）...')) end
  local names={} for n in pairs(HV.SIGS) do names[#names+1]=n end table.sort(names)
  for _,n in ipairs(names) do HV.resolveSig(n, not HV.sameBuild) end
  if HV.scanned&gt;0 then HV.msg(('AOB-scanned %d patterns.'):format(HV.scanned),('%d件のパターンをAOBスキャンしました。'):format(HV.scanned)) end
  HV.missing=HV.pendingNames()
  local total=#names; local found=total-#HV.missing
  if #HV.missing==0 then
    print('[HV] '..HV.T(('Done: all game code found (%d/%d). Addresses matched; gameplay effects are not verified.'):format(found,total),
                        ('完了: 全てのゲームコードを確認しました（%d/%d）。アドレスの一致を確認しました。各機能の動作確認を意味するものではありません。'):format(found,total)))
  else
    print('[HV] '..HV.T(('Done: %d/%d game code found. Not loaded into memory yet (or not found): '):format(found,total),
                        ('完了: ゲームコード %d/%d を確認。まだメモリに読み込まれていない（または見つからない）もの: '):format(found,total))..table.concat(HV.missing,', '))
    print('[HV] '..HV.T('Functions with matching code may be available. This game loads its code while it runs: the table re-checks every 5 s and tells you when the rest is loaded.',
                        '一致したコードを使う機能は個別に確認できます。このゲームは実行中にコードを読み込むため、テーブルが5秒ごとに再確認し、読み込まれたらお知らせします。'))
  end
  local sl={} for k in pairs(HV.stale) do sl[#sl+1]=k end table.sort(sl)
  if #sl&gt;0 then
    print('[HV] '..HV.T(('Hooks from an earlier Cheat Engine session are still in the game (%d sites: %s). Features enabled back then may still be active. Run [ATTACH / ALL OFF] to remove them.'):format(#sl,table.concat(sl,', ')),
                        ('以前のCheat Engineのセッションで書き込んだフックが、ゲームに残っています（%dか所: %s）。当時有効にした機能が今も効いている可能性があります。【アタッチ／一括解除】で元に戻せます。'):format(#sl,table.concat(sl,', '))))
  end
  HV.startPendTimer()
  local ts=HV.peTimestamp()
  local fmt=function(t) local ok,d=pcall(os.date,'!%Y-%m-%d %H:%M:%S UTC',t) return ok and d or '?' end
  if ts and ts&gt;0 and HV.processAlive() and ts~=HV.BUILD.ts then
    local msg=HV.T(("GameAssembly.dll is not the build this table was made for.\n\n"..
      "Table built for : %s (0x%08X)\nThis game       : %s (0x%08X)\n\n"..
      "The table locates game code by AOB pattern scan, so many features may still work.\n"..
      "However, data layouts may have changed: using this table on a different build can\n"..
      "CRASH THE GAME or corrupt your save. Save your game before using any feature.\n\n"..
      "Patterns not found: %d%s"):format(fmt(HV.BUILD.ts),HV.BUILD.ts,fmt(ts or 0),ts or 0,#HV.missing,
      #HV.missing&gt;0 and ("\n(not found now: "..table.concat(HV.missing,', ')..".\nThe game loads code while it runs, so some of them may be found later.)") or ''),
      ("GameAssembly.dll が、このテーブルの対応ビルドではありません。\n\n"..
      "対応ビルド : %s (0x%08X)\nこのゲーム : %s (0x%08X)\n\n"..
      "ゲームコードはAOBパターンで検索するため、多くの機能は動く可能性があります。\n"..
      "ただしデータ構造が変わっている可能性があり、別ビルドで使うと\n"..
      "ゲームがクラッシュしたり、セーブデータが壊れたりするおそれがあります。使う前にセーブしてください。\n\n"..
      "見つからないパターン: %d%s"):format(fmt(HV.BUILD.ts),HV.BUILD.ts,fmt(ts or 0),ts or 0,#HV.missing,
      #HV.missing&gt;0 and ("\n（現在見つからないもの: "..table.concat(HV.missing,', ').."。\nこのゲームは実行中にコードを読み込むため、後で見つかる場合があります）") or ''))
    print('[HV] '..HV.T('WARNING: ','警告: ')..msg)
    if not HV.warned or HV.warned~=getOpenedProcessID() then HV.warned=getOpenedProcessID(); pcall(showMessage,msg) end
  end
end
function HV.pendingNames()
  local r={} for n in pairs(HV.pend or {}) do r[#r+1]=n end table.sort(r) return r
end
-- background retry (known locations only: cheap readBytes)
function HV.startPendTimer()
  if HV.pendTimer then return end
  HV.pendTimer=createTimer(nil,false); HV.pendTimer.Interval=5000
  HV.pendTimer.OnTimer=HV.guard(function()
    if HV.pid and (getOpenedProcessID()~=HV.pid or getProcessIDFromProcessName(HV.EXE)~=HV.pid) then
      HV.msg('Game process changed or exited. Run [ATTACH / ALL OFF] again.','ゲームプロセスが変わったか終了しました。【アタッチ／一括解除】を再実行してください。')
      HV.forgetProcess() return
    end
    if not HV.pend or not next(HV.pend) or getOpenedProcessID()~=HV.pid then return end
    for _,n in ipairs(HV.pendingNames()) do
      if HV.resolveSig(n, false) then HV.msg('Game code is now loaded: '..n, 'ゲームコードが読み込まれました: '..n) end
    end
    if not next(HV.pend) then HV.msg('All game code is now loaded. Addresses matched; gameplay effects are not verified.', '全てのゲームコードが読み込まれました。アドレスの一致を確認しました。各機能の動作確認を意味するものではありません。') end
  end)
  HV.pendTimer.Enabled=true
end
-- where the code of a signature lives: game scenes to try (from the classes containing the pattern sites)
local SCENES={ {'^Fi_','a duel','決闘'}, {'^De_','a debate','討論'}, {'^Wa_','a war battle','戦争（合戦）'},
  {'^Wo_','army/transport orders on the world map','ワールドマップの部隊操作'}, {'^Ci_','a city scene','都市シーン'},
  {'^Mb_','the city building screen','都市の建設画面'} }
local function sceneOf(fn)
  if not fn then return nil end
  for _,s in ipairs(SCENES) do if fn:match(s[1]) then return HV.T(s[2],s[3]) end end
  local ui=fn:match('^UI_(%w+)UI%$%$') or fn:match('^UI_(%w+)%$%$')
  if ui then return HV.T('the "'..ui..'" screen','「'..ui..'」画面') end
end
function HV.pendingText(list)
  local sc,seen={}, {}
  for _,n in ipairs(list) do local sg=HV.SIGS[n]
    for _,c in ipairs(sigCands(sg)) do local s=sceneOf(c.fn) if s and not seen[s] then seen[s]=true sc[#sc+1]=s end end end
  local nl=true for _,n in ipairs(list) do if not (HV.pend[n] and HV.pend[n].notLoaded) then nl=false end end
  local t
  if nl then
    t=HV.T('The game code this feature needs is not loaded into memory yet: ','この機能に必要なゲームコードが、まだメモリに読み込まれていません: ')..table.concat(list,', ')..'\n\n'..
      HV.T('This game loads its code while it runs. Playing on a little, or showing a related scene once, may load it.',
           'このゲームは実行中にコードを読み込みます。ゲームを少し進めるか、関係する場面を一度表示すると読み込まれる場合があります。')
    if #sc&gt;0 then t=t..'\n'..HV.T('Scenes where this code is used: ','このコードが使われる場面: ')..table.concat(sc,' / ',1,math.min(#sc,6)) end
    t=t..'\n\n'..HV.T('Then run this feature again. (Status: 0. Settings &gt; Diagnostics: game code not loaded yet)',
                      'その後、もう一度この機能を実行してください。（状況確認: 0. 設定・説明 &gt; 診断: 未読み込みのゲームコード）')
  else
    t=HV.T('The game code this feature needs was not found: ','この機能に必要なゲームコードが見つかりません: ')..table.concat(list,', ')..'\n\n'..
      HV.T('It may not be loaded yet, or it was changed by a game update.','まだ読み込まれていないか、ゲームのアップデートで変更された可能性があります。')
  end
  return t
end
-- run a user action; afterwards tell the user about game code that was needed but is not loaded
-- one user action at a time. CE's sleep() on the main thread processes window messages, so a click on
-- another entry while an action waits for the game (troop add, relation MAX, ...) used to run that entry
-- *inside* the waiting one. Repeated, this nested deeper and deeper until "C stack overflow".
-- Such calls are now queued and run one by one from a timer (fresh, shallow stack).
HV.uq = HV.uq or {}
function HV.kickQueue() HV.uq={} end
function HV.userRun(fn)
  if HV.inUser then
    HV.msg('An action is running; this operation was not queued.','処理中のため、この操作は待ち行列へ追加しません。')
    return false
  end
  HV.inUser=true
  HV.userAct=true; HV.missNote={}
  local ok,err=pcall(fn)
  HV.inUser=false
  HV.userAct=false
  if HV.pid and (HV.pid~=getOpenedProcessID() or not HV.processAlive()) then HV.forgetProcess() end
  if HV.detached then HV.missNote=nil return false end
  local l={} for n in pairs(HV.missNote or {}) do if HV.pend[n] then l[#l+1]=n end end table.sort(l)
  HV.missNote=nil
  if #l&gt;0 then local t=HV.pendingText(l) print('[HV] '..t) pcall(showMessage,t)
  elseif not ok then local m=tostring(err) print('[HV] '..m) pcall(showMessage,m) end
  if #HV.uq&gt;0 then HV.kickQueue() end
  return ok
end
-- diagnostics: state of pending signatures
function HV.pendingReport()
  HV.openLuaEngine(true)
  HV.init()
  local ga=HV.ga(); local size=getModuleSize('GameAssembly.dll')
  local c,f=0,0
  pcall(function() for _,r in ipairs(enumMemoryRegions()) do
    local b=r.BaseAddress
    if b&gt;=ga and b&lt;ga+size then if r.State==0x1000 then c=c+r.RegionSize else f=f+r.RegionSize end end end end)
  if c+f&gt;0 then print(('[HV] GameAssembly.dll: %.1f%% of its memory is loaded (committed).'):format(100*c/(c+f))) end
  for _,n in ipairs(HV.pendingNames()) do HV.resolveSig(n, false) end
  local l=HV.pendingNames()
  if #l==0 then print('[HV] '..HV.T('All game code is located.','全てのゲームコードを確認済みです。')) return end
  for _,n in ipairs(l) do
    local p=HV.pend[n]
    print(('[HV]   %-12s %s  (%d/%d pattern sites unreadable)'):format(n, p.notLoaded and HV.T('not loaded yet','未読み込み') or HV.T('not found','見つからない'), p.unreadable, p.total))
    for _,cd in ipairs(sigCands(HV.SIGS[n])) do
      local x=(type(cd.at)=='table') and cd.at[1] or cd.at
      print(('[HV]       GA+%-8X %-9s %s'):format(x, readBytes(ga+x,1,true) and 'loaded' or 'NOT LOADED', cd.fn or ''))
    end
  end
end

----------------------------------------------------------------- hook manager
local function siteBytesText(sym)
  local b=HV.orig[sym]; if not b then return nil end
  local t={} for i=1,#b do t[i]=string.format('%02X',b[i]) end
  return 'hvA_'..sym..':\n  db '..table.concat(t,' ')..'\n'
end
local function restoreHook(h)
  local n=0
  for _,st in ipairs(h.sites) do
    local x=HV.A[st[1]]; local b=HV.orig[st[1]]
    if x and b then
      local cur=readBytes(x,#b,true); local diff=false
      if cur then for i=1,#b do if cur[i]~=b[i] then diff=true break end end end
      if diff and autoAssemble(siteBytesText(st[1])) then n=n+1 end
    end
  end
  h.on=false
  return n
end
HV.restoreHook=restoreHook
function HV.hookUse(name, on)
  HV.hookState[name]=HV.hookState[name] or {ref=0}
  local s=HV.hookState[name]
  if on then
    if s.ref==0 then
      local done,errs,skipped=0,{},0
      for _,h in ipairs(HV.HOOKS[name]) do
        local ready=true
        local deps={} for _,st in ipairs(h.sites) do deps[st[1]]=true end
        for sym in h.en:gmatch('hvA_([%w_]+)') do deps[sym]=true end
        for sym in pairs(deps) do if not HV.A[sym] then ready=false end end   -- pending code is retried here
        for _,st in ipairs(h.sites) do if not HV.orig[st[1]] then ready=false end end
        if ready then
          local ok,err=autoAssemble(h.en)
          if ok then h.on=true; done=done+1 else restoreHook(h); errs[#errs+1]=tostring(err) end
        else skipped=skipped+1 end
      end
      if done==0 then
        local l={} for n in pairs(HV.missNote or {}) do if HV.pend[n] then l[#l+1]=n end end table.sort(l)
        if #l&gt;0 then error(HV.pendingText(l),0) end
        error(HV.T('Feature unavailable: game code for "'..name..'" was not found in this build. ',
                   'この機能は使えません: このビルドでは「'..name..'」のゲームコードが見つかりません。')..table.concat(errs,' / '),0)
      end
      if skipped&gt;0 or #errs&gt;0 then HV.msg(('Hook "%s": %d of %d sites applied.'):format(name,done,#HV.HOOKS[name]),
                                          ('フック「%s」: %d/%dか所を適用。'):format(name,done,#HV.HOOKS[name])) end
    end
    s.ref=s.ref+1
  else
    if s.ref&gt;0 then
      s.ref=s.ref-1
      if s.ref==0 then for _,h in ipairs(HV.HOOKS[name]) do if h.on then restoreHook(h) end end end
    end
  end
end

HV.tasks = HV.tasks or {}
HV.F = {
  godSelf    ={flags={0},     hooks={'fiHP','deHP','warDmg'}},
  fiGodSide  ={flags={1},     hooks={'fiHP'}},
  fiOneHit   ={flags={2},     hooks={'fiHP'}},
  deGodSide  ={flags={3},     hooks={'deHP'}},
  deOneHit   ={flags={4},     hooks={'deHP'}},
  infAP      ={flags={5},     hooks={'fiAP','deAP'}},
  warInv     ={flags={6},     hooks={'warDmg'}},
  warOneHit  ={flags={7},     hooks={'warDmg'}},
  warNoLoss  ={flags={8},     hooks={'warLoss'}},
  warMorale  ={flags={9},     hooks={'warMorale'}},
  warFood    ={flags={10},    hooks={'warFood'}},
  warSkill   ={flags={11,12}, hooks={'warSkill'}},
  speed      ={flags={13},    hooks={'speed'}},
  teleport   ={flags={14},    hooks={'teleport'}},
  techInstant={flags={15},    hooks={'tech'}},
  buildAll   ={flags={16},    hooks={'build'}},
  buildHere  ={flags={17},    hooks={'build'}},
  forgeMat   ={hooks={'forgeMat'}},
  estLimit   ={hooks={'estLimit'}},
  estArea    ={hooks={'estArea'}},
  estLand    ={flags={23},    hooks={'estForest','estPub'}},
  warFreeze  ={flags={20},    hooks={'warFreeze'}},
  socialEff  ={flags={21},    hooks={'socialEff'}},
  cockGod    ={flags={18},    hooks={'fiHP'}},
  cockOneHit ={flags={19},    hooks={'fiHP'}},
  warMoraleMax={task='warMoraleMax'},
  warFoodMax ={task='warFoodMax'},
  techPts    ={task='techPts'},
  playerStat ={task='playerStat'},
}
function HV.feature(name, on)
  if not on and (HV.detached or not HV.processAlive()) then return end
  if on then HV.init() elseif not HV.featOn or not HV.featOn[name] then return end
  local f=HV.F[name]
  if on then
    if HV.featOn[name] then return end
    HV.userAct=true; HV.missNote={}
    for i,h in ipairs(f.hooks or {}) do
      local ok,err=pcall(HV.hookUse,h,true)
      if not ok then HV.userAct=false; HV.missNote=nil for j=i-1,1,-1 do HV.hookUse(f.hooks[j],false) end error(err,0) end
    end
    HV.userAct=false; HV.missNote=nil
    for _,b in ipairs(f.flags or {}) do writeBytes(HV.flagAddr(b),1) end
    if f.task then HV.tasks[f.task]=true end
    HV.featOn[name]=true
  else
    for _,b in ipairs(f.flags or {}) do writeBytes(HV.flagAddr(b),0) end
    for _,h in ipairs(f.hooks or {}) do pcall(HV.hookUse,h,false) end
    if f.task then HV.tasks[f.task]=nil end
    HV.featOn[name]=nil
  end
end

----------------------------------------------------------------- conversation: developer test menu
-- options: OGEN static +0x130 Dictionary&lt;string, option&gt;; option +0x28 name (multilingual), +0xC8 children,
-- +0x68 show conditions (List&lt;string&gt;), +0x70 selectable conditions (List&lt;string&gt;).
-- The game treats an empty condition list as "passed", so the lists are emptied (count=0) and restored on OFF.
HV.talkTestSaved = HV.talkTestSaved or nil
local function isTestName(o)
  local s=HV.ml(rq(o+0x28),true)
  if not s:find('***',1,true) then return false end
  local l=s:lower()
  return s:find('测试',1,true) or s:find('測試',1,true) or s:find('テスト',1,true) or l:find('test',1,true)
end
function HV.talkTest(on)
  if not on and HV.detached then HV.talkTestSaved=nil;return end
  if not on then
    local sv=HV.talkTestSaved; HV.talkTestSaved=nil
    if sv then for _,x in ipairs(sv) do if ri(x.l+0x18)==0 then writeInteger(x.l+0x18,x.n) end end end
    return
  end
  HV.init()
  if HV.talkTestSaved then return end
  local og=HV.st('OGEN'); local d=og and rq(og+0x130)
  if not d then HV.err('Conversation data not found (load a save first).','会話データが見つかりません（セーブデータをロードしてください）。') end
  local roots={}
  HV.dictEach(d, function(k,o) if isTestName(o) then roots[#roots+1]=o end end)
  if #roots==0 then HV.err('The test menu was not found in the conversation data.','会話データにテストメニューが見つかりません。') end
  local seen,sv,names={},{},{}
  local function walk(o, depth)
    if not o or seen[o] or depth&gt;8 then return end
    seen[o]=true
    for _,off in ipairs({0x68,0x70}) do
      local l=rq(o+off); local n=l and ri(l+0x18)
      if n and n&gt;0 and n&lt;1000 then sv[#sv+1]={l=l,n=n} writeInteger(l+0x18,0) end
    end
    HV.listEach(rq(o+0xC8), function(c) walk(c, depth+1) end)
  end
  for _,o in ipairs(roots) do names[#names+1]=HV.ml(rq(o+0x28)) walk(o,0) end
  HV.talkTestSaved=sv
  local cnt=0 for _ in pairs(seen) do cnt=cnt+1 end
  HV.msg(('Test menu enabled: %s (%d options, %d condition lists cleared). Reopen the conversation.'):format(table.concat(names,', '),cnt,#sv),
         ('テストメニューを表示: %s（選択肢%d個、条件リスト%d個を解除）。会話を開き直してください。'):format(table.concat(names,', '),cnt,#sv))
end

----------------------------------------------------------------- pointer slots
function HV.heroCtx(base, h)
  local story=h and rq(h+0x120)
  writeQword(base+0x00, h or 0)
  writeQword(base+0x08, story or 0)
  writeQword(base+0x10, story and rq(story+0x48) or 0)
  writeQword(base+0x18, h and rq(h+0x160) or 0)
  writeQword(base+0x20, h and rq(h+0x50) or 0)
  writeQword(base+0x28, story and rq(story+0x70) or 0)
  writeQword(base+0x30, h and rq(h+0x168) or 0)
  writeQword(base+0x38, story and rq(story+0x50) or 0)
end
function HV.playerHero() local st=HV.st('OFFA') return st and rq(st+0x30) end
function HV.powerById(idp)
  local id=HV.utf16(idp); if not id or id=='' then return nil end
  local st=HV.st('OFFA'); if not st then return nil end
  local res
  HV.dictEach(rq(st+0x20), function(k,v) if HV.utf16(k)==id then res=v return false end end)
  return res
end
function HV.playerPower()
  local st=HV.st('OFFA'); if not st then return nil end
  local h=rq(st+0x30); local story=h and rq(h+0x120)
  local p = story and HV.powerById(rq(story+0x18))
  if not p then p=HV.powerById(rq(st+0x28)) end
  return p
end
function HV.curCity()
  if HV.selCity then return HV.selCity end
  local st=HV.st('OFFA'); return st and rq(st+0x198)
end
function HV.updatePtrs()
  local P=getAddressSafe('hvPtrs'); if not P then return end
  local st=HV.st('OFFA')
  HV.heroCtx(P, st and rq(st+0x30))
  HV.heroCtx(P+0x40, HV.selHero)
  local c=HV.curCity()
  writeQword(P+0x80, c or 0); writeQword(P+0x88, c and rq(c+0xD8) or 0)
  local pf=0
  local gv=c and rq(c+0xD8)
  if gv then local own=HV.utf16(rq(gv+0x10)); local e=HV.feelEntry(gv, own) if e then pf=e end end
  writeQword(P+0x98, pf)
  HV.ppCnt=(HV.ppCnt or 0)+1
  if HV.ppCnt%8==1 then HV.ppower=HV.playerPower() end
  writeQword(P+0x90, HV.ppower or 0)
  writeQword(P+0xA0, st or 0); writeQword(P+0xA8, HV.st('KJNF') or 0); writeQword(P+0xB0, HV.st('WAC') or 0)
  writeQword(P+0xB8, HV.st('FIC') or 0)
  writeQword(P+0xC0, HV.influenceEntry() or 0)
  if HV.syncHeroFamily then HV.syncHeroFamily() end
  writeQword(P+0xD0,HV.selPower or 0);writeQword(P+0xD8,HV.selFamily or 0)
end
-- influence (発言力): OFFA static +0x1D8 Dictionary&lt;string power-id, float&gt;; key = player story +0x18 (see NMMNAJHKKNN$$FNCOLKEJDOO)
function HV.influenceEntry()
  local st=HV.st('OFFA'); if not st then return nil end
  local h=rq(st+0x30); local story=h and rq(h+0x120)
  local id=story and HV.utf16(rq(story+0x18)); if not id or id=='' then return nil end
  local d=rq(st+0x1D8); local ent=d and rq(d+0x18); local n=d and ri(d+0x20) or 0
  if not ent or n&lt;=0 or n&gt;200000 then return nil end
  for i=0,n-1 do local e=ent+0x20+i*0x18 local hh=ri(e)
    if hh and hh&gt;=0 and HV.utf16(rq(e+8))==id then return e+0x10 end end
  return nil
end

----------------------------------------------------------------- periodic tasks
local TASK={}
function TASK.warMoraleMax()
  local w=HV.st('WAC'); local k=HV.st('KJNF'); if not w or not k then return end
  local mx=(ri(k+0x1C) or 0)
  local arr=rq(w+0x248); if arr then mx=mx+(ri(arr+0x20) or 0) end
  if mx&lt;=0 then return end
  HV.listEach(rq(w+0xE8), function(a) local at=rq(a+0x18) local tr=at and rq(at+0x20)
    if tr then writeFloat(tr+0x5C, mx) end end)
end
local function warTeams(mine)
  local w=HV.st('WAC'); if not w then return nil end
  local wi=rq(w+0x20); local arr=wi and rq(wi+0x28); if not arr then return nil end
  local myIdx=(readBytes(w+0x50,1)~=0) and 1 or 0
  local idx= mine and myIdx or (1-myIdx)
  return rq(arr+0x20+idx*8)
end
HV.warTeams=warTeams
function TASK.warFoodMax()
  HV.listEach(warTeams(true), function(t) if (ri(t+0x150) or 0)&lt;99999 then writeInteger(t+0x150,99999) end end)
end
function TASK.techPts()
  local p=HV.ppower; if p then if (ri(p+0xA0) or 0)&lt;99999 then writeInteger(p+0xA0,99999) end end
  local st=HV.st('OFFA'); if st and (ri(st+0x98) or 0)&lt;99999 then writeInteger(st+0x98,99999) end
end
function TASK.playerStat()
  local h=HV.playerHero(); if not h then return end
  local story=rq(h+0x120); local at=story and rq(story+0x48)
  local force=at and ri(at+0x24) or 0; local will=at and ri(at+0x34) or 0
  local mx=800+(ri(h+0x1A4) or 0)+2*(force+will)
  if (ri(h+0x1A0) or 0)&lt;mx then writeInteger(h+0x1A0,mx) end
  writeInteger(h+0x194,0); writeInteger(h+0x198,0)
  if (ri(h+0x19C) or 0)&lt;1000 then writeInteger(h+0x19C,1000) end
end
HV.TASK=TASK

if HV.timer then HV.timer.destroy() end
HV.timer=createTimer(nil,false)
HV.timer.Interval=300
HV.timer.OnTimer=HV.guard(function()
  if not HV.pid then return end -- explicit attach/feature activation initializes a session
  if not HV.processAlive() or HV.pid~=getOpenedProcessID() then HV.forgetProcess() return end
  local ok,e=pcall(HV.updatePtrs)
  if not ok and HV.ptrError~=tostring(e) then HV.ptrError=tostring(e);print('[HV] Pointer refresh: '..HV.ptrError) elseif ok then HV.ptrError=nil end
  for k in pairs(HV.tasks) do local ok,e=pcall(TASK[k]) end
  pcall(HV.watchTick)
end)
HV.timer.Enabled=true

----------------------------------------------------------------- one-shot actions
function HV.enemyWar(what)
  HV.init()
  local w=HV.st('WAC'); if not w then HV.msg('Not in war.','戦争中ではありません。') return end
  local n=0
  if what=='food' then
    HV.listEach(warTeams(false), function(t) writeInteger(t+0x150,0) n=n+1 end)
  else
    HV.listEach(rq(w+0xF0), function(a) local at=rq(a+0x18) local tr=at and rq(at+0x20)
      if tr then
        if what=='soldier' then writeInteger(tr+0x50,0) writeInteger(tr+0x54,0)
        else writeFloat(tr+0x5C,0) end
        n=n+1
      end end)
  end
  HV.msg('Applied to '..n..' enemy entries.','敵 '..n..' 件に適用しました。')
end

-- technology: mode 'acquire' (first layer of every tech) / 'max' (all layers)
function HV.ensurePeff()
  if HV.peffOK and getAddressSafe('hvCallPeff') then return end
  local ok,e=autoAssemble(HV.PEFF_STUB); if not ok then error('stub: '..tostring(e)) end
  HV.peffOK=true
end
local function techOwner(owner)
  if owner=='private' then local st=HV.st('OFFA') return st and rq(st+0x88), st and rq(st+0x90) end
  local p=HV.playerPower(); if not p then return nil end
  return rq(p+0x90), rq(p+0x98)
end
function HV.techAll(mode, owner)
  HV.init(); HV.ensurePeff()
  local dict,bonus=techOwner(owner)
  if not dict or not bonus then HV.msg('Technology data not found (no power?).','技術データが見つかりません（勢力未所属？）。') return end
  local og=HV.st('OGEN'); local defs={}
  HV.dictEach(og and rq(og+0x198), function(k,v) local s=HV.utf16(k) if s then defs[s]=v end end)
  local call=getAddress('hvCallPeff')
  local changed,skipped=0,0
  HV.dictEach(dict, function(k,t)
    local def=defs[HV.utf16(rq(t+0x10)) or '']
    if not def then return end
    local res=rq(t+0x28); if res and (ri(res+0x18) or 0)&gt;0 then skipped=skipped+1 return end
    local maxL=(readBytes(def+0x7C,1)~=0) and 2 or 0
    local up=rq(def+0x40); local qty=rq(def+0x50)
    if not up or not qty then return end
    for guard=1,4 do
      local L=ri(t+0x20) or 0; if L&lt;0 or L&gt;2 then break end
      local q=ri(qty+0x20+L*4) or 1
      if (ri(t+0x1C) or 0)&gt;=q then break end         -- current layer already completed (final)
      if mode=='acquire' and L&gt;0 then break end
      writeInteger(t+0x18, ri(up+0x20+L*4) or 0)
      writeInteger(t+0x1C, q)
      executeCodeEx(0, 5000, call, t, bonus)
      changed=changed+1
      if L&lt;maxL then writeInteger(t+0x20,L+1) writeQword(t+0x18,0) else break end
      if mode=='acquire' then break end
    end
  end)
  HV.msg(('Tech layers completed: %d (skipped under research: %d)'):format(changed,skipped),
         ('技術段階を完了: %d（研究中のためスキップ: %d）'):format(changed,skipped))
end

function HV.maxProfession(which)
  HV.init()
  local h = (which=='sel') and HV.selHero or HV.playerHero()
  if not h then HV.msg('No hero.','武将がありません。') return end
  local k=HV.st('KJNF'); local lst=k and rq(k+0x240); local mx=lst and ri(lst+0x18)
  if not mx or mx&lt;=0 then HV.msg('Profession exp table not loaded.','熟練度テーブル未ロード。') return end
  local story=rq(h+0x120); local lv=story and rq(story+0x70); local ex=rq(h+0x168)
  if not lv then return end
  local n=ri(lv+0x18) or 0
  for i=0,n-1 do writeInteger(lv+0x20+i*4,mx) end
  if ex then for i=0,(ri(ex+0x18) or 0)-1 do writeInteger(ex+0x20+i*4,0) end end
  HV.msg('Professions set to level '..mx,'熟練度をレベル'..mx..'に設定しました')
end

function HV.maxAttr(which, v)
  HV.init()
  local h = (which=='sel') and HV.selHero or HV.playerHero(); if not h then return end
  local story=rq(h+0x120); local at=story and rq(story+0x48); if not at then return end
  for i=0,5 do writeInteger(at+0x20+i*4, v) end
  HV.msg('Base attributes set to '..v,'基本能力を'..v..'に設定しました')
end

-- city helpers
function HV.cityMaxDev()
  HV.init()
  local c=HV.curCity(); if not c then HV.msg('No city.','都市がありません。') return end
  local n=0
  HV.listEach(rq(c+0x120), function(b)
    local c6=ri(b+0x6C) or 0; local a7=ri(b+0x70) or 0
    if c6&gt;0 and (ri(b+0x5C) or 0)&lt;c6 then writeInteger(b+0x5C,c6) end
    if a7&gt;0 and (ri(b+0x60) or 0)&lt;a7 then writeInteger(b+0x60,a7) end
    n=n+1 end)
  HV.msg('Blocks updated: '..n,'街区を更新: '..n)
end
function HV.cityMaxWall()
  HV.init()
  local c=HV.curCity(); if not c then return end
  local n=0
  HV.listEach(rq(c+0x220), function(w) local ty=rq(w+0x60) local mx=ty and ri(ty+0xC8)
    if mx and mx&gt;0 then writeInteger(w+0x40,mx) n=n+1 end end)
  HV.msg('Wall segments repaired: '..n,'城壁を修復: '..n)
end


----------------------------------------------------------------- relation MAX (runs on the game main thread)
-- AKFNGFLIKCB(hero, 0.0f, 99999, false): the game's own "add relation with player" (friendship / family /
-- sworn brother / love, capped by the game); FOHFEOGHKCG(hero): clamps respect/gratitude/acknowledge to trait caps.
-- relation values written by the game's relation add (hero +0xF8 / +0x108 int, +0x110 / +0x118 Dictionary&lt;string,int&gt;,
-- story +0x110 / +0x118 Dictionary&lt;string,int&gt;). Family relations have no cap in the game, so a wrong multiplier
-- (1.0 instead of the game's 0.0, used by this table before 006-007) doubled them on every run until int32 overflowed.
-- Values beyond +-10,000,000 cannot come from normal play: HV.relMax resets them to 0 (target heroes + player) before adding.
HV.REL_BROKEN = 10000000
local function relFixInt(a) local v=ri(a) if v and (v&gt;HV.REL_BROKEN or v&lt; -HV.REL_BROKEN) then writeInteger(a,0) return 1 end return 0 end
local function relFixDict(d)
  if not d then return 0 end
  local ent=rq(d+0x18); local n=ri(d+0x20) or 0; local c=0
  if not ent or n&lt;=0 or n&gt;200000 then return 0 end
  for i=0,n-1 do local e=ent+0x20+i*0x18 local h=ri(e) if h and h&gt;=0 then c=c+relFixInt(e+0x10) end end
  return c
end
function HV.relSanitize(h)
  if not h then return 0 end
  local c=relFixInt(h+0xF8)+relFixInt(h+0x108)+relFixDict(rq(h+0x110))+relFixDict(rq(h+0x118))
  local s=rq(h+0x120)
  if s then c=c+relFixDict(rq(s+0x110))+relFixDict(rq(s+0x118)) end
  return c
end
function HV.relMax(scope)
  HV.init()
  local st=HV.st('OFFA'); local ph=st and rq(st+0x30); if not ph then HV.msg('No player.','主人公がいません。') return end
  local targets={}
  if scope=='sel' then
    if not HV.selHero or HV.selHero==ph then HV.msg('Select another hero first.','主人公以外の武将を選択してください。') return end
    targets[1]=HV.selHero
  elseif scope=='all' then
    -- every hero that exists in the world: story +0x30 state 1 (UnFound) / 2 (Show); 0 (UnShow) and 3 (Death) are excluded
    local og=HV.st('OGEN')
    HV.dictEach(og and rq(og+0x8), function(k,h)
      if h~=ph then local s=rq(h+0x120) local sv=s and ri(s+0x30) if sv==1 or sv==2 then targets[#targets+1]=h end end end)
  else
    local ps=rq(ph+0x120); local pid=ps and HV.utf16(rq(ps+0x18))
    if not pid or pid=='' then HV.msg('Player belongs to no power.','主人公は勢力に所属していません。') return end
    local og=HV.st('OGEN')
    HV.dictEach(og and rq(og+0x8), function(k,h)
      if h~=ph then local s=rq(h+0x120) if s and HV.utf16(rq(s+0x18))==pid then targets[#targets+1]=h end end end)
  end
  if #targets==0 then HV.msg('No target heroes.','対象武将がいません。') return end
  local F=getAddress('hvFlags')
  writeFloat(F+0x34,0.0)   -- the game always passes 0.0 (1.0 doubled uncapped family relations every run)
  local ph2=ph; HV.relSanitize(ph2) for _,h in ipairs(targets) do HV.relSanitize(h) end
  HV.hookUse('relDisp',true)
  local done,i=0,1
  local ok,err=pcall(function()
    while i&lt;=#targets do
      local n=0
      while i&lt;=#targets and n&lt;190 do
        local h=targets[i]
        for _,o in ipairs({0x29C,0x2A0,0x2A4}) do if (ri(h+o) or 0)&lt;300 then writeInteger(h+o,300) end end
        writeQword(F+0xA00+n*8,h); n=n+1; i=i+1
      end
      writeInteger(F+0x30,n)
      local t=0
      while (ri(F+0x30) or 0)~=0 and t&lt;150 do sleep(20) t=t+1 end
      if (ri(F+0x30) or 0)~=0 then writeInteger(F+0x30,0) error(HV.T('Game main loop did not run (paused / loading?).','ゲームのメインループが動いていません（一時停止・ロード中？）。')) end
      done=done+n
    end
  end)
  HV.hookUse('relDisp',false)
  if not ok then HV.msg(tostring(err),tostring(err)) end
  HV.msg('Relation MAX applied: '..done..' heroes','関係MAXを適用: '..done..'人')
end


----------------------------------------------------------------- disable everything (safe before swapping the CT file)
-- 1) deactivates every active record (runs each DISABLE), 2) force-restores the original bytes of ALL hook sites
--    known to this table (even ones left patched by a previously loaded copy of the table), 3) clears flags/tasks.
----------------------------------------------------------------- forge blueprints (設計図)
-- learned list: OFFAMMPEGAD static +0x310 List&lt;string&gt; (equipment ids). Forge book = Drug def (KJMPKKJIOLH) type 16, +0x80 = equipment id.
-- adding is done on the game main thread through the dispatcher, calling List&lt;__Canon&gt;.Add (GA+2B10) with the
-- List&lt;string&gt;.Add MethodInfo slot (GA+5E19478; initialised by the game when a save is loaded).
-- policy cooldown reset = the effect of the policy 諸策継続 (strategy effect type 43 ResetCD, handled in LHNDPIAEADK$$AIKLDNIDJDJ):
-- cooldowns are Dictionary&lt;string policy id, int days&gt;: power +0xF8 (power policies) / OFFA static +0x418 (family policies; +0x410 before build 0x6ABCD523);
-- the game empties them with Dictionary&lt;string,int&gt;.Clear(). Here both are cleared on the game main thread.
local function dictLive(d) local n=0 HV.dictEach(d, function() n=n+1 end) return n end
function HV.policyCDReset()
  HV.init()
  if not HV.A.f_dictclear or not HV.A.MI_DICTSICLEAR then HV.err('Game code for this feature was not found.','この機能に必要なゲームコードが見つかりません。') end
  local mi=rq(HV.A.MI_DICTSICLEAR)
  if not mi or mi&lt;0x10000 or (mi%2)==1 then HV.msg('Game not ready (metadata not initialised). Load a save and retry.','ゲームの準備ができていません（メタデータ未初期化）。セーブデータをロードしてから再実行してください。') return end
  local jobs={}; local np,nf=0,0
  local pw=HV.playerPower(); local d1=pw and rq(pw+0xF8)
  if d1 then np=dictLive(d1) jobs[#jobs+1]={HV.A.f_dictclear, d1, mi} end
  local st=HV.st('OFFA'); local d2=st and rq(st+0x418)
  if d2 then nf=dictLive(d2) jobs[#jobs+1]={HV.A.f_dictclear, d2, mi} end
  if #jobs==0 then HV.msg('No policy cooldown data (load a save first).','政策のクールタイムのデータがありません（セーブデータをロードしてください）。') return end
  HV.callMain(jobs)
  HV.msg(('Policy cooldowns reset: power %d / family %d'):format(np,nf),('政策のクールタイムをリセット: 勢力 %d件 / 家族 %d件'):format(np,nf))
end
function HV.forgeIds()
  local og=HV.st('OGEN'); local eq=og and rq(og+0x40); local ids,seen={}, {}
  local eqs={}; HV.dictEach(eq, function(k,v) local s=HV.utf16(k) if s then eqs[s]=true end end)
  HV.dictEach(og and rq(og+0x50), function(k,v)
    if ri(v+0x40)==16 then local p=rq(v+0x80); local s=p and HV.utf16(p)
      if s and s~='' and eqs[s] and not seen[s] then seen[s]=true ids[#ids+1]={s=s,p=p} end end end)
  return ids
end
function HV.forgeLearnAll()
  HV.init()
  local st=HV.st('OFFA'); local lst=st and rq(st+0x310)
  if not lst then HV.msg('Blueprint list not found (load a save first).','設計図リストが見つかりません（セーブデータをロードしてください）。') return end
  local mi=HV.A.MI_LSTRADD and rq(HV.A.MI_LSTRADD)
  if not mi or mi&lt;0x10000 or (mi%2)==1 then HV.msg('Game not ready (List.Add metadata not initialised). Load a save and retry.','ゲームの準備ができていません（メタデータ未初期化）。セーブデータをロードしてから再実行してください。') return end
  local have={}; HV.listEach(lst, function(p) local s=HV.utf16(p) if s then have[s]=true end end)
  local todo={}
  for _,e in ipairs(HV.forgeIds()) do if not have[e.s] then todo[#todo+1]=e.p end end
  if #todo==0 then HV.msg('All blueprints already learned.','すべての設計図を記憶済みです。') return end
  local F=getAddress('hvFlags')
  HV.hookUse('relDisp',true)
  local done,i=0,1
  local ok,err=pcall(function()
    while i&lt;=#todo do
      local n=0
      while i&lt;=#todo and n&lt;190 do writeQword(F+0xA00+n*8,todo[i]); n=n+1; i=i+1 end
      writeQword(F+0x40,lst); writeQword(F+0x48,mi); writeInteger(F+0x38,n)
      local t=0
      while (ri(F+0x38) or 0)~=0 and t&lt;150 do sleep(20) t=t+1 end
      if (ri(F+0x38) or 0)~=0 then writeInteger(F+0x38,0) error(HV.T('Game main loop did not run (paused / loading?).','ゲームのメインループが動いていません（一時停止・ロード中？）。')) end
      done=done+n
    end
  end)
  HV.hookUse('relDisp',false)
  if not ok then HV.msg(tostring(err),tostring(err)) end
  HV.msg('Blueprints learned: '..done..' added','設計図を一括記憶: '..done..'件追加')
end

-- loyalty MAX: the game's own ACBLCFNABCM$$ALMMPFINCPH(hero, n) (29DA970) adds n to record+0xE8 and caps it at
-- ACBLCFNABCM$$JKEKHOLOPHC (2A25A80) = the hero's max loyalty (depends on relation level and compatibility).
function HV.loyaltyMax(scope)
  HV.init()
  local st=HV.st('OFFA'); local ph=st and rq(st+0x30); if not ph then HV.msg('No player.','主人公がいません。') return end
  local targets={}
  if scope=='sel' then
    if not HV.selHero or HV.selHero==ph then HV.msg('Select another hero first.','主人公以外の武将を選択してください。') return end
    targets[1]=HV.selHero
  else
    local ps=rq(ph+0x120); local pid=ps and HV.utf16(rq(ps+0x18))
    if not pid or pid=='' then HV.msg('Player belongs to no power.','主人公は勢力に所属していません。') return end
    local og=HV.st('OGEN')
    HV.dictEach(og and rq(og+0x8), function(k,h)
      if h~=ph then local s=rq(h+0x120) if s and HV.utf16(rq(s+0x18))==pid then targets[#targets+1]=h end end end)
  end
  if #targets==0 then HV.msg('No target heroes.','対象武将がいません。') return end
  local F=getAddress('hvFlags')
  HV.hookUse('relDisp',true)
  local done,i=0,1
  local ok,err=pcall(function()
    while i&lt;=#targets do
      local n=0
      while i&lt;=#targets and n&lt;190 do writeQword(F+0xA00+n*8,targets[i]); n=n+1; i=i+1 end
      writeInteger(F+0x80,n)
      local t=0
      while (ri(F+0x80) or 0)~=0 and t&lt;150 do sleep(20) t=t+1 end
      if (ri(F+0x80) or 0)~=0 then writeInteger(F+0x80,0) error(HV.T('Game main loop did not run (paused / loading?).','ゲームのメインループが動いていません（一時停止・ロード中？）。')) end
      done=done+n
    end
  end)
  HV.hookUse('relDisp',false)
  if not ok then HV.msg(tostring(err),tostring(err)) end
  HV.msg('Loyalty MAX applied: '..done..' heroes','忠誠MAXを適用: '..done..'人')
end

----------------------------------------------------------------- generic main-thread calls
-- jobs = { {fn, a1, a2, a3, a4}, ... } executed by the dispatcher (GlobalUpdateCtrl$$Update) on the game main thread
function HV.callMain(jobs)
  HV.init()
  local F=getAddress('hvFlags'); local J=getAddress('hvJobs')
  HV.hookUse('relDisp',true)
  local done,i=0,1
  local ok,err=pcall(function()
    while i&lt;=#jobs do
      local n=0
      while i&lt;=#jobs and n&lt;256 do
        local j=jobs[i]; local b=J+n*0x28
        writeQword(b,j[1]); writeQword(b+8,j[2] or 0); writeQword(b+0x10,j[3] or 0); writeQword(b+0x18,j[4] or 0); writeQword(b+0x20,j[5] or 0)
        n=n+1; i=i+1
      end
      writeQword(F+0x98,J); writeInteger(F+0x90,n)
      local t=0
      while (ri(F+0x90) or 0)~=0 and t&lt;250 do sleep(20) t=t+1 end
      if (ri(F+0x90) or 0)~=0 then writeInteger(F+0x90,0) error(HV.T('Game main loop did not run (paused / loading?).','ゲームのメインループが動いていません（一時停止・ロード中？）。')) end
      done=done+n
    end
  end)
  HV.hookUse('relDisp',false)
  if not ok then error(err) end
  return done
end

----------------------------------------------------------------- give items (OFFAMMPEGAD$$AINOPDCLNED(string id, int count): game's own add-to-player-bag)
function HV.giveItems(list)   -- list = { {d=def, n=count}, ... }
  if not HV.A.f_additem then error(HV.T('Feature unavailable: add-item code not found in this build.','この機能は使えません: このビルドではアイテム追加のコードが見つかりません。')) end
  local jobs={}
  for _,e in ipairs(list) do if e.d and e.d.k and e.n and e.n&gt;0 then jobs[#jobs+1]={HV.A.f_additem, e.d.k, e.n} end end
  if #jobs==0 then return 0 end
  return HV.callMain(jobs)
end
local function defName(d) return HV.ml(rq(d.v+d.no)) end
local function defNameAll(d) return HV.ml(rq(d.v+d.no),true) end
local function sortedDefs(filter)
  local out={}
  for id,d in pairs(HV.itemDefs()) do if filter(d) then out[#out+1]=d end end
  table.sort(out,function(a,b) return a.id&lt;b.id end)
  return out
end
function HV.giveMaps()
  HV.init()
  local L=sortedDefs(function(d) if d.kind~='drug' then return false end local t=ri(d.v+0x40) return t==4 or t==5 or t==6 end)
  if #L==0 then HV.msg('No map items found.','地図アイテムが見つかりません。') return end
  local list={} for _,d in ipairs(L) do list[#list+1]={d=d,n=1} end
  local n=HV.giveItems(list)
  HV.msg(('Map items added: %d kinds x1 (map fragment / map / treasure map)'):format(n),('地図アイテムを追加: %d種類×1個（地図の断片・地図・宝の地図）'):format(n))
end
function HV.giveBooks()
  HV.init()
  local L=sortedDefs(function(d) if d.kind~='drug' then return false end local ma,mi=HV.itemCat(d) return ma==2 and mi==6 and defNameAll(d):find('精要',1,true)~=nil end)
  if #L==0 then HV.msg('No matching books found.','該当する本が見つかりません。') return end
  local list={} for _,d in ipairs(L) do list[#list+1]={d=d,n=10} end
  local n=HV.giveItems(list)
  local names={} for _,d in ipairs(L) do names[#names+1]=defName(d) end
  HV.msg(('Books added: %d kinds x10 (%s)'):format(n,table.concat(names,', ')),('本を追加: %d種類×10個（%s）'):format(n,table.concat(names,'、')))
end
-- skill books (秘伝書): Drug definitions of type 8 WarSkill / 10 BattleSkill / 12 DebateSkill (enum LLOAEHBNIAF; 9/11/13 = souls)
function HV.giveSkillBooks()
  HV.init()
  local T={[8]=0,[10]=0,[12]=0}
  local L=sortedDefs(function(d) if d.kind~='drug' then return false end local t=ri(d.v+0x40) return T[t]~=nil end)
  if #L==0 then HV.msg('No skill books found (load a save first).','秘伝書が見つかりません（セーブデータをロードしてください）。') return end
  local list={} for _,d in ipairs(L) do list[#list+1]={d=d,n=1} local t=ri(d.v+0x40) T[t]=T[t]+1 end
  local n=HV.giveItems(list)
  HV.msg(('Skill books added: %d kinds x1 (war %d / battle %d / debate %d)'):format(n,T[8],T[10],T[12]),
         ('秘伝書を追加: %d種類×1個（軍技 %d・武技 %d・弁技 %d）'):format(n,T[8],T[10],T[12]))
end
-- title certificates (官職証書): Drug definitions of type 14 TitleCertificate (enum LLOAEHBNIAF)
function HV.giveTitleCerts()
  HV.init()
  local L=sortedDefs(function(d) return d.kind=='drug' and ri(d.v+0x40)==14 end)
  if #L==0 then HV.msg('No title certificates found (load a save first).','官職証書が見つかりません（セーブデータをロードしてください）。') return end
  local list={} for _,d in ipairs(L) do list[#list+1]={d=d,n=1} end
  local n=HV.giveItems(list)
  HV.msg(('Title certificates added: %d kinds x1'):format(n),('官職証書を追加: %d種類×1個'):format(n))
end
function HV.itemAddPick()
  HV.init()
  local pid,hero,registry=HV.pid,HV.playerHero(),HV.st('OGEN')
  if not hero then HV.err('Load a save first.','先にセーブデータをロードしてください。') end
  local defs=HV.itemDefs();local cats={}
  for ma,cat in ipairs(HV.ITEMCAT) do for mi,sub in ipairs(cat[3]) do
    local rows={}
    for _,d in pairs(defs) do local a,b=HV.itemCat(d)
      if a==ma and b==mi then
        local p=rq(d.v+d.no)
        rows[#rows+1]={id=d.kind..':'..d.id,displayId=d.id,en=p and HV.utf16(rq(p+0x20)) or defName(d),ja=p and HV.utf16(rq(p+0x28)) or defName(d),d=d}
      end
    end
    table.sort(rows,function(a,b)return a.id&lt;b.id end)
    if #rows&gt;0 then cats[#cats+1]={id=ma..':'..mi,en=cat[1]..' / '..sub[1]..' ('..#rows..')',ja=cat[2]..' / '..sub[2]..' ('..#rows..')',rows=rows} end
  end end
  local selected,meta=HV.chooseBatch(HV.T('Add items','アイテム追加'),cats,{quantity={min=1,max=9999,default=1}})
  if not selected then return end
  if not HV.processAlive() or HV.pid~=pid or HV.playerHero()~=hero or HV.st('OGEN')~=registry then HV.err('Game or player changed. Select again.','ゲームまたは主人公が変わりました。選択し直してください。') end
  HV._defs=nil;local fresh=HV.itemDefs();local byId={}
  for _,d in pairs(fresh) do byId[d.kind..':'..d.id]=d end
  local jobs={}
  for _,r in ipairs(selected) do
    local d=byId[r.id]
    if not d or d.v~=r.d.v or d.k~=r.d.k then HV.err('Item definitions changed. Select again.','アイテム情報が変わりました。選択し直してください。') end
    jobs[#jobs+1]={d=d,n=meta.quantity}
  end
  local n=HV.giveItems(jobs)
  HV.msg(('Added %d item types, %d each.'):format(n,meta.quantity),('%d種類のアイテムを各%d個追加しました。'):format(n,meta.quantity))
end

----------------------------------------------------------------- move own hero to a city (ACBLCFNABCM$$NHBFIIAPGKE(hero, cityId, 0, false) = the game's "武将調任")
function HV.heroMove()
  HV.init()
  if not HV.A.f_heromove then error(HV.T('Feature unavailable: transfer code not found in this build.','この機能は使えません: このビルドでは調任のコードが見つかりません。')) end
  local st=HV.st('OFFA'); local ph=st and rq(st+0x30); if not ph then HV.msg('No player.','主人公がいません。') return end
  local ps=rq(ph+0x120); local pid=ps and HV.utf16(rq(ps+0x18))
  if not pid or pid=='' then HV.msg('Player belongs to no power.','主人公は勢力に所属していません。') return end
  local og=HV.st('OGEN'); local hs,hn={},{}
  HV.dictEach(og and rq(og+0x8), function(k,h)
    local s=rq(h+0x120) if s and HV.utf16(rq(s+0x18))==pid then hs[#hs+1]=h end end)
  table.sort(hs,function(a,b) return HV.heroName(a)&lt;HV.heroName(b) end)
  local fm=HV.st('FMAF'); local cmap={}
  HV.listEach(fm and rq(fm+0x58), function(c) local id=HV.utf16(rq(c+0x28)) if id then cmap[id]=c end end)
  for i,h in ipairs(hs) do local r=rq(h+0x120); local c=r and cmap[HV.utf16(rq(r+0x40)) or '']
    hn[i]=HV.heroName(h)..'  @ '..(c and HV.ml(rq(c+0x10)) or '?') end
  if #hs==0 then HV.msg('No heroes in your power.','自勢力の武将がいません。') return end
  local hi=HV.pick(HV.T('Hero to move','移動する武将'),hn); if not hi then return end
  local cs,cn={},{}
  HV.listEach(fm and rq(fm+0x58), function(c) local gv=rq(c+0xD8); local own=gv and HV.utf16(rq(gv+0x10))
    if own==pid then cs[#cs+1]=c cn[#cn+1]=HV.ml(rq(c+0x10)) end end)
  if #cs==0 then HV.msg('Your power has no city.','自勢力に都市がありません。') return end
  local ci=HV.pick(HV.T('Destination city (own power)','移動先の都市（自勢力）'),cn); if not ci then return end
  HV.callMain({{HV.A.f_heromove, hs[hi], rq(cs[ci]+0x28), 0, 0}})
  local r=rq(hs[hi]+0x120); local now=r and cmap[HV.utf16(rq(r+0x40)) or '']
  HV.msg(('Transfer ordered: %s -&gt; %s (current city: %s)'):format(HV.heroName(hs[hi]),cn[ci],now and HV.ml(rq(now+0x10)) or '?'),
         ('調任を実行: %s → %s（現在の所属都市: %s）'):format(HV.heroName(hs[hi]),cn[ci],now and HV.ml(rq(now+0x10)) or '?'))
end

HV.EXE='ThreeKingdom.exe'
-- attach CE to the game (same approach as the DQM4 table): returns true when the opened process changed
function HV.attachGame()
  local pid=getProcessIDFromProcessName(HV.EXE)
  if not pid or pid==0 then error(HV.T('The game is not running: '..HV.EXE,'ゲームが起動していません: '..HV.EXE),0) end
  local changed=false
  if getOpenedProcessID()~=pid then
    openProcess(pid); changed=true
    HV.msg(('Attached to %s (PID %d).'):format(HV.EXE,pid), ('%s（PID %d）にアタッチしました。'):format(HV.EXE,pid))
  end
  if not HV.ga() then pcall(reinitializeSymbolhandler,true) end
  if not HV.ga() then error(HV.T('GameAssembly.dll is not loaded yet. Wait until the title screen and try again.',
                                 'GameAssembly.dll がまだ読み込まれていません。タイトル画面まで待ってから再実行してください。'),0) end
  return changed
end
-- the table state belongs to another (old) process: drop it without touching the new process
function HV.forgetProcess(exclude)
  for form in pairs(HV.forms or {}) do pcall(function() form.ModalResult=2 end) end
  if HV.cleaning then return end
  HV.cleaning=true
  local hadSession=HV.pid~=nil
  HV.detached=true
  if HV.timer then HV.timer.Enabled=false end
  for _,name in ipairs({'pendTimer','uqTimer','childTimer'}) do
    local timer=HV[name];HV[name]=nil
    if timer then pcall(function() timer.Enabled=false;timer.destroy() end) end
  end
  for timer in pairs(HV.oneTimers or {}) do pcall(function() timer.Enabled=false;timer.destroy() end) end
  HV.oneTimers={};HV.actionPending=false;HV.actionJob=nil;HV.uq={};HV.childQ={};HV.childBusyStep=false
  HV.hookState={};HV.featOn={};HV.tasks={};HV.W={};HV.orig={};HV.pend={};HV.stale={};HV.missing={}
  for _,list in pairs(HV.HOOKS) do for _,h in ipairs(list) do h.on=false end end
  -- Feature disable paths return immediately while detached; only local UI cleanup runs.
  local al=getAddressList()
  for i=al.Count-1,0,-1 do
    local record=al.getMemoryRecord(i)
    if record.Active and record.ID~=exclude and record.ID~=HV.actionRecord then record.Active=false end
  end
  for k in pairs(HV.A or {}) do pcall(unregisterSymbol,'hvA_'..k) end
  HV.A={}
  for _,s in ipairs({'hvFlags','hvVars','hvPtrs','hvUnits','hvJobs','hvCallPeff','hvScanTmp'}) do pcall(unregisterSymbol,s) end
  HV.pid=nil;HV.warned=nil;HV._defs=nil;HV._defsPid=nil;HV.selHero=nil;HV.selCity=nil;HV.selPower=nil;HV.selFamily=nil;HV.ppower=nil
  HV.cleaning=false
  if hadSession then HV.msg('Game disconnected. Table stopped; attach again after restarting the game.',
                           'ゲームとの接続が終了しました。テーブルを停止しました。再起動後にアタッチしてください。') end
end
function HV.disableAll(self)
  local running=getProcessIDFromProcessName(HV.EXE)
  if not running or running==0 then HV.forgetProcess() return end
  local ok,changed=pcall(HV.attachGame)
  if not ok then print('[HV] '..tostring(changed)) pcall(showMessage,tostring(changed)) return end
  if HV.pid and HV.pid~=getOpenedProcessID() then HV.forgetProcess(self and self.ID) end
  local okI,e=pcall(HV.init);if not okI then error(e,0) end
  local own=(HV.pid~=nil and HV.pid==getOpenedProcessID())   -- addresses were resolved in this process
  local staleN=0 for _ in pairs(HV.stale or {}) do staleN=staleN+1 end
  local al=getAddressList(); local n=0
  for i=al.Count-1,0,-1 do
    local m=al.getMemoryRecord(i)
    if m.Active and not (self and m.ID==self.ID) then pcall(function() m.Active=false end) n=n+1 end
  end
  HV.tasks={}; HV.W={}
  if HV.childStop then pcall(HV.childStop,true) end
  local F=own and getAddressSafe('hvFlags') or nil
  local paused=own and pcall(pause)
  local restored=0
  if own then
    for name,list in pairs(HV.HOOKS) do
      for _,h in ipairs(list) do restored=restored+restoreHook(h) end
    end
  end
  if F then for i=0,0xFF do writeBytes(F+i,0) end writeInteger(F+0x30,0) writeInteger(F+0x38,0) writeInteger(F+0x50,0) writeInteger(F+0x80,0) writeInteger(F+0x90,0) end
  if paused then pcall(unpause) end
  HV.hookState={}; HV.featOn={}
  if own and staleN&gt;0 then
    HV.msg(('Removed %d hook sites left by an earlier Cheat Engine session.'):format(staleN), ('以前のCheat Engineのセッションで残っていたフック %dか所を元に戻しました。'):format(staleN))
    HV.stale={}
  end
  HV.msg(('Attach / All OFF: %d records deactivated, %d hook sites restored.'):format(n,restored),
         ('アタッチ／一括解除: %d件を無効化、%dか所のフックを元に戻しました。'):format(n,restored))
end


----------------------------------------------------------------- item lists (EBPFBFHJGOO: +0x10 id, +0x18 count)
-- definitions: OGENELIEPGD static +0x40 Equipment, +0x48 Book, +0x50 Drug/item, +0x188 Topic
local ITEMDEF={{0x40,0x10,'eq'},{0x48,0x10,'book'},{0x50,0x10,'drug'},{0x188,0x18,'topic'}}
-- category tree: major -&gt; minors. Equipment type (FKJAPFHELIM+0x40, DGPALGLCOJK), Drug type (KJMPKKJIOLH+0x40, IKLPNHFLLLA)
HV.ITEMCAT={
  {'Equipment','装備',{{'Weapon','武器'},{'Armor','鎧（衣甲）'},{'Helmet','兜'},{'Shield','盾'},{'Horse','馬'},{'Treasure','宝物'},{'Present','贈り物'},{'Mission item','任務アイテム'}}},
  {'Consumables','消耗品',{{'Wine','酒'},{'Medicine','薬'},{'Food','食物'},{'Poison','毒'},{'Maps (fragment / map / treasure map)','地図・地図の断片・宝の地図'},{'Other','その他'}}},
  {'Skills &amp; souls','技能・魂',{{'War skill / war soul','軍技・軍魂'},{'Battle skill / martial soul','武技・武魂'},{'Debate skill / wisdom soul','弁技・智魂'}}},
  {'Books &amp; certificates','書物・証書',{{'Book','書物'},{'EXP book','経験書'},{'Forge book','鍛造書'},{'Title certificate','官職証書'}}},
  {'Materials &amp; trade goods','素材・交易品',{{'Forge / cloth material','鍛造素材・布素材'},{'Iron, cloth, gold, wood, jade','鉄・布・金・木材・玉'},{'Tea, meat, salt, herb, spices, cereal','茶・肉・塩・薬草・香辛料・穀物'},{'Ceramics, lacquerware, stationery','陶磁器・漆器・文具'}}},
  {'Topics','話題',{{'Topic','話題'}}},
  {'Unknown','不明',{{'Unknown definition','定義不明'}}},
}
local EQMAP={[0]=1,[1]=2,[4]=3,[7]=4,[3]=5,[2]=6,[6]=7,[5]=8}
local DRMAP={[0]={2,1},[1]={2,2},[2]={2,3},[7]={2,4},[4]={2,5},[5]={2,5},[6]={2,5},[3]={2,6},
  [8]={3,1},[9]={3,1},[10]={3,2},[11]={3,2},[12]={3,3},[13]={3,3},
  [15]={4,2},[16]={4,3},[14]={4,4},[17]={5,1},[18]={5,1},[19]={5,2},[20]={5,2},[21]={5,2},[22]={5,2},[23]={5,2},
  [24]={5,3},[25]={5,3},[26]={5,3},[27]={5,3},[28]={5,3},[32]={5,3},[29]={5,4},[30]={5,4},[31]={5,4}}
function HV.itemCat(d)
  if not d then return 7,1 end
  if d.kind=='eq' then local t=ri(d.v+0x40); return 1,(t and EQMAP[t]) or 8 end
  if d.kind=='book' then return 4,1 end
  if d.kind=='topic' then return 6,1 end
  local t=ri(d.v+0x40); local m=t and DRMAP[t]
  if m then return m[1],m[2] end
  return 2,6
end
function HV.itemDefs()
  if HV._defs and HV._defsPid==HV.pid then return HV._defs end
  local og=HV.st('OGEN'); local defs={}
  for _,d in ipairs(ITEMDEF) do
    HV.dictEach(og and rq(og+d[1]), function(k,v) local s=HV.utf16(k) if s then defs[s]={v=v,no=d[2],kind=d[3],k=k,id=s} end end)
  end
  HV._defs=defs; HV._defsPid=HV.pid
  return defs
end
function HV.refreshItems(kind, parentID)
  HV.init()
  local parent=getAddressList().getMemoryRecordByID(parentID); if not parent then return end
  while parent.Count&gt;0 do parent.Child[0].destroy() end
  local owner, first, last
  if kind=='itw' then owner=HV.playerPower() first,last=0x110,0x160
  else owner=(kind=='its') and HV.selHero or HV.playerHero() first,last=0x310,0x370 end
  if not owner then HV.msg('Owner not found (select a hero / belong to a power).','所有者が見つかりません（武将選択・勢力所属を確認）。') return end
  local defs=HV.itemDefs(); local total=0
  local bucket={}   -- bucket[major][minor] = list of {it,id,name}
  for off=first,last,8 do
    local lst=rq(owner+off); local n=lst and ri(lst+0x18) or 0
    if n and n&gt;0 then
      HV.listEach(lst, function(it)
        local id=HV.utf16(rq(it+0x10)) or '?'
        local d=defs[id]
        local ma,mi=HV.itemCat(d)
        bucket[ma]=bucket[ma] or {}; bucket[ma][mi]=bucket[ma][mi] or {}
        local t=bucket[ma][mi]; t[#t+1]={it=it,id=id,name=d and HV.ml(rq(d.v+d.no)) or ''}
        total=total+1
      end)
    end
  end
  local al=getAddressList()
  local function grp(p,en,jp)
    local g=al.createMemoryRecord(); g.DontSave=true; g.IsGroupHeader=true; g.appendToEntry(p)
    g.Description=HV.T(en,jp); HV.dyn[#HV.dyn+1]={id=g.ID,en=en,jp=jp}
    g.Color=HV.C_GROUP
    return g
  end
  for ma,cat in ipairs(HV.ITEMCAT) do
    if bucket[ma] then
      local gm=grp(parent,cat[1],cat[2])
      for mi,sub in ipairs(cat[3]) do
        local lst=bucket[ma][mi]
        if lst then
          local gs=grp(gm,sub[1],sub[2])
          for _,e in ipairs(lst) do
            local m=al.createMemoryRecord(); m.DontSave=true
            local en=('%s [%s]'):format(e.name,e.id)
            m.Description=en; m.Address=string.format('%X',e.it+0x18); m.Type=vtDword
            pcall(function() m.ShowAsSigned=true end)
            m.appendToEntry(gs)
            HV.dyn[#HV.dyn+1]={id=m.ID,en=en,jp=en}
          end
        end
      end
    end
  end
  if not HV.quiet then HV.msg('Items listed: '..total..' (value = count)','アイテム一覧: '..total..'件（値＝個数）') end
end


----------------------------------------------------------------- popular support (民心): gov block +0x38 Dictionary&lt;string power-id, float&gt;
-- entry layout: +0 hash, +4 next, +8 key, +0x10 value(float); max = KJNFHAIAKFP static +0x4
function HV.feelEntry(gv, id)
  if not gv or not id then return nil end
  local d=rq(gv+0x38); local ent=d and rq(d+0x18); local n=d and ri(d+0x20) or 0
  if not ent then return nil end
  for i=0,n-1 do local e=ent+0x20+i*0x18 local h=ri(e)
    if h and h&gt;=0 and HV.utf16(rq(e+8))==id then return e+0x10 end end
  return nil
end
function HV.feelMax() local k=HV.st('KJNF') return k and ri(k+0x4) or nil end
function HV.powerName(id)
  if not id or id=='' then return HV.T('(none)','（なし）') end
  local st=HV.st('OFFA'); local pw
  HV.dictEach(st and rq(st+0x20), function(k,v) if HV.utf16(k)==id then pw=v return false end end)
  local nm=pw and HV.utf16(rq(pw+0x18))
  if nm and nm~='' then return nm end
  local og=HV.st('OGEN'); local h
  HV.dictEach(og and rq(og+0x8), function(k,v) if HV.utf16(k)==id then h=v return false end end)
  return h and HV.heroName(h) or id
end
function HV.cityFeel(mode)
  HV.init()
  local c=HV.curCity(); local gv=c and rq(c+0xD8)
  if not gv then HV.msg('No city.','都市がありません。') return end
  local mx=HV.feelMax(); if not mx or mx&lt;=0 then HV.msg('Max value not loaded.','上限値が未ロードです。') return end
  local own=HV.utf16(rq(gv+0x10)); local n=0
  local d=rq(gv+0x38); local ent=d and rq(d+0x18); local cnt=d and ri(d+0x20) or 0
  if ent then for i=0,cnt-1 do local e=ent+0x20+i*0x18 local h=ri(e)
    if h and h&gt;=0 then local k=HV.utf16(rq(e+8))
      if mode=='all' or k==own then writeFloat(e+0x10,mx) n=n+1 end end end end
  if n==0 then HV.msg('No support entry for the owner power in this city.','この都市に所有勢力の民心データがありません。')
  else HV.msg(('Support set to %d (%d entries)'):format(mx,n),('民心を%dに設定（%d件）'):format(mx,n)) end
end
function HV.refreshFeel(kind, parentID)
  HV.init()
  local parent=getAddressList().getMemoryRecordByID(parentID); if not parent then return end
  while parent.Count&gt;0 do parent.Child[0].destroy() end
  local c=HV.curCity(); local gv=c and rq(c+0xD8); if not gv then HV.msg('No city.','都市がありません。') return end
  local d=rq(gv+0x38); local ent=d and rq(d+0x18); local cnt=d and ri(d+0x20) or 0; local n=0
  if ent then for i=0,cnt-1 do local e=ent+0x20+i*0x18 local h=ri(e)
    if h and h&gt;=0 then
      local k=HV.utf16(rq(e+8)) or '?'
      local m=getAddressList().createMemoryRecord(); m.DontSave=true
      local nm=HV.powerName(k)..' ['..k..']'
      m.Description=nm; m.Address=string.format('%X',e+0x10); m.Type=vtSingle; m.appendToEntry(parent)
      HV.dyn[#HV.dyn+1]={id=m.ID,en=nm,jp=nm}; n=n+1
    end end end
  HV.msg('Support entries: '..n,'民心の項目: '..n..'件')
end


----------------------------------------------------------------- city garrison troops (gov block +0x40 List&lt;LHELDOLBNAN&gt;)
-- troop: +0x30 army-kind id (string), +0x38 army-kind def (BFFONNGCIHJ, name +0x10), +0x4C state (0 none/1 supplement/2 train/3 deploy/4 transport)
--        +0x50 soldiers (incl. wounded), +0x54 wounded, +0x58 experience, +0x5C morale (float)
local TSTATE={[0]={'-','－'},[1]={'Supplement','補充'},[2]={'Training','訓練'},[3]={'Deployed','出陣'},[4]={'Transport','輸送'}}
function HV.cityTroops()
  local c=HV.curCity(); local gv=c and rq(c+0xD8); return gv and rq(gv+0x40)
end
-- private troops (私兵軍政): city +0x108 List&lt;troop&gt; (same troop class as the garrison; see FIJIIFOIBOJ$$ANKDIMHEIBC / UI_PrivateArmyUI$$RefreshTroopRow)
function HV.cityPrivTroops()
  local c=HV.curCity(); return c and rq(c+0x108)
end
function HV.troopName(t)
  local def=rq(t+0x38); local nm=def and HV.ml(rq(def+0x10)) or ''
  if nm=='' then nm=HV.utf16(rq(t+0x30)) or '?' end
  return nm
end
function HV.refreshTroops(kind, parentID)
  HV.init()
  local parent=getAddressList().getMemoryRecordByID(parentID); if not parent then return end
  while parent.Count&gt;0 do parent.Child[0].destroy() end
  local lst=(kind=='prv') and HV.cityPrivTroops() or HV.cityTroops(); local n=0
  if not lst then HV.msg('No city.','都市がありません。') return end
  HV.listEach(lst, function(t)
    n=n+1
    local st=TSTATE[ri(t+0x4C) or -1] or {'?','?'}
    local nm=HV.troopName(t)
    local en=('#%d %s [%s]'):format(n,nm,st[1]); local jp=('#%d %s［%s］'):format(n,nm,st[2])
    local g=getAddressList().createMemoryRecord(); g.DontSave=true; g.IsGroupHeader=true; g.appendToEntry(parent)
    g.Description=HV.T(en,jp); HV.dyn[#HV.dyn+1]={id=g.ID,en=en,jp=jp}
    g.Color=HV.C_GROUP
    local function rec(e,j,off,vt)
      local r=getAddressList().createMemoryRecord(); r.DontSave=true
      r.Address=string.format('%X',t+off); r.Type=vt or vtDword
      if (vt or vtDword)==vtDword then pcall(function() r.ShowAsSigned=true end) end
      r.Description=HV.T(e,j); r.appendToEntry(g); HV.dyn[#HV.dyn+1]={id=r.ID,en=e,jp=j}
    end
    rec('Soldiers (incl. wounded)','兵士数（負傷兵含む）',0x50)
    rec('Wounded','負傷兵',0x54)
    rec('Experience','経験値',0x58)
    rec('Morale','士気',0x5C,vtSingle)
    rec('State (0 none/1 supplement/2 train/3 deploy/4 transport)','状態（0なし/1補充/2訓練/3出陣/4輸送）',0x4C)
  end)
  if not HV.quiet then
    if kind=='prv' then HV.msg('Private troops: '..n,'私兵部隊: '..n..'部隊')
    else HV.msg('Garrison troops: '..n,'保有部隊: '..n..'部隊') end
  end
end
function HV.troopsMax(kind)
  HV.init()
  local lst=(kind=='prv') and HV.cityPrivTroops() or HV.cityTroops(); if not lst then HV.msg('No city.','都市がありません。') return end
  local k=HV.st('KJNF'); local sMax=k and ri(k+0x2C); local mMax=k and ri(k+0x1C)
  local n=0
  HV.listEach(lst, function(t)
    if sMax and sMax&gt;0 and (ri(t+0x50) or 0)&lt;sMax then writeInteger(t+0x50,sMax) end
    writeInteger(t+0x54,0)
    writeInteger(t+0x58,100)
    if mMax and mMax&gt;0 then writeFloat(t+0x5C,mMax) end
    n=n+1 end)
  HV.msg(('Troops: %d (soldiers=%s, wounded=0, EXP=100, morale=%s)'):format(n,tostring(sMax),tostring(mMax)),
         ('部隊 %d: 兵士数=%s、負傷兵=0、経験値=100、士気=%s'):format(n,tostring(sMax),tostring(mMax)))
end
function HV.troopKind()
  HV.init()
  local lst=HV.cityTroops(); if not lst then HV.msg('No city.','都市がありません。') return end
  local tr,tn={},{}
  HV.listEach(lst, function(t) tr[#tr+1]=t tn[#tn+1]=('#%d %s  %d'):format(#tr,HV.troopName(t),ri(t+0x50) or 0) end)
  if #tr==0 then HV.msg('No troops.','部隊がありません。') return end
  tn[#tn+1]=HV.T('(all troops of this city)','（この都市の全部隊）')
  local i=HV.pick(HV.T('Select troop','部隊を選択'),tn); if not i then return end
  local og=HV.st('OGEN'); local ks,kn,kk={},{},{}
  HV.dictEach(og and rq(og+0xD0), function(k,v) ks[#ks+1]=v kk[#kk+1]=k kn[#kn+1]=HV.ml(rq(v+0x10))..' ['..(HV.utf16(k) or '')..']' end)
  if #ks==0 then HV.msg('Army kind table not loaded.','兵種データ未ロード。') return end
  local j=HV.pick(HV.T('Select army kind','兵種を選択'),kn); if not j then return end
  local targets = (i&gt;#tr) and tr or {tr[i]}
  for _,t in ipairs(targets) do writeQword(t+0x30,kk[j]) writeQword(t+0x38,ks[j]) end
  HV.msg('Army kind changed: '..#targets,'兵種を変更: '..#targets..'部隊')
end

-- add a new garrison troop to the selected city (game main thread, via dispatcher):
-- new LHELDOLBNAN (TypeInfo slot GA+5E444E8) -&gt; .ctor (1E89860) -&gt; +0x30 kind id, +0x20 city id -&gt; OBBECEPKCAK (1E889D0:
-- unique no., kind definition, owner power) -&gt; +0x50 soldiers -&gt; +0x58 EXP = 100 -&gt; gov+0x40 List.Add (MethodInfo slot GA+5E60E88).
-- Same sequence as the game's own troop creation (e.g. EKCOPHKIFME$$KEPLHNCHGNO 10204F1-10205A2).
-- create one troop of army kind (dictionary key string) with n soldiers in the selected city; returns true/false
local function troopCreate(key, n)
  local c=HV.curCity(); local gv=c and rq(c+0xD8); local lst=gv and rq(gv+0x40); local cid=c and rq(c+0x28)
  if not lst or not cid then HV.msg('No city selected.','都市が選択されていません。') return false end
  local F=getAddress('hvFlags')
  writeQword(F+0x58,key); writeQword(F+0x60,cid); writeInteger(F+0x68,n); writeQword(F+0x70,lst); writeQword(F+0x78,0)
  HV.hookUse('relDisp',true)
  writeInteger(F+0x50,1)
  local t=0
  while (ri(F+0x50) or 0)~=0 and t&lt;150 do sleep(20) t=t+1 end
  local timeout=(ri(F+0x50) or 0)~=0
  if timeout then writeInteger(F+0x50,0) end
  HV.hookUse('relDisp',false)
  local obj=rq(F+0x78)
  if timeout or not obj or obj==0 then HV.msg('Failed (game main loop not running?).','失敗しました（ゲームのメインループが動いていない可能性）。') return false end
  return true
end
local function troopReady()
  HV.init()
  local c=HV.curCity(); local gv=c and rq(c+0xD8)
  if not (gv and rq(gv+0x40)) then HV.msg('No city selected.','都市が選択されていません。') return false end
  local ti=HV.A.TI_TROOP and rq(HV.A.TI_TROOP); local mi=HV.A.MI_TROOPADD and rq(HV.A.MI_TROOPADD)
  local function ok(p) return p and p&gt;0x10000 and (p%2)==0 end
  if not ok(ti) or not ok(mi) then HV.msg('Game not ready (metadata not initialised). Load a save and retry.','ゲームの準備ができていません（メタデータ未初期化）。セーブデータをロードしてから再実行してください。') return false end
  return true
end
function HV.troopAdd()
  if not troopReady() then return end
  local og=HV.st('OGEN'); local kk,kn={},{}
  HV.dictEach(og and rq(og+0xD0), function(k,v) kk[#kk+1]=k kn[#kn+1]=HV.ml(rq(v+0x10))..' ['..(HV.utf16(k) or '')..']' end)
  if #kk==0 then HV.msg('Army kind table not loaded.','兵種データ未ロード。') return end
  local j=HV.pick(HV.T('Select army kind for the new troop','追加する部隊の兵種を選択'),kn); if not j then return end
  local k=HV.st('KJNF'); local cap=k and ri(k+0x2C) or 0
  local def=tostring(cap&gt;0 and cap or 1000)
  local v=HV.numberInput(HV.T('Add troop','部隊追加'), HV.T('Soldiers (1 - 1000000):','兵士数（1～1000000）:'), def)
  if not v then return end
  local n=math.tointeger(tonumber(v)); if not n or n&lt;1 or n&gt;1000000 then HV.msg('Invalid soldier count.','兵士数が不正です。') return end
  if not troopCreate(kk[j], n) then return end
  local warn=(cap&gt;0 and n&gt;cap) and HV.T(' (above the normal cap '..cap..')','（通常の上限 '..cap..' を超えています）') or ''
  HV.msg(('Troop added: %s, soldiers %d, EXP 100%s'):format(kn[j],n,warn), ('部隊を追加: %s、兵士数 %d、経験値 100%s'):format(kn[j],n,warn))
end
-- preset: add `count` troops of army kind id `kindId` with `n` soldiers each (e.g. 虎豹騎 [11702] x5, 10000)
function HV.troopAddPreset(kindId, n, count)
  if not troopReady() then return end
  local og=HV.st('OGEN'); local key,name
  HV.dictEach(og and rq(og+0xD0), function(k,v) if not key and HV.utf16(k)==kindId then key=k name=HV.ml(rq(v+0x10)) end end)
  if not key then HV.msg('Army kind '..kindId..' not found.','兵種 '..kindId..' が見つかりません。') return end
  local done=0
  for i=1,count do if troopCreate(key, n) then done=done+1 else break end end
  local c=HV.curCity(); local cn=c and HV.ml(rq(c+0x10)) or '?'
  HV.msg(('Troops added to %s: %s [%s] x%d, soldiers %d each, EXP 100'):format(cn,name or '?',kindId,done,n),
         ('%sに部隊を追加: %s [%s] ×%d部隊、兵士数 各%d、経験値 100'):format(cn,name or '?',kindId,done,n))
end

----------------------------------------------------------------- live lists (refresh on collapse/reopen)
HV.W = HV.W or {}
local SIG={}
local function listSig(l, t) if not l then t[#t+1]='0' return end
  t[#t+1]=tostring(ri(l+0x18) or 0); HV.listEach(l, function(v) t[#t+1]=string.format('%X',v) end) end
function SIG.item(kind)
  local owner, a, b
  if kind=='itw' then owner=HV.playerPower() a,b=0x110,0x160 else owner=(kind=='its') and HV.selHero or HV.playerHero() a,b=0x310,0x370 end
  local t={tostring(owner)}
  if owner then for off=a,b,8 do listSig(rq(owner+off),t) end end
  return table.concat(t,',')
end
function SIG.trp() local t={tostring(HV.curCity())} listSig(HV.cityTroops(),t) return table.concat(t,',') end
function SIG.prv() local t={tostring(HV.curCity())} listSig(HV.cityPrivTroops(),t) return table.concat(t,',') end
function SIG.pet() local t={} listSig(HV.petList(),t) return table.concat(t,',') end
function SIG.team() local t={} listSig(HV.teamList(),t) return table.concat(t,',') end
local function sigOf(kind) if kind=='trp' then return SIG.trp() elseif kind=='prv' then return SIG.prv()
  elseif kind=='pet' then return SIG.pet() elseif kind=='team' then return SIG.team() end return SIG.item(kind) end
local function build(kind,id)
  if kind=='trp' or kind=='prv' then HV.refreshTroops(kind,id)
  elseif kind=='pet' then HV.refreshPets(id) elseif kind=='team' then HV.refreshTeams(id)
  else HV.refreshItems(kind,id) end
  local p=getAddressList().getMemoryRecordByID(id)
  if p then  -- placeholder keeps the expander visible; expanding the group rebuilds the list
    local ph=getAddressList().createMemoryRecord(); ph.DontSave=true; ph.IsGroupHeader=true
    local en,jp='(collapse / expand this group to refresh)','（このグループを閉じて開くと更新）'
    ph.Description=HV.T(en,jp); ph.appendToEntry(p); HV.dyn[#HV.dyn+1]={id=ph.ID,en=en,jp=jp}
  end
end
function HV.watchStart(kind, id)
  HV.init()
  build(kind,id)
  HV.W[id]={kind=kind, sig=sigOf(kind)}
end
function HV.watchStop(id)
  HV.W[id]=nil
  local p=getAddressList().getMemoryRecordByID(id)
  if p then while p.Count&gt;0 do p.Child[0].destroy() end end
end
HV.expPrev = HV.expPrev or {}
function HV.expandTick()
  if not HV.EXPGROUPS then return end
  local al=getAddressList()
  for id,kind in pairs(HV.EXPGROUPS) do
    local mr=HV.W[id] and al.getMemoryRecordByID(id)
    if mr then
      local ok,col=pcall(function() return mr.Collapsed end)
      if ok and col~=nil then
        if HV.expPrev[id]==true and col==false then
          HV.quiet=false; pcall(build,kind,id)
          if HV.W[id] then HV.W[id].sig=sigOf(kind) end
        end
        HV.expPrev[id]=col
      end
    end
  end
end
function HV.watchTick()
  HV.expandTick() -- refresh only on explicit collapse/reopen
end

----------------------------------------------------------------- selection
local function pick(title,names)
  if #names==0 then return nil end
  local rows={};for i,name in ipairs(names) do rows[#rows+1]={id=i,name=name} end
  local row=HV.choose(title,rows,false)
  return row and row.id
end
HV.pick=pick
function HV.selectHeroUI()
  HV.init()
  local st=HV.st('UIHERO'); local h=st and rq(st+0x0)
  if not h then HV.msg('Open a hero info window in game first.','ゲーム内で武将情報画面を開いてください。') return end
  HV.selHero=h; HV.msg('Selected: '..HV.heroName(h),'選択: '..HV.heroName(h)); HV.refreshSuffix()
end
function HV.selectHeroSearch()
  HV.init()
  local pid=HV.pid;local og=HV.st('OGEN');local rows={}
  HV.dictEach(og and rq(og+0x8),function(k,h)
    rows[#rows+1]={id=h,displayId=HV.utf16(k) or '',name=HV.heroName(h),searchText=HV.heroName(h,true)}
  end)
  table.sort(rows,function(a,b)return a.name&lt;b.name end)
  local row=HV.choose(HV.T('Select hero','武将を選択'),rows,false)
  if not row then return end
  if not HV.processAlive() or HV.pid~=pid or HV.st('OGEN')~=og then HV.err('Game changed. Select again.','ゲームの状態が変わりました。選択し直してください。') end
  HV.selHero=row.id;HV.updatePtrs();HV.refreshSuffix()
end
function HV.selectPlayerAsSel() HV.init() HV.selHero=HV.playerHero() HV.refreshSuffix() end
function HV.selectCity(mode)
  HV.init()
  if mode=='cur' then HV.selCity=nil
  elseif mode=='ui' then local st=HV.st('UICITY') local c=st and rq(st+0x0)
    if not c then HV.msg('Open a city info window first.','ゲーム内で都市情報画面を開いてください。') return end
    HV.selCity=c
  else
    local pid=HV.pid;local fm=HV.st('FMAF');local rows={}
    HV.listEach(fm and rq(fm+0x58),function(c)
      rows[#rows+1]={id=c,displayId=#rows+1,name=HV.ml(rq(c+0x10)),searchText=HV.ml(rq(c+0x10),true)}
    end)
    local row=HV.choose(HV.T('Select city','都市を選択'),rows,false,{idCaption='No.'})
    if not row then return end
    if not HV.processAlive() or HV.pid~=pid or HV.st('FMAF')~=fm then HV.err('Game changed. Select again.','ゲームの状態が変わりました。選択し直してください。') end
    HV.selCity=row.id;HV.updatePtrs()
  end
  HV.refreshSuffix()
end

----------------------------------------------------------------- dynamic lists (template pattern (c))
HV.dyn = HV.dyn or {}
local function clearChildren(mr) while mr.Count&gt;0 do mr.Child[0].destroy() end end
-- [DISABLE] of a list row: stop its auto refresh and delete the generated rows
function HV.clearChildren(mr)
  if not mr then return end
  if HV.W then HV.W[mr.ID]=nil end
  clearChildren(mr)
end
function HV.addHdr(parent, en, ja)
  local m=getAddressList().createMemoryRecord(); m.DontSave=true
  m.IsGroupHeader=true m.Options='[moManualExpandCollapse]' m.Description=HV.T(en,ja) m.Color=HV.C_GROUP m.appendToEntry(parent)
  HV.dyn[#HV.dyn+1]={id=m.ID,en=en,jp=ja} return m
end
function HV.addRec(parent, en, ja, addr, vt)
  local m=getAddressList().createMemoryRecord(); m.DontSave=true
  m.Description=HV.T(en,ja) m.Type=vt or vtDword m.Address=addr m.appendToEntry(parent)
  HV.dyn[#HV.dyn+1]={id=m.ID,en=en,jp=ja} return m
end
-- [ENABLE] of the list rows
function HV.refreshDuelUnits(mr)   HV.refreshUnits('fi', mr.ID) end
function HV.refreshDebateUnits(mr) HV.refreshUnits('de', mr.ID) end
function HV.refreshWarUnits(mr)    HV.refreshUnits('wa', mr.ID) end
function HV.refreshFeelList(mr)    HV.refreshFeel('feel', mr.ID) end
function HV.refreshTroopList(mr)   HV.watchStart('trp', mr.ID) end   -- refresh on collapse/reopen
function HV.refreshPrivTroopList(mr) HV.watchStart('prv', mr.ID) end
function HV.refreshPlayerItems(mr) HV.watchStart('itp', mr.ID) end
function HV.refreshHeroItems(mr)   HV.watchStart('its', mr.ID) end
function HV.refreshStorageItems(mr) HV.watchStart('itw', mr.ID) end
local function addRec(parent, en, jp, slot, off, vt)
  local m=getAddressList().createMemoryRecord(); m.DontSave=true
  m.Description=HV.T(en,jp)
  m.Address=string.format('hvUnits+%X',slot*8)
  m.OffsetCount=1; m.Offset[0]=off
  m.Type=vt or vtDword
  if (vt or vtDword)==vtDword then pcall(function() m.ShowAsSigned=true end) end
  m.appendToEntry(parent)
  HV.dyn[#HV.dyn+1]={id=m.ID,en=en,jp=jp}
  return m
end
local function addHdr(parent, en, jp)
  local m=getAddressList().createMemoryRecord(); m.DontSave=true
  m.Description=HV.T(en,jp); m.IsGroupHeader=true; m.Options='[moManualExpandCollapse]'; m.appendToEntry(parent)
  HV.dyn[#HV.dyn+1]={id=m.ID,en=en,jp=jp}
  m.Color=HV.C_GROUP
  return m
end
local SIDE={[0]={'Mine','自軍'},[1]={'Enemy','敵'},[2]={'Neutral','中立'},[3]={'Ally','友軍'}}
local function sideName(s) local t=SIDE[s or -1] or {'?','?'} return t[1],t[2] end
function HV.refreshUnits(kind, parentID)
  HV.init()
  local parent=getAddressList().getMemoryRecordByID(parentID); if not parent then return end
  clearChildren(parent)
  local U=getAddress('hvUnits'); local slot=0; local maxSlot=190
  local function put(p) if slot&gt;=maxSlot then return nil end writeQword(U+slot*8,p) slot=slot+1 return slot-1 end
  if kind=='fi' then
    local st=HV.st('FIC'); local npcK=HV.klass('NPC'); local anK=HV.klass('ANIMAL')
    HV.listEach(st and rq(st+0x48), function(o)
      local k=rq(o); local at,name
      if k==npcK then at=rq(o+0x128) name=HV.heroName(rq(o+0x110))
      elseif k==anK then at=rq(o+0x40) local ao=rq(o+0x28) name=HV.ml(ao and rq(ao+0x20)) end
      if at then local s=put(at) if not s then return false end
        local se,sj=sideName(ri(at+0x28))
        local g=addHdr(parent,'['..se..'] '..(name or '?'),'['..sj..'] '..(name or '?'))
        addRec(g,'HP','HP',s,0x40); addRec(g,'MP','MP',s,0x44); addRec(g,'AP (action)','AP(行動力)',s,0x50)
        addRec(g,'Side (0 mine/1 enemy/2 neutral/3 ally)','陣営(0自軍/1敵/2中立/3友軍)',s,0x28)
      end end)
  elseif kind=='de' then
    local st=HV.st('DEC')
    HV.listEach(st and rq(st+0x20), function(o)
      local at=rq(o+0x130); if not at then return end
      local s=put(at); if not s then return false end
      local se,sj=sideName(ri(at+0x20)); local name=HV.heroName(rq(o+0x110))
      local g=addHdr(parent,'['..se..'] '..name,'['..sj..'] '..name)
      addRec(g,'HP','HP',s,0x28); addRec(g,'HP max','HP上限',s,0x2C); addRec(g,'AP (action)','AP(行動力)',s,0x48)
      addRec(g,'Side (0 mine/1 enemy/3 ally)','陣営(0自軍/1敵/3友軍)',s,0x20)
    end)
  elseif kind=='wa' then
    local w=HV.st('WAC')
    for _,sd in ipairs({{0xE8,'Mine','自軍'},{0xF0,'Enemy','敵'}}) do
      HV.listEach(w and rq(w+sd[1]), function(a)
        local at=rq(a+0x18); local tr=at and rq(at+0x20); if not tr then return end
        local s=put(tr); if not s then return false end
        local name=HV.heroName(at and rq(at+0x18))
        local g=addHdr(parent,'['..sd[2]..'] '..name,'['..sd[3]..'] '..name)
        addRec(g,'Soldiers','兵士数',s,0x50); addRec(g,'Wounded','負傷兵',s,0x54)
        addRec(g,'Experience','経験',s,0x58); addRec(g,'Morale','士気',s,0x5C,vtSingle)
      end)
    end
    for _,sd in ipairs({{true,'Mine','自軍'},{false,'Enemy','敵'}}) do
      HV.listEach(warTeams(sd[1]), function(t) local s=put(t) if not s then return false end
        addRec(parent,'['..sd[2]..'] Deploy team food','['..sd[3]..'] 出陣部隊の兵糧',s,0x150) end)
    end
  end
  HV.msg('Listed entries: '..slot,'一覧化: '..slot..' 件')
end


----------------------------------------------------------------- 1.0.6 additions
-- pets (保有ペット): OFFA static +0x50 List&lt;pet&gt;. Fields as shown by the game's pet screen (UI_AnimalUI$$HFODNFHFKKH):
-- +0x10 definition (+0x18 breed name), +0x20 name, +0x38 level cap, +0x3C feed cost / month, +0x40 value,
-- +0x48 attack, +0x4C defense, +0x50 speed, +0x54 HP, +0x58 true qi, +0x5C dodge %, +0x60 critical %, +0x64 counter %,
-- +0x6C action points, +0x74 cards drawn, +0x128 level, +0x12C EXP (next level: KJNF static +0x248 List&lt;int&gt;), +0x130 age (months)
HV.PETROWS={
  {0x128,'Level','等級'},{0x38,'Level cap','等級上限'},{0x12C,'EXP','経験値'},
  {0x130,'Age (months)','年齢（月数）'},{0x40,'Value','価値'},{0x3C,'Feed cost / month','飼育費（月額）'},
  {0x48,'Attack','攻撃力'},{0x4C,'Defense','防御力'},{0x50,'Speed','速度'},{0x54,'HP','生命値'},
  {0x58,'True qi','真気値'},{0x6C,'Action points','行動点'},{0x5C,'Dodge (%)','回避率（%）'},
  {0x60,'Critical (%)','会心率（%）'},{0x64,'Counter (%)','反撃率（%）'},{0x74,'Cards drawn','ドロー枚数'},
}
function HV.petList() local st=HV.st('OFFA') return st and rq(st+0x50) end
function HV.refreshPets(parentID)
  HV.init()
  local parent=getAddressList().getMemoryRecordByID(parentID); if not parent then return end
  while parent.Count&gt;0 do parent.Child[0].destroy() end
  local lst=HV.petList()
  if not lst then HV.msg('No pet data (load a save first).','ペットのデータがありません（セーブデータをロードしてください）。') return end
  local n=0
  HV.listEach(lst, function(p)
    n=n+1
    local def=rq(p+0x10)
    local br=def and HV.ml(rq(def+0x18)) or ''
    local nm=HV.ml(rq(p+0x20)); if nm=='' then nm=br end
    local lv=ri(p+0x128) or 0
    local g=HV.addHdr(parent,('#%d %s [%s] Lv %d'):format(n,nm,br,lv),('#%d %s［%s］等級 %d'):format(n,nm,br,lv))
    for _,r in ipairs(HV.PETROWS) do
      local m=HV.addRec(g,r[2],r[3],string.format('%X',p+r[1]),vtDword)
      pcall(function() m.ShowAsSigned=true end)
    end
  end)
  if not HV.quiet then HV.msg('Pets: '..n,'保有ペット: '..n..'匹') end
end
function HV.refreshPetList(mr) HV.watchStart('pet', mr.ID) end

-- accompanying teams (同行部隊): OFFA static +0x58 List&lt;team&gt; (hired with UI_MercenaryUI; capacity check in UI_MercenaryUI$$ButtonHirePress).
-- team: +0x10 mercenary kind (+0x10 id, +0x18 template hero; its +0x94 = max soldiers of the team),
--       +0x18 loyalty (the game's setter clamps 0-200), +0x1C EXP (clamped 0-10000), +0x20 soldiers, +0x24 wounded
--       (replenish = max - wounded - soldiers, UI_MercenaryUI$$JGCHJKALMGM)
HV.TEAMROWS={
  {0x20,'Soldiers','兵士数'},{0x24,'Wounded','負傷兵'},
  {0x18,'Loyalty (0-200)','忠誠（0～200）'},{0x1C,'EXP (0-10000)','経験値（0～10000）'},
}
function HV.teamList() local st=HV.st('OFFA') return st and rq(st+0x58) end
function HV.refreshTeams(parentID)
  HV.init()
  local parent=getAddressList().getMemoryRecordByID(parentID); if not parent then return end
  while parent.Count&gt;0 do parent.Child[0].destroy() end
  local lst=HV.teamList()
  if not lst then HV.msg('No accompanying team data (load a save first).','同行部隊のデータがありません（セーブデータをロードしてください）。') return end
  local n=0
  HV.listEach(lst, function(t)
    n=n+1
    local def=rq(t+0x10); local h=def and rq(def+0x18)
    local nm=h and HV.heroName(h) or ''
    if nm=='' or nm=='?' then nm=(def and HV.utf16(rq(def+0x10))) or '?' end
    local mx=h and ri(h+0x94) or 0
    local g=HV.addHdr(parent,('#%d %s (soldiers + wounded max %d)'):format(n,nm,mx),('#%d %s（兵士数＋負傷兵の上限 %d）'):format(n,nm,mx))
    for _,r in ipairs(HV.TEAMROWS) do
      local m=HV.addRec(g,r[2],r[3],string.format('%X',t+r[1]),vtDword)
      pcall(function() m.ShowAsSigned=true end)
    end
  end)
  if not HV.quiet then HV.msg('Accompanying teams: '..n,'同行部隊: '..n..'部隊') end
end
function HV.refreshTeamList(mr) HV.watchStart('team', mr.ID) end

-- add an accompanying team from the mercenary list (same as hiring, UI_MercenaryUI$$ELMIKACBCDN):
-- kinds = OGEN static +0x1F0 Dictionary&lt;string, kind&gt; (kind +0x18 template hero; its +0x94 = max soldiers;
--   kind +0x2C rarity MNGEAENFIJL 0 Common / 1 Good / 2 Excellent / 3 Legend, shown by UI_MercenaryUI$$RefreshListContent);
-- new HCHLHPMNGPC (TypeInfo TI_TEAM) -&gt; +0x10 kind, +0x20 soldiers -&gt; OFFA static +0x58 List.Add (MethodInfo MI_TEAMADD).
-- The game's hire leaves loyalty and EXP at 0 (empty .ctor); this does the same. No money is paid and the team cap is not checked.
HV.TEAM_STUB = [==[unregistersymbol(hvTeamNew)
alloc(hvTeamNew,$100,GameAssembly.dll)
registersymbol(hvTeamNew)
label(hvTeamNew_end)
hvTeamNew:
  push rbx
  push rsi
  push rdi
  push r12
  sub rsp,28
  mov rsi,rcx
  mov edi,edx
  mov r12,r8
  mov rbx,r9
  mov rcx,[hvA_TI_TEAM]
  call hvA_f_objnew
  test rax,rax
  je hvTeamNew_end
  mov [rax+10],rsi
  mov [rax+20],edi
  mov [rbx],rax
  mov rcx,r12
  mov rdx,rax
  mov r8,[hvA_MI_TEAMADD]
  call hvA_f_listadd
hvTeamNew_end:
  add rsp,28
  pop r12
  pop rdi
  pop rsi
  pop rbx
  ret
]==]
HV.RARITY={[0]={'Common','普通'},[1]={'Good','良好'},[2]={'Excellent','優秀'},[3]={'Legend','伝説'}}
function HV.teamAdd()
  HV.init()
  for _,k in ipairs({'TI_TEAM','MI_TEAMADD','f_objnew','f_listadd'}) do
    if not HV.A[k] then HV.err('Game code for this feature was not found ('..k..').','この機能に必要なゲームコードが見つかりません（'..k..'）。') end
  end
  local function ok(p) return p and p&gt;0x10000 and (p%2)==0 end
  if not ok(rq(HV.A.TI_TEAM)) or not ok(rq(HV.A.MI_TEAMADD)) then
    HV.msg('Game not ready (metadata not initialised). Load a save and retry.','ゲームの準備ができていません（メタデータ未初期化）。セーブデータをロードしてから再実行してください。') return end
  local lst=HV.teamList(); if not lst then HV.msg('No accompanying team data (load a save first).','同行部隊のデータがありません（セーブデータをロードしてください）。') return end
  local og=HV.st('OGEN'); local ks={}
  HV.dictEach(og and rq(og+0x1F0), function(k,d)
    local h=rq(d+0x18); local nm=h and HV.heroName(h) or '?'
    ks[#ks+1]={d=d,nm=nm,id=HV.utf16(k) or '',mx=(h and ri(h+0x94)) or 0,rr=ri(d+0x2C)} end)
  if #ks==0 then HV.msg('Mercenary list not loaded.','傭兵の一覧が読み込まれていません。') return end
  table.sort(ks,function(a,b) if a.nm~=b.nm then return a.nm&lt;b.nm end return a.id&lt;b.id end)
  local names={}
  for i,e in ipairs(ks) do
    local r=HV.RARITY[e.rr or -1] or {'?','?'}
    names[i]=HV.T(('%s [%s] (rarity: %s, max %d)'):format(e.nm,e.id,r[1],e.mx),('%s［%s］（レア度: %s、上限 %d）'):format(e.nm,e.id,r[2],e.mx))
  end
  local i=HV.pick(HV.T('Mercenary to add','追加する傭兵'),names); if not i then return end
  local e=ks[i]
  local v=HV.numberInput(HV.T('Add accompanying team','同行部隊を追加'),HV.T('Soldiers (1 - 1000000):','兵士数（1～1000000）:'),tostring(e.mx&gt;0 and e.mx or 100))
  if not v then return end
  local n=math.tointeger(tonumber(v)); if not n or n&lt;1 or n&gt;1000000 then HV.msg('Invalid soldier count.','兵士数が不正です。') return end
  if not HV.teamOK or not getAddressSafe('hvTeamNew') then
    local okA,err=autoAssemble(HV.TEAM_STUB); if not okA then error('stub: '..tostring(err)) end
    HV.teamOK=true
  end
  local S=getAddress('hvTeamNew'); local res=S+0xF0
  writeQword(res,0)
  HV.callMain({{S, e.d, n, lst, res}})
  if (rq(res) or 0)==0 then HV.msg('Failed (game main loop not running?).','失敗しました（ゲームのメインループが動いていない可能性）。') return end
  local k=HV.st('KJNF'); local cap=k and ri(k+0x28) or 0
  local st=HV.st('OFFA'); local cnt=(ri(lst+0x18) or 0)+((st and rq(st+0x40)) and (ri(rq(st+0x40)+0x18) or 0) or 0)
  local warn=(cap&gt;0 and cnt&gt;cap) and HV.T((' (above the normal capacity %d)'):format(cap),('（通常の同行上限 %d を超えています）'):format(cap)) or ''
  local warn2=(e.mx&gt;0 and n&gt;e.mx) and HV.T((' (above the team max %d)'):format(e.mx),('（部隊の上限 %d を超えています）'):format(e.mx)) or ''
  local r=HV.RARITY[e.rr or -1] or {'?','?'}
  HV.msg(('Accompanying team added: %s (rarity: %s), soldiers %d%s%s'):format(e.nm,r[1],n,warn2,warn),('同行部隊を追加: %s（レア度: %s）、兵士数 %d%s%s'):format(e.nm,r[2],n,warn2,warn))
end

-- identify all items: item +0x1D = unidentified flag (GGFGEFIDKJJ$$MINOKFMEELM shows "待鉴定" while it is set).
-- The game's identify (UI_IdentifyUI$$ExecuteIdentity) removes the item and gives the same item id x1 with the flag off;
-- here the flag is cleared in place (player items hero +0x310..+0x370, power storage +0x110..+0x160).
function HV.identifyAll()
  HV.init()
  local n=0
  local function scan(owner,a,b)
    if not owner then return end
    for off=a,b,8 do HV.listEach(rq(owner+off), function(it)
      if readBytes(it+0x1D,1)~=0 then writeBytes(it+0x1D,0) n=n+1 end end) end
  end
  scan(HV.playerHero(),0x310,0x370); local np=n
  scan(HV.playerPower(),0x110,0x160)
  HV.msg(('Items identified: player %d / power storage %d'):format(np,n-np),('未鑑定品を鑑定済みにしました: 主人公 %d件 / 勢力の所蔵品 %d件'):format(np,n-np))
end

----------------------------------------------------------------- children with every spouse
-- spouse = hero whose relation stage toward the player (+0x2AC) is 11 夫妻 / 12 灵魂伴侣 / 13 至死不渝 (ENOMPEFKFND$$IMHBIHHENEL)
-- conception: ENOMPEFKFND$$MPGFHGJIEPL(mother, father id string): mother must be female (+0x4C = 1) and not pregnant
--   (+0x260 List empty); it creates the child record in mother+0x260 and sets +0x258 father id, +0x268 pregnancy days,
--   +0x26C days passed (same call as the event command, DNBEGJHBLEP$$EGNPJIKFBLO).
-- birth: ENOMPEFKFND$$MBCHOLNMFMM(mother). The game's daily tick (ENOMPEFKFND$$LHGCGKEKOOD) calls it when +0x26C &gt;= +0x268
--   and UI_SetChildNameUI.m_isOpen (static +9), DCNIHGCEGNJ static +0x55A and OFFA static +0x1B8 are all 0, then sets
--   +0x26C = 0 and clears +0x260. This table does the same, one spouse at a time (the naming screen opens for each child).
HV.childQ = HV.childQ or {}
local function childBusy()
  local ui=HV.st('TI_CHILDUI'); local dc=HV.st('TI_DCNI'); local st=HV.st('OFFA')
  if not dc or not st then return true end
  if ui and readBytes(ui+9,1)~=0 then return true end
  return readBytes(dc+0x55A,1)~=0 or readBytes(st+0x1B8,1)~=0
end
local function listClear(l)   -- same as the game: version+1, size 0, clear used slots
  local n=ri(l+0x18) or 0; local items=rq(l+0x10)
  writeInteger(l+0x1C,(ri(l+0x1C) or 0)+1); writeInteger(l+0x18,0)
  if items then for i=0,n-1 do writeQword(items+0x20+i*8,0) end end
end
function HV.childStop(quiet)
  if HV.childTimer then pcall(function() HV.childTimer.destroy() end) HV.childTimer=nil end
  local n=#(HV.childQ or {})
  HV.childQ={}
  if not quiet then HV.msg(('Pending child creation stopped (%d cancelled). Children already born are kept.'):format(n),
                           ('子供作成の待機分を停止しました（取消 %d件）。作成済みの子供はそのままです。'):format(n)) end
end
local function childSummary()
  local R=HV.childR or {}
  HV.msg(('Children done: born %d / skipped (pregnant by someone else) %d / failed %d / same sex %d / dead %d'):format(R.done or 0,R.skip or 0,R.fail or 0,R.same or 0,R.dead or 0),
         ('子供作成の完了: 出生 %d / スキップ（他の相手の子を妊娠中） %d / 失敗 %d / 同性 %d / 死亡 %d'):format(R.done or 0,R.skip or 0,R.fail or 0,R.same or 0,R.dead or 0))
end
local function childStep()
  if HV.childBusyStep then return end
  if not HV.attached() then HV.childStop(true) return end
  if childBusy() then return end
  local e=HV.childQ[1]
  if not e then HV.childStop(true) childSummary() return end
  local R=HV.childR
  HV.childBusyStep=true
  local ok,err=pcall(function()
    local m=e.m; local l=rq(m+0x260)
    if not l then table.remove(HV.childQ,1) R.fail=R.fail+1 return end
    if (ri(l+0x18) or 0)&gt;0 then
      if HV.utf16(rq(m+0x258))~=e.fid then
        table.remove(HV.childQ,1) R.skip=R.skip+1
        HV.msg('Skipped (already pregnant by someone else): '..e.name,'スキップ（他の相手の子を妊娠中）: '..e.name)
        return
      end
    else
      HV.callMain({{HV.A.f_conceive, m, e.fp, 0, 0}})
      if (ri(l+0x18) or 0)==0 then
        table.remove(HV.childQ,1) R.fail=R.fail+1
        HV.msg('Failed (the game refused the pregnancy): '..e.name,'失敗（ゲームが妊娠を受け付けませんでした）: '..e.name)
        return
      end
    end
    HV.callMain({{HV.A.f_birth, m, 0, 0, 0}})
    writeInteger(m+0x26C,0); listClear(l)
    table.remove(HV.childQ,1) R.done=R.done+1
    HV.msg(('Child born: %s (%d left). Name the child in game; the next one follows after the naming screen closes.'):format(e.name,#HV.childQ),
           ('子供が生まれました: %s（残り %d）。ゲームの画面で命名してください。命名画面が閉じると次へ進みます。'):format(e.name,#HV.childQ))
  end)
  HV.childBusyStep=false
  if not ok then HV.msg('Child creation paused: '..tostring(err),'子供作成を一時停止中: '..tostring(err)) end
end
function HV.childAll()
  HV.init()
  if not HV.A.f_conceive or not HV.A.f_birth then
    HV.err('Feature unavailable: pregnancy / birth code not found in this build.','この機能は使えません: このビルドでは妊娠・出生のコードが見つかりません。') end
  if not HV.A.TI_DCNI then HV.err('Game code for this feature was not found (TI_DCNI).','この機能に必要なゲームコードが見つかりません（TI_DCNI）。') end
  if HV.childTimer and #HV.childQ&gt;0 then HV.msg(('Child creation is already running (%d left).'):format(#HV.childQ),('子供作成は実行中です（残り %d）。'):format(#HV.childQ)) return end
  local ph=HV.playerHero(); if not ph then HV.msg('No player.','主人公がいません。') return end
  local og=HV.st('OGEN'); local q={}; local same,dead=0,0
  local psex=ri(ph+0x4C)
  HV.dictEach(og and rq(og+0x8), function(k,h)
    if h==ph then return end
    local stg=ri(h+0x2AC)
    if stg~=11 and stg~=12 and stg~=13 then return end
    local s=rq(h+0x120); if s and ri(s+0x30)==3 then dead=dead+1 return end
    local hs=ri(h+0x4C)
    if hs==psex then same=same+1 return end
    local mom=(hs==1) and h or ph; local dad=(hs==1) and ph or h
    local fp=rq(dad+0x30)
    if fp then q[#q+1]={m=mom,fp=fp,fid=HV.utf16(fp),name=HV.heroName(h)} end
  end)
  if #q==0 then HV.msg(('No spouse to have a child with (same sex %d, dead %d).'):format(same,dead),('子供を作れる配偶者がいません（同性 %d、死亡 %d）。'):format(same,dead)) return end
  HV.childQ=q; HV.childR={done=0,skip=0,fail=0,same=same,dead=dead}
  if HV.childTimer then pcall(function() HV.childTimer.destroy() end) end
  HV.childTimer=createTimer(nil,false); HV.childTimer.Interval=500
  HV.childTimer.OnTimer=HV.guard(function() pcall(childStep) end)
  HV.childTimer.Enabled=true
  HV.msg(('Child creation started for %d spouse(s). Keep the game on the world / city screen and name each child when asked.'):format(#q),
         ('%d人の配偶者との子供作成を開始しました。ワールド／都市画面のまま、命名画面が出たら命名してください。'):format(#q))
end

----------------------------------------------------------------- language
HV.suffix = HV.suffix or {}
function HV.refreshSuffix()
  if HV.syncHeroFamily then HV.syncHeroFamily(true) end
  HV.suffix[HV.ID_SELHERO or -1] = HV.selHero and HV.heroName(HV.selHero) or nil
  local c=HV.curCity(); HV.suffix[HV.ID_CITY or -1] = c and HV.ml(rq(c+0x10)) or nil
  HV.suffix[14000]=HV.selPower and (HV.utf16(HV.rq(HV.selPower+0x10)) or '') or nil
  HV.suffix[14100]=HV.selFamily and HV.ml(HV.rq(HV.selFamily+0x18)) or nil
  HV.applyLang()
end
function HV.applyLang()
  local al=getAddressList()
  for i=0,al.Count-1 do
    local m=al.getMemoryRecord(i); local n=HV.NAMES[m.ID]
    if n then
      local d=(HV.lang=='ja') and n[2] or n[1]
      if HV.suffix[m.ID] then d=d..' : '..HV.suffix[m.ID] end
      if m.Description~=d then m.Description=d end
    end
  end
  local keep={}
  for _,e in ipairs(HV.dyn) do local m=e.id and al.getMemoryRecordByID(e.id);if m then local d=HV.T(e.en,e.jp);if m.Description~=d then m.Description=d end;keep[#keep+1]=e end end
  HV.dyn=keep
end
function HV.setLang(l) if l=='jp' then l='ja' end HV.lang=l HV.applyLang() end
-- initial layout when the table is opened: "0. Settings &amp; README" expanded, every other group collapsed
----------------------------------------------------------------- social statuses of the selected hero toward the player
-- hero +0x2B0 List&lt;DOFGHPJFGID&gt;{+10 type (0 Romantic, 1 Awe, 2 Obligation, 3 Roused), +14 days left, +18 layers}
-- hero +0x2B8 social will (current). PPBDENEFMNG$$HAGAIMHDCEM(hero, type): the game's own "add one layer".
HV.SOCIAL={[0]={'Romantic','浪漫'},[1]={'Awe','畏敬'},[2]={'Obligation','借り'},[3]={'Roused','発奮'}}
local function selTarget()
  local h=HV.selHero
  if not h then HV.err('Select a hero first (7. Hero editor &gt; Selected hero).','先に武将を選択してください（7. 武将エディタ ＞ 選択武将）。') end
  if h==HV.playerHero() then HV.err('Select a hero other than the player.','主人公以外の武将を選択してください。') end
  return h
end
function HV.addSocialStatus(t)
  HV.init()
  local h=selTarget()
  if not HV.A.f_addstatus then HV.err('Game code for this feature was not found.','この機能に必要なゲームコードが見つかりません。') end
  HV.callMain({{HV.A.f_addstatus, h, t, 0, 0}})
  local n=0
  HV.listEach(rq(h+0x2B0), function(e) if ri(e+0x10)==t then n=ri(e+0x18) or 0 end end)
  local s=HV.SOCIAL[t]
  HV.msg(('%s: %d layer(s) now.'):format(s[1],n),('%s: 現在 %d 層。'):format(s[2],n))
end
function HV.refreshSocialStatus(mr)
  HV.init()
  HV.clearChildren(mr)
  local h=selTarget()
  local n=0
  HV.listEach(rq(h+0x2B0), function(e)
    local t=ri(e+0x10); local s=HV.SOCIAL[t] or {'Type '..tostring(t),'種類 '..tostring(t)}
    local g=HV.addHdr(mr, s[1], s[2])
    HV.addRec(g, 'Layers', '層数', string.format('%X',e+0x18), vtDword)
    HV.addRec(g, 'Days left', '残り日数', string.format('%X',e+0x14), vtDword)
    n=n+1
  end)
  if n==0 then HV.addHdr(mr,'(none: add a layer with the actions above)','（なし: 上の項目で1層追加してください）') end
end

----------------------------------------------------------------- diagnostics (template)
function HV.attached() return HV.pid~=nil and HV.pid==getOpenedProcessID() and HV.processAlive() and getAddressSafe('hvFlags')~=nil end
-- Lua Engine window: the diagnostics row is a toggle (check = open / uncheck = close)
function HV.luaEngine() local ok,f=pcall(getLuaEngine) if ok then return f end end
function HV.openLuaEngine(quiet)
  local f=HV.luaEngine()
  if f then pcall(function() f.show() end) pcall(function() f.bringToFront() end) end
  if not quiet then HV.msg('Lua Engine opened. Messages of this table are printed here.','Lua Engineを開きました。このテーブルのメッセージはここに表示されます。') end
end
function HV.closeLuaEngine()
  local f=HV.luaEngine()
  if f then pcall(function() f.hide() end) end
end
function HV.envReport()
  HV.openLuaEngine(true)
  local pid=getOpenedProcessID()
  print(('[HV] CE version      : %s'):format(tostring(getCEVersion and getCEVersion())))
  print(('[HV] target process  : %s (running PID %s / opened PID %s / table PID %s)'):format(HV.EXE,
        tostring(getProcessIDFromProcessName(HV.EXE)), tostring(pid), tostring(HV.pid)))
  local okx,x64=pcall(targetIs64Bit) print(('[HV] target 64-bit   : %s'):format(tostring(okx and x64)))
  local m=HV.ga()
  if m then
    local ts=HV.peTimestamp()
    print(('[HV] module          : %s base=%X size=%X PE-timestamp=%X'):format(HV.MODULE, m, getModuleSize(HV.MODULE) or 0, ts or 0))
    print(('[HV] expected build  : timestamp=%X size=%X (v%s)'):format(HV.BUILD.ts, HV.BUILD.size or 0, HV.GAMEVER))
  else print(('[HV] module          : %s NOT FOUND'):format(HV.MODULE)) end
  local b=getAddressSafe('hvFlags')
  print(('[HV] shared memory   : hvFlags=%s'):format(b and string.format('%X',b) or 'not allocated'))
  print(('[HV] attached        : %s'):format(tostring(HV.attached())))
end
function HV.statusReport()
  HV.openLuaEngine(true)
  local l=HV.pendingNames and HV.pendingNames() or {}
  print(('[HV] unresolved signatures: %s'):format(#l&gt;0 and table.concat(l,', ') or '-'))
  local h={} for n,st in pairs(HV.hookState or {}) do if (st.ref or 0)&gt;0 then h[#h+1]=n end end table.sort(h)
  print(('[HV] active hooks        : %s'):format(#h&gt;0 and table.concat(h,', ') or '-'))
  local sl={} for k in pairs(HV.stale or {}) do sl[#sl+1]=k end table.sort(sl)
  print(('[HV] hooks left by an earlier CE session: %s'):format(#sl&gt;0 and table.concat(sl,', ') or '-'))
  local f={} for k in pairs(HV.featOn or {}) do f[#f+1]=k end table.sort(f)
  print(('[HV] features on         : %s'):format(#f&gt;0 and table.concat(f,', ') or '-'))
  local al=getAddressList(); local a={}
  for i=0,al.Count-1 do local m=al.getMemoryRecord(i) if m.Active then a[#a+1]=('[%d] %s'):format(m.ID,m.Description) end end
  print(('[HV] active records      : %s'):format(#a&gt;0 and table.concat(a,' / ') or '-'))
end

function HV.initCollapse()
  local al=getAddressList()
  for i=0,al.Count-1 do
    local m=al.getMemoryRecord(i)
    if m.Count&gt;0 then
      local opt=''; pcall(function() opt=tostring(m.Options) end)
      if not opt:find('moHideChildren') then
        local inZero=false; local p=m
        while p do if p.ID==HV.ID_TOP0 then inZero=true break end p=p.Parent end
        pcall(function() m.Collapsed = not inZero end)
      end
    end
  end
  HV.expPrev={}
end

-- Steam achievement action: explicit one-shot only; never called by a timer.
local function steamBool(v) return type(v)=='number' and (v&amp;0xFF)~=0 end
function HV.steamAchievementExports(module)
  local base,size=getAddressSafe(module),getModuleSize(module)
  if not base or not size or size&lt;=0 then HV.err('Steam API is not loaded. Start the game through Steam.','Steam APIが読み込まれていません。Steamからゲームを起動してください。') end
  local function at(rva,n)
    assert(type(rva)=='number' and rva&gt;=0 and rva+(n or 4)&lt;=size,'Invalid Steam API export layout')
    return base+rva
  end
  local function uint(rva)
    local n=readInteger(at(rva,4));assert(n,'Unreadable Steam API export layout');return n&amp;0xFFFFFFFF
  end
  local nt=uint(0x3C)
  assert(readSmallInteger(base)==0x5A4D and uint(nt)==0x4550 and readSmallInteger(at(nt+0x18,2))==0x20B,'Invalid Steam API PE header')
  local dir,dirSize=uint(nt+0x88),uint(nt+0x8C)
  at(dir,40);assert(dir&gt;0 and dirSize&gt;0,'Missing Steam API export directory')
  local functions,names=uint(dir+0x14),uint(dir+0x18)
  assert(functions&gt;0 and functions&lt;=65536 and names&gt;0 and names&lt;=65536,'Invalid Steam API export count')
  local ft,ntable,ord=uint(dir+0x1C),uint(dir+0x20),uint(dir+0x24)
  at(ft,functions*4);at(ntable,names*4);at(ord,names*2)
  local exports={}
  for i=0,names-1 do
    local nameRva=uint(ntable+i*4)
    local name=readString(at(nameRva,1),math.min(256,size-nameRva),false)
    if name and name:find('SteamAPI_',1,true)==1 then
      local index=readSmallInteger(at(ord+i*2,2))
      assert(index and (index&amp;0xFFFF)&lt;functions,'Invalid Steam API export ordinal')
      local rva=uint(ft+(index&amp;0xFFFF)*4)
      if rva&gt;0 and not (rva&gt;=dir and rva&lt;dir+dirSize) then exports[name]=at(rva,1) end
    end
  end
  return exports,base,size
end

function HV.steamAchievementsApi()
  HV.attachGame()
  if not HV.processAlive() then HV.err('Game is not available.','ゲームに接続できません。') end
  local module='steam_api64.dll'
  local exports,base,size=HV.steamAchievementExports(module)
  local names={stats='SteamAPI_SteamUserStats_v012',utils='SteamAPI_SteamUtils_v010',app='SteamAPI_ISteamUtils_GetAppID',
    count='SteamAPI_ISteamUserStats_GetNumAchievements',name='SteamAPI_ISteamUserStats_GetAchievementName',
    get='SteamAPI_ISteamUserStats_GetAchievement',set='SteamAPI_ISteamUserStats_SetAchievement',store='SteamAPI_ISteamUserStats_StoreStats'}
  local api={pid=getOpenedProcessID()}
  for key,name in pairs(names) do
    local a=exports[name]
    if not a or a&lt;base or a&gt;=base+size then HV.err('Steam API export unavailable: '..name,'Steam API関数を取得できません: '..name) end
    api[key]=a
  end
  function api.call(key,...)
    if getOpenedProcessID()~=api.pid or not HV.processAlive() then
      api.uncertain=true
      HV.err('Game disconnected; achievement action stopped.','ゲームとの接続が終了したため、実績処理を停止しました。')
    end
    local result=executeCodeEx(0,5000,assert(api[key]),...)
    if type(result)~='number' then
      api.uncertain=true
      HV.err('Steam API call did not complete: '..key..'. Result is unknown; no automatic retry.','Steam API呼び出しが完了しませんでした: '..key..'。結果は不明です。自動再試行は行いません。')
    end
    return result
  end
  local utils=api.call('utils')
  if utils==0 or (api.call('app',utils)&amp;0xFFFFFFFF)~=3020510 then HV.err('Steam AppID does not match Heroes Vow (3020510).','Steam AppIDがHeroes Vow（3020510）と一致しません。') end
  api.instance=api.call('stats')
  if api.instance==0 then HV.err('Steam user stats are not ready.','Steam実績情報が準備できていません。') end
  return api
end

local function steamAchievementRead(api,items)
  local buf=assert(allocateMemory(16),'Steam achievement read buffer unavailable')
  local ok,result=xpcall(function()
    for _,item in ipairs(items) do
      writeBytes(buf,0xFE)
      local good=steamBool(api.call('get',api.instance,{type=3,value=item.name},buf))
      local value=readBytes(buf,1)
      if not good or (value~=0 and value~=1) then HV.err('Steam achievement data not ready: '..item.name,'Steam実績情報を読み取れません: '..item.name) end
      item.unlocked=(value==1)
    end
    return items
  end,debug.traceback)
  -- A timed-out call could still be using the buffer. Retain it until process exit.
  if not api.uncertain then deAlloc(buf) end
  if not ok then error(result,0) end
  return result
end

function HV.steamAchievementsPlan()
  local api=HV.steamAchievementsApi()
  local n=api.call('count',api.instance)&amp;0xFFFFFFFF
  if n==0 or n&gt;4096 then HV.err('Steam achievement list is empty or invalid. Wait for Steam to finish loading.','Steam実績一覧が空、または無効です。Steamの読み込み完了後に実行してください。') end
  local items,seen={},{}
  -- Steam may return thread-local strings. Copy while the calling thread still exists.
  local mem=assert(allocateMemory(4096),'Steam name-copy allocation failed')
  local buf=mem+0x200
  local asm=string.format([==[
%X:
  push rbx
  sub rsp,20
  mov rax,rcx
  mov rcx,rdx
  mov edx,r8d
  mov rbx,r9
  call rax
  test rax,rax
  je hvSteamCopyNull
  xor ecx,ecx
hvSteamCopyLoop:
  mov dl,[rax+rcx]
  mov [rbx+rcx],dl
  test dl,dl
  je hvSteamCopyDone
  inc ecx
  cmp ecx,1FF
  jb hvSteamCopyLoop
hvSteamCopyNull:
  mov byte ptr [rbx],0
  mov ecx,-1
hvSteamCopyDone:
  mov eax,ecx
  add rsp,20
  pop rbx
  ret
]==],mem)
  asm='label(hvSteamCopyNull)\nlabel(hvSteamCopyLoop)\nlabel(hvSteamCopyDone)\n'..asm
  local assembled,why=autoAssemble(asm)
  if not assembled then deAlloc(mem);error(tostring(why),0) end
  local ok,err=xpcall(function()
    for i=0,n-1 do
      if getOpenedProcessID()~=api.pid or not HV.processAlive() then api.uncertain=true;error('Game disconnected',0) end
      local len=executeCodeEx(0,5000,mem,api.name,api.instance,i,buf)
      if type(len)~='number' then api.uncertain=true;error('Steam name copy timed out; no automatic retry',0) end
      len=len&amp;0xFFFFFFFF
      local name=len&gt;0 and len&lt;512 and readString(buf,len,false)
      if not name or #name~=len or seen[name] then
        HV.err('Steam achievement name could not be copied (index '..i..').','Steam実績名を取得できません（番号 '..i..'）。')
      end
      seen[name]=true;items[#items+1]={name=name}
    end
  end,debug.traceback)
  if not api.uncertain and getOpenedProcessID()==api.pid then deAlloc(mem) end
  if not ok then error(err,0) end
  steamAchievementRead(api,items) -- Preflight every entry before changing anything.
  return api,items
end

function HV.steamUnlockAll()
  if HV.steamAchievementBusy then HV.err('Steam achievement action is already running.','Steam実績処理はすでに実行中です。') end
  HV.steamAchievementBusy=true
  local ok,result=xpcall(function()
    local api,items=HV.steamAchievementsPlan()
    local previous,updated,failed=0,0,{}
    for _,item in ipairs(items) do
      if item.unlocked then previous=previous+1
      elseif steamBool(api.call('set',api.instance,{type=3,value=item.name})) then updated=updated+1
      else failed[#failed+1]=item.name end
    end
    -- Submit once after the batch, including a retry after a previous failed submission.
    local stored=steamBool(api.call('store',api.instance))
    steamAchievementRead(api,items)
    local verified=0 for _,item in ipairs(items) do if item.unlocked then verified=verified+1 end end
    HV.msg(('Steam achievements: local %d/%d; already unlocked %d, newly accepted %d, rejected %d.'):format(verified,#items,previous,updated,#failed),
      ('Steam実績: ローカル解除 %d/%d件、解除済み %d件、新規受付 %d件、拒否 %d件。'):format(verified,#items,previous,updated,#failed))
    if not stored then HV.err('Steam rejected the save request. Local changes may be pending; retry later.','Steamへの保存要求が拒否されました。ローカル変更は未同期の可能性があります。時間を置いて再実行してください。') end
    if #failed&gt;0 or verified~=#items then HV.err('Some achievements were not unlocked; Steam sync was requested for accepted changes.','解除できなかった実績があります。受け付けられた変更についてSteam同期を要求しました。') end
    HV.msg('Steam sync requested. Server completion has not been confirmed; check your Steam achievement list.',
      'Steam同期を要求しました。サーバーでの完了は未確認です。Steamの実績一覧で確認してください。')
  end,debug.traceback)
  HV.steamAchievementBusy=false
  if not ok then error(result,0) end
end

HV.NAMES[1100]={'11. Other','11. その他'}
HV.NAMES[1101]={'Unlock all Steam achievements','Steam実績全解除'}


HV.forms={}
local function hvUiNeed(v,en,ja) if not v then HV.err(en,ja) end return v end
function HV.choose(title,rows,multiple,options)
  options=options or {}
  local state=options.state or {}; state.selected=state.selected or {}
  local original={selected={},query=state.query,quantity=state.quantity}
  for id,v in pairs(state.selected) do original.selected[id]=v end
  local selected,known={},{}
  for _,r in ipairs(rows) do
    hvUiNeed((type(r.id)=='string' or type(r.id)=='number') and not known[r.id],
      'Selection IDs must be stable and unique.','選択IDは安定した一意の値にしてください。')
    known[r.id]=true
  end
  for id,v in pairs(state.selected) do if v and (known[id] or options.allowExternal) then selected[id]=true end end
  local qty=options.quantity
  if qty then hvUiNeed(type(qty.min)=='number' and type(qty.max)=='number' and qty.min&gt;=1 and qty.max&gt;=qty.min,
    'Quantity bounds are required.','数量の最小値・最大値を指定してください。') end
  local form=createForm(false); HV.forms[form]=true;form.Name='HV_Chooser';form.Color=0x252525;form.Font.Name='Yu Gothic UI';form.Font.Size=10;form.Font.Color=0xFFFFFF
  form.Caption=title; form.Position='poScreenCenter'; form.BorderStyle='bsSizeable'
  form.ClientWidth=840; form.ClientHeight=620
  form.Constraints.MinWidth=760;form.Constraints.MinHeight=540
  local search=createEdit(form); search.Name='HV_Search'; search.Left=12; search.Top=36; search.Width=736; search.Anchors='[akTop,akLeft,akRight]'
  local checks=false
  local list=createListView(form);list.ViewStyle='vsReport';list.ReadOnly=true;list.RowSelect=true;list.HideSelection=false;list.Color=0x252525;list.Font.Color=0xFFFFFF
  local idcol=list.Columns.add();idcol.Caption=options.idCaption or 'ID';idcol.Width=140
  local namecol=list.Columns.add();namecol.Caption=HV.T('Name','名前');namecol.Width=560
  list.ShowColumnHeaders=false
  local idSearch=createEdit(form);idSearch.Name='HV_IDSearch';idSearch.Text='';idSearch.Color=0x353535;idSearch.Font.Color=0xFFFFFF
  local idSort=createButton(form);idSort.Name='HV_IDSort';idSort.Caption=idcol.Caption
  local nameSort=createButton(form);nameSort.Name='HV_NameSort';nameSort.Caption=namecol.Caption
  local clearFilter=createButton(form);clearFilter.Name='HV_ClearFilter';clearFilter.Caption=HV.T('Clear filters','検索解除')
  pcall(function() idSearch.TextHint=HV.T('Search ID','ID検索');search.TextHint=HV.T('Search name','名前検索') end)
  search.Color=0x353535;search.Font.Color=0xFFFFFF
  list.Name='HV_Selection'; list.Left=12; list.Top=72; list.Width=736; list.Height=402
  list.Anchors='[akTop,akBottom,akLeft,akRight]'; list.MultiSelect=multiple==true and not checks

  local select=createButton(form); select.Name='HV_Accept';select.Caption=HV.T('Select','選択'); select.Left=468; select.Top=574; select.Width=132
  select.Anchors='[akRight,akBottom]'; select.Default=true
  local cancel=createButton(form); cancel.Name='HV_Cancel';cancel.Caption=HV.T('Cancel','キャンセル'); cancel.Left=608; cancel.Top=574; cancel.Width=140
  cancel.Anchors='[akRight,akBottom]'; cancel.Cancel=true
  local hint=createLabel(form);hint.Left=12;hint.Top=10;hint.Width=736;hint.AutoSize=false;hint.Height=26
  hint.Caption=not multiple and HV.T('Search by name / ID','名前・IDで検索') or
    (checks and HV.T('Tick several entries; selections survive filtering.','チェックで複数選択できます。絞り込み後も選択を保持します。') or
    HV.T('Ctrl: individual / Shift: range. Selections survive filtering.','Ctrlで個別／Shiftで範囲選択。絞り込み後も選択を保持します。'))
  local status=createLabel(form);status.Name='HV_Count';status.Left=12;status.Top=480;status.Width=736;status.AutoSize=false;status.Height=26;status.Anchors='[akLeft,akRight,akBottom]'
  local quantity,quantityLabel
  if qty then
    local label=createLabel(form);quantityLabel=label;label.Left=12;label.Top=541;label.Caption=HV.T('Quantity per selected entry','選択した各項目の数量');label.Anchors='[akLeft,akBottom]'
    quantity=createEdit(form);quantity.Name='HV_Quantity';quantity.Left=240;quantity.Top=536;quantity.Width=120
    quantity.Color=0x353535;quantity.Font.Color=0xFFFFFF;quantity.Anchors='[akLeft,akBottom]';quantity.Text=tostring(state.quantity or qty.default or qty.min)
  end
  local shown,result,reason,amount={},nil,'cancel',nil
  local ordered={};for _,r in ipairs(rows) do ordered[#ordered+1]=r end
  local sortCol,ascending=1,true
  local rendering=false
  local function isSelected(i) return list.Items[i].Selected end
  local function setSelected(i,v) list.Items[i].Selected=v end
  local function count()
    local total,visible=0,0
    for _ in pairs(selected) do total=total+1 end
    for _,r in ipairs(shown) do if selected[r.id] then visible=visible+1 end end
    return total,visible
  end
  local function updateCount()
    if not multiple then status.Caption=HV.T('Shown ','表示 ')..#shown..' / '..#rows;return end
    local total,visible=count()
    status.Caption=HV.T(('Selected: %d (shown: %d / %d)'):format(total,visible,#shown),
      ('選択数: %d（表示中の選択: %d／%d）'):format(total,visible,#shown))
    select.Enabled=total&gt;0
  end
  local function saveSelection()
    if rendering then return end
    if multiple then for i,r in ipairs(shown) do selected[r.id]=isSelected(i-1) and true or nil end end
    updateCount()
  end
  local function filter()
    saveSelection(); rendering=true; list.Items.beginUpdate(); list.Items.clear(); shown={}
    local query=search.Text:lower()
    for _,r in ipairs(ordered) do
      local label=HV.T(r.en or r.name,r.ja or r.name)
      local searchable=table.concat({r.en or r.name or '',r.ja or r.name or '',r.searchText or ''},' '):lower()
      if (query=='' or searchable:find(query,1,true)) and tostring(r.displayId or r.id):lower():find(idSearch.Text:lower(),1,true) then
        shown[#shown+1]=r; local item=list.Items.add();item.Caption=tostring(r.displayId or r.id);item.SubItems.add(label)
        if multiple then setSelected(#shown-1,selected[r.id]==true) end
      end
    end
    list.Items.endUpdate();rendering=false; select.Enabled=#shown&gt;0
    if #shown&gt;0 and not multiple then list.Items[0].Selected=true end
    updateCount()
  end
  list.OnColumnClick=function(_,column)
    saveSelection();if sortCol==column.Index then ascending=not ascending else sortCol=column.Index;ascending=true end
    table.sort(ordered,function(a,b)
      local x=sortCol==0 and tostring(a.displayId or a.id) or HV.T(a.en or a.name,a.ja or a.name)
      local y=sortCol==0 and tostring(b.displayId or b.id) or HV.T(b.en or b.name,b.ja or b.name)
      if x==y then x,y=tostring(a.id),tostring(b.id) end
      return ascending and x&lt;y or (not ascending and x&gt;y)
    end);idSort.Caption=idcol.Caption..(sortCol==0 and (ascending and ' ↑' or ' ↓') or '');nameSort.Caption=namecol.Caption..(sortCol==1 and (ascending and ' ↑' or ' ↓') or '');filter()
  end
  idSort.OnClick=function()list.OnColumnClick(list,idcol)end
  nameSort.OnClick=function()list.OnColumnClick(list,namecol)end
  list.OnCustomDrawItem=function(sender,item)
    local rect=item.displayRect('drBounds');local canvas=sender.Canvas
    canvas.Font.Color=0xFFFFFF;canvas.Brush.Color=item.Selected and 0x805020 or 0x252525
    canvas.fillRect(rect.Left,rect.Top,sender.Width,rect.Bottom)
    local x=rect.Left
    for i,col in ipairs({idcol,namecol}) do
      local text=i==1 and item.Caption or item.SubItems[0]
      canvas.textRect({Left=x+6,Top=rect.Top,Right=x+col.Width-6,Bottom=rect.Bottom},x+6,rect.Top+2,text)
      x=x+col.Width
    end
    return false
  end
  local function draft()
    state.selected={};for id,v in pairs(selected) do state.selected[id]=v end
    state.query=search.Text
    if quantity then state.quantity=quantity.Text end
  end
  local function finish()
    saveSelection()
    if qty then
      local v=tonumber(quantity.Text)
      if not v or v%1~=0 or v&lt;qty.min or v&gt;qty.max then
        status.Caption=HV.T(('Enter an integer from %d to %d.'):format(qty.min,qty.max),
          ('数量は%d～%dの整数で指定してください。'):format(qty.min,qty.max));return
      end
      amount=v
    end
    if multiple then
      if count()==0 then return end
      result={}; for _,r in ipairs(rows) do if selected[r.id] then result[#result+1]=r end end
    else result=list.Selected and shown[list.Selected.Index+1]; if not result then return end end
    draft();if amount then state.quantity=amount end;reason='ok'
    form.ModalResult=1
  end
  if multiple then
    local function button(name,en,ja,left,width,fn)
      local b=createButton(form);b.Name=name;b.Caption=HV.T(en,ja);b.Left=left;b.Top=504;b.Width=width
      b.Anchors='[akLeft,akBottom]';b.OnClick=fn
    end
    button('HV_SelectShown','Select all shown','表示中を全選択',12,220,function()
      saveSelection();for i,r in ipairs(shown) do selected[r.id]=true;setSelected(i-1,true) end;updateCount()
    end)
    button('HV_ClearShown','Clear shown','表示中を解除',240,180,function()
      saveSelection();for i,r in ipairs(shown) do selected[r.id]=nil;setSelected(i-1,false) end;updateCount()
    end)
    button('HV_ClearAll','Clear ALL selections','全選択を解除',428,220,function()
      selected={};for i in ipairs(shown) do setSelected(i-1,false) end;updateCount()
    end)
    list.OnClick=saveSelection;list.OnKeyUp=saveSelection
    if checks then list.OnClickCheck=saveSelection end
  end
  if options.back then
    local back=createButton(form);back.Name='HV_Back';back.Caption=HV.T('Back','戻る');back.Left=12;back.Top=574;back.Width=132
    back.Anchors='[akLeft,akBottom]';back.OnClick=function() saveSelection();draft();reason='back';form.ModalResult=3 end
  end
  search.OnChange=filter;idSearch.OnChange=filter; select.OnClick=finish
  clearFilter.OnClick=function()search.Text='';idSearch.Text='';filter()end
  local function layout()
    local w,h=form.ClientWidth,form.ClientHeight
    hint.Left=14;hint.Top=12;hint.Width=w-28;hint.Height=30
    idSearch.Left=14;idSearch.Top=54;idSearch.Width=134;idSearch.Height=28
    search.Left=154;search.Top=54;search.Width=w-182;search.Height=28
    idSort.Left=14;idSort.Top=91;idSort.Width=140;idSort.Height=30
    nameSort.Left=154;nameSort.Top=91;nameSort.Width=w-182;nameSort.Height=30
    idcol.Width=140;namecol.Width=w-188
    list.Left=14;list.Top=122;list.Width=w-28
    local extra=(multiple and 42 or 0)+(qty and 42 or 0)+(options.back and 38 or 0)
    list.Height=h-186-extra
    local y=list.Top+list.Height+6
    if multiple then
      for i,key in ipairs({'HV_SelectShown','HV_ClearShown','HV_ClearAll'}) do local button=form.findComponentByName(key);button.Left=14+(i-1)*230;button.Top=y;button.Width=220;button.Height=33 end
      y=y+42
    end
    if qty then quantityLabel.Left=16;quantityLabel.Top=y+4;quantityLabel.Height=28;quantity.Left=300;quantity.Top=y;quantity.Width=140;quantity.Height=28;y=y+42 end
    if options.back then local back=form.findComponentByName('HV_Back');back.Left=14;back.Top=y;back.Width=118;back.Height=33 end
    status.Left=16;status.Top=h-43;status.Width=240;status.Height=28
    clearFilter.Left=266;clearFilter.Top=h-49;clearFilter.Width=110;clearFilter.Height=33
    select.Left=w-266;select.Top=h-49;select.Width=118;select.Height=33
    cancel.Left=w-136;cancel.Top=h-49;cancel.Width=118;cancel.Height=33
  end
  form.OnResize=layout;layout()
  cancel.OnClick=function() reason='cancel';form.ModalResult=2 end
  if not multiple then list.OnDblClick=finish end
  search.Text=state.query or ''
  local ok,err=pcall(function() filter();if form.showModal()~=1 then result=nil end end)
  HV.forms[form]=nil; form.destroy()
  if reason=='cancel' or not ok then
    state.selected=original.selected;state.query=original.query;state.quantity=original.quantity
  end
  if not ok then error(err,0) end
  return result,{reason=reason,quantity=amount,state=state}
end
-- Multi-category item/person chooser. Stable IDs must be unique across categories.
-- Keeps selection and quantity across Back; Cancel discards the whole draft.
-- Pure selection: caller revalidates game/object identity before applying any result.

function HV.numberInput(title,label,default)
  local form=createForm(false);HV.forms[form]=true
  form.Name='HV_NumberInput';form.Caption=title;form.Position='poScreenCenter';form.ClientWidth=600;form.ClientHeight=210
  form.Font.Name='Yu Gothic UI';form.Font.Size=10;form.Color=0x252525;form.Font.Color=0xFFFFFF
  local caption=createLabel(form);caption.Left=16;caption.Top=20;caption.Caption=label
  local edit=createEdit(form);edit.Name='HV_Number';edit.Left=16;edit.Top=60;edit.Width=568;edit.Color=0x353535;edit.Font.Color=0xFFFFFF;edit.Text=tostring(default)
  local status=createLabel(form);status.Left=16;status.Top=104;status.Caption=''
  local apply=createButton(form);apply.Name='HV_NumberAccept';apply.Caption=HV.T('Apply','適用');apply.Left=334;apply.Top=161;apply.Width=118;apply.Height=33;apply.Default=true
  local cancel=createButton(form);cancel.Name='HV_NumberCancel';cancel.Caption=HV.T('Cancel','キャンセル');cancel.Left=464;cancel.Top=161;cancel.Width=118;cancel.Height=33;cancel.Cancel=true
  local result
  apply.OnClick=function()local n=tonumber(edit.Text);if not n or n%1~=0 or n&lt;1 or n&gt;1000000 then status.Caption=HV.T('Enter an integer from 1 to 1000000.','1～1000000の整数を入力してください。');return end;result=tostring(n);form.ModalResult=1 end
  cancel.OnClick=function()form.ModalResult=2 end
  local ok,e=pcall(function()if form.showModal()~=1 then result=nil end end)
  HV.forms[form]=nil;form.destroy();if not ok then error(e,0)end;return result
end

function HV.chooseBatch(title,categories,options)
  options=options or {}
  local state={selected={},query='',quantity=options.quantity and options.quantity.default}
  local categoryRows,allRows,known={},{},{}
  local states={}
  for _,c in ipairs(categories) do
    hvUiNeed(c.id~=nil and not states[c.id],'Duplicate category ID.','カテゴリIDが重複しています。')
    states[c.id]={query=''}
    categoryRows[#categoryRows+1]={id=c.id,en=c.en,ja=c.ja,category=c}
    for _,r in ipairs(c.rows) do
      hvUiNeed(r.id~=nil and not known[r.id],'Batch IDs must be unique across categories.','カテゴリ間でも一意の対象IDが必要です。')
      known[r.id]=true;allRows[#allRows+1]=r
    end
  end
  while true do
    local category=HV.choose(title,categoryRows,false)
    if not category then return nil,{reason='cancel'} end
    local localState=states[category.id];localState.selected=state.selected;localState.quantity=state.quantity
    local _,meta=HV.choose(title..' / '..HV.T(category.en,category.ja),category.category.rows,true,
      {back=true,state=localState,allowExternal=true,checks=options.checks,quantity=options.quantity})
    if meta.reason=='cancel' then return nil,{reason='cancel'} end
    state.selected=localState.selected;state.quantity=localState.quantity
    if meta.reason=='ok' then
      local result={};for _,r in ipairs(allRows) do if state.selected[r.id] then result[#result+1]=r end end
      return result,{reason='ok',quantity=meta.quantity}
    end
  end
end

-- Category layout and labels follow GameTemplate V3 / WP10_2026.
HV.NAMES[12031]={"War","戦争"}
HV.NAMES[12021]={"Hero actions &amp; relationships","武将操作・関係"}
HV.NAMES[12032]={"City troops / private troops","都市保有部隊・私兵"}
HV.NAMES[12051]={"Select city by name","都市を名前で選択"}
HV.NAMES[100]={"01. Gameplay","01. 便利機能"}
HV.NAMES[7000]={"02. Player, heroes &amp; pets","02. プレイヤー・武将・ペット"}
HV.NAMES[400]={"03. Battles, war &amp; troops","03. 戦闘・戦争・部隊"}
HV.NAMES[800]={"04. Items","04. アイテム"}
HV.NAMES[500]={"05. Cities &amp; domestic affairs","05. 都市・内政"}
HV.NAMES[600]={"06. Technology, research &amp; policies","06. 技術・研究政策"}
HV.NAMES[1100]={"07. Other","07. その他"}
HV.NAMES[7001]={"Player editor","プレイヤーエディタ"}
HV.NAMES[7110]={"Hero editor (select a hero)","武将エディタ（対象選択）"}
HV.NAMES[900]={"Pets","保有ペット"}
HV.NAMES[1000]={"Accompanying troops","同行部隊"}
HV.NAMES[200]={"Duel &amp; cockfight","決闘・闘鶏"}
HV.NAMES[300]={"Debate","討論"}
HV.NAMES[803]={"Add items (category / Ctrl+Shift selection / quantity)","アイテム追加（カテゴリ・Ctrl/Shift複数選択・個数）"}
HV.NAMES[806]={"Player item quantities (enable to edit)","プレイヤーのアイテム個数変更（チェックで編集）"}

-- Read-only list snapshots; records navigate to the existing CT editors.

function HV.syncHeroFamily(force)
  local st=HV.st('OFFA');local list=st and HV.rq(st+0x430)
  if not force and HV.familyHero==HV.selHero and HV.familyList==list then return end
  HV.familyHero=HV.selHero;HV.familyList=list;HV.selFamily=nil
  local id=HV.selHero and HV.utf16(HV.rq(HV.selHero+0x30))
  if id then HV.listEach(list,function(g)
    local found=false;HV.listEach(HV.rq(g+0x30),function(v)if HV.utf16(v)==id then found=true;return false end end)
    if found then HV.selFamily=g;return false end
  end)end
  local record=getAddressList().getMemoryRecordByID(14100)
  if HV.selFamily then
    HV.NAMES[14100]={'Family (shared family parameters)','所属家族（家族共通のパラメーター）'}
    HV.suffix[14100]=HV.ml(HV.rq(HV.selFamily+0x18))
    if record then record.Options='[moManualExpandCollapse]' end
  else
    HV.NAMES[14100]={'Family (none)','所属家族（なし）'};HV.suffix[14100]=nil
    if record then record.Collapsed=true;record.Options='[moManualExpandCollapse,moHideChildren]' end
  end
  if record then record.Description=HV.T(HV.NAMES[14100][1],HV.NAMES[14100][2])..(HV.suffix[14100] and ' : '..HV.suffix[14100] or '') end
end

-- Population rules transcribed from UI_TotalInfoUI in the installed build.
-- Read-only: no UI/game methods are invoked to construct these snapshots.
function HV.listHeroAge(h)
  local function int(a)return readInteger(a,true)end
  local function trunc(n)return n&lt;0 and math.ceil(n) or math.floor(n)end
  if readBytes(h+0x2BC,1)~=0 then return trunc(assert(int(h+0x214))/360)end
  if assert(int(h+0x8C))&gt;1 then return int(h+0x84)end
  local st=assert(HV.st('OFFA'));local year=assert(int(st+0x138))+trunc(assert(int(st+0x13C))/360)
  local age=year-assert(int(h+0x78))
  if age&lt;16 then
    local cfg=HV.rq(st+0x18);cfg=cfg and HV.rq(cfg+0x10)
    local story=HV.rq(h+0x120)
    if cfg and int(cfg+0x6C)==1 and story and int(story+0x30)==2 then age=16 end
  end
  return age
end
function HV.entityRows(kind)
  HV.init()
  local st=assert(HV.st('OFFA'));local og=assert(HV.st('OGEN'));local rows={};local heroes={}
  HV.dictEach(HV.rq(og+8),function(k,h)heroes[HV.utf16(k) or '']=h end)
  local player=HV.playerHero();local story=player and HV.rq(player+0x120)
  local own=story and HV.utf16(HV.rq(story+0x18))
  -- These three game menu entries are disabled when the player has no power.
  if (kind=='ownHeroes' or kind=='ownCities' or kind=='ownFamilies') and (not own or own=='') then return rows end
  local function powerOf(h)local s=h and HV.rq(h+0x120);return s and HV.utf16(HV.rq(s+0x18))end
  local function status(h)local s=h and HV.rq(h+0x120);return s and readInteger(s+0x30,true)end
  local function heroRow(h)
    if h then rows[#rows+1]={id=h,displayId=HV.utf16(HV.rq(h+0x30)),name=HV.heroName(h),searchText=HV.heroName(h,true),entity='hero'}end
  end
  if kind=='heroes' or kind=='ownHeroes' then
    HV.listEach(HV.rq(og),function(h)
      if status(h)==2 and (readBytes(h+0x2BC,1)==0 or HV.listHeroAge(h)&gt;=16)
        and (kind=='heroes' or powerOf(h)==own)then heroRow(h)end
    end)
    -- The game's common helper appends children aged 0..15 of own-power officers.
    if own and own~='' then
      local seen={}
      HV.listEach(HV.rq(og),function(h)
        if status(h)==2 and powerOf(h)==own then
          local d=HV.rq(h+0x110);local entries=d and HV.rq(d+0x18);local count=d and readInteger(d+0x20) or 0
          local function addChild(k)
            local child=heroes[HV.utf16(k) or '']
            if child and not seen[child] and status(child)==0 then
              local age=HV.listHeroAge(child)
              if age&gt;=0 and age&lt;=15 then heroRow(child);seen[child]=true end
            end
          end
          if entries and count&gt;=0 and count&lt;=200000 then
            for i=0,count-1 do local e=entries+0x20+i*0x18;local hash=readInteger(e,true)
              if hash and hash&gt;=0 then addChild(HV.rq(e+8))end
            end
          end
        end
      end)
      -- The same helper also appends the player's children below age 16.
      HV.listEach(HV.rq(st+0x48),function(h)if HV.listHeroAge(h)&lt;16 then heroRow(h)end end)
    end
  elseif kind=='familyHeroes' then
    HV.listEach(HV.rq(st+0x38),function(v)heroRow(heroes[HV.utf16(v) or ''])end)
  elseif kind=='cities' or kind=='ownCities' then
    local fm=HV.st('FMAF');local seq=0
    HV.listEach(fm and HV.rq(fm+0x58),function(c)
      seq=seq+1;local gov=HV.rq(c+0xD8);local owner=gov and HV.utf16(HV.rq(gov+0x10))
      if kind=='cities' or owner==own then
        rows[#rows+1]={id=c,displayId=seq,name=HV.ml(HV.rq(c+0x10)),searchText=HV.ml(HV.rq(c+0x10),true),entity='city'}
      end
    end)
  elseif kind=='powers' then
    HV.dictEach(HV.rq(st+0x20),function(k,p)
      local id=HV.utf16(k) or '';local name=heroes[id] and HV.heroName(heroes[id]) or id
      rows[#rows+1]={id=p,displayId=id,name=name,entity='power'}
    end)
  elseif kind=='families' or kind=='ownFamilies' then
    HV.listEach(HV.rq(st+0x430),function(g)
      local first;local hasPlayer=false
      HV.listEach(HV.rq(g+0x30),function(v)
        local id=HV.utf16(v);local h=heroes[id or '']
        if id==HV.utf16(HV.rq(st+0x28))then hasPlayer=true end
        if not first and h and status(h)==2 and HV.listHeroAge(h)&gt;0 then first=h end
      end)
      if not first and hasPlayer then HV.listEach(HV.rq(st+0x38),function(v)first=heroes[HV.utf16(v) or ''];return not first end)end
      if kind=='families' or (first and powerOf(first)==own)then
        rows[#rows+1]={id=g,displayId=HV.utf16(HV.rq(g+0x10)) or '',name=HV.ml(HV.rq(g+0x18)),searchText=HV.ml(HV.rq(g+0x18),true),entity='family'}
      end
    end)
  elseif kind=='familyMembers' then
    if HV.selFamily then HV.listEach(HV.rq(HV.selFamily+0x30),function(v)heroRow(heroes[HV.utf16(v) or ''])end)end
  else error('Unknown entity list: '..tostring(kind))end
  return rows
end

function HV.jumpToEntity(row)
  local target
  if row.entity=='hero' then HV.selHero=row.id;target=7110
  elseif row.entity=='city' then HV.selCity=row.id;target=500
  elseif row.entity=='power' then HV.selPower=row.id;target=14000
  elseif row.entity=='family' then
    local lookup={};for _,h in ipairs(HV.entityRows('heroes'))do lookup[h.displayId]=h end
    local members={};HV.listEach(HV.rq(row.id+0x30),function(v)local h=lookup[HV.utf16(v) or ''];if h then members[#members+1]=h end end)
    local member=HV.choose(HV.T('Select family member: ','構成武将を選択: ')..row.name,members,false)
    if not member then return end
    local valid=false;HV.listEach(HV.rq(row.id+0x30),function(v)if HV.utf16(v)==member.displayId then valid=true;return false end end)
    if not HV.processAlive() or not valid then HV.err('Family changed. Reopen the list.','家族の状態が変わりました。一覧を開き直してください。')end
    HV.selHero=member.id;target=7110
  else error('Invalid editor target')end
  HV.updatePtrs();HV.refreshSuffix()
  local record=assert(getAddressList().getMemoryRecordByID(target))
  local parent=record.Parent;while parent do parent.Collapsed=false;parent=parent.Parent end
  record.Collapsed=false;if row.entity=='family' then getAddressList().getMemoryRecordByID(14100).Collapsed=false end;getAddressList().SelectedRecord=record
  pcall(function()local node=getAddressList().Control[0].Selected;if node then node.makeVisible()end end)
  getMainForm().show();getMainForm().bringToFront()
end
-- Parameter-list UI adapted from the user's WP10_2026.CT Lists implementation.
do
  local api=HV
  local str=function(v)return v==nil and '—' or tostring(v)end
  local text=function(v)return v==nil and '' or tostring(v)end
  local Picker={}
  local Lists={windows={},schemas={["hero"]={{["id"]=7133,["slot"]=80,["offset"]=32,["float"]=false,["group"]=7132},{["id"]=7134,["slot"]=80,["offset"]=36,["float"]=false,["group"]=7132},{["id"]=7135,["slot"]=80,["offset"]=40,["float"]=false,["group"]=7132},{["id"]=7136,["slot"]=80,["offset"]=44,["float"]=false,["group"]=7132},{["id"]=7137,["slot"]=80,["offset"]=48,["float"]=false,["group"]=7132},{["id"]=7138,["slot"]=80,["offset"]=52,["float"]=false,["group"]=7132},{["id"]=7120,["slot"]=64,["offset"]=132,["float"]=false,["group"]=7118},{["id"]=7119,["slot"]=64,["offset"]=776,["float"]=false,["group"]=7118},{["id"]=7121,["slot"]=64,["offset"]=128,["float"]=false,["group"]=7118},{["id"]=7122,["slot"]=64,["offset"]=120,["float"]=false,["group"]=7118},{["id"]=7123,["slot"]=64,["offset"]=104,["float"]=false,["group"]=7118},{["id"]=7124,["slot"]=72,["offset"]=244,["float"]=false,["group"]=7118},{["id"]=7126,["slot"]=64,["offset"]=416,["float"]=false,["group"]=7125},{["id"]=7127,["slot"]=64,["offset"]=420,["float"]=false,["group"]=7125},{["id"]=7128,["slot"]=64,["offset"]=412,["float"]=false,["group"]=7125},{["id"]=7129,["slot"]=64,["offset"]=404,["float"]=false,["group"]=7125},{["id"]=7130,["slot"]=64,["offset"]=408,["float"]=false,["group"]=7125},{["id"]=7140,["slot"]=88,["offset"]=32,["float"]=false,["group"]=7139},{["id"]=7141,["slot"]=88,["offset"]=36,["float"]=false,["group"]=7139},{["id"]=7142,["slot"]=88,["offset"]=40,["float"]=false,["group"]=7139},{["id"]=7143,["slot"]=88,["offset"]=44,["float"]=false,["group"]=7139},{["id"]=7144,["slot"]=88,["offset"]=48,["float"]=false,["group"]=7139},{["id"]=7145,["slot"]=88,["offset"]=52,["float"]=false,["group"]=7139},{["id"]=7147,["slot"]=96,["offset"]=32,["float"]=false,["group"]=7146},{["id"]=7148,["slot"]=96,["offset"]=36,["float"]=false,["group"]=7146},{["id"]=7149,["slot"]=96,["offset"]=40,["float"]=false,["group"]=7146},{["id"]=7150,["slot"]=96,["offset"]=44,["float"]=false,["group"]=7146},{["id"]=7151,["slot"]=96,["offset"]=48,["float"]=false,["group"]=7146},{["id"]=7152,["slot"]=96,["offset"]=52,["float"]=false,["group"]=7146},{["id"]=7155,["slot"]=104,["offset"]=32,["float"]=false,["group"]=7154},{["id"]=7156,["slot"]=112,["offset"]=32,["float"]=false,["group"]=7154},{["id"]=7157,["slot"]=104,["offset"]=36,["float"]=false,["group"]=7154},{["id"]=7158,["slot"]=112,["offset"]=36,["float"]=false,["group"]=7154},{["id"]=7159,["slot"]=104,["offset"]=40,["float"]=false,["group"]=7154},{["id"]=7160,["slot"]=112,["offset"]=40,["float"]=false,["group"]=7154},{["id"]=7161,["slot"]=104,["offset"]=44,["float"]=false,["group"]=7154},{["id"]=7162,["slot"]=112,["offset"]=44,["float"]=false,["group"]=7154},{["id"]=7163,["slot"]=104,["offset"]=48,["float"]=false,["group"]=7154},{["id"]=7164,["slot"]=112,["offset"]=48,["float"]=false,["group"]=7154},{["id"]=7165,["slot"]=104,["offset"]=52,["float"]=false,["group"]=7154},{["id"]=7166,["slot"]=112,["offset"]=52,["float"]=false,["group"]=7154},{["id"]=7167,["slot"]=104,["offset"]=56,["float"]=false,["group"]=7154},{["id"]=7168,["slot"]=112,["offset"]=56,["float"]=false,["group"]=7154},{["id"]=7170,["slot"]=104,["offset"]=60,["float"]=false,["group"]=7169},{["id"]=7171,["slot"]=112,["offset"]=60,["float"]=false,["group"]=7169},{["id"]=7172,["slot"]=104,["offset"]=64,["float"]=false,["group"]=7169},{["id"]=7173,["slot"]=112,["offset"]=64,["float"]=false,["group"]=7169},{["id"]=7174,["slot"]=104,["offset"]=68,["float"]=false,["group"]=7169},{["id"]=7175,["slot"]=112,["offset"]=68,["float"]=false,["group"]=7169},{["id"]=7176,["slot"]=104,["offset"]=72,["float"]=false,["group"]=7169},{["id"]=7177,["slot"]=112,["offset"]=72,["float"]=false,["group"]=7169},{["id"]=7178,["slot"]=104,["offset"]=76,["float"]=false,["group"]=7169},{["id"]=7179,["slot"]=112,["offset"]=76,["float"]=false,["group"]=7169},{["id"]=7180,["slot"]=104,["offset"]=80,["float"]=false,["group"]=7169},{["id"]=7181,["slot"]=112,["offset"]=80,["float"]=false,["group"]=7169},{["id"]=7182,["slot"]=104,["offset"]=84,["float"]=false,["group"]=7169},{["id"]=7183,["slot"]=112,["offset"]=84,["float"]=false,["group"]=7169},{["id"]=7184,["slot"]=104,["offset"]=88,["float"]=false,["group"]=7169},{["id"]=7185,["slot"]=112,["offset"]=88,["float"]=false,["group"]=7169},{["id"]=7187,["slot"]=104,["offset"]=92,["float"]=false,["group"]=7186},{["id"]=7188,["slot"]=112,["offset"]=92,["float"]=false,["group"]=7186},{["id"]=7189,["slot"]=104,["offset"]=96,["float"]=false,["group"]=7186},{["id"]=7190,["slot"]=112,["offset"]=96,["float"]=false,["group"]=7186},{["id"]=7191,["slot"]=104,["offset"]=100,["float"]=false,["group"]=7186},{["id"]=7192,["slot"]=112,["offset"]=100,["float"]=false,["group"]=7186},{["id"]=7193,["slot"]=104,["offset"]=104,["float"]=false,["group"]=7186},{["id"]=7194,["slot"]=112,["offset"]=104,["float"]=false,["group"]=7186},{["id"]=7195,["slot"]=104,["offset"]=108,["float"]=false,["group"]=7186},{["id"]=7196,["slot"]=112,["offset"]=108,["float"]=false,["group"]=7186},{["id"]=7197,["slot"]=104,["offset"]=112,["float"]=false,["group"]=7186},{["id"]=7198,["slot"]=112,["offset"]=112,["float"]=false,["group"]=7186},{["id"]=7199,["slot"]=104,["offset"]=116,["float"]=false,["group"]=7186},{["id"]=7200,["slot"]=112,["offset"]=116,["float"]=false,["group"]=7186},{["id"]=7201,["slot"]=104,["offset"]=120,["float"]=false,["group"]=7186},{["id"]=7202,["slot"]=112,["offset"]=120,["float"]=false,["group"]=7186},{["id"]=7203,["slot"]=104,["offset"]=124,["float"]=false,["group"]=7186},{["id"]=7204,["slot"]=112,["offset"]=124,["float"]=false,["group"]=7186},{["id"]=7206,["slot"]=120,["offset"]=32,["float"]=false,["group"]=7205},{["id"]=7207,["slot"]=120,["offset"]=36,["float"]=false,["group"]=7205},{["id"]=7208,["slot"]=120,["offset"]=40,["float"]=false,["group"]=7205},{["id"]=7210,["slot"]=72,["offset"]=232,["float"]=false,["group"]=7209},{["id"]=7211,["slot"]=72,["offset"]=240,["float"]=false,["group"]=7209},{["id"]=7212,["slot"]=72,["offset"]=248,["float"]=false,["group"]=7209},{["id"]=7213,["slot"]=72,["offset"]=252,["float"]=true,["group"]=7209},{["id"]=7214,["slot"]=64,["offset"]=400,["float"]=true,["group"]=7209},{["id"]=7216,["slot"]=64,["offset"]=392,["float"]=false,["group"]=7215},{["id"]=7217,["slot"]=64,["offset"]=396,["float"]=false,["group"]=7215},{["id"]=7219,["slot"]=64,["offset"]=476,["float"]=false,["group"]=7218},{["id"]=7220,["slot"]=64,["offset"]=480,["float"]=false,["group"]=7218},{["id"]=7221,["slot"]=64,["offset"]=484,["float"]=false,["group"]=7218},{["id"]=7222,["slot"]=64,["offset"]=488,["float"]=false,["group"]=7218},{["id"]=7223,["slot"]=64,["offset"]=492,["float"]=false,["group"]=7218},{["id"]=7224,["slot"]=64,["offset"]=496,["float"]=false,["group"]=7218},{["id"]=7226,["slot"]=64,["offset"]=664,["float"]=false,["group"]=7225},{["id"]=7227,["slot"]=64,["offset"]=668,["float"]=false,["group"]=7225},{["id"]=7228,["slot"]=64,["offset"]=672,["float"]=false,["group"]=7225},{["id"]=7229,["slot"]=64,["offset"]=676,["float"]=false,["group"]=7225},{["id"]=7230,["slot"]=64,["offset"]=680,["float"]=false,["group"]=7225},{["id"]=7231,["slot"]=64,["offset"]=684,["float"]=false,["group"]=7225},{["id"]=7233,["slot"]=64,["offset"]=696,["float"]=false,["group"]=7232}},["city"]={{["id"]=506,["slot"]=136,["offset"]=40,["float"]=false,["group"]=505},{["id"]=507,["slot"]=136,["offset"]=44,["float"]=false,["group"]=505},{["id"]=508,["slot"]=136,["offset"]=48,["float"]=false,["group"]=505},{["id"]=509,["slot"]=136,["offset"]=52,["float"]=true,["group"]=505},{["id"]=511,["slot"]=152,["offset"]=0,["float"]=true,["group"]=510},{["id"]=517,["slot"]=128,["offset"]=120,["float"]=false,["group"]=516},{["id"]=518,["slot"]=128,["offset"]=128,["float"]=false,["group"]=516},{["id"]=519,["slot"]=128,["offset"]=764,["float"]=false,["group"]=516}},["power"]={{["id"]=14001,["slot"]=208,["offset"]=264,["float"]=false,["group"]=14000},{["id"]=14002,["slot"]=208,["offset"]=160,["float"]=false,["group"]=14000},{["id"]=14003,["slot"]=208,["offset"]=164,["float"]=false,["group"]=14000}},["family"]={{["id"]=14101,["slot"]=216,["offset"]=40,["float"]=false,["group"]=14100},{["id"]=14102,["slot"]=216,["offset"]=44,["float"]=false,["group"]=14100},{["id"]=14103,["slot"]=216,["offset"]=64,["float"]=false,["group"]=14100},{["id"]=14104,["slot"]=216,["offset"]=68,["float"]=false,["group"]=14100},{["id"]=14105,["slot"]=216,["offset"]=72,["float"]=false,["group"]=14100}}}}
  HV.ParameterLists=Lists
  local kinds={heroes='hero',ownHeroes='hero',familyHeroes='hero',cities='city',ownCities='city',powers='power',families='family',ownFamilies='family',familyMembers='hero'}
  local titles={heroes=13001,ownHeroes=13002,familyHeroes=13003,cities=13004,ownCities=13005,powers=13006,families=13007,ownFamilies=13008,familyMembers=14106}
  function Lists.title(key)local n=api.NAMES[titles[key]];return api.T(n[1],n[2])end
  function Lists.snapshot(fn)assert(api.processAlive(),'Game is not running');return fn()end
  function Lists.columns(key)
    local cols={{key='displayId',title='ID',width=100},{key='name',title=api.T('Name','名前'),width=210}}
    for _,f in ipairs(assert(Lists.schemas[kinds[key]]))do
      local n=assert(api.NAMES[f.id]);local label=api.T(n[1],n[2])
      if f.slot==0x58 or f.slot==0x60 then local g=api.NAMES[f.group];if g then label=api.T(g[1],g[2])..': '..label end end
      cols[#cols+1]={key='f'..f.id,title=label,width=math.max(125,math.min(260,#label*7)),numeric=true,field=f}
    end
    return cols
  end
  function Lists.readRow(s,source)
    assert(not s.closed,'List closed')
    local h=source.id;local rq=api.rq;local ctx={}
    if source.entity=='hero' then
      local story=rq(h+0x120)
      ctx[0x40]=h;ctx[0x48]=story;ctx[0x50]=story and rq(story+0x48);ctx[0x58]=rq(h+0x160)
      ctx[0x60]=rq(h+0x50);ctx[0x68]=story and rq(story+0x70);ctx[0x70]=rq(h+0x168);ctx[0x78]=story and rq(story+0x50)
    elseif source.entity=='city' then
      ctx[0x80]=h;ctx[0x88]=rq(h+0xD8)
      local gv=ctx[0x88];if gv then ctx[0x98]=api.feelEntry(gv,api.utf16(rq(gv+0x10)))end
    elseif source.entity=='power' then ctx[0xD0]=h
    elseif source.entity=='family' then ctx[0xD8]=h end
    local row={id=h,displayId=source.displayId,name=source.name,source=source,display={displayId=str(source.displayId),name=source.name}}
    for _,col in ipairs(s.columns)do
      local f=col.field
      if f then
        local base=ctx[f.slot];local value
        if f.id==7120 then value=api.listHeroAge(h)
        elseif base then value=f.float and readFloat(base+f.offset) or readInteger(base+f.offset,true)end
        row[col.key]=value;row.display[col.key]=str(value)
      end
    end
    local right={};for i=4,#s.columns do right[#right+1]=row.display[s.columns[i].key]:gsub('[\r\n]',' ')end
    row.rightText=table.concat(right,'\n')
    return row
  end
    function Picker.matches(value, query, numeric)
      query = text(query):match('^%s*(.-)%s*$')
      if query == '' then
        return true
      end
      if numeric then
        local n = tonumber(value)
        if not n then
          return false
        end
        local lo, hi = query:match('^(%d+)%s*%-%s*(%d+)$')
        if lo then
          return n &gt;= tonumber(lo) and n &lt;= tonumber(hi)
        end
        local op, rhs = query:match('^([&lt;&gt;!=]+)%s*(%d+)$')
        rhs = tonumber(rhs)
        if rhs then
          if op == '&gt;=' then
            return n &gt;= rhs
          elseif op == '&lt;=' then
            return n &lt;= rhs
          elseif op == '&gt;' then
            return n &gt; rhs
          elseif op == '&lt;' then
            return n &lt; rhs
          elseif op == '=' or op == '==' then
            return n == rhs
          elseif op == '!=' then
            return n ~= rhs
          end
        end
        local exact = tonumber(query)
        if exact then
          return n == exact
        end
      end
      return text(value):lower():find(query:lower(), 1, true) ~= nil
    end
    function Picker.view(rows, columns, queries, sortIndex, ascending)
      local shown = {}
      for _, row in ipairs(rows) do
        local include = true
        for i, col in ipairs(columns) do
          if not Picker.matches(row[col.key], queries[i], col.numeric) then
            include = false
            break
          end
        end
        if include then
          shown[#shown + 1] = row
        end
      end
      local col = columns[sortIndex]
      table.sort(shown, function(a, b)
        local x, y = a[col.key], b[col.key]
        if x == nil or y == nil then
          if x ~= y then
            return y == nil
          end
        else
          if not col.numeric then
            x = text(x):lower()
            y = text(y):lower()
          end
          if x ~= y then
            if ascending then
              return x &lt; y
            else
              return x &gt; y
            end
          end
        end
        return a.id &lt; b.id
      end)
      return shown
    end
    function Lists.view(s)
      local rows = {}
      for _, row in ipairs(s.rows) do
        local include = true
        for key, query in pairs(s.queries) do
          if query ~= '' then
            if key == '*' then
              local found = false
              for _, col in ipairs(s.columns) do
                if Picker.matches(row.display[col.key], query, false) then
                  found = true
                  break
                end
              end
              if not found then
                include = false
                break
              end
            else
              local col = s.byKey[key]
              local numeric = col.numeric
                and (tonumber(query) ~= nil or query:match('^[&lt;&gt;!=]') or query:match('^%d+%s*%-%s*%d+$'))
              if not Picker.matches(numeric and row[key] or row.display[key], query, numeric) then
                include = false
                break
              end
            end
          end
        end
        if include then
          rows[#rows + 1] = row
        end
      end
      return Picker.view(rows, s.columns, {}, s.sortIndex, s.ascending)
    end
    function Lists.create(key)
      local s = {
        key = key,
        lang = api.lang,
        columns = Lists.columns(key),
        byKey = {},
        rows = {},
        shown = {},
        queries = {},
        sortIndex = 2,
        ascending = true,
        names = {},
        choiceMaps = {},
        closed = false,
        pid = api.pid,
        busy = false,
        position = 1,
        errors = 0,
      }
      local form = createForm(false)
      s.form = form
      form.Name = 'HV_ParameterList_' .. key
      form.Caption = Lists.title(key)
        .. api.T(' — parameter list', ' — パラメーター一覧')
      form.Position = 'poScreenCenter'
      form.BorderStyle = 'bsSizeable'
      form.ClientWidth = 1500
      form.ClientHeight = 820
      form.Color = 0x252525
      form.Font.Name = 'Yu Gothic UI'
      form.Font.Size = 10
      form.Font.Color = 0xffffff
      pcall(function()
        form.Constraints.MinWidth = 900
        form.Constraints.MinHeight = 450
      end)
      local layout
      local field = createComboBox(form)
      s.field = field
      field.Style = 'csDropDownList'
      field.Items.add(api.T('All columns', 'すべての列'))
      local search = createEdit(form)
      s.search = search
      search.Color = 0x353535
      search.Font.Color = 0xffffff
      search.Text = ''
      local clear = createButton(form)
      s.clear = clear
      clear.Caption = api.T('Clear filters', '検索解除')
      local refresh = createButton(form)
      s.refresh = refresh
      refresh.Caption = api.T('Refresh', '更新')
      local close = createButton(form)
      s.close = close
      close.Caption = api.T('Close', '閉じる')
      close.Cancel = true
      local status = createLabel(form)
      s.status = status
      status.Font.Color = 0xffffff
      local list = createListView(form)
      s.list = list
      list.ViewStyle = 'vsReport'
      list.OwnerData = true
      list.ReadOnly = true
      list.RowSelect = true
      list.HideSelection = false
      list.MultiSelect = true
      list.Color = 0x252525
      list.Font.Color = 0xffffff
      list.ShowColumnHeaders = true
      local host = createPanel(form)
      s.frozenHost = host
      host.Caption = ''
      host.BevelOuter = 'bvNone'
      host.Color = 0x252525
      local frozen = createListView(host)
      s.frozen = frozen
      frozen.ViewStyle = 'vsReport'
      frozen.OwnerData = true
      frozen.ReadOnly = true
      frozen.RowSelect = true
      frozen.HideSelection = false
      frozen.MultiSelect = true
      frozen.Color = 0x252525
      frozen.Font.Color = 0xffffff
      frozen.ShowColumnHeaders = true
      for i, col in ipairs(s.columns) do
        s.byKey[col.key] = col
        local header = (i &lt;= 2 and frozen or list).Columns.add()
        header.Caption = col.title
        header.Width = col.width or 110
        field.Items.add(col.title)
      end
      local send = assert(getAddressSafe('user32.SendMessageW', true))
      local style = assert(getAddressSafe('user32.GetWindowLongW', true))
      local metrics = assert(getAddressSafe('user32.GetSystemMetrics', true))
      local showScroll = assert(getAddressSafe('user32.ShowScrollBar', true))
      local function message(view, msg, w, l)
        return sendMessage(view.Handle, msg, w or 0, l or 0)
      end
      frozen.OnData = function(_, item)
        if s.closed then
          return
        end
        local row = s.shown[item.Index + 1]
        if row then
          item.Caption = row.display.displayId
          item.SubItems.Text = row.display.name
        end
      end
      field.ItemIndex = 0
      list.OnData = function(_, item)
        if s.closed then
          return
        end
        local row = s.shown[item.Index + 1]
        if not row then
          return
        end
        item.Caption = row.display[s.columns[3].key]
        item.SubItems.Text = row.rightText or ''
      end
      -- Explicit selected text and background, including horizontally scrolled columns.
      list.OnCustomDrawItem = function(sender, item)
        if s.closed then
          return true
        end
        sender.Canvas.Font.Color = 0xffffff
        sender.Canvas.Brush.Color = item.Selected and 0x805020 or 0x252525
        return true
      end
      frozen.OnCustomDrawItem = list.OnCustomDrawItem
      function s.syncScroll()
        if
          s.closed
          or s.rendering
          or s.syncing
          or #s.shown == 0
          or list.Items.Count ~= #s.shown
          or frozen.Items.Count ~= #s.shown
        then
          return
        end
        s.syncing = true
        local left = message(frozen, 0x1027)
        local right = message(list, 0x1027)
        local source, target, top
        if left ~= s.lastLeft and right == s.lastRight then
          source, target, top = frozen, list, left
        elseif right ~= s.lastRight or left ~= right then
          source, target, top = list, frozen, right
        end
        if target then
          local from = message(target, 0x1027)
          local item = target.Items[from]
          if item then
            local rect = item.displayRect('drBounds')
            message(target, 0x1014, 0, (top - from) * math.max(1, rect.Bottom - rect.Top))
          end
        end
        if target then
          s.lastLeft = message(frozen, 0x1027)
          s.lastRight = message(list, 0x1027)
        else
          s.lastLeft = left
          s.lastRight = right
        end
        s.syncing = false
      end
      local scrollTimer = createTimer(form, false)
      s.scrollTimer = scrollTimer
      scrollTimer.Interval = 20
      scrollTimer.OnTimer = function()
        if s.closed then
          return
        end
        local width = frozen.Columns[0].Width + frozen.Columns[1].Width + 4
        local now = getTickCount()
        local bar = s.barHeight or 0
        if now &gt;= (s.geometryNext or 0) then
          bar = (executeCodeLocalEx(style, list.Handle, -16) &amp; 0x100000) ~= 0 and executeCodeLocalEx(metrics, 3) or 0
          s.geometryNext = now + 250
        end
        if width ~= s.fixedWidth or bar ~= s.barHeight then
          s.fixedWidth = width
          s.barHeight = bar
          layout()
        end
        s.syncScroll()
      end
      scrollTimer.Enabled = true
      local function selectOther(sender, item)
        if s.closed or s.rendering or s.busy or s.selecting or not item or not item.Selected then
          return
        end
        local other = sender == frozen and list or frozen
        if item.Index &lt; 0 or item.Index &gt;= other.Items.Count then
          return
        end
        s.selecting = true
        other.ItemIndex = item.Index
        s.selecting = false
      end
      frozen.OnSelectItem = selectOther
      list.OnSelectItem = selectOther
      function s.openSelected()
        if s.closed or s.inFlight then
          return
        end
        local index = frozen.ItemIndex
        local row = s.shown[index + 1]
        if not row then
          return
        end
        s.inFlight = true
        local ok, err = pcall(function()
          assert(api.processAlive() and api.pid == s.pid and getOpenedProcessID() == s.pid, 'List process changed')
          local found = false
          for _, candidate in ipairs(api.entityRows(s.key)) do
            if candidate.id == row.id and candidate.displayId == row.displayId then found = true; break end
          end
          assert(found, api.T('The entity changed. Refresh the list.', '対象が変わりました。一覧を更新してください。'))
          if not s.closed then api.jumpToEntity(row.source) end
        end)
        s.inFlight = false
        if not ok and not s.closed then
          status.Caption = api.T('Cannot open: ', '開けません：') .. str(err)
        end
      end
      frozen.OnDblClick = s.openSelected
      function s.render()
        if s.closed then
          return
        end
        s.shown = Lists.view(s)
        s.rendering = true
        list.beginUpdate()
        frozen.beginUpdate()
        list.Items.Count = 0
        frozen.Items.Count = 0
        list.Items.Count = #s.shown
        frozen.Items.Count = #s.shown
        frozen.endUpdate()
        list.endUpdate()
        s.rendering = false
        list.repaint()
        frozen.repaint()
        s.lastLeft = nil
        s.lastRight = nil
        for i, col in ipairs(s.columns) do
          local view = i &lt;= 2 and frozen or list
          local offset = i &lt;= 2 and i - 1 or i - 3
          view.Columns[offset].Caption = col.title .. (i == s.sortIndex and (s.ascending and ' ↑' or ' ↓') or '')
        end
        local filters = 0
        for _, q in pairs(s.queries) do
          if q ~= '' then
            filters = filters + 1
          end
        end
        status.Caption = api.T('Shown ', '表示 ')
          .. #s.shown
          .. ' / '
          .. #s.rows
          .. api.T('   Columns: ', '   項目数：')
          .. #s.columns
          .. api.T('   Filters: ', '   検索条件：')
          .. filters
          .. (s.busy and api.T('   Loading ', '   読み取り中 ') .. math.min(s.position - 1, #s.sources) .. ' / ' .. #s.sources or '')
          .. (s.errors &gt; 0 and api.T('   Unavailable: ', '   読み取り不可：') .. s.errors or '')
      end
      function s.sort(index)
        if s.sortIndex == index then
          s.ascending = not s.ascending
        else
          s.sortIndex = index
          s.ascending = true
        end
        s.render()
      end
      list.OnColumnClick = function(_, column)
        for i = 0, list.Columns.Count - 1 do
          if list.Columns[i].Caption == column.Caption then
            s.sort(i + 3)
            break
          end
        end
      end
      frozen.OnColumnClick = function(_, column)
        for i = 0, 1 do
          if frozen.Columns[i].Caption == column.Caption then
            s.sort(i + 1)
            break
          end
        end
      end
      local filterTimer = createTimer(form, false)
      filterTimer.Interval = 160
      filterTimer.OnTimer = function()
        filterTimer.Enabled = false
        if not s.closed then
          s.render()
        end
      end
      s.filterTimer = filterTimer
      search.OnChange = function()
        if s.changing then
          return
        end
        local col = s.columns[field.ItemIndex]
        s.queries[col and col.key or '*'] = search.Text
        filterTimer.Enabled = false
        filterTimer.Enabled = true
      end
      field.OnChange = function()
        s.changing = true
        local col = s.columns[field.ItemIndex]
        search.Text = s.queries[col and col.key or '*'] or ''
        s.changing = false
      end
      clear.OnClick = function()
        s.queries = {}
        s.changing = true
        search.Text = ''
        s.changing = false
        s.render()
      end
      local loader = createTimer(form, false)
      loader.Interval = 15
      s.loader = loader
      function s.begin()
        if s.closed or s.busy then
          return
        end
        s.busy = true
        refresh.Enabled = false
        s.errors = 0
        s.names = {}
        s.choiceMaps = {}
        s.position = 1
        s.rows = {}
        s.shown = {}
        list.Items.Count = 0
        frozen.Items.Count = 0
        s.inFlight = true
        local ok, rows = pcall(api.entityRows, s.key)
        s.inFlight = false
        if s.closed then
          return
        end
        if not ok then
          s.busy = false
          refresh.Enabled = true
          status.Caption = api.T('Cannot read list: ', '一覧を取得できません：') .. str(rows)
          return
        end
        s.sources = rows
        s.pid = api.pid
        s.render()
        loader.Enabled = true
      end
      loader.OnTimer = function()
        loader.Enabled = false
        if s.closed then
          return
        end
        local started = getTickCount()
        s.inFlight = true
        local ok, err = pcall(Lists.snapshot, function()
          assert(HV == api and api.pid == s.pid and getOpenedProcessID() == s.pid, 'List process changed')
          repeat
            if s.closed then
              break
            end
            local source = s.sources[s.position]
            if not source then
              break
            end
            local valid, row = pcall(Lists.readRow, s, source)
            if valid then
              s.rows[#s.rows + 1] = row
            else
              s.errors = s.errors + 1
              s.lastError = row
            end
            s.position = s.position + 1
          until s.closed or s.position &gt; #s.sources or getTickCount() - started &gt;= 25
        end)
        s.inFlight = false
        if s.closed then
          return
        end
        if not ok then
          s.busy = false
          refresh.Enabled = true
          status.Caption = api.T('Reading stopped: ', '読み取り停止：') .. str(err)
          return
        end
        if s.position &gt; #s.sources then
          s.busy = false
          refresh.Enabled = true
          s.render()
        else
          status.Caption = api.T('Loading ', '読み取り中 ') .. (s.position - 1) .. ' / ' .. #s.sources
          loader.Enabled = true
        end
      end
      refresh.OnClick = s.begin
      s.regionButtons = {}
      layout = function()
        local w, h = form.ClientWidth, form.ClientHeight
        field.Left = 14
        field.Top = 12
        field.Width = 260
        field.Height = 28
        search.Left = 284
        search.Top = 12
        search.Width = math.max(180, w - 680)
        search.Height = 28
        clear.Left = w - 380
        clear.Top = 10
        clear.Width = 110
        clear.Height = 32
        refresh.Left = w - 260
        refresh.Top = 10
        refresh.Width = 110
        refresh.Height = 32
        close.Left = w - 140
        close.Top = 10
        close.Width = 126
        close.Height = 32
        for i, button in ipairs(s.regionButtons) do
          button.Left = w - 334 + (i - 1) * 80
          button.Top = 46
          button.Width = 80
          button.Height = 28
        end
        status.Left = 16
        status.Top = 52
        status.AutoSize = false
        status.Height = 24
        status.Width = math.max(200, w - 32)
        local fw = s.fixedWidth or 314
        host.Left = 14
        host.Top = 80
        host.Width = fw
        host.Height = h - 94 - (s.barHeight or 0)
        frozen.Left = 0
        frozen.Top = 0
        frozen.Width = fw + executeCodeLocalEx(metrics, 2) + 2
        frozen.Height = host.Height
        list.Left = 18 + fw
        list.Top = 80
        list.Width = math.max(150, w - 32 - fw)
        list.Height = h - 94
      end
      function s.destroy()
        if s.closed then
          return
        end
        s.closed = true
        loader.Enabled = false
        filterTimer.Enabled = false
        scrollTimer.Enabled = false
        if Lists.windows[key] == s then
          Lists.windows[key] = nil
        end
        form.OnResize = nil
        form.hide()
        -- Native getters may pump UI messages. Keep controls alive until their caller returns.
        local disposer = createTimer(nil, false)
        disposer.Interval = 50
        s.disposer = disposer
        disposer.OnTimer = function()
          if s.inFlight then
            return
          end
          disposer.Enabled = false
          s.disposer = nil
          list.OnData = nil
          list.OnCustomDrawItem = nil
          list.OnColumnClick = nil
          list.OnSelectItem = nil
          frozen.OnData = nil
          frozen.OnCustomDrawItem = nil
          frozen.OnColumnClick = nil
          frozen.OnSelectItem = nil
          frozen.OnDblClick = nil
          form.OnClose = nil
          form.destroy()
          s.disposed = true
          disposer.destroy()
        end
        disposer.Enabled = true
      end
      close.OnClick = s.destroy
      form.OnClose = function()
        s.destroy()
        return caHide
      end
      form.OnResize = layout
      layout()
      Lists.windows[key] = s
      return s
    end

  function HV.openEntityList(key,title)
    HV.init()
    local old=Lists.windows[key]
    if old and not old.closed then old.form.show();old.form.bringToFront();return old end
    local s=Lists.create(key);s.form.show();s.begin();return s
  end
  local oldForget=HV.forgetProcess
  function HV.forgetProcess(...)
    for _,s in pairs(Lists.windows)do if not s.closed then s.destroy()end end
    return oldForget(...)
  end
  local oldApply=HV.applyLang
  function HV.applyLang(...)
    for _,s in pairs(Lists.windows)do if not s.closed and s.lang~=api.lang then s.destroy()end end
    return oldApply(...)
  end
end

HV.NAMES[13000]={"07. Lists","07. 一覧表示"}
HV.NAMES[1100]={"08. Other","08. その他"}
HV.NAMES[13001]={"All heroes","全武将"}
HV.NAMES[13002]={"Own-power heroes","自勢力の武将"}
HV.NAMES[13003]={"Family heroes","家族の武将"}
HV.NAMES[13004]={"All cities","全都市"}
HV.NAMES[13005]={"Own-power cities","自勢力の都市"}
HV.NAMES[13006]={"Powers","勢力"}
HV.NAMES[13007]={"All families","全家族"}
HV.NAMES[13008]={"Own-power families","自勢力の家族"}
HV.NAMES[14000]={"Power editor (selected from Lists)","勢力エディタ（一覧から選択）"}
HV.NAMES[14001]={"Funds","資金"}
HV.NAMES[14002]={"Technology points","技術点"}
HV.NAMES[14003]={"Policy points","政策ポイント"}
HV.NAMES[14100]={"Family (none)","所属家族（なし）"}
HV.NAMES[14101]={"Start year","存続開始年"}
HV.NAMES[14102]={"End year","存続終了年"}
HV.NAMES[14103]={"Military talent","軍事適性"}
HV.NAMES[14104]={"Commerce talent","商業適性"}
HV.NAMES[14105]={"Politics talent","政治適性"}
HV.NAMES[14106]={"Members (double-click a name to open hero editor)","構成武将（名前のダブルクリックで武将エディタへ）"}

HV.familyHero=nil;HV.familyList=nil;HV.selFamily=nil
pcall(HV.initCollapse)
HV.applyLang()
HV.msg("Heroes' Vow table loaded.","Heroes' Vow テーブルを読み込みました。")
</LuaScript>
</CheatTable>