HK QuestData Struktur

01/07/2016 16:34 EpicFight#1
Ich hatte für Daniel angefangen die QuestData zu analysieren und jetzt kb mehr da drauf. Den Rest könnt ihr selber machen ;)

Viel Spaß damit.

[Only registered and activated users can see links. Click Here To Register...]
[Only registered and activated users can see links. Click Here To Register...]


PHP Code:
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;

namespace 
iQuest
{
    public 
sealed class QuestFile
    
{
        private 
FileStream _File;
        private 
BinaryReader Reader;
        public 
short QuestCount;
        private 
byte[] QuestHeader = new byte[2];
        public static List<
QuestQuests = new List<Quest>();
        private 
byte RewardMax 12;

        public 
QuestFile(string path)
        {
            if (!
File.Exists(path))
            {
                throw new 
Exception("File does not exists");
            }
            
_File File.Open(pathFileMode.Open);
            
Reader = new BinaryReader(_File);
            
QuestHeader Reader.ReadBytes(2);
            
short questCount Reader.ReadInt16();
            for (
short i 0questCount= (short)(1))
            {
                
LoadQuest();
            }
            
_File.Dispose();
        }

        public 
Quest get_Item(ushort ushort_0)
        {
            foreach (
Quest quest in Quests)
            {
                if (
quest.ID == ushort_0)
                {
                    return 
quest;
                }
            }
            return 
null;
        }

        private 
void LoadQuest()
        {
            
Quest quest = new Quest();
            
ParseDefault(quest);
            
ParseMobs(quest);
            
ParseItems(quest);
            
ParseRewards(quest);
            
quest.StartScript ReadNulledString();
            
quest.ActionScript ReadNulledString();
            
quest.FinishScript ReadNulledString();
            
Quests.Add(quest);
        }

        
void ParseDefault(Quest quest)
        {
            
Reader.ReadUInt32();
            
quest.ID Reader.ReadUInt16();
            if (
quest.ID == 15)
            {
                
quest.ID quest.ID;
            }
            
quest.Title Reader.ReadUInt16();
            
quest.Description Reader.ReadUInt16();
            
quest.UnkBytes.Add(1Reader.ReadBytes(1));
            
quest.QuestGrade Reader.ReadByte();
            
quest.MultiQuest Reader.ReadByte();
            
quest.DailyQuest Reader.ReadByte();
            
quest.UnkBytes.Add(2Reader.ReadBytes(2));
            
quest.EnableQuest Reader.ReadByte();
            
quest.InstAcc Reader.ReadByte();
            
quest.NeedLevel Reader.ReadByte();
            
quest.MinLevel Reader.ReadByte();
            
quest.MaxLevel Reader.ReadByte();
            
quest.NeedNPC Reader.ReadByte();
            
quest.StartingNPC Reader.ReadUInt16();
            
quest.NeedItem Reader.ReadByte();
            
quest.UnkBytes.Add(3Reader.ReadBytes(1));
            
quest.ItemID Reader.ReadUInt16();
            
quest.ItemVanish Reader.ReadByte();
            
quest.UnkBytes.Add(4Reader.ReadBytes(19));
            
quest.NeedPred Reader.ReadByte();
            
quest.UnkBytes.Add(5Reader.ReadBytes(1));
            
quest.Predesessor Reader.ReadUInt16();
            
quest.UnkBytes.Add(6Reader.ReadBytes(2));
            
quest.NeedClass Reader.ReadByte();
            
quest.ClassType Reader.ReadByte();
            
quest.UnkBytes.Add(7Reader.ReadBytes(24));
            
quest.InstHand Reader.ReadByte();
            
quest.UnkBytes.Add(8Reader.ReadBytes(3));
        }

        private 
void RestoreDefault(BinaryWriter writerQuest quest)
        {
            
writer.Write(quest.DataLen());
            
writer.Write(quest.ID);
            
writer.Write(quest.Title);
            
writer.Write(quest.Description);
            
writer.Write(quest.UnkBytes[1]);
            
writer.Write(quest.QuestGrade);
            
writer.Write(quest.MultiQuest);
            
writer.Write(quest.DailyQuest);
            
writer.Write(quest.UnkBytes[2]);
            
writer.Write(quest.EnableQuest);
            
writer.Write(quest.InstAcc);
            
writer.Write(quest.NeedLevel);
            
writer.Write(quest.MinLevel);
            
writer.Write(quest.MaxLevel);
            
writer.Write(quest.NeedNPC);
            
writer.Write(quest.StartingNPC);
            
writer.Write(quest.NeedItem);
            
writer.Write(quest.UnkBytes[3]);
            
writer.Write(quest.ItemID);
            
writer.Write(quest.ItemVanish);
            
writer.Write(quest.UnkBytes[4]);
            
writer.Write(quest.NeedPred);
            
writer.Write(quest.UnkBytes[5]);
            
writer.Write(quest.Predesessor);
            
writer.Write(quest.UnkBytes[6]);
            
writer.Write(quest.NeedClass);
            
writer.Write(quest.ClassType);
            
writer.Write(quest.UnkBytes[7]);
            
writer.Write(quest.InstHand);
            
writer.Write(quest.UnkBytes[8]);
        }

        private 
void ParseRewards(Quest quest)
        {
            for (
byte i 0RewardMax= (byte)(1))
            {
                
QuestReward item = new QuestReward
                
{
                    
isGiven Reader.ReadByte(),
                    
Type = (QuestReward.RewardType)Reader.ReadByte(),
                    
unkShort Reader.ReadUInt16() 
                };
                if (
item.Type == QuestReward.RewardType.Item)
                {
                    
item.Value Reader.ReadUInt16();
                    
item.ItemCount Reader.ReadUInt16();
                    
item.unkDword Reader.ReadUInt32();
                }
                else
                {
                    
item.Amount Reader.ReadUInt64();
                }
                
quest.Rewards.Add(item);
            }
            
Stream baseStream Reader.BaseStream;
            
baseStream.Position += 6L;
            
quest.RewardData Reader.ReadBytes(14);
        }

        public 
void SaveFile(string path)
        {
            
FileStream stream File.Create(path);
            
BinaryWriter writor = new BinaryWriter(stream);
            
writor.Write(QuestHeader);
            
writor.Write((short)Quests.Count);
            for (
int i 0Quests.Count; ++i)
            {
                
long position writor.BaseStream.Position;
                
RestoreDefault(writorQuests[i]);

                foreach (
Mob mob in Quests[i].Mobs)
                {
                    
writor.Write(Convert.ToByte(mob.isActive));
                    
writor.Write(Convert.ToByte(mob.isMob));
                    
writor.Write(mob.ID);
                    
writor.Write(Convert.ToByte(mob.HasToBeKilled));
                    
writor.Write(mob.Amount);
                    
writor.Write(Convert.ToByte(mob.UnkDataMob));
                    
writor.Write(Convert.ToByte(mob.UnkDataMob2));
                }
                foreach (
Item item in Quests[i].Items)
                {
                    
writor.Write(item.isActive);
                    
writor.Write(item.Type);
                    
writor.Write(item.ID);
                    
writor.Write(item.Amount);
                }
                
writor.Write(Quests[i].DropCount);
                foreach (
ItemDrop drop in Quests[i].ItemDrop)
                {
                    
writor.Write(drop.isActive);
                    
writor.Write(drop.MobID);
                    
writor.Write(drop.Amount);
                    
writor.Write(drop.ItemID);
                    
writor.Write(drop.Rate);
                    
writor.Write(drop.UnkByte1);
                    
writor.Write(drop.UnkByte2);
                }
                foreach (
ItemDropPadding padding in Quests[i].ItemPadding)
                {
                    
writor.Write(padding.Padding);
                }
                
long num2 writor.BaseStream.Position;
                foreach (
QuestReward reward in Quests[i].Rewards)
                {
                    
writor.Write(reward.isGiven);
                    switch (
reward.Type)
                    {
                        case 
QuestReward.RewardType.Exp:
                            
writor.Write((byte)0);
                            break;

                        case 
QuestReward.RewardType.Money:
                            
writor.Write((byte)1);
                            break;

                        case 
QuestReward.RewardType.Item:
                            
writor.Write((byte)2);
                            break;

                        case 
QuestReward.RewardType.Fame:
                            
writor.Write((byte)4);
                            break;
                    }
                    
writor.Write(reward.unkShort);
                    if (
reward.Type == QuestReward.RewardType.Item)
                    {
                        
writor.Write(reward.Value);
                        
writor.Write(reward.ItemCount);
                        
writor.Write(reward.unkDword);
                    }
                    else
                    {
                        
writor.Write(reward.Amount);
                    }
                }
                
long num1 writor.BaseStream.Position num2;
                
writor.Write((ushort)(Quests[i].StartScript.Length 1));
                
writor.Write((ushort)(Quests[i].FinishScript.Length 1));
                
writor.Write((ushort)(Quests[i].ActionScript.Length 1));
                
writor.Write(Quests[i].RewardData);
                
long num4 writor.BaseStream.Position position;
                
long num5 672;
                if (
num4 != 672)
                {
                    throw new 
Exception("Required Length: " num5.ToString() + " - Current Length: " num4.ToString());
                }
                
WriteNulledString(writorQuests[i].StartScript);
                
WriteNulledString(writorQuests[i].ActionScript);
                
WriteNulledString(writorQuests[i].FinishScript);
            }
            
stream.Close();
            
stream.Dispose();
        }

        
void ParseItems(Quest quest)
        {
            for (
byte i 010= (byte) (1))
            {
                
Item item = new Item
                
{
                    
isActive Reader.ReadByte(),
                    
Type Reader.ReadByte(),
                    
ID Reader.ReadUInt16(),
                    
Amount Reader.ReadUInt16()
                };
                
quest.Items.Add(item);
            }
            
quest.DropCount Reader.ReadUInt32();
            for (
byte j 0quest.DropCount= (byte)(1))
            {
                
ItemDrop drop = new ItemDrop
                
{
                    
isActive Reader.ReadUInt32(),
                    
MobID Reader.ReadUInt32(),
                    
Amount Reader.ReadUInt32(),
                    
ItemID Reader.ReadUInt32(),
                    
Rate Reader.ReadUInt32(),
                    
UnkByte1 Reader.ReadUInt32(),
                    
UnkByte2 Reader.ReadUInt32()
                };
                
quest.ItemDrop.Add(drop);
            }
            
uint num3 0;
            if (
quest.DropCount 0)
            {
                
num3 = (28 * (11 quest.DropCount)) + 12;
            }
            else
            {
                
num3 = (28 * (11 quest.DropCount)) + 12;
            }
            
ItemDropPadding padding = new ItemDropPadding
            
{
                
Padding Reader.ReadBytes(Convert.ToInt32(num3))
            };
            
quest.ItemPadding.Add(padding);
        }

        private 
void ParseMobs(Quest quest)
        {
            for (
int i 05; ++i)
            {

                
Mob item = new Mob
                
{
                    
isActive Convert.ToBoolean(Reader.ReadByte()),
                    
isMob Convert.ToBoolean(Reader.ReadByte()),
                    
ID Reader.ReadUInt16(),
                    
HasToBeKilled Convert.ToBoolean(Reader.ReadByte()),
                    
Amount Reader.ReadByte(),
                    
UnkDataMob Reader.ReadByte(),
                    
UnkDataMob2 Reader.ReadByte()
                };
                
quest.Mobs.Add(item);
            }
        }

        
string ReadNulledString()
        {
            
byte[] data = new byte[256];
            
int index 0;
            
byte b;
            while ((
Reader.ReadByte()) != 0)
            {
                if (
data.Length == index) Array.Resize(ref datadata.Length 2);
                {
                    
data[index++] = b;
                }              
            }
            return 
Encoding.ASCII.GetString(data0index);
        }

        
void WriteZeros(BinaryWriter writerint count)
        {
            for (
int i 0count; ++i)
            {
                
writer.Write((byte)0);
            }
        }

        
void WriteNulledString(BinaryWriter writerstring text)
        {
            
writer.Write(Encoding.Default.GetBytes(text));
            
writer.Write((byte)0);
        }
    }

    public 
sealed class Quest
    
{
        public 
uint DropCount 0;
        public List<
ItemDropItemDrop = new List<ItemDrop>();
        public List<
ItemDropPaddingItemPadding = new List<ItemDropPadding>();
        public List<
MobMobs = new List<Mob>();
        public List<
QuestRewardRewards = new List<QuestReward>();
        public List<
ItemItems = new List<Item>();
        public 
string ActionScript getset; }
        public 
ushort Description getset; }
        public 
