diff --git a/src/AcDream.Core/Properties/PropertyBool.cs b/src/AcDream.Core/Properties/PropertyBool.cs
new file mode 100644
index 00000000..3989866d
--- /dev/null
+++ b/src/AcDream.Core/Properties/PropertyBool.cs
@@ -0,0 +1,221 @@
+//
+// 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.
+//
+
+namespace AcDream.Core.Properties;
+
+///
+/// AC's PropertyBool property table — the numeric keys the server sends in
+/// PrivateUpdatePropertyBool (0x02C9) / PublicUpdatePropertyBool (0x02CA)
+/// and in the property bundles carried by CreateObject / PlayerDescription /
+/// IdentifyResponse. The CLR payload for this table is bool.
+///
+/// Verified 2026-07-29 against two independent oracles: the vendored
+/// client-side enum catalog (references/acclientlib/UtilityBelt.Common/Enums/Enums.cs,
+/// which names this table BoolId) and the 38,985-file ACE weenie export corpus
+/// (references/weenies/), whose per-stat _comment 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.
+///
+/// This enum is a vocabulary, not a parser contract: the wire carries a raw
+/// uint and unknown keys must still round-trip untouched, so never assume a
+/// received key is a defined member.
+///
+public enum PropertyBool : uint
+{
+ Undef = 0,
+ /// 21884 weenie attestations.
+ Stuck = 1,
+ /// 1077 weenie attestations.
+ Open = 2,
+ /// 646 weenie attestations.
+ Locked = 3,
+ RotProof = 4,
+ AllegianceUpdateRequest = 5,
+ /// 1282 weenie attestations.
+ AiUsesMana = 6,
+ /// 16 weenie attestations.
+ AiUseHumanMagicAnimations = 7,
+ /// 853 weenie attestations.
+ AllowGive = 8,
+ CurrentlyAttacking = 9,
+ AttackerAi = 10,
+ /// 6212 weenie attestations.
+ IgnoreCollisions = 11,
+ /// 9020 weenie attestations.
+ ReportCollisions = 12,
+ /// 15282 weenie attestations.
+ Ethereal = 13,
+ /// 7376 weenie attestations.
+ GravityStatus = 14,
+ /// 3382 weenie attestations.
+ LightsStatus = 15,
+ /// 139 weenie attestations.
+ ScriptedCollision = 16,
+ /// 475 weenie attestations.
+ Inelastic = 17,
+ /// 1677 weenie attestations.
+ Visibility = 18,
+ /// 3972 weenie attestations.
+ Attackable = 19,
+ SafeSpellComponents = 20,
+ AdvocateState = 21,
+ /// 15455 weenie attestations.
+ Inscribable = 22,
+ /// 7755 weenie attestations.
+ DestroyOnSell = 23,
+ /// 6728 weenie attestations.
+ UiHidden = 24,
+ IgnoreHouseBarriers = 25,
+ HiddenAdmin = 26,
+ PkWounder = 27,
+ PkKiller = 28,
+ /// 262 weenie attestations.
+ NoCorpse = 29,
+ UnderLifestoneProtection = 30,
+ ItemManaUpdatePending = 31,
+ GeneratorStatus = 32,
+ /// 831 weenie attestations.
+ ResetMessagePending = 33,
+ /// 831 weenie attestations.
+ DefaultOpen = 34,
+ /// 511 weenie attestations.
+ DefaultLocked = 35,
+ DefaultOn = 36,
+ OpenForBusiness = 37,
+ IsFrozen = 38,
+ /// 1049 weenie attestations.
+ DealMagicalItems = 39,
+ LogoffImDead = 40,
+ /// 2208 weenie attestations.
+ ReportCollisionsAsEnvironment = 41,
+ /// 1327 weenie attestations.
+ AllowEdgeSlide = 42,
+ AdvocateQuest = 43,
+ IsAdmin = 44,
+ IsArch = 45,
+ IsSentinel = 46,
+ IsAdvocate = 47,
+ CurrentlyPoweringUp = 48,
+ GeneratorEnteredWorld = 49,
+ /// 890 weenie attestations.
+ NeverFailCasting = 50,
+ /// 264 weenie attestations.
+ VendorService = 51,
+ /// 1421 weenie attestations.
+ AiImmobile = 52,
+ /// 1 weenie attestations.
+ DamagedByCollisions = 53,
+ /// 34 weenie attestations.
+ IsDynamic = 54,
+ /// 81 weenie attestations.
+ IsHot = 55,
+ IsAffecting = 56,
+ /// 49 weenie attestations.
+ AffectsAis = 57,
+ SpellQueueActive = 58,
+ GeneratorDisabled = 59,
+ IsAcceptingTells = 60,
+ /// 1 weenie attestations.
+ LoggingChannel = 61,
+ /// 5 weenie attestations.
+ OpensAnyLock = 62,
+ /// 20 weenie attestations.
+ UnlimitedUse = 63,
+ GeneratedTreasureItem = 64,
+ /// 97 weenie attestations.
+ IgnoreMagicResist = 65,
+ /// 87 weenie attestations.
+ IgnoreMagicArmor = 66,
+ AiAllowTrade = 67,
+ /// 2 weenie attestations.
+ SpellComponentsRequired = 68,
+ /// 4617 weenie attestations.
+ IsSellable = 69,
+ /// 4 weenie attestations.
+ IgnoreShieldsBySkill = 70,
+ /// 6275 weenie attestations.
+ NoDraw = 71,
+ ActivationUntargeted = 72,
+ HouseHasGottenPriorityBootPos = 73,
+ /// 12 weenie attestations.
+ GeneratorAutomaticDestruction = 74,
+ HouseHooksVisible = 75,
+ /// 8 weenie attestations.
+ HouseRequiresMonarch = 76,
+ HouseHooksEnabled = 77,
+ HouseNotifiedHudOfHookCount = 78,
+ /// 15 weenie attestations.
+ AiAcceptEverything = 79,
+ IgnorePortalRestrictions = 80,
+ /// 5 weenie attestations.
+ RequiresBackpackSlot = 81,
+ /// 444 weenie attestations.
+ DontTurnOrMoveWhenGiving = 82,
+ /// 442 weenie attestations.
+ NpcLooksLikeObject = 83,
+ /// 210 weenie attestations.
+ IgnoreCloIcons = 84,
+ /// 178 weenie attestations.
+ AppraisalHasAllowedWielder = 85,
+ ChestRegenOnClose = 86,
+ LogoffInMinigame = 87,
+ /// 17 weenie attestations.
+ PortalShowDestination = 88,
+ /// 30 weenie attestations.
+ PortalIgnoresPkAttackTimer = 89,
+ /// 43 weenie attestations.
+ NpcInteractsSilently = 90,
+ /// 230 weenie attestations.
+ Retained = 91,
+ /// 1 weenie attestations.
+ IgnoreAuthor = 92,
+ Limbo = 93,
+ AppraisalHasAllowedActivator = 94,
+ ExistedBeforeAllegianceXpChanges = 95,
+ IsDeaf = 96,
+ IsPsr = 97,
+ Invincible = 98,
+ /// 1068 weenie attestations.
+ Ivoryable = 99,
+ /// 687 weenie attestations.
+ Dyable = 100,
+ CanGenerateRare = 101,
+ CorpseGeneratedRare = 102,
+ /// 14 weenie attestations.
+ NonProjectileMagicImmune = 103,
+ ActdReceivedItems = 104,
+ Unknown105 = 105,
+ FirstEnterWorldDone = 106,
+ RecallsDisabled = 107,
+ /// 13 weenie attestations.
+ 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,
+ /// 14 weenie attestations.
+ AutowieldLeft = 130,
+}
diff --git a/src/AcDream.Core/Properties/PropertyDataId.cs b/src/AcDream.Core/Properties/PropertyDataId.cs
new file mode 100644
index 00000000..2d22b902
--- /dev/null
+++ b/src/AcDream.Core/Properties/PropertyDataId.cs
@@ -0,0 +1,134 @@
+//
+// 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.
+//
+
+namespace AcDream.Core.Properties;
+
+///
+/// AC's PropertyDataId property table — the numeric keys the server sends in
+/// PrivateUpdatePropertyDataId (0x02E1) / PublicUpdatePropertyDataId (0x02E2)
+/// and in the property bundles carried by CreateObject / PlayerDescription /
+/// IdentifyResponse. The CLR payload for this table is uint (DAT file id).
+///
+/// Verified 2026-07-29 against two independent oracles: the vendored
+/// client-side enum catalog (references/acclientlib/UtilityBelt.Common/Enums/Enums.cs,
+/// which names this table DataId) and the 38,985-file ACE weenie export corpus
+/// (references/weenies/), whose per-stat _comment 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.
+///
+/// This enum is a vocabulary, not a parser contract: the wire carries a raw
+/// uint and unknown keys must still round-trip untouched, so never assume a
+/// received key is a defined member.
+///
+public enum PropertyDataId : uint
+{
+ Undef = 0,
+ /// 38985 weenie attestations.
+ Setup = 1,
+ /// 12219 weenie attestations.
+ MotionTable = 2,
+ /// 23696 weenie attestations.
+ SoundTable = 3,
+ /// 4319 weenie attestations.
+ CombatTable = 4,
+ /// 2 weenie attestations.
+ QualityFilter = 5,
+ /// 13875 weenie attestations.
+ PaletteBase = 6,
+ /// 9049 weenie attestations.
+ ClothingBase = 7,
+ /// 38985 weenie attestations.
+ Icon = 8,
+ /// 741 weenie attestations.
+ EyesTexture = 9,
+ /// 741 weenie attestations.
+ NoseTexture = 10,
+ /// 741 weenie attestations.
+ MouthTexture = 11,
+ DefaultEyesTexture = 12,
+ DefaultNoseTexture = 13,
+ DefaultMouthTexture = 14,
+ /// 741 weenie attestations.
+ HairPalette = 15,
+ /// 741 weenie attestations.
+ EyesPalette = 16,
+ /// 741 weenie attestations.
+ SkinPalette = 17,
+ HeadObject = 18,
+ /// 4 weenie attestations.
+ ActivationAnimation = 19,
+ /// 4 weenie attestations.
+ InitMotion = 20,
+ ActivationSound = 21,
+ /// 23266 weenie attestations.
+ PhysicsEffectTable = 22,
+ /// 138 weenie attestations.
+ UseSound = 23,
+ /// 48 weenie attestations.
+ UseTargetAnimation = 24,
+ /// 4 weenie attestations.
+ UseTargetSuccessAnimation = 25,
+ /// 2 weenie attestations.
+ UseTargetFailureAnimation = 26,
+ /// 232 weenie attestations.
+ UseUserAnimation = 27,
+ /// 3696 weenie attestations.
+ Spell = 28,
+ /// 156 weenie attestations.
+ SpellComponent = 29,
+ /// 794 weenie attestations.
+ PhysicsScript = 30,
+ /// 497 weenie attestations.
+ LinkedPortalOne = 31,
+ /// 861 weenie attestations.
+ WieldedTreasureType = 32,
+ /// 5 weenie attestations.
+ UnknownGuessedname = 33,
+ UnknownGuessedname2 = 34,
+ /// 2000 weenie attestations.
+ DeathTreasureType = 35,
+ /// 2276 weenie attestations.
+ MutateFilter = 36,
+ /// 1253 weenie attestations.
+ ItemSkillLimit = 37,
+ /// 1 weenie attestations.
+ UseCreateItem = 38,
+ DeathSpell = 39,
+ VendorsClassId = 40,
+ /// 13 weenie attestations.
+ ItemSpecializedOnly = 41,
+ /// 6274 weenie attestations.
+ HouseId = 42,
+ AccountHouseId = 43,
+ /// 6274 weenie attestations.
+ RestrictionEffect = 44,
+ CreationMutationFilter = 45,
+ /// 584 weenie attestations.
+ TsysMutationFilter = 46,
+ LastPortal = 47,
+ /// 1 weenie attestations.
+ LinkedPortalTwo = 48,
+ OriginalPortal = 49,
+ /// 1000 weenie attestations.
+ IconOverlay = 50,
+ /// 16 weenie attestations.
+ IconOverlaySecondary = 51,
+ /// 554 weenie attestations.
+ IconUnderlay = 52,
+ AugmentationMutationFilter = 53,
+ AugmentationEffect = 54,
+ /// 84 weenie attestations.
+ ProcSpell = 55,
+ AugmentationCreateItem = 56,
+ AlternateCurrency = 57,
+ BlueSurgeSpell = 58,
+ YellowSurgeSpell = 59,
+ RedSurgeSpell = 60,
+ OlthoiDeathTreasureType = 61,
+}
diff --git a/src/AcDream.Core/Properties/PropertyFloat.cs b/src/AcDream.Core/Properties/PropertyFloat.cs
new file mode 100644
index 00000000..e58caebb
--- /dev/null
+++ b/src/AcDream.Core/Properties/PropertyFloat.cs
@@ -0,0 +1,289 @@
+//
+// 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.
+//
+
+namespace AcDream.Core.Properties;
+
+///
+/// AC's PropertyFloat property table — the numeric keys the server sends in
+/// PrivateUpdatePropertyFloat (0x02D5) / PublicUpdatePropertyFloat (0x02D6)
+/// and in the property bundles carried by CreateObject / PlayerDescription /
+/// IdentifyResponse. The CLR payload for this table is double.
+///
+/// Verified 2026-07-29 against two independent oracles: the vendored
+/// client-side enum catalog (references/acclientlib/UtilityBelt.Common/Enums/Enums.cs,
+/// which names this table FloatId) and the 38,985-file ACE weenie export corpus
+/// (references/weenies/), whose per-stat _comment 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.
+///
+/// This enum is a vocabulary, not a parser contract: the wire carries a raw
+/// uint and unknown keys must still round-trip untouched, so never assume a
+/// received key is a defined member.
+///
+public enum PropertyFloat : uint
+{
+ Undef = 0,
+ /// 4243 weenie attestations.
+ HeartbeatInterval = 1,
+ /// 4243 weenie attestations.
+ HeartbeatTimestamp = 2,
+ /// 4361 weenie attestations.
+ HealthRate = 3,
+ /// 4361 weenie attestations.
+ StaminaRate = 4,
+ /// 7706 weenie attestations.
+ ManaRate = 5,
+ /// 79 weenie attestations.
+ HealthUponResurrection = 6,
+ /// 79 weenie attestations.
+ StaminaUponResurrection = 7,
+ /// 79 weenie attestations.
+ ManaUponResurrection = 8,
+ StartTime = 9,
+ StopTime = 10,
+ /// 1749 weenie attestations.
+ ResetInterval = 11,
+ /// 3290 weenie attestations.
+ Shade = 12,
+ /// 6001 weenie attestations.
+ ArmorModVsSlash = 13,
+ /// 6005 weenie attestations.
+ ArmorModVsPierce = 14,
+ /// 6005 weenie attestations.
+ ArmorModVsBludgeon = 15,
+ /// 6005 weenie attestations.
+ ArmorModVsCold = 16,
+ /// 6005 weenie attestations.
+ ArmorModVsFire = 17,
+ /// 6005 weenie attestations.
+ ArmorModVsAcid = 18,
+ /// 6005 weenie attestations.
+ ArmorModVsElectric = 19,
+ CombatSpeed = 20,
+ /// 2733 weenie attestations.
+ WeaponLength = 21,
+ /// 3174 weenie attestations.
+ DamageVariance = 22,
+ CurrentPowerMod = 23,
+ AccuracyMod = 24,
+ StrengthMod = 25,
+ /// 1386 weenie attestations.
+ MaximumVelocity = 26,
+ /// 233 weenie attestations.
+ RotationSpeed = 27,
+ MotionTimestamp = 28,
+ /// 3892 weenie attestations.
+ WeaponDefense = 29,
+ WimpyLevel = 30,
+ /// 2169 weenie attestations.
+ VisualAwarenessRange = 31,
+ AuralAwarenessRange = 32,
+ PerceptionLevel = 33,
+ /// 1987 weenie attestations.
+ PowerupTime = 34,
+ MaxChargeDistance = 35,
+ /// 1892 weenie attestations.
+ ChargeSpeed = 36,
+ /// 1049 weenie attestations.
+ BuyPrice = 37,
+ /// 1049 weenie attestations.
+ SellPrice = 38,
+ /// 18233 weenie attestations.
+ DefaultScale = 39,
+ /// 10 weenie attestations.
+ LockpickMod = 40,
+ /// 2195 weenie attestations.
+ RegenerationInterval = 41,
+ RegenerationTimestamp = 42,
+ /// 2135 weenie attestations.
+ GeneratorRadius = 43,
+ /// 66 weenie attestations.
+ TimeToRot = 44,
+ DeathTimestamp = 45,
+ PkTimestamp = 46,
+ VictimTimestamp = 47,
+ LoginTimestamp = 48,
+ CreationTimestamp = 49,
+ /// 4 weenie attestations.
+ MinimumTimeSincePk = 50,
+ DeprecatedHousekeepingPriority = 51,
+ AbuseLoggingTimestamp = 52,
+ LastPortalTeleportTimestamp = 53,
+ /// 9152 weenie attestations.
+ UseRadius = 54,
+ /// 46 weenie attestations.
+ HomeRadius = 55,
+ ReleasedTimestamp = 56,
+ MinHomeRadius = 57,
+ Facing = 58,
+ ResetTimestamp = 59,
+ LogoffTimestamp = 60,
+ EconRecoveryInterval = 61,
+ /// 3523 weenie attestations.
+ WeaponOffense = 62,
+ /// 1223 weenie attestations.
+ DamageMod = 63,
+ /// 4361 weenie attestations.
+ ResistSlash = 64,
+ /// 4361 weenie attestations.
+ ResistPierce = 65,
+ /// 4361 weenie attestations.
+ ResistBludgeon = 66,
+ /// 4361 weenie attestations.
+ ResistFire = 67,
+ /// 4361 weenie attestations.
+ ResistCold = 68,
+ /// 4361 weenie attestations.
+ ResistAcid = 69,
+ /// 4361 weenie attestations.
+ ResistElectric = 70,
+ /// 4361 weenie attestations.
+ ResistHealthBoost = 71,
+ /// 4361 weenie attestations.
+ ResistStaminaDrain = 72,
+ /// 4361 weenie attestations.
+ ResistStaminaBoost = 73,
+ /// 4361 weenie attestations.
+ ResistManaDrain = 74,
+ /// 4361 weenie attestations.
+ ResistManaBoost = 75,
+ /// 794 weenie attestations.
+ Translucency = 76,
+ /// 269 weenie attestations.
+ PhysicsScriptIntensity = 77,
+ /// 761 weenie attestations.
+ Friction = 78,
+ /// 761 weenie attestations.
+ Elasticity = 79,
+ /// 1076 weenie attestations.
+ AiUseMagicDelay = 80,
+ ItemMinSpellcraftMod = 81,
+ ItemMaxSpellcraftMod = 82,
+ ItemRankProbability = 83,
+ Shade2 = 84,
+ Shade3 = 85,
+ Shade4 = 86,
+ /// 15 weenie attestations.
+ 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,
+ /// 22 weenie attestations.
+ HealkitMod = 100,
+ FrozenTimestamp = 101,
+ HealthRateMod = 102,
+ AllegianceSwearTimestamp = 103,
+ /// 4361 weenie attestations.
+ ObviousRadarRange = 104,
+ /// 81 weenie attestations.
+ HotspotCycleTime = 105,
+ /// 74 weenie attestations.
+ HotspotCycleTimeVariance = 106,
+ SpamTimestamp = 107,
+ SpamRate = 108,
+ /// 26 weenie attestations.
+ BondWieldedTreasure = 109,
+ /// 1039 weenie attestations.
+ BulkMod = 110,
+ /// 1039 weenie attestations.
+ SizeMod = 111,
+ GagTimestamp = 112,
+ GeneratorUpdateTimestamp = 113,
+ DeathSpamTimestamp = 114,
+ DeathSpamRate = 115,
+ WildAttackProbability = 116,
+ /// 312 weenie attestations.
+ FocusedProbability = 117,
+ CrashAndTurnProbability = 118,
+ CrashAndTurnRadius = 119,
+ CrashAndTurnBias = 120,
+ /// 186 weenie attestations.
+ GeneratorInitialDelay = 121,
+ /// 575 weenie attestations.
+ AiAcquireHealth = 122,
+ /// 6 weenie attestations.
+ AiAcquireStamina = 123,
+ /// 6 weenie attestations.
+ AiAcquireMana = 124,
+ /// 4361 weenie attestations.
+ ResistHealthDrain = 125,
+ LifestoneProtectionTimestamp = 126,
+ /// 72 weenie attestations.
+ AiCounteractEnchantment = 127,
+ /// 10 weenie attestations.
+ AiDispelEnchantment = 128,
+ TradeTimestamp = 129,
+ AiTargetedDetectionRadius = 130,
+ /// 29 weenie attestations.
+ EmotePriority = 131,
+ LastTeleportStartTimestamp = 132,
+ EventSpamTimestamp = 133,
+ EventSpamRate = 134,
+ /// 5 weenie attestations.
+ InventoryOffset = 135,
+ /// 396 weenie attestations.
+ CriticalMultiplier = 136,
+ /// 15 weenie attestations.
+ ManaStoneDestroyChance = 137,
+ /// 351 weenie attestations.
+ SlayerDamageBonus = 138,
+ AllegianceInfoSpamTimestamp = 139,
+ AllegianceInfoSpamRate = 140,
+ NextSpellcastTimestamp = 141,
+ AppraisalRequestedTimestamp = 142,
+ AppraisalHeartbeatDueTimestamp = 143,
+ /// 209 weenie attestations.
+ ManaConversionMod = 144,
+ LastPkAttackTimestamp = 145,
+ FellowshipUpdateTimestamp = 146,
+ /// 395 weenie attestations.
+ CriticalFrequency = 147,
+ LimboStartTimestamp = 148,
+ /// 356 weenie attestations.
+ WeaponMissileDefense = 149,
+ /// 368 weenie attestations.
+ WeaponMagicDefense = 150,
+ /// 87 weenie attestations.
+ IgnoreShield = 151,
+ /// 135 weenie attestations.
+ ElementalDamageMod = 152,
+ StartMissileAttackTimestamp = 153,
+ LastRareUsedTimestamp = 154,
+ /// 69 weenie attestations.
+ IgnoreArmor = 155,
+ ProcSpellRate = 156,
+ /// 93 weenie attestations.
+ ResistanceModifier = 157,
+ AllegianceGagTimestamp = 158,
+ /// 18 weenie attestations.
+ AbsorbMagicDamage = 159,
+ CachedMaxAbsorbMagicDamage = 160,
+ GagDuration = 161,
+ AllegianceGagDuration = 162,
+ GlobalXpMod = 163,
+ HealingModifier = 164,
+ /// 391 weenie attestations.
+ ArmorModVsNether = 165,
+ ResistNether = 166,
+ /// 369 weenie attestations.
+ CooldownDuration = 167,
+ WeaponAuraOffense = 168,
+ WeaponAuraDefense = 169,
+ WeaponAuraElemental = 170,
+ WeaponAuraManaConv = 171,
+}
diff --git a/src/AcDream.Core/Properties/PropertyInstanceId.cs b/src/AcDream.Core/Properties/PropertyInstanceId.cs
new file mode 100644
index 00000000..c386c1ed
--- /dev/null
+++ b/src/AcDream.Core/Properties/PropertyInstanceId.cs
@@ -0,0 +1,79 @@
+//
+// 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.
+//
+
+namespace AcDream.Core.Properties;
+
+///
+/// AC's PropertyInstanceId property table — the numeric keys the server sends in
+/// PrivateUpdatePropertyInstanceId (0x02E5) / PublicUpdatePropertyInstanceId (0x02E6)
+/// and in the property bundles carried by CreateObject / PlayerDescription /
+/// IdentifyResponse. The CLR payload for this table is uint (object guid).
+///
+/// Verified 2026-07-29 against two independent oracles: the vendored
+/// client-side enum catalog (references/acclientlib/UtilityBelt.Common/Enums/Enums.cs,
+/// which names this table InstanceId) and the 38,985-file ACE weenie export corpus
+/// (references/weenies/), whose per-stat _comment 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.
+///
+/// This enum is a vocabulary, not a parser contract: the wire carries a raw
+/// uint and unknown keys must still round-trip untouched, so never assume a
+/// received key is a defined member.
+///
+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,
+ /// 130 weenie attestations.
+ 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,
+ /// 2 weenie attestations.
+ AllowedWielder = 38,
+ AssignedTarget = 39,
+ LimboSource = 40,
+ Snooper = 41,
+ TeleportedCharacter = 42,
+ Pet = 43,
+ PetOwner = 44,
+ PetDevice = 45,
+}
diff --git a/src/AcDream.Core/Properties/PropertyInt.cs b/src/AcDream.Core/Properties/PropertyInt.cs
new file mode 100644
index 00000000..b288dda3
--- /dev/null
+++ b/src/AcDream.Core/Properties/PropertyInt.cs
@@ -0,0 +1,611 @@
+//
+// 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.
+//
+
+namespace AcDream.Core.Properties;
+
+///
+/// AC's PropertyInt property table — the numeric keys the server sends in
+/// PrivateUpdatePropertyInt (0x02CD) / PublicUpdatePropertyInt (0x02CE)
+/// and in the property bundles carried by CreateObject / PlayerDescription /
+/// IdentifyResponse. The CLR payload for this table is int.
+///
+/// Verified 2026-07-29 against two independent oracles: the vendored
+/// client-side enum catalog (references/acclientlib/UtilityBelt.Common/Enums/Enums.cs,
+/// which names this table IntId) and the 38,985-file ACE weenie export corpus
+/// (references/weenies/), whose per-stat _comment 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.
+///
+/// This enum is a vocabulary, not a parser contract: the wire carries a raw
+/// uint and unknown keys must still round-trip untouched, so never assume a
+/// received key is a defined member.
+///
+public enum PropertyInt : uint
+{
+ Undef = 0,
+ /// UtilityBelt catalog calls this ObjectType; 37329 weenie attestations.
+ ItemType = 1,
+ /// 6140 weenie attestations.
+ CreatureType = 2,
+ /// 8344 weenie attestations.
+ PaletteTemplate = 3,
+ /// 1597 weenie attestations.
+ ClothingPriority = 4,
+ /// 25793 weenie attestations.
+ EncumbranceVal = 5,
+ /// 8633 weenie attestations.
+ ItemsCapacity = 6,
+ /// 8618 weenie attestations.
+ ContainersCapacity = 7,
+ /// 23605 weenie attestations.
+ Mass = 8,
+ /// 20797 weenie attestations.
+ ValidLocations = 9,
+ CurrentWieldedLocation = 10,
+ /// 4373 weenie attestations.
+ MaxStackSize = 11,
+ /// 4373 weenie attestations.
+ StackSize = 12,
+ /// 3181 weenie attestations.
+ StackUnitEncumbrance = 13,
+ /// 3181 weenie attestations.
+ StackUnitMass = 14,
+ /// 3181 weenie attestations.
+ StackUnitValue = 15,
+ /// 37280 weenie attestations.
+ ItemUseable = 16,
+ /// 21 weenie attestations.
+ RareId = 17,
+ /// 5705 weenie attestations.
+ UiEffects = 18,
+ /// 25852 weenie attestations.
+ Value = 19,
+ /// 1 weenie attestations.
+ CoinValue = 20,
+ TotalExperience = 21,
+ AvailableCharacter = 22,
+ TotalSkillCredits = 23,
+ AvailableSkillCredits = 24,
+ /// 6140 weenie attestations.
+ Level = 25,
+ /// 28 weenie attestations.
+ AccountRequirements = 26,
+ /// 5476 weenie attestations.
+ ArmorType = 27,
+ /// 1657 weenie attestations.
+ ArmorLevel = 28,
+ AllegianceCpPool = 29,
+ /// 1 weenie attestations.
+ AllegianceRank = 30,
+ ChannelsAllowed = 31,
+ ChannelsActive = 32,
+ /// 6252 weenie attestations.
+ Bonded = 33,
+ MonarchsRank = 34,
+ AllegianceFollowers = 35,
+ /// 997 weenie attestations.
+ ResistMagic = 36,
+ /// 575 weenie attestations.
+ ResistItemAppraisal = 37,
+ /// 677 weenie attestations.
+ ResistLockpick = 38,
+ DeprecatedResistRepair = 39,
+ /// 1634 weenie attestations.
+ CombatMode = 40,
+ CurrentAttackHeight = 41,
+ CombatCollisions = 42,
+ /// 1 weenie attestations.
+ NumDeaths = 43,
+ /// 3717 weenie attestations.
+ Damage = 44,
+ /// 3357 weenie attestations.
+ DamageType = 45,
+ /// 2973 weenie attestations.
+ DefaultCombatStyle = 46,
+ /// 2364 weenie attestations.
+ AttackType = 47,
+ /// 3393 weenie attestations.
+ WeaponSkill = 48,
+ /// 3394 weenie attestations.
+ WeaponTime = 49,
+ /// 972 weenie attestations.
+ AmmoType = 50,
+ /// 4499 weenie attestations.
+ CombatUse = 51,
+ /// 440 weenie attestations.
+ ParentLocation = 52,
+ /// 440 weenie attestations.
+ PlacementPosition = 53,
+ WeaponEncumbrance = 54,
+ WeaponMass = 55,
+ ShieldValue = 56,
+ ShieldEncumbrance = 57,
+ MissileInventoryLocation = 58,
+ FullDamageType = 59,
+ /// 545 weenie attestations.
+ WeaponRange = 60,
+ AttackersSkill = 61,
+ DefendersSkill = 62,
+ AttackersSkillValue = 63,
+ AttackersClass = 64,
+ Placement = 65,
+ /// 179 weenie attestations.
+ CheckpointStatus = 66,
+ /// 219 weenie attestations.
+ Tolerance = 67,
+ /// 2151 weenie attestations.
+ TargetingTactic = 68,
+ /// 48 weenie attestations.
+ CombatTactic = 69,
+ HomesickTargetingTactic = 70,
+ NumFollowFailures = 71,
+ /// 494 weenie attestations.
+ FriendType = 72,
+ FoeType = 73,
+ /// UtilityBelt catalog calls this MerchandiseObjectTypes; 1049 weenie attestations.
+ MerchandiseItemTypes = 74,
+ /// 1049 weenie attestations.
+ MerchandiseMinValue = 75,
+ /// 1049 weenie attestations.
+ MerchandiseMaxValue = 76,
+ NumItemsSold = 77,
+ NumItemsBought = 78,
+ MoneyIncome = 79,
+ MoneyOutflow = 80,
+ /// 2195 weenie attestations.
+ MaxGeneratedObjects = 81,
+ /// 2195 weenie attestations.
+ InitGeneratedObjects = 82,
+ /// 787 weenie attestations.
+ ActivationResponse = 83,
+ OriginalValue = 84,
+ NumMoveFailures = 85,
+ /// 815 weenie attestations.
+ MinLevel = 86,
+ /// 115 weenie attestations.
+ MaxLevel = 87,
+ /// 10 weenie attestations.
+ LockpickMod = 88,
+ /// 525 weenie attestations.
+ BoosterEnum = 89,
+ /// 532 weenie attestations.
+ BoostValue = 90,
+ /// 800 weenie attestations.
+ MaxStructure = 91,
+ /// 713 weenie attestations.
+ Structure = 92,
+ /// 38985 weenie attestations.
+ PhysicsState = 93,
+ /// 3570 weenie attestations.
+ TargetType = 94,
+ /// 2668 weenie attestations.
+ RadarBlipColor = 95,
+ /// 472 weenie attestations.
+ EncumbranceCapacity = 96,
+ LoginTimestamp = 97,
+ /// 119 weenie attestations.
+ CreationTimestamp = 98,
+ /// 4 weenie attestations.
+ PkLevelModifier = 99,
+ /// 575 weenie attestations.
+ GeneratorType = 100,
+ /// 1265 weenie attestations.
+ AiAllowedCombatStyle = 101,
+ LogoffTimestamp = 102,
+ /// 158 weenie attestations.
+ GeneratorDestructionType = 103,
+ ActivationCreateClass = 104,
+ /// 693 weenie attestations.
+ ItemWorkmanship = 105,
+ /// 4213 weenie attestations.
+ ItemSpellcraft = 106,
+ /// 4173 weenie attestations.
+ ItemCurMana = 107,
+ /// 4211 weenie attestations.
+ ItemMaxMana = 108,
+ /// 3091 weenie attestations.
+ ItemDifficulty = 109,
+ /// 1043 weenie attestations.
+ ItemAllegianceRankLimit = 110,
+ /// 2940 weenie attestations.
+ PortalBitmask = 111,
+ AdvocateLevel = 112,
+ /// 749 weenie attestations.
+ Gender = 113,
+ /// 4502 weenie attestations.
+ Attuned = 114,
+ /// 1640 weenie attestations.
+ ItemSkillLevelLimit = 115,
+ GateLogic = 116,
+ /// 66 weenie attestations.
+ ItemManaCost = 117,
+ Logoff = 118,
+ /// 365 weenie attestations.
+ Active = 119,
+ AttackHeight = 120,
+ NumAttackFailures = 121,
+ AiCpThreshold = 122,
+ AiAdvancementStrategy = 123,
+ Version = 124,
+ /// 1 weenie attestations.
+ Age = 125,
+ /// 1048 weenie attestations.
+ VendorHappyMean = 126,
+ /// 1048 weenie attestations.
+ VendorHappyVariance = 127,
+ CloakStatus = 128,
+ VitaeCpPool = 129,
+ NumServicesSold = 130,
+ /// 586 weenie attestations.
+ MaterialType = 131,
+ NumAllegianceBreaks = 132,
+ /// 10541 weenie attestations.
+ ShowableOnRadar = 133,
+ /// 3138 weenie attestations.
+ PlayerKillerStatus = 134,
+ VendorHappyMaxItems = 135,
+ /// 5 weenie attestations.
+ ScorePageNum = 136,
+ /// 5 weenie attestations.
+ ScoreConfigNum = 137,
+ /// 5 weenie attestations.
+ ScoreNumScores = 138,
+ DeathLevel = 139,
+ /// 1411 weenie attestations.
+ AiOptions = 140,
+ OpenToEveryone = 141,
+ /// 297 weenie attestations.
+ GeneratorTimeType = 142,
+ /// 51 weenie attestations.
+ GeneratorStartTime = 143,
+ /// 50 weenie attestations.
+ GeneratorEndTime = 144,
+ /// 257 weenie attestations.
+ GeneratorEndDestructionType = 145,
+ /// 4361 weenie attestations.
+ XpOverride = 146,
+ NumCrashAndTurns = 147,
+ ComponentWarningThreshold = 148,
+ /// 7 weenie attestations.
+ HouseStatus = 149,
+ /// 4715 weenie attestations.
+ HookPlacement = 150,
+ /// 6799 weenie attestations.
+ HookType = 151,
+ /// UtilityBelt catalog calls this HookObjectType; 5 weenie attestations.
+ HookItemType = 152,
+ AiPpThreshold = 153,
+ GeneratorVersion = 154,
+ /// 6274 weenie attestations.
+ HouseType = 155,
+ /// 10 weenie attestations.
+ PickupEmoteOffset = 156,
+ /// 1 weenie attestations.
+ WeenieIteration = 157,
+ /// 2557 weenie attestations.
+ WieldRequirements = 158,
+ /// 2557 weenie attestations.
+ WieldSkilltype = 159,
+ /// 2557 weenie attestations.
+ WieldDifficulty = 160,
+ /// 654 weenie attestations.
+ HouseMaxHooksUsable = 161,
+ HouseCurrentHooksUsable = 162,
+ /// 8 weenie attestations.
+ AllegianceMinLevel = 163,
+ AllegianceMaxLevel = 164,
+ HouseRelinkHookCount = 165,
+ /// 537 weenie attestations.
+ SlayerCreatureType = 166,
+ ConfirmationInProgress = 167,
+ ConfirmationTypeInProgress = 168,
+ /// 728 weenie attestations.
+ TsysMutationData = 169,
+ /// 36 weenie attestations.
+ NumItemsInMaterial = 170,
+ /// 228 weenie attestations.
+ NumTimesTinkered = 171,
+ /// 358 weenie attestations.
+ AppraisalLongDescDecoration = 172,
+ /// 133 weenie attestations.
+ AppraisalLockpickSuccessPercent = 173,
+ /// 103 weenie attestations.
+ AppraisalPages = 174,
+ /// 103 weenie attestations.
+ AppraisalMaxPages = 175,
+ /// 355 weenie attestations.
+ AppraisalItemSkill = 176,
+ /// 281 weenie attestations.
+ GemCount = 177,
+ /// 281 weenie attestations.
+ GemType = 178,
+ /// 495 weenie attestations.
+ ImbuedEffect = 179,
+ AttackersRawSkillValue = 180,
+ ChessRank = 181,
+ ChessTotalGames = 182,
+ ChessGamesWon = 183,
+ ChessGamesLost = 184,
+ /// 71 weenie attestations.
+ TypeOfAlteration = 185,
+ /// 71 weenie attestations.
+ SkillToBeAltered = 186,
+ SkillAlterationCount = 187,
+ /// 807 weenie attestations.
+ HeritageGroup = 188,
+ /// 30 weenie attestations.
+ TransferFromAttribute = 189,
+ /// 30 weenie attestations.
+ TransferToAttribute = 190,
+ AttributeTransferCount = 191,
+ FakeFishingSkill = 192,
+ /// 3 weenie attestations.
+ NumKeys = 193,
+ DeathTimestamp = 194,
+ PkTimestamp = 195,
+ VictimTimestamp = 196,
+ /// 22 weenie attestations.
+ HookGroup = 197,
+ AllegianceSwearTimestamp = 198,
+ HousePurchaseTimestamp = 199,
+ RedirectableEquippedArmorCount = 200,
+ MeleedefenseImbuedEffectTypeCache = 201,
+ MissileDefenseImbuedEffectTypeCache = 202,
+ MagicDefenseImbuedEffectTypeCache = 203,
+ /// 121 weenie attestations.
+ 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,
+ /// 1 weenie attestations.
+ ItemAttributeLimit = 257,
+ /// 1 weenie attestations.
+ ItemAttributeLevelLimit = 258,
+ ItemAttribute2ndLimit = 259,
+ ItemAttribute2ndLevelLimit = 260,
+ /// 2 weenie attestations.
+ CharacterTitleId = 261,
+ /// 1 weenie attestations.
+ NumCharacterTitles = 262,
+ /// 93 weenie attestations.
+ ResistanceModifierType = 263,
+ FreeTinkersBitfield = 264,
+ /// 316 weenie attestations.
+ EquipmentSetId = 265,
+ PetClass = 266,
+ /// 119 weenie attestations.
+ Lifespan = 267,
+ /// 119 weenie attestations.
+ RemainingLifespan = 268,
+ UseCreateQuantity = 269,
+ /// 62 weenie attestations.
+ WieldRequirements2 = 270,
+ /// 62 weenie attestations.
+ WieldSkilltype2 = 271,
+ /// 62 weenie attestations.
+ WieldDifficulty2 = 272,
+ /// 3 weenie attestations.
+ WieldRequirements3 = 273,
+ /// 3 weenie attestations.
+ WieldSkilltype3 = 274,
+ /// 3 weenie attestations.
+ WieldDifficulty3 = 275,
+ /// 17 weenie attestations.
+ WieldRequirements4 = 276,
+ /// 17 weenie attestations.
+ WieldSkilltype4 = 277,
+ /// 17 weenie attestations.
+ WieldDifficulty4 = 278,
+ /// 14 weenie attestations.
+ Unique = 279,
+ /// 365 weenie attestations.
+ SharedCooldown = 280,
+ /// 177 weenie attestations.
+ Faction1Bits = 281,
+ Faction2Bits = 282,
+ Faction3Bits = 283,
+ Hatred1Bits = 284,
+ Hatred2Bits = 285,
+ Hatred3Bits = 286,
+ /// 61 weenie attestations.
+ SocietyRankCelhan = 287,
+ /// 60 weenie attestations.
+ SocietyRankEldweb = 288,
+ /// 56 weenie attestations.
+ SocietyRankRadblo = 289,
+ HearLocalSignals = 290,
+ HearLocalSignalsRadius = 291,
+ /// 67 weenie attestations.
+ Cleaving = 292,
+ AugmentationSpecializeGearcraft = 293,
+ AugmentationInfusedCreatureMagic = 294,
+ AugmentationInfusedItemMagic = 295,
+ AugmentationInfusedLifeMagic = 296,
+ AugmentationInfusedWarMagic = 297,
+ AugmentationCriticalExpertise = 298,
+ AugmentationCriticalPower = 299,
+ AugmentationSkilledMelee = 300,
+ AugmentationSkilledMissile = 301,
+ AugmentationSkilledMagic = 302,
+ /// 124 weenie attestations.
+ ImbuedEffect2 = 303,
+ /// 124 weenie attestations.
+ ImbuedEffect3 = 304,
+ /// 117 weenie attestations.
+ ImbuedEffect4 = 305,
+ /// 117 weenie attestations.
+ ImbuedEffect5 = 306,
+ /// 1403 weenie attestations.
+ DamageRating = 307,
+ /// 729 weenie attestations.
+ DamageResistRating = 308,
+ AugmentationDamageBonus = 309,
+ AugmentationDamageReduction = 310,
+ ImbueStackingBits = 311,
+ HealOverTime = 312,
+ /// 880 weenie attestations.
+ CritRating = 313,
+ /// 843 weenie attestations.
+ CritDamageRating = 314,
+ /// 713 weenie attestations.
+ CritResistRating = 315,
+ /// 732 weenie attestations.
+ CritDamageResistRating = 316,
+ HealingResistRating = 317,
+ DamageOverTime = 318,
+ /// 79 weenie attestations.
+ ItemMaxLevel = 319,
+ /// 79 weenie attestations.
+ ItemXpStyle = 320,
+ EquipmentSetExtra = 321,
+ AetheriaBitfield = 322,
+ HealingBoostRating = 323,
+ /// 29 weenie attestations.
+ 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,
+ /// 13 weenie attestations.
+ CloakWeaveProc = 352,
+ /// 492 weenie attestations.
+ 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,
+ /// 259 weenie attestations.
+ UseRequiresSkill = 366,
+ /// 259 weenie attestations.
+ UseRequiresSkillLevel = 367,
+ /// 36 weenie attestations.
+ UseRequiresSkillSpec = 368,
+ /// 271 weenie attestations.
+ UseRequiresLevel = 369,
+ /// 869 weenie attestations.
+ GearDamage = 370,
+ /// 868 weenie attestations.
+ GearDamageResist = 371,
+ /// 854 weenie attestations.
+ GearCrit = 372,
+ /// 854 weenie attestations.
+ GearCritResist = 373,
+ /// 955 weenie attestations.
+ GearCritDamage = 374,
+ /// 953 weenie attestations.
+ GearCritDamageResist = 375,
+ /// 610 weenie attestations.
+ GearHealingBoost = 376,
+ /// 602 weenie attestations.
+ GearNetherResist = 377,
+ /// 602 weenie attestations.
+ GearLifeResist = 378,
+ /// 640 weenie attestations.
+ GearMaxHealth = 379,
+ Unknown380 = 380,
+ /// 616 weenie attestations.
+ PKDamageRating = 381,
+ /// 602 weenie attestations.
+ PKDamageResistRating = 382,
+ /// 643 weenie attestations.
+ GearPKDamageRating = 383,
+ /// 640 weenie attestations.
+ GearPKDamageResistRating = 384,
+ Unknown385 = 385,
+ /// 766 weenie attestations.
+ Overpower = 386,
+ /// 602 weenie attestations.
+ OverpowerResist = 387,
+ /// 602 weenie attestations.
+ GearOverpower = 388,
+ /// 602 weenie attestations.
+ GearOverpowerResist = 389,
+ /// 2 weenie attestations.
+ Enlightenment = 390,
+}
diff --git a/src/AcDream.Core/Properties/PropertyInt64.cs b/src/AcDream.Core/Properties/PropertyInt64.cs
new file mode 100644
index 00000000..e6792529
--- /dev/null
+++ b/src/AcDream.Core/Properties/PropertyInt64.cs
@@ -0,0 +1,43 @@
+//
+// 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.
+//
+
+namespace AcDream.Core.Properties;
+
+///
+/// AC's PropertyInt64 property table — the numeric keys the server sends in
+/// PrivateUpdatePropertyInt64 (0x02D1)
+/// and in the property bundles carried by CreateObject / PlayerDescription /
+/// IdentifyResponse. The CLR payload for this table is long.
+///
+/// Verified 2026-07-29 against two independent oracles: the vendored
+/// client-side enum catalog (references/acclientlib/UtilityBelt.Common/Enums/Enums.cs,
+/// which names this table Int64Id) and the 38,985-file ACE weenie export corpus
+/// (references/weenies/), whose per-stat _comment 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.
+///
+/// This enum is a vocabulary, not a parser contract: the wire carries a raw
+/// uint and unknown keys must still round-trip untouched, so never assume a
+/// received key is a defined member.
+///
+public enum PropertyInt64 : uint
+{
+ Undef = 0,
+ TotalExperience = 1,
+ AvailableExperience = 2,
+ /// 7 weenie attestations.
+ AugmentationCost = 3,
+ /// 79 weenie attestations.
+ ItemTotalXp = 4,
+ /// 79 weenie attestations.
+ ItemBaseXp = 5,
+ AvailableLuminance = 6,
+ MaximumLuminance = 7,
+ InteractionReqs = 8,
+}
diff --git a/src/AcDream.Core/Properties/PropertyString.cs b/src/AcDream.Core/Properties/PropertyString.cs
new file mode 100644
index 00000000..0e2f0b03
--- /dev/null
+++ b/src/AcDream.Core/Properties/PropertyString.cs
@@ -0,0 +1,112 @@
+//
+// 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.
+//
+
+namespace AcDream.Core.Properties;
+
+///
+/// AC's PropertyString property table — the numeric keys the server sends in
+/// PrivateUpdatePropertyString (0x02DD) / PublicUpdatePropertyString (0x02DE)
+/// and in the property bundles carried by CreateObject / PlayerDescription /
+/// IdentifyResponse. The CLR payload for this table is string.
+///
+/// Verified 2026-07-29 against two independent oracles: the vendored
+/// client-side enum catalog (references/acclientlib/UtilityBelt.Common/Enums/Enums.cs,
+/// which names this table StringId) and the 38,985-file ACE weenie export corpus
+/// (references/weenies/), whose per-stat _comment 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.
+///
+/// This enum is a vocabulary, not a parser contract: the wire carries a raw
+/// uint and unknown keys must still round-trip untouched, so never assume a
+/// received key is a defined member.
+///
+public enum PropertyString : uint
+{
+ Undef = 0,
+ /// 38984 weenie attestations.
+ Name = 1,
+ Title = 2,
+ /// 1697 weenie attestations.
+ Sex = 3,
+ /// 1693 weenie attestations.
+ HeritageGroup = 4,
+ /// 1622 weenie attestations.
+ Template = 5,
+ AttackersName = 6,
+ /// 93 weenie attestations.
+ Inscription = 7,
+ /// 93 weenie attestations.
+ ScribeName = 8,
+ VendorsName = 9,
+ /// 1 weenie attestations.
+ Fellowship = 10,
+ MonarchsName = 11,
+ /// 449 weenie attestations.
+ LockCode = 12,
+ /// 238 weenie attestations.
+ KeyCode = 13,
+ /// 3219 weenie attestations.
+ Use = 14,
+ /// 5597 weenie attestations.
+ ShortDesc = 15,
+ /// 7107 weenie attestations.
+ LongDesc = 16,
+ /// 109 weenie attestations.
+ ActivationTalk = 17,
+ /// 10 weenie attestations.
+ UseMessage = 18,
+ /// 45 weenie attestations.
+ ItemHeritageGroupRestriction = 19,
+ /// 1318 weenie attestations.
+ PluralName = 20,
+ MonarchsTitle = 21,
+ /// 96 weenie attestations.
+ ActivationFailure = 22,
+ ScribeAccount = 23,
+ /// 591 weenie attestations.
+ TownName = 24,
+ /// 2 weenie attestations.
+ CraftsmanName = 25,
+ /// 4 weenie attestations.
+ UsePkServerError = 26,
+ ScoreCachedText = 27,
+ /// 5 weenie attestations.
+ ScoreDefaultEntryFormat = 28,
+ /// 5 weenie attestations.
+ ScoreFirstEntryFormat = 29,
+ /// 5 weenie attestations.
+ ScoreLastEntryFormat = 30,
+ /// 5 weenie attestations.
+ ScoreOnlyEntryFormat = 31,
+ /// 5 weenie attestations.
+ ScoreNoEntry = 32,
+ /// 859 weenie attestations.
+ Quest = 33,
+ /// 249 weenie attestations.
+ GeneratorEvent = 34,
+ PatronsTitle = 35,
+ HouseOwnerName = 36,
+ /// 170 weenie attestations.
+ 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,
+}
diff --git a/tests/AcDream.Core.Tests/Properties/PropertyEnumConformanceTests.cs b/tests/AcDream.Core.Tests/Properties/PropertyEnumConformanceTests.cs
new file mode 100644
index 00000000..f6e7ed03
--- /dev/null
+++ b/tests/AcDream.Core.Tests/Properties/PropertyEnumConformanceTests.cs
@@ -0,0 +1,1398 @@
+//
+// Golden conformance table for the seven Property* enums. Regenerate with the
+// 2026-07-29 enum verification campaign tooling; see
+// docs/research/2026-07-29-enum-verification-campaign.md.
+//
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using AcDream.Core.Properties;
+using Xunit;
+
+namespace AcDream.Core.Tests.Properties;
+
+///
+/// Pins every member of AC's seven property tables to its wire value. The table
+/// below is the verbatim output of the 2026-07-29 oracle cross-check, so any hand
+/// edit to a Property* enum — a renamed member, a changed value, an added or
+/// dropped key — fails here rather than silently mis-reading the wire.
+///
+/// is the stronger subset: members whose
+/// name/value pairing is independently attested by the ACE weenie export corpus,
+/// not just by the client-side enum catalog.
+///
+public sealed class PropertyEnumConformanceTests
+{
+ private static readonly (string Name, uint Value)[] PropertyIntGolden =
+ [
+ ("Undef", 0),
+ ("ItemType", 1),
+ ("CreatureType", 2),
+ ("PaletteTemplate", 3),
+ ("ClothingPriority", 4),
+ ("EncumbranceVal", 5),
+ ("ItemsCapacity", 6),
+ ("ContainersCapacity", 7),
+ ("Mass", 8),
+ ("ValidLocations", 9),
+ ("CurrentWieldedLocation", 10),
+ ("MaxStackSize", 11),
+ ("StackSize", 12),
+ ("StackUnitEncumbrance", 13),
+ ("StackUnitMass", 14),
+ ("StackUnitValue", 15),
+ ("ItemUseable", 16),
+ ("RareId", 17),
+ ("UiEffects", 18),
+ ("Value", 19),
+ ("CoinValue", 20),
+ ("TotalExperience", 21),
+ ("AvailableCharacter", 22),
+ ("TotalSkillCredits", 23),
+ ("AvailableSkillCredits", 24),
+ ("Level", 25),
+ ("AccountRequirements", 26),
+ ("ArmorType", 27),
+ ("ArmorLevel", 28),
+ ("AllegianceCpPool", 29),
+ ("AllegianceRank", 30),
+ ("ChannelsAllowed", 31),
+ ("ChannelsActive", 32),
+ ("Bonded", 33),
+ ("MonarchsRank", 34),
+ ("AllegianceFollowers", 35),
+ ("ResistMagic", 36),
+ ("ResistItemAppraisal", 37),
+ ("ResistLockpick", 38),
+ ("DeprecatedResistRepair", 39),
+ ("CombatMode", 40),
+ ("CurrentAttackHeight", 41),
+ ("CombatCollisions", 42),
+ ("NumDeaths", 43),
+ ("Damage", 44),
+ ("DamageType", 45),
+ ("DefaultCombatStyle", 46),
+ ("AttackType", 47),
+ ("WeaponSkill", 48),
+ ("WeaponTime", 49),
+ ("AmmoType", 50),
+ ("CombatUse", 51),
+ ("ParentLocation", 52),
+ ("PlacementPosition", 53),
+ ("WeaponEncumbrance", 54),
+ ("WeaponMass", 55),
+ ("ShieldValue", 56),
+ ("ShieldEncumbrance", 57),
+ ("MissileInventoryLocation", 58),
+ ("FullDamageType", 59),
+ ("WeaponRange", 60),
+ ("AttackersSkill", 61),
+ ("DefendersSkill", 62),
+ ("AttackersSkillValue", 63),
+ ("AttackersClass", 64),
+ ("Placement", 65),
+ ("CheckpointStatus", 66),
+ ("Tolerance", 67),
+ ("TargetingTactic", 68),
+ ("CombatTactic", 69),
+ ("HomesickTargetingTactic", 70),
+ ("NumFollowFailures", 71),
+ ("FriendType", 72),
+ ("FoeType", 73),
+ ("MerchandiseItemTypes", 74),
+ ("MerchandiseMinValue", 75),
+ ("MerchandiseMaxValue", 76),
+ ("NumItemsSold", 77),
+ ("NumItemsBought", 78),
+ ("MoneyIncome", 79),
+ ("MoneyOutflow", 80),
+ ("MaxGeneratedObjects", 81),
+ ("InitGeneratedObjects", 82),
+ ("ActivationResponse", 83),
+ ("OriginalValue", 84),
+ ("NumMoveFailures", 85),
+ ("MinLevel", 86),
+ ("MaxLevel", 87),
+ ("LockpickMod", 88),
+ ("BoosterEnum", 89),
+ ("BoostValue", 90),
+ ("MaxStructure", 91),
+ ("Structure", 92),
+ ("PhysicsState", 93),
+ ("TargetType", 94),
+ ("RadarBlipColor", 95),
+ ("EncumbranceCapacity", 96),
+ ("LoginTimestamp", 97),
+ ("CreationTimestamp", 98),
+ ("PkLevelModifier", 99),
+ ("GeneratorType", 100),
+ ("AiAllowedCombatStyle", 101),
+ ("LogoffTimestamp", 102),
+ ("GeneratorDestructionType", 103),
+ ("ActivationCreateClass", 104),
+ ("ItemWorkmanship", 105),
+ ("ItemSpellcraft", 106),
+ ("ItemCurMana", 107),
+ ("ItemMaxMana", 108),
+ ("ItemDifficulty", 109),
+ ("ItemAllegianceRankLimit", 110),
+ ("PortalBitmask", 111),
+ ("AdvocateLevel", 112),
+ ("Gender", 113),
+ ("Attuned", 114),
+ ("ItemSkillLevelLimit", 115),
+ ("GateLogic", 116),
+ ("ItemManaCost", 117),
+ ("Logoff", 118),
+ ("Active", 119),
+ ("AttackHeight", 120),
+ ("NumAttackFailures", 121),
+ ("AiCpThreshold", 122),
+ ("AiAdvancementStrategy", 123),
+ ("Version", 124),
+ ("Age", 125),
+ ("VendorHappyMean", 126),
+ ("VendorHappyVariance", 127),
+ ("CloakStatus", 128),
+ ("VitaeCpPool", 129),
+ ("NumServicesSold", 130),
+ ("MaterialType", 131),
+ ("NumAllegianceBreaks", 132),
+ ("ShowableOnRadar", 133),
+ ("PlayerKillerStatus", 134),
+ ("VendorHappyMaxItems", 135),
+ ("ScorePageNum", 136),
+ ("ScoreConfigNum", 137),
+ ("ScoreNumScores", 138),
+ ("DeathLevel", 139),
+ ("AiOptions", 140),
+ ("OpenToEveryone", 141),
+ ("GeneratorTimeType", 142),
+ ("GeneratorStartTime", 143),
+ ("GeneratorEndTime", 144),
+ ("GeneratorEndDestructionType", 145),
+ ("XpOverride", 146),
+ ("NumCrashAndTurns", 147),
+ ("ComponentWarningThreshold", 148),
+ ("HouseStatus", 149),
+ ("HookPlacement", 150),
+ ("HookType", 151),
+ ("HookItemType", 152),
+ ("AiPpThreshold", 153),
+ ("GeneratorVersion", 154),
+ ("HouseType", 155),
+ ("PickupEmoteOffset", 156),
+ ("WeenieIteration", 157),
+ ("WieldRequirements", 158),
+ ("WieldSkilltype", 159),
+ ("WieldDifficulty", 160),
+ ("HouseMaxHooksUsable", 161),
+ ("HouseCurrentHooksUsable", 162),
+ ("AllegianceMinLevel", 163),
+ ("AllegianceMaxLevel", 164),
+ ("HouseRelinkHookCount", 165),
+ ("SlayerCreatureType", 166),
+ ("ConfirmationInProgress", 167),
+ ("ConfirmationTypeInProgress", 168),
+ ("TsysMutationData", 169),
+ ("NumItemsInMaterial", 170),
+ ("NumTimesTinkered", 171),
+ ("AppraisalLongDescDecoration", 172),
+ ("AppraisalLockpickSuccessPercent", 173),
+ ("AppraisalPages", 174),
+ ("AppraisalMaxPages", 175),
+ ("AppraisalItemSkill", 176),
+ ("GemCount", 177),
+ ("GemType", 178),
+ ("ImbuedEffect", 179),
+ ("AttackersRawSkillValue", 180),
+ ("ChessRank", 181),
+ ("ChessTotalGames", 182),
+ ("ChessGamesWon", 183),
+ ("ChessGamesLost", 184),
+ ("TypeOfAlteration", 185),
+ ("SkillToBeAltered", 186),
+ ("SkillAlterationCount", 187),
+ ("HeritageGroup", 188),
+ ("TransferFromAttribute", 189),
+ ("TransferToAttribute", 190),
+ ("AttributeTransferCount", 191),
+ ("FakeFishingSkill", 192),
+ ("NumKeys", 193),
+ ("DeathTimestamp", 194),
+ ("PkTimestamp", 195),
+ ("VictimTimestamp", 196),
+ ("HookGroup", 197),
+ ("AllegianceSwearTimestamp", 198),
+ ("HousePurchaseTimestamp", 199),
+ ("RedirectableEquippedArmorCount", 200),
+ ("MeleedefenseImbuedEffectTypeCache", 201),
+ ("MissileDefenseImbuedEffectTypeCache", 202),
+ ("MagicDefenseImbuedEffectTypeCache", 203),
+ ("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),
+ ("ItemAttributeLimit", 257),
+ ("ItemAttributeLevelLimit", 258),
+ ("ItemAttribute2ndLimit", 259),
+ ("ItemAttribute2ndLevelLimit", 260),
+ ("CharacterTitleId", 261),
+ ("NumCharacterTitles", 262),
+ ("ResistanceModifierType", 263),
+ ("FreeTinkersBitfield", 264),
+ ("EquipmentSetId", 265),
+ ("PetClass", 266),
+ ("Lifespan", 267),
+ ("RemainingLifespan", 268),
+ ("UseCreateQuantity", 269),
+ ("WieldRequirements2", 270),
+ ("WieldSkilltype2", 271),
+ ("WieldDifficulty2", 272),
+ ("WieldRequirements3", 273),
+ ("WieldSkilltype3", 274),
+ ("WieldDifficulty3", 275),
+ ("WieldRequirements4", 276),
+ ("WieldSkilltype4", 277),
+ ("WieldDifficulty4", 278),
+ ("Unique", 279),
+ ("SharedCooldown", 280),
+ ("Faction1Bits", 281),
+ ("Faction2Bits", 282),
+ ("Faction3Bits", 283),
+ ("Hatred1Bits", 284),
+ ("Hatred2Bits", 285),
+ ("Hatred3Bits", 286),
+ ("SocietyRankCelhan", 287),
+ ("SocietyRankEldweb", 288),
+ ("SocietyRankRadblo", 289),
+ ("HearLocalSignals", 290),
+ ("HearLocalSignalsRadius", 291),
+ ("Cleaving", 292),
+ ("AugmentationSpecializeGearcraft", 293),
+ ("AugmentationInfusedCreatureMagic", 294),
+ ("AugmentationInfusedItemMagic", 295),
+ ("AugmentationInfusedLifeMagic", 296),
+ ("AugmentationInfusedWarMagic", 297),
+ ("AugmentationCriticalExpertise", 298),
+ ("AugmentationCriticalPower", 299),
+ ("AugmentationSkilledMelee", 300),
+ ("AugmentationSkilledMissile", 301),
+ ("AugmentationSkilledMagic", 302),
+ ("ImbuedEffect2", 303),
+ ("ImbuedEffect3", 304),
+ ("ImbuedEffect4", 305),
+ ("ImbuedEffect5", 306),
+ ("DamageRating", 307),
+ ("DamageResistRating", 308),
+ ("AugmentationDamageBonus", 309),
+ ("AugmentationDamageReduction", 310),
+ ("ImbueStackingBits", 311),
+ ("HealOverTime", 312),
+ ("CritRating", 313),
+ ("CritDamageRating", 314),
+ ("CritResistRating", 315),
+ ("CritDamageResistRating", 316),
+ ("HealingResistRating", 317),
+ ("DamageOverTime", 318),
+ ("ItemMaxLevel", 319),
+ ("ItemXpStyle", 320),
+ ("EquipmentSetExtra", 321),
+ ("AetheriaBitfield", 322),
+ ("HealingBoostRating", 323),
+ ("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),
+ ("CloakWeaveProc", 352),
+ ("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),
+ ("UseRequiresSkill", 366),
+ ("UseRequiresSkillLevel", 367),
+ ("UseRequiresSkillSpec", 368),
+ ("UseRequiresLevel", 369),
+ ("GearDamage", 370),
+ ("GearDamageResist", 371),
+ ("GearCrit", 372),
+ ("GearCritResist", 373),
+ ("GearCritDamage", 374),
+ ("GearCritDamageResist", 375),
+ ("GearHealingBoost", 376),
+ ("GearNetherResist", 377),
+ ("GearLifeResist", 378),
+ ("GearMaxHealth", 379),
+ ("Unknown380", 380),
+ ("PKDamageRating", 381),
+ ("PKDamageResistRating", 382),
+ ("GearPKDamageRating", 383),
+ ("GearPKDamageResistRating", 384),
+ ("Unknown385", 385),
+ ("Overpower", 386),
+ ("OverpowerResist", 387),
+ ("GearOverpower", 388),
+ ("GearOverpowerResist", 389),
+ ("Enlightenment", 390),
+ ];
+
+ private static readonly (string Name, uint Value)[] PropertyInt64Golden =
+ [
+ ("Undef", 0),
+ ("TotalExperience", 1),
+ ("AvailableExperience", 2),
+ ("AugmentationCost", 3),
+ ("ItemTotalXp", 4),
+ ("ItemBaseXp", 5),
+ ("AvailableLuminance", 6),
+ ("MaximumLuminance", 7),
+ ("InteractionReqs", 8),
+ ];
+
+ private static readonly (string Name, uint Value)[] PropertyBoolGolden =
+ [
+ ("Undef", 0),
+ ("Stuck", 1),
+ ("Open", 2),
+ ("Locked", 3),
+ ("RotProof", 4),
+ ("AllegianceUpdateRequest", 5),
+ ("AiUsesMana", 6),
+ ("AiUseHumanMagicAnimations", 7),
+ ("AllowGive", 8),
+ ("CurrentlyAttacking", 9),
+ ("AttackerAi", 10),
+ ("IgnoreCollisions", 11),
+ ("ReportCollisions", 12),
+ ("Ethereal", 13),
+ ("GravityStatus", 14),
+ ("LightsStatus", 15),
+ ("ScriptedCollision", 16),
+ ("Inelastic", 17),
+ ("Visibility", 18),
+ ("Attackable", 19),
+ ("SafeSpellComponents", 20),
+ ("AdvocateState", 21),
+ ("Inscribable", 22),
+ ("DestroyOnSell", 23),
+ ("UiHidden", 24),
+ ("IgnoreHouseBarriers", 25),
+ ("HiddenAdmin", 26),
+ ("PkWounder", 27),
+ ("PkKiller", 28),
+ ("NoCorpse", 29),
+ ("UnderLifestoneProtection", 30),
+ ("ItemManaUpdatePending", 31),
+ ("GeneratorStatus", 32),
+ ("ResetMessagePending", 33),
+ ("DefaultOpen", 34),
+ ("DefaultLocked", 35),
+ ("DefaultOn", 36),
+ ("OpenForBusiness", 37),
+ ("IsFrozen", 38),
+ ("DealMagicalItems", 39),
+ ("LogoffImDead", 40),
+ ("ReportCollisionsAsEnvironment", 41),
+ ("AllowEdgeSlide", 42),
+ ("AdvocateQuest", 43),
+ ("IsAdmin", 44),
+ ("IsArch", 45),
+ ("IsSentinel", 46),
+ ("IsAdvocate", 47),
+ ("CurrentlyPoweringUp", 48),
+ ("GeneratorEnteredWorld", 49),
+ ("NeverFailCasting", 50),
+ ("VendorService", 51),
+ ("AiImmobile", 52),
+ ("DamagedByCollisions", 53),
+ ("IsDynamic", 54),
+ ("IsHot", 55),
+ ("IsAffecting", 56),
+ ("AffectsAis", 57),
+ ("SpellQueueActive", 58),
+ ("GeneratorDisabled", 59),
+ ("IsAcceptingTells", 60),
+ ("LoggingChannel", 61),
+ ("OpensAnyLock", 62),
+ ("UnlimitedUse", 63),
+ ("GeneratedTreasureItem", 64),
+ ("IgnoreMagicResist", 65),
+ ("IgnoreMagicArmor", 66),
+ ("AiAllowTrade", 67),
+ ("SpellComponentsRequired", 68),
+ ("IsSellable", 69),
+ ("IgnoreShieldsBySkill", 70),
+ ("NoDraw", 71),
+ ("ActivationUntargeted", 72),
+ ("HouseHasGottenPriorityBootPos", 73),
+ ("GeneratorAutomaticDestruction", 74),
+ ("HouseHooksVisible", 75),
+ ("HouseRequiresMonarch", 76),
+ ("HouseHooksEnabled", 77),
+ ("HouseNotifiedHudOfHookCount", 78),
+ ("AiAcceptEverything", 79),
+ ("IgnorePortalRestrictions", 80),
+ ("RequiresBackpackSlot", 81),
+ ("DontTurnOrMoveWhenGiving", 82),
+ ("NpcLooksLikeObject", 83),
+ ("IgnoreCloIcons", 84),
+ ("AppraisalHasAllowedWielder", 85),
+ ("ChestRegenOnClose", 86),
+ ("LogoffInMinigame", 87),
+ ("PortalShowDestination", 88),
+ ("PortalIgnoresPkAttackTimer", 89),
+ ("NpcInteractsSilently", 90),
+ ("Retained", 91),
+ ("IgnoreAuthor", 92),
+ ("Limbo", 93),
+ ("AppraisalHasAllowedActivator", 94),
+ ("ExistedBeforeAllegianceXpChanges", 95),
+ ("IsDeaf", 96),
+ ("IsPsr", 97),
+ ("Invincible", 98),
+ ("Ivoryable", 99),
+ ("Dyable", 100),
+ ("CanGenerateRare", 101),
+ ("CorpseGeneratedRare", 102),
+ ("NonProjectileMagicImmune", 103),
+ ("ActdReceivedItems", 104),
+ ("Unknown105", 105),
+ ("FirstEnterWorldDone", 106),
+ ("RecallsDisabled", 107),
+ ("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),
+ ("AutowieldLeft", 130),
+ ];
+
+ private static readonly (string Name, uint Value)[] PropertyFloatGolden =
+ [
+ ("Undef", 0),
+ ("HeartbeatInterval", 1),
+ ("HeartbeatTimestamp", 2),
+ ("HealthRate", 3),
+ ("StaminaRate", 4),
+ ("ManaRate", 5),
+ ("HealthUponResurrection", 6),
+ ("StaminaUponResurrection", 7),
+ ("ManaUponResurrection", 8),
+ ("StartTime", 9),
+ ("StopTime", 10),
+ ("ResetInterval", 11),
+ ("Shade", 12),
+ ("ArmorModVsSlash", 13),
+ ("ArmorModVsPierce", 14),
+ ("ArmorModVsBludgeon", 15),
+ ("ArmorModVsCold", 16),
+ ("ArmorModVsFire", 17),
+ ("ArmorModVsAcid", 18),
+ ("ArmorModVsElectric", 19),
+ ("CombatSpeed", 20),
+ ("WeaponLength", 21),
+ ("DamageVariance", 22),
+ ("CurrentPowerMod", 23),
+ ("AccuracyMod", 24),
+ ("StrengthMod", 25),
+ ("MaximumVelocity", 26),
+ ("RotationSpeed", 27),
+ ("MotionTimestamp", 28),
+ ("WeaponDefense", 29),
+ ("WimpyLevel", 30),
+ ("VisualAwarenessRange", 31),
+ ("AuralAwarenessRange", 32),
+ ("PerceptionLevel", 33),
+ ("PowerupTime", 34),
+ ("MaxChargeDistance", 35),
+ ("ChargeSpeed", 36),
+ ("BuyPrice", 37),
+ ("SellPrice", 38),
+ ("DefaultScale", 39),
+ ("LockpickMod", 40),
+ ("RegenerationInterval", 41),
+ ("RegenerationTimestamp", 42),
+ ("GeneratorRadius", 43),
+ ("TimeToRot", 44),
+ ("DeathTimestamp", 45),
+ ("PkTimestamp", 46),
+ ("VictimTimestamp", 47),
+ ("LoginTimestamp", 48),
+ ("CreationTimestamp", 49),
+ ("MinimumTimeSincePk", 50),
+ ("DeprecatedHousekeepingPriority", 51),
+ ("AbuseLoggingTimestamp", 52),
+ ("LastPortalTeleportTimestamp", 53),
+ ("UseRadius", 54),
+ ("HomeRadius", 55),
+ ("ReleasedTimestamp", 56),
+ ("MinHomeRadius", 57),
+ ("Facing", 58),
+ ("ResetTimestamp", 59),
+ ("LogoffTimestamp", 60),
+ ("EconRecoveryInterval", 61),
+ ("WeaponOffense", 62),
+ ("DamageMod", 63),
+ ("ResistSlash", 64),
+ ("ResistPierce", 65),
+ ("ResistBludgeon", 66),
+ ("ResistFire", 67),
+ ("ResistCold", 68),
+ ("ResistAcid", 69),
+ ("ResistElectric", 70),
+ ("ResistHealthBoost", 71),
+ ("ResistStaminaDrain", 72),
+ ("ResistStaminaBoost", 73),
+ ("ResistManaDrain", 74),
+ ("ResistManaBoost", 75),
+ ("Translucency", 76),
+ ("PhysicsScriptIntensity", 77),
+ ("Friction", 78),
+ ("Elasticity", 79),
+ ("AiUseMagicDelay", 80),
+ ("ItemMinSpellcraftMod", 81),
+ ("ItemMaxSpellcraftMod", 82),
+ ("ItemRankProbability", 83),
+ ("Shade2", 84),
+ ("Shade3", 85),
+ ("Shade4", 86),
+ ("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),
+ ("HealkitMod", 100),
+ ("FrozenTimestamp", 101),
+ ("HealthRateMod", 102),
+ ("AllegianceSwearTimestamp", 103),
+ ("ObviousRadarRange", 104),
+ ("HotspotCycleTime", 105),
+ ("HotspotCycleTimeVariance", 106),
+ ("SpamTimestamp", 107),
+ ("SpamRate", 108),
+ ("BondWieldedTreasure", 109),
+ ("BulkMod", 110),
+ ("SizeMod", 111),
+ ("GagTimestamp", 112),
+ ("GeneratorUpdateTimestamp", 113),
+ ("DeathSpamTimestamp", 114),
+ ("DeathSpamRate", 115),
+ ("WildAttackProbability", 116),
+ ("FocusedProbability", 117),
+ ("CrashAndTurnProbability", 118),
+ ("CrashAndTurnRadius", 119),
+ ("CrashAndTurnBias", 120),
+ ("GeneratorInitialDelay", 121),
+ ("AiAcquireHealth", 122),
+ ("AiAcquireStamina", 123),
+ ("AiAcquireMana", 124),
+ ("ResistHealthDrain", 125),
+ ("LifestoneProtectionTimestamp", 126),
+ ("AiCounteractEnchantment", 127),
+ ("AiDispelEnchantment", 128),
+ ("TradeTimestamp", 129),
+ ("AiTargetedDetectionRadius", 130),
+ ("EmotePriority", 131),
+ ("LastTeleportStartTimestamp", 132),
+ ("EventSpamTimestamp", 133),
+ ("EventSpamRate", 134),
+ ("InventoryOffset", 135),
+ ("CriticalMultiplier", 136),
+ ("ManaStoneDestroyChance", 137),
+ ("SlayerDamageBonus", 138),
+ ("AllegianceInfoSpamTimestamp", 139),
+ ("AllegianceInfoSpamRate", 140),
+ ("NextSpellcastTimestamp", 141),
+ ("AppraisalRequestedTimestamp", 142),
+ ("AppraisalHeartbeatDueTimestamp", 143),
+ ("ManaConversionMod", 144),
+ ("LastPkAttackTimestamp", 145),
+ ("FellowshipUpdateTimestamp", 146),
+ ("CriticalFrequency", 147),
+ ("LimboStartTimestamp", 148),
+ ("WeaponMissileDefense", 149),
+ ("WeaponMagicDefense", 150),
+ ("IgnoreShield", 151),
+ ("ElementalDamageMod", 152),
+ ("StartMissileAttackTimestamp", 153),
+ ("LastRareUsedTimestamp", 154),
+ ("IgnoreArmor", 155),
+ ("ProcSpellRate", 156),
+ ("ResistanceModifier", 157),
+ ("AllegianceGagTimestamp", 158),
+ ("AbsorbMagicDamage", 159),
+ ("CachedMaxAbsorbMagicDamage", 160),
+ ("GagDuration", 161),
+ ("AllegianceGagDuration", 162),
+ ("GlobalXpMod", 163),
+ ("HealingModifier", 164),
+ ("ArmorModVsNether", 165),
+ ("ResistNether", 166),
+ ("CooldownDuration", 167),
+ ("WeaponAuraOffense", 168),
+ ("WeaponAuraDefense", 169),
+ ("WeaponAuraElemental", 170),
+ ("WeaponAuraManaConv", 171),
+ ];
+
+ private static readonly (string Name, uint Value)[] PropertyStringGolden =
+ [
+ ("Undef", 0),
+ ("Name", 1),
+ ("Title", 2),
+ ("Sex", 3),
+ ("HeritageGroup", 4),
+ ("Template", 5),
+ ("AttackersName", 6),
+ ("Inscription", 7),
+ ("ScribeName", 8),
+ ("VendorsName", 9),
+ ("Fellowship", 10),
+ ("MonarchsName", 11),
+ ("LockCode", 12),
+ ("KeyCode", 13),
+ ("Use", 14),
+ ("ShortDesc", 15),
+ ("LongDesc", 16),
+ ("ActivationTalk", 17),
+ ("UseMessage", 18),
+ ("ItemHeritageGroupRestriction", 19),
+ ("PluralName", 20),
+ ("MonarchsTitle", 21),
+ ("ActivationFailure", 22),
+ ("ScribeAccount", 23),
+ ("TownName", 24),
+ ("CraftsmanName", 25),
+ ("UsePkServerError", 26),
+ ("ScoreCachedText", 27),
+ ("ScoreDefaultEntryFormat", 28),
+ ("ScoreFirstEntryFormat", 29),
+ ("ScoreLastEntryFormat", 30),
+ ("ScoreOnlyEntryFormat", 31),
+ ("ScoreNoEntry", 32),
+ ("Quest", 33),
+ ("GeneratorEvent", 34),
+ ("PatronsTitle", 35),
+ ("HouseOwnerName", 36),
+ ("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),
+ ];
+
+ private static readonly (string Name, uint Value)[] PropertyDataIdGolden =
+ [
+ ("Undef", 0),
+ ("Setup", 1),
+ ("MotionTable", 2),
+ ("SoundTable", 3),
+ ("CombatTable", 4),
+ ("QualityFilter", 5),
+ ("PaletteBase", 6),
+ ("ClothingBase", 7),
+ ("Icon", 8),
+ ("EyesTexture", 9),
+ ("NoseTexture", 10),
+ ("MouthTexture", 11),
+ ("DefaultEyesTexture", 12),
+ ("DefaultNoseTexture", 13),
+ ("DefaultMouthTexture", 14),
+ ("HairPalette", 15),
+ ("EyesPalette", 16),
+ ("SkinPalette", 17),
+ ("HeadObject", 18),
+ ("ActivationAnimation", 19),
+ ("InitMotion", 20),
+ ("ActivationSound", 21),
+ ("PhysicsEffectTable", 22),
+ ("UseSound", 23),
+ ("UseTargetAnimation", 24),
+ ("UseTargetSuccessAnimation", 25),
+ ("UseTargetFailureAnimation", 26),
+ ("UseUserAnimation", 27),
+ ("Spell", 28),
+ ("SpellComponent", 29),
+ ("PhysicsScript", 30),
+ ("LinkedPortalOne", 31),
+ ("WieldedTreasureType", 32),
+ ("UnknownGuessedname", 33),
+ ("UnknownGuessedname2", 34),
+ ("DeathTreasureType", 35),
+ ("MutateFilter", 36),
+ ("ItemSkillLimit", 37),
+ ("UseCreateItem", 38),
+ ("DeathSpell", 39),
+ ("VendorsClassId", 40),
+ ("ItemSpecializedOnly", 41),
+ ("HouseId", 42),
+ ("AccountHouseId", 43),
+ ("RestrictionEffect", 44),
+ ("CreationMutationFilter", 45),
+ ("TsysMutationFilter", 46),
+ ("LastPortal", 47),
+ ("LinkedPortalTwo", 48),
+ ("OriginalPortal", 49),
+ ("IconOverlay", 50),
+ ("IconOverlaySecondary", 51),
+ ("IconUnderlay", 52),
+ ("AugmentationMutationFilter", 53),
+ ("AugmentationEffect", 54),
+ ("ProcSpell", 55),
+ ("AugmentationCreateItem", 56),
+ ("AlternateCurrency", 57),
+ ("BlueSurgeSpell", 58),
+ ("YellowSurgeSpell", 59),
+ ("RedSurgeSpell", 60),
+ ("OlthoiDeathTreasureType", 61),
+ ];
+
+ private static readonly (string Name, uint Value)[] PropertyInstanceIdGolden =
+ [
+ ("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),
+ ("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),
+ ("AllowedWielder", 38),
+ ("AssignedTarget", 39),
+ ("LimboSource", 40),
+ ("Snooper", 41),
+ ("TeleportedCharacter", 42),
+ ("Pet", 43),
+ ("PetOwner", 44),
+ ("PetDevice", 45),
+ ];
+
+ public static TheoryData Families =>
+ new("PropertyInt", "PropertyInt64", "PropertyBool", "PropertyFloat", "PropertyString", "PropertyDataId", "PropertyInstanceId");
+
+ private static (Type Enum, (string Name, uint Value)[] Golden) Resolve(string family) => family switch
+ {
+ "PropertyInt" => (typeof(PropertyInt), PropertyIntGolden),
+ "PropertyInt64" => (typeof(PropertyInt64), PropertyInt64Golden),
+ "PropertyBool" => (typeof(PropertyBool), PropertyBoolGolden),
+ "PropertyFloat" => (typeof(PropertyFloat), PropertyFloatGolden),
+ "PropertyString" => (typeof(PropertyString), PropertyStringGolden),
+ "PropertyDataId" => (typeof(PropertyDataId), PropertyDataIdGolden),
+ "PropertyInstanceId" => (typeof(PropertyInstanceId), PropertyInstanceIdGolden),
+ _ => throw new ArgumentOutOfRangeException(nameof(family), family, "unknown property family"),
+ };
+
+ [Theory]
+ [MemberData(nameof(Families))]
+ public void EnumMatchesGoldenTableExactly(string family)
+ {
+ var (type, golden) = Resolve(family);
+ var actual = Enum.GetNames(type)
+ .Select(n => (Name: n, Value: Convert.ToUInt32(Enum.Parse(type, n))))
+ .OrderBy(e => e.Value).ThenBy(e => e.Name, StringComparer.Ordinal)
+ .ToArray();
+ var expected = golden
+ .OrderBy(e => e.Value).ThenBy(e => e.Name, StringComparer.Ordinal)
+ .ToArray();
+ Assert.Equal(expected, actual);
+ }
+
+ [Theory]
+ [MemberData(nameof(Families))]
+ public void UnderlyingTypeIsUInt32(string family)
+ {
+ var (type, _) = Resolve(family);
+ Assert.Equal(typeof(uint), Enum.GetUnderlyingType(type));
+ }
+
+ [Theory]
+ [MemberData(nameof(Families))]
+ public void NoTwoMembersShareAValue(string family)
+ {
+ var (_, golden) = Resolve(family);
+ var dupes = golden.GroupBy(e => e.Value)
+ .Where(g => g.Count() > 1)
+ .Select(g => g.Key + ": " + string.Join(", ", g.Select(e => e.Name)))
+ .ToArray();
+ Assert.Empty(dupes);
+ }
+
+ ///
+ /// The name/value pairs the ACE weenie export corpus attests directly. These are
+ /// the two-oracle-confirmed members; the campaign found zero value conflicts
+ /// between the corpus and the client-side catalog across all seven tables.
+ ///
+ public static TheoryData WeenieAttested
+ {
+ get
+ {
+ var d = new TheoryData();
+ d.Add("PropertyInt", "ItemType", 1);
+ d.Add("PropertyInt", "CreatureType", 2);
+ d.Add("PropertyInt", "PaletteTemplate", 3);
+ d.Add("PropertyInt", "ClothingPriority", 4);
+ d.Add("PropertyInt", "EncumbranceVal", 5);
+ d.Add("PropertyInt", "ItemsCapacity", 6);
+ d.Add("PropertyInt", "ContainersCapacity", 7);
+ d.Add("PropertyInt", "Mass", 8);
+ d.Add("PropertyInt", "ValidLocations", 9);
+ d.Add("PropertyInt", "MaxStackSize", 11);
+ d.Add("PropertyInt", "StackSize", 12);
+ d.Add("PropertyInt", "StackUnitEncumbrance", 13);
+ d.Add("PropertyInt", "StackUnitMass", 14);
+ d.Add("PropertyInt", "StackUnitValue", 15);
+ d.Add("PropertyInt", "ItemUseable", 16);
+ d.Add("PropertyInt", "RareId", 17);
+ d.Add("PropertyInt", "UiEffects", 18);
+ d.Add("PropertyInt", "Value", 19);
+ d.Add("PropertyInt", "CoinValue", 20);
+ d.Add("PropertyInt", "Level", 25);
+ d.Add("PropertyInt", "AccountRequirements", 26);
+ d.Add("PropertyInt", "ArmorType", 27);
+ d.Add("PropertyInt", "ArmorLevel", 28);
+ d.Add("PropertyInt", "AllegianceRank", 30);
+ d.Add("PropertyInt", "Bonded", 33);
+ d.Add("PropertyInt", "ResistMagic", 36);
+ d.Add("PropertyInt", "ResistItemAppraisal", 37);
+ d.Add("PropertyInt", "ResistLockpick", 38);
+ d.Add("PropertyInt", "CombatMode", 40);
+ d.Add("PropertyInt", "NumDeaths", 43);
+ d.Add("PropertyInt", "Damage", 44);
+ d.Add("PropertyInt", "DamageType", 45);
+ d.Add("PropertyInt", "DefaultCombatStyle", 46);
+ d.Add("PropertyInt", "AttackType", 47);
+ d.Add("PropertyInt", "WeaponSkill", 48);
+ d.Add("PropertyInt", "WeaponTime", 49);
+ d.Add("PropertyInt", "AmmoType", 50);
+ d.Add("PropertyInt", "CombatUse", 51);
+ d.Add("PropertyInt", "ParentLocation", 52);
+ d.Add("PropertyInt", "PlacementPosition", 53);
+ d.Add("PropertyInt", "WeaponRange", 60);
+ d.Add("PropertyInt", "CheckpointStatus", 66);
+ d.Add("PropertyInt", "Tolerance", 67);
+ d.Add("PropertyInt", "TargetingTactic", 68);
+ d.Add("PropertyInt", "CombatTactic", 69);
+ d.Add("PropertyInt", "FriendType", 72);
+ d.Add("PropertyInt", "MerchandiseItemTypes", 74);
+ d.Add("PropertyInt", "MerchandiseMinValue", 75);
+ d.Add("PropertyInt", "MerchandiseMaxValue", 76);
+ d.Add("PropertyInt", "MaxGeneratedObjects", 81);
+ d.Add("PropertyInt", "InitGeneratedObjects", 82);
+ d.Add("PropertyInt", "ActivationResponse", 83);
+ d.Add("PropertyInt", "MinLevel", 86);
+ d.Add("PropertyInt", "MaxLevel", 87);
+ d.Add("PropertyInt", "LockpickMod", 88);
+ d.Add("PropertyInt", "BoosterEnum", 89);
+ d.Add("PropertyInt", "BoostValue", 90);
+ d.Add("PropertyInt", "MaxStructure", 91);
+ d.Add("PropertyInt", "Structure", 92);
+ d.Add("PropertyInt", "PhysicsState", 93);
+ d.Add("PropertyInt", "TargetType", 94);
+ d.Add("PropertyInt", "RadarBlipColor", 95);
+ d.Add("PropertyInt", "EncumbranceCapacity", 96);
+ d.Add("PropertyInt", "CreationTimestamp", 98);
+ d.Add("PropertyInt", "PkLevelModifier", 99);
+ d.Add("PropertyInt", "GeneratorType", 100);
+ d.Add("PropertyInt", "AiAllowedCombatStyle", 101);
+ d.Add("PropertyInt", "GeneratorDestructionType", 103);
+ d.Add("PropertyInt", "ItemWorkmanship", 105);
+ d.Add("PropertyInt", "ItemSpellcraft", 106);
+ d.Add("PropertyInt", "ItemCurMana", 107);
+ d.Add("PropertyInt", "ItemMaxMana", 108);
+ d.Add("PropertyInt", "ItemDifficulty", 109);
+ d.Add("PropertyInt", "ItemAllegianceRankLimit", 110);
+ d.Add("PropertyInt", "PortalBitmask", 111);
+ d.Add("PropertyInt", "Gender", 113);
+ d.Add("PropertyInt", "Attuned", 114);
+ d.Add("PropertyInt", "ItemSkillLevelLimit", 115);
+ d.Add("PropertyInt", "ItemManaCost", 117);
+ d.Add("PropertyInt", "Active", 119);
+ d.Add("PropertyInt", "Age", 125);
+ d.Add("PropertyInt", "VendorHappyMean", 126);
+ d.Add("PropertyInt", "VendorHappyVariance", 127);
+ d.Add("PropertyInt", "MaterialType", 131);
+ d.Add("PropertyInt", "ShowableOnRadar", 133);
+ d.Add("PropertyInt", "PlayerKillerStatus", 134);
+ d.Add("PropertyInt", "ScorePageNum", 136);
+ d.Add("PropertyInt", "ScoreConfigNum", 137);
+ d.Add("PropertyInt", "ScoreNumScores", 138);
+ d.Add("PropertyInt", "AiOptions", 140);
+ d.Add("PropertyInt", "GeneratorTimeType", 142);
+ d.Add("PropertyInt", "GeneratorStartTime", 143);
+ d.Add("PropertyInt", "GeneratorEndTime", 144);
+ d.Add("PropertyInt", "GeneratorEndDestructionType", 145);
+ d.Add("PropertyInt", "XpOverride", 146);
+ d.Add("PropertyInt", "HouseStatus", 149);
+ d.Add("PropertyInt", "HookPlacement", 150);
+ d.Add("PropertyInt", "HookType", 151);
+ d.Add("PropertyInt", "HookItemType", 152);
+ d.Add("PropertyInt", "HouseType", 155);
+ d.Add("PropertyInt", "PickupEmoteOffset", 156);
+ d.Add("PropertyInt", "WeenieIteration", 157);
+ d.Add("PropertyInt", "WieldRequirements", 158);
+ d.Add("PropertyInt", "WieldSkilltype", 159);
+ d.Add("PropertyInt", "WieldDifficulty", 160);
+ d.Add("PropertyInt", "HouseMaxHooksUsable", 161);
+ d.Add("PropertyInt", "AllegianceMinLevel", 163);
+ d.Add("PropertyInt", "SlayerCreatureType", 166);
+ d.Add("PropertyInt", "TsysMutationData", 169);
+ d.Add("PropertyInt", "NumItemsInMaterial", 170);
+ d.Add("PropertyInt", "NumTimesTinkered", 171);
+ d.Add("PropertyInt", "AppraisalLongDescDecoration", 172);
+ d.Add("PropertyInt", "AppraisalLockpickSuccessPercent", 173);
+ d.Add("PropertyInt", "AppraisalPages", 174);
+ d.Add("PropertyInt", "AppraisalMaxPages", 175);
+ d.Add("PropertyInt", "AppraisalItemSkill", 176);
+ d.Add("PropertyInt", "GemCount", 177);
+ d.Add("PropertyInt", "GemType", 178);
+ d.Add("PropertyInt", "ImbuedEffect", 179);
+ d.Add("PropertyInt", "TypeOfAlteration", 185);
+ d.Add("PropertyInt", "SkillToBeAltered", 186);
+ d.Add("PropertyInt", "HeritageGroup", 188);
+ d.Add("PropertyInt", "TransferFromAttribute", 189);
+ d.Add("PropertyInt", "TransferToAttribute", 190);
+ d.Add("PropertyInt", "NumKeys", 193);
+ d.Add("PropertyInt", "HookGroup", 197);
+ d.Add("PropertyInt", "ElementalDamageBonus", 204);
+ d.Add("PropertyInt", "ItemAttributeLimit", 257);
+ d.Add("PropertyInt", "ItemAttributeLevelLimit", 258);
+ d.Add("PropertyInt", "CharacterTitleId", 261);
+ d.Add("PropertyInt", "NumCharacterTitles", 262);
+ d.Add("PropertyInt", "ResistanceModifierType", 263);
+ d.Add("PropertyInt", "EquipmentSetId", 265);
+ d.Add("PropertyInt", "Lifespan", 267);
+ d.Add("PropertyInt", "RemainingLifespan", 268);
+ d.Add("PropertyInt", "WieldRequirements2", 270);
+ d.Add("PropertyInt", "WieldSkilltype2", 271);
+ d.Add("PropertyInt", "WieldDifficulty2", 272);
+ d.Add("PropertyInt", "WieldRequirements3", 273);
+ d.Add("PropertyInt", "WieldSkilltype3", 274);
+ d.Add("PropertyInt", "WieldDifficulty3", 275);
+ d.Add("PropertyInt", "WieldRequirements4", 276);
+ d.Add("PropertyInt", "WieldSkilltype4", 277);
+ d.Add("PropertyInt", "WieldDifficulty4", 278);
+ d.Add("PropertyInt", "Unique", 279);
+ d.Add("PropertyInt", "SharedCooldown", 280);
+ d.Add("PropertyInt", "Faction1Bits", 281);
+ d.Add("PropertyInt", "SocietyRankCelhan", 287);
+ d.Add("PropertyInt", "SocietyRankEldweb", 288);
+ d.Add("PropertyInt", "SocietyRankRadblo", 289);
+ d.Add("PropertyInt", "Cleaving", 292);
+ d.Add("PropertyInt", "ImbuedEffect2", 303);
+ d.Add("PropertyInt", "ImbuedEffect3", 304);
+ d.Add("PropertyInt", "ImbuedEffect4", 305);
+ d.Add("PropertyInt", "ImbuedEffect5", 306);
+ d.Add("PropertyInt", "DamageRating", 307);
+ d.Add("PropertyInt", "DamageResistRating", 308);
+ d.Add("PropertyInt", "CritRating", 313);
+ d.Add("PropertyInt", "CritDamageRating", 314);
+ d.Add("PropertyInt", "CritResistRating", 315);
+ d.Add("PropertyInt", "CritDamageResistRating", 316);
+ d.Add("PropertyInt", "ItemMaxLevel", 319);
+ d.Add("PropertyInt", "ItemXpStyle", 320);
+ d.Add("PropertyInt", "HeritageSpecificArmor", 324);
+ d.Add("PropertyInt", "CloakWeaveProc", 352);
+ d.Add("PropertyInt", "WeaponType", 353);
+ d.Add("PropertyInt", "UseRequiresSkill", 366);
+ d.Add("PropertyInt", "UseRequiresSkillLevel", 367);
+ d.Add("PropertyInt", "UseRequiresSkillSpec", 368);
+ d.Add("PropertyInt", "UseRequiresLevel", 369);
+ d.Add("PropertyInt", "GearDamage", 370);
+ d.Add("PropertyInt", "GearDamageResist", 371);
+ d.Add("PropertyInt", "GearCrit", 372);
+ d.Add("PropertyInt", "GearCritResist", 373);
+ d.Add("PropertyInt", "GearCritDamage", 374);
+ d.Add("PropertyInt", "GearCritDamageResist", 375);
+ d.Add("PropertyInt", "GearHealingBoost", 376);
+ d.Add("PropertyInt", "GearNetherResist", 377);
+ d.Add("PropertyInt", "GearLifeResist", 378);
+ d.Add("PropertyInt", "GearMaxHealth", 379);
+ d.Add("PropertyInt", "PKDamageRating", 381);
+ d.Add("PropertyInt", "PKDamageResistRating", 382);
+ d.Add("PropertyInt", "GearPKDamageRating", 383);
+ d.Add("PropertyInt", "GearPKDamageResistRating", 384);
+ d.Add("PropertyInt", "Overpower", 386);
+ d.Add("PropertyInt", "OverpowerResist", 387);
+ d.Add("PropertyInt", "GearOverpower", 388);
+ d.Add("PropertyInt", "GearOverpowerResist", 389);
+ d.Add("PropertyInt", "Enlightenment", 390);
+ d.Add("PropertyInt64", "AugmentationCost", 3);
+ d.Add("PropertyInt64", "ItemTotalXp", 4);
+ d.Add("PropertyInt64", "ItemBaseXp", 5);
+ d.Add("PropertyBool", "Stuck", 1);
+ d.Add("PropertyBool", "Open", 2);
+ d.Add("PropertyBool", "Locked", 3);
+ d.Add("PropertyBool", "AiUsesMana", 6);
+ d.Add("PropertyBool", "AiUseHumanMagicAnimations", 7);
+ d.Add("PropertyBool", "AllowGive", 8);
+ d.Add("PropertyBool", "IgnoreCollisions", 11);
+ d.Add("PropertyBool", "ReportCollisions", 12);
+ d.Add("PropertyBool", "Ethereal", 13);
+ d.Add("PropertyBool", "GravityStatus", 14);
+ d.Add("PropertyBool", "LightsStatus", 15);
+ d.Add("PropertyBool", "ScriptedCollision", 16);
+ d.Add("PropertyBool", "Inelastic", 17);
+ d.Add("PropertyBool", "Visibility", 18);
+ d.Add("PropertyBool", "Attackable", 19);
+ d.Add("PropertyBool", "Inscribable", 22);
+ d.Add("PropertyBool", "DestroyOnSell", 23);
+ d.Add("PropertyBool", "UiHidden", 24);
+ d.Add("PropertyBool", "NoCorpse", 29);
+ d.Add("PropertyBool", "ResetMessagePending", 33);
+ d.Add("PropertyBool", "DefaultOpen", 34);
+ d.Add("PropertyBool", "DefaultLocked", 35);
+ d.Add("PropertyBool", "DealMagicalItems", 39);
+ d.Add("PropertyBool", "ReportCollisionsAsEnvironment", 41);
+ d.Add("PropertyBool", "AllowEdgeSlide", 42);
+ d.Add("PropertyBool", "NeverFailCasting", 50);
+ d.Add("PropertyBool", "VendorService", 51);
+ d.Add("PropertyBool", "AiImmobile", 52);
+ d.Add("PropertyBool", "DamagedByCollisions", 53);
+ d.Add("PropertyBool", "IsDynamic", 54);
+ d.Add("PropertyBool", "IsHot", 55);
+ d.Add("PropertyBool", "AffectsAis", 57);
+ d.Add("PropertyBool", "LoggingChannel", 61);
+ d.Add("PropertyBool", "OpensAnyLock", 62);
+ d.Add("PropertyBool", "UnlimitedUse", 63);
+ d.Add("PropertyBool", "IgnoreMagicResist", 65);
+ d.Add("PropertyBool", "IgnoreMagicArmor", 66);
+ d.Add("PropertyBool", "SpellComponentsRequired", 68);
+ d.Add("PropertyBool", "IsSellable", 69);
+ d.Add("PropertyBool", "IgnoreShieldsBySkill", 70);
+ d.Add("PropertyBool", "NoDraw", 71);
+ d.Add("PropertyBool", "GeneratorAutomaticDestruction", 74);
+ d.Add("PropertyBool", "HouseRequiresMonarch", 76);
+ d.Add("PropertyBool", "AiAcceptEverything", 79);
+ d.Add("PropertyBool", "RequiresBackpackSlot", 81);
+ d.Add("PropertyBool", "DontTurnOrMoveWhenGiving", 82);
+ d.Add("PropertyBool", "NpcLooksLikeObject", 83);
+ d.Add("PropertyBool", "IgnoreCloIcons", 84);
+ d.Add("PropertyBool", "AppraisalHasAllowedWielder", 85);
+ d.Add("PropertyBool", "PortalShowDestination", 88);
+ d.Add("PropertyBool", "PortalIgnoresPkAttackTimer", 89);
+ d.Add("PropertyBool", "NpcInteractsSilently", 90);
+ d.Add("PropertyBool", "Retained", 91);
+ d.Add("PropertyBool", "IgnoreAuthor", 92);
+ d.Add("PropertyBool", "Ivoryable", 99);
+ d.Add("PropertyBool", "Dyable", 100);
+ d.Add("PropertyBool", "NonProjectileMagicImmune", 103);
+ d.Add("PropertyBool", "RareUsesTimer", 108);
+ d.Add("PropertyBool", "AutowieldLeft", 130);
+ d.Add("PropertyFloat", "HeartbeatInterval", 1);
+ d.Add("PropertyFloat", "HeartbeatTimestamp", 2);
+ d.Add("PropertyFloat", "HealthRate", 3);
+ d.Add("PropertyFloat", "StaminaRate", 4);
+ d.Add("PropertyFloat", "ManaRate", 5);
+ d.Add("PropertyFloat", "HealthUponResurrection", 6);
+ d.Add("PropertyFloat", "StaminaUponResurrection", 7);
+ d.Add("PropertyFloat", "ManaUponResurrection", 8);
+ d.Add("PropertyFloat", "ResetInterval", 11);
+ d.Add("PropertyFloat", "Shade", 12);
+ d.Add("PropertyFloat", "ArmorModVsSlash", 13);
+ d.Add("PropertyFloat", "ArmorModVsPierce", 14);
+ d.Add("PropertyFloat", "ArmorModVsBludgeon", 15);
+ d.Add("PropertyFloat", "ArmorModVsCold", 16);
+ d.Add("PropertyFloat", "ArmorModVsFire", 17);
+ d.Add("PropertyFloat", "ArmorModVsAcid", 18);
+ d.Add("PropertyFloat", "ArmorModVsElectric", 19);
+ d.Add("PropertyFloat", "WeaponLength", 21);
+ d.Add("PropertyFloat", "DamageVariance", 22);
+ d.Add("PropertyFloat", "MaximumVelocity", 26);
+ d.Add("PropertyFloat", "RotationSpeed", 27);
+ d.Add("PropertyFloat", "WeaponDefense", 29);
+ d.Add("PropertyFloat", "VisualAwarenessRange", 31);
+ d.Add("PropertyFloat", "PowerupTime", 34);
+ d.Add("PropertyFloat", "ChargeSpeed", 36);
+ d.Add("PropertyFloat", "BuyPrice", 37);
+ d.Add("PropertyFloat", "SellPrice", 38);
+ d.Add("PropertyFloat", "DefaultScale", 39);
+ d.Add("PropertyFloat", "LockpickMod", 40);
+ d.Add("PropertyFloat", "RegenerationInterval", 41);
+ d.Add("PropertyFloat", "GeneratorRadius", 43);
+ d.Add("PropertyFloat", "TimeToRot", 44);
+ d.Add("PropertyFloat", "MinimumTimeSincePk", 50);
+ d.Add("PropertyFloat", "UseRadius", 54);
+ d.Add("PropertyFloat", "HomeRadius", 55);
+ d.Add("PropertyFloat", "WeaponOffense", 62);
+ d.Add("PropertyFloat", "DamageMod", 63);
+ d.Add("PropertyFloat", "ResistSlash", 64);
+ d.Add("PropertyFloat", "ResistPierce", 65);
+ d.Add("PropertyFloat", "ResistBludgeon", 66);
+ d.Add("PropertyFloat", "ResistFire", 67);
+ d.Add("PropertyFloat", "ResistCold", 68);
+ d.Add("PropertyFloat", "ResistAcid", 69);
+ d.Add("PropertyFloat", "ResistElectric", 70);
+ d.Add("PropertyFloat", "ResistHealthBoost", 71);
+ d.Add("PropertyFloat", "ResistStaminaDrain", 72);
+ d.Add("PropertyFloat", "ResistStaminaBoost", 73);
+ d.Add("PropertyFloat", "ResistManaDrain", 74);
+ d.Add("PropertyFloat", "ResistManaBoost", 75);
+ d.Add("PropertyFloat", "Translucency", 76);
+ d.Add("PropertyFloat", "PhysicsScriptIntensity", 77);
+ d.Add("PropertyFloat", "Friction", 78);
+ d.Add("PropertyFloat", "Elasticity", 79);
+ d.Add("PropertyFloat", "AiUseMagicDelay", 80);
+ d.Add("PropertyFloat", "ItemEfficiency", 87);
+ d.Add("PropertyFloat", "HealkitMod", 100);
+ d.Add("PropertyFloat", "ObviousRadarRange", 104);
+ d.Add("PropertyFloat", "HotspotCycleTime", 105);
+ d.Add("PropertyFloat", "HotspotCycleTimeVariance", 106);
+ d.Add("PropertyFloat", "BondWieldedTreasure", 109);
+ d.Add("PropertyFloat", "BulkMod", 110);
+ d.Add("PropertyFloat", "SizeMod", 111);
+ d.Add("PropertyFloat", "FocusedProbability", 117);
+ d.Add("PropertyFloat", "GeneratorInitialDelay", 121);
+ d.Add("PropertyFloat", "AiAcquireHealth", 122);
+ d.Add("PropertyFloat", "AiAcquireStamina", 123);
+ d.Add("PropertyFloat", "AiAcquireMana", 124);
+ d.Add("PropertyFloat", "ResistHealthDrain", 125);
+ d.Add("PropertyFloat", "AiCounteractEnchantment", 127);
+ d.Add("PropertyFloat", "AiDispelEnchantment", 128);
+ d.Add("PropertyFloat", "EmotePriority", 131);
+ d.Add("PropertyFloat", "InventoryOffset", 135);
+ d.Add("PropertyFloat", "CriticalMultiplier", 136);
+ d.Add("PropertyFloat", "ManaStoneDestroyChance", 137);
+ d.Add("PropertyFloat", "SlayerDamageBonus", 138);
+ d.Add("PropertyFloat", "ManaConversionMod", 144);
+ d.Add("PropertyFloat", "CriticalFrequency", 147);
+ d.Add("PropertyFloat", "WeaponMissileDefense", 149);
+ d.Add("PropertyFloat", "WeaponMagicDefense", 150);
+ d.Add("PropertyFloat", "IgnoreShield", 151);
+ d.Add("PropertyFloat", "ElementalDamageMod", 152);
+ d.Add("PropertyFloat", "IgnoreArmor", 155);
+ d.Add("PropertyFloat", "ResistanceModifier", 157);
+ d.Add("PropertyFloat", "AbsorbMagicDamage", 159);
+ d.Add("PropertyFloat", "ArmorModVsNether", 165);
+ d.Add("PropertyFloat", "CooldownDuration", 167);
+ d.Add("PropertyString", "Name", 1);
+ d.Add("PropertyString", "Sex", 3);
+ d.Add("PropertyString", "HeritageGroup", 4);
+ d.Add("PropertyString", "Template", 5);
+ d.Add("PropertyString", "Inscription", 7);
+ d.Add("PropertyString", "ScribeName", 8);
+ d.Add("PropertyString", "Fellowship", 10);
+ d.Add("PropertyString", "LockCode", 12);
+ d.Add("PropertyString", "KeyCode", 13);
+ d.Add("PropertyString", "Use", 14);
+ d.Add("PropertyString", "ShortDesc", 15);
+ d.Add("PropertyString", "LongDesc", 16);
+ d.Add("PropertyString", "ActivationTalk", 17);
+ d.Add("PropertyString", "UseMessage", 18);
+ d.Add("PropertyString", "ItemHeritageGroupRestriction", 19);
+ d.Add("PropertyString", "PluralName", 20);
+ d.Add("PropertyString", "ActivationFailure", 22);
+ d.Add("PropertyString", "TownName", 24);
+ d.Add("PropertyString", "CraftsmanName", 25);
+ d.Add("PropertyString", "UsePkServerError", 26);
+ d.Add("PropertyString", "ScoreDefaultEntryFormat", 28);
+ d.Add("PropertyString", "ScoreFirstEntryFormat", 29);
+ d.Add("PropertyString", "ScoreLastEntryFormat", 30);
+ d.Add("PropertyString", "ScoreOnlyEntryFormat", 31);
+ d.Add("PropertyString", "ScoreNoEntry", 32);
+ d.Add("PropertyString", "Quest", 33);
+ d.Add("PropertyString", "GeneratorEvent", 34);
+ d.Add("PropertyString", "QuestRestriction", 37);
+ d.Add("PropertyDataId", "Setup", 1);
+ d.Add("PropertyDataId", "MotionTable", 2);
+ d.Add("PropertyDataId", "SoundTable", 3);
+ d.Add("PropertyDataId", "CombatTable", 4);
+ d.Add("PropertyDataId", "QualityFilter", 5);
+ d.Add("PropertyDataId", "PaletteBase", 6);
+ d.Add("PropertyDataId", "ClothingBase", 7);
+ d.Add("PropertyDataId", "Icon", 8);
+ d.Add("PropertyDataId", "EyesTexture", 9);
+ d.Add("PropertyDataId", "NoseTexture", 10);
+ d.Add("PropertyDataId", "MouthTexture", 11);
+ d.Add("PropertyDataId", "HairPalette", 15);
+ d.Add("PropertyDataId", "EyesPalette", 16);
+ d.Add("PropertyDataId", "SkinPalette", 17);
+ d.Add("PropertyDataId", "ActivationAnimation", 19);
+ d.Add("PropertyDataId", "InitMotion", 20);
+ d.Add("PropertyDataId", "PhysicsEffectTable", 22);
+ d.Add("PropertyDataId", "UseSound", 23);
+ d.Add("PropertyDataId", "UseTargetAnimation", 24);
+ d.Add("PropertyDataId", "UseTargetSuccessAnimation", 25);
+ d.Add("PropertyDataId", "UseTargetFailureAnimation", 26);
+ d.Add("PropertyDataId", "UseUserAnimation", 27);
+ d.Add("PropertyDataId", "Spell", 28);
+ d.Add("PropertyDataId", "SpellComponent", 29);
+ d.Add("PropertyDataId", "PhysicsScript", 30);
+ d.Add("PropertyDataId", "LinkedPortalOne", 31);
+ d.Add("PropertyDataId", "WieldedTreasureType", 32);
+ d.Add("PropertyDataId", "UnknownGuessedname", 33);
+ d.Add("PropertyDataId", "DeathTreasureType", 35);
+ d.Add("PropertyDataId", "MutateFilter", 36);
+ d.Add("PropertyDataId", "ItemSkillLimit", 37);
+ d.Add("PropertyDataId", "UseCreateItem", 38);
+ d.Add("PropertyDataId", "ItemSpecializedOnly", 41);
+ d.Add("PropertyDataId", "HouseId", 42);
+ d.Add("PropertyDataId", "RestrictionEffect", 44);
+ d.Add("PropertyDataId", "TsysMutationFilter", 46);
+ d.Add("PropertyDataId", "LinkedPortalTwo", 48);
+ d.Add("PropertyDataId", "IconOverlay", 50);
+ d.Add("PropertyDataId", "IconOverlaySecondary", 51);
+ d.Add("PropertyDataId", "IconUnderlay", 52);
+ d.Add("PropertyDataId", "ProcSpell", 55);
+ d.Add("PropertyInstanceId", "ActivationTarget", 16);
+ d.Add("PropertyInstanceId", "AllowedWielder", 38);
+ return d;
+ }
+ }
+
+ [Theory]
+ [MemberData(nameof(WeenieAttested))]
+ public void WeenieAttestedMemberHasExactWireValue(string family, string name, uint value)
+ {
+ var (type, _) = Resolve(family);
+ Assert.True(Enum.IsDefined(type, value), $"{family}.{name} ({value}) is not defined");
+ Assert.Equal(name, Enum.GetName(type, value));
+ }
+}