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

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

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

    这里是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  =   - 1 const ;
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  =   - 1 const ;
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  =   - 1 const ;
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 

你可能感兴趣的:(M2过程:修改DBCField对象,更新WOW.Dev Wiki)