#pragma once #include #include #include namespace wowee { namespace pipeline { /** * Maps DBC field names to column indices for a single DBC file. * Column indices vary between WoW expansions. */ struct DBCFieldMap { std::unordered_map fields; /** Get column index by field name. Returns 0xFFFFFFFF if unknown. */ uint32_t field(const std::string& name) const { auto it = fields.find(name); return (it != fields.end()) ? it->second : 0xFFFFFFFF; } /** Convenience operator for shorter syntax: layout["Name"] */ uint32_t operator[](const std::string& name) const { return field(name); } }; /** * Maps DBC file names to their field layouts. * Loaded from JSON (e.g. Data/expansions/wotlk/dbc_layouts.json). */ class DBCLayout { public: /** Load from JSON file. Returns true if successful. */ bool loadFromJson(const std::string& path); /** Get the field map for a DBC file. Returns nullptr if unknown. */ const DBCFieldMap* getLayout(const std::string& dbcName) const; /** Number of DBC layouts loaded. */ size_t size() const { return layouts_.size(); } private: std::unordered_map layouts_; }; /** * Global active DBC layout (set by Application at startup). */ void setActiveDBCLayout(const DBCLayout* layout); const DBCLayout* getActiveDBCLayout(); /** Convenience: get field index for a DBC field. */ inline uint32_t dbcField(const std::string& dbcName, const std::string& fieldName) { const auto* l = getActiveDBCLayout(); if (!l) return 0xFFFFFFFF; const auto* fm = l->getLayout(dbcName); return fm ? fm->field(fieldName) : 0xFFFFFFFF; } // Forward declaration class DBCFile; /** * Resolved CharSections.dbc field indices. * * Stock WotLK 3.3.5a uses: Texture1=4, Texture2=5, Texture3=6, Flags=7, * VariationIndex=8, ColorIndex=9 (textures first). * Classic/TBC/Turtle and HD-texture WotLK use: VariationIndex=4, ColorIndex=5, * Texture1=6, Texture2=7, Texture3=8, Flags=9 (variation first). * * detectCharSectionsFields() auto-detects which layout the actual DBC uses * by sampling field-4 values: small integers (0-15) => variation-first, * large values (string offsets) => texture-first. */ struct CharSectionsFields { uint32_t raceId = 1; uint32_t sexId = 2; uint32_t baseSection = 3; uint32_t variationIndex = 4; uint32_t colorIndex = 5; uint32_t texture1 = 6; uint32_t texture2 = 7; uint32_t texture3 = 8; uint32_t flags = 9; }; /** * Detect the actual CharSections.dbc field layout by probing record data. * @param dbc Loaded CharSections.dbc file (must not be null). * @param csL JSON-derived field map (may be null — defaults used). * @return Resolved field indices for this particular DBC binary. */ CharSectionsFields detectCharSectionsFields(const DBCFile* dbc, const DBCFieldMap* csL); } // namespace pipeline } // namespace wowee