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);
}
}
}