string FinishScript getset; }
        public 
ushort ID getset; }
        public 
byte ClassType getset; }
        public 
byte DailyQuest getset; }
        public 
byte EnableQuest getset; }
        public 
byte InstAcc getset; }
        public 
byte InstHand getset; }
        public 
byte[] ItemData getset; }
        public 
ushort ItemID getset; }
        public 
byte ItemVanish getset; }
        public 
byte MaxLevel getset; }
        public 
byte MinLevel getset; }
        public 
byte MultiQuest getset; }
        public 
byte NeedClass getset; }
        public 
byte NeedItem getset; }
        public 
byte NeedLevel getset; }
        public 
byte NeedNPC getset; }
        public 
byte NeedPred getset; }
        public 
ushort Predesessor getset; }
        public 
byte QuestGrade getset; }
        public 
byte[] RewardData getset; }
        public 
ushort StartingNPC getset; }
        public 
string StartScript getset; }
        public 
ushort Title getset; }

        public 
Dictionary<bytebyte[]> UnkBytes = new Dictionary<bytebyte[]>();

        public 
string GetUnkString()
        {
            
string tot "";
            for (
int i 0RewardData.Length 1; ++i)
            {
                
tot += RewardData[i].ToString("X2") + " ";
            }
            
tot += RewardData[RewardData.Length 1].ToString("X2");
            return 
tot;
        }

        public 
void SetUnkString(string hex)
        {
            
string[] splitted hex.Split(' ');
            if (
splitted.Length != 18) { throw new Exception("Incorrect lenght!"); }
            for (
int i 0splitted.Length; ++i)
            {
                
RewardData[i] = byte.Parse(splitted[i], System.Globalization.NumberStyles.HexNumber);
            }
        }

        public 
uint DataLen()
        {
            
uint start 0;
            
start 672;
            
start = (uint)(672 + (StartScript.Length 1));
            
start += (uint)(ActionScript.Length 1);
            return (
start + ((uint)FinishScript.Length 1));
        }
    }

    public 
sealed class Mob
    
{
        public 
byte Amount getset; }
        public 
bool HasToBeKilled getset; }
        public 
bool isActive getset; }
        public 
bool isMob getset; }
        public 
ushort ID getset; }
        public 
byte UnkDataMob getset; }
        public 
byte UnkDataMob2 getset; }

    }


    public class 
QuestReward
    
{
        public 
enum RewardType byte
        
{
            
Exp 0,
            
Money 1,
            
Item 2,
            
Fame 4,
        }
        public 
RewardType Type getset; }
        public 
ushort unkShort getset; }
        public 
ushort Value getset; }
        public 
ushort ItemCount getset; }
        public 
ulong Amount getset; }
        public 
byte isGiven getset; }
        public 
uint unkDword getset; }

    }

    public class 
Item
    
{
        public 
byte Type getset; }
        public 
ushort ID getset; }
        public 
ushort Amount getset; }
        public 
byte isActive getset; }
    }

    public class 
ItemDrop
    
{
        public 
uint Amount getset; }
        public 
uint isActive getset; }
        public 
uint ItemID getset; }
        public 
uint MobID getset; }
        public 
uint Rate getset; }
        public 
uint UnkByte1 getset; }
        public 
uint UnkByte2 getset; }
    }

    public class 
ItemDropPadding
    
{
        public 
byte[] Padding getset; }
    }