Ok so I posted about this ages ago but realized after being msg'd on youtube that I've never actually posted the code to do this...
As many of you know, I never bothered adding npc scripts for well... any npcs in the hellmouth source...
THIS WILL ONLY LOG NPC SPAWN LOCATIONS AND THE FIRST PAGE OF TEXT/OPTIONS WHEN YOU TALK TO THEM!!!
I've also been trying to encourage people to use the damn external python scripts but so far they haven't taken much of an interest... well here's something that may change that for some people.
What do I need?
This is for use with my proxy release which can be found [Only registered and activated users can see links. Click Here To Register...]
Set up should be rather simple but I'll go over it very quickly here...
-Edit conquer loader to use the ports in the program.cs (namely 5001 or 5002 for login port 5000 for game port + a local hamachi ip. DO NOT USE 127.0.0.1 OR YOU WILL CRASH THE CLIENT)
Port 5001 = new server groups (generally left side of groups)
Port 5002 = old server groups (generally right side... IE: wild kingdom and such)
Now, you'll want to edit your settings.txt file in the proxy bin/debug folder to be using the correct settings.
THIS WILL CAUSE THE DATABASE TO BE USED SO PLEASE ENSURE YOU'VE RUN THE DATABASE BACKUP (make sure innodb is enabled... not sure if i'm using it in this db though) AND THE MYSQL SETTINGS ARE CORRECT IN THE SETTINGS.TXT FILE
Now... open up the proxy source code and follow my lead.
Not strongly needed but I added it for the hell of it and so I could see what I was missing...
Program.cs
anywhere near the top (since ppl suck lets just say right above 'DynaMaps')
Right below " Wha.Start();" place
Database.cs
Now in Client/Client.cs
above public class Client place
Inside the Client class (so lets just say right below sniffing)
Now in Packets/Handler.cs where Client packets are being handled
(public static void HandleClient(byte[] Data, Client Client)) place
obviously this goes in the main switch statement.
Now in the handle server side ( public static void HandleServer(byte[] Data, Client Client, bool Modify)) place
What I did was to dump the npc I made a new .cs file (doesn't matter where) and put this
<<EDIT>>
You will also need the sob/npc classes (yes, I'm well aware I should have been using structs all through this but bite me)
And you should be good to go.
Attached is the database I was logging the files to.
NOTE: you must place a folder called npcs in your debug folder for the scripts to write properly.
NOTEX2: Tq has changed the npc uids for most npcs. I'd suggest logging them all from scratch (make a new npc db + logging their scripts by talking to them) and use that.
NOTEX3: The way tq uses their npcs there is no simple way to log more than the first page of dialogue. This is ONLY to make the server look more complete and save you some typing. They will not 'do' anything nor will they have any dialogue past the first page.
As many of you know, I never bothered adding npc scripts for well... any npcs in the hellmouth source...
THIS WILL ONLY LOG NPC SPAWN LOCATIONS AND THE FIRST PAGE OF TEXT/OPTIONS WHEN YOU TALK TO THEM!!!
I've also been trying to encourage people to use the damn external python scripts but so far they haven't taken much of an interest... well here's something that may change that for some people.
What do I need?
This is for use with my proxy release which can be found [Only registered and activated users can see links. Click Here To Register...]
Set up should be rather simple but I'll go over it very quickly here...
-Edit conquer loader to use the ports in the program.cs (namely 5001 or 5002 for login port 5000 for game port + a local hamachi ip. DO NOT USE 127.0.0.1 OR YOU WILL CRASH THE CLIENT)
Port 5001 = new server groups (generally left side of groups)
Port 5002 = old server groups (generally right side... IE: wild kingdom and such)
Now, you'll want to edit your settings.txt file in the proxy bin/debug folder to be using the correct settings.
THIS WILL CAUSE THE DATABASE TO BE USED SO PLEASE ENSURE YOU'VE RUN THE DATABASE BACKUP (make sure innodb is enabled... not sure if i'm using it in this db though) AND THE MYSQL SETTINGS ARE CORRECT IN THE SETTINGS.TXT FILE
Now... open up the proxy source code and follow my lead.
Not strongly needed but I added it for the hell of it and so I could see what I was missing...
Program.cs
anywhere near the top (since ppl suck lets just say right above 'DynaMaps')
Code:
public static List<uint> npcsInDatabase = new List<uint>();
Code:
Database.GetNpcs();
Code:
public static void AddNpc(Npc S)
{
MySqlCommand cmd = new MySqlCommand(MySqlCommandType.INSERT);
cmd.Insert("npcs")
.Insert("UID", S.UID)
.Insert("ID", S.ID)
.Insert("X", S.X)
.Insert("Y", S.Y)
.Insert("Map", S.Map)
.Insert("Mesh", S.Mesh)
.Insert("Flag", S.Flag);
cmd.Execute();
}
public static void GetNpcs()
{
MySqlCommand cmd = new MySqlCommand(MySqlCommandType.SELECT);
cmd.Select("npcs");
MySqlReader r = new MySqlReader(cmd);
while (r.Read())
{
Program.npcsInDatabase.Add(r.ReadUInt32("UID"));
}
Console.WriteLine("loaded " + Program.npcsInDatabase.Count + " npcs from database");
}
public static void AddSOB(Sob S)
{
MySqlCommand cmd = new MySqlCommand(MySqlCommandType.INSERT);
cmd.Insert("Sobs")
.Insert("UID", S.UID)
.Insert("X", S.X)
.Insert("Y", S.Y)
.Insert("Map", S.Map)
.Insert("Mesh", S.Type)
.Insert("Flag", S.Flag)
.Insert("MaxHp", S.Hp);
cmd.Execute();
}
above public class Client place
Code:
public class LogNPC
{
public ushort Face, NPCID = 0;
public List<String> Text = new List<String>();
public Dictionary<byte, string> Links = new Dictionary<byte, string>();
}
Code:
public LogNPC RecordingNpc = null
Now in Packets/Handler.cs where Client packets are being handled
(public static void HandleClient(byte[] Data, Client Client)) place
Code:
#region NPC REQUEST
case 2031:
{
if (Client.RecordingNpc != null)
{
Client.RecordingNpc = null;
return;
}
Client.RecordingNpc = new LogNPC();
Client.RecordingNpc.NPCID = (ushort)ReadUInt32(Data, 4);
break;
}
#endregion
Now in the handle server side ( public static void HandleServer(byte[] Data, Client Client, bool Modify)) place
Code:
#region SOB LOGGER
case 1109:
{
Sob S = new Sob();
S.UID = ReadUInt32(Data, 4);
S.Type = ReadUInt16(Data, 24);
S.Hp = ReadUInt32(Data, 12);
S.Flag = ReadUInt16(Data, 26);
S.X = ReadUInt16(Data, 20);
S.Y = ReadUInt16(Data, 22);
S.Map = Client.Map;
Database.AddSOB(S);
break;
}
#endregion
#region NPC LOGGER
case 2032:
if (Client.RecordingNpc != null)
{
Client.ToClientQueue.Enqueue(Data);
send = false;
switch (Data[11])
{
case 1:
Client.RecordingNpc.Text.Add(ReadString(Data, 14, Data[13]).Replace('~', ' '));
break;
case 2:
Client.RecordingNpc.Links.Add(Data[10], ReadString(Data, 14, Data[13]).Replace('~', ' '));
break;
case 4://face
Client.RecordingNpc.Face = ReadUInt16(Data, 8);
break;
case 100:
Handler.DumpNpc(Client);
Client.RecordingNpc.NPCID = 0;
Client.RecordingNpc = null;
break;
}
}
break;
#endregion
#region SpawnNpc
case 2030:
{
Npc N = new Npc();
N.UID = ReadUInt32(Data, 4);
N.ID = ReadUInt32(Data, 8);
N.X = ReadUInt16(Data, 12);
N.Y = ReadUInt16(Data, 14);
N.Mesh = ReadUInt16(Data, 16);
N.Flag = Data[18];
N.Map = Client.Map;
if (!Program.npcsInDatabase.Contains(N.UID))
{ Program.npcsInDatabase.Add(N.UID); Console.WriteLine("Adding new NPC ID: " + N.UID); Database.AddNpc(N); }
Location L = new Location();
L.X = ReadUInt16(Data, 12);
L.Y = ReadUInt16(Data, 14);
L.Map = Client.Map;
if (!Program.NpcLocations.Contains(L))
Program.NpcLocations.Add(L);
if (Client.Alone)
send = false;
break;
}
#endregion
What I did was to dump the npc I made a new .cs file (doesn't matter where) and put this
Code:
public partial class Handler
{
public static void DumpNpc(Client C)
{
try
{
if (C.RecordingNpc == null)
return;
if (File.Exists(Application.StartupPath + @"\npcs\" + C.RecordingNpc.NPCID + ".npc"))
File.Delete(Application.StartupPath + @"\npcs\" + C.RecordingNpc.NPCID + ".npc");
StreamWriter SW = new StreamWriter(File.Create(Application.StartupPath + @"\npcs\" + C.RecordingNpc.NPCID + ".npc"));
SW.WriteLine("def npc(Client, Option):");
SW.WriteLine(" if(Option == 0):");
foreach (String Text in C.RecordingNpc.Text)
SW.WriteLine(" Text(\"" + Text + "\")");
foreach (KeyValuePair<byte, string> Option in C.RecordingNpc.Links)
SW.WriteLine(" Link(\"" + Option.Value + "\", " + Option.Key + ")");
SW.WriteLine(" Face(" + C.RecordingNpc.Face + ")");
SW.WriteLine(" return 0");
SW.Close();
SW.Flush();
C.RecordingNpc = null;
}
catch { }
}
}
You will also need the sob/npc classes (yes, I'm well aware I should have been using structs all through this but bite me)
Code:
public class Sob
{
public uint Type, UID, Hp;
public ushort Flag, Map, X, Y;
}
public class Npc
{
public uint UID,ID;
public byte Flag;
public ushort Mesh, Map, X, Y;
}
Attached is the database I was logging the files to.
NOTE: you must place a folder called npcs in your debug folder for the scripts to write properly.
NOTEX2: Tq has changed the npc uids for most npcs. I'd suggest logging them all from scratch (make a new npc db + logging their scripts by talking to them) and use that.
NOTEX3: The way tq uses their npcs there is no simple way to log more than the first page of dialogue. This is ONLY to make the server look more complete and save you some typing. They will not 'do' anything nor will they have any dialogue past the first page.