From 8872a9286a05d4fc1a5656e83a4e19f879dc5ade Mon Sep 17 00:00:00 2001 From: Erik Date: Sun, 6 Sep 2026 19:33:06 +0200 Subject: [PATCH] =?UTF-8?q?docs(vt):=20VT1=20catalog=2001=20=E2=80=94=20VT?= =?UTF-8?q?ank=20settings,=20defaults=20and=20the=20.usd=20profile=20forma?= =?UTF-8?q?t?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit All 137 settings with type/default/category/UI control/consumer citation, the self-describing .usd table grammar (parsed from the decompile and verified against defaultsettings.usd), profile selection and /vt opt. MossTank gap: no .usd reader/writer, BuffProfileDocument drops ten fields, RechargeHandlerSet opaque; setting-name coverage is already 137/137. Lead spot-check: f3 accessors, the four reader classes, catalog count. Co-Authored-By: Claude Fable 5.1 --- .../vtank-kb/01-settings-and-profiles.md | 574 ++++++++++++++++++ 1 file changed, 574 insertions(+) create mode 100644 docs/research/vtank-kb/01-settings-and-profiles.md diff --git a/docs/research/vtank-kb/01-settings-and-profiles.md b/docs/research/vtank-kb/01-settings-and-profiles.md new file mode 100644 index 00000000..35f31355 --- /dev/null +++ b/docs/research/vtank-kb/01-settings-and-profiles.md @@ -0,0 +1,574 @@ +# VTank knowledge base 01 — settings and profiles + +Campaign VT, phase VT1. Oracle: `refs/vtank/decompiled/` (ILSpy output of +`utank2-i.dll`, obfuscated identifiers, real strings) plus +`refs/vtank/uTank2.Resources.defaultsettings.usd`, +`uTank2.Resources.defaultsettingstemplate.usd`, `uTank2.ViewXML.mainView.xml`, +`uTank2.ViewXML.AdvancedOptionsView.xml`. All paths in this document are +relative to the repo root unless stated otherwise; none of the cited code is +reproduced verbatim beyond short identifiers and strings, per the campaign +rules in `docs/plans/2026-09-06-campaign-vt-vtank-oracle.md`. + +No code changes are part of this document. Every claim below cites a +`file:line` in the decompile; a companion Python parser used to extract the +`.usd` grammar and the settings/UI/consumer correlation lives only in the +session scratchpad (not committed) and is described in enough detail here to +be reproduced. + +## 1. How settings are stored and read (architecture) + +VTank settings are not a flat key/value file. They are rows in a small +generic in-memory relational database (`y` = a named collection of tables, +`bd` = one table, `cw` = one row, `gy` = one self-describing typed cell) that +gets serialized to a `.usd` file. The same database format is reused for +`.ast` per-character caches (section 3) and — per the embedded resource names +— shares a family with `.ugd` template/database resources. + +- **`gy`** (`refs/vtank/decompiled/gy.cs:20-56`) is a self-typing cell. + `gy.a(TextReader)` reads one line for a *type tag*, then, depending on the + tag, one more line for the value: `d`=double, `i`=int, `u`=uint, `f`=float, + `s`=string (the raw next line, possibly empty), `b`=bool + (`gy.cs:25-49`). Any other tag string is looked up in a type registry + (`y.a(string)`, `refs/vtank/decompiled/y.cs:28-43`) and the matching custom + type's own multi-line reader runs recursively — two such types are + registered at startup: `bd` itself (tag `"TABLE"`, + `refs/vtank/decompiled/bd.cs:422-426`, used when a setting's *value* is a + nested table) and a length-prefixed raw-text blob class (tag `"ba"`, + `refs/vtank/decompiled/f6.cs:9-30`, `int` length line then that many raw + characters — not lines — allowing embedded newlines). +- **`cw`** (`refs/vtank/decompiled/cw.cs:9-40`) is one row: a fixed-size list + of `gy` cells, one per column of its owning table. +- **`bd`** (`refs/vtank/decompiled/bd.cs`) is one table. Its text format + (`bd.a(TextReader)`, `bd.cs:364-395`) is: column count, then that many raw + column-name lines, then that many `"y"`/`"n"` index-flag lines (whether + that column is hash-indexed for fast lookup), then a row count, then that + many rows (each row is `columnCount` `gy` cells in order — **not** always 2 + lines each; a `tCustom` cell recurses into a full nested table or blob, so + row length is variable and must be parsed, never assumed). +- **`y`** (`refs/vtank/decompiled/y.cs`) is the whole database: a table + count line, then that many `(tableName, bd)` pairs + (`y.a(TextReader)`, `y.cs:87-97`). `y.d(path)` reads a plain file + (`y.cs:99-104`); `y.c(resourceName)` reads an embedded assembly resource + (`y.cs:131-139`, used only for the two shipped defaults). +- **`f3`** (`refs/vtank/decompiled/f3.cs`) is the accessor facade all other + code calls: `f3.k(name)`→bool (`f3.cs:52-61`), `f3.j(name)`→int + (`f3.cs:63-72`), `f3.i(name)`→double (`f3.cs:74-83`), `f3.h(name)`→float + (`f3.cs:85-94`), `f3.g(name)`→string (`f3.cs:96-105`), + `f3.e(name)`→raw `gy` (`f3.cs:129-147`), `f3.b(name, gy)` sets + persists + + refreshes dependent UI (`f3.cs:150-174`), `f3.a(name, gy)` sets without the + refresh (`f3.cs:176-198`), `f3.d(name)`→description string + (`f3.cs:200-215`), `f3.b(name)`→`eSettingValueType` + (`f3.cs:223-238`), `f3.a(eSettingCategories)`→list of setting names in any + of the given category flags (`f3.cs:339-352`, `[Flags]` OR test). Every + read-through accessor caches by name in a `static Dictionary` + (`f3.cs:8-20`) that `f3.b()` (the no-arg cache-clear, `f3.cs:118-125`) + flushes on every write. +- **Two databases, one fallback chain.** `f3.e(name)` (`f3.cs:129-147`) + first looks in `PluginCore.dz.m.c["Settings"]` (the *current*, loaded + profile) and only if the key is missing there falls back to + `PluginCore.dz.m.b["Settings"]` (the *built-in* defaults, seeded once from + the embedded `defaultsettings.usd` resource, `refs/vtank/decompiled/da.cs:21` + field `d`, loaded in the `da()` constructor at `da.cs:55-58`). **This is + VTank's unknown/missing-key handling**: a `.usd` saved by an older build + that lacks a setting the current build added silently reads that setting's + shipped default; there is no error, no migration write-back for scalar + settings. (Grid-shaped settings such as `MyMonsters` get an *explicit* + column-count migration instead — see section 3.) +- **`da`** (`refs/vtank/decompiled/da.cs`) is the profile manager, + reachable as `PluginCore.dz.m` (`dz` is `PluginCore`'s singleton hub, of + type `s`; `s.m` is declared and constructed at + `refs/vtank/decompiled/s.cs:33,152`). `da.b` is the built-in-defaults `y`; + `da.c` is the loaded/current `y`. +- **`db`** (`refs/vtank/decompiled/db.cs`) is the *Advanced Options* window + — a single generic property-grid editor that is the **primary UI for the + great majority of settings** (see section 4). It is reachable as + `PluginCore.dz.ad` (field declared and constructed as type `db` at + `refs/vtank/decompiled/s.cs:67,186`) and toggled by the "Advanced Options" + checkbox (`cShowAdvanced` in `mainView.xml`, bound to field `x` at + `refs/vtank/decompiled/uTank2/PluginCore.cs:1627`, toggle call at + `uTank2/PluginCore.cs:6731`). + +## 2. Complete settings table (137 rows) + +Generated by parsing `uTank2.Resources.defaultsettings.usd`'s `Settings` +table (4 columns: `Setting`, `Value`, `Description`, `SettingType`; 137 rows, +confirmed against `SettingsCategories` (136 rows — every setting except +`RechargeHandlerSet`, which has no category) and `SettingsEnumInfo` (33 rows, +the `tEnum` display-label mappings)) with a from-scratch grammar-accurate +parser (implementing the exact `gy`/`bd`/`cw`/`y` recursive format above), +then cross-referencing each name against: + +- every `f3.("Name")` call site across all 344 decompiled `.cs` + files (a same-line regex match against `X.Checked`/`X.Text`/`.SelectedIndex`/ + `.Value` was used to find a bound UI field), and +- the `this. = (ICheckBox|ITextBox|...)this.k[""]` + binding table built from every such assignment in + `refs/vtank/decompiled/uTank2/PluginCore.cs` (115 bindings extracted, one + per named view control PluginCore holds a reference to), joined against + every `` element in `mainView.xml` / + `AdvancedOptionsView.xml` (189 controls, walked with page/tab tracking). + +`eSettingValueType` (`refs/vtank/decompiled/uTank2/eSettingValueType.cs`) and +`eSettingCategories` (`refs/vtank/decompiled/uTank2/eSettingCategories.cs`, +a `[Flags]` enum) supply the Type and Category columns. All 137 settings are +global to the loaded profile (`da.c`) — VTank's per-character/per-profile +scoping happens at the **file** level (section 3: which `.usd` file is +loaded for a character), not at the individual-setting level; there is no +concept of a setting being "per-character" independent of which profile file +is currently selected. + +| # | Setting | Type | Default | Category | UI | Primary consumer (decompiled) | +|---|---|---|---|---|---|---| +| 1 | `EnableLooting` | bool | False | Looting | Advanced Options list only (`lOptionList`, filter category Looting) | `refs/vtank/decompiled/a1.cs:63 [k]`; `refs/vtank/decompiled/ar.cs:63 [k]`; `refs/vtank/decompiled/b7.cs:109 [k]` | +| 2 | `EnableNav` | bool | False | Navigation | Advanced Options list only (`lOptionList`, filter category Navigation) | `refs/vtank/decompiled/b7.cs:92 [k]`; `refs/vtank/decompiled/da.cs:708 [a]`; `refs/vtank/decompiled/g8.cs:87 [k]` | +| 3 | `EnableBuffing` | bool | True | Buffing | Advanced Options list only (`lOptionList`, filter category Buffing) | `refs/vtank/decompiled/fz.cs:76 [k]`; `refs/vtank/decompiled/uTank2/PluginCore.cs:1513 [k]`; `refs/vtank/decompiled/uTank2/PluginCore.cs:1514 [b]` | +| 4 | `EnableCombat` | bool | True | MeleeCombat\|SpellCombat | Advanced Options list only (`lOptionList`, filter category MeleeCombat\|SpellCombat) | `refs/vtank/decompiled/b4.cs:69 [k]`; `refs/vtank/decompiled/dq.cs:42 [k]`; `refs/vtank/decompiled/h1.cs:32 [k]` | +| 5 | `SpellDiffExcessThreshold-Hunt` | int | 25 | SpellCombat | Advanced Options list only (`lOptionList`, filter category SpellCombat) | `refs/vtank/decompiled/da.cs:64 [j]`; `refs/vtank/decompiled/da.cs:711 [a]` | +| 6 | `SpellDiffExcessThreshold-Buff` | int | 5 | Buffing | Advanced Options list only (`lOptionList`, filter category Buffing) | `refs/vtank/decompiled/da.cs:66 [j]`; `refs/vtank/decompiled/da.cs:712 [a]` | +| 7 | `ArrowheadFletchDiffExcessThreshold` | int | 10 | Crafting | Advanced Options list only (`lOptionList`, filter category Crafting) | `refs/vtank/decompiled/da.cs:713 [a]` | +| 8 | `Recharge-Norm-HitP` | int | 75 | Recharge | Advanced Options list only (`lOptionList`, filter category Recharge) | `refs/vtank/decompiled/da.cs:714 [a]`; `refs/vtank/decompiled/ei.cs:54 [j]`; `refs/vtank/decompiled/uTank2/PluginCore.cs:4421 [a]` | +| 9 | `Recharge-Norm-Stam` | int | 50 | Recharge | Advanced Options list only (`lOptionList`, filter category Recharge) | `refs/vtank/decompiled/da.cs:715 [a]`; `refs/vtank/decompiled/uTank2/PluginCore.cs:4408 [a]`; `refs/vtank/decompiled/uTank2/PluginCore.cs:4412 [b]` | +| 10 | `Recharge-Norm-Mana` | int | 50 | Recharge | Advanced Options list only (`lOptionList`, filter category Recharge) | `refs/vtank/decompiled/da.cs:716 [a]`; `refs/vtank/decompiled/uTank2/PluginCore.cs:4395 [a]`; `refs/vtank/decompiled/uTank2/PluginCore.cs:4399 [b]` | +| 11 | `Recharge-NoTarg-HitP` | int | 1 | Recharge | Advanced Options list only (`lOptionList`, filter category Recharge) | `refs/vtank/decompiled/da.cs:717 [a]`; `refs/vtank/decompiled/uTank2/PluginCore.cs:4343 [a]`; `refs/vtank/decompiled/uTank2/PluginCore.cs:4347 [b]` | +| 12 | `Recharge-NoTarg-Stam` | int | 1 | Recharge | Advanced Options list only (`lOptionList`, filter category Recharge) | `refs/vtank/decompiled/da.cs:718 [a]`; `refs/vtank/decompiled/uTank2/PluginCore.cs:4330 [a]`; `refs/vtank/decompiled/uTank2/PluginCore.cs:4334 [b]` | +| 13 | `Recharge-NoTarg-Mana` | int | 1 | Recharge | Advanced Options list only (`lOptionList`, filter category Recharge) | `refs/vtank/decompiled/da.cs:719 [a]`; `refs/vtank/decompiled/uTank2/PluginCore.cs:4317 [a]`; `refs/vtank/decompiled/uTank2/PluginCore.cs:4321 [b]` | +| 14 | `Recharge-Helper-HitP` | int | 20 | Recharge | Advanced Options list only (`lOptionList`, filter category Recharge) | `refs/vtank/decompiled/da.cs:720 [a]`; `refs/vtank/decompiled/uTank2/PluginCore.cs:4382 [a]`; `refs/vtank/decompiled/uTank2/PluginCore.cs:4386 [b]` | +| 15 | `Recharge-Helper-Stam` | int | 1 | Recharge | Advanced Options list only (`lOptionList`, filter category Recharge) | `refs/vtank/decompiled/da.cs:721 [a]`; `refs/vtank/decompiled/uTank2/PluginCore.cs:4369 [a]`; `refs/vtank/decompiled/uTank2/PluginCore.cs:4373 [b]` | +| 16 | `Recharge-Helper-Mana` | int | 1 | Recharge | Advanced Options list only (`lOptionList`, filter category Recharge) | `refs/vtank/decompiled/da.cs:722 [a]`; `refs/vtank/decompiled/uTank2/PluginCore.cs:4356 [a]`; `refs/vtank/decompiled/uTank2/PluginCore.cs:4360 [b]` | +| 17 | `DoHelp` | bool | True | Recharge | Advanced Options list only (`lOptionList`, filter category Recharge) | `refs/vtank/decompiled/da.cs:723 [a]` | +| 18 | `AttackDistance` | double | 0.0208333333333333 | Ranges | Advanced Options list only (`lOptionList`, filter category Ranges) | `refs/vtank/decompiled/da.cs:724 [a]`; `refs/vtank/decompiled/dz.cs:666 [i]`; `refs/vtank/decompiled/ga.cs:1084 [i]` | +| 19 | `AttackMinimumDistance` | double | 0 | Ranges | Advanced Options list only (`lOptionList`, filter category Ranges) | `refs/vtank/decompiled/dz.cs:716 [i]`; `refs/vtank/decompiled/dz.cs:952 [i]`; `refs/vtank/decompiled/dz.cs:966 [i]` | +| 20 | `ApproachDistance` | double | 0 | Ranges\|Navigation | Advanced Options list only (`lOptionList`, filter category Ranges\|Navigation) | `refs/vtank/decompiled/da.cs:725 [a]`; `refs/vtank/decompiled/uTank2/PluginCore.cs:6502 [i]`; `refs/vtank/decompiled/uTank2/PluginCore.cs:6504 [b]` | +| 21 | `RingDistance` | double | 0.0208333333333333 | SpellCombat\|Ranges | `txtRingRange` (Edit, tab "Options"): "" | `refs/vtank/decompiled/da.cs:726 [a]`; `refs/vtank/decompiled/dz.cs:721 [i]`; `refs/vtank/decompiled/uTank2/PluginCore.cs:6522 [i]` | +| 22 | `CorpseApproachRange-Max` | double | 0 | Ranges\|Navigation | Advanced Options list only (`lOptionList`, filter category Ranges\|Navigation) | `refs/vtank/decompiled/uTank2/PluginCore.cs:6506 [i]`; `refs/vtank/decompiled/uTank2/PluginCore.cs:6508 [b]`; `refs/vtank/decompiled/uTank2.Logic/SettingDelegate_SetWaitingOnCorpseId.cs:27 [i]` | +| 23 | `CorpseApproachRange-Min` | double | 0.014 | Ranges\|Navigation | Advanced Options list only (`lOptionList`, filter category Ranges\|Navigation) | *(no direct f3 accessor call found — see notes / doc 02)* | +| 24 | `NavCloseStopRange` | double | 0.00833333333333333 | Ranges\|Navigation | Advanced Options list only (`lOptionList`, filter category Ranges\|Navigation) | `refs/vtank/decompiled/ca.cs:199 [i]`; `refs/vtank/decompiled/ca.cs:256 [i]`; `refs/vtank/decompiled/ca.cs:317 [i]` | +| 25 | `NavFarStopRange` | double | 999999 | Ranges\|Navigation | Advanced Options list only (`lOptionList`, filter category Ranges\|Navigation) | `refs/vtank/decompiled/da.cs:710 [a]` | +| 26 | `UsePortalDistance` | double | 0.0166666666666667 | Ranges\|Navigation | Advanced Options list only (`lOptionList`, filter category Ranges\|Navigation) | `refs/vtank/decompiled/fq.cs:100 [i]`; `refs/vtank/decompiled/fq.cs:109 [i]` | +| 27 | `HelperDistanceHitP` | double | 0.310416666666667 | Recharge\|Ranges | Advanced Options list only (`lOptionList`, filter category Recharge\|Ranges) | `refs/vtank/decompiled/ai.cs:290 [i]`; `refs/vtank/decompiled/ai.cs:354 [i]`; `refs/vtank/decompiled/da.cs:727 [a]` | +| 28 | `HelperDistanceStam` | double | 0.310416666666667 | Recharge\|Ranges | Advanced Options list only (`lOptionList`, filter category Recharge\|Ranges) | `refs/vtank/decompiled/ai.cs:296 [i]`; `refs/vtank/decompiled/ai.cs:360 [i]`; `refs/vtank/decompiled/da.cs:728 [a]` | +| 29 | `HelperDistanceMana` | double | 0.166666666666667 | Recharge\|Ranges | Advanced Options list only (`lOptionList`, filter category Recharge\|Ranges) | `refs/vtank/decompiled/ai.cs:302 [i]`; `refs/vtank/decompiled/ai.cs:366 [i]`; `refs/vtank/decompiled/da.cs:729 [a]` | +| 30 | `MinimumRingTargets` | int | 4 | SpellCombat | Advanced Options list only (`lOptionList`, filter category SpellCombat) | `refs/vtank/decompiled/da.cs:730 [a]`; `refs/vtank/decompiled/hi.cs:222 [j]` | +| 31 | `DefaultMeleeAttackHeight` | int | 2 | MeleeCombat | Advanced Options list only (`lOptionList`, filter category MeleeCombat) | `refs/vtank/decompiled/bo.cs:300 [j]`; `refs/vtank/decompiled/f7.cs:119 [j]`; `refs/vtank/decompiled/uTank2/PluginCore.cs:1528 [b]` | +| 32 | `CastDispelSelf` | bool | False | Recharge | `cDispel` (Checkbox, tab "Options"): "Cast Dispel Self" | `refs/vtank/decompiled/c8.cs:68 [k]`; `refs/vtank/decompiled/da.cs:731 [a]`; `refs/vtank/decompiled/uTank2/PluginCore.cs:6567 [b]` | +| 33 | `UseDispelItems` | bool | False | Recharge | `cGems` (Checkbox, tab "Options"): "Use Dispel Items" | `refs/vtank/decompiled/cx.cs:66 [k]`; `refs/vtank/decompiled/da.cs:732 [a]`; `refs/vtank/decompiled/uTank2/PluginCore.cs:6579 [b]` | +| 34 | `AutoCram` | bool | False | Misc | `cEnableAutoCram` (Checkbox, tab "Options"): "Enable Autocram" | `refs/vtank/decompiled/el.cs:129 [k]`; `refs/vtank/decompiled/uTank2/PluginCore.cs:3273 [k]`; `refs/vtank/decompiled/uTank2/PluginCore.cs:3276 [b]` | +| 35 | `AutoStack` | bool | True | Misc | `cEnableAutoStack` (Checkbox, tab "Options"): "Enable Autostack" | `refs/vtank/decompiled/el.cs:81 [k]`; `refs/vtank/decompiled/uTank2/PluginCore.cs:3272 [k]`; `refs/vtank/decompiled/uTank2/PluginCore.cs:3275 [b]` | +| 36 | `ReadUnknownScrolls` | bool | True | Looting | Advanced Options list only (`lOptionList`, filter category Looting) | `refs/vtank/decompiled/hv.cs:479 [k]` | +| 37 | `UseDispelDrum` | bool | False | Recharge | Advanced Options list only (`lOptionList`, filter category Recharge) | `refs/vtank/decompiled/af.cs:75 [k]`; `refs/vtank/decompiled/uTank2/PluginCore.cs:3046 [b]` | +| 38 | `SwitchWandsToDebuff` | bool | False | SpellCombat | Advanced Options list only (`lOptionList`, filter category SpellCombat) | `refs/vtank/decompiled/dz.cs:488 [k]` | +| 39 | `AutoCraftItems` | bool | True | Crafting | Advanced Options list only (`lOptionList`, filter category Crafting) | `refs/vtank/decompiled/a9.cs:111 [k]` | +| 40 | `UseHealersHeart` | bool | True | Recharge | Advanced Options list only (`lOptionList`, filter category Recharge) | `refs/vtank/decompiled/fb.cs:71 [k]` | +| 41 | `JumpOutWandCasting` | bool | False | Recharge\|SpellCombat | Advanced Options list only (`lOptionList`, filter category Recharge\|SpellCombat) | `refs/vtank/decompiled/gs.cs:238 [k]`; `refs/vtank/decompiled/gs.cs:304 [k]` | +| 42 | `LootAllCorpses` | bool | False | Looting | Advanced Options list only (`lOptionList`, filter category Looting) | `refs/vtank/decompiled/fo.cs:431 [k]` | +| 43 | `LootFellowCorpses` | bool | False | Looting | Advanced Options list only (`lOptionList`, filter category Looting) | `refs/vtank/decompiled/fo.cs:426 [k]` | +| 44 | `DoJiggle` | bool | False | SpellCombat | Advanced Options list only (`lOptionList`, filter category SpellCombat) | `refs/vtank/decompiled/gj.cs:165 [k]`; `refs/vtank/decompiled/gs.cs:119 [k]` | +| 45 | `RandomHelperBuffs` | bool | False | Misc | Advanced Options list only (`lOptionList`, filter category Misc) | `refs/vtank/decompiled/ba.cs:85 [k]` | +| 46 | `RandomHelperIntervalSeconds` | double | 5 | Misc | Advanced Options list only (`lOptionList`, filter category Misc) | `refs/vtank/decompiled/ba.cs:154 [i]` | +| 47 | `IdlePeaceMode` | bool | False | Misc | `cIdlePeace` (Checkbox, tab "Options"): "Peace Mode When Idle" | `refs/vtank/decompiled/cm.cs:66 [k]`; `refs/vtank/decompiled/fd.cs:131 [k]`; `refs/vtank/decompiled/uTank2/PluginCore.cs:6744 [b]` | +| 48 | `TargetLock` | bool | False | MeleeCombat\|SpellCombat | Advanced Options list only (`lOptionList`, filter category MeleeCombat\|SpellCombat) | `refs/vtank/decompiled/dz.cs:717 [k]`; `refs/vtank/decompiled/dz.cs:952 [k]`; `refs/vtank/decompiled/dz.cs:967 [k]` | +| 49 | `StopMacroOnDeath` | bool | True | Misc | Advanced Options list only (`lOptionList`, filter category Misc) | `refs/vtank/decompiled/uTank2/PluginCore.cs:4155 [k]` | +| 50 | `UseArcs` | enum | 1 | SpellCombat | Advanced Options list only (`lOptionList`, filter category SpellCombat) Enum: 1=No, 2=At Range, 3=Yes | `refs/vtank/decompiled/hi.cs:515 [f]` | +| 51 | `ArcRange` | double | 0.0208333333333333 | SpellCombat\|Ranges | Advanced Options list only (`lOptionList`, filter category SpellCombat\|Ranges) | `refs/vtank/decompiled/hi.cs:522 [i]` | +| 52 | `TargetSelectMethod` | enum | 3 | MeleeCombat\|SpellCombat | Advanced Options list only (`lOptionList`, filter category MeleeCombat\|SpellCombat) Enum: 1=By range, 2=By angle, 3=Both | `refs/vtank/decompiled/dz.cs:722 [f]` | +| 53 | `TargetSelectAngleRange` | double | 0.0208333333333333 | MeleeCombat\|SpellCombat\|Ranges | Advanced Options list only (`lOptionList`, filter category MeleeCombat\|SpellCombat\|Ranges) | `refs/vtank/decompiled/dz.cs:726 [i]` | +| 54 | `IdleBuffTopoff` | bool | False | Buffing | `cTopoffBuffs` (Checkbox, tab "Options"): "Rebuff When Idle" | `refs/vtank/decompiled/uTank2/PluginCore.cs:6675 [b]`; `refs/vtank/decompiled/uTank2/PluginCore.cs:7278 [k]` | +| 55 | `IdleBuffTopoffTimeSeconds` | int | 1200 | Buffing | Advanced Options list only (`lOptionList`, filter category Buffing) | *(no direct f3 accessor call found — see notes / doc 02)* | +| 56 | `RebuffTimeRemainingSeconds` | int | 300 | Buffing | Advanced Options list only (`lOptionList`, filter category Buffing) | `refs/vtank/decompiled/gw.cs:14 [j]` | +| 57 | `RefillWornMana` | bool | True | Misc | Advanced Options list only (`lOptionList`, filter category Misc) | `refs/vtank/decompiled/ev.cs:108 [k]` | +| 58 | `RefillWornMana-Item-ManaPercent` | int | 33 | Misc | Advanced Options list only (`lOptionList`, filter category Misc) | `refs/vtank/decompiled/ev.cs:113 [j]` | +| 59 | `BuffProfile-Prots` | string | "ALFCBPS" | Buffing | Advanced Options list only (`lOptionList`, filter category Buffing) | `refs/vtank/decompiled/eq.cs:161 [g]` | +| 60 | `BuffProfile-Banes` | string | "ALFCBPS" | Buffing | Advanced Options list only (`lOptionList`, filter category Buffing) | `refs/vtank/decompiled/eq.cs:248 [g]` | +| 61 | `BuffProfile_Prots` | enum | 2 | Buffing | Advanced Options list only (`lOptionList`, filter category Buffing) Enum: 1=Custom, 2=All, 3=None, 4=B, 5=BPS, 6=BPSA, 7=ALFC, 8=BPSAC | `refs/vtank/decompiled/eq.cs:160 [f]`; `refs/vtank/decompiled/eq.cs:161 [b]` | +| 62 | `BuffProfile_Banes` | enum | 2 | Buffing | Advanced Options list only (`lOptionList`, filter category Buffing) Enum: 1=Custom, 2=All, 3=None, 4=B, 5=BPS, 6=BPSA, 7=BPSAC, 8=ALFC | `refs/vtank/decompiled/eq.cs:247 [f]`; `refs/vtank/decompiled/eq.cs:248 [b]` | +| 63 | `DebuffEachFirst` | enum | 1 | MeleeCombat\|SpellCombat | Advanced Options list only (`lOptionList`, filter category MeleeCombat\|SpellCombat) Enum: 1=One, 2=Priority, 3=All | `refs/vtank/decompiled/dz.cs:712 [c]`; `refs/vtank/decompiled/dz.cs:712 [c]`; `refs/vtank/decompiled/dz.cs:713 [c]` | +| 64 | `AutoAttackPower` | bool | True | MeleeCombat | Advanced Options list only (`lOptionList`, filter category MeleeCombat) | `refs/vtank/decompiled/bo.cs:301 [k]` | +| 65 | `LootPriorityBoost` | bool | False | Looting | `cLootPriorityBoost` (Checkbox, tab "Options"): "Boost Loot Priority" | `refs/vtank/decompiled/uTank2/PluginCore.cs:1574 [k]`; `refs/vtank/decompiled/uTank2/PluginCore.cs:1575 [b]`; `refs/vtank/decompiled/uTank2/PluginCore.cs:1583 [b]` | +| 66 | `CorpseCacheTimeoutMinutes` | double | 60 | Navigation | Advanced Options list only (`lOptionList`, filter category Navigation) | `refs/vtank/decompiled/fo.cs:138 [i]` | +| 67 | `CorpseItemAppearanceTimeoutSeconds` | double | 6 | Looting | Advanced Options list only (`lOptionList`, filter category Looting) | `refs/vtank/decompiled/hv.cs:318 [i]` | +| 68 | `CorpseItemIDTimeoutSeconds` | double | 60 | Looting | Advanced Options list only (`lOptionList`, filter category Looting) | `refs/vtank/decompiled/hv.cs:336 [i]` | +| 69 | `DebuffSelectionMethod` | enum | 2 | MeleeCombat\|SpellCombat | Advanced Options list only (`lOptionList`, filter category MeleeCombat\|SpellCombat) Enum: 1=SpellLevel, 2=Skill | `refs/vtank/decompiled/dz.cs:38 [c]`; `refs/vtank/decompiled/dz.cs:57 [c]` | +| 70 | `ManaStoneLootCount` | int | 4 | Misc\|Looting | Advanced Options list only (`lOptionList`, filter category Misc\|Looting) | `refs/vtank/decompiled/dy.cs:276 [j]` | +| 71 | `ManaTankMinimumMana` | int | 1000 | Misc\|Looting | Advanced Options list only (`lOptionList`, filter category Misc\|Looting) | `refs/vtank/decompiled/dy.cs:132 [j]` | +| 72 | `SplitPeas` | bool | True | Crafting | Advanced Options list only (`lOptionList`, filter category Crafting) | `refs/vtank/decompiled/as.cs:76 [k]` | +| 73 | `SpellCompMin-Critical` | int | 4 | Crafting | Advanced Options list only (`lOptionList`, filter category Crafting) | *(no direct f3 accessor call found — see notes / doc 02)* | +| 74 | `SpellCompMin-Normal` | int | 20 | Crafting | Advanced Options list only (`lOptionList`, filter category Crafting) | *(no direct f3 accessor call found — see notes / doc 02)* | +| 75 | `SpellCompMin-Idle` | int | 20 | Crafting | Advanced Options list only (`lOptionList`, filter category Crafting) | *(no direct f3 accessor call found — see notes / doc 02)* | +| 76 | `RechargeBoostTimeSeconds` | double | 5 | Recharge | Advanced Options list only (`lOptionList`, filter category Recharge) | `refs/vtank/decompiled/be.cs:142 [i]`; `refs/vtank/decompiled/be.cs:149 [i]`; `refs/vtank/decompiled/be.cs:154 [i]` | +| 77 | `RechargeBoostAmount` | int | 40 | Recharge | Advanced Options list only (`lOptionList`, filter category Recharge) | `refs/vtank/decompiled/cg.cs:44 [j]`; `refs/vtank/decompiled/cg.cs:65 [j]`; `refs/vtank/decompiled/cg.cs:86 [j]` | +| 78 | `UseSpecialAmmo` | enum | 0 | Crafting | Advanced Options list only (`lOptionList`, filter category Crafting) Enum: 0=None, 1=Raider, 2=SCurrency, 3=Both | `refs/vtank/decompiled/bv.cs:88 [f]` | +| 79 | `OpenDoors` | bool | False | Navigation | Advanced Options list only (`lOptionList`, filter category Navigation) | `refs/vtank/decompiled/b7.cs:88 [k]` | +| 80 | `DoorIDRange` | double | 0.0833333333333333 | Ranges\|Navigation | Advanced Options list only (`lOptionList`, filter category Ranges\|Navigation) | `refs/vtank/decompiled/b7.cs:99 [i]` | +| 81 | `DoorOpenRange` | double | 0.0166666666666667 | Ranges\|Navigation | Advanced Options list only (`lOptionList`, filter category Ranges\|Navigation) | `refs/vtank/decompiled/b7.cs:138 [i]` | +| 82 | `DoorLockpickDiffExcessThreshold` | int | -50 | Navigation\|Crafting | Advanced Options list only (`lOptionList`, filter category Navigation\|Crafting) | `refs/vtank/decompiled/b7.cs:149 [j]` | +| 83 | `ManaChargesWhenOff` | bool | True | Misc | `cMChargesWhenOff` (Checkbox, tab "Options"): "M. Charges When Off" | `refs/vtank/decompiled/uTank2/PluginCore.cs:6768 [b]`; `refs/vtank/decompiled/uTank2/PluginCore.cs:7284 [k]` | +| 84 | `AutoFellowManagement` | bool | True | Misc | Advanced Options list only (`lOptionList`, filter category Misc) | `refs/vtank/decompiled/bf.cs:224 [k]`; `refs/vtank/decompiled/bf.cs:476 [k]`; `refs/vtank/decompiled/bf.cs:604 [k]` | +| 85 | `MinimumHealKitSuccessChance` | int | 95 | Recharge | Advanced Options list only (`lOptionList`, filter category Recharge) | `refs/vtank/decompiled/a5.cs:84 [j]` | +| 86 | `UseKitsInMagicMode` | bool | True | Recharge | Advanced Options list only (`lOptionList`, filter category Recharge) | `refs/vtank/decompiled/a5.cs:61 [k]` | +| 87 | `StaminaToHealthMultiplier` | double | 1.9 | Recharge | Advanced Options list only (`lOptionList`, filter category Recharge) | `refs/vtank/decompiled/dg.cs:104 [i]` | +| 88 | `ManaToHealthMultiplier` | double | 2.8 | Recharge | Advanced Options list only (`lOptionList`, filter category Recharge) | `refs/vtank/decompiled/dg.cs:108 [i]` | +| 89 | `NavPriorityBoost` | bool | False | Navigation | `cNavPriorityBoost` (Checkbox, tab "Options"): "Boost Nav. Priority" | `refs/vtank/decompiled/uTank2/PluginCore.cs:1567 [k]`; `refs/vtank/decompiled/uTank2/PluginCore.cs:1568 [b]`; `refs/vtank/decompiled/uTank2/PluginCore.cs:1581 [k]` | +| 90 | `DeleteGhostMonsters` | bool | True | Misc | Advanced Options list only (`lOptionList`, filter category Misc) | `refs/vtank/decompiled/b8.cs:114 [k]` | +| 91 | `GhostMonsterSpellAttemptCount` | int | 200 | Misc | Advanced Options list only (`lOptionList`, filter category Misc) | `refs/vtank/decompiled/b8.cs:111 [j]` | +| 92 | `WhoYouGonnaCall` | bool | True | Misc | Advanced Options list only (`lOptionList`, filter category Misc) | *(no direct f3 accessor call found — see notes / doc 02)* | +| 93 | `BlacklistMonsterAttemptCount` | int | 4 | Misc | Advanced Options list only (`lOptionList`, filter category Misc) | `refs/vtank/decompiled/fp.cs:79 [j]` | +| 94 | `BlacklistMonsterTimeoutSeconds` | int | 120 | Misc | Advanced Options list only (`lOptionList`, filter category Misc) | `refs/vtank/decompiled/fp.cs:96 [j]` | +| 95 | `CombineSalvage` | bool | True | Looting | Advanced Options list only (`lOptionList`, filter category Looting) | `refs/vtank/decompiled/c7.cs:207 [k]` | +| 96 | `LootOnlyRareCorpses` | bool | False | Looting | `cLootOnlyRareCorpses` (Checkbox, tab "Options"): "Loot Only Rare Corpses" | `refs/vtank/decompiled/fo.cs:403 [k]`; `refs/vtank/decompiled/uTank2/PluginCore.cs:6860 [b]`; `refs/vtank/decompiled/uTank2/PluginCore.cs:7289 [k]` | +| 97 | `DeleteGhostMonstersByHPTracker` | bool | True | Misc\|MeleeCombat\|SpellCombat | Advanced Options list only (`lOptionList`, filter category Misc\|MeleeCombat\|SpellCombat) | `refs/vtank/decompiled/b8.cs:79 [k]` | +| 98 | `GhostDeleteHPTrackerSeconds` | int | 30 | Misc\|MeleeCombat\|SpellCombat | Advanced Options list only (`lOptionList`, filter category Misc\|MeleeCombat\|SpellCombat) | `refs/vtank/decompiled/b8.cs:89 [j]`; `refs/vtank/decompiled/b8.cs:89 [j]` | +| 99 | `GoToPeaceModeToUseKits` | bool | False | Misc\|Recharge | Advanced Options list only (`lOptionList`, filter category Misc\|Recharge) | `refs/vtank/decompiled/a5.cs:121 [k]` | +| 100 | `UseRecklessness` | bool | True | MeleeCombat | Advanced Options list only (`lOptionList`, filter category MeleeCombat) | `refs/vtank/decompiled/hi.cs:663 [k]` | +| 101 | `DebuffPrecastSeconds` | int | 5 | SpellCombat | Advanced Options list only (`lOptionList`, filter category SpellCombat) | `refs/vtank/decompiled/dz.cs:579 [j]`; `refs/vtank/decompiled/hi.cs:111 [j]` | +| 102 | `ClearLevelBoostFlagOnCast` | bool | True | Recharge | Advanced Options list only (`lOptionList`, filter category Recharge) | `refs/vtank/decompiled/be.cs:168 [k]`; `refs/vtank/decompiled/be.cs:178 [k]`; `refs/vtank/decompiled/be.cs:188 [k]` | +| 103 | `IdleCraftCount_HealthKits` | int | 2 | Recharge\|Crafting | Advanced Options list only (`lOptionList`, filter category Recharge\|Crafting) | `refs/vtank/decompiled/a9.cs:88 [j]` | +| 104 | `IdleCraftCount_StamKits` | int | 2 | Recharge\|Crafting | Advanced Options list only (`lOptionList`, filter category Recharge\|Crafting) | `refs/vtank/decompiled/a9.cs:89 [j]` | +| 105 | `IdleCraftCount_ManaKits` | int | 2 | Recharge\|Crafting | Advanced Options list only (`lOptionList`, filter category Recharge\|Crafting) | `refs/vtank/decompiled/a9.cs:90 [j]` | +| 106 | `IdleCraftCount_HealthFood` | int | 15 | Recharge\|Crafting | Advanced Options list only (`lOptionList`, filter category Recharge\|Crafting) | `refs/vtank/decompiled/a9.cs:91 [j]` | +| 107 | `IdleCraftCount_StamFood` | int | 15 | Recharge\|Crafting | Advanced Options list only (`lOptionList`, filter category Recharge\|Crafting) | `refs/vtank/decompiled/a9.cs:92 [j]` | +| 108 | `IdleCraftCount_ManaFood` | int | 15 | Recharge\|Crafting | Advanced Options list only (`lOptionList`, filter category Recharge\|Crafting) | `refs/vtank/decompiled/a9.cs:93 [j]` | +| 109 | `BuffCastRecast_Seconds` | int | 30 | Buffing | Advanced Options list only (`lOptionList`, filter category Buffing) | `refs/vtank/decompiled/fz.cs:83 [j]`; `refs/vtank/decompiled/gw.cs:17 [j]` | +| 110 | `BuffCastRecastReset_Seconds` | int | 30 | Buffing | Advanced Options list only (`lOptionList`, filter category Buffing) | `refs/vtank/decompiled/fz.cs:118 [j]` | +| 111 | `EnableMeta` | bool | False | Misc | `c1EnableMeta` (Checkbox, tab "Options"): "Enable Meta" | `refs/vtank/decompiled/a7.cs:91 [k]`; `refs/vtank/decompiled/ao.cs:79 [b]`; `refs/vtank/decompiled/cp.cs:148 [b]` | +| 112 | `BlacklistedSpellComps` | string | "" | Recharge\|SpellCombat\|Buffing | Advanced Options list only (`lOptionList`, filter category Recharge\|SpellCombat\|Buffing) | `refs/vtank/decompiled/uTank2/MySpell.cs:403 [g]`; `refs/vtank/decompiled/uTank2/PluginCore.cs:7734 [g]`; `refs/vtank/decompiled/uTank2/PluginCore.cs:7749 [b]` | +| 113 | `DropToPeaceModeRetryCount` | int | 34 | Misc\|MeleeCombat\|SpellCombat | Advanced Options list only (`lOptionList`, filter category Misc\|MeleeCombat\|SpellCombat) | `refs/vtank/decompiled/ga.cs:1511 [j]` | +| 114 | `FollowAroundCorners` | bool | True | Navigation | Advanced Options list only (`lOptionList`, filter category Navigation) | `refs/vtank/decompiled/gl.cs:83 [k]`; `refs/vtank/decompiled/gl.cs:121 [k]`; `refs/vtank/decompiled/gl.cs:142 [k]` | +| 115 | `BlacklistCorpseOpenAttemptCount` | int | 30 | Misc\|Looting | Advanced Options list only (`lOptionList`, filter category Misc\|Looting) | `refs/vtank/decompiled/fo.cs:339 [j]` | +| 116 | `BlacklistCorpseOpenTimeoutSeconds` | int | 200 | Misc\|Looting | Advanced Options list only (`lOptionList`, filter category Misc\|Looting) | `refs/vtank/decompiled/fo.cs:349 [j]`; `refs/vtank/decompiled/fo.cs:393 [j]` | +| 117 | `SummonPets` | bool | True | MeleeCombat\|SpellCombat | `cSummonPets` (Checkbox, tab "Options"): "Summon Pets" | `refs/vtank/decompiled/h1.cs:36 [k]`; `refs/vtank/decompiled/uTank2/PluginCore.cs:6848 [b]`; `refs/vtank/decompiled/uTank2/PluginCore.cs:7290 [k]` | +| 118 | `PetRangeMode` | enum | 0 | MeleeCombat\|SpellCombat\|Ranges | Advanced Options list only (`lOptionList`, filter category MeleeCombat\|SpellCombat\|Ranges) Enum: 0=AttackDistance, 1=PetCustomRange | `refs/vtank/decompiled/ga.cs:1081 [f]`; `refs/vtank/decompiled/uTank2/PluginCore.cs:6831 [b]`; `refs/vtank/decompiled/uTank2/PluginCore.cs:6835 [b]` | +| 119 | `PetCustomRange` | double | 0.0208333333333333 | MeleeCombat\|SpellCombat\|Ranges | `txtCustomPetRange` (Edit, tab "Options"): "" | `refs/vtank/decompiled/ga.cs:1083 [i]`; `refs/vtank/decompiled/uTank2/PluginCore.cs:6814 [i]`; `refs/vtank/decompiled/uTank2/PluginCore.cs:6816 [b]` | +| 120 | `PetRefillCount-Idle` | int | 3 | MeleeCombat\|SpellCombat | Advanced Options list only (`lOptionList`, filter category MeleeCombat\|SpellCombat) | *(no direct f3 accessor call found — see notes / doc 02)* | +| 121 | `PetRefillCount-Normal` | int | 1 | MeleeCombat\|SpellCombat | Advanced Options list only (`lOptionList`, filter category MeleeCombat\|SpellCombat) | *(no direct f3 accessor call found — see notes / doc 02)* | +| 122 | `CorpseOpenTimeoutSeconds` | double | 1.5 | Looting | Advanced Options list only (`lOptionList`, filter category Looting) | `refs/vtank/decompiled/bj.cs:109 [i]` | +| 123 | `PetMonsterDensity` | int | 1 | MeleeCombat\|SpellCombat | `txtPetDensity` (Edit, tab "Options"): "" | `refs/vtank/decompiled/ga.cs:1086 [j]`; `refs/vtank/decompiled/uTank2/PluginCore.cs:6799 [j]`; `refs/vtank/decompiled/uTank2/PluginCore.cs:6801 [b]` | +| 124 | `CorpseLootItemMaxAttempts` | int | 20 | Looting | Advanced Options list only (`lOptionList`, filter category Looting) | `refs/vtank/decompiled/hv.cs:379 [j]` | +| 125 | `FastCastBuffs` | bool | False | Buffing | `cFastCast` (Checkbox, tab "Options"): "Fastcast Buffs" | `refs/vtank/decompiled/gj.cs:171 [k]`; `refs/vtank/decompiled/uTank2/PluginCore.cs:6687 [b]`; `refs/vtank/decompiled/uTank2/PluginCore.cs:7279 [k]` | +| 126 | `UseBreakableTurnTo` | bool | True | SpellCombat | Advanced Options list only (`lOptionList`, filter category SpellCombat) | `refs/vtank/decompiled/gj.cs:505 [k]` | +| 127 | `UseProjectileAwareness` | bool | True | MeleeCombat\|SpellCombat | `cCollisionChecks` (Checkbox, tab "Options"): "Don't Shoot at Walls" | `refs/vtank/decompiled/cz.cs:122 [k]`; `refs/vtank/decompiled/dz.cs:676 [k]`; `refs/vtank/decompiled/uTank2/PluginCore.cs:6699 [b]` | +| 128 | `CollisionProjectileRadius` | double | 0.4 | MeleeCombat\|SpellCombat | Advanced Options list only (`lOptionList`, filter category MeleeCombat\|SpellCombat) | `refs/vtank/decompiled/cz.cs:164 [i]` | +| 129 | `CollisionStepDistance` | double | 0.7 | MeleeCombat\|SpellCombat | Advanced Options list only (`lOptionList`, filter category MeleeCombat\|SpellCombat) | `refs/vtank/decompiled/cz.cs:165 [i]` | +| 130 | `ShowCollisionDebug` | bool | False | MeleeCombat\|SpellCombat | Advanced Options list only (`lOptionList`, filter category MeleeCombat\|SpellCombat) | `refs/vtank/decompiled/cz.cs:166 [k]` | +| 131 | `MaximumCollisionChecksPerTick` | int | 500 | MeleeCombat\|SpellCombat | Advanced Options list only (`lOptionList`, filter category MeleeCombat\|SpellCombat) | `refs/vtank/decompiled/dz.cs:676 [j]` | +| 132 | `SpellRangeFudge` | double | 1 | SpellCombat | Advanced Options list only (`lOptionList`, filter category SpellCombat) | `refs/vtank/decompiled/uTank2/MySpell.cs:351 [i]` | +| 133 | `BuffWithUntrained-Item` | int | 80 | Buffing | Advanced Options list only (`lOptionList`, filter category Buffing) | `refs/vtank/decompiled/eq.cs:199 [j]`; `refs/vtank/decompiled/eq.cs:242 [j]` | +| 134 | `BuffWithUntrained-Creature` | int | 80 | Buffing | Advanced Options list only (`lOptionList`, filter category Buffing) | `refs/vtank/decompiled/eq.cs:211 [j]` | +| 135 | `BuffWithUntrained-Life` | int | 80 | Buffing | Advanced Options list only (`lOptionList`, filter category Buffing) | `refs/vtank/decompiled/eq.cs:223 [j]` | +| 136 | `AllowDebuffFallback` | bool | False | MeleeCombat\|SpellCombat | `cDebuffFallback` (Checkbox, tab "Options"): "Fallback Debuffs if Blocked" | `refs/vtank/decompiled/dz.cs:234 [k]`; `refs/vtank/decompiled/hi.cs:369 [k]`; `refs/vtank/decompiled/uTank2/PluginCore.cs:6711 [b]` | +| 137 | `RechargeHandlerSet` | custom(table) | (nested table — 5 columns `Vital`/`HandlerString`/`MinPercent`/`MaxPercent`/`Stance`, 24 seed rows; see prose) | *(none)* | **Not exposed** by the generic Advanced Options editor — `tCustom` has no case in its display/edit switch (`refs/vtank/decompiled/db.cs:118-165`) and no case in `/vt opt set` either (`refs/vtank/decompiled/uTank2/PluginCore.cs:5567-5610`). Owned by a dedicated `cRechargeManager` object (`refs/vtank/decompiled/s.cs:83`), not by any control found in `mainView.xml`/`AdvancedOptionsView.xml`. See "Could not determine". | `refs/vtank/decompiled/da.cs:659 [a]`; `refs/vtank/decompiled/da.cs:685 [e]` | + +Where "Primary consumer" shows *(no direct f3 accessor call found)*, the +setting's only reference found was inside `cLogic.cs`'s scheduler-rule +registration (`AddLogicRule(new (priority, "SettingName", ...))`) +— the rule class itself reads the setting through its own indirection at +runtime. That indirection is scheduler-and-actions territory (doc 02), not +this settings doc; `WhoYouGonnaCall` is the one name with **no** reference +anywhere outside the `.usd` files themselves — see "Could not determine". + +## 3. The `.usd`/`.ast` file format, locations, naming, and versioning + +**Format**: exactly the `y` database grammar from section 1 — plain text, +CRLF line endings (confirmed on-disk: `refs/vtank` sources and the live +`.usd`/`.ast` files under `C:\Games\VirindiPlugins\VirindiTank\` both use +`\r\n`), no compression, no checksum, no version header of its own (the +version discipline lives inside individual tables — see below). + +**Directory and path source**: the profile folder (referenced everywhere as +`PluginCore.dq`, declared at `refs/vtank/decompiled/uTank2/PluginCore.cs:921`) +is **not hardcoded** — it is read once from the Windows registry: +`Registry.LocalMachine.OpenSubKey("Software\Decal\Plugins\{642F1F48-16BE-48BF-B1D4-286652C4533E}").GetValue("ProfilePath")` +(`uTank2/PluginCore.cs:4052`). On the user's machine this currently resolves +to `C:\Games\VirindiPlugins\VirindiTank\`, confirmed by directory listing +(read-only inspection performed for this doc). **Linux-portability note**: +this registry dependency cannot be ported as-is (no Windows registry, no +Decal); MossTank must choose its own directory-discovery mechanism (an env +var, an XDG-style config dir, or a user-set path) while keeping the `.usd` +**file format** byte-for-byte compatible so existing profiles remain +loadable. This is an explicit design decision doc 02+/VT2 needs to make, not +something the decompile answers. + +**Per-character binding file — the `.cdf`**: one file per character, +`Path.Combine(dq, Server + "_" + CharacterName + ".cdf")` +(`refs/vtank/decompiled/da.cs:110`, read in `da.e()` at `da.cs:105-154`, +written in `da.q()` at `da.cs:156-164`). Format: line 1 is the literal +version header `"uTank2 CDF 1.0"` (`da.cs:15`); if that doesn't match, the +`.cdf` is treated as absent/corrupt and every profile resets to that +character's auto-created per-character defaults (`da.cs:113-121`). Lines +2–4 are the three profile filenames currently assigned to this character: +settings (`.usd`), loot (extension varies — see below), nav (`.nav`); an +optional line 5 (present only if `!streamReader.EndOfStream`, +`da.cs:125-128`) carries the meta (`.met`) filename, handled by a different +owner (`PluginCore.dz.at`, not `da` itself). **Backward-compat rewrite**: if +the settings filename read from line 2 ends in the legacy extension `.uts`, +`da.e()` silently rewrites it in memory to the same basename with `.usd` +(`da.cs:130-141`) before use — see the `.uts`→`.usd` one-time file migration +below. + +**Auto per-character profile names** (the "[By char]" entries in every +profile combo box): built as `"--" + CharacterName + "_" + Server + ".usd"` +/ `.nav` / `.met` (`refs/vtank/decompiled/uTank2/PluginCore.cs:3863-3865`), +stored on `da.o`/`da.p`/`da.q` (`da.cs:43`, `da.cs:45`, `da.cs:47` — the +loot default has no equivalent auto-name; loot profiles default to none). +Confirmed against the live directory: files named exactly +`--_.usd/.met/.nav` exist (read-only inspection). + +**The `--` prefix — reserved, per-character**: any profile filename whose +first two characters are `"--"` is hidden from the normal (cross-character) +profile picker (`uTank2/PluginCore.cs:7020,7072,7144`, etc.) *unless* it +additionally starts with that character's own prefix +`"--" + Name + "_" + Server + "_"` (trailing underscore — a **different**, +longer prefix than the single auto-file name above, stored in the field +`dw`, `uTank2/PluginCore.cs:933,3866`), in which case it is shown specially +as `"[Char] "` with the `--Name_Server_` prefix and the extension +stripped (`uTank2/PluginCore.cs:7016-7046` builds the display name; +`uTank2/PluginCore.cs:7060-7112` is the equivalent list-population pass). +This is confirmed live: `--Barris_Coldeve_Base.usd`, +`--Barris_Coldeve_Blank.usd`, `--Barris_Coldeve_viridian.usd` etc. are all +named per-character sub-profiles for the character "Barris" on server +"Coldeve", distinct from that character's single default +`--Barris_Coldeve.usd`. A profile whose name starts with `"--"` but does +**not** match the current character's own `dw` prefix belongs to a +*different* character and is invisible to this one. + +Nav profiles additionally hide any file starting with `"~~"` +(`uTank2/PluginCore.cs:7182`) — a third reserved prefix whose purpose was +not determined from the settings/profile code path examined (see "Could not +determine"). + +**Profile listing and selection UI** (`refs/vtank/decompiled/uTank2/PluginCore.cs`): +four near-identical list-builder methods populate the four combo boxes — +`a0()` (settings, `cmbSettingsSet`, lines 7057-7115) always seeds +`"[Default]"` and `"[By char]"` first, then every non-`--` `*.usd` file +(filtered to only the currently-selected one when the "Mine only" checkbox +`cSettingsShowAll`/field `a9` is checked, `7020-7024`) plus every +`dw`-matching `"[Char] "`-labeled file; `aa()` (loot, `cmbLootSet`, +lines 7127-7154) seeds only `"[None]"` and lists **every** non-`--` file +across all of `dz.ah.a()`'s loot-profile extensions with no "mine only" +filter and no `"[By char]"` option; `l()` (nav, `cmbNavSet`, lines +7156-7185) seeds `"[None]"`/`"[By char]"` and filters out both `--` and +`~~`; `ac()` (meta, `cmbMetaSet`, lines 7187+) seeds `"[None]"`/`"[By char]"` +and filters only `--`. **Loot profiles are structurally the odd one out**: +no auto per-character file, no "mine only" filtering, and (per Classic +Looter's own file format — out of scope for this doc, see doc 05) a +different file extension family, not `.usd`. + +**`.uts`→`.usd` one-time migration** (`da.g()`, `refs/vtank/decompiled/da.cs:688-780`): +on every profile-load pass, VTank scans the profile directory for `*.uts` +files (the pre-0.2.1 flat line-by-line settings format, header +`"uTank2 SCF 1.06"`, `da.cs:690`), and for each one: loads defaults from the +**template** resource (`da.c.c(this.e)`, i.e. `defaultsettingstemplate.usd`, +not `defaultsettings.usd`), reads roughly 25 fixed fields by position +(`Convert.ToBoolean`/`ToDouble`/`ToInt32`/`ToSingle` in a fixed order, +`da.cs:707-732`), then a variable-length gem/food and assist-items block, +then hands off to another owner for spell-book-derived data +(`PluginCore.dz.e`, `da.cs:749-759`), writes the result as `.usd` +(`da.cs:763`), and renames the old `.uts` to `.uts.bak` +(`da.cs:765`). This is legacy/historical and is unlikely to matter for +drop-in compatibility today (no live `.uts` files were found in the +inspected directory) — noted for completeness since the task calls for the +format "exactly as VTank reads and writes it," including old formats it +still tolerates. + +**Grid-shaped setting schema migration** (`da.k()`, +`refs/vtank/decompiled/da.cs:259-367` — the settings-profile loader): +after loading a `.usd` file's `Settings`/`MyMonsters`/etc. tables, VTank +checks the **column count** of the loaded `MyMonsters` table +(`this.c["MyMonsters"].d()`) against ten hardcoded thresholds +(`da.cs:280-323`) and appends a new column with a hardcoded default value +for every column added by a newer build than the one that saved the file +(e.g. `if (...).d() <= 16) { ...a("Corrosion", gy.a(false)); }` at +`da.cs:304-307`) — this is VTank's explicit unknown-schema/versioning +strategy for **table**-shaped settings (as opposed to the silent +default-database fallback used for scalar settings in section 1). The same +method also adds three whole tables outright if missing +(`ExtraBuffSpells`, `AntiExtraBuffSpells`, `ItemUseSpecifiers`, +`da.cs:324-336`) — i.e., **whole-table addition uses `ContainsKey`, per-column +addition uses a row-count-like column-count threshold; neither uses an +explicit schema-version field.** If the `.usd` file fails to parse at all, +`da.k()` falls back to the **template** resource and immediately overwrites +the file on disk with defaults (`da.cs:347-358`) — a corrupt/foreign `.usd` +is silently replaced, not preserved or backed up. + +**`defaultsettings.usd` vs `defaultsettingstemplate.usd`**: both share the +identical 10-table/137-setting schema; `defaultsettings.usd` (2270 lines) +additionally seeds real starter content in the grid tables (`GemFoodItems` +has 2 rows: "Asheron's Benediction"→spell 3810, "Blackmoor's Favor"→spell +3811; `MyMonsters` has 1 row, the `` monster rule) while +`defaultsettingstemplate.usd` (141 lines) ships the same tables **empty**. +`defaultsettings.usd` is the built-in fallback database (`da.b`, never +written to disk on its own); `defaultsettingstemplate.usd` is what a brand +new (or unparseable) profile is seeded from (`da.f()`, +`refs/vtank/decompiled/da.cs:592-610`, and `da.k()`'s failure path above). + +**`.ast` — a related but distinct per-character cache**: same `y` database +grammar, but no `"--"` prefix and not user-selectable — always exactly +`CharacterName + "_" + Server + ".ast"` +(`refs/vtank/decompiled/dm.cs:391`, class `dm`). Live inspection of +`+Horan_sawato.ast` (65 bytes) shows one table, `Spells`, four columns +(`SpellID`, `EndTime`, `Target`, `CastTime`), zero rows in the sample +inspected. `dm.g()` (`dm.cs:389-399`) falls back to seeding from the +embedded `defaultitemagedb.ugd` resource if the file is missing or +corrupt. This looks like a per-character cast/assist-tracking cache +(tracking spell durations placed on other players) rather than a settings +profile; its exact runtime semantics were not traced further as out of +scope for this document. + +## 4. `/vt opt` and other settings commands + +`refs/vtank/decompiled/uTank2/PluginCore.cs:5446-5610` (inside the `/vt ` +chat-command dispatcher — the surrounding `if` chain is a long +`text.CompareTo(...)`/`text.StartsWith(...)` ladder over the text after the +`/vt ` prefix): + +| Command | Grammar | Behavior | Error text | +|---|---|---|---| +| `/vt opt` (no args) | `opt` | prints usage | `"Usage: /vt opt [list/get/set/setinall]"` (`:5450`) | +| `/vt opt list` | `opt list` | prints `"Available options: (" + + ")"` then every `Settings` row's name from the **built-in defaults** table (`dz.m.b["Settings"]`, not the loaded profile), four per line, `" "`-indented (`:5518-5538`) | `"Usage: /vt opt list"` if extra args (`:5514`) | +| `/vt opt get ` | `opt get X` | prints `"Option " + name + " = " + f3.e(name)"` via the raw `gy.ToString()` (`:5539-5556`) | `"Option get: Invalid option specified."` if the name isn't found (`:5553`); `"Usage: /vt opt get [option name]"` for wrong arg count (`:5543`) | +| `/vt opt set ` | `opt set X V` | looks up the name's declared type in the **built-in defaults** table, converts `V` to that CLR type (`double`/`int`/`float`/`string`/`bool` — note **no case for a `tCustom` value**, so `RechargeHandlerSet` cannot be set this way), then calls `f3.b(name, gy)` (persists + refreshes) (`:5560-5602`) | `"Option set: Invalid option specified."` if name not found; `"Option set: Invalid value specified. Proper type of " + name + " is " + type + "."` on conversion failure or unrecognized type; `"Usage: /vt opt set [option name] [option value]"` for wrong arg count | +| `/vt opt setinall ` | `opt setinall X V` | same type resolution as `set`, but writes through `global::bk.a(name, gy)` instead of `f3.b` (`:5457-5498`) — `bk` was not traced further in this pass; likely writes to every loaded profile database rather than just the current one, but that inference is **not confirmed** from code read so far | `"Usage: /vt opt setinall [option name] [option value]"` if arg count != 4 (`:5462`) | +| *(default)* | any other `opt ` | | `"Usage: /vt opt [list/get/set]"` (`:5606`) — note this usage string omits `setinall` even though it is a real, dispatched subcommand | + +The exact same `/vt` ladder also contains many non-settings debug commands +(`dumptracker`, `deletemonster`, `getdb`, `obtest`, `nav save/load`, …, +`uTank2/PluginCore.cs:5401-5445,5610+`) that are out of scope for this +document (see doc 09 for the full command catalogue). + +## 5. MossTank gap analysis + +`src/AcDream.Plugins.MossTank/` already has a **large amount of real parity** +with VTank's setting *names* and *defaults* — this is a materially different +starting point than "MossTank has nothing." Evidence: + +- `VtankOptionCatalog.Names` (`src/AcDream.Plugins.MossTank/VtankOptionCatalog.cs:9-`) + is an exact, order-preserved copy of all 137 `.usd` `Settings` row names. +- `MossTankPanel.SetMetaOption` (`src/AcDream.Plugins.MossTank/MossTankPanel.cs:2788-3372`) + has a `case` for the **lowercased form of every one of the 137 VTank + setting names**, confirmed by an exhaustive diff (137/137 matched; 0 + missing) run for this document. +- `CombatSettings`/`BuffSettings` (`BuffPlan.cs`)/`VitalSettings` (`VitalPlan.cs`)/ + `InventoryProfileDocument` (`MossTankProfileStore.cs`) carry live fields for + the great majority of those names, frequently with the exact VTank default + value and a doc comment citing the VTank setting name. + +That said, real gaps and divergences were found: + +1. **No `.usd` file compatibility at all.** MossTank persists profiles as + JSON via `_host.Storage` (`MossTankProfileStore.cs:279-311`), not as the + `y`/`bd`/`cw`/`gy` grammar in section 1. `MossTankCommands.cs:236` + strips a `".usd"`/`".settings"` suffix from a **profile name argument** + purely for display/matching — no code anywhere in + `src/AcDream.Plugins.MossTank/` opens or parses an actual `.usd` file + (confirmed by grep: every `.usd` reference in the plugin's source is a + code comment citing VTank's own defaults file as the source of a ported + constant, e.g. `InventoryMaintenance.cs:8`, `Looting.cs:81`, + `VitalPlan.cs:28`, `VtankOptionCatalog.cs:5`). **A real, unmodified + VTank `.usd` profile cannot be loaded by MossTank today.** This is the + headline gap the campaign plan (VT2/VT3) already flags as the + first-priority slice. +2. **`BuffProfileDocument` (the JSON persistence record, + `MossTankProfileStore.cs:807-856`) does not round-trip several fields + that the live `BuffSettings` model (`BuffPlan.cs`) actually has and that + `SetMetaOption` actually writes.** Confirmed missing from both + `Capture()` and `Apply()`: `BuffCastRecastSeconds`, + `BuffCastRecastResetSeconds`, `FastCastBuffs`, `RandomHelperBuffs`, + `RandomHelperIntervalSeconds`, `BlacklistedSpellComponents`, + `ProtectionElements`, `ProtectionProfileMode`, `BaneElements`, + `BaneProfileMode` — i.e. VTank's `BuffCastRecast_Seconds`, + `BuffCastRecastReset_Seconds`, `FastCastBuffs`, `RandomHelperBuffs`, + `RandomHelperIntervalSeconds`, `BlacklistedSpellComps`, + `BuffProfile-Prots`, `BuffProfile_Prots`, `BuffProfile-Banes`, + `BuffProfile_Banes` are all settable at runtime + (`MossTankPanel.cs:2942-2973,3297-3317`) but **silently reset to the + class defaults on the next save/load round-trip** because the + persistence record never captures them. This reads as an oversight (the + fields were added to `BuffSettings` and to `SetMetaOption` but the + corresponding `BuffProfileDocument` fields were never added), not an + intentional design choice. +3. **`RechargeHandlerSet` is accepted only as an opaque string.** + `MossTankPanel.cs:3368-3370` stores whatever text is given verbatim into + `_vitalSettings.RechargeHandlerSet` with no parsing into VTank's real + 5-column `Vital`/`HandlerString`/`MinPercent`/`MaxPercent`/`Stance` + structure (section 2, row 137), and the actual recharge-priority + *behavior* MossTank runs is a hand-ported, hardcoded replica of VTank's + **default** table baked into `VitalRechargePlanner` + (`VitalRecharge.cs:33-` — its own doc comment says exactly this: "VTank's + default `RechargeHandlerSet`, including its stance- and + current-percentage-dependent order"). A user who customized their + RechargeHandlerSet table in real VTank has no way to bring that + customization into MossTank today, and `_vitalSettings.RechargeHandlerSet` + does not appear to be read back by `VitalRechargePlanner` at all (not + fully confirmed — would need a full read of `VitalRecharge.cs`, which + this doc's scope did not require). +4. **Buff classification model is architecturally different, not just + incomplete.** VTank's `BuffProfile_Prots`/`BuffProfile_Banes` are an + 8-way named enum (`Custom`/`All`/`None`/`B`/`BPS`/`BPSA`/`ALFC`/`BPSAC`, + section 2 rows 61-62) whose letters index into **fixed, hardcoded lists + of specific spell families** (not decompiled further in this pass — + doc 04's scope). MossTank instead classifies buffs at runtime from each + spell's own English description text (`BuffProfile.cs:1-70`, matching + phrases like "Increases the caster's ... skill by"), producing a + `BuffTargetKind` (`Skill`/`Attribute`/`Protection`/`Aura`/`Bane`/ + `Regeneration`/`Other`) and exposing coarser boolean toggles + (`BuffProtections`, `BuffBanes`, etc., `MossTankProfileStore.cs:807-815`) + rather than VTank's letter-coded profile modes. MossTank *does* also + carry the exact VTank enum fields (`ProtectionProfileMode`/ + `BaneProfileMode`, gap #2 above) alongside the coarse booleans, so the + two models currently coexist rather than one replacing the other — this + needs an explicit design decision (which model is authoritative) before + a `.usd`-compatible profile with a non-default `BuffProfile_Prots` value + can be faithfully honored. +5. **No character/profile-selection machinery matching VTank's file-naming + scheme.** `MossTankProfileStore.ProfileIndex`/`ProfileEntry` + (`MossTankProfileStore.cs:320-333`) has its own `Owner` and + `SelectedByCharacter` fields — a real analogue exists — but it has + no equivalent to VTank's `"--"`-prefix / `"[By char]"` / + `dw`-prefixed-named-sub-profile scheme (section 3). Because MossTank + doesn't read the filesystem for profiles at all (gap #1), there is + currently no way for it to see, list, or select among a real character's + existing `--Name_Server*.usd` files from `C:\Games\VirindiPlugins\VirindiTank\`. +6. **Minor naming difference, not a functional gap**: VTank's setting is + `BlacklistedSpellComps`; `CombatSettings.BlacklistedSpellComponents` + (`CombatSettings.cs:106`) and `BuffSettings.BlacklistedSpellComponents` + (`BuffPlan.cs:26`) spell the field out in full. `SetMetaOption`'s case + label is still the exact VTank string (`"blacklistedspellcomps"`, + `MossTankPanel.cs:3305`), so external-facing compatibility (`/vt`-style + commands, once implemented) is unaffected — only the internal C# field + name differs. + +No settings were found present in the `.usd` schema but entirely absent from +MossTank's `SetMetaOption` table (0/137 missing by name, confirmed by +programmatic diff) — the gaps here are all about **persistence fidelity**, +**file-format compatibility**, and **one architecturally-coarser model** +(buff profiles), not missing setting coverage. + +## 6. Could not determine + +- **The exact runtime semantics of `global::bk.a(name, gy)`** used by + `/vt opt setinall` (`uTank2/PluginCore.cs:5488`) — presumably "set this + value in every loaded profile database," inferred from the command name + and the fact it bypasses `f3.b`/`f3.a`, but `bk.cs` was not read in this + pass to confirm. +- **The `"~~"` filename prefix** filtered out of the nav-profile list + alongside `"--"` (`uTank2/PluginCore.cs:7182`) — no assignment or + producer of a `"~~"`-prefixed file was found in the code paths read for + this document; possibly an auto-backup or in-progress-save marker used + elsewhere in the nav system (doc 06's scope). +- **Whether `RechargeHandlerSet` has *any* live UI editor at all.** No + control in `mainView.xml` or `AdvancedOptionsView.xml` matches (no + `lstRecharge`-style list), and both `/vt opt set` and the generic + Advanced Options editor explicitly exclude `tCustom` values (section 2, + row 137). It's owned by a dedicated `cRechargeManager` object + (`refs/vtank/decompiled/s.cs:83`) which may have its own popup view not + captured among the four `.xml` resources extracted at VT0, or may simply + be defaults-only in the shipped build. Not resolved in this pass. +- **Whether `MossTankProfileStore`'s `ProfileIndex.SelectedByCharacter` + already covers the "[By char]" semantics conceptually** (as opposed to + file-naming) — a fuller read of `MossTankProfileStore.cs`'s selection + logic (lines outside the ranges read for this document) would be needed + to say whether gap #5 is "needs new code" or "needs a new file-backed + adapter over existing logic." +- **Whether `_vitalSettings.RechargeHandlerSet` (the opaque string, + MossTank gap #3) is read by anything at all**, or is a write-only field + today. `VitalRecharge.cs` was read only through its top ~60 lines for + this document.