using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.IO; namespace EasyNPC { /* EODATA.cs * Unfinished EODATA port of EOSERV project by Julian Smythe * Contains Classes to read the pub files of Endless Online * Currently reads and stores: Item file, NPC file, Spell file * */ #region enums enum Type { Static, UnknownType1, Money, Heal, Teleport, Spell, EXPReward, StatReward, SkillReward, Key, Weapon, Shield, Armor, Hat, Boots, Gloves, Accessory, Belt, Necklace, Ring, Armlet, Bracer, Beer, EffectPotion, HairDye, CureCurse } enum SubType { None, Ranged, Arrows, Wings } enum Special { Normal, Rare, // ? UnknownSpecial2, Unique, // ? Lore, Cursed } enum Size { Size1x1, Size1x2, Size1x3, Size1x4, Size2x1, Size2x2, Size2x3, Size2x4, } enum NPCType { NPC, Passive, Aggressive, Unknown1, Unknown2, Unknown3, Shop, Inn, Unknown4, Bank, Barber, Guild, Priest, Law, Skills, Quest, NONE, } enum SpellType { Damage, Heal, Bard } enum TargetRestrict { Any, Friendly, Opponent } enum Target { Normal, Self, Unknown1, Group } #endregion class EIFreader { private byte[] rid = new byte[4]; private byte[] len = new byte[2]; private List<EIF_Data> data = new List<EIF_Data>(); public int maxCount; public EIFreader(string fileLocation) { FileStream sr; try { sr = new FileStream(fileLocation + "/dat001.eif", FileMode.Open, FileAccess.Read); } catch (Exception) { return; } sr.Seek(3, SeekOrigin.Begin); for (int i = 0; i < 4; i++) rid[i] = (byte) sr.ReadByte(); for (int i = 0; i < 2; i++) len[i] = (byte) sr.ReadByte(); int numobj = maxCount = PacketProcessor.number(len[0], len[1]); sr.Seek(1, SeekOrigin.Current); byte[] buf = new byte[58]; data.Add(new EIF_Data()); byte namesize; for (int i = 1; i <= numobj; i++) { string name = ""; EIF_Data newdata = new EIF_Data(); namesize = (byte) sr.ReadByte(); namesize = (byte) PacketProcessor.number(namesize); byte[] namedata = new byte[namesize]; sr.Read(namedata, 0, namesize); foreach (byte b in namedata) name += (char)b; sr.Read(buf, 0, 58); newdata.id = i; newdata.name = name; newdata.graphic = (short) PacketProcessor.number(buf[0], buf[1]); newdata.type = (Type)PacketProcessor.number(buf[2]); newdata.subtype = (SubType)PacketProcessor.number(buf[3]); if(newdata.id == 365 && newdata.name.Equals("Gun")) newdata.subtype = SubType.Ranged; newdata.special = (Special)PacketProcessor.number(buf[4]); newdata.hp = (short) PacketProcessor.number(buf[5], buf[6]); newdata.tp = (short) PacketProcessor.number(buf[7], buf[8]); newdata.mindam = (short)PacketProcessor.number(buf[9], buf[10]); newdata.mindam = (short)PacketProcessor.number(buf[11], buf[12]); newdata.accuracy = (short) PacketProcessor.number(buf[13], buf[14]); newdata.evade = (short)PacketProcessor.number(buf[15], buf[16]); newdata.armor = (short)PacketProcessor.number(buf[17], buf[18]); newdata.str = PacketProcessor.number(buf[20]); newdata.intl = PacketProcessor.number(buf[21]); newdata.wis = PacketProcessor.number(buf[22]); newdata.agi = PacketProcessor.number(buf[23]); newdata.con = PacketProcessor.number(buf[24]); newdata.cha = PacketProcessor.number(buf[25]); newdata.light = PacketProcessor.number(buf[26]); newdata.dark = PacketProcessor.number(buf[27]); newdata.earth = PacketProcessor.number(buf[28]); newdata.air = PacketProcessor.number(buf[29]); newdata.water = PacketProcessor.number(buf[30]); newdata.fire = PacketProcessor.number(buf[31]); newdata.scrollmap = PacketProcessor.number(buf[32], buf[33], buf[34]); newdata.scrollx = PacketProcessor.number(buf[35]); newdata.scrolly = PacketProcessor.number(buf[36]); newdata.levelreq = (short) PacketProcessor.number(buf[37], buf[38]); newdata.classreq = (short) PacketProcessor.number(buf[39], buf[40]); newdata.strreq = (short)PacketProcessor.number(buf[41], buf[42]); newdata.intreq = (short)PacketProcessor.number(buf[43], buf[44]); newdata.wisreq = (short)PacketProcessor.number(buf[45], buf[46]); newdata.agireq = (short)PacketProcessor.number(buf[47], buf[48]); newdata.conreq = (short)PacketProcessor.number(buf[49], buf[50]); newdata.chareq = (short)PacketProcessor.number(buf[51], buf[52]); newdata.weight = PacketProcessor.number(buf[55]); newdata.size = (Size)PacketProcessor.number(buf[57]); if (sr.Read(new byte[1], 0, 1) != 1) break; else sr.Seek(-1, SeekOrigin.Current); data.Add(newdata); } if (data[data.Count - 1].name.Equals("eof")) data.RemoveAt(data.Count - 1); sr.Close(); } public string getName(int index) { if (index >= 0 && index < data.Count) return data[index].name; else return "--"; } public EIF_Data getData(int index) { return data[index]; } } class EIF_Data { public int id = 0; public string name = ""; public short graphic = 0; public Type type = Type.Static; public SubType subtype = SubType.None; public Special special = Special.Normal; public short hp = 0; public short tp = 0; public short mindam = 0; public short maxdam = 0; public short accuracy = 0; public short evade = 0; public short armor = 0; public int str = 0; public int intl = 0; public int wis = 0; public int agi = 0; public int con = 0; public int cha = 0; public int light = 0; public int dark = 0; public int earth = 0; public int air = 0; public int water = 0; public int fire = 0; //union the next 5 public int scrollmap = 0; public int dollgraphic = 0; public int expreward = 0; public int haircolor = 0; public int effect = 0; //union the next 2 public int gender = 0; public int scrollx = 0; public int scrolly = 0; public short levelreq = 0; public short classreq = 0; public short strreq = 0; public short intreq = 0; public short wisreq = 0; public short agireq = 0; public short conreq = 0; public short chareq = 0; public int weight = 0; public Size size = Size.Size1x1; public EIF_Data() { } } class ENFReader { private List<ENFData> data = new List<ENFData>(); private byte[] rid = new byte[4]; private byte[] len = new byte[2]; public int maxCount; public ENFReader(string filepath) { FileStream sr; try { sr = new FileStream(filepath + "/dtn001.enf", FileMode.Open, FileAccess.Read); } catch (Exception) { return; } sr.Seek(3, SeekOrigin.Begin); for (int i = 0; i < 4; i++) rid[i] = (byte)sr.ReadByte(); for (int i = 0; i < 2; i++) len[i] = (byte)sr.ReadByte(); int numobj = maxCount = PacketProcessor.number(len[0], len[1]); sr.Seek(1, SeekOrigin.Current); byte namesize; byte[] buf = new byte[39]; data.Add(new ENFData()); for (int i = 1; i <= numobj; i++) { string name = ""; ENFData newdata = new ENFData(); namesize = (byte)sr.ReadByte(); namesize = (byte)PacketProcessor.number(namesize); byte[] namedata = new byte[namesize]; sr.Read(namedata, 0, namesize); foreach (byte b in namedata) name += (char)b; newdata.name = name; //figure out what all the other data means later, //just take care of name for now sr.Read(buf, 0, 39); newdata.graphic = PacketProcessor.number(buf[0], buf[1]); newdata.boss = (short)PacketProcessor.number(buf[3], buf[4]); newdata.child = (short)PacketProcessor.number(buf[5], buf[6]); newdata.type = (NPCType)PacketProcessor.number(buf[7], buf[8]); newdata.hp = PacketProcessor.number(buf[11], buf[12], buf[13]); newdata.mindam = (short)PacketProcessor.number(buf[16], buf[17]); newdata.maxdam = (short)PacketProcessor.number(buf[18], buf[19]); newdata.accuracy = (short)PacketProcessor.number(buf[20], buf[21]); newdata.evade = (short)PacketProcessor.number(buf[22], buf[23]); newdata.armor = (short)PacketProcessor.number(buf[24], buf[25]); newdata.exp = (short)PacketProcessor.number(buf[36], buf[37]); data.Add(newdata); if (sr.Read(new byte[1], 0, 1) != 1) break; else sr.Seek(-1, SeekOrigin.Current); } if (data[data.Count - 1].name.Equals("eof")) data.RemoveAt(data.Count - 1); sr.Close(); } public string getName(int index) { if (index >= 0 && index < data.Count) return data[index].name; else return "--"; } public NPCType getNpcType(int index) { if (index >= 0 && index < data.Count) return data[index].type; else return NPCType.NONE; } } class ENFData { public string name; public int graphic; public short boss; public short child; public NPCType type; public int hp; public short exp; public short mindam; public short maxdam; public short accuracy; public short evade; public short armor; } class ESFReader { private List<ESFData> data = new List<ESFData>(); private byte[] rid = new byte[4]; private byte[] len = new byte[2]; public int maxCount; public ESFReader(string filepath) { FileStream sr; try { sr = new FileStream(filepath + "/dsl001.esf", FileMode.Open, FileAccess.Read); } catch (Exception) { return; } sr.Seek(3, SeekOrigin.Begin); for (int i = 0; i < 4; i++) rid[i] = (byte)sr.ReadByte(); for (int i = 0; i < 2; i++) len[i] = (byte)sr.ReadByte(); int numobj = maxCount = PacketProcessor.number(len[0], len[1]); sr.Seek(1, SeekOrigin.Current); byte namesize, shoutsize; string name = "", shout = ""; byte[] buf = new byte[51]; data.Add(new ESFData()); for (int i = 1; i <= numobj; i++) { name = ""; shout = ""; namesize = (byte)sr.ReadByte(); shoutsize = (byte)sr.ReadByte(); ESFData newdata = new ESFData(); namesize = (byte)PacketProcessor.number(namesize); if (namesize > 0) { byte[] temp = new byte[namesize]; sr.Read(temp, 0, namesize); foreach (byte b in temp) name += (char)b; } shoutsize = (byte)PacketProcessor.number(shoutsize); if (shoutsize > 0) { byte[] temp = new byte[shoutsize]; sr.Read(temp, 0, shoutsize); foreach (byte b in temp) shout += (char)b; } sr.Read(buf, 0, 51); newdata.id = i; newdata.name = name; newdata.shout = shout; newdata.icon = (short)PacketProcessor.number(buf[0], buf[1]); newdata.graphic = (short)PacketProcessor.number(buf[2], buf[3]); newdata.tp = (short)PacketProcessor.number(buf[4], buf[5]); newdata.sp = (short)PacketProcessor.number(buf[6], buf[7]); newdata.castTime = (byte)PacketProcessor.number(buf[8]); newdata.type = (SpellType)PacketProcessor.number(buf[10]); newdata.targetRestrict = (TargetRestrict)PacketProcessor.number(buf[17]); newdata.target = (Target)PacketProcessor.number(buf[18]); newdata.mindam = (short)PacketProcessor.number(buf[23], buf[24]); newdata.maxdam = (short)PacketProcessor.number(buf[25], buf[26]); newdata.accuracy = (short)PacketProcessor.number(buf[27], buf[28]); newdata.hp = (short)PacketProcessor.number(buf[34], buf[35]); data.Add(newdata); if (sr.Read(new byte[1], 0, 1) != 1) break; if (sr.Read(new byte[1], 0, 1) != 1) break; else sr.Seek(-2, SeekOrigin.Current); } if (data[data.Count - 1].name.Equals("eof")) data.RemoveAt(data.Count - 1); sr.Close(); } public string getName(int index) { if (index >= 0 && index < data.Count) return data[index].name; else return "--"; } } class ESFData { public int id; public string name; public string shout; public short icon; public short graphic; public short tp; public short sp; public byte castTime; public SpellType type; public TargetRestrict targetRestrict; public Target target; public short mindam; public short maxdam; public short accuracy; public short hp; public ESFData() { } } class PacketProcessor { const int MAX1 = 253; const int MAX2 = 64009; const int MAX3 = 16194277; public static int number(byte b1) { byte b2 = 254, b3 = 254, b4 = 254; if (b1 == 0 || b1 == 254) b1 = 1; if (b2 == 0 || b2 == 254) b2 = 1; if (b3 == 0 || b3 == 254) b3 = 1; if (b4 == 0 || b4 == 254) b4 = 1; --b1; --b2; --b3; --b4; return (b4 * PacketProcessor.MAX3 + b3 * PacketProcessor.MAX2 + b2 * PacketProcessor.MAX1 + b1); } public static int number(byte b1, byte b2) { byte b3 = 254, b4 = 254; if (b1 == 0 || b1 == 254) b1 = 1; if (b2 == 0 || b2 == 254) b2 = 1; if (b3 == 0 || b3 == 254) b3 = 1; if (b4 == 0 || b4 == 254) b4 = 1; --b1; --b2; --b3; --b4; return (b4 * PacketProcessor.MAX3 + b3 * PacketProcessor.MAX2 + b2 * PacketProcessor.MAX1 + b1); } public static int number(byte b1, byte b2, byte b3) { byte b4 = 254; if (b1 == 0 || b1 == 254) b1 = 1; if (b2 == 0 || b2 == 254) b2 = 1; if (b3 == 0 || b3 == 254) b3 = 1; if (b4 == 0 || b4 == 254) b4 = 1; --b1; --b2; --b3; --b4; return (b4 * PacketProcessor.MAX3 + b3 * PacketProcessor.MAX2 + b2 * PacketProcessor.MAX1 + b1); } public static int number(byte b1, byte b2, byte b3, byte b4) { if (b1 == 0 || b1 == 254) b1 = 1; if (b2 == 0 || b2 == 254) b2 = 1; if (b3 == 0 || b3 == 254) b3 = 1; if (b4 == 0 || b4 == 254) b4 = 1; --b1; --b2; --b3; --b4; return (b4 * PacketProcessor.MAX3 + b3 * PacketProcessor.MAX2 + b2 * PacketProcessor.MAX1 + b1); } } }