#include <iostream>
#include <fstream>
#include <vector>
using namespace std;
struct ObjectId{
union{
int Integer;
char Bytes[4u];
};
};
const char tf_Invis_NonSolid(0);
const char tf_Vis_NonSolid(1);
const char tf_Vis_Solid(2);
enum ItemType{it_Any='Y',it_Permanent='i',it_Charged,it_PowerUp,it_Artifact,it_Purchasable,it_Campaign,it_Miscellaneous,it_None='\0'};
struct DroppedItem{
ObjectId ItemId;
int ChanceToDrop;
bool IsRandom()const{
return ItemId.Bytes[0u]=='Y'&&ItemId.Bytes[2u]=='I';
}
ItemType GetRandomItemType()const{
switch(ItemId.Bytes[1u]){
case 'Y':return it_Any;
case 'i':return it_Permanent;
case 'j':return it_Charged;
case 'k':return it_PowerUp;
case 'l':return it_Artifact;
case 'm':return it_Purchasable;
case 'n':return it_Campaign;
case 'o':return it_Miscellaneous;
default:return it_None;
}
}
int GetRandomItemLevel()const{
return int(ItemId.Bytes[3u])-48; // return of -1 means any level.
}
};
typedef vector<DroppedItem> ItemSet;
struct Tree{
ObjectId Id;
int Variation;
float X;
float Y;
float Z;
float Angle;
float ScaleX;
float ScaleY;
float ScaleZ;
char Flags;
char Life;
int ItemTablePointer;
vector<ItemSet> DroppedSets;
int WorldEditorId;
};
struct SpecialDoodad{
ObjectId Id;
int Z;
int X;
int Y;
};
struct DoodadFile{
ObjectId FileId;
int Version;
int Subversion;
vector<Tree> Trees;
int SpecialDoodadFormat;
vector<SpecialDoodad> SpecialDoodads;
};
DoodadFile ParseTrees(ifstream& FileStream);
DoodadFile ParseTreesWrapper(const string& FileName){
ifstream File(FileName.c_str(),ifstream::in|istream::binary);
if(File)return ParseTrees(File);
return DoodadFile();
}
int main(int NumFiles,char** FileNames){
if(NumFiles>1){
for(int FileIndex=1;FileIndex<NumFiles;FileIndex++){
cout<<"Trees: "<<ParseTreesWrapper(string(FileNames[FileIndex])).Trees.size()<<endl;
}
}
char C;
cin>>C;
return 0;
}
DoodadFile ParseTrees(ifstream& FileStream){
DoodadFile Ret;
FileStream.read((char*)&Ret.FileId.Integer,4u);
FileStream.read((char*)&Ret.Version,4u);
FileStream.read((char*)&Ret.Subversion,4u);
unsigned int NumberOfTrees=0u;
FileStream.read((char*)&NumberOfTrees,4u);
Ret.Trees.resize(NumberOfTrees);
for(Tree& Iter:Ret.Trees){
FileStream.read((char*)&Iter.Id.Integer,4u);
FileStream.read((char*)&Iter.Variation,4u);
// Position
FileStream.read((char*)&Iter.X,4u);
FileStream.read((char*)&Iter.Y,4u);
FileStream.read((char*)&Iter.Z,4u);
// Rotation
FileStream.read((char*)&Iter.Angle,4u);
// Scale
FileStream.read((char*)&Iter.ScaleX,4u);
FileStream.read((char*)&Iter.ScaleY,4u);
FileStream.read((char*)&Iter.ScaleZ,4u);
// Rest
FileStream.read(&Iter.Flags,1u);
FileStream.read(&Iter.Life,1u);
// Begin Item Set Parsing.
FileStream.read((char*)&Iter.ItemTablePointer,4u);
if(Iter.ItemTablePointer==-1){
unsigned int ItemSets=0u;
FileStream.read((char*)&ItemSets,4u);
Iter.DroppedSets.resize(ItemSets);
for(ItemSet& Set:Iter.DroppedSets){
unsigned int ItemsInSet=0u;
FileStream.read((char*)&ItemsInSet,4u);
Set.resize(ItemsInSet);
for(DroppedItem& Item:Set){
FileStream.read((char*)&Item.ItemId.Integer,4u);
FileStream.read((char*)&Item.ChanceToDrop,4u);
}
}
}
FileStream.read((char*)&Iter.WorldEditorId,4u);
}
FileStream.read((char*)&Ret.SpecialDoodadFormat,4u);
unsigned int SpecialDoods=0u;
FileStream.read((char*)&SpecialDoods,4u);
Ret.SpecialDoodads.resize(SpecialDoods);
for(SpecialDoodad& Doodad:Ret.SpecialDoodads){
FileStream.read((char*)&Doodad.Id.Integer,4u);
FileStream.read((char*)&Doodad.Z,4u);
FileStream.read((char*)&Doodad.X,4u);
FileStream.read((char*)&Doodad.Y,4u);
}
return Ret;
}