merge(core): the enum verification campaign, onto the post-deletion tree
Brings `github/overnight/enums` (`c19680fd`) forward onto the V11 tree. The branch was cut at `b70b9832`, before the OpenGL deletion, and the two lines of work turned out to be disjoint: the enum campaign lives entirely in `AcDream.Core` and its tests, while V11 emptied `AcDream.App`. The merge is clean — no conflicting file on either side. What it carries: names for AC's seven property tables verified against two oracles, a correction to `DamageType`'s rotated bits and `ItemType`'s shifted craft ladder, the retail members the equipment and physics enums were missing, and names for `AmmoType`, `CombatUse` and `ItemUseable`. Five commits, seventeen files, +3,767 / -27 lines. Verified on the merge result rather than on the branch: Release build 0 errors, no new warning attributable to any file the branch touches, and `AcDream.Core.Tests` at 3,893 passed / 2 skipped / 3,895. The campaign's claimed +597 is exact — the `Properties` namespace alone runs 597 tests, all passing. The campaign's open decision items — whether to adopt `WeenieError` wholesale, whether the `SoundId` subset is the right cut, and the re-clone of the ACE and Chorizite references that `references/` no longer holds — are not settled here. They are carried into the morning report as questions for the user. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
commit
cd2f3feae2
17 changed files with 3767 additions and 27 deletions
|
|
@ -17,7 +17,7 @@ once Campaign V closes.
|
||||||
|
|
||||||
| Item | Existing foundation | Shape of the work |
|
| Item | Existing foundation | Shape of the work |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
| **VERIFY all enums** | `docs/research/2026-06-04-property-enum-divergence.md`: 929 values missing across 7 `Property*` enums, plus the `acdream-property-enum-sweep` skill for regeneration. | Extend the sweep beyond Property* to every wire-adjacent enum family; adopt values with ACE as oracle; conformance tests per enum. |
|
| **VERIFY all enums** — **DONE 2026-07-29**, see [`docs/research/2026-07-29-enum-verification-campaign.md`](../research/2026-07-29-enum-verification-campaign.md) | The 2026-06-04 divergence note turned out to be missing from the repo entirely (open question 1 in the successor), so the sweep was regenerated from scratch. | Seven `Property*` tables created (864 members); `DamageType` and `ItemType` value bugs fixed; equipment/physics/item families closed against retail. Twelve open questions remain, headed by five empty `references/` repos. |
|
||||||
| **Verify networking stack** | `docs/research/2026-06-04-wire-message-catalog.md`: 256 opcodes catalogued, 114 parsed. | Audit parsed-vs-stub-vs-missing against the catalog; prioritize by what live servers actually send (Coldeve session logs are now a real corpus); holtburger remains the client-side oracle. |
|
| **Verify networking stack** | `docs/research/2026-06-04-wire-message-catalog.md`: 256 opcodes catalogued, 114 parsed. | Audit parsed-vs-stub-vs-missing against the catalog; prioritize by what live servers actually send (Coldeve session logs are now a real corpus); holtburger remains the client-side oracle. |
|
||||||
| **Physics review — retail landing bounce et al.** | The named-retail decomp workflow; carried debt #116 (slide response), TS-50/51/53 in the divergence register. | A focused fidelity pass: start with the user's observed case — long-jump landing should bounce/recoil as retail does (grep `named-retail` for the landing/impact path in `MovementManager`/`SetMotion` land states before writing anything). Each fix follows grep→decompile→pseudocode→port→conformance. |
|
| **Physics review — retail landing bounce et al.** | The named-retail decomp workflow; carried debt #116 (slide response), TS-50/51/53 in the divergence register. | A focused fidelity pass: start with the user's observed case — long-jump landing should bounce/recoil as retail does (grep `named-retail` for the landing/impact path in `MovementManager`/`SetMotion` land states before writing anything). Each fix follows grep→decompile→pseudocode→port→conformance. |
|
||||||
|
|
||||||
|
|
|
||||||
260
docs/research/2026-07-29-enum-verification-campaign.md
Normal file
260
docs/research/2026-07-29-enum-verification-campaign.md
Normal file
|
|
@ -0,0 +1,260 @@
|
||||||
|
# Enum verification campaign — 2026-07-29
|
||||||
|
|
||||||
|
Bucket B item 1 of [`docs/plans/2026-07-29-post-vulkan-work-intake.md`](../plans/2026-07-29-post-vulkan-work-intake.md).
|
||||||
|
Successor to the (missing — see Open question 1) 2026-06-04 property-enum
|
||||||
|
divergence note. Run unattended against base `b70b9832`.
|
||||||
|
|
||||||
|
**Headline: the campaign found two real value bugs and one wrong comment, all in
|
||||||
|
enums nothing currently reads.** They were traps armed for the next person to
|
||||||
|
write a comparison, not live defects. Everything else diffs clean.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. The oracle set actually used
|
||||||
|
|
||||||
|
CLAUDE.md's reference hierarchy names six vendored repos. In this environment
|
||||||
|
**`references/ACE`, `references/Chorizite.ACProtocol`, `references/holtburger`,
|
||||||
|
`references/ACViewer`, `references/AC2D` and `references/DatReaderWriter` are all
|
||||||
|
empty directories** (`references/*` is gitignored; only WorldBuilder is checked
|
||||||
|
in). The campaign therefore re-anchored on the oracles that *are* present, which
|
||||||
|
is no loss of rigour — CLAUDE.md ranks the first of them above ACE anyway:
|
||||||
|
|
||||||
|
| # | Oracle | What it is | Weight |
|
||||||
|
|---|---|---|---|
|
||||||
|
| 1 | `docs/research/named-retail/acclient.h` | The Sept 2013 EoR retail header, verbatim. 348 parseable `enum` blocks. | **Decides.** CLAUDE.md: "beats every other reference for what the real client does." |
|
||||||
|
| 2 | `references/acclientlib/UtilityBelt.Common/Enums/Enums.cs` | 18,313-line client-side enum catalog, shipped beside a vendored `ACE.Entity` tree. Holds the seven property tables as `IntId`/`BoolId`/`FloatId`/… | Strong, **not infallible** — see §2. |
|
||||||
|
| 3 | `references/weenies/**/*.json` | 38,985 ACE weenie exports. Every stat entry carries the numeric key *and* the enum member name in its `_comment`; enum-valued ints also name the value member after `=`. | Independent mechanical attestation, limited to values some weenie actually sets. |
|
||||||
|
| 4 | `references/WorldBuilder/.../ACEnums.cs` | 233 lines, a handful of property members. | Spot check only. |
|
||||||
|
|
||||||
|
Retail does **not** name the seven property tables anywhere in `acclient.h`
|
||||||
|
(searched as `SType*`, `Property*`, and by member name). The client receives
|
||||||
|
property keys as opaque `u32`, so oracles 2 and 3 carry those alone.
|
||||||
|
|
||||||
|
**Why having more than one oracle mattered:** on `ItemType.CraftFletchingBase`
|
||||||
|
the *catalog* is wrong (says `0x02000000`) and acdream was right (`0x01000000`,
|
||||||
|
matching retail). Had the campaign trusted the catalog the way the mission brief
|
||||||
|
assumed it would trust ACE, it would have introduced a bug. No single source was
|
||||||
|
taken on faith; retail's header decided every disagreement, with the weenie
|
||||||
|
corpus as tiebreak.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. Bugs found and fixed
|
||||||
|
|
||||||
|
### 2.1 `DamageType` — four bits rotated (`f3e95a3e`)
|
||||||
|
|
||||||
|
acdream assigned `Nether/Mana/Health/Stamina` to `0x80/0x100/0x200/0x400`.
|
||||||
|
Retail `DAMAGE_TYPE` (acclient.h:3788) assigns `Health/Stamina/Mana/Nether`.
|
||||||
|
|
||||||
|
| value | acdream (before) | retail | catalog | weenie corpus |
|
||||||
|
|---|---|---|---|---|
|
||||||
|
| 0x80 | Nether | **Health** | — | — |
|
||||||
|
| 0x100 | Mana | **Stamina** | — | Stamina (n=2) |
|
||||||
|
| 0x200 | Health | **Mana** | — | Mana (n=8) |
|
||||||
|
| 0x400 | Stamina | **Nether** | — | Nether (n=9) |
|
||||||
|
|
||||||
|
`BASE_DAMAGE_TYPE = 0x10000000` was also absent. Both of acdream's live
|
||||||
|
damage-type name tables — `CombatChatTranslator.FormatDamageType` (ported from
|
||||||
|
holtburger) and `ItemAppraisalTextFormatter.TryDamageTypeName` — already used
|
||||||
|
retail's order reading the raw wire `uint`, and `CombatChatTranslator` already
|
||||||
|
knew about `base`. The enum was the only thing in the tree that was wrong, and
|
||||||
|
nothing consumed the rotated members. **No live mislabel; latent trap removed.**
|
||||||
|
|
||||||
|
### 2.2 `ItemType` — shifted craft ladder + locally recomputed composites (`f3e95a3e`)
|
||||||
|
|
||||||
|
Retail `ITEM_TYPE` (acclient.h:3300) leaves `0x02000000` unused and puts
|
||||||
|
`CRAFT_ALCHEMY_INTERMEDIATE` on `0x04000000`. acdream had alchemy-intermediate
|
||||||
|
on `0x02000000` and an **invented `CraftCookingIntermediate`** squatting on
|
||||||
|
`0x04000000`. The weenie corpus attests `0x04000000` as
|
||||||
|
`Craft_Alchemy_Intermediate` 235 times and contains no cooking-intermediate at
|
||||||
|
all — there is no such item type.
|
||||||
|
|
||||||
|
Separately the composite masks were derived from the local primitives instead of
|
||||||
|
transcribed, which is how the ladder drifted in the first place:
|
||||||
|
|
||||||
|
| member | acdream (before) | retail |
|
||||||
|
|---|---|---|
|
||||||
|
| `Weapon` | `0x8101` (= melee\|missile\|caster) | `0x101` — melee\|missile, **no caster** |
|
||||||
|
| `WeaponOrCaster` | `0x8101` (alias of `Weapon`) | `0x8101` |
|
||||||
|
| `Item` | `0x830F` | `0x2DFBEF` |
|
||||||
|
|
||||||
|
Five retail composites acdream never had (`PortalMagicTarget`,
|
||||||
|
`LockableMagicTarget`, `ItemEnchantableTarget`,
|
||||||
|
`RedirectableItemEnchantmentTarget`, `VendorShopkeep`, `VendorGrocer`) came
|
||||||
|
along. Only one site in the tree referenced any changed member — a test that
|
||||||
|
wants a nonzero `HookItemTypes` and does not care which — so **no branch changed.**
|
||||||
|
|
||||||
|
### 2.3 `EquipMask` — a wrong type remark (`8ccaf72a`)
|
||||||
|
|
||||||
|
A remark claimed retail's `CLOTHING_LOC` composite "also sets bit 31,
|
||||||
|
0x80000000, which is not a named INVENTORY_LOC primitive". It does not.
|
||||||
|
`CLOTHING_LOC` is `0x080001FF`: the nine wear slots plus **bit 27**, which is the
|
||||||
|
perfectly well-named `Cloak` slot. No `INVENTORY_LOC` member touches bit 31 at
|
||||||
|
all — `ALL_LOC` stops at bit 30. Caught by writing the composite test.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. Per-family end state
|
||||||
|
|
||||||
|
### 3.1 The seven `Property*` tables (`251dd68a`)
|
||||||
|
|
||||||
|
acdream had **no** `Property*` enums at all — property IDs were bare `uint`s with
|
||||||
|
the meaning carried in prose (`private const uint EncumbranceValProperty = 5u`
|
||||||
|
duplicated across two files, `UiEffects` as "ACE enum value 18" in a doc comment).
|
||||||
|
All seven are now created under `AcDream.Core.Properties`.
|
||||||
|
|
||||||
|
| family | members adopted | attested by both oracles | single-sourced |
|
||||||
|
|---|---|---|---|
|
||||||
|
| `PropertyInt` | 391 | 189 | 202 |
|
||||||
|
| `PropertyFloat` | 172 | 86 | 86 |
|
||||||
|
| `PropertyBool` | 131 | 59 | 72 |
|
||||||
|
| `PropertyDataId` | 62 | 41 | 21 |
|
||||||
|
| `PropertyString` | 53 | 28 | 25 |
|
||||||
|
| `PropertyInstanceId` | 46 | 2 | 44 |
|
||||||
|
| `PropertyInt64` | 9 | 3 | 6 |
|
||||||
|
| **total** | **864** | **408** | **456** |
|
||||||
|
|
||||||
|
Zero value conflicts between the two oracles across all seven, and the corpus
|
||||||
|
contained no key the catalog lacked — the catalog is a strict superset of
|
||||||
|
everything 38,985 weenies set. Three members differ in *spelling* only; acdream
|
||||||
|
took ACE's (`ItemType`/`HookItemType`/`MerchandiseItemTypes` over the catalog's
|
||||||
|
`ObjectType`/…), which is what the corpus emits and what acdream's own `ItemType`
|
||||||
|
already called it.
|
||||||
|
|
||||||
|
### 3.2 Existing wire-adjacent enums, diffed against retail
|
||||||
|
|
||||||
|
Legend: **closed** = every retail member present at retail's value.
|
||||||
|
|
||||||
|
| acdream enum | retail enum | end state |
|
||||||
|
|---|---|---|
|
||||||
|
| `ItemType` | `ITEM_TYPE` | **closed** (2 fixed) — retail's `TYPE_UNDEF`/`TYPE_SELF` are both 0; acdream spells the single 0 `None` |
|
||||||
|
| `DamageType` | `DAMAGE_TYPE` | **closed** (4 fixed, 1 added) |
|
||||||
|
| `EquipMask` | `INVENTORY_LOC` | **closed** — 43/43, 11 composites adopted |
|
||||||
|
| `TransientStateFlags` | `TransientState` | **closed** — `WaterContact`, `CheckEthereal` adopted |
|
||||||
|
| `PhysicsStateFlags` | `PhysicsState` | **closed** — `ReservedUnused1/2` adopted |
|
||||||
|
| `ObjectInfoState` | `ObjectInfoEnum` | **closed** — was already exact (`None` = `DEFAULT_OI`) |
|
||||||
|
| `AttackHeight` | `ATTACK_HEIGHT` | **closed** — `Undef` adopted; `NUM_ATTACK_HEIGHTS` is a count, deliberately not a member |
|
||||||
|
| `HoldKey` | `HoldKey` | **closed** — `Num_HoldKeys` is a count |
|
||||||
|
| `AttackType` | `AttackType` | **already correct**, incl. both composites (`Unarmed` 0x19, `MultiStrike` 0x79E0) |
|
||||||
|
| `RadarBlipShape` | `RadarBlipShape` | already exact (14/14) |
|
||||||
|
| `RadarBehavior` | `RadarEnum` | already exact (5/5) |
|
||||||
|
| `MovementType` | `MovementTypes::Type` | already exact (10/10) |
|
||||||
|
| `ParticleType` | `ParticleType` | already exact (14/14) |
|
||||||
|
| `PhysicsDescriptionFlag` | `PhysicsDesc::PhysicsDescInfo` | already exact (naming only: `AnimationFrame`/`ANIMFRAME_ID`) |
|
||||||
|
|
||||||
|
### 3.3 New enums for wire fields acdream parsed but never named (`3efa266a`)
|
||||||
|
|
||||||
|
| enum | retail source | members | why |
|
||||||
|
|---|---|---|---|
|
||||||
|
| `AmmoType` | acclient.h:4221 | 10 | parsed via `PublicWeenieDesc._ammo_type`; the appraisal sentence matched raw hex |
|
||||||
|
| `CombatUse` | acclient.h:6523 | 6 | `PropertyInt.CombatUse` (51) |
|
||||||
|
| `ItemUseable` | acclient.h:6478 | 39 | `PropertyInt.ItemUseable` (16); two 16-bit halves, ~30 named combinations |
|
||||||
|
|
||||||
|
`ItemAppraisalTextFormatter`'s ammunition fold now reads through `AmmoType`. Its
|
||||||
|
crystal/chorizite → base collapse was verified correct against retail's bit
|
||||||
|
layout before the change; behaviour is unchanged.
|
||||||
|
|
||||||
|
### 3.4 Verified correct, no change needed
|
||||||
|
|
||||||
|
- `ItemAppraisalTextFormatter` ammo fold (§3.3) against `AMMO_TYPE`.
|
||||||
|
- `CombatChatTranslator.FormatDamageType` and
|
||||||
|
`ItemAppraisalTextFormatter.TryDamageTypeName` against `DAMAGE_TYPE` — both
|
||||||
|
already retail-correct, which is what exposed §2.1.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. Open questions
|
||||||
|
|
||||||
|
Each is something the campaign could **not** settle from an oracle. Per
|
||||||
|
CLAUDE.md these are recorded rather than guessed.
|
||||||
|
|
||||||
|
1. **The 2026-06-04 research drop is missing.** `claude-memory/MEMORY.md` indexes
|
||||||
|
`research/2026-06-04-property-enum-divergence.md` (the "929 values across 7
|
||||||
|
enums" ledger) and `research/2026-06-04-magic-number-audit.md`. Neither exists
|
||||||
|
in the working tree, under any ref (`git log --all --diff-filter=A`), or in the
|
||||||
|
memory directory — which has no `research/` subfolder at all. The 929 figure
|
||||||
|
could not be reproduced or audited; this campaign regenerated from scratch and
|
||||||
|
arrived at 864 property members. **Blocker:** source documents absent. Either
|
||||||
|
they were never committed or they lived in a discarded worktree. Suggest
|
||||||
|
fixing the MEMORY.md index entries to point at this doc.
|
||||||
|
2. **Five of six reference repos are empty** (§1). Everything sourced here came
|
||||||
|
from retail + the UtilityBelt catalog + the weenie corpus. **Blocker:** repos
|
||||||
|
not cloned in this environment. Re-cloning ACE and Chorizite would let the 456
|
||||||
|
single-sourced property members (§3.1) be promoted to two-oracle confirmed.
|
||||||
|
3. **456 of 864 property members are single-sourced.** They are transcribed from
|
||||||
|
the catalog, not invented, but no weenie in the corpus sets them so there is no
|
||||||
|
independent attestation. **Blocker:** needs ACE source, or the client DAT's own
|
||||||
|
`EnumMapper` file type (`acclientlib` has a reader for it — a genuinely retail
|
||||||
|
oracle, and the most promising unexplored lead).
|
||||||
|
4. **`WeenieError` — 362 unadopted status codes.** acdream has 16 members; the
|
||||||
|
catalog's `StatusMessage` has 372, with 10 shared and zero conflicts. Retail's
|
||||||
|
`charError` (26) is a *different* enum — character-creation errors only — so
|
||||||
|
retail cannot arbitrate. Register row **AP-15** already tracks that acdream's
|
||||||
|
translation table covers only ~30 common codes. **Blocker:** needs a decision
|
||||||
|
on importing 362 server-side codes wholesale, and ideally retail's
|
||||||
|
`string_table.bin` for the real sentences. Deliberately not done here.
|
||||||
|
5. **`CombatMode` has no located retail counterpart.** acdream's 7 members match
|
||||||
|
the catalog's `CombatMode` (`Magic = 8`). Retail's `CombatStyle` (25 members,
|
||||||
|
`Magic_CombatStyle = 512`) is a different enum — weapon-style, not combat mode.
|
||||||
|
A retail `COMBAT_MODE` was not found in `acclient.h`. **Blocker:** oracle not
|
||||||
|
located; acdream is probably right but is single-sourced.
|
||||||
|
6. **`PublicWeenieFlags` counterpart unidentified.** acdream's 17 members
|
||||||
|
(`Attackable`, `Door`, `Vendor`, …) share exactly one name with retail's
|
||||||
|
`PublicWeenieDescPackHeader` (34), which is the *pack-header* bitfield — a
|
||||||
|
different thing. `PublicWeenieDesc::BitfieldIndex` (31 members) is the likely
|
||||||
|
real counterpart. **Blocker:** pairing unconfirmed; not diffed.
|
||||||
|
7. **`SoundId` is a curated 23-member local subset** of retail's `SoundType`
|
||||||
|
(206), with acdream-local names (`FootstepGrass`, `BuffApplied`) that do not
|
||||||
|
correspond 1:1 to retail members. **Blocker:** needs a decision — adopt
|
||||||
|
retail's table wholesale, or record the subset as an intentional divergence
|
||||||
|
with a register row. Neither was done.
|
||||||
|
8. **`ChatType` / `BlobType` / `DispatchType`** (TurbineChat) share no members
|
||||||
|
with retail's `eChatTypes` (26) or `ChatTypeEnum` (12); they describe chat
|
||||||
|
*channels*, not text-display types. **Blocker:** correct counterpart not
|
||||||
|
identified. Relevant to the Bucket C chatbox cleanup.
|
||||||
|
9. **`GameEventType` (103 members) was not verified.** No counterpart found under
|
||||||
|
a matching name in either retail or the catalog. **Blocker:** needs the wire
|
||||||
|
catalog (Bucket B item 2) to supply the pairing.
|
||||||
|
10. **`MaterialType` not adopted.** acdream parses it as raw `uint` from
|
||||||
|
`PublicWeenieDesc`; the catalog has 108 members; no retail counterpart located
|
||||||
|
in `acclient.h`. **Blocker:** single-sourced, and unused so far.
|
||||||
|
11. **`SpellTargetType`, `ItemPrimaryUseResult`, `PositionFlags`,
|
||||||
|
`EnchantmentMask`/`EnchantmentBucket`, `GameMessageGroup`, `InventoryRequestKind`
|
||||||
|
are acdream-local** with no retail counterpart at the same semantics. Confirmed
|
||||||
|
for `EnchantmentMask`/`EnchantmentBucket`: they are PlayerDescription wire
|
||||||
|
*trailer bucket* flags (ACE's `EnchantmentMask`), not retail's
|
||||||
|
`EnchantmentTypeEnum` — the apparent value conflict is a false pairing. The
|
||||||
|
others were not individually run down.
|
||||||
|
12. **Tooling limitation, for whoever re-runs this.** The extractor reads one line
|
||||||
|
per enum member, so a member whose value spans multiple lines is truncated.
|
||||||
|
This produced a false `AttackType.MultiStrike` conflict (read as `0x1E0`,
|
||||||
|
actually `0x79E0`). Any automated re-run must join continuation lines before
|
||||||
|
trusting a reported conflict.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. Reproducing
|
||||||
|
|
||||||
|
Extraction and diff scripts were scratch tooling, not committed (they hardcode
|
||||||
|
absolute paths into `references/`). The method, in order:
|
||||||
|
|
||||||
|
1. Parse `acclient.h` for `enum NAME {` blocks; resolve member expressions
|
||||||
|
(hex, digit separators, references to earlier members).
|
||||||
|
2. Parse the UtilityBelt catalog the same way.
|
||||||
|
3. Walk `references/weenies/**/*.json`, pulling `(key, value, _comment)` from each
|
||||||
|
`*Stats` array; the comment's left side is the property name, the right side
|
||||||
|
(after `=`) names the value member for enum-typed ints.
|
||||||
|
4. Normalise names across conventions (retail `SCREAMING_SNAKE` with family
|
||||||
|
prefix/suffix ↔ acdream `PascalCase`) and diff on the normalised key, comparing
|
||||||
|
values exactly.
|
||||||
|
5. Any disagreement: retail decides, corpus breaks ties, and anything still
|
||||||
|
unresolved becomes an open question above rather than a guess.
|
||||||
|
|
||||||
|
## 6. Commits
|
||||||
|
|
||||||
|
| commit | slice |
|
||||||
|
|---|---|
|
||||||
|
| `251dd68a` | the seven `Property*` tables (864 members, 429 tests) |
|
||||||
|
| `f3e95a3e` | `DamageType` rotation + `ItemType` craft ladder and composites |
|
||||||
|
| `8ccaf72a` | `EquipMask` composites, `TransientState`, `PhysicsState`, `AttackHeight` |
|
||||||
|
| `3efa266a` | `AmmoType`, `CombatUse`, `ItemUseable` |
|
||||||
|
|
@ -398,22 +398,24 @@ public static class ItemAppraisalTextFormatter
|
||||||
if (ammoType == 0u)
|
if (ammoType == 0u)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
uint baseAmmoType = ammoType switch
|
// Retail gives the crystal and chorizite variants their own bits
|
||||||
|
// (acclient.h:4221); each folds back to the base kind for this sentence.
|
||||||
|
AmmoType baseAmmoType = (AmmoType)ammoType switch
|
||||||
{
|
{
|
||||||
0x08u or 0x40u => 1u,
|
AmmoType.ArrowCrystal or AmmoType.ArrowChorizite => AmmoType.Arrow,
|
||||||
0x10u or 0x80u => 2u,
|
AmmoType.BoltCrystal or AmmoType.BoltChorizite => AmmoType.Bolt,
|
||||||
0x20u or 0x100u => 4u,
|
AmmoType.AtlatlCrystal or AmmoType.AtlatlChorizite => AmmoType.Atlatl,
|
||||||
_ => ammoType,
|
var other => other,
|
||||||
};
|
};
|
||||||
bool launcher = (validLocations & (uint)EquipMask.MissileWeapon) != 0;
|
bool launcher = (validLocations & (uint)EquipMask.MissileWeapon) != 0;
|
||||||
string? description = (launcher, baseAmmoType) switch
|
string? description = (launcher, baseAmmoType) switch
|
||||||
{
|
{
|
||||||
(true, 1u) => "Uses arrows as ammunition.",
|
(true, AmmoType.Arrow) => "Uses arrows as ammunition.",
|
||||||
(true, 2u) => "Uses quarrels as ammunition.",
|
(true, AmmoType.Bolt) => "Uses quarrels as ammunition.",
|
||||||
(true, 4u) => "Uses atlatl darts as ammunition.",
|
(true, AmmoType.Atlatl) => "Uses atlatl darts as ammunition.",
|
||||||
(false, 1u) => "Used as ammunition by bows.",
|
(false, AmmoType.Arrow) => "Used as ammunition by bows.",
|
||||||
(false, 2u) => "Used as ammunition by crossbows.",
|
(false, AmmoType.Bolt) => "Used as ammunition by crossbows.",
|
||||||
(false, 4u) => "Used as ammunition by atlatls.",
|
(false, AmmoType.Atlatl) => "Used as ammunition by atlatls.",
|
||||||
_ => null,
|
_ => null,
|
||||||
};
|
};
|
||||||
if (description is not null)
|
if (description is not null)
|
||||||
|
|
|
||||||
|
|
@ -22,8 +22,14 @@ public enum CombatMode
|
||||||
CombatCombat = Melee | Missile | Magic,
|
CombatCombat = Melee | Missile | Magic,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Verbatim retail <c>ATTACK_HEIGHT</c> (<c>docs/research/named-retail/acclient.h:4371</c>).
|
||||||
|
/// The three real heights are 1-based; retail reserves 0 for "not chosen yet", which the
|
||||||
|
/// wire does send, so it is named rather than left to fall through as an undefined cast.
|
||||||
|
/// </summary>
|
||||||
public enum AttackHeight
|
public enum AttackHeight
|
||||||
{
|
{
|
||||||
|
Undef = 0,
|
||||||
High = 1,
|
High = 1,
|
||||||
Medium = 2,
|
Medium = 2,
|
||||||
Low = 3,
|
Low = 3,
|
||||||
|
|
@ -204,6 +210,18 @@ public enum AttackType : uint
|
||||||
| OffhandDoubleThrust | OffhandTripleThrust,
|
| OffhandDoubleThrust | OffhandTripleThrust,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Verbatim retail <c>DAMAGE_TYPE</c> (<c>docs/research/named-retail/acclient.h:3788</c>).
|
||||||
|
///
|
||||||
|
/// <para>The four drain/restore bits used to be rotated here: Nether/Mana/Health/Stamina
|
||||||
|
/// were assigned 0x80/0x100/0x200/0x400 where retail assigns Health/Stamina/Mana/Nether.
|
||||||
|
/// Retail, the vendored client-side enum catalog, and the ACE weenie corpus all agree on
|
||||||
|
/// retail's order (the corpus attests 0x100=Stamina, 0x200=Mana, 0x400=Nether directly),
|
||||||
|
/// and both of acdream's live damage-type name tables — <c>CombatChatTranslator</c> and
|
||||||
|
/// <c>ItemAppraisalTextFormatter</c> — were already reading the retail order off the raw
|
||||||
|
/// wire uint. Nothing consumed the rotated members, so this corrects a latent trap rather
|
||||||
|
/// than a live mislabel.</para>
|
||||||
|
/// </summary>
|
||||||
[Flags]
|
[Flags]
|
||||||
public enum DamageType : uint
|
public enum DamageType : uint
|
||||||
{
|
{
|
||||||
|
|
@ -215,10 +233,11 @@ public enum DamageType : uint
|
||||||
Fire = 0x0010,
|
Fire = 0x0010,
|
||||||
Acid = 0x0020,
|
Acid = 0x0020,
|
||||||
Electric = 0x0040,
|
Electric = 0x0040,
|
||||||
Nether = 0x0080,
|
Health = 0x0080,
|
||||||
Mana = 0x0100,
|
Stamina = 0x0100,
|
||||||
Health = 0x0200,
|
Mana = 0x0200,
|
||||||
Stamina = 0x0400,
|
Nether = 0x0400,
|
||||||
|
Base = 0x10000000,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
||||||
|
|
@ -10,9 +10,17 @@ namespace AcDream.Core.Items;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// AC's <c>ItemType</c> is a 32-bit flags enum — a single dat weenie can
|
/// AC's <c>ItemType</c> is a 32-bit flags enum — a single dat weenie can
|
||||||
/// assert multiple type bits. From <c>ACE.Entity.Enum.ItemType</c>
|
/// assert multiple type bits. Verbatim retail <c>ITEM_TYPE</c>
|
||||||
/// cross-checked against the decompile paperdoll tooltip dispatcher.
|
/// (<c>docs/research/named-retail/acclient.h:3300</c>).
|
||||||
/// Full bit list in the research doc §1.
|
///
|
||||||
|
/// <para>The craft ladder used to be shifted: <c>CraftAlchemyIntermediate</c> sat on
|
||||||
|
/// 0x02000000 (retail leaves that bit unused and puts alchemy-intermediate on
|
||||||
|
/// 0x04000000), and an invented <c>CraftCookingIntermediate</c> occupied the real
|
||||||
|
/// alchemy-intermediate bit. The ACE weenie corpus attests 0x04000000 =
|
||||||
|
/// Craft_Alchemy_Intermediate 235 times and contains no cooking-intermediate at all.
|
||||||
|
/// The composite masks were likewise recomputed locally rather than transcribed, which
|
||||||
|
/// made <c>Weapon</c> an alias of <c>WeaponOrCaster</c> and left <c>Item</c> two orders
|
||||||
|
/// of magnitude narrower than retail's. Full bit list in the research doc §1.</para>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Flags]
|
[Flags]
|
||||||
public enum ItemType : uint
|
public enum ItemType : uint
|
||||||
|
|
@ -43,17 +51,27 @@ public enum ItemType : uint
|
||||||
CraftCookingBase = 0x00400000,
|
CraftCookingBase = 0x00400000,
|
||||||
CraftAlchemyBase = 0x00800000,
|
CraftAlchemyBase = 0x00800000,
|
||||||
CraftFletchingBase = 0x01000000,
|
CraftFletchingBase = 0x01000000,
|
||||||
CraftAlchemyIntermediate= 0x02000000,
|
// 0x02000000 is deliberately unused in retail's ladder.
|
||||||
CraftCookingIntermediate= 0x04000000,
|
CraftAlchemyIntermediate= 0x04000000,
|
||||||
CraftFletchingIntermediate = 0x08000000,
|
CraftFletchingIntermediate = 0x08000000,
|
||||||
LifeStone = 0x10000000,
|
LifeStone = 0x10000000,
|
||||||
TinkeringTool = 0x20000000,
|
TinkeringTool = 0x20000000,
|
||||||
TinkeringMaterial = 0x40000000,
|
TinkeringMaterial = 0x40000000,
|
||||||
Gameboard = 0x80000000u,
|
Gameboard = 0x80000000u,
|
||||||
Vestements = Armor | Clothing,
|
|
||||||
Weapon = MeleeWeapon | MissileWeapon | Caster,
|
// Composite masks, transcribed verbatim rather than recomputed from the bits
|
||||||
WeaponOrCaster = Weapon,
|
// above — retail's TYPE_ITEM in particular is far broader than any obvious
|
||||||
Item = Weapon | Armor | Clothing | Jewelry | Container,
|
// union, and deriving these locally is how the craft ladder drifted.
|
||||||
|
Vestements = 0x00000006, // TYPE_VESTEMENTS
|
||||||
|
Weapon = 0x00000101, // TYPE_WEAPON: melee | missile, no caster
|
||||||
|
WeaponOrCaster = 0x00008101, // TYPE_WEAPON_OR_CASTER
|
||||||
|
LockableMagicTarget = 0x00000280, // TYPE_LOCKABLE_MAGIC_TARGET
|
||||||
|
RedirectableItemEnchantmentTarget = 0x00008107,
|
||||||
|
PortalMagicTarget = 0x10010000, // TYPE_PORTAL_MAGIC_TARGET
|
||||||
|
ItemEnchantableTarget = 0x00088B8F, // TYPE_ITEM_ENCHANTABLE_TARGET
|
||||||
|
Item = 0x002DFBEF, // TYPE_ITEM
|
||||||
|
VendorShopkeep = 0x480467A7, // TYPE_VENDOR_SHOPKEEP
|
||||||
|
VendorGrocer = 0x00446220, // TYPE_VENDOR_GROCER
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -61,8 +79,10 @@ public enum ItemType : uint
|
||||||
/// (docs/research/named-retail/acclient.h:3193; identical to ACE's EquipMask).
|
/// (docs/research/named-retail/acclient.h:3193; identical to ACE's EquipMask).
|
||||||
/// The wire (ValidLocations / CurrentWieldedLocation / WieldObject EquipLoc) delivers
|
/// The wire (ValidLocations / CurrentWieldedLocation / WieldObject EquipLoc) delivers
|
||||||
/// these exact bits. Pinned by EquipMaskTests — do NOT renumber.
|
/// these exact bits. Pinned by EquipMaskTests — do NOT renumber.
|
||||||
/// (The header's <c>CLOTHING_LOC</c> composite also sets bit 31, 0x80000000, which is
|
/// (A remark here used to claim the header's <c>CLOTHING_LOC</c> composite sets an
|
||||||
/// not a named INVENTORY_LOC primitive and has no member here; <c>ALL_LOC</c> tops out at bit 30.)
|
/// unnamed bit 31. It does not: <c>CLOTHING_LOC</c> is 0x080001FF, the nine wear slots
|
||||||
|
/// plus bit 27, which is the named <see cref="EquipMask.Cloak"/> slot. <c>ALL_LOC</c>
|
||||||
|
/// tops out at bit 30, so no INVENTORY_LOC member uses bit 31 at all.)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Flags]
|
[Flags]
|
||||||
public enum EquipMask : uint
|
public enum EquipMask : uint
|
||||||
|
|
@ -99,6 +119,23 @@ public enum EquipMask : uint
|
||||||
SigilOne = 0x10000000,
|
SigilOne = 0x10000000,
|
||||||
SigilTwo = 0x20000000,
|
SigilTwo = 0x20000000,
|
||||||
SigilThree = 0x40000000,
|
SigilThree = 0x40000000,
|
||||||
|
|
||||||
|
// Retail's composite slot groups, transcribed verbatim from the same header
|
||||||
|
// block rather than recomputed from the primitives above. Clothing in
|
||||||
|
// particular is not the union of the wear slots — it also carries the cloak
|
||||||
|
// slot (bit 27).
|
||||||
|
Clothing = 0x080001FF, // CLOTHING_LOC: the nine wear slots | Cloak
|
||||||
|
Armor = 0x00007E00, // ARMOR_LOC
|
||||||
|
Jewelry = 0x7C0F8000, // JEWELRY_LOC
|
||||||
|
WristWear = 0x00030000, // WRIST_WEAR_LOC
|
||||||
|
FingerWear = 0x000C0000, // FINGER_WEAR_LOC
|
||||||
|
Sigil = 0x70000000, // SIGIL_LOC
|
||||||
|
ReadySlot = 0x03F00000, // READY_SLOT_LOC
|
||||||
|
Weapon = 0x02500000, // WEAPON_LOC
|
||||||
|
WeaponReadySlot = 0x03500000, // WEAPON_READY_SLOT_LOC
|
||||||
|
All = 0x7FFFFFFF, // ALL_LOC
|
||||||
|
/// <summary>Retail gives CAN_GO_IN_READY_SLOT_LOC the same value as ALL_LOC.</summary>
|
||||||
|
CanGoInReadySlot = 0x7FFFFFFF,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
||||||
104
src/AcDream.Core/Items/ItemWireEnums.cs
Normal file
104
src/AcDream.Core/Items/ItemWireEnums.cs
Normal file
|
|
@ -0,0 +1,104 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace AcDream.Core.Items;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Verbatim retail <c>AMMO_TYPE</c> (<c>docs/research/named-retail/acclient.h:4221</c>).
|
||||||
|
/// Arrives on the wire as <c>PublicWeenieDesc._ammo_type</c> (CreateObject weenie flag
|
||||||
|
/// 0x00000100) and in the appraisal weapon profile.
|
||||||
|
///
|
||||||
|
/// <para>The three base kinds each have a crystal and a chorizite variant on their own
|
||||||
|
/// bit, so a launcher's "uses arrows" test must fold the variants back to the base — see
|
||||||
|
/// <c>ItemAppraisalTextFormatter</c>, which does exactly that.</para>
|
||||||
|
/// </summary>
|
||||||
|
[Flags]
|
||||||
|
public enum AmmoType : uint
|
||||||
|
{
|
||||||
|
None = 0x000,
|
||||||
|
Arrow = 0x001,
|
||||||
|
Bolt = 0x002,
|
||||||
|
Atlatl = 0x004,
|
||||||
|
ArrowCrystal = 0x008,
|
||||||
|
BoltCrystal = 0x010,
|
||||||
|
AtlatlCrystal = 0x020,
|
||||||
|
ArrowChorizite = 0x040,
|
||||||
|
BoltChorizite = 0x080,
|
||||||
|
AtlatlChorizite = 0x100,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Verbatim retail <c>COMBAT_USE</c> (<c>docs/research/named-retail/acclient.h:6523</c>) —
|
||||||
|
/// how a wieldable participates in combat. This is a plain sequence, not a bitfield.
|
||||||
|
/// Arrives as <c>PropertyInt.CombatUse</c> (51).
|
||||||
|
/// </summary>
|
||||||
|
public enum CombatUse : uint
|
||||||
|
{
|
||||||
|
None = 0,
|
||||||
|
Melee = 1,
|
||||||
|
Missile = 2,
|
||||||
|
Ammo = 3,
|
||||||
|
Shield = 4,
|
||||||
|
TwoHanded = 5,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Verbatim retail <c>ITEM_USEABLE</c> (<c>docs/research/named-retail/acclient.h:6478</c>) —
|
||||||
|
/// where an object must be, and where its target must be, for a use attempt to be legal.
|
||||||
|
/// Arrives as <c>PropertyInt.ItemUseable</c> (16).
|
||||||
|
///
|
||||||
|
/// <para>The layout is two 16-bit halves: the low half (<see cref="SourceMask"/>) constrains
|
||||||
|
/// the object being used, the high half (<see cref="TargetMask"/>) constrains its target.
|
||||||
|
/// Retail names the useful combinations explicitly rather than expecting callers to compose
|
||||||
|
/// them, and they are transcribed here the same way — several are not the obvious union
|
||||||
|
/// (<see cref="SourceContainedTargetObjSelfOrContained"/> is 0x880008, not
|
||||||
|
/// <c>ObjSelf | Contained | (Contained << 16)</c>).</para>
|
||||||
|
/// </summary>
|
||||||
|
[Flags]
|
||||||
|
public enum ItemUseable : uint
|
||||||
|
{
|
||||||
|
Undef = 0x0,
|
||||||
|
No = 0x1,
|
||||||
|
Self = 0x2,
|
||||||
|
Wielded = 0x4,
|
||||||
|
Contained = 0x8,
|
||||||
|
Viewed = 0x10,
|
||||||
|
Remote = 0x20,
|
||||||
|
NeverWalk = 0x40,
|
||||||
|
ObjSelf = 0x80,
|
||||||
|
|
||||||
|
ContainedViewed = 0x18,
|
||||||
|
ViewedRemote = 0x30,
|
||||||
|
ContainedViewedRemote = 0x38,
|
||||||
|
RemoteNeverWalk = 0x60,
|
||||||
|
ViewedRemoteNeverWalk = 0x70,
|
||||||
|
ContainedViewedRemoteNeverWalk = 0x78,
|
||||||
|
|
||||||
|
SourceWieldedTargetWielded = 0x00040004,
|
||||||
|
SourceWieldedTargetContained = 0x00080004,
|
||||||
|
SourceWieldedTargetViewed = 0x00100004,
|
||||||
|
SourceWieldedTargetRemote = 0x00200004,
|
||||||
|
SourceWieldedTargetRemoteNeverWalk = 0x00600004,
|
||||||
|
|
||||||
|
SourceContainedTargetWielded = 0x00040008,
|
||||||
|
SourceContainedTargetContained = 0x00080008,
|
||||||
|
SourceContainedTargetSelfOrContained = 0x000A0008,
|
||||||
|
SourceContainedTargetViewed = 0x00100008,
|
||||||
|
SourceContainedTargetRemote = 0x00200008,
|
||||||
|
SourceContainedTargetRemoteOrSelf = 0x00220008,
|
||||||
|
SourceContainedTargetRemoteNeverWalk = 0x00600008,
|
||||||
|
SourceContainedTargetObjSelfOrContained = 0x00880008,
|
||||||
|
|
||||||
|
SourceViewedTargetWielded = 0x00040010,
|
||||||
|
SourceViewedTargetContained = 0x00080010,
|
||||||
|
SourceViewedTargetViewed = 0x00100010,
|
||||||
|
SourceViewedTargetRemote = 0x00200010,
|
||||||
|
|
||||||
|
SourceRemoteTargetWielded = 0x00040020,
|
||||||
|
SourceRemoteTargetContained = 0x00080020,
|
||||||
|
SourceRemoteTargetViewed = 0x00100020,
|
||||||
|
SourceRemoteTargetRemote = 0x00200020,
|
||||||
|
SourceRemoteTargetRemoteNeverWalk = 0x00600020,
|
||||||
|
|
||||||
|
SourceMask = 0x0000FFFF,
|
||||||
|
TargetMask = 0xFFFF0000,
|
||||||
|
}
|
||||||
|
|
@ -27,6 +27,12 @@ public enum PhysicsStateFlags : uint
|
||||||
{
|
{
|
||||||
None = 0x00000000,
|
None = 0x00000000,
|
||||||
Static = 0x00000001,
|
Static = 0x00000001,
|
||||||
|
/// <summary>
|
||||||
|
/// Retail declares 0x2 and 0x2000 as UNUSED1_PS / UNNUSED2_PS (acclient.h:2818,
|
||||||
|
/// 2830) — reserved, never set. Named here so neither bit gets repurposed for an
|
||||||
|
/// acdream-local flag and then collides with a server that starts using it.
|
||||||
|
/// </summary>
|
||||||
|
ReservedUnused1 = 0x00000002,
|
||||||
Ethereal = 0x00000004,
|
Ethereal = 0x00000004,
|
||||||
ReportCollisions = 0x00000008,
|
ReportCollisions = 0x00000008,
|
||||||
IgnoreCollisions = 0x00000010,
|
IgnoreCollisions = 0x00000010,
|
||||||
|
|
@ -38,6 +44,8 @@ public enum PhysicsStateFlags : uint
|
||||||
Gravity = 0x00000400,
|
Gravity = 0x00000400,
|
||||||
Lighting = 0x00000800,
|
Lighting = 0x00000800,
|
||||||
ParticleEmitter = 0x00001000,
|
ParticleEmitter = 0x00001000,
|
||||||
|
/// <summary>Retail UNNUSED2_PS — reserved, never set. See <see cref="ReservedUnused1"/>.</summary>
|
||||||
|
ReservedUnused2 = 0x00002000,
|
||||||
Hidden = 0x00004000,
|
Hidden = 0x00004000,
|
||||||
ScriptedCollision = 0x00008000,
|
ScriptedCollision = 0x00008000,
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -88,6 +96,11 @@ public enum TransientStateFlags : uint
|
||||||
StationaryStop = 0x00000020, // bit 5 — fsf == 2
|
StationaryStop = 0x00000020, // bit 5 — fsf == 2
|
||||||
StationaryStuck = 0x00000040, // bit 6 — fsf == 3
|
StationaryStuck = 0x00000040, // bit 6 — fsf == 3
|
||||||
Active = 0x00000080, // bit 7 — object needs per-frame update
|
Active = 0x00000080, // bit 7 — object needs per-frame update
|
||||||
|
// Declared to complete retail's TransientState (acclient.h:3688). Neither bit is
|
||||||
|
// produced or consumed by acdream's transition yet; they are here so the two free
|
||||||
|
// slots cannot be reused for something else and quietly collide with the wire.
|
||||||
|
WaterContact = 0x00000008, // bit 3 — WATER_CONTACT_TS
|
||||||
|
CheckEthereal = 0x00000100, // bit 8 — CHECK_ETHEREAL_TS
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
||||||
221
src/AcDream.Core/Properties/PropertyBool.cs
Normal file
221
src/AcDream.Core/Properties/PropertyBool.cs
Normal file
|
|
@ -0,0 +1,221 @@
|
||||||
|
// <auto-generated-source>
|
||||||
|
// Regenerate with the 2026-07-29 enum verification campaign tooling; see
|
||||||
|
// docs/research/2026-07-29-enum-verification-campaign.md for the oracle set,
|
||||||
|
// the extraction method, and the open-question ledger.
|
||||||
|
// Hand edits are pinned by PropertyEnumConformanceTests — change the oracle,
|
||||||
|
// not the enum.
|
||||||
|
// </auto-generated-source>
|
||||||
|
|
||||||
|
namespace AcDream.Core.Properties;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// AC's <c>PropertyBool</c> property table — the numeric keys the server sends in
|
||||||
|
/// <c>PrivateUpdatePropertyBool (0x02C9) / PublicUpdatePropertyBool (0x02CA)</c>
|
||||||
|
/// and in the property bundles carried by <c>CreateObject</c> / <c>PlayerDescription</c> /
|
||||||
|
/// <c>IdentifyResponse</c>. The CLR payload for this table is <c>bool</c>.
|
||||||
|
///
|
||||||
|
/// <para>Verified 2026-07-29 against two independent oracles: the vendored
|
||||||
|
/// client-side enum catalog (<c>references/acclientlib/UtilityBelt.Common/Enums/Enums.cs</c>,
|
||||||
|
/// which names this table <c>BoolId</c>) and the 38,985-file ACE weenie export corpus
|
||||||
|
/// (<c>references/weenies/</c>), whose per-stat <c>_comment</c> carries the enum member
|
||||||
|
/// name beside the numeric key. 59 of these 131 members are attested by BOTH
|
||||||
|
/// oracles with zero value conflicts; the remainder are single-sourced from the
|
||||||
|
/// catalog because no weenie in the corpus sets them.</para>
|
||||||
|
///
|
||||||
|
/// <para>This enum is a <b>vocabulary</b>, not a parser contract: the wire carries a raw
|
||||||
|
/// <c>uint</c> and unknown keys must still round-trip untouched, so never assume a
|
||||||
|
/// received key is a defined member.</para>
|
||||||
|
/// </summary>
|
||||||
|
public enum PropertyBool : uint
|
||||||
|
{
|
||||||
|
Undef = 0,
|
||||||
|
/// <summary>21884 weenie attestations.</summary>
|
||||||
|
Stuck = 1,
|
||||||
|
/// <summary>1077 weenie attestations.</summary>
|
||||||
|
Open = 2,
|
||||||
|
/// <summary>646 weenie attestations.</summary>
|
||||||
|
Locked = 3,
|
||||||
|
RotProof = 4,
|
||||||
|
AllegianceUpdateRequest = 5,
|
||||||
|
/// <summary>1282 weenie attestations.</summary>
|
||||||
|
AiUsesMana = 6,
|
||||||
|
/// <summary>16 weenie attestations.</summary>
|
||||||
|
AiUseHumanMagicAnimations = 7,
|
||||||
|
/// <summary>853 weenie attestations.</summary>
|
||||||
|
AllowGive = 8,
|
||||||
|
CurrentlyAttacking = 9,
|
||||||
|
AttackerAi = 10,
|
||||||
|
/// <summary>6212 weenie attestations.</summary>
|
||||||
|
IgnoreCollisions = 11,
|
||||||
|
/// <summary>9020 weenie attestations.</summary>
|
||||||
|
ReportCollisions = 12,
|
||||||
|
/// <summary>15282 weenie attestations.</summary>
|
||||||
|
Ethereal = 13,
|
||||||
|
/// <summary>7376 weenie attestations.</summary>
|
||||||
|
GravityStatus = 14,
|
||||||
|
/// <summary>3382 weenie attestations.</summary>
|
||||||
|
LightsStatus = 15,
|
||||||
|
/// <summary>139 weenie attestations.</summary>
|
||||||
|
ScriptedCollision = 16,
|
||||||
|
/// <summary>475 weenie attestations.</summary>
|
||||||
|
Inelastic = 17,
|
||||||
|
/// <summary>1677 weenie attestations.</summary>
|
||||||
|
Visibility = 18,
|
||||||
|
/// <summary>3972 weenie attestations.</summary>
|
||||||
|
Attackable = 19,
|
||||||
|
SafeSpellComponents = 20,
|
||||||
|
AdvocateState = 21,
|
||||||
|
/// <summary>15455 weenie attestations.</summary>
|
||||||
|
Inscribable = 22,
|
||||||
|
/// <summary>7755 weenie attestations.</summary>
|
||||||
|
DestroyOnSell = 23,
|
||||||
|
/// <summary>6728 weenie attestations.</summary>
|
||||||
|
UiHidden = 24,
|
||||||
|
IgnoreHouseBarriers = 25,
|
||||||
|
HiddenAdmin = 26,
|
||||||
|
PkWounder = 27,
|
||||||
|
PkKiller = 28,
|
||||||
|
/// <summary>262 weenie attestations.</summary>
|
||||||
|
NoCorpse = 29,
|
||||||
|
UnderLifestoneProtection = 30,
|
||||||
|
ItemManaUpdatePending = 31,
|
||||||
|
GeneratorStatus = 32,
|
||||||
|
/// <summary>831 weenie attestations.</summary>
|
||||||
|
ResetMessagePending = 33,
|
||||||
|
/// <summary>831 weenie attestations.</summary>
|
||||||
|
DefaultOpen = 34,
|
||||||
|
/// <summary>511 weenie attestations.</summary>
|
||||||
|
DefaultLocked = 35,
|
||||||
|
DefaultOn = 36,
|
||||||
|
OpenForBusiness = 37,
|
||||||
|
IsFrozen = 38,
|
||||||
|
/// <summary>1049 weenie attestations.</summary>
|
||||||
|
DealMagicalItems = 39,
|
||||||
|
LogoffImDead = 40,
|
||||||
|
/// <summary>2208 weenie attestations.</summary>
|
||||||
|
ReportCollisionsAsEnvironment = 41,
|
||||||
|
/// <summary>1327 weenie attestations.</summary>
|
||||||
|
AllowEdgeSlide = 42,
|
||||||
|
AdvocateQuest = 43,
|
||||||
|
IsAdmin = 44,
|
||||||
|
IsArch = 45,
|
||||||
|
IsSentinel = 46,
|
||||||
|
IsAdvocate = 47,
|
||||||
|
CurrentlyPoweringUp = 48,
|
||||||
|
GeneratorEnteredWorld = 49,
|
||||||
|
/// <summary>890 weenie attestations.</summary>
|
||||||
|
NeverFailCasting = 50,
|
||||||
|
/// <summary>264 weenie attestations.</summary>
|
||||||
|
VendorService = 51,
|
||||||
|
/// <summary>1421 weenie attestations.</summary>
|
||||||
|
AiImmobile = 52,
|
||||||
|
/// <summary>1 weenie attestations.</summary>
|
||||||
|
DamagedByCollisions = 53,
|
||||||
|
/// <summary>34 weenie attestations.</summary>
|
||||||
|
IsDynamic = 54,
|
||||||
|
/// <summary>81 weenie attestations.</summary>
|
||||||
|
IsHot = 55,
|
||||||
|
IsAffecting = 56,
|
||||||
|
/// <summary>49 weenie attestations.</summary>
|
||||||
|
AffectsAis = 57,
|
||||||
|
SpellQueueActive = 58,
|
||||||
|
GeneratorDisabled = 59,
|
||||||
|
IsAcceptingTells = 60,
|
||||||
|
/// <summary>1 weenie attestations.</summary>
|
||||||
|
LoggingChannel = 61,
|
||||||
|
/// <summary>5 weenie attestations.</summary>
|
||||||
|
OpensAnyLock = 62,
|
||||||
|
/// <summary>20 weenie attestations.</summary>
|
||||||
|
UnlimitedUse = 63,
|
||||||
|
GeneratedTreasureItem = 64,
|
||||||
|
/// <summary>97 weenie attestations.</summary>
|
||||||
|
IgnoreMagicResist = 65,
|
||||||
|
/// <summary>87 weenie attestations.</summary>
|
||||||
|
IgnoreMagicArmor = 66,
|
||||||
|
AiAllowTrade = 67,
|
||||||
|
/// <summary>2 weenie attestations.</summary>
|
||||||
|
SpellComponentsRequired = 68,
|
||||||
|
/// <summary>4617 weenie attestations.</summary>
|
||||||
|
IsSellable = 69,
|
||||||
|
/// <summary>4 weenie attestations.</summary>
|
||||||
|
IgnoreShieldsBySkill = 70,
|
||||||
|
/// <summary>6275 weenie attestations.</summary>
|
||||||
|
NoDraw = 71,
|
||||||
|
ActivationUntargeted = 72,
|
||||||
|
HouseHasGottenPriorityBootPos = 73,
|
||||||
|
/// <summary>12 weenie attestations.</summary>
|
||||||
|
GeneratorAutomaticDestruction = 74,
|
||||||
|
HouseHooksVisible = 75,
|
||||||
|
/// <summary>8 weenie attestations.</summary>
|
||||||
|
HouseRequiresMonarch = 76,
|
||||||
|
HouseHooksEnabled = 77,
|
||||||
|
HouseNotifiedHudOfHookCount = 78,
|
||||||
|
/// <summary>15 weenie attestations.</summary>
|
||||||
|
AiAcceptEverything = 79,
|
||||||
|
IgnorePortalRestrictions = 80,
|
||||||
|
/// <summary>5 weenie attestations.</summary>
|
||||||
|
RequiresBackpackSlot = 81,
|
||||||
|
/// <summary>444 weenie attestations.</summary>
|
||||||
|
DontTurnOrMoveWhenGiving = 82,
|
||||||
|
/// <summary>442 weenie attestations.</summary>
|
||||||
|
NpcLooksLikeObject = 83,
|
||||||
|
/// <summary>210 weenie attestations.</summary>
|
||||||
|
IgnoreCloIcons = 84,
|
||||||
|
/// <summary>178 weenie attestations.</summary>
|
||||||
|
AppraisalHasAllowedWielder = 85,
|
||||||
|
ChestRegenOnClose = 86,
|
||||||
|
LogoffInMinigame = 87,
|
||||||
|
/// <summary>17 weenie attestations.</summary>
|
||||||
|
PortalShowDestination = 88,
|
||||||
|
/// <summary>30 weenie attestations.</summary>
|
||||||
|
PortalIgnoresPkAttackTimer = 89,
|
||||||
|
/// <summary>43 weenie attestations.</summary>
|
||||||
|
NpcInteractsSilently = 90,
|
||||||
|
/// <summary>230 weenie attestations.</summary>
|
||||||
|
Retained = 91,
|
||||||
|
/// <summary>1 weenie attestations.</summary>
|
||||||
|
IgnoreAuthor = 92,
|
||||||
|
Limbo = 93,
|
||||||
|
AppraisalHasAllowedActivator = 94,
|
||||||
|
ExistedBeforeAllegianceXpChanges = 95,
|
||||||
|
IsDeaf = 96,
|
||||||
|
IsPsr = 97,
|
||||||
|
Invincible = 98,
|
||||||
|
/// <summary>1068 weenie attestations.</summary>
|
||||||
|
Ivoryable = 99,
|
||||||
|
/// <summary>687 weenie attestations.</summary>
|
||||||
|
Dyable = 100,
|
||||||
|
CanGenerateRare = 101,
|
||||||
|
CorpseGeneratedRare = 102,
|
||||||
|
/// <summary>14 weenie attestations.</summary>
|
||||||
|
NonProjectileMagicImmune = 103,
|
||||||
|
ActdReceivedItems = 104,
|
||||||
|
Unknown105 = 105,
|
||||||
|
FirstEnterWorldDone = 106,
|
||||||
|
RecallsDisabled = 107,
|
||||||
|
/// <summary>13 weenie attestations.</summary>
|
||||||
|
RareUsesTimer = 108,
|
||||||
|
ActdPreorderReceivedItems = 109,
|
||||||
|
Afk = 110,
|
||||||
|
IsGagged = 111,
|
||||||
|
ProcSpellSelfTargeted = 112,
|
||||||
|
IsAllegianceGagged = 113,
|
||||||
|
EquipmentSetTriggerPiece = 114,
|
||||||
|
Uninscribe = 115,
|
||||||
|
WieldOnUse = 116,
|
||||||
|
ChestClearedWhenClosed = 117,
|
||||||
|
NeverAttack = 118,
|
||||||
|
SuppressGenerateEffect = 119,
|
||||||
|
TreasureCorpse = 120,
|
||||||
|
EquipmentSetAddLevel = 121,
|
||||||
|
BarberActive = 122,
|
||||||
|
TopLayerPriority = 123,
|
||||||
|
NoHeldItemShown = 124,
|
||||||
|
LoginAtLifestone = 125,
|
||||||
|
OlthoiPk = 126,
|
||||||
|
Account15Days = 127,
|
||||||
|
HadNoVitae = 128,
|
||||||
|
NoOlthoiTalk = 129,
|
||||||
|
/// <summary>14 weenie attestations.</summary>
|
||||||
|
AutowieldLeft = 130,
|
||||||
|
}
|
||||||
134
src/AcDream.Core/Properties/PropertyDataId.cs
Normal file
134
src/AcDream.Core/Properties/PropertyDataId.cs
Normal file
|
|
@ -0,0 +1,134 @@
|
||||||
|
// <auto-generated-source>
|
||||||
|
// Regenerate with the 2026-07-29 enum verification campaign tooling; see
|
||||||
|
// docs/research/2026-07-29-enum-verification-campaign.md for the oracle set,
|
||||||
|
// the extraction method, and the open-question ledger.
|
||||||
|
// Hand edits are pinned by PropertyEnumConformanceTests — change the oracle,
|
||||||
|
// not the enum.
|
||||||
|
// </auto-generated-source>
|
||||||
|
|
||||||
|
namespace AcDream.Core.Properties;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// AC's <c>PropertyDataId</c> property table — the numeric keys the server sends in
|
||||||
|
/// <c>PrivateUpdatePropertyDataId (0x02E1) / PublicUpdatePropertyDataId (0x02E2)</c>
|
||||||
|
/// and in the property bundles carried by <c>CreateObject</c> / <c>PlayerDescription</c> /
|
||||||
|
/// <c>IdentifyResponse</c>. The CLR payload for this table is <c>uint (DAT file id)</c>.
|
||||||
|
///
|
||||||
|
/// <para>Verified 2026-07-29 against two independent oracles: the vendored
|
||||||
|
/// client-side enum catalog (<c>references/acclientlib/UtilityBelt.Common/Enums/Enums.cs</c>,
|
||||||
|
/// which names this table <c>DataId</c>) and the 38,985-file ACE weenie export corpus
|
||||||
|
/// (<c>references/weenies/</c>), whose per-stat <c>_comment</c> carries the enum member
|
||||||
|
/// name beside the numeric key. 41 of these 62 members are attested by BOTH
|
||||||
|
/// oracles with zero value conflicts; the remainder are single-sourced from the
|
||||||
|
/// catalog because no weenie in the corpus sets them.</para>
|
||||||
|
///
|
||||||
|
/// <para>This enum is a <b>vocabulary</b>, not a parser contract: the wire carries a raw
|
||||||
|
/// <c>uint</c> and unknown keys must still round-trip untouched, so never assume a
|
||||||
|
/// received key is a defined member.</para>
|
||||||
|
/// </summary>
|
||||||
|
public enum PropertyDataId : uint
|
||||||
|
{
|
||||||
|
Undef = 0,
|
||||||
|
/// <summary>38985 weenie attestations.</summary>
|
||||||
|
Setup = 1,
|
||||||
|
/// <summary>12219 weenie attestations.</summary>
|
||||||
|
MotionTable = 2,
|
||||||
|
/// <summary>23696 weenie attestations.</summary>
|
||||||
|
SoundTable = 3,
|
||||||
|
/// <summary>4319 weenie attestations.</summary>
|
||||||
|
CombatTable = 4,
|
||||||
|
/// <summary>2 weenie attestations.</summary>
|
||||||
|
QualityFilter = 5,
|
||||||
|
/// <summary>13875 weenie attestations.</summary>
|
||||||
|
PaletteBase = 6,
|
||||||
|
/// <summary>9049 weenie attestations.</summary>
|
||||||
|
ClothingBase = 7,
|
||||||
|
/// <summary>38985 weenie attestations.</summary>
|
||||||
|
Icon = 8,
|
||||||
|
/// <summary>741 weenie attestations.</summary>
|
||||||
|
EyesTexture = 9,
|
||||||
|
/// <summary>741 weenie attestations.</summary>
|
||||||
|
NoseTexture = 10,
|
||||||
|
/// <summary>741 weenie attestations.</summary>
|
||||||
|
MouthTexture = 11,
|
||||||
|
DefaultEyesTexture = 12,
|
||||||
|
DefaultNoseTexture = 13,
|
||||||
|
DefaultMouthTexture = 14,
|
||||||
|
/// <summary>741 weenie attestations.</summary>
|
||||||
|
HairPalette = 15,
|
||||||
|
/// <summary>741 weenie attestations.</summary>
|
||||||
|
EyesPalette = 16,
|
||||||
|
/// <summary>741 weenie attestations.</summary>
|
||||||
|
SkinPalette = 17,
|
||||||
|
HeadObject = 18,
|
||||||
|
/// <summary>4 weenie attestations.</summary>
|
||||||
|
ActivationAnimation = 19,
|
||||||
|
/// <summary>4 weenie attestations.</summary>
|
||||||
|
InitMotion = 20,
|
||||||
|
ActivationSound = 21,
|
||||||
|
/// <summary>23266 weenie attestations.</summary>
|
||||||
|
PhysicsEffectTable = 22,
|
||||||
|
/// <summary>138 weenie attestations.</summary>
|
||||||
|
UseSound = 23,
|
||||||
|
/// <summary>48 weenie attestations.</summary>
|
||||||
|
UseTargetAnimation = 24,
|
||||||
|
/// <summary>4 weenie attestations.</summary>
|
||||||
|
UseTargetSuccessAnimation = 25,
|
||||||
|
/// <summary>2 weenie attestations.</summary>
|
||||||
|
UseTargetFailureAnimation = 26,
|
||||||
|
/// <summary>232 weenie attestations.</summary>
|
||||||
|
UseUserAnimation = 27,
|
||||||
|
/// <summary>3696 weenie attestations.</summary>
|
||||||
|
Spell = 28,
|
||||||
|
/// <summary>156 weenie attestations.</summary>
|
||||||
|
SpellComponent = 29,
|
||||||
|
/// <summary>794 weenie attestations.</summary>
|
||||||
|
PhysicsScript = 30,
|
||||||
|
/// <summary>497 weenie attestations.</summary>
|
||||||
|
LinkedPortalOne = 31,
|
||||||
|
/// <summary>861 weenie attestations.</summary>
|
||||||
|
WieldedTreasureType = 32,
|
||||||
|
/// <summary>5 weenie attestations.</summary>
|
||||||
|
UnknownGuessedname = 33,
|
||||||
|
UnknownGuessedname2 = 34,
|
||||||
|
/// <summary>2000 weenie attestations.</summary>
|
||||||
|
DeathTreasureType = 35,
|
||||||
|
/// <summary>2276 weenie attestations.</summary>
|
||||||
|
MutateFilter = 36,
|
||||||
|
/// <summary>1253 weenie attestations.</summary>
|
||||||
|
ItemSkillLimit = 37,
|
||||||
|
/// <summary>1 weenie attestations.</summary>
|
||||||
|
UseCreateItem = 38,
|
||||||
|
DeathSpell = 39,
|
||||||
|
VendorsClassId = 40,
|
||||||
|
/// <summary>13 weenie attestations.</summary>
|
||||||
|
ItemSpecializedOnly = 41,
|
||||||
|
/// <summary>6274 weenie attestations.</summary>
|
||||||
|
HouseId = 42,
|
||||||
|
AccountHouseId = 43,
|
||||||
|
/// <summary>6274 weenie attestations.</summary>
|
||||||
|
RestrictionEffect = 44,
|
||||||
|
CreationMutationFilter = 45,
|
||||||
|
/// <summary>584 weenie attestations.</summary>
|
||||||
|
TsysMutationFilter = 46,
|
||||||
|
LastPortal = 47,
|
||||||
|
/// <summary>1 weenie attestations.</summary>
|
||||||
|
LinkedPortalTwo = 48,
|
||||||
|
OriginalPortal = 49,
|
||||||
|
/// <summary>1000 weenie attestations.</summary>
|
||||||
|
IconOverlay = 50,
|
||||||
|
/// <summary>16 weenie attestations.</summary>
|
||||||
|
IconOverlaySecondary = 51,
|
||||||
|
/// <summary>554 weenie attestations.</summary>
|
||||||
|
IconUnderlay = 52,
|
||||||
|
AugmentationMutationFilter = 53,
|
||||||
|
AugmentationEffect = 54,
|
||||||
|
/// <summary>84 weenie attestations.</summary>
|
||||||
|
ProcSpell = 55,
|
||||||
|
AugmentationCreateItem = 56,
|
||||||
|
AlternateCurrency = 57,
|
||||||
|
BlueSurgeSpell = 58,
|
||||||
|
YellowSurgeSpell = 59,
|
||||||
|
RedSurgeSpell = 60,
|
||||||
|
OlthoiDeathTreasureType = 61,
|
||||||
|
}
|
||||||
289
src/AcDream.Core/Properties/PropertyFloat.cs
Normal file
289
src/AcDream.Core/Properties/PropertyFloat.cs
Normal file
|
|
@ -0,0 +1,289 @@
|
||||||
|
// <auto-generated-source>
|
||||||
|
// Regenerate with the 2026-07-29 enum verification campaign tooling; see
|
||||||
|
// docs/research/2026-07-29-enum-verification-campaign.md for the oracle set,
|
||||||
|
// the extraction method, and the open-question ledger.
|
||||||
|
// Hand edits are pinned by PropertyEnumConformanceTests — change the oracle,
|
||||||
|
// not the enum.
|
||||||
|
// </auto-generated-source>
|
||||||
|
|
||||||
|
namespace AcDream.Core.Properties;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// AC's <c>PropertyFloat</c> property table — the numeric keys the server sends in
|
||||||
|
/// <c>PrivateUpdatePropertyFloat (0x02D5) / PublicUpdatePropertyFloat (0x02D6)</c>
|
||||||
|
/// and in the property bundles carried by <c>CreateObject</c> / <c>PlayerDescription</c> /
|
||||||
|
/// <c>IdentifyResponse</c>. The CLR payload for this table is <c>double</c>.
|
||||||
|
///
|
||||||
|
/// <para>Verified 2026-07-29 against two independent oracles: the vendored
|
||||||
|
/// client-side enum catalog (<c>references/acclientlib/UtilityBelt.Common/Enums/Enums.cs</c>,
|
||||||
|
/// which names this table <c>FloatId</c>) and the 38,985-file ACE weenie export corpus
|
||||||
|
/// (<c>references/weenies/</c>), whose per-stat <c>_comment</c> carries the enum member
|
||||||
|
/// name beside the numeric key. 86 of these 172 members are attested by BOTH
|
||||||
|
/// oracles with zero value conflicts; the remainder are single-sourced from the
|
||||||
|
/// catalog because no weenie in the corpus sets them.</para>
|
||||||
|
///
|
||||||
|
/// <para>This enum is a <b>vocabulary</b>, not a parser contract: the wire carries a raw
|
||||||
|
/// <c>uint</c> and unknown keys must still round-trip untouched, so never assume a
|
||||||
|
/// received key is a defined member.</para>
|
||||||
|
/// </summary>
|
||||||
|
public enum PropertyFloat : uint
|
||||||
|
{
|
||||||
|
Undef = 0,
|
||||||
|
/// <summary>4243 weenie attestations.</summary>
|
||||||
|
HeartbeatInterval = 1,
|
||||||
|
/// <summary>4243 weenie attestations.</summary>
|
||||||
|
HeartbeatTimestamp = 2,
|
||||||
|
/// <summary>4361 weenie attestations.</summary>
|
||||||
|
HealthRate = 3,
|
||||||
|
/// <summary>4361 weenie attestations.</summary>
|
||||||
|
StaminaRate = 4,
|
||||||
|
/// <summary>7706 weenie attestations.</summary>
|
||||||
|
ManaRate = 5,
|
||||||
|
/// <summary>79 weenie attestations.</summary>
|
||||||
|
HealthUponResurrection = 6,
|
||||||
|
/// <summary>79 weenie attestations.</summary>
|
||||||
|
StaminaUponResurrection = 7,
|
||||||
|
/// <summary>79 weenie attestations.</summary>
|
||||||
|
ManaUponResurrection = 8,
|
||||||
|
StartTime = 9,
|
||||||
|
StopTime = 10,
|
||||||
|
/// <summary>1749 weenie attestations.</summary>
|
||||||
|
ResetInterval = 11,
|
||||||
|
/// <summary>3290 weenie attestations.</summary>
|
||||||
|
Shade = 12,
|
||||||
|
/// <summary>6001 weenie attestations.</summary>
|
||||||
|
ArmorModVsSlash = 13,
|
||||||
|
/// <summary>6005 weenie attestations.</summary>
|
||||||
|
ArmorModVsPierce = 14,
|
||||||
|
/// <summary>6005 weenie attestations.</summary>
|
||||||
|
ArmorModVsBludgeon = 15,
|
||||||
|
/// <summary>6005 weenie attestations.</summary>
|
||||||
|
ArmorModVsCold = 16,
|
||||||
|
/// <summary>6005 weenie attestations.</summary>
|
||||||
|
ArmorModVsFire = 17,
|
||||||
|
/// <summary>6005 weenie attestations.</summary>
|
||||||
|
ArmorModVsAcid = 18,
|
||||||
|
/// <summary>6005 weenie attestations.</summary>
|
||||||
|
ArmorModVsElectric = 19,
|
||||||
|
CombatSpeed = 20,
|
||||||
|
/// <summary>2733 weenie attestations.</summary>
|
||||||
|
WeaponLength = 21,
|
||||||
|
/// <summary>3174 weenie attestations.</summary>
|
||||||
|
DamageVariance = 22,
|
||||||
|
CurrentPowerMod = 23,
|
||||||
|
AccuracyMod = 24,
|
||||||
|
StrengthMod = 25,
|
||||||
|
/// <summary>1386 weenie attestations.</summary>
|
||||||
|
MaximumVelocity = 26,
|
||||||
|
/// <summary>233 weenie attestations.</summary>
|
||||||
|
RotationSpeed = 27,
|
||||||
|
MotionTimestamp = 28,
|
||||||
|
/// <summary>3892 weenie attestations.</summary>
|
||||||
|
WeaponDefense = 29,
|
||||||
|
WimpyLevel = 30,
|
||||||
|
/// <summary>2169 weenie attestations.</summary>
|
||||||
|
VisualAwarenessRange = 31,
|
||||||
|
AuralAwarenessRange = 32,
|
||||||
|
PerceptionLevel = 33,
|
||||||
|
/// <summary>1987 weenie attestations.</summary>
|
||||||
|
PowerupTime = 34,
|
||||||
|
MaxChargeDistance = 35,
|
||||||
|
/// <summary>1892 weenie attestations.</summary>
|
||||||
|
ChargeSpeed = 36,
|
||||||
|
/// <summary>1049 weenie attestations.</summary>
|
||||||
|
BuyPrice = 37,
|
||||||
|
/// <summary>1049 weenie attestations.</summary>
|
||||||
|
SellPrice = 38,
|
||||||
|
/// <summary>18233 weenie attestations.</summary>
|
||||||
|
DefaultScale = 39,
|
||||||
|
/// <summary>10 weenie attestations.</summary>
|
||||||
|
LockpickMod = 40,
|
||||||
|
/// <summary>2195 weenie attestations.</summary>
|
||||||
|
RegenerationInterval = 41,
|
||||||
|
RegenerationTimestamp = 42,
|
||||||
|
/// <summary>2135 weenie attestations.</summary>
|
||||||
|
GeneratorRadius = 43,
|
||||||
|
/// <summary>66 weenie attestations.</summary>
|
||||||
|
TimeToRot = 44,
|
||||||
|
DeathTimestamp = 45,
|
||||||
|
PkTimestamp = 46,
|
||||||
|
VictimTimestamp = 47,
|
||||||
|
LoginTimestamp = 48,
|
||||||
|
CreationTimestamp = 49,
|
||||||
|
/// <summary>4 weenie attestations.</summary>
|
||||||
|
MinimumTimeSincePk = 50,
|
||||||
|
DeprecatedHousekeepingPriority = 51,
|
||||||
|
AbuseLoggingTimestamp = 52,
|
||||||
|
LastPortalTeleportTimestamp = 53,
|
||||||
|
/// <summary>9152 weenie attestations.</summary>
|
||||||
|
UseRadius = 54,
|
||||||
|
/// <summary>46 weenie attestations.</summary>
|
||||||
|
HomeRadius = 55,
|
||||||
|
ReleasedTimestamp = 56,
|
||||||
|
MinHomeRadius = 57,
|
||||||
|
Facing = 58,
|
||||||
|
ResetTimestamp = 59,
|
||||||
|
LogoffTimestamp = 60,
|
||||||
|
EconRecoveryInterval = 61,
|
||||||
|
/// <summary>3523 weenie attestations.</summary>
|
||||||
|
WeaponOffense = 62,
|
||||||
|
/// <summary>1223 weenie attestations.</summary>
|
||||||
|
DamageMod = 63,
|
||||||
|
/// <summary>4361 weenie attestations.</summary>
|
||||||
|
ResistSlash = 64,
|
||||||
|
/// <summary>4361 weenie attestations.</summary>
|
||||||
|
ResistPierce = 65,
|
||||||
|
/// <summary>4361 weenie attestations.</summary>
|
||||||
|
ResistBludgeon = 66,
|
||||||
|
/// <summary>4361 weenie attestations.</summary>
|
||||||
|
ResistFire = 67,
|
||||||
|
/// <summary>4361 weenie attestations.</summary>
|
||||||
|
ResistCold = 68,
|
||||||
|
/// <summary>4361 weenie attestations.</summary>
|
||||||
|
ResistAcid = 69,
|
||||||
|
/// <summary>4361 weenie attestations.</summary>
|
||||||
|
ResistElectric = 70,
|
||||||
|
/// <summary>4361 weenie attestations.</summary>
|
||||||
|
ResistHealthBoost = 71,
|
||||||
|
/// <summary>4361 weenie attestations.</summary>
|
||||||
|
ResistStaminaDrain = 72,
|
||||||
|
/// <summary>4361 weenie attestations.</summary>
|
||||||
|
ResistStaminaBoost = 73,
|
||||||
|
/// <summary>4361 weenie attestations.</summary>
|
||||||
|
ResistManaDrain = 74,
|
||||||
|
/// <summary>4361 weenie attestations.</summary>
|
||||||
|
ResistManaBoost = 75,
|
||||||
|
/// <summary>794 weenie attestations.</summary>
|
||||||
|
Translucency = 76,
|
||||||
|
/// <summary>269 weenie attestations.</summary>
|
||||||
|
PhysicsScriptIntensity = 77,
|
||||||
|
/// <summary>761 weenie attestations.</summary>
|
||||||
|
Friction = 78,
|
||||||
|
/// <summary>761 weenie attestations.</summary>
|
||||||
|
Elasticity = 79,
|
||||||
|
/// <summary>1076 weenie attestations.</summary>
|
||||||
|
AiUseMagicDelay = 80,
|
||||||
|
ItemMinSpellcraftMod = 81,
|
||||||
|
ItemMaxSpellcraftMod = 82,
|
||||||
|
ItemRankProbability = 83,
|
||||||
|
Shade2 = 84,
|
||||||
|
Shade3 = 85,
|
||||||
|
Shade4 = 86,
|
||||||
|
/// <summary>15 weenie attestations.</summary>
|
||||||
|
ItemEfficiency = 87,
|
||||||
|
ItemManaUpdateTimestamp = 88,
|
||||||
|
SpellGestureSpeedMod = 89,
|
||||||
|
SpellStanceSpeedMod = 90,
|
||||||
|
AllegianceAppraisalTimestamp = 91,
|
||||||
|
PowerLevel = 92,
|
||||||
|
AccuracyLevel = 93,
|
||||||
|
AttackAngle = 94,
|
||||||
|
AttackTimestamp = 95,
|
||||||
|
CheckpointTimestamp = 96,
|
||||||
|
SoldTimestamp = 97,
|
||||||
|
UseTimestamp = 98,
|
||||||
|
UseLockTimestamp = 99,
|
||||||
|
/// <summary>22 weenie attestations.</summary>
|
||||||
|
HealkitMod = 100,
|
||||||
|
FrozenTimestamp = 101,
|
||||||
|
HealthRateMod = 102,
|
||||||
|
AllegianceSwearTimestamp = 103,
|
||||||
|
/// <summary>4361 weenie attestations.</summary>
|
||||||
|
ObviousRadarRange = 104,
|
||||||
|
/// <summary>81 weenie attestations.</summary>
|
||||||
|
HotspotCycleTime = 105,
|
||||||
|
/// <summary>74 weenie attestations.</summary>
|
||||||
|
HotspotCycleTimeVariance = 106,
|
||||||
|
SpamTimestamp = 107,
|
||||||
|
SpamRate = 108,
|
||||||
|
/// <summary>26 weenie attestations.</summary>
|
||||||
|
BondWieldedTreasure = 109,
|
||||||
|
/// <summary>1039 weenie attestations.</summary>
|
||||||
|
BulkMod = 110,
|
||||||
|
/// <summary>1039 weenie attestations.</summary>
|
||||||
|
SizeMod = 111,
|
||||||
|
GagTimestamp = 112,
|
||||||
|
GeneratorUpdateTimestamp = 113,
|
||||||
|
DeathSpamTimestamp = 114,
|
||||||
|
DeathSpamRate = 115,
|
||||||
|
WildAttackProbability = 116,
|
||||||
|
/// <summary>312 weenie attestations.</summary>
|
||||||
|
FocusedProbability = 117,
|
||||||
|
CrashAndTurnProbability = 118,
|
||||||
|
CrashAndTurnRadius = 119,
|
||||||
|
CrashAndTurnBias = 120,
|
||||||
|
/// <summary>186 weenie attestations.</summary>
|
||||||
|
GeneratorInitialDelay = 121,
|
||||||
|
/// <summary>575 weenie attestations.</summary>
|
||||||
|
AiAcquireHealth = 122,
|
||||||
|
/// <summary>6 weenie attestations.</summary>
|
||||||
|
AiAcquireStamina = 123,
|
||||||
|
/// <summary>6 weenie attestations.</summary>
|
||||||
|
AiAcquireMana = 124,
|
||||||
|
/// <summary>4361 weenie attestations.</summary>
|
||||||
|
ResistHealthDrain = 125,
|
||||||
|
LifestoneProtectionTimestamp = 126,
|
||||||
|
/// <summary>72 weenie attestations.</summary>
|
||||||
|
AiCounteractEnchantment = 127,
|
||||||
|
/// <summary>10 weenie attestations.</summary>
|
||||||
|
AiDispelEnchantment = 128,
|
||||||
|
TradeTimestamp = 129,
|
||||||
|
AiTargetedDetectionRadius = 130,
|
||||||
|
/// <summary>29 weenie attestations.</summary>
|
||||||
|
EmotePriority = 131,
|
||||||
|
LastTeleportStartTimestamp = 132,
|
||||||
|
EventSpamTimestamp = 133,
|
||||||
|
EventSpamRate = 134,
|
||||||
|
/// <summary>5 weenie attestations.</summary>
|
||||||
|
InventoryOffset = 135,
|
||||||
|
/// <summary>396 weenie attestations.</summary>
|
||||||
|
CriticalMultiplier = 136,
|
||||||
|
/// <summary>15 weenie attestations.</summary>
|
||||||
|
ManaStoneDestroyChance = 137,
|
||||||
|
/// <summary>351 weenie attestations.</summary>
|
||||||
|
SlayerDamageBonus = 138,
|
||||||
|
AllegianceInfoSpamTimestamp = 139,
|
||||||
|
AllegianceInfoSpamRate = 140,
|
||||||
|
NextSpellcastTimestamp = 141,
|
||||||
|
AppraisalRequestedTimestamp = 142,
|
||||||
|
AppraisalHeartbeatDueTimestamp = 143,
|
||||||
|
/// <summary>209 weenie attestations.</summary>
|
||||||
|
ManaConversionMod = 144,
|
||||||
|
LastPkAttackTimestamp = 145,
|
||||||
|
FellowshipUpdateTimestamp = 146,
|
||||||
|
/// <summary>395 weenie attestations.</summary>
|
||||||
|
CriticalFrequency = 147,
|
||||||
|
LimboStartTimestamp = 148,
|
||||||
|
/// <summary>356 weenie attestations.</summary>
|
||||||
|
WeaponMissileDefense = 149,
|
||||||
|
/// <summary>368 weenie attestations.</summary>
|
||||||
|
WeaponMagicDefense = 150,
|
||||||
|
/// <summary>87 weenie attestations.</summary>
|
||||||
|
IgnoreShield = 151,
|
||||||
|
/// <summary>135 weenie attestations.</summary>
|
||||||
|
ElementalDamageMod = 152,
|
||||||
|
StartMissileAttackTimestamp = 153,
|
||||||
|
LastRareUsedTimestamp = 154,
|
||||||
|
/// <summary>69 weenie attestations.</summary>
|
||||||
|
IgnoreArmor = 155,
|
||||||
|
ProcSpellRate = 156,
|
||||||
|
/// <summary>93 weenie attestations.</summary>
|
||||||
|
ResistanceModifier = 157,
|
||||||
|
AllegianceGagTimestamp = 158,
|
||||||
|
/// <summary>18 weenie attestations.</summary>
|
||||||
|
AbsorbMagicDamage = 159,
|
||||||
|
CachedMaxAbsorbMagicDamage = 160,
|
||||||
|
GagDuration = 161,
|
||||||
|
AllegianceGagDuration = 162,
|
||||||
|
GlobalXpMod = 163,
|
||||||
|
HealingModifier = 164,
|
||||||
|
/// <summary>391 weenie attestations.</summary>
|
||||||
|
ArmorModVsNether = 165,
|
||||||
|
ResistNether = 166,
|
||||||
|
/// <summary>369 weenie attestations.</summary>
|
||||||
|
CooldownDuration = 167,
|
||||||
|
WeaponAuraOffense = 168,
|
||||||
|
WeaponAuraDefense = 169,
|
||||||
|
WeaponAuraElemental = 170,
|
||||||
|
WeaponAuraManaConv = 171,
|
||||||
|
}
|
||||||
79
src/AcDream.Core/Properties/PropertyInstanceId.cs
Normal file
79
src/AcDream.Core/Properties/PropertyInstanceId.cs
Normal file
|
|
@ -0,0 +1,79 @@
|
||||||
|
// <auto-generated-source>
|
||||||
|
// Regenerate with the 2026-07-29 enum verification campaign tooling; see
|
||||||
|
// docs/research/2026-07-29-enum-verification-campaign.md for the oracle set,
|
||||||
|
// the extraction method, and the open-question ledger.
|
||||||
|
// Hand edits are pinned by PropertyEnumConformanceTests — change the oracle,
|
||||||
|
// not the enum.
|
||||||
|
// </auto-generated-source>
|
||||||
|
|
||||||
|
namespace AcDream.Core.Properties;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// AC's <c>PropertyInstanceId</c> property table — the numeric keys the server sends in
|
||||||
|
/// <c>PrivateUpdatePropertyInstanceId (0x02E5) / PublicUpdatePropertyInstanceId (0x02E6)</c>
|
||||||
|
/// and in the property bundles carried by <c>CreateObject</c> / <c>PlayerDescription</c> /
|
||||||
|
/// <c>IdentifyResponse</c>. The CLR payload for this table is <c>uint (object guid)</c>.
|
||||||
|
///
|
||||||
|
/// <para>Verified 2026-07-29 against two independent oracles: the vendored
|
||||||
|
/// client-side enum catalog (<c>references/acclientlib/UtilityBelt.Common/Enums/Enums.cs</c>,
|
||||||
|
/// which names this table <c>InstanceId</c>) and the 38,985-file ACE weenie export corpus
|
||||||
|
/// (<c>references/weenies/</c>), whose per-stat <c>_comment</c> carries the enum member
|
||||||
|
/// name beside the numeric key. 2 of these 46 members are attested by BOTH
|
||||||
|
/// oracles with zero value conflicts; the remainder are single-sourced from the
|
||||||
|
/// catalog because no weenie in the corpus sets them.</para>
|
||||||
|
///
|
||||||
|
/// <para>This enum is a <b>vocabulary</b>, not a parser contract: the wire carries a raw
|
||||||
|
/// <c>uint</c> and unknown keys must still round-trip untouched, so never assume a
|
||||||
|
/// received key is a defined member.</para>
|
||||||
|
/// </summary>
|
||||||
|
public enum PropertyInstanceId : uint
|
||||||
|
{
|
||||||
|
Undef = 0,
|
||||||
|
Owner = 1,
|
||||||
|
Container = 2,
|
||||||
|
Wielder = 3,
|
||||||
|
Freezer = 4,
|
||||||
|
Viewer = 5,
|
||||||
|
Generator = 6,
|
||||||
|
Scribe = 7,
|
||||||
|
CurrentCombatTarget = 8,
|
||||||
|
CurrentEnemy = 9,
|
||||||
|
ProjectileLauncher = 10,
|
||||||
|
CurrentAttacker = 11,
|
||||||
|
CurrentDamager = 12,
|
||||||
|
CurrentFollowTarget = 13,
|
||||||
|
CurrentAppraisalTarget = 14,
|
||||||
|
CurrentFellowshipAppraisalTarget = 15,
|
||||||
|
/// <summary>130 weenie attestations.</summary>
|
||||||
|
ActivationTarget = 16,
|
||||||
|
Creator = 17,
|
||||||
|
Victim = 18,
|
||||||
|
Killer = 19,
|
||||||
|
Vendor = 20,
|
||||||
|
Customer = 21,
|
||||||
|
Bonded = 22,
|
||||||
|
Wounder = 23,
|
||||||
|
Allegiance = 24,
|
||||||
|
Patron = 25,
|
||||||
|
Monarch = 26,
|
||||||
|
CombatTarget = 27,
|
||||||
|
HealthQueryTarget = 28,
|
||||||
|
LastUnlocker = 29,
|
||||||
|
CrashAndTurnTarget = 30,
|
||||||
|
AllowedActivator = 31,
|
||||||
|
HouseOwner = 32,
|
||||||
|
House = 33,
|
||||||
|
Slumlord = 34,
|
||||||
|
ManaQueryTarget = 35,
|
||||||
|
CurrentGame = 36,
|
||||||
|
RequestedAppraisalTarget = 37,
|
||||||
|
/// <summary>2 weenie attestations.</summary>
|
||||||
|
AllowedWielder = 38,
|
||||||
|
AssignedTarget = 39,
|
||||||
|
LimboSource = 40,
|
||||||
|
Snooper = 41,
|
||||||
|
TeleportedCharacter = 42,
|
||||||
|
Pet = 43,
|
||||||
|
PetOwner = 44,
|
||||||
|
PetDevice = 45,
|
||||||
|
}
|
||||||
611
src/AcDream.Core/Properties/PropertyInt.cs
Normal file
611
src/AcDream.Core/Properties/PropertyInt.cs
Normal file
|
|
@ -0,0 +1,611 @@
|
||||||
|
// <auto-generated-source>
|
||||||
|
// Regenerate with the 2026-07-29 enum verification campaign tooling; see
|
||||||
|
// docs/research/2026-07-29-enum-verification-campaign.md for the oracle set,
|
||||||
|
// the extraction method, and the open-question ledger.
|
||||||
|
// Hand edits are pinned by PropertyEnumConformanceTests — change the oracle,
|
||||||
|
// not the enum.
|
||||||
|
// </auto-generated-source>
|
||||||
|
|
||||||
|
namespace AcDream.Core.Properties;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// AC's <c>PropertyInt</c> property table — the numeric keys the server sends in
|
||||||
|
/// <c>PrivateUpdatePropertyInt (0x02CD) / PublicUpdatePropertyInt (0x02CE)</c>
|
||||||
|
/// and in the property bundles carried by <c>CreateObject</c> / <c>PlayerDescription</c> /
|
||||||
|
/// <c>IdentifyResponse</c>. The CLR payload for this table is <c>int</c>.
|
||||||
|
///
|
||||||
|
/// <para>Verified 2026-07-29 against two independent oracles: the vendored
|
||||||
|
/// client-side enum catalog (<c>references/acclientlib/UtilityBelt.Common/Enums/Enums.cs</c>,
|
||||||
|
/// which names this table <c>IntId</c>) and the 38,985-file ACE weenie export corpus
|
||||||
|
/// (<c>references/weenies/</c>), whose per-stat <c>_comment</c> carries the enum member
|
||||||
|
/// name beside the numeric key. 189 of these 391 members are attested by BOTH
|
||||||
|
/// oracles with zero value conflicts; the remainder are single-sourced from the
|
||||||
|
/// catalog because no weenie in the corpus sets them.</para>
|
||||||
|
///
|
||||||
|
/// <para>This enum is a <b>vocabulary</b>, not a parser contract: the wire carries a raw
|
||||||
|
/// <c>uint</c> and unknown keys must still round-trip untouched, so never assume a
|
||||||
|
/// received key is a defined member.</para>
|
||||||
|
/// </summary>
|
||||||
|
public enum PropertyInt : uint
|
||||||
|
{
|
||||||
|
Undef = 0,
|
||||||
|
/// <summary>UtilityBelt catalog calls this <c>ObjectType</c>; 37329 weenie attestations.</summary>
|
||||||
|
ItemType = 1,
|
||||||
|
/// <summary>6140 weenie attestations.</summary>
|
||||||
|
CreatureType = 2,
|
||||||
|
/// <summary>8344 weenie attestations.</summary>
|
||||||
|
PaletteTemplate = 3,
|
||||||
|
/// <summary>1597 weenie attestations.</summary>
|
||||||
|
ClothingPriority = 4,
|
||||||
|
/// <summary>25793 weenie attestations.</summary>
|
||||||
|
EncumbranceVal = 5,
|
||||||
|
/// <summary>8633 weenie attestations.</summary>
|
||||||
|
ItemsCapacity = 6,
|
||||||
|
/// <summary>8618 weenie attestations.</summary>
|
||||||
|
ContainersCapacity = 7,
|
||||||
|
/// <summary>23605 weenie attestations.</summary>
|
||||||
|
Mass = 8,
|
||||||
|
/// <summary>20797 weenie attestations.</summary>
|
||||||
|
ValidLocations = 9,
|
||||||
|
CurrentWieldedLocation = 10,
|
||||||
|
/// <summary>4373 weenie attestations.</summary>
|
||||||
|
MaxStackSize = 11,
|
||||||
|
/// <summary>4373 weenie attestations.</summary>
|
||||||
|
StackSize = 12,
|
||||||
|
/// <summary>3181 weenie attestations.</summary>
|
||||||
|
StackUnitEncumbrance = 13,
|
||||||
|
/// <summary>3181 weenie attestations.</summary>
|
||||||
|
StackUnitMass = 14,
|
||||||
|
/// <summary>3181 weenie attestations.</summary>
|
||||||
|
StackUnitValue = 15,
|
||||||
|
/// <summary>37280 weenie attestations.</summary>
|
||||||
|
ItemUseable = 16,
|
||||||
|
/// <summary>21 weenie attestations.</summary>
|
||||||
|
RareId = 17,
|
||||||
|
/// <summary>5705 weenie attestations.</summary>
|
||||||
|
UiEffects = 18,
|
||||||
|
/// <summary>25852 weenie attestations.</summary>
|
||||||
|
Value = 19,
|
||||||
|
/// <summary>1 weenie attestations.</summary>
|
||||||
|
CoinValue = 20,
|
||||||
|
TotalExperience = 21,
|
||||||
|
AvailableCharacter = 22,
|
||||||
|
TotalSkillCredits = 23,
|
||||||
|
AvailableSkillCredits = 24,
|
||||||
|
/// <summary>6140 weenie attestations.</summary>
|
||||||
|
Level = 25,
|
||||||
|
/// <summary>28 weenie attestations.</summary>
|
||||||
|
AccountRequirements = 26,
|
||||||
|
/// <summary>5476 weenie attestations.</summary>
|
||||||
|
ArmorType = 27,
|
||||||
|
/// <summary>1657 weenie attestations.</summary>
|
||||||
|
ArmorLevel = 28,
|
||||||
|
AllegianceCpPool = 29,
|
||||||
|
/// <summary>1 weenie attestations.</summary>
|
||||||
|
AllegianceRank = 30,
|
||||||
|
ChannelsAllowed = 31,
|
||||||
|
ChannelsActive = 32,
|
||||||
|
/// <summary>6252 weenie attestations.</summary>
|
||||||
|
Bonded = 33,
|
||||||
|
MonarchsRank = 34,
|
||||||
|
AllegianceFollowers = 35,
|
||||||
|
/// <summary>997 weenie attestations.</summary>
|
||||||
|
ResistMagic = 36,
|
||||||
|
/// <summary>575 weenie attestations.</summary>
|
||||||
|
ResistItemAppraisal = 37,
|
||||||
|
/// <summary>677 weenie attestations.</summary>
|
||||||
|
ResistLockpick = 38,
|
||||||
|
DeprecatedResistRepair = 39,
|
||||||
|
/// <summary>1634 weenie attestations.</summary>
|
||||||
|
CombatMode = 40,
|
||||||
|
CurrentAttackHeight = 41,
|
||||||
|
CombatCollisions = 42,
|
||||||
|
/// <summary>1 weenie attestations.</summary>
|
||||||
|
NumDeaths = 43,
|
||||||
|
/// <summary>3717 weenie attestations.</summary>
|
||||||
|
Damage = 44,
|
||||||
|
/// <summary>3357 weenie attestations.</summary>
|
||||||
|
DamageType = 45,
|
||||||
|
/// <summary>2973 weenie attestations.</summary>
|
||||||
|
DefaultCombatStyle = 46,
|
||||||
|
/// <summary>2364 weenie attestations.</summary>
|
||||||
|
AttackType = 47,
|
||||||
|
/// <summary>3393 weenie attestations.</summary>
|
||||||
|
WeaponSkill = 48,
|
||||||
|
/// <summary>3394 weenie attestations.</summary>
|
||||||
|
WeaponTime = 49,
|
||||||
|
/// <summary>972 weenie attestations.</summary>
|
||||||
|
AmmoType = 50,
|
||||||
|
/// <summary>4499 weenie attestations.</summary>
|
||||||
|
CombatUse = 51,
|
||||||
|
/// <summary>440 weenie attestations.</summary>
|
||||||
|
ParentLocation = 52,
|
||||||
|
/// <summary>440 weenie attestations.</summary>
|
||||||
|
PlacementPosition = 53,
|
||||||
|
WeaponEncumbrance = 54,
|
||||||
|
WeaponMass = 55,
|
||||||
|
ShieldValue = 56,
|
||||||
|
ShieldEncumbrance = 57,
|
||||||
|
MissileInventoryLocation = 58,
|
||||||
|
FullDamageType = 59,
|
||||||
|
/// <summary>545 weenie attestations.</summary>
|
||||||
|
WeaponRange = 60,
|
||||||
|
AttackersSkill = 61,
|
||||||
|
DefendersSkill = 62,
|
||||||
|
AttackersSkillValue = 63,
|
||||||
|
AttackersClass = 64,
|
||||||
|
Placement = 65,
|
||||||
|
/// <summary>179 weenie attestations.</summary>
|
||||||
|
CheckpointStatus = 66,
|
||||||
|
/// <summary>219 weenie attestations.</summary>
|
||||||
|
Tolerance = 67,
|
||||||
|
/// <summary>2151 weenie attestations.</summary>
|
||||||
|
TargetingTactic = 68,
|
||||||
|
/// <summary>48 weenie attestations.</summary>
|
||||||
|
CombatTactic = 69,
|
||||||
|
HomesickTargetingTactic = 70,
|
||||||
|
NumFollowFailures = 71,
|
||||||
|
/// <summary>494 weenie attestations.</summary>
|
||||||
|
FriendType = 72,
|
||||||
|
FoeType = 73,
|
||||||
|
/// <summary>UtilityBelt catalog calls this <c>MerchandiseObjectTypes</c>; 1049 weenie attestations.</summary>
|
||||||
|
MerchandiseItemTypes = 74,
|
||||||
|
/// <summary>1049 weenie attestations.</summary>
|
||||||
|
MerchandiseMinValue = 75,
|
||||||
|
/// <summary>1049 weenie attestations.</summary>
|
||||||
|
MerchandiseMaxValue = 76,
|
||||||
|
NumItemsSold = 77,
|
||||||
|
NumItemsBought = 78,
|
||||||
|
MoneyIncome = 79,
|
||||||
|
MoneyOutflow = 80,
|
||||||
|
/// <summary>2195 weenie attestations.</summary>
|
||||||
|
MaxGeneratedObjects = 81,
|
||||||
|
/// <summary>2195 weenie attestations.</summary>
|
||||||
|
InitGeneratedObjects = 82,
|
||||||
|
/// <summary>787 weenie attestations.</summary>
|
||||||
|
ActivationResponse = 83,
|
||||||
|
OriginalValue = 84,
|
||||||
|
NumMoveFailures = 85,
|
||||||
|
/// <summary>815 weenie attestations.</summary>
|
||||||
|
MinLevel = 86,
|
||||||
|
/// <summary>115 weenie attestations.</summary>
|
||||||
|
MaxLevel = 87,
|
||||||
|
/// <summary>10 weenie attestations.</summary>
|
||||||
|
LockpickMod = 88,
|
||||||
|
/// <summary>525 weenie attestations.</summary>
|
||||||
|
BoosterEnum = 89,
|
||||||
|
/// <summary>532 weenie attestations.</summary>
|
||||||
|
BoostValue = 90,
|
||||||
|
/// <summary>800 weenie attestations.</summary>
|
||||||
|
MaxStructure = 91,
|
||||||
|
/// <summary>713 weenie attestations.</summary>
|
||||||
|
Structure = 92,
|
||||||
|
/// <summary>38985 weenie attestations.</summary>
|
||||||
|
PhysicsState = 93,
|
||||||
|
/// <summary>3570 weenie attestations.</summary>
|
||||||
|
TargetType = 94,
|
||||||
|
/// <summary>2668 weenie attestations.</summary>
|
||||||
|
RadarBlipColor = 95,
|
||||||
|
/// <summary>472 weenie attestations.</summary>
|
||||||
|
EncumbranceCapacity = 96,
|
||||||
|
LoginTimestamp = 97,
|
||||||
|
/// <summary>119 weenie attestations.</summary>
|
||||||
|
CreationTimestamp = 98,
|
||||||
|
/// <summary>4 weenie attestations.</summary>
|
||||||
|
PkLevelModifier = 99,
|
||||||
|
/// <summary>575 weenie attestations.</summary>
|
||||||
|
GeneratorType = 100,
|
||||||
|
/// <summary>1265 weenie attestations.</summary>
|
||||||
|
AiAllowedCombatStyle = 101,
|
||||||
|
LogoffTimestamp = 102,
|
||||||
|
/// <summary>158 weenie attestations.</summary>
|
||||||
|
GeneratorDestructionType = 103,
|
||||||
|
ActivationCreateClass = 104,
|
||||||
|
/// <summary>693 weenie attestations.</summary>
|
||||||
|
ItemWorkmanship = 105,
|
||||||
|
/// <summary>4213 weenie attestations.</summary>
|
||||||
|
ItemSpellcraft = 106,
|
||||||
|
/// <summary>4173 weenie attestations.</summary>
|
||||||
|
ItemCurMana = 107,
|
||||||
|
/// <summary>4211 weenie attestations.</summary>
|
||||||
|
ItemMaxMana = 108,
|
||||||
|
/// <summary>3091 weenie attestations.</summary>
|
||||||
|
ItemDifficulty = 109,
|
||||||
|
/// <summary>1043 weenie attestations.</summary>
|
||||||
|
ItemAllegianceRankLimit = 110,
|
||||||
|
/// <summary>2940 weenie attestations.</summary>
|
||||||
|
PortalBitmask = 111,
|
||||||
|
AdvocateLevel = 112,
|
||||||
|
/// <summary>749 weenie attestations.</summary>
|
||||||
|
Gender = 113,
|
||||||
|
/// <summary>4502 weenie attestations.</summary>
|
||||||
|
Attuned = 114,
|
||||||
|
/// <summary>1640 weenie attestations.</summary>
|
||||||
|
ItemSkillLevelLimit = 115,
|
||||||
|
GateLogic = 116,
|
||||||
|
/// <summary>66 weenie attestations.</summary>
|
||||||
|
ItemManaCost = 117,
|
||||||
|
Logoff = 118,
|
||||||
|
/// <summary>365 weenie attestations.</summary>
|
||||||
|
Active = 119,
|
||||||
|
AttackHeight = 120,
|
||||||
|
NumAttackFailures = 121,
|
||||||
|
AiCpThreshold = 122,
|
||||||
|
AiAdvancementStrategy = 123,
|
||||||
|
Version = 124,
|
||||||
|
/// <summary>1 weenie attestations.</summary>
|
||||||
|
Age = 125,
|
||||||
|
/// <summary>1048 weenie attestations.</summary>
|
||||||
|
VendorHappyMean = 126,
|
||||||
|
/// <summary>1048 weenie attestations.</summary>
|
||||||
|
VendorHappyVariance = 127,
|
||||||
|
CloakStatus = 128,
|
||||||
|
VitaeCpPool = 129,
|
||||||
|
NumServicesSold = 130,
|
||||||
|
/// <summary>586 weenie attestations.</summary>
|
||||||
|
MaterialType = 131,
|
||||||
|
NumAllegianceBreaks = 132,
|
||||||
|
/// <summary>10541 weenie attestations.</summary>
|
||||||
|
ShowableOnRadar = 133,
|
||||||
|
/// <summary>3138 weenie attestations.</summary>
|
||||||
|
PlayerKillerStatus = 134,
|
||||||
|
VendorHappyMaxItems = 135,
|
||||||
|
/// <summary>5 weenie attestations.</summary>
|
||||||
|
ScorePageNum = 136,
|
||||||
|
/// <summary>5 weenie attestations.</summary>
|
||||||
|
ScoreConfigNum = 137,
|
||||||
|
/// <summary>5 weenie attestations.</summary>
|
||||||
|
ScoreNumScores = 138,
|
||||||
|
DeathLevel = 139,
|
||||||
|
/// <summary>1411 weenie attestations.</summary>
|
||||||
|
AiOptions = 140,
|
||||||
|
OpenToEveryone = 141,
|
||||||
|
/// <summary>297 weenie attestations.</summary>
|
||||||
|
GeneratorTimeType = 142,
|
||||||
|
/// <summary>51 weenie attestations.</summary>
|
||||||
|
GeneratorStartTime = 143,
|
||||||
|
/// <summary>50 weenie attestations.</summary>
|
||||||
|
GeneratorEndTime = 144,
|
||||||
|
/// <summary>257 weenie attestations.</summary>
|
||||||
|
GeneratorEndDestructionType = 145,
|
||||||
|
/// <summary>4361 weenie attestations.</summary>
|
||||||
|
XpOverride = 146,
|
||||||
|
NumCrashAndTurns = 147,
|
||||||
|
ComponentWarningThreshold = 148,
|
||||||
|
/// <summary>7 weenie attestations.</summary>
|
||||||
|
HouseStatus = 149,
|
||||||
|
/// <summary>4715 weenie attestations.</summary>
|
||||||
|
HookPlacement = 150,
|
||||||
|
/// <summary>6799 weenie attestations.</summary>
|
||||||
|
HookType = 151,
|
||||||
|
/// <summary>UtilityBelt catalog calls this <c>HookObjectType</c>; 5 weenie attestations.</summary>
|
||||||
|
HookItemType = 152,
|
||||||
|
AiPpThreshold = 153,
|
||||||
|
GeneratorVersion = 154,
|
||||||
|
/// <summary>6274 weenie attestations.</summary>
|
||||||
|
HouseType = 155,
|
||||||
|
/// <summary>10 weenie attestations.</summary>
|
||||||
|
PickupEmoteOffset = 156,
|
||||||
|
/// <summary>1 weenie attestations.</summary>
|
||||||
|
WeenieIteration = 157,
|
||||||
|
/// <summary>2557 weenie attestations.</summary>
|
||||||
|
WieldRequirements = 158,
|
||||||
|
/// <summary>2557 weenie attestations.</summary>
|
||||||
|
WieldSkilltype = 159,
|
||||||
|
/// <summary>2557 weenie attestations.</summary>
|
||||||
|
WieldDifficulty = 160,
|
||||||
|
/// <summary>654 weenie attestations.</summary>
|
||||||
|
HouseMaxHooksUsable = 161,
|
||||||
|
HouseCurrentHooksUsable = 162,
|
||||||
|
/// <summary>8 weenie attestations.</summary>
|
||||||
|
AllegianceMinLevel = 163,
|
||||||
|
AllegianceMaxLevel = 164,
|
||||||
|
HouseRelinkHookCount = 165,
|
||||||
|
/// <summary>537 weenie attestations.</summary>
|
||||||
|
SlayerCreatureType = 166,
|
||||||
|
ConfirmationInProgress = 167,
|
||||||
|
ConfirmationTypeInProgress = 168,
|
||||||
|
/// <summary>728 weenie attestations.</summary>
|
||||||
|
TsysMutationData = 169,
|
||||||
|
/// <summary>36 weenie attestations.</summary>
|
||||||
|
NumItemsInMaterial = 170,
|
||||||
|
/// <summary>228 weenie attestations.</summary>
|
||||||
|
NumTimesTinkered = 171,
|
||||||
|
/// <summary>358 weenie attestations.</summary>
|
||||||
|
AppraisalLongDescDecoration = 172,
|
||||||
|
/// <summary>133 weenie attestations.</summary>
|
||||||
|
AppraisalLockpickSuccessPercent = 173,
|
||||||
|
/// <summary>103 weenie attestations.</summary>
|
||||||
|
AppraisalPages = 174,
|
||||||
|
/// <summary>103 weenie attestations.</summary>
|
||||||
|
AppraisalMaxPages = 175,
|
||||||
|
/// <summary>355 weenie attestations.</summary>
|
||||||
|
AppraisalItemSkill = 176,
|
||||||
|
/// <summary>281 weenie attestations.</summary>
|
||||||
|
GemCount = 177,
|
||||||
|
/// <summary>281 weenie attestations.</summary>
|
||||||
|
GemType = 178,
|
||||||
|
/// <summary>495 weenie attestations.</summary>
|
||||||
|
ImbuedEffect = 179,
|
||||||
|
AttackersRawSkillValue = 180,
|
||||||
|
ChessRank = 181,
|
||||||
|
ChessTotalGames = 182,
|
||||||
|
ChessGamesWon = 183,
|
||||||
|
ChessGamesLost = 184,
|
||||||
|
/// <summary>71 weenie attestations.</summary>
|
||||||
|
TypeOfAlteration = 185,
|
||||||
|
/// <summary>71 weenie attestations.</summary>
|
||||||
|
SkillToBeAltered = 186,
|
||||||
|
SkillAlterationCount = 187,
|
||||||
|
/// <summary>807 weenie attestations.</summary>
|
||||||
|
HeritageGroup = 188,
|
||||||
|
/// <summary>30 weenie attestations.</summary>
|
||||||
|
TransferFromAttribute = 189,
|
||||||
|
/// <summary>30 weenie attestations.</summary>
|
||||||
|
TransferToAttribute = 190,
|
||||||
|
AttributeTransferCount = 191,
|
||||||
|
FakeFishingSkill = 192,
|
||||||
|
/// <summary>3 weenie attestations.</summary>
|
||||||
|
NumKeys = 193,
|
||||||
|
DeathTimestamp = 194,
|
||||||
|
PkTimestamp = 195,
|
||||||
|
VictimTimestamp = 196,
|
||||||
|
/// <summary>22 weenie attestations.</summary>
|
||||||
|
HookGroup = 197,
|
||||||
|
AllegianceSwearTimestamp = 198,
|
||||||
|
HousePurchaseTimestamp = 199,
|
||||||
|
RedirectableEquippedArmorCount = 200,
|
||||||
|
MeleedefenseImbuedEffectTypeCache = 201,
|
||||||
|
MissileDefenseImbuedEffectTypeCache = 202,
|
||||||
|
MagicDefenseImbuedEffectTypeCache = 203,
|
||||||
|
/// <summary>121 weenie attestations.</summary>
|
||||||
|
ElementalDamageBonus = 204,
|
||||||
|
ImbueAttempts = 205,
|
||||||
|
ImbueSuccesses = 206,
|
||||||
|
CreatureKills = 207,
|
||||||
|
PlayerKillsPk = 208,
|
||||||
|
PlayerKillsPkl = 209,
|
||||||
|
RaresTierOne = 210,
|
||||||
|
RaresTierTwo = 211,
|
||||||
|
RaresTierThree = 212,
|
||||||
|
RaresTierFour = 213,
|
||||||
|
RaresTierFive = 214,
|
||||||
|
AugmentationStat = 215,
|
||||||
|
AugmentationFamilyStat = 216,
|
||||||
|
AugmentationInnateFamily = 217,
|
||||||
|
AugmentationInnateStrength = 218,
|
||||||
|
AugmentationInnateEndurance = 219,
|
||||||
|
AugmentationInnateCoordination = 220,
|
||||||
|
AugmentationInnateQuickness = 221,
|
||||||
|
AugmentationInnateFocus = 222,
|
||||||
|
AugmentationInnateSelf = 223,
|
||||||
|
AugmentationSpecializeSalvaging = 224,
|
||||||
|
AugmentationSpecializeItemTinkering = 225,
|
||||||
|
AugmentationSpecializeArmorTinkering = 226,
|
||||||
|
AugmentationSpecializeMagicItemTinkering = 227,
|
||||||
|
AugmentationSpecializeWeaponTinkering = 228,
|
||||||
|
AugmentationExtraPackSlot = 229,
|
||||||
|
AugmentationIncreasedCarryingCapacity = 230,
|
||||||
|
AugmentationLessDeathItemLoss = 231,
|
||||||
|
AugmentationSpellsRemainPastDeath = 232,
|
||||||
|
AugmentationCriticalDefense = 233,
|
||||||
|
AugmentationBonusXp = 234,
|
||||||
|
AugmentationBonusSalvage = 235,
|
||||||
|
AugmentationBonusImbueChance = 236,
|
||||||
|
AugmentationFasterRegen = 237,
|
||||||
|
AugmentationIncreasedSpellDuration = 238,
|
||||||
|
AugmentationResistanceFamily = 239,
|
||||||
|
AugmentationResistanceSlash = 240,
|
||||||
|
AugmentationResistancePierce = 241,
|
||||||
|
AugmentationResistanceBlunt = 242,
|
||||||
|
AugmentationResistanceAcid = 243,
|
||||||
|
AugmentationResistanceFire = 244,
|
||||||
|
AugmentationResistanceFrost = 245,
|
||||||
|
AugmentationResistanceLightning = 246,
|
||||||
|
RaresTierOneLogin = 247,
|
||||||
|
RaresTierTwoLogin = 248,
|
||||||
|
RaresTierThreeLogin = 249,
|
||||||
|
RaresTierFourLogin = 250,
|
||||||
|
RaresTierFiveLogin = 251,
|
||||||
|
RaresLoginTimestamp = 252,
|
||||||
|
RaresTierSix = 253,
|
||||||
|
RaresTierSeven = 254,
|
||||||
|
RaresTierSixLogin = 255,
|
||||||
|
RaresTierSevenLogin = 256,
|
||||||
|
/// <summary>1 weenie attestations.</summary>
|
||||||
|
ItemAttributeLimit = 257,
|
||||||
|
/// <summary>1 weenie attestations.</summary>
|
||||||
|
ItemAttributeLevelLimit = 258,
|
||||||
|
ItemAttribute2ndLimit = 259,
|
||||||
|
ItemAttribute2ndLevelLimit = 260,
|
||||||
|
/// <summary>2 weenie attestations.</summary>
|
||||||
|
CharacterTitleId = 261,
|
||||||
|
/// <summary>1 weenie attestations.</summary>
|
||||||
|
NumCharacterTitles = 262,
|
||||||
|
/// <summary>93 weenie attestations.</summary>
|
||||||
|
ResistanceModifierType = 263,
|
||||||
|
FreeTinkersBitfield = 264,
|
||||||
|
/// <summary>316 weenie attestations.</summary>
|
||||||
|
EquipmentSetId = 265,
|
||||||
|
PetClass = 266,
|
||||||
|
/// <summary>119 weenie attestations.</summary>
|
||||||
|
Lifespan = 267,
|
||||||
|
/// <summary>119 weenie attestations.</summary>
|
||||||
|
RemainingLifespan = 268,
|
||||||
|
UseCreateQuantity = 269,
|
||||||
|
/// <summary>62 weenie attestations.</summary>
|
||||||
|
WieldRequirements2 = 270,
|
||||||
|
/// <summary>62 weenie attestations.</summary>
|
||||||
|
WieldSkilltype2 = 271,
|
||||||
|
/// <summary>62 weenie attestations.</summary>
|
||||||
|
WieldDifficulty2 = 272,
|
||||||
|
/// <summary>3 weenie attestations.</summary>
|
||||||
|
WieldRequirements3 = 273,
|
||||||
|
/// <summary>3 weenie attestations.</summary>
|
||||||
|
WieldSkilltype3 = 274,
|
||||||
|
/// <summary>3 weenie attestations.</summary>
|
||||||
|
WieldDifficulty3 = 275,
|
||||||
|
/// <summary>17 weenie attestations.</summary>
|
||||||
|
WieldRequirements4 = 276,
|
||||||
|
/// <summary>17 weenie attestations.</summary>
|
||||||
|
WieldSkilltype4 = 277,
|
||||||
|
/// <summary>17 weenie attestations.</summary>
|
||||||
|
WieldDifficulty4 = 278,
|
||||||
|
/// <summary>14 weenie attestations.</summary>
|
||||||
|
Unique = 279,
|
||||||
|
/// <summary>365 weenie attestations.</summary>
|
||||||
|
SharedCooldown = 280,
|
||||||
|
/// <summary>177 weenie attestations.</summary>
|
||||||
|
Faction1Bits = 281,
|
||||||
|
Faction2Bits = 282,
|
||||||
|
Faction3Bits = 283,
|
||||||
|
Hatred1Bits = 284,
|
||||||
|
Hatred2Bits = 285,
|
||||||
|
Hatred3Bits = 286,
|
||||||
|
/// <summary>61 weenie attestations.</summary>
|
||||||
|
SocietyRankCelhan = 287,
|
||||||
|
/// <summary>60 weenie attestations.</summary>
|
||||||
|
SocietyRankEldweb = 288,
|
||||||
|
/// <summary>56 weenie attestations.</summary>
|
||||||
|
SocietyRankRadblo = 289,
|
||||||
|
HearLocalSignals = 290,
|
||||||
|
HearLocalSignalsRadius = 291,
|
||||||
|
/// <summary>67 weenie attestations.</summary>
|
||||||
|
Cleaving = 292,
|
||||||
|
AugmentationSpecializeGearcraft = 293,
|
||||||
|
AugmentationInfusedCreatureMagic = 294,
|
||||||
|
AugmentationInfusedItemMagic = 295,
|
||||||
|
AugmentationInfusedLifeMagic = 296,
|
||||||
|
AugmentationInfusedWarMagic = 297,
|
||||||
|
AugmentationCriticalExpertise = 298,
|
||||||
|
AugmentationCriticalPower = 299,
|
||||||
|
AugmentationSkilledMelee = 300,
|
||||||
|
AugmentationSkilledMissile = 301,
|
||||||
|
AugmentationSkilledMagic = 302,
|
||||||
|
/// <summary>124 weenie attestations.</summary>
|
||||||
|
ImbuedEffect2 = 303,
|
||||||
|
/// <summary>124 weenie attestations.</summary>
|
||||||
|
ImbuedEffect3 = 304,
|
||||||
|
/// <summary>117 weenie attestations.</summary>
|
||||||
|
ImbuedEffect4 = 305,
|
||||||
|
/// <summary>117 weenie attestations.</summary>
|
||||||
|
ImbuedEffect5 = 306,
|
||||||
|
/// <summary>1403 weenie attestations.</summary>
|
||||||
|
DamageRating = 307,
|
||||||
|
/// <summary>729 weenie attestations.</summary>
|
||||||
|
DamageResistRating = 308,
|
||||||
|
AugmentationDamageBonus = 309,
|
||||||
|
AugmentationDamageReduction = 310,
|
||||||
|
ImbueStackingBits = 311,
|
||||||
|
HealOverTime = 312,
|
||||||
|
/// <summary>880 weenie attestations.</summary>
|
||||||
|
CritRating = 313,
|
||||||
|
/// <summary>843 weenie attestations.</summary>
|
||||||
|
CritDamageRating = 314,
|
||||||
|
/// <summary>713 weenie attestations.</summary>
|
||||||
|
CritResistRating = 315,
|
||||||
|
/// <summary>732 weenie attestations.</summary>
|
||||||
|
CritDamageResistRating = 316,
|
||||||
|
HealingResistRating = 317,
|
||||||
|
DamageOverTime = 318,
|
||||||
|
/// <summary>79 weenie attestations.</summary>
|
||||||
|
ItemMaxLevel = 319,
|
||||||
|
/// <summary>79 weenie attestations.</summary>
|
||||||
|
ItemXpStyle = 320,
|
||||||
|
EquipmentSetExtra = 321,
|
||||||
|
AetheriaBitfield = 322,
|
||||||
|
HealingBoostRating = 323,
|
||||||
|
/// <summary>29 weenie attestations.</summary>
|
||||||
|
HeritageSpecificArmor = 324,
|
||||||
|
AlternateRacialSkills = 325,
|
||||||
|
AugmentationJackOfAllTrades = 326,
|
||||||
|
AugmentationResistanceNether = 327,
|
||||||
|
AugmentationInfusedVoidMagic = 328,
|
||||||
|
WeaknessRating = 329,
|
||||||
|
NetherOverTime = 330,
|
||||||
|
NetherResistRating = 331,
|
||||||
|
LuminanceAward = 332,
|
||||||
|
LumAugDamageRating = 333,
|
||||||
|
LumAugDamageReductionRating = 334,
|
||||||
|
LumAugCritDamageRating = 335,
|
||||||
|
LumAugCritReductionRating = 336,
|
||||||
|
LumAugSurgeEffectRating = 337,
|
||||||
|
LumAugSurgeChanceRating = 338,
|
||||||
|
LumAugItemManaUsage = 339,
|
||||||
|
LumAugItemManaGain = 340,
|
||||||
|
LumAugVitality = 341,
|
||||||
|
LumAugHealingRating = 342,
|
||||||
|
LumAugSkilledCraft = 343,
|
||||||
|
LumAugSkilledSpec = 344,
|
||||||
|
LumAugNoDestroyCraft = 345,
|
||||||
|
RestrictInteraction = 346,
|
||||||
|
OlthoiLootTimestamp = 347,
|
||||||
|
OlthoiLootStep = 348,
|
||||||
|
UseCreatesContractId = 349,
|
||||||
|
DotResistRating = 350,
|
||||||
|
LifeResistRating = 351,
|
||||||
|
/// <summary>13 weenie attestations.</summary>
|
||||||
|
CloakWeaveProc = 352,
|
||||||
|
/// <summary>492 weenie attestations.</summary>
|
||||||
|
WeaponType = 353,
|
||||||
|
MeleeMastery = 354,
|
||||||
|
RangedMastery = 355,
|
||||||
|
SneakAttackRating = 356,
|
||||||
|
RecklessnessRating = 357,
|
||||||
|
DeceptionRating = 358,
|
||||||
|
CombatPetRange = 359,
|
||||||
|
WeaponAuraDamage = 360,
|
||||||
|
WeaponAuraSpeed = 361,
|
||||||
|
SummoningMastery = 362,
|
||||||
|
HeartbeatLifespan = 363,
|
||||||
|
UseLevelRequirement = 364,
|
||||||
|
LumAugAllSkills = 365,
|
||||||
|
/// <summary>259 weenie attestations.</summary>
|
||||||
|
UseRequiresSkill = 366,
|
||||||
|
/// <summary>259 weenie attestations.</summary>
|
||||||
|
UseRequiresSkillLevel = 367,
|
||||||
|
/// <summary>36 weenie attestations.</summary>
|
||||||
|
UseRequiresSkillSpec = 368,
|
||||||
|
/// <summary>271 weenie attestations.</summary>
|
||||||
|
UseRequiresLevel = 369,
|
||||||
|
/// <summary>869 weenie attestations.</summary>
|
||||||
|
GearDamage = 370,
|
||||||
|
/// <summary>868 weenie attestations.</summary>
|
||||||
|
GearDamageResist = 371,
|
||||||
|
/// <summary>854 weenie attestations.</summary>
|
||||||
|
GearCrit = 372,
|
||||||
|
/// <summary>854 weenie attestations.</summary>
|
||||||
|
GearCritResist = 373,
|
||||||
|
/// <summary>955 weenie attestations.</summary>
|
||||||
|
GearCritDamage = 374,
|
||||||
|
/// <summary>953 weenie attestations.</summary>
|
||||||
|
GearCritDamageResist = 375,
|
||||||
|
/// <summary>610 weenie attestations.</summary>
|
||||||
|
GearHealingBoost = 376,
|
||||||
|
/// <summary>602 weenie attestations.</summary>
|
||||||
|
GearNetherResist = 377,
|
||||||
|
/// <summary>602 weenie attestations.</summary>
|
||||||
|
GearLifeResist = 378,
|
||||||
|
/// <summary>640 weenie attestations.</summary>
|
||||||
|
GearMaxHealth = 379,
|
||||||
|
Unknown380 = 380,
|
||||||
|
/// <summary>616 weenie attestations.</summary>
|
||||||
|
PKDamageRating = 381,
|
||||||
|
/// <summary>602 weenie attestations.</summary>
|
||||||
|
PKDamageResistRating = 382,
|
||||||
|
/// <summary>643 weenie attestations.</summary>
|
||||||
|
GearPKDamageRating = 383,
|
||||||
|
/// <summary>640 weenie attestations.</summary>
|
||||||
|
GearPKDamageResistRating = 384,
|
||||||
|
Unknown385 = 385,
|
||||||
|
/// <summary>766 weenie attestations.</summary>
|
||||||
|
Overpower = 386,
|
||||||
|
/// <summary>602 weenie attestations.</summary>
|
||||||
|
OverpowerResist = 387,
|
||||||
|
/// <summary>602 weenie attestations.</summary>
|
||||||
|
GearOverpower = 388,
|
||||||
|
/// <summary>602 weenie attestations.</summary>
|
||||||
|
GearOverpowerResist = 389,
|
||||||
|
/// <summary>2 weenie attestations.</summary>
|
||||||
|
Enlightenment = 390,
|
||||||
|
}
|
||||||
43
src/AcDream.Core/Properties/PropertyInt64.cs
Normal file
43
src/AcDream.Core/Properties/PropertyInt64.cs
Normal file
|
|
@ -0,0 +1,43 @@
|
||||||
|
// <auto-generated-source>
|
||||||
|
// Regenerate with the 2026-07-29 enum verification campaign tooling; see
|
||||||
|
// docs/research/2026-07-29-enum-verification-campaign.md for the oracle set,
|
||||||
|
// the extraction method, and the open-question ledger.
|
||||||
|
// Hand edits are pinned by PropertyEnumConformanceTests — change the oracle,
|
||||||
|
// not the enum.
|
||||||
|
// </auto-generated-source>
|
||||||
|
|
||||||
|
namespace AcDream.Core.Properties;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// AC's <c>PropertyInt64</c> property table — the numeric keys the server sends in
|
||||||
|
/// <c>PrivateUpdatePropertyInt64 (0x02D1)</c>
|
||||||
|
/// and in the property bundles carried by <c>CreateObject</c> / <c>PlayerDescription</c> /
|
||||||
|
/// <c>IdentifyResponse</c>. The CLR payload for this table is <c>long</c>.
|
||||||
|
///
|
||||||
|
/// <para>Verified 2026-07-29 against two independent oracles: the vendored
|
||||||
|
/// client-side enum catalog (<c>references/acclientlib/UtilityBelt.Common/Enums/Enums.cs</c>,
|
||||||
|
/// which names this table <c>Int64Id</c>) and the 38,985-file ACE weenie export corpus
|
||||||
|
/// (<c>references/weenies/</c>), whose per-stat <c>_comment</c> carries the enum member
|
||||||
|
/// name beside the numeric key. 3 of these 9 members are attested by BOTH
|
||||||
|
/// oracles with zero value conflicts; the remainder are single-sourced from the
|
||||||
|
/// catalog because no weenie in the corpus sets them.</para>
|
||||||
|
///
|
||||||
|
/// <para>This enum is a <b>vocabulary</b>, not a parser contract: the wire carries a raw
|
||||||
|
/// <c>uint</c> and unknown keys must still round-trip untouched, so never assume a
|
||||||
|
/// received key is a defined member.</para>
|
||||||
|
/// </summary>
|
||||||
|
public enum PropertyInt64 : uint
|
||||||
|
{
|
||||||
|
Undef = 0,
|
||||||
|
TotalExperience = 1,
|
||||||
|
AvailableExperience = 2,
|
||||||
|
/// <summary>7 weenie attestations.</summary>
|
||||||
|
AugmentationCost = 3,
|
||||||
|
/// <summary>79 weenie attestations.</summary>
|
||||||
|
ItemTotalXp = 4,
|
||||||
|
/// <summary>79 weenie attestations.</summary>
|
||||||
|
ItemBaseXp = 5,
|
||||||
|
AvailableLuminance = 6,
|
||||||
|
MaximumLuminance = 7,
|
||||||
|
InteractionReqs = 8,
|
||||||
|
}
|
||||||
112
src/AcDream.Core/Properties/PropertyString.cs
Normal file
112
src/AcDream.Core/Properties/PropertyString.cs
Normal file
|
|
@ -0,0 +1,112 @@
|
||||||
|
// <auto-generated-source>
|
||||||
|
// Regenerate with the 2026-07-29 enum verification campaign tooling; see
|
||||||
|
// docs/research/2026-07-29-enum-verification-campaign.md for the oracle set,
|
||||||
|
// the extraction method, and the open-question ledger.
|
||||||
|
// Hand edits are pinned by PropertyEnumConformanceTests — change the oracle,
|
||||||
|
// not the enum.
|
||||||
|
// </auto-generated-source>
|
||||||
|
|
||||||
|
namespace AcDream.Core.Properties;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// AC's <c>PropertyString</c> property table — the numeric keys the server sends in
|
||||||
|
/// <c>PrivateUpdatePropertyString (0x02DD) / PublicUpdatePropertyString (0x02DE)</c>
|
||||||
|
/// and in the property bundles carried by <c>CreateObject</c> / <c>PlayerDescription</c> /
|
||||||
|
/// <c>IdentifyResponse</c>. The CLR payload for this table is <c>string</c>.
|
||||||
|
///
|
||||||
|
/// <para>Verified 2026-07-29 against two independent oracles: the vendored
|
||||||
|
/// client-side enum catalog (<c>references/acclientlib/UtilityBelt.Common/Enums/Enums.cs</c>,
|
||||||
|
/// which names this table <c>StringId</c>) and the 38,985-file ACE weenie export corpus
|
||||||
|
/// (<c>references/weenies/</c>), whose per-stat <c>_comment</c> carries the enum member
|
||||||
|
/// name beside the numeric key. 28 of these 53 members are attested by BOTH
|
||||||
|
/// oracles with zero value conflicts; the remainder are single-sourced from the
|
||||||
|
/// catalog because no weenie in the corpus sets them.</para>
|
||||||
|
///
|
||||||
|
/// <para>This enum is a <b>vocabulary</b>, not a parser contract: the wire carries a raw
|
||||||
|
/// <c>uint</c> and unknown keys must still round-trip untouched, so never assume a
|
||||||
|
/// received key is a defined member.</para>
|
||||||
|
/// </summary>
|
||||||
|
public enum PropertyString : uint
|
||||||
|
{
|
||||||
|
Undef = 0,
|
||||||
|
/// <summary>38984 weenie attestations.</summary>
|
||||||
|
Name = 1,
|
||||||
|
Title = 2,
|
||||||
|
/// <summary>1697 weenie attestations.</summary>
|
||||||
|
Sex = 3,
|
||||||
|
/// <summary>1693 weenie attestations.</summary>
|
||||||
|
HeritageGroup = 4,
|
||||||
|
/// <summary>1622 weenie attestations.</summary>
|
||||||
|
Template = 5,
|
||||||
|
AttackersName = 6,
|
||||||
|
/// <summary>93 weenie attestations.</summary>
|
||||||
|
Inscription = 7,
|
||||||
|
/// <summary>93 weenie attestations.</summary>
|
||||||
|
ScribeName = 8,
|
||||||
|
VendorsName = 9,
|
||||||
|
/// <summary>1 weenie attestations.</summary>
|
||||||
|
Fellowship = 10,
|
||||||
|
MonarchsName = 11,
|
||||||
|
/// <summary>449 weenie attestations.</summary>
|
||||||
|
LockCode = 12,
|
||||||
|
/// <summary>238 weenie attestations.</summary>
|
||||||
|
KeyCode = 13,
|
||||||
|
/// <summary>3219 weenie attestations.</summary>
|
||||||
|
Use = 14,
|
||||||
|
/// <summary>5597 weenie attestations.</summary>
|
||||||
|
ShortDesc = 15,
|
||||||
|
/// <summary>7107 weenie attestations.</summary>
|
||||||
|
LongDesc = 16,
|
||||||
|
/// <summary>109 weenie attestations.</summary>
|
||||||
|
ActivationTalk = 17,
|
||||||
|
/// <summary>10 weenie attestations.</summary>
|
||||||
|
UseMessage = 18,
|
||||||
|
/// <summary>45 weenie attestations.</summary>
|
||||||
|
ItemHeritageGroupRestriction = 19,
|
||||||
|
/// <summary>1318 weenie attestations.</summary>
|
||||||
|
PluralName = 20,
|
||||||
|
MonarchsTitle = 21,
|
||||||
|
/// <summary>96 weenie attestations.</summary>
|
||||||
|
ActivationFailure = 22,
|
||||||
|
ScribeAccount = 23,
|
||||||
|
/// <summary>591 weenie attestations.</summary>
|
||||||
|
TownName = 24,
|
||||||
|
/// <summary>2 weenie attestations.</summary>
|
||||||
|
CraftsmanName = 25,
|
||||||
|
/// <summary>4 weenie attestations.</summary>
|
||||||
|
UsePkServerError = 26,
|
||||||
|
ScoreCachedText = 27,
|
||||||
|
/// <summary>5 weenie attestations.</summary>
|
||||||
|
ScoreDefaultEntryFormat = 28,
|
||||||
|
/// <summary>5 weenie attestations.</summary>
|
||||||
|
ScoreFirstEntryFormat = 29,
|
||||||
|
/// <summary>5 weenie attestations.</summary>
|
||||||
|
ScoreLastEntryFormat = 30,
|
||||||
|
/// <summary>5 weenie attestations.</summary>
|
||||||
|
ScoreOnlyEntryFormat = 31,
|
||||||
|
/// <summary>5 weenie attestations.</summary>
|
||||||
|
ScoreNoEntry = 32,
|
||||||
|
/// <summary>859 weenie attestations.</summary>
|
||||||
|
Quest = 33,
|
||||||
|
/// <summary>249 weenie attestations.</summary>
|
||||||
|
GeneratorEvent = 34,
|
||||||
|
PatronsTitle = 35,
|
||||||
|
HouseOwnerName = 36,
|
||||||
|
/// <summary>170 weenie attestations.</summary>
|
||||||
|
QuestRestriction = 37,
|
||||||
|
AppraisalPortalDestination = 38,
|
||||||
|
TinkerName = 39,
|
||||||
|
ImbuerName = 40,
|
||||||
|
HouseOwnerAccount = 41,
|
||||||
|
DisplayName = 42,
|
||||||
|
DateOfBirth = 43,
|
||||||
|
ThirdPartyApi = 44,
|
||||||
|
KillQuest = 45,
|
||||||
|
Afk = 46,
|
||||||
|
AllegianceName = 47,
|
||||||
|
AugmentationAddQuest = 48,
|
||||||
|
KillQuest2 = 49,
|
||||||
|
KillQuest3 = 50,
|
||||||
|
UseSendsSignal = 51,
|
||||||
|
GearPlatingName = 52,
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,133 @@
|
||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using AcDream.Core.Items;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace AcDream.Core.Tests.Properties;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Pins the three item-data enums the 2026-07-29 campaign added — all of them describe
|
||||||
|
/// fields acdream already parses off the wire and stored as bare numbers. Tables are
|
||||||
|
/// transcribed from <c>docs/research/named-retail/acclient.h</c>.
|
||||||
|
/// </summary>
|
||||||
|
public sealed class ItemWireEnumConformanceTests
|
||||||
|
{
|
||||||
|
/// <summary>acclient.h:4221, <c>enum AMMO_TYPE</c>.</summary>
|
||||||
|
public static TheoryData<string, uint> RetailAmmoType => new()
|
||||||
|
{
|
||||||
|
{ "None", 0x0 },
|
||||||
|
{ "Arrow", 0x1 },
|
||||||
|
{ "Bolt", 0x2 },
|
||||||
|
{ "Atlatl", 0x4 },
|
||||||
|
{ "ArrowCrystal", 0x8 },
|
||||||
|
{ "BoltCrystal", 0x10 },
|
||||||
|
{ "AtlatlCrystal", 0x20 },
|
||||||
|
{ "ArrowChorizite", 0x40 },
|
||||||
|
{ "BoltChorizite", 0x80 },
|
||||||
|
{ "AtlatlChorizite", 0x100 },
|
||||||
|
};
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[MemberData(nameof(RetailAmmoType))]
|
||||||
|
public void AmmoTypeMatchesRetail(string name, uint value)
|
||||||
|
{
|
||||||
|
Assert.True(Enum.IsDefined(typeof(AmmoType), name), $"AmmoType.{name} is missing");
|
||||||
|
Assert.Equal(value, (uint)Enum.Parse<AmmoType>(name));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void AmmoTypeDeclaresNothingRetailDoesNot()
|
||||||
|
{
|
||||||
|
var expected = RetailAmmoType.Select(r => (string)r[0]).OrderBy(n => n, StringComparer.Ordinal);
|
||||||
|
Assert.Equal(expected, Enum.GetNames<AmmoType>().OrderBy(n => n, StringComparer.Ordinal));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>acclient.h:6523, <c>enum COMBAT_USE</c>.</summary>
|
||||||
|
[Theory]
|
||||||
|
[InlineData("None", 0u)]
|
||||||
|
[InlineData("Melee", 1u)]
|
||||||
|
[InlineData("Missile", 2u)]
|
||||||
|
[InlineData("Ammo", 3u)]
|
||||||
|
[InlineData("Shield", 4u)]
|
||||||
|
[InlineData("TwoHanded", 5u)]
|
||||||
|
public void CombatUseMatchesRetail(string name, uint value)
|
||||||
|
{
|
||||||
|
Assert.True(Enum.IsDefined(typeof(CombatUse), name), $"CombatUse.{name} is missing");
|
||||||
|
Assert.Equal(value, (uint)Enum.Parse<CombatUse>(name));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>acclient.h:6478, <c>enum ITEM_USEABLE</c>, including the composites.</summary>
|
||||||
|
public static TheoryData<string, uint> RetailItemUseable => new()
|
||||||
|
{
|
||||||
|
{ "Undef", 0x0 },
|
||||||
|
{ "No", 0x1 },
|
||||||
|
{ "Self", 0x2 },
|
||||||
|
{ "Wielded", 0x4 },
|
||||||
|
{ "Contained", 0x8 },
|
||||||
|
{ "Viewed", 0x10 },
|
||||||
|
{ "ContainedViewed", 0x18 },
|
||||||
|
{ "Remote", 0x20 },
|
||||||
|
{ "ViewedRemote", 0x30 },
|
||||||
|
{ "ContainedViewedRemote", 0x38 },
|
||||||
|
{ "NeverWalk", 0x40 },
|
||||||
|
{ "RemoteNeverWalk", 0x60 },
|
||||||
|
{ "ViewedRemoteNeverWalk", 0x70 },
|
||||||
|
{ "ContainedViewedRemoteNeverWalk", 0x78 },
|
||||||
|
{ "ObjSelf", 0x80 },
|
||||||
|
{ "SourceMask", 0xFFFF },
|
||||||
|
{ "SourceWieldedTargetWielded", 0x40004 },
|
||||||
|
{ "SourceContainedTargetWielded", 0x40008 },
|
||||||
|
{ "SourceViewedTargetWielded", 0x40010 },
|
||||||
|
{ "SourceRemoteTargetWielded", 0x40020 },
|
||||||
|
{ "SourceWieldedTargetContained", 0x80004 },
|
||||||
|
{ "SourceContainedTargetContained", 0x80008 },
|
||||||
|
{ "SourceViewedTargetContained", 0x80010 },
|
||||||
|
{ "SourceRemoteTargetContained", 0x80020 },
|
||||||
|
{ "SourceContainedTargetSelfOrContained", 0xA0008 },
|
||||||
|
{ "SourceWieldedTargetViewed", 0x100004 },
|
||||||
|
{ "SourceContainedTargetViewed", 0x100008 },
|
||||||
|
{ "SourceViewedTargetViewed", 0x100010 },
|
||||||
|
{ "SourceRemoteTargetViewed", 0x100020 },
|
||||||
|
{ "SourceWieldedTargetRemote", 0x200004 },
|
||||||
|
{ "SourceContainedTargetRemote", 0x200008 },
|
||||||
|
{ "SourceViewedTargetRemote", 0x200010 },
|
||||||
|
{ "SourceRemoteTargetRemote", 0x200020 },
|
||||||
|
{ "SourceContainedTargetRemoteOrSelf", 0x220008 },
|
||||||
|
{ "SourceWieldedTargetRemoteNeverWalk", 0x600004 },
|
||||||
|
{ "SourceContainedTargetRemoteNeverWalk", 0x600008 },
|
||||||
|
{ "SourceRemoteTargetRemoteNeverWalk", 0x600020 },
|
||||||
|
{ "SourceContainedTargetObjSelfOrContained", 0x880008 },
|
||||||
|
{ "TargetMask", 0xFFFF0000 },
|
||||||
|
};
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[MemberData(nameof(RetailItemUseable))]
|
||||||
|
public void ItemUseableMatchesRetail(string name, uint value)
|
||||||
|
{
|
||||||
|
Assert.True(Enum.IsDefined(typeof(ItemUseable), name), $"ItemUseable.{name} is missing");
|
||||||
|
Assert.Equal(value, (uint)Enum.Parse<ItemUseable>(name));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ItemUseableDeclaresNothingRetailDoesNot()
|
||||||
|
{
|
||||||
|
var expected = RetailItemUseable.Select(r => (string)r[0]).OrderBy(n => n, StringComparer.Ordinal);
|
||||||
|
Assert.Equal(expected, Enum.GetNames<ItemUseable>().OrderBy(n => n, StringComparer.Ordinal));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The two halves partition the word, and at least one retail composite is
|
||||||
|
/// deliberately not the obvious union — which is why they are transcribed rather
|
||||||
|
/// than composed.
|
||||||
|
/// </summary>
|
||||||
|
[Fact]
|
||||||
|
public void ItemUseableSourceAndTargetMasksPartitionTheWord()
|
||||||
|
{
|
||||||
|
Assert.Equal(0u, (uint)ItemUseable.SourceMask & (uint)ItemUseable.TargetMask);
|
||||||
|
Assert.Equal(uint.MaxValue, (uint)ItemUseable.SourceMask | (uint)ItemUseable.TargetMask);
|
||||||
|
|
||||||
|
uint naiveUnion = (uint)ItemUseable.ObjSelf | (uint)ItemUseable.Contained
|
||||||
|
| ((uint)ItemUseable.Contained << 16);
|
||||||
|
Assert.NotEqual(naiveUnion, (uint)ItemUseable.SourceContainedTargetObjSelfOrContained);
|
||||||
|
}
|
||||||
|
}
|
||||||
1398
tests/AcDream.Core.Tests/Properties/PropertyEnumConformanceTests.cs
Normal file
1398
tests/AcDream.Core.Tests/Properties/PropertyEnumConformanceTests.cs
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,285 @@
|
||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using AcDream.Core.Combat;
|
||||||
|
using AcDream.Core.Items;
|
||||||
|
using AcDream.Core.Physics;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace AcDream.Core.Tests.Properties;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Pins the wire-adjacent enums acdream shares with the retail client to the values
|
||||||
|
/// in the Sept 2013 EoR header, <c>docs/research/named-retail/acclient.h</c>. Each
|
||||||
|
/// table below is transcribed from the cited <c>enum</c> block, so a hand edit that
|
||||||
|
/// drifts from retail fails here.
|
||||||
|
///
|
||||||
|
/// <para>These tables are the reason the 2026-07-29 enum campaign found real bugs:
|
||||||
|
/// <see cref="DamageType"/> had its four drain/restore bits rotated, and
|
||||||
|
/// <see cref="ItemType"/> had a shifted craft ladder plus locally recomputed composite
|
||||||
|
/// masks. Both are corrected and pinned below.</para>
|
||||||
|
/// </summary>
|
||||||
|
public sealed class RetailEnumConformanceTests
|
||||||
|
{
|
||||||
|
/// <summary>acclient.h:3788, <c>enum DAMAGE_TYPE</c>. FORCE_*_32_BIT omitted.</summary>
|
||||||
|
public static TheoryData<string, uint> RetailDamageType => new()
|
||||||
|
{
|
||||||
|
{ "Undef", 0x0 },
|
||||||
|
{ "Slash", 0x1 },
|
||||||
|
{ "Pierce", 0x2 },
|
||||||
|
{ "Bludgeon", 0x4 },
|
||||||
|
{ "Cold", 0x8 },
|
||||||
|
{ "Fire", 0x10 },
|
||||||
|
{ "Acid", 0x20 },
|
||||||
|
{ "Electric", 0x40 },
|
||||||
|
{ "Health", 0x80 },
|
||||||
|
{ "Stamina", 0x100 },
|
||||||
|
{ "Mana", 0x200 },
|
||||||
|
{ "Nether", 0x400 },
|
||||||
|
{ "Base", 0x10000000 },
|
||||||
|
};
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[MemberData(nameof(RetailDamageType))]
|
||||||
|
public void DamageTypeMatchesRetail(string name, uint value)
|
||||||
|
{
|
||||||
|
Assert.True(Enum.IsDefined(typeof(DamageType), name),
|
||||||
|
$"DamageType.{name} is missing");
|
||||||
|
Assert.Equal(value, (uint)Enum.Parse<DamageType>(name));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void DamageTypeDeclaresNothingRetailDoesNot()
|
||||||
|
{
|
||||||
|
var expected = RetailDamageType.Select(r => (string)r[0]).OrderBy(n => n, StringComparer.Ordinal);
|
||||||
|
var actual = Enum.GetNames<DamageType>().OrderBy(n => n, StringComparer.Ordinal);
|
||||||
|
Assert.Equal(expected, actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// acclient.h:3300, <c>enum ITEM_TYPE</c>. TYPE_UNDEF and TYPE_SELF both sit on 0
|
||||||
|
/// in retail; acdream spells that single zero <c>None</c>. FORCE_*_32_BIT omitted.
|
||||||
|
/// </summary>
|
||||||
|
public static TheoryData<string, uint> RetailItemType => new()
|
||||||
|
{
|
||||||
|
{ "None", 0x0 },
|
||||||
|
{ "MeleeWeapon", 0x1 },
|
||||||
|
{ "Armor", 0x2 },
|
||||||
|
{ "Vestements", 0x6 },
|
||||||
|
{ "Clothing", 0x4 },
|
||||||
|
{ "Jewelry", 0x8 },
|
||||||
|
{ "Creature", 0x10 },
|
||||||
|
{ "Food", 0x20 },
|
||||||
|
{ "Money", 0x40 },
|
||||||
|
{ "Misc", 0x80 },
|
||||||
|
{ "MissileWeapon", 0x100 },
|
||||||
|
{ "Weapon", 0x101 },
|
||||||
|
{ "Container", 0x200 },
|
||||||
|
{ "LockableMagicTarget", 0x280 },
|
||||||
|
{ "Useless", 0x400 },
|
||||||
|
{ "Gem", 0x800 },
|
||||||
|
{ "SpellComponents", 0x1000 },
|
||||||
|
{ "Writable", 0x2000 },
|
||||||
|
{ "Key", 0x4000 },
|
||||||
|
{ "Caster", 0x8000 },
|
||||||
|
{ "WeaponOrCaster", 0x8101 },
|
||||||
|
{ "RedirectableItemEnchantmentTarget", 0x8107 },
|
||||||
|
{ "Portal", 0x10000 },
|
||||||
|
{ "Lockable", 0x20000 },
|
||||||
|
{ "PromissoryNote", 0x40000 },
|
||||||
|
{ "ManaStone", 0x80000 },
|
||||||
|
{ "ItemEnchantableTarget", 0x88B8F },
|
||||||
|
{ "Service", 0x100000 },
|
||||||
|
{ "MagicWieldable", 0x200000 },
|
||||||
|
{ "Item", 0x2DFBEF },
|
||||||
|
{ "CraftCookingBase", 0x400000 },
|
||||||
|
{ "VendorGrocer", 0x446220 },
|
||||||
|
{ "CraftAlchemyBase", 0x800000 },
|
||||||
|
{ "CraftFletchingBase", 0x1000000 },
|
||||||
|
{ "CraftAlchemyIntermediate", 0x4000000 },
|
||||||
|
{ "CraftFletchingIntermediate", 0x8000000 },
|
||||||
|
{ "LifeStone", 0x10000000 },
|
||||||
|
{ "PortalMagicTarget", 0x10010000 },
|
||||||
|
{ "TinkeringTool", 0x20000000 },
|
||||||
|
{ "TinkeringMaterial", 0x40000000 },
|
||||||
|
{ "VendorShopkeep", 0x480467A7 },
|
||||||
|
{ "Gameboard", 0x80000000 },
|
||||||
|
};
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[MemberData(nameof(RetailItemType))]
|
||||||
|
public void ItemTypeMatchesRetail(string name, uint value)
|
||||||
|
{
|
||||||
|
Assert.True(Enum.IsDefined(typeof(ItemType), name),
|
||||||
|
$"ItemType.{name} is missing");
|
||||||
|
Assert.Equal(value, (uint)Enum.Parse<ItemType>(name));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ItemTypeDeclaresNothingRetailDoesNot()
|
||||||
|
{
|
||||||
|
var expected = RetailItemType.Select(r => (string)r[0]).OrderBy(n => n, StringComparer.Ordinal);
|
||||||
|
var actual = Enum.GetNames<ItemType>().OrderBy(n => n, StringComparer.Ordinal);
|
||||||
|
Assert.Equal(expected, actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The craft ladder specifically: retail leaves 0x02000000 unused, and the ACE
|
||||||
|
/// weenie corpus attests 0x04000000 as Craft_Alchemy_Intermediate 235 times. This
|
||||||
|
/// is the pairing acdream had wrong.
|
||||||
|
/// </summary>
|
||||||
|
[Fact]
|
||||||
|
public void CraftLadderMatchesRetailAndLeavesTheUnusedBitUnclaimed()
|
||||||
|
{
|
||||||
|
Assert.Equal(0x00400000u, (uint)ItemType.CraftCookingBase);
|
||||||
|
Assert.Equal(0x00800000u, (uint)ItemType.CraftAlchemyBase);
|
||||||
|
Assert.Equal(0x01000000u, (uint)ItemType.CraftFletchingBase);
|
||||||
|
Assert.Equal(0x04000000u, (uint)ItemType.CraftAlchemyIntermediate);
|
||||||
|
Assert.Equal(0x08000000u, (uint)ItemType.CraftFletchingIntermediate);
|
||||||
|
Assert.DoesNotContain(Enum.GetValues<ItemType>(), t => (uint)t == 0x02000000u);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// <c>Weapon</c> and <c>WeaponOrCaster</c> were aliases before the campaign, because
|
||||||
|
/// <c>Weapon</c> was recomputed locally as melee|missile|caster. Retail keeps them
|
||||||
|
/// distinct and only the latter includes the caster bit.
|
||||||
|
/// </summary>
|
||||||
|
[Fact]
|
||||||
|
public void WeaponExcludesCasterAndWeaponOrCasterIncludesIt()
|
||||||
|
{
|
||||||
|
Assert.NotEqual(ItemType.Weapon, ItemType.WeaponOrCaster);
|
||||||
|
Assert.Equal(ItemType.MeleeWeapon | ItemType.MissileWeapon, ItemType.Weapon);
|
||||||
|
Assert.Equal(ItemType.Weapon | ItemType.Caster, ItemType.WeaponOrCaster);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// acclient.h:3193, <c>enum INVENTORY_LOC</c> — the composite slot groups only. The
|
||||||
|
/// 32 primitive slots were already correct and are pinned by <c>EquipMaskTests</c>.
|
||||||
|
/// </summary>
|
||||||
|
public static TheoryData<string, uint> RetailEquipMaskComposites => new()
|
||||||
|
{
|
||||||
|
{ "Clothing", 0x080001FF },
|
||||||
|
{ "Armor", 0x00007E00 },
|
||||||
|
{ "Jewelry", 0x7C0F8000 },
|
||||||
|
{ "WristWear", 0x00030000 },
|
||||||
|
{ "FingerWear", 0x000C0000 },
|
||||||
|
{ "Sigil", 0x70000000 },
|
||||||
|
{ "ReadySlot", 0x03F00000 },
|
||||||
|
{ "Weapon", 0x02500000 },
|
||||||
|
{ "WeaponReadySlot", 0x03500000 },
|
||||||
|
{ "All", 0x7FFFFFFF },
|
||||||
|
{ "CanGoInReadySlot", 0x7FFFFFFF },
|
||||||
|
};
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[MemberData(nameof(RetailEquipMaskComposites))]
|
||||||
|
public void EquipMaskCompositeMatchesRetail(string name, uint value)
|
||||||
|
{
|
||||||
|
Assert.True(Enum.IsDefined(typeof(EquipMask), name), $"EquipMask.{name} is missing");
|
||||||
|
Assert.Equal(value, (uint)Enum.Parse<EquipMask>(name));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Retail's CLOTHING_LOC is the nine wear slots plus the cloak slot (bit 27) — it is
|
||||||
|
/// NOT the union of the wear slots alone. A type remark here used to claim the extra
|
||||||
|
/// bit was 31 and unnamed; it is 27 and it is <see cref="EquipMask.Cloak"/>.
|
||||||
|
/// </summary>
|
||||||
|
[Fact]
|
||||||
|
public void ClothingCompositeIsTheWearSlotsPlusCloak()
|
||||||
|
{
|
||||||
|
EquipMask wearSlots =
|
||||||
|
EquipMask.HeadWear | EquipMask.ChestWear | EquipMask.AbdomenWear
|
||||||
|
| EquipMask.UpperArmWear | EquipMask.LowerArmWear | EquipMask.HandWear
|
||||||
|
| EquipMask.UpperLegWear | EquipMask.LowerLegWear | EquipMask.FootWear;
|
||||||
|
|
||||||
|
Assert.Equal(0x000001FFu, (uint)wearSlots);
|
||||||
|
Assert.Equal(EquipMask.Clothing, wearSlots | EquipMask.Cloak);
|
||||||
|
Assert.NotEqual(EquipMask.Clothing, wearSlots);
|
||||||
|
Assert.Equal(0u, (uint)EquipMask.Clothing & 0x80000000u);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>acclient.h:3688, <c>enum TransientState</c>.</summary>
|
||||||
|
public static TheoryData<string, uint> RetailTransientState => new()
|
||||||
|
{
|
||||||
|
{ "Contact", 0x1 },
|
||||||
|
{ "OnWalkable", 0x2 },
|
||||||
|
{ "Sliding", 0x4 },
|
||||||
|
{ "WaterContact", 0x8 },
|
||||||
|
{ "StationaryFall", 0x10 },
|
||||||
|
{ "StationaryStop", 0x20 },
|
||||||
|
{ "StationaryStuck", 0x40 },
|
||||||
|
{ "Active", 0x80 },
|
||||||
|
{ "CheckEthereal", 0x100 },
|
||||||
|
};
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[MemberData(nameof(RetailTransientState))]
|
||||||
|
public void TransientStateFlagsMatchesRetail(string name, uint value)
|
||||||
|
{
|
||||||
|
Assert.True(Enum.IsDefined(typeof(TransientStateFlags), name),
|
||||||
|
$"TransientStateFlags.{name} is missing");
|
||||||
|
Assert.Equal(value, (uint)Enum.Parse<TransientStateFlags>(name));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>acclient.h:2815, <c>enum PhysicsState</c>, including the two bits retail itself reserves.</summary>
|
||||||
|
public static TheoryData<string, uint> RetailPhysicsState => new()
|
||||||
|
{
|
||||||
|
{ "Static", 0x1 },
|
||||||
|
{ "ReservedUnused1", 0x2 },
|
||||||
|
{ "Ethereal", 0x4 },
|
||||||
|
{ "ReportCollisions", 0x8 },
|
||||||
|
{ "IgnoreCollisions", 0x10 },
|
||||||
|
{ "NoDraw", 0x20 },
|
||||||
|
{ "Missile", 0x40 },
|
||||||
|
{ "Pushable", 0x80 },
|
||||||
|
{ "AlignPath", 0x100 },
|
||||||
|
{ "PathClipped", 0x200 },
|
||||||
|
{ "Gravity", 0x400 },
|
||||||
|
{ "Lighting", 0x800 },
|
||||||
|
{ "ParticleEmitter", 0x1000 },
|
||||||
|
{ "ReservedUnused2", 0x2000 },
|
||||||
|
{ "Hidden", 0x4000 },
|
||||||
|
{ "ScriptedCollision", 0x8000 },
|
||||||
|
{ "HasPhysicsBsp", 0x10000 },
|
||||||
|
{ "Inelastic", 0x20000 },
|
||||||
|
{ "HasDefaultAnim", 0x40000 },
|
||||||
|
{ "HasDefaultScript", 0x80000 },
|
||||||
|
{ "Cloaked", 0x100000 },
|
||||||
|
{ "ReportAsEnvironment", 0x200000 },
|
||||||
|
{ "EdgeSlide", 0x400000 },
|
||||||
|
{ "Sledding", 0x800000 },
|
||||||
|
{ "Frozen", 0x1000000 },
|
||||||
|
};
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[MemberData(nameof(RetailPhysicsState))]
|
||||||
|
public void PhysicsStateFlagsMatchesRetail(string name, uint value)
|
||||||
|
{
|
||||||
|
Assert.True(Enum.IsDefined(typeof(PhysicsStateFlags), name),
|
||||||
|
$"PhysicsStateFlags.{name} is missing");
|
||||||
|
Assert.Equal(value, (uint)Enum.Parse<PhysicsStateFlags>(name));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>acclient.h:4371, <c>enum ATTACK_HEIGHT</c>. NUM_ATTACK_HEIGHTS is a count, not a height.</summary>
|
||||||
|
[Theory]
|
||||||
|
[InlineData("Undef", 0)]
|
||||||
|
[InlineData("High", 1)]
|
||||||
|
[InlineData("Medium", 2)]
|
||||||
|
[InlineData("Low", 3)]
|
||||||
|
public void AttackHeightMatchesRetail(string name, int value)
|
||||||
|
{
|
||||||
|
Assert.True(Enum.IsDefined(typeof(AttackHeight), name), $"AttackHeight.{name} is missing");
|
||||||
|
Assert.Equal(value, (int)Enum.Parse<AttackHeight>(name));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// acclient.h:3807, <c>enum AttackType</c>. The two composites are the interesting
|
||||||
|
/// part: retail spells Unarmed 0x19 and MultiStrike 0x79E0, and acdream derives both
|
||||||
|
/// from its primitives. This asserts the derivation lands on retail's literal.
|
||||||
|
/// </summary>
|
||||||
|
[Fact]
|
||||||
|
public void AttackTypeCompositesMatchRetailLiterals()
|
||||||
|
{
|
||||||
|
Assert.Equal(0x19u, (uint)AttackType.Unarmed);
|
||||||
|
Assert.Equal(0x79E0u, (uint)AttackType.MultiStrike);
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue