Forgot to update - I figured it out shortly after! I'll post this in case anyone else needs this info (I used the leaked EO source for the info)
Here is the struct:
Code:
typedef struct
{
unsigned int uID; //0 item type 的 ID // 精灵的lookface根据itemtype 定义
char szName[_MAX_NAMESIZE]; //1 物品名字
unsigned char ucRequiredProfession; //2 要求职业 附加属性类型
unsigned char ucRequiredWeaponSkill; //3 要求的武器技能
unsigned char ucRequiredLevel; //4 要求的等级 // 精灵等级 装备精灵的玩家的等级必须不能少于精灵的等级×2。
unsigned char ucRequiredSex; //5 要求的性别
unsigned short usRequiredForce; //6 要求力量
unsigned short usRequiredSpeed; //7 要求速度
unsigned short usRequiredHealth; //8 要求健康
unsigned short usRequiredSoul; //9 要求精神
unsigned char ucMonopoly; //10 独占物品标志
unsigned short usWeight; //11 物品重量
unsigned int uPrice; //12 价格
//int uLuck; //13 幸运值 // 升级到下一级需要的经验值 - not used in CO
unsigned int uUnknown;
unsigned short usMaxAttack; //14 最大攻击
unsigned short usMinAttack; //15 最小攻击
short usDefense; //16 防御
short usDexterity; //17 敏捷 // 最小魔攻击
short usDodge; //18 闪避 // add soul
short sLife; //19 生命
short sMana; //20 魔法力
unsigned short usAmount; //21 数量 // 精灵亲密度=忠诚 - dura
unsigned short usAmountLimit; //22 数量 // 精灵附加属性 // 显示时应当 /100 - maxdura
unsigned char ucStatus; //23 状态 - not sure
unsigned char ucGem1; //24 镶嵌宝石1
unsigned char ucGem2; //25 镶嵌宝石2
unsigned char ucMagic1; //26 附加魔法1
unsigned char ucMagic2; //27 幸运
unsigned char ucMagic3; //28 追加
unsigned short usMagicAttack; //29 魔攻 // 最大魔攻
unsigned short usMagicDefence; //30 魔防
unsigned short usRange; //31 攻击范围
unsigned short usAttackSpeed; //32 攻击速度
//int nHitarte; //33 命中 not used
//unsigned short usTarget; //34 使用对象 not used
char szDesc[128]; //35 描述
}ItemTypeInfo;
And as for reading it... its a bit complex, but you get the idea from here (it's a lookup table basically):
Code:
CItemData::CItemData()
{
m_dwRecordAmount = 0;
m_pIDIndex = NULL;
m_fp = NULL;
char szFilename[]="ini/itemtype.dat";
m_fp = fopen(szFilename, "rb");
MYASSERT(m_fp);
this->CreateIndexTable();
FILE* fp = fopen("ini/itemnamelist.ini", "r");
if(fp)
{
char szLine[1024] = "";
while(true)
{
if (1 != fscanf(fp,"%s\n", szLine))
break;
if(strlen(szLine) == 0)
continue;
std::string str = szLine;
m_setItemName.push_back(str);
}
fclose(fp);
}
this->CreateAdditionalInfo();
}
BOOL CItemData::CreateIndexTable()
{
// 创建索引表
// 取记录条数
fread(&m_dwRecordAmount, sizeof(DWORD), 1, m_fp);
// 为ID索引表分配内存
m_pIDIndex = new OBJID[m_dwRecordAmount];
MYASSERT(m_pIDIndex);
// 读取ID索引
fread(m_pIDIndex, sizeof(OBJID), m_dwRecordAmount, m_fp);
return true;
}
BOOL CItemData::GetItemTypeInfo(OBJID idType, ItemTypeInfo& infoItemType)
{
MAP_ITEMINFO::iterator itr = s_mapItemType.find(idType);
if (itr != s_mapItemType.end())
{
memcpy(&infoItemType, &itr->second, sizeof(ItemTypeInfo));
return true;
}
if(!m_pIDIndex)
return false;
// 初始化定位信息 -1 为没有找到
int nLocate = -1;
// 查找索引表, 当ItemType表超过300时考虑做多级索引
for(DWORD i = 0; i < m_dwRecordAmount; i++)
{
OBJID* pObjID = m_pIDIndex + i;
OBJID idItem = *pObjID;
if(*pObjID == idType)
{
nLocate = i;
break;
}
}
// 看看索引表中有没有
if(nLocate < 0)
return false;
// 定位文件指针
DWORD dwOffset = sizeof(DWORD) +
sizeof(OBJID) * m_dwRecordAmount +
sizeof(ItemTypeInfo) * nLocate;
fseek(m_fp, dwOffset, SEEK_SET);
// 读记录
fread(&infoItemType, sizeof(ItemTypeInfo), 1, m_fp);
// save type info
s_mapItemType.insert(MAP_ITEMINFO::value_type(idType, infoItemType));
return true;
}