Here is what I have gotten so far:
1. Installed MySQL Community server
2. Installed MySQL .Net Connectors
3. Installed Heidi SQL Client
4. Grabbed arkDB from Arkania Files repository
Note: this data base has a lot of other useful info in it. If anyone knows of a better or more complete database please post in this thread.
5. Created arkdb,auth, and characters tables in MySQL
6. Ran the arkdb install batch file for a fresh database install.
Used the following code to generate QuestNpc and QuestGameObject Ids.
Code:
class QuestObjectiveTracker
{
public static List<int> QuestGameObjects;
public static List<int> QuestNpcs;
private static Dictionary<int, QuestObjectiveEntry> m_questDict = new Dictionary<int, QuestObjectiveEntry>();
private static Thread m_thread;
private static bool m_bRunning;
public class QuestObjectiveEntry
{
public PlayerQuest Quest;
public QuestCache Cache; // I am using TomRus's QuestCache reader and code
}
// I grabbed Apoc's FSM engine thread code and used it here
public static void Start(int sleepTime)
{
// We want to round a bit here.
m_bRunning = true;
m_questDict = new Dictionary<int, QuestObjectiveEntry>();
// Leave it as a background thread. This CAN trail off
// as the program exits, without any issues really.
m_thread = new Thread(Run) { IsBackground = true };
m_thread.Start(sleepTime);
}
private static void Run(object sleepTime)
{
try
{
while (m_bRunning)
{
Pulse();
Thread.Sleep((int)sleepTime);
}
}
finally
{
// If we exit due to some exception,
// that isn't caught elsewhere,
// we need to make sure we set the Running
// property to false, to avoid confusion,
// and other bugs.
m_bRunning = false;
}
}
public static void Stop()
{
if (!m_bRunning)
{
// Nothing to do.
return;
}
if (m_thread.IsAlive)
{
m_thread.Abort();
}
// Clear out the thread object.
m_thread = null;
QuestGameObjects = null;
QuestNpcs = null;
m_questDict = null;
// Make sure we let everyone know, we're not running anymore!
m_bRunning = false;
}
private static void Pulse()
{
var questGameObjects = new List<int>();
var questNpcs = new List<int>();
for (var x = 0; x <= 0x32; x++)
{
var quest = Quest.Get(x);
if (quest.ID == 0) continue;
if (quest.ID == 27046) // used to debug add what quest ID you want to debug
{
var b = 1;
}
if (m_questDict.ContainsKey(quest.ID))
{
QuestObjectiveEntry entry;
var result = m_questDict.TryGetValue(quest.ID, out entry);
if (!result) continue;
if (entry.Cache.CollectItemId == null) continue;
if (entry.Cache.Id == 27047) // used to debug add what quest ID you want to debug
{
var b = 1;
}
if (entry.Cache.CollectItemId[0] > 0)
{
var current =
TC.Mem.Read<short>(
TC.Mem.Read<uint>(
Manager.Instance.Me.Address + Offsets.DescriptorFields)
+ (uint)ePlayerField.PLAYER_QUEST_LOG_1_3 + (uint)(0x14 * x));
if (entry.Cache.CollectItemCount[0] > current )
{
{
var commandString =
string.Format("select entry from arkdb.gameobject_template where questItem1 = {0}",
entry.Cache.CollectItemId[0]);
var idList = ArkDbQuerry(commandString);
if (idList != null && idList.Count > 0)
{
foreach (var id in idList)
{
questGameObjects.Add(id);
}
}
}
{
var commandString =
string.Format("select entry from arkdb.creature_template where questItem1 = {0}",
entry.Cache.CollectItemId[0]);
var idList = ArkDbQuerry(commandString);
if (idList != null && idList.Count > 0)
{
foreach (var id in idList)
{
questNpcs.Add(id);
}
}
}
}
}
if (entry.Cache.ReqCreatureOrGOId[0] > 0)
{
var current =
TC.Mem.Read<short>(
TC.Mem.Read<uint>(
Manager.Instance.Me.Address + Offsets.DescriptorFields)
+ (uint) ePlayerField.PLAYER_QUEST_LOG_1_3 + (uint) (0x14*x));
if (entry.Cache.ReqCreatureOrGOIdCount[0] > current)
{
{
var commandString =
string.Format(
"select entry from arkdb.creature_template where entry = {0} or KillCredit1 = {0}",
entry.Cache.ReqCreatureOrGOId[0]);
var idList = ArkDbQuerry(commandString);
if (idList != null && idList.Count > 0)
{
foreach (var id in idList)
{
questNpcs.Add(id);
}
}
}
{
var commandString =
string.Format("select entry from arkdb.gameobject_template where data1 = {0} or questItem1 = {1}",
entry.Quest.ID, entry.Cache.ReqCreatureOrGOId[0]);
var idList = ArkDbQuerry(commandString);
if (idList != null && idList.Count > 0)
{
foreach (var id in idList)
{
questGameObjects.Add(id);
}
}
}
}
}
continue;
}
var questCache = WowCache.GetQuestCachebyId(quest.ID);
var qe = new QuestObjectiveEntry { Quest = quest, Cache = questCache };
m_questDict.Add(quest.ID, qe);
}
QuestGameObjects = questGameObjects;
QuestNpcs = questNpcs;
}
private static List<int> ArkDbQuerry(string commandString)
{
var resultList = new List<int>();
const string myConString = "SERVER=quadcore;" + "DATABASE=arkdb;" + "UID=root;" + "PASSWORD=harl3y;";
var connection = new MySqlConnection(myConString);
var command = connection.CreateCommand();
connection.Open();
command.CommandText = commandString;
var reader = command.ExecuteReader();
while (reader.Read())
{
for (var i = 0; i < reader.FieldCount; i++)
{
var s = reader.GetValue(i);
if (s == null) continue;
var data = Convert.ToInt32(s);
resultList.Add(data);
}
}
reader.Close();
return resultList;
}
}
[StructLayout(LayoutKind.Sequential)]
public struct PlayerQuest
{
public int ID;
public int State;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
public short[] ObjectiveRequiredCounts;
public int Time;
public enum eStateFlag : uint
{
NONE = 0,
COMPLETE = 1,
FAILED = 2
}
}
public static class Quest
{
private static readonly uint m_questBase = TC.Mem.Read<uint>(Manager.Instance.Me.Address + Offsets.DescriptorFields) + (uint)ePlayerField.PLAYER_QUEST_LOG_1_1;
public static PlayerQuest Get(int index)
{
return TC.Mem.ReadStruct<PlayerQuest>(m_questBase + (uint)index * 0x14);
}
public static void Dump()
{
uint n;
var qList = new List<PlayerQuest>();
for (n = 0; n < 0x32; n++)
{
var questData = TC.Mem.ReadStruct<PlayerQuest>((m_questBase + 0x14 * n));
qList.Add(questData);
}
}
}
I this works for most quests where you have to kill something or collect something.
I am working on more complex quests now like "Underground Economy" and or " Magnets, How do they work".
Also not sure how I am going to handle "The Restless Brood"
Hope this helps someone else...
-counted