docs(vt): fold the citation-pass corrections into KB 02 (ga.a line map, gj/gs identity, fd.cs IdlePeace gate scope, VitalPlan.Threshold branch, entry counts)
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
parent
1b81836747
commit
887242cd15
1 changed files with 32 additions and 32 deletions
|
|
@ -66,8 +66,8 @@ ey.b()`) — i.e. it coalesces multiple timer/event firings within the same
|
|||
render frame into one pass.
|
||||
|
||||
`SchedulePoke()` (`cLogic.cs:154-161`) is the fast-wake path: two Decal
|
||||
game-state trackers, `gj` (spell-cast completion, `gj.cs`) and `gs`
|
||||
(attack/missile completion, `gs.cs`), each fire a `b`-enum "completed/idle"
|
||||
game-state trackers, `gj` (the SpellCaster cast-completion tracker, `gj.cs:269,326,442`) and `gs`
|
||||
(the WandCaster cast-completion tracker, `gs.cs:178,194,233,442` — NOT attack/missile completion; citation pass 2026-09-06), each fire a `b`-enum "completed/idle"
|
||||
event that `cLogic` subscribes to (`cLogic.cs:52-59, 125-139`); on that
|
||||
event `SchedulePoke()` stamps the dedup counter to the *current* frame and
|
||||
re-arms `f` for **1 ms**, forcing a near-immediate re-poke on the very
|
||||
|
|
@ -121,7 +121,7 @@ is the actual pass, called as `a(l, n)` from `TryPokeMacro` and as
|
|||
(in the second case) immediately calls `StopMacro()` on itself.
|
||||
- Sets `dz.o.c = true` (the single "is the macro running" flag almost
|
||||
every `ValidNow`/`Running` body reads), clears the loot-wait table
|
||||
(`dz.o.j`), resets the equip-retry counter (`dz.o.r = 0`), clears every
|
||||
(`dz.o.l()` and `dz.o.k()`, `cLogic.cs:319,321` — the field letter `j` in the first draft was wrong), resets the equip-retry counter (`dz.o.r = 0`), clears every
|
||||
`ActionLockType` cooldown (`dz.o.n.b()`), resets Meta, arms the 293 ms
|
||||
timer and starts it, disables every item in the macro-disabled Always
|
||||
Rules list `m` (they're only meaningful while stopped — see §1.1), and
|
||||
|
|
@ -155,7 +155,7 @@ lock-target-requested, corpse-open-attempt, recharge-level-boost per
|
|||
vital, random-helper-buff-lock, buff-cast-recast) — see the "Suppressors"
|
||||
column in §2. `ga.a(CombatState,...)` (the shared wield/mode gate, §3)
|
||||
also returns `false` outright whenever `Actions.BusyState != 0`
|
||||
(`ga.cs:1454-1458`), which starves every rule that routes through it
|
||||
(`ga.cs:1448-1451`), which starves every rule that routes through it
|
||||
(BuffSelf, DispelSelf, DispelAllies, RechargeOther, UseHealersHeart,
|
||||
RandomHelper, Attack's own wield step) for that tick without any explicit
|
||||
"paused" bookkeeping.
|
||||
|
|
@ -190,7 +190,7 @@ VTank schedules rules on two separate tracks:
|
|||
|
||||
### 2.2 Main-track priority order
|
||||
|
||||
All 39 entries of `l`, in the exact order `InitializeDefaultLogicRules`
|
||||
All 66 entries of `l`, in the exact order `InitializeDefaultLogicRules`
|
||||
(`cLogic.cs:433-578`) adds them. Sentinel rows are markers only (their
|
||||
`ValidNow` is hard-coded `false`, `LogicRuleSentinel.cs:11`); they never
|
||||
win, but their names are the section headers VTank's own debug UI/log
|
||||
|
|
@ -487,38 +487,38 @@ near-identical body to `cr`, including its own copy of the stuck-combat-
|
|||
state handling for level-boost spells. No `new be(` appears anywhere in
|
||||
the decompiled tree — it is superseded, unreachable code, not a rule any
|
||||
current VTank build ever runs. Flagged here so it is not mistaken for a
|
||||
27th live rule.
|
||||
25th live rule.
|
||||
|
||||
---
|
||||
|
||||
## 3. Combat-mode and equipment sequencing
|
||||
|
||||
### 3.1 The shared gate: `ga.a(CombatState, int, bool, eDamageElement,
|
||||
ePrismaticDamageBehavior, int)` (`ga.cs:1421-1568`)
|
||||
ePrismaticDamageBehavior, int)` (`ga.cs:1433-1573`)
|
||||
|
||||
Every rule that needs to cast a buff/heal/recharge/dispel spell — BuffSelf,
|
||||
DispelSelf, DispelAllies, RechargeOther, UseHealersHeart, RandomHelper —
|
||||
calls through this **one** subroutine (via an overload chain,
|
||||
`ga.cs:1417-1447`) instead of switching mode itself. Per call:
|
||||
`ga.cs:1415-1431`) instead of switching mode itself. Per call:
|
||||
|
||||
1. **Busy check.** If `Actions.BusyState != 0`, return `false`
|
||||
immediately — `ga.cs:1454-1458`.
|
||||
immediately — `ga.cs:1448-1451`.
|
||||
2. **Resolve the primary item to wield.**
|
||||
- Start from the explicit override `A_1` (an item id), if the caller
|
||||
passed one, and validate it's owned by the player and currently
|
||||
wieldable (`b(WorldFilter[num])`); if invalid, fall back to `0` and
|
||||
log a warning — `ga.cs:1459-1470`.
|
||||
log a warning — `ga.cs:1452-1461`.
|
||||
- **Prefer whatever is already wielded**: if auto-select is on (`A_2`)
|
||||
or no override was given, *and* something is already wielded whose
|
||||
weapon-class already maps to the requested `CombatState` (via
|
||||
`a(ObjectClass)`, `ga.cs:1573-1607`), keep using that item instead of
|
||||
switching — `ga.cs:1471-1475`.
|
||||
switching — `ga.cs:1462-1465`.
|
||||
- Otherwise, call the private `a()` helper (`ga.cs:1398-1411`): scan
|
||||
`dz.k.j()` (a tracked item-id list — see §0; **its population order
|
||||
is not established from this file alone**, see §6) for the first
|
||||
owned item classified `fi.b` ("is a wand"); if none, post **"You
|
||||
must add at least one wand to your profile."**, `StopMacro()`, return
|
||||
`false` — `ga.cs:1477-1481`.
|
||||
`false` — `ga.cs:1466-1475` (message at 1471).
|
||||
3. **Resolve a secondary/held item** the same way (`A_5`), and whether a
|
||||
spell/element re-selection is needed (`bv.a(...)`, an
|
||||
element/prismatic-compatibility check) — `ga.cs:1482-1499`.
|
||||
|
|
@ -536,8 +536,8 @@ calls through this **one** subroutine (via an overload chain,
|
|||
- Once in Peace mode (`r` reset to 0, `ga.cs:1527`): if the target item
|
||||
is a wand type (`fi.h`) *and* a secondary must also change, unequip
|
||||
the current primary first if one is worn, else equip the secondary
|
||||
— `ga.cs:1528-1547`; else if the primary itself needs to change,
|
||||
equip it — `ga.cs:1548-1551`; else if only the spell/element
|
||||
— `ga.cs:1530-1539`; else if the primary itself needs to change,
|
||||
equip it — `ga.cs:1540-1544`; else if only the spell/element
|
||||
selection needs updating, do that (`bv.a()`) — `ga.cs:1552-1554`.
|
||||
- Any of the above branches returns `false` for this tick — the wield
|
||||
step always costs at least one extra tick before it can report ready.
|
||||
|
|
@ -550,7 +550,7 @@ calls through this **one** subroutine (via an overload chain,
|
|||
cast/use inside their own `if (ga.a(...)) { ... }` branch — see e.g.
|
||||
`c8.cs:114-121`, `af.cs:185-189`, `ba.cs:152-156`.
|
||||
|
||||
`ga.a(ObjectClass)` (`ga.cs:1573-1607`) is the class→mode map:
|
||||
`ga.a(ObjectClass)` (`ga.cs:1581-1613`) is the class→mode map:
|
||||
`MeleeWeapon → Melee(2)`, class `9` (missile launcher) `→ Missile(4)`,
|
||||
class `31` and everything else `→ Magic(8)` (the default).
|
||||
|
||||
|
|
@ -565,12 +565,10 @@ back to the first `fi.b`-classified item found while scanning `dz.k.j()`
|
|||
verification 2026-09-06): `eq.j()` (`eq.cs:83-94`) walks `m_e` in list
|
||||
order and emits each distinct item id (skipping `-1` and self); `m_e` is
|
||||
appended by `eq.a(c)` (`eq.cs:54-57`, a plain `List.Add`), whose only
|
||||
producers are the Items-tab Add buttons — `PluginCore.cs:8422-8434`
|
||||
producers are the Items-tab Add buttons — `PluginCore.cs:8348-8434` (five switch cases)
|
||||
(`dz.k.a(new eq.c(item, spell))`, one row per element for "Add", a single
|
||||
`-1`-spell row for "Add (no buffs)") — and the profile loader. So the
|
||||
first wand a player added is the fallback caster. (`ga.cs:1462-1464` is
|
||||
the wielded-first branch; the line numbers `1471-1475` above refer to the
|
||||
same function's error path.)
|
||||
`-1`-spell row for "Add (no buffs)") — and the profile loader (`da.cs:628`). So the
|
||||
first wand a player added is the fallback caster.
|
||||
|
||||
### 3.2 (b) Fighting with the rule weapon
|
||||
|
||||
|
|
@ -652,9 +650,10 @@ carefully:
|
|||
`fd.cs:103-110`, the `nav minimum distance` referenced in the campaign
|
||||
brief).
|
||||
- If that "stop" condition is true **and** `Actions.CombatMode == Peace`
|
||||
(`fd.cs:129`): if `IdlePeaceMode` is on, log **"Warning: Idle peace
|
||||
(`fd.cs:129`): if `IdlePeaceMode` is on (`fd.cs:131`) log **"Warning: Idle peace
|
||||
selected with low waypoint minimum distance. Will switch to magic
|
||||
mode."** (`fd.cs:133`), then attempt to force Magic mode via
|
||||
mode."** (`fd.cs:133`) — the warning is the ONLY thing that setting gates —
|
||||
then, regardless of the setting, attempt to force Magic mode via
|
||||
`dz.o.a((CombatState)8, 0, true)` (the shared gate, §3.1) — and if that
|
||||
fails, cancel the "stop" decision for this tick, i.e. keep walking
|
||||
instead (`fd.cs:135-138`).
|
||||
|
|
@ -687,7 +686,7 @@ Files read: `MossTankPanel.cs` (`OnTick`, `TickAutomaticBuffing`,
|
|||
VTank's `l` is a declarative list of independent `ILogicRule` objects; one
|
||||
pass picks the first whose `ValidNow` is true and marks it `Running`, and
|
||||
every other rule is explicitly told `Running = false` (§1.2). MossTank's
|
||||
`OnTick` (`MossTankPanel.cs:3732-3936`) is an imperative chain of ~16
|
||||
`OnTick` (`MossTankPanel.cs:3732-4022`) is an imperative chain of ~16
|
||||
named controllers, each called unconditionally every tick with a `canAct`
|
||||
argument that is the logical AND of "not owned by any higher controller
|
||||
so far." The net *suppression* behavior is similar (a higher controller
|
||||
|
|
@ -732,7 +731,7 @@ observably different: retail VTank always buffs allies with the weakest
|
|||
version of Tier-I self-buffs, cycling randomly; MossTank always buffs
|
||||
with the strongest known tier, cycling in a fixed order. The 18 m range
|
||||
constant (VTank's hardcoded `0.075` landblock units) is correctly ported
|
||||
(`< 18d`, line 4071, with an explicit comment tying it to the conversion).
|
||||
(`< 18d`, line 4071; no comment ties it to the conversion).
|
||||
|
||||
### 5.4 BuffCasterPreparer vs. `ga.a(...)`: same shape, one real
|
||||
difference
|
||||
|
|
@ -769,11 +768,12 @@ VTank re-checks self-vital recharge at two separate priority tiers
|
|||
(`cr` "Recharge-Norm-*" before Attack, "Recharge-NoTarg-*" after target-
|
||||
approach fails, §2.2 rows 4 and 59) — two independent settings, gated
|
||||
purely by *list position* relative to Attack. MossTank's `VitalPlan.
|
||||
Threshold` (`VitalPlan.cs:79-88`) keeps both `Normal*` and `NoTarget*`
|
||||
settings but combines them as `Math.Max(Normal, NoTarget)` regardless of
|
||||
whether a target is present, then only the `noTarget` bool
|
||||
(`VitalRechargeController.Tick`'s third parameter,
|
||||
`VitalRecharge.cs:887, 933-939`) selects which pair applies. This
|
||||
Threshold` (`VitalPlan.cs:79-91`) keeps both `Normal*` and `NoTarget*`
|
||||
settings and evaluates `noTarget ? Math.Max(Normal, NoTarget) : Normal` —
|
||||
with a target present the NoTarget setting is ignored entirely, and only
|
||||
in the no-target branch does the Max apply (the `noTarget` bool is
|
||||
`VitalRechargeController.Tick`'s third parameter, `VitalRecharge.cs:887,
|
||||
933-939`). This
|
||||
converges on similar behavior in the common case (both thresholds usually
|
||||
agree in intent — top off more eagerly while idle) but is not a literal
|
||||
port: VTank's two rules can disagree in *which* vitals they check (a
|
||||
|
|
@ -848,9 +848,9 @@ fight.
|
|||
likely covered by a combat-math KB doc.
|
||||
- **`gj`/`gs` (the two Decal state trackers that drive `SchedulePoke`'s
|
||||
fast-wake path)** were read only enough to confirm what they represent
|
||||
in shape (spell-cast completion and attack/missile completion,
|
||||
`gj.cs`/`gs.cs` headers); their own internal state machines were not
|
||||
traced.
|
||||
in shape (resolved by the citation pass: `gj` = SpellCaster, `gs` =
|
||||
WandCaster, both cast-completion trackers); their own internal state
|
||||
machines were not traced.
|
||||
- **Meta FSM** (`dz.at.h()`, `a7.e()`, `cLogic.cs:191-196`) is explicitly
|
||||
out of scope — it is evaluated once per pass alongside the main rule
|
||||
list but is its own subsystem (VTank's expression-language meta layer),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue