Textdata NN.dat

From Raynegard Wiki
Revision as of 01:35, 3 July 2026 by ::1 (talk) (Record types)
Jump to navigationJump to search

NN.dat (part of BIN textdata) is the numbered family of item/NPC/monster object-definition files (5.dat, 8.dat, 16.dat, … 92.dat). Despite the .dat extension every file is plain CP949 text.

Record format

Each file is line-based:

<record count>
<Korean name>            ┐
<English name>           ├ one record = 3 lines
<stat line: space-separated ints>  ┘
… repeated <count> times

Example (8.dat, record 1, a ring): 레인가 루지아 / Reynega_rugia / 8 1 1 1 22 492 100000 5000 0 0 0 0 0 0.

Loading pipeline

  • Struct_Setup_DatFiles @ 00483ff0 — loops all 60 slots, each calling TextArchive_Load_Dat_From_Array @ 00484080, which reads the count then the 3 lines per record.
  • TextFile_Dat_FileNum_to_value @ 00485760 — the authoritative NN.dat → slot-index switch (see BIN textdata for context).
  • DatFiles_FileNum_value_to_DatType @ 00485650 — slot value (0–59) → one of 14 record types (Dat_Type 0–0xD).
  • Vtable_DatFiles_DecodeFuncs[Dat_Type] @ 00485618 — a 14-entry table of per-type decoders. Each decoder sscanfs an exact number of stat-line fields, operator_news the record, and copies the parsed columns into it. Decoders are recursive (decode one record, tail-call the next).
  • TextDatFiles_GetSlotEntry(g_TextDatFiles, datEnum, idx) @ 00485ac0 — runtime fetch of record idx from a loaded slot.

Record types

Type Decoder Category .dat files Stat cols Carries
0 0048422b Weapons (katana/sword/axe/spear/bow/bowgun) 16–22, 62, 63 44 header + 6 stats + weapon block
1 0048453f Armor 23–31, 61 16 header + 6 stats + sprite/variant
2 0048468c Rings 8, 32 14 header + 6 stats
3 004847b7 Emblems 9, 33 8 header only (no stats)
4 00484882 Medicine / food 10, 11, 34 10–11 header + recovery + effect name
5 0048496d Money 15 8 header (no price)
6 00484a18 Scrolls 38–43 33 header + skill/effect params
7 00484bd9 Books 44–47 8 header only
8 00484c80 Misc items (ore / monster-item / letter) 35, 36, 37, 48, 49 8 header only
9 00484d33 Monsters 64–69, 73, 78, 79 32 (31 parsed) monster block
0xA 00484f8b Monster (special) 70 36 monster block (extended)
0xB 00485235 NPCs (field/party) 5, 74, 75 8 header + refs (no shop)
0xC 00485305 NPC shopkeepers (incl. Au) 77 22 (21 parsed) header + shop-type + category flags
0xD 004854f8 Monsters 89–92 ~3 sparse / mostly empty

Item vs entity split: only weapon/armor/ring carry the 6-stat block. Emblem, money, book, and misc items are header-only (8 cols) — a name + price, nothing more. Consumables add a recovery value + an effect-name string; scrolls add skill params. Monsters/NPCs use the entity layout instead of the item layout.

Common header (every record)

Built by the root constructor DatRecord_InitHeader @ 00483e80:

Offset Type Field
0x00 char[0x10] Korean name (CP949)
0x11 char[0x10] English name (_ → space)
0x24 int col1 = dat file number
0x28 int col2 = record index (1-based)

Column → offset mapping

The constructors copy parsed columns sequentially into 4-byte fields starting at 0x24:

coln → record offset 0x24 + 4·(n − 1) (col1→0x24, col2→0x28, col3→0x2c, …)

Verified by the weapon record: 44 cols, last field at 0x24 + 4·43 = 0xd0. A few fields are single bytes rather than ints.

Item families (weapon / armor / ring / emblem / consumable / scroll / book / misc)

Share the item base (ItemRecord_InitBase @ 004862c0…_InitBase2 @ 00486a30), which fills 0x2c–0x40, then a per-type extension:

  • Ring (RingRecord_Init @ 00486930): +0x44–0x58 → 14 fields total (0x240x58).
  • Armor (ArmorRecord_Init @ 004861b0): +0x44–0x60 → 16 fields.
  • Weapon (WeaponRecord_Init @ 00486b10): +0x44–0xd0 → 44 fields; a byte at 0x68 (col 18), plus a run of ~15 id-like values (col 26+) that look like sprite/effect/skill references.

Entities (NPC / monster)

Use the root header (0x24/0x28) then category fields from 0x2c:

  • Monster (MonsterRecord_Init @ 00485c10): 0x2c (byte) then ints 0x30–0x9c — 29 fields (31 parsed; the 32nd column on the line isn't read). Example 64.dat "Weldok": 64 1 36 1 0 0 620 62 79 354 … 160 120 100 350 50 85 150 233 61 …. HP/stats not yet labelled (consumed server-side).
  • NPC (NpcRecord_Init @ 00485f90, via NpcRecord_InitBase @ 004860d0): ints 0x2c/0x30, a byte 0x34, ints 0x38–0x40, then a 14-byte block 0x44–0x51. Example 77.dat "Noick": 77 1 121 85 0 0 75 57 0 ….

Common header columns (cols 1–8, item records)

Col Offset Meaning Confidence
1 0x24 dat file number confirmed
2 0x28 record index (1-based) confirmed
3 0x2c sub-type / grade (small: 0–3) tentative
4 0x30 sub-type / grade (small) tentative
5 0x34 item level / sort key (e.g. 22, 47, 52) tentative
6 0x38 icon bitmap index confirmed (leader-emblem icon)
7 0x3c buy price confirmed (shop gold check)
8 0x40 sell price inferred (buy/sell pair)

Header-only items (emblem/money/book/misc, 8 cols) end here. Money (15.dat) has col7=col8=0 — it is currency, no price. Equippables continue with the 6-stat block below.

The 6 equip stat columns (confirmed)

Every equippable item record carries six stats at a fixed offset block 0x44–0x58 (cols 9–14), confirmed from the stat-display builder FUN_004bacb0 (the item-detail panel):

Col Offset Stat
col9 0x44 OFC — offense / attack
col10 0x48 DEF — defense
col11 0x4c AGL — agility
col12 0x50 LUCK
col13 0x54 LIFE
col14 0x58 FOOD

The on-screen order differs from the record order — the header (misccaption_u.txt line 1) reads LIFE FOOD OFC DEF AGL LUCK, and FUN_004bacb0 re-orders fields to match. It prints two rows: the item's stat values, and a SPEC row (misccaption_u.txt line 2) with the %+d equip delta.

Cross-checks: rings (8.dat) only ever set cols 9–12 (OFC/DEF/AGL/LUCK), never LIFE/FOOD; armor 23.dat col10 = DEF (main stat), col11 = AGL; weapon 16.dat katana col9 = 110 (OFFENSE), col11 = 65 (AGL). These offsets are identical across item types — weapons carry the same 6 at 0x44–0x58, plus their weapon-specific columns beyond.

Weapon block (cols 15–44, 0x5c0xd0)

Example 16.dat katana: … 9 120 0 1 2 148 0 255 0 0 0 | 463 436 489 490 491 492 589 590 539 540 541 542 601 602 | 2 1 38 1 0.

  • cols 15–25 — weapon params (attack range/speed/hit-rate class; 0x68/col18 is a byte). Consumed by the attack/combat path (server-side for damage).
  • cols 26–39 — a run of 14 sprite/animation sequence ids (463…602, in the sprite-archive range) — the weapon's swing/effect frames, loaded by the animation system on equip.
  • cols 40–44 — display/misc; col42 (0xc8) = catalog icon (read by Stuct_Setup_cpt_panel_catalog).

Consumables / scrolls

  • Consumable (type 4, 10–11 cols): header + col9 = recovery amount (e.g. food 600) + a trailing effect/skill-name string.
  • Scroll (type 6, 33 cols): header + col9…col15 = skill/effect params (skill id, power, level req), rest padding.

Monster block (0x2c–0x9c, ~30 fields)

MonsterRecord_Init writes cols 3+ as HP / base stats / AI / drop data. These are read by the server combat/AI — the client only uses the monster record for its sprite/name — so the columns aren't labelled here.

Confirmed column labels (field-consumer trace)

Record Col / offset Meaning Evidence
Item (all types) col7 = 0x3c buy price State_NpcShopBuy_Tick @ 00467fd0: buy allowed only if record->0x3c <= player.money, then sends 0x35. Ring col7=100000, weapon 9000, matches.
Item col8 = 0x40 sell price (inferred) Not consumer-confirmed, but the buy/sell pair — ring col8=5000 vs buy 100000; weapon col8=900 vs buy 9000.
NPC/shop (type 0xB/0xC) col7 = 0x3c shop-type code State_NpcShopBuy_Tick case 0 switches on npcRecord->0x3c, accepts 0x44,0x47,0x4a,0x4d,0x50,0x53 = letters D G J M P S (shop kinds).
NPC/shop cols 9–22 = 0x440x51 (14 bytes) per-category "sells this" flags same function loops npcRecord[i + 0x44], i = 0..13; each nonzero byte adds item-category i to the shop's list (14 categories: Katana…MonsterItem).
Item / emblem col6 = 0x38 class/icon bitmap index cpt_panel_status_widget_Draw: for the party-leader emblem (dat 9), record->0x38 is passed to File_Read_Bitmap_Archive as the icon image id.

Server relevance: col7 (buy price) is the value the shop's gold check uses; an equipped item's col9–14 bonuses (OFC/DEF/AGL/LUCK/LIFE/FOOD) are applied to the wearer's totals. The player's total stats (base + all equipped bonuses) are computed server-side and pushed via packets 0xC001/0xC002 — the client never re-derives totals from records.

See also