Skip to content

Fix two tables that did not read and correct key targets in eight more - #250

Merged
SnosMe merged 1 commit into
poe-tool-dev:mainfrom
juddisjudd:fix-misread-layouts-and-key-targets
Oct 14, 2026
Merged

SnosMe merged 1 commit into
poe-tool-dev:mainfrom
juddisjudd:fix-misread-layouts-and-key-targets

Conversation

@juddisjudd

Copy link
Copy Markdown
Contributor

Ten tables, checked against PoE 2 0.5.5.4.2 and PoE 1 3.29.3.3. Two of the changes correct targets I got wrong in #249.

Each change passed three checks: the bytes have the shape of the new type in every row, the values resolve to rows that make sense next to the row's other columns, and with the change every table still reads with no key out of range and no list data left unread.

The pointer columns were first flagged by comparing the schema with what the game client's own loader fixes up for each table. Everything below is from the table data itself.

Corrections to #249 (PoE 2)

AfflictionQuestFogBankValues points at EndgameMapAtlas, not NPCs.

  • The one row holds keys 873 to 892. In EndgameMapAtlas those are exactly AtlasLeagueDeliriumInnerNode1 to 20, the rows with the map_endgame_fog_depth… stats.
  • As NPCs the same range starts and ends in the middle of the Incursion NPCs. Both tables have enough rows, which is why the range check passed last time.

CharacterStartStates: SupportGems does not hold support gems.

  • All 748 values are attribute nodes in PassiveSkills (strengthN, dexterityN, intelligenceN, attributesN), and 732 of them are also in the same row's PassiveSkillsKeys. They follow the class: rows for the StrFourb character hold strength nodes, rows for IntFour intelligence nodes.
  • The first 636 rows of PassiveSkills are nearly all attribute nodes and SupportGems has 637 rows, so every index fits both tables.
  • The list after it has the same length in all 109 rows and holds generic_attribute_strength, generic_attribute_dexterity or generic_attribute_intelligence_: the attribute chosen for each node.
  • The two untargeted lists before them hold passives too: stun_threshold11 for WarriorActTwo, accuracy18 and accuracy8 for RangerActTwo. As BaseItemTypes the same values give RandomFossilOutcome124, RunedArtifact3 and Talisman9End.

Tables that did not read

MapDeviceLayouts (PoE 1; PoE 2 has no such file): i32, string, bool, i32, i32 becomes bool, i32, [i32], the same 21 bytes.

  • The first byte is 0 or 1 in every row and the number after it is 0 to 4.
  • Read with 4-byte elements, the new list ends exactly where the next list starts in 10 of the 11 rows. In the eleventh, NoSlotRecipe, the next list points back at an earlier row's copy.
  • With the old layout the string reads offsets that were never written.

ExpeditionDeals (PoE 2): string, i32, i32 becomes one key to SoundEffects. Every row reads UseOrb.

ExpeditionDeals (PoE 1): NPCShop: NPCShop becomes SoundEffect: SoundEffects.

  • 81 deals hold one value and set_quality holds another.
  • As SoundEffects those are UseOrb and Sharpening. As NPCShop they are ExpeditionGambler and ExpeditionDealer.

Types and targets

QuestAchievements (both games): QuestStates: [i32] becomes QuestFlags: [QuestFlags].

  • The elements are 16-byte keys. AllAscendancyPoints lists AscendancyPoints1 to 4; LabyrinthAllComplete lists LabyrinthComplete1 to 3 and LabyrinthCompleteMaps.
  • Read as [i32], three quarters of the list data is never read.

NPCTalk (PoE 2): Music1 and Music2 become WorldArea1 and WorldArea2.

  • HoodedMentor reads G1_town, LilyRothsCrewFirstMate reads G4_town, and the three FarrowAct1Dungeon rows read ExpeditionSubArea_Kalguur_Act1, Act2 and Act3.
  • As Music the same values are PoE 1 tracks: Act7_FellshrineRuins, LegionIdleState, A3_JungleDepths.
  • PoE 1 is left alone. Its five values read plausibly either way.

MapDeviceRecipes (PoE 2): WorldArea is a list. All 14 rows hold a count of 1 and an offset, not a key; the Reliquary… recipes list MapVoidReliquary.

WeaponImpactSoundData (PoE 2): the 16 bytes after Id are a key to WeaponSoundTypes. Cleaving reads Sword2H, Slashing reads Sword1H, Bludgeoning reads Mace2HWood, Puncturing reads Stab1HMetal, AnimalClaw reads Beast, BowArrow reads Arrow.

RecombinableClasses (PoE 2): the 16 bytes after Id are a key to BaseItemTypes. Weapons read ExpeditionVendorCurrencyFaction1, amulets and rings ExpeditionVendorCurrencyFaction2.

Names

The new names (AttributePassives, AttributeChoices, SoundEffect, WorldArea1, WorldArea2, WorldAreas, QuestFlags, Currency, WeaponSoundType) are my reading of what the values are. I am happy to change any of them.

PoE 1 MapDeviceLayouts and PoE 2 ExpeditionDeals read offsets that were never
written. MapDeviceLayouts has a bool, an i32 and a list of i32 where the schema
had i32, string, bool, i32, i32. ExpeditionDeals has one key to SoundEffects
where the schema had a string and two i32. PoE 1 calls the same key NPCShop,
but it reads UseOrb on 81 deals and Sharpening on set_quality.

Two targets from poe-tool-dev#249 were wrong. AfflictionQuestFogBankValues points at
EndgameMapAtlas: its keys are the 20 AtlasLeagueDeliriumInnerNode rows.
CharacterStartStates.SupportGems holds attribute passives that are also in the
row's PassiveSkillsKeys, and the list after it names the attribute chosen for
each. The two untargeted lists before them hold passives as well.

QuestAchievements.QuestStates is a list of QuestFlags keys in both games. In
PoE 2, NPCTalk.Music1 and Music2 are WorldAreas, MapDeviceRecipes.WorldArea is
a list, and the first unnamed columns of WeaponImpactSoundData and
RecombinableClasses are keys to WeaponSoundTypes and BaseItemTypes.

Checked against PoE 2 0.5.5.4.2 and PoE 1 3.29.3.3.
@SnosMe
SnosMe merged commit 8762468 into poe-tool-dev:main Oct 14, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants