昨天闲着无聊把wow2.33中的技能说明都给提取了出来,想在自己单机版的武器上添加绿字技能玩,下面是代码(我比较懒所以只提取的技能ID,名称和说明部分,好多地方的实现不是很好)
Spell.dbc结构:
Header(文件头20字节)
row2.....(占Record Size字节)
例:技能名称提取 先由Data中找出技能名称所在字段,在127列*4byte=508byte位置得到技能名称在Text区的偏移量,String Block Size+偏移量就能得到技能名称的位置
Spell.dbc结构:
Header(文件头20字节)
Records.................行数(4字节)
Fields....................列数(4字节)
Record Size...............每行所占字节(4字节)
String Block Size.....字符区所占字节(4字节)
Data(数据区 共Records * Record Size字节)-----存技能各种数据
row1.....(占Record Size字节)row2.....(占Record Size字节)
Text(字符区 共String Block Size字节)------存技能文字说明等字符信息
第一行总为/0,后面的遇到/0为一行例:技能名称提取 先由Data中找出技能名称所在字段,在127列*4byte=508byte位置得到技能名称在Text区的偏移量,String Block Size+偏移量就能得到技能名称的位置
------------------------------------------------------------------------------------------
using System;
using System.IO;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Xml.Serialization;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
namespace WowItemTool
{
[Serializable]
public class spellInfo
{
public int id;
public string name, type, memo;
}
class spell
{
private byte[] m_stringTable;
private byte[] rowData;
public List<spellInfo> GetSpellList()
{
int rows, cols, rlen, tlen;
List<spellInfo> list=new List<spellInfo>();
![]()
//打开文件
FileStream file = new FileStream("c:/dbc/spell.dbc",FileMode.Open,FileAccess.Read);
BinaryReader br= new BinaryReader(file);
//取文件头信息
if (br.ReadUInt32() != 0x43424457) // WDBC标志
return list;
rows = br.ReadInt32();//行数
cols = br.ReadInt32();//列数
rlen = br.ReadInt32();//行占字节
tlen = br.ReadInt32();//文本块字节
//读取文本块
br.BaseStream.Position = br.BaseStream.Length-tlen;
byte[] stringTable = br.ReadBytes(tlen);
m_stringTable = stringTable;
//读技能信息
br.BaseStream.Position = 20;
for (int i = 0; i < rows; i++)
{
spellInfo spell = new spellInfo();
rowData = br.ReadBytes(rlen);
spell.id = GetInt32(rowData, 0);//技能ID
spell.name = GetString(rowData, 127).Replace('', ' ').Trim();//技能名称
spell.type = GetString(rowData, 144).Replace('', ' ').Trim();//技能属性
spell.memo = GetString(rowData, 161).Replace('', ' ').Trim();//技能介绍
list.Add(spell);
}
![]()
file.Close();
SaveTxt("c:/MyFile.txt",list);
//BINserializer("c:/MyFile.txt", list);
//List<spellInfo> l = (List<spellInfo>)BINDeserialize("c:/MyFile.txt");
//XMLserializer("c:/record.xml", list, new Type[] { typeof(spellInfo) });
//sp1 = (List<spellInfo>)XMLDeserialize("c:/record.xml",list, new Type[] { typeof(spellInfo) });
return list;
}
//导出到纯文本
public void SaveTxt(string fn, List<spellInfo> list)
{
FileStream file = new FileStream(fn, FileMode.OpenOrCreate);
StreamWriter sw = new StreamWriter(file);
for (int i = 0; i < list.Count; i++)
sw.WriteLine(list[i].id + " " + list[i].name + " " + list[i].type + " " + list[i].memo);
sw.Close();
}
//序列化二进制文件
public void BINserializer(string fn, object o)
{
IFormatter formatter = new BinaryFormatter();
Stream stream = new FileStream(fn, FileMode.Create,FileAccess.Write, FileShare.None);
formatter.Serialize(stream, o);
stream.Close();
}
//反序列化二进制文件
private object BINDeserialize(string fn)
{
IFormatter formatter = new BinaryFormatter();
Stream stream = new FileStream(fn, FileMode.Open,FileAccess.Read, FileShare.Read);
object ro = formatter.Deserialize(stream);
stream.Close();
return ro;
}
//序列化XML文件
public void XMLserializer(string fn,object o,Type[] type)
{
XmlSerializer serializer = new XmlSerializer(o.GetType(), type);
TextWriter writer = new StreamWriter(fn);
serializer.Serialize(writer, o);
writer.Close();
}
//反序列化XML文件
private object XMLDeserialize(string fn, object o,Type[] type)
{
XmlSerializer Serializer = new XmlSerializer(o.GetType(), type);
TextReader read = new StreamReader(fn);
object ro=Serializer.Deserialize(read);
read.Close();
return ro;
}
public string GetString(byte[] data, uint field)
{
System.Text.UTF8Encoding converter = new System.Text.UTF8Encoding();
uint startOffset = GetUInt32(data, field);
byte[] s=new byte[1024];
int i = 0;
while ((s[i] = m_stringTable[startOffset++]) != 0)
{
i++;
}
return converter.GetString(s);
}
protected static unsafe uint GetUInt32(byte[] data, uint field)
{
uint startIndex = field * 4;
if (startIndex + 4 > data.Length)
return uint.MaxValue;
fixed (byte* pData = &data[startIndex])
{
return *(uint*)pData;
}
}
protected static unsafe int GetInt32(byte[] data, uint field)
{
uint startIndex = field * 4;
if (startIndex + 4 > data.Length)
return int.MaxValue;
fixed (byte* pData = &data[startIndex])
{
return *(int*)pData;
}
}
![]()
![]()
}
}
![]()