Codejie's C++ Space

Using C++

M2过程:修改DBCField对象,更新WOW.Dev Wiki

    在分析M2文件时,其中GlobalModelFlags是指向CreateureModelData.dbc的,这样不可避免的要先分析这个表。使用wxDeMPQ的查看DBC功能,发现wiki已经有些过时了,随便就更新了,参见这里
    下图是wxDeMPQ分析DBC文件的图片,配合DBC的Field配置说明,查看DBC还是满方便的。


    这里是DBC的Field配置文件,XML格式的,好理解的,不解释了:
 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <DBCFile version="1.0">
 3     <File name="GameTables.dbc" version="1.0">
 4         <Note>GameTables</Note>
 5         <Fields>
 6             <Field position="0" type="string" size="0">FieldA</Field>
 7             <Field position="1" type="integer" size="4">FieldB</Field>
 8             <Field position="2" type="integer" size="4">FieldC</Field>
 9         </Fields>
10     </File>
11   <File name="CreatureModelData.dbc" version="1.0">
12     <Note></Note>
13     <Fields>
14       <Field position="0" type="integer" size="4">ID</Field>
15       <Field position="1" type="integer" size="4">UnknownA</Field>
16       <Field position="2" type="string">ModulePath</Field>
17       <Field position="3" type="integer" size="4">UnknownB</Field>
18       <Field position="4" type="integer">UnknownC</Field>
19       <Field position="5" type="float">AnimationSpeed</Field>
20       <Field position="6" type="integer">UnknownD</Field>
21       <Field position="7" type="integer">UnknownE</Field>
22       <Field position="8" type="float">UnknownF</Field>
23       <Field position="9" type="float">UnknownG</Field>
24       <Field position="10" type="float">Unknown?</Field>
25       <Field position="11" type="integer">UnknownH</Field>
26       <Field position="12" type="integer">UnknownI</Field>
27       <Field position="13" type="integer">Unknown?1</Field>
28       <Field position="14" type="integer">GroupID</Field>
29       <Field position="15" type="float">Collision</Field>
30       <Field position="16" type="float">UnknownK</Field>
31       <Field position="17" type="float">UnknownL</Field>
32       <Field position="18" type="float">UnknownM</Field>
33       <Field position="19" type="float">UnknownN</Field>
34       <Field position="20" type="float">UnknownO</Field>
35       <Field position="21" type="float">UnknownP</Field>
36       <Field position="22" type="float">UnknownQ</Field>
37       <Field position="23" type="float">UnknownR</Field>
38       <Field position="24" type="float">UnknownS</Field>
39       <Field position="25" type="float">UnknownT</Field>      
40     </Fields>
41   </File>  
42     <File name="b.dbc" version="1.0">
43         <Note>this is a sample.</Note>
44         <Fields>
45             <Field position="0" type="string" size="0">FieldA</Field>
46             <Field position="1" type="integer" size="4">FieldB</Field>
47             <Field position="2" type="refid" size="4" refdbc="ref.dbc" reffield="0">FieldC</Field>
48             <Field position="3" type="array of integer" size="4" number="10">FieldD</Field>
49         </Fields>
50     </File>
51 </DBCFile>

    下面是分析上面XML的代码,当前仅支持integer,string,float类型的Field,分析使用的是tinyxml,有兴趣的可以看看。
    MPQDBCFieldObject.h
 1 #ifndef __MPQDBCFIELDOBJECT_H__
 2 #define __MPQDBCFIELDOBJECT_H__
 3 
 4 #include <string>
 5 #include <map>
 6 
 7 #include "FileBuffer.h"
 8 
 9 namespace DBCField
10 {
11     class CField;
12 }
13 
14 class CMPQDBCFieldManager
15 {
16 public:
17     typedef std::map<int, DBCField::CField*> TFieldMap;
18     typedef std::map<std::string, TFieldMap> TDBCMap;
19     struct FieldAttr_t
20     {
21         std::string m_strTitle;
22         int m_iPos;
23         std::string m_strType;
24         int m_iSize;
25         std::string m_strRefDBC;
26         int m_iRefPos;
27         int m_iNumber;
28     };
29 public:
30     CMPQDBCFieldManager();
31     virtual ~CMPQDBCFieldManager();
32 
33     int Load(const std::string& xml, bool reload = false);
34     const TFieldMap* FindDBCFields(const std::string& dbc) const;
35 private:
36     int ParseXML(const std::string& xml);
37     DBCField::CField* MakeDBCField(const FieldAttr_t& attr) const;
38     void Destory();
39 private:
40     TDBCMap _mapDBC;
41 };
42                                
43 
44 namespace DBCField
45 {
46 
47 enum FieldType { FT_INTEGER, FT_STRING, FT_FLOAT };
48 
49 class CField
50 {
51 public:
52     CField(FieldType type, const std::string& title, int pos, int size)
53         : m_strTitle(title), m_iPos(pos), m_eType(type), m_iSize(size)
54     {
55     }
56     virtual ~CField() {}
57 
58     virtual int Data2String(std::string& str, CFileBuffer& fb, int offset, int strpos = -1const;
59 public:
60     FieldType m_eType;
61     std::string m_strTitle;
62     int m_iPos;
63     int m_iSize;
64 };
65 
66 class CIntegerField : public CField
67 {
68 public:
69     CIntegerField(const std::string& title, int pos, int size)
70         : CField(FT_INTEGER, title, pos, size)
71     {
72     }
73 };
74 
75 class CStringField : public CField
76 {
77 public:
78     CStringField(const std::string& title, int pos, int size)
79         : CField(FT_STRING, title, pos, size)
80     {
81     }
82     virtual int Data2String(std::string& str, CFileBuffer& fb, int offset, int strpos = -1const;
83 };
84 
85 class CFloatField : public CField
86 {
87 public:
88     CFloatField(const std::string& title, int pos, int size)
89         : CField(FT_FLOAT, title, pos, size)
90     {
91     }
92     virtual int Data2String(std::string& str, CFileBuffer& fb, int offset, int strpos = -1const;
93 };
94 
95 }
96 #endif

  MPQDBCFieldObject.cpp
  1 #include "tinyxml.h"
  2 
  3 #include "Toolkit.h"
  4 
  5 #include "MPQDBCFieldObject.h"
  6 
  7 CMPQDBCFieldManager::CMPQDBCFieldManager()
  8 {
  9 }
 10 
 11 CMPQDBCFieldManager::~CMPQDBCFieldManager()
 12 {
 13     Destory();
 14 }
 15 
 16 void CMPQDBCFieldManager::Destory()
 17 {
 18     TDBCMap::iterator it = _mapDBC.begin();
 19     while(it != _mapDBC.end())
 20     {
 21         TFieldMap::iterator i = it->second.begin();
 22         while(i != it->second.end())
 23         {
 24             delete i->second;
 25             it->second.erase(i++);
 26         }
 27         _mapDBC.erase(it ++);
 28     }
 29 }
 30 
 31 int CMPQDBCFieldManager::Load(const std::string &xml, bool reload)
 32 {
 33     if(reload)
 34     {
 35         Destory();
 36     }
 37     return ParseXML(xml);        
 38 }
 39 
 40 const CMPQDBCFieldManager::TFieldMap* CMPQDBCFieldManager::FindDBCFields(const std::string& dbc) const
 41 {
 42     TDBCMap::const_iterator it = _mapDBC.find(dbc);
 43     if(it == _mapDBC.end())
 44         return NULL;
 45     return &it->second;
 46 }
 47 
 48 int CMPQDBCFieldManager::ParseXML(const std::string &xml)
 49 {
 50     TiXmlDocument doc;
 51     if(!doc.LoadFile(xml.c_str()))
 52         return -1;
 53 
 54     std::string name;
 55 
 56     const TiXmlElement* root = doc.RootElement();
 57     if(root->ValueStr() != "DBCFile")
 58         return -1;
 59     const TiXmlElement* file = root->FirstChildElement();
 60     while(file != NULL)
 61     {
 62         //File Attribute
 63         name.clear();
 64         const TiXmlAttribute* attr = file->FirstAttribute();
 65         while(attr != NULL)
 66         {
 67             if(attr->NameTStr() == "name")
 68                 name = attr->ValueStr();
 69             attr = attr->Next();
 70         }
 71         if(!name.empty())
 72         {
 73             TDBCMap::iterator it = _mapDBC.insert(std::make_pair(name, TFieldMap())).first;
 74             if(it == _mapDBC.end())
 75                 return -1;
 76 
 77             const TiXmlElement* fields = file->FirstChildElement("Fields");
 78             if(fields != NULL)
 79             {
 80                 const TiXmlElement * field = fields->FirstChildElement("Field");
 81                 while(field != NULL)
 82                 {
 83                     FieldAttr_t data;
 84                     data.m_iPos = -1;
 85                     data.m_strType.clear();
 86                     data.m_strTitle = field->GetText();
 87                     data.m_iSize = 4;
 88                     attr = field->FirstAttribute();
 89                     while(attr != NULL)
 90                     {
 91                         if(attr->NameTStr() == "position")
 92                             data.m_iPos = attr->IntValue();
 93                         else if(attr->NameTStr() == "type")
 94                             data.m_strType = attr->ValueStr();
 95                         else if(attr->NameTStr() == "size")
 96                             data.m_iSize = attr->IntValue();
 97                         else if(attr->NameTStr() == "refdbc")
 98                             data.m_strRefDBC = attr->ValueStr();
 99                         else if(attr->NameTStr() == "reffield")
100                             data.m_iRefPos = attr->IntValue();
101                         else if(attr->NameTStr() == "number")
102                             data.m_iNumber = attr->IntValue();
103 
104                         attr = attr->Next();
105                     }
106                     DBCField::CField* dbcfield = MakeDBCField(data);
107                     if(dbcfield != NULL)
108                     {
109                         TFieldMap::iterator i = it->second.find(data.m_iPos);
110                         if(i == it->second.end())
111                         {
112                             it->second.insert(std::make_pair(dbcfield->m_iPos, dbcfield));
113                         }
114                         else
115                         {
116                             delete i->second;
117                             i->second = dbcfield;
118                         }
119                     }
120 
121                     field = field->NextSiblingElement();
122                 }
123             }
124         }
125         file = file->NextSiblingElement();
126     }
127 
128     return 0;
129 }
130 
131 DBCField::CField* CMPQDBCFieldManager::MakeDBCField(const CMPQDBCFieldManager::FieldAttr_t &attr) const
132 {
133     if(attr.m_iPos == -1 || attr.m_strType.empty())
134         return NULL;
135     if(attr.m_strType == "integer")
136         return new DBCField::CIntegerField(attr.m_strTitle, attr.m_iPos, attr.m_iSize);
137     else if(attr.m_strType == "string")
138         return new DBCField::CStringField(attr.m_strTitle, attr.m_iPos, attr.m_iSize);
139     else if(attr.m_strType == "float")
140         return new DBCField::CFloatField(attr.m_strTitle, attr.m_iPos, attr.m_iSize);
141     return NULL;
142 }
143 
144 //////
145 namespace DBCField
146 {
147 
148 int CField::Data2String(std::string& str, CFileBuffer &fb, int offset, int strpos) const
149 {
150     int data = 0;
151     fb.Seek(offset);
152     fb.Read(data);
153 
154     Toolkit::StringOf<int>(data, str);
155 
156     return fb.Good() ? 0 : -1;
157 }
158 
159 //
160 int CStringField::Data2String(std::string& str, CFileBuffer &fb, int offset, int strpos) const
161 {
162     int data = 0;
163     fb.Seek(offset);
164     fb.Read(data);
165     
166     fb.Seek(data + strpos);
167     fb.Read(str);
168 
169     return fb.Good() ? 0 : -1;
170 }
171 
172 //
173 int CFloatField::Data2String(std::string& str, CFileBuffer &fb, int offset, int strpos) const
174 {
175     float data = 0.0f;
176     fb.Seek(offset);
177     fb.Read(data);
178     
179     Toolkit::StringOf<float>(data, str);
180 
181     return fb.Good() ? 0 : -1;
182 }
183 
184 }
185 

posted on 2009-03-31 16:50 codejie 阅读(429) 评论(0)  编辑 收藏 引用 所属分类: C++MPQ - WOW


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理


公告

Using C++

导航

统计

留言簿(73)

随笔分类(513)

积分与排名

最新评论

阅读排行榜

评论排行榜