Well... let me explain a thing, IT'S NOT FOR HELLMOUNTH SOURCE!. So don't ask me to convert or do anything like... because i won't!
let's start.
First create those enums & class:
Code:
public enum SubClassType : byte
{
Switch = 0,
Activate = 1,
Show = 7,
MartialPromoted = 5,
Learn = 4
}
public class SubClass
{
public SubClassID ID;
public byte Level;
public byte Phase;
}
public enum SubClassID : byte
{
None = 0,
MartialArtist = 1,
Warlock = 2,
ChiMaster = 3,
Sage = 4,
Apothecary = 5,
Performer = 6
}
this are the packets:
Code:
public static byte[] SubClass(Struct.SubClass SubClass, Struct.SubClassType Type)
{
byte[] Buffer = new byte[8 + 26];
Writer.WriteUInt16((ushort)(Buffer.Length - 8), 0, Buffer);
Writer.WriteUInt16(2320, 2, Buffer);
Writer.WriteUInt16((ushort)Type, 4, Buffer);
Writer.WriteByte((byte)SubClass.ID, 6, Buffer);
Writer.WriteByte(SubClass.Level, 7, Buffer);
Writer.WriteString(Server.MainKey, (Buffer.Length - 8), Buffer);
return Buffer;
}
public static byte[] SubClassesInfo(Client CSocket, Struct.SubClassType Type)
{
int Position = 26;
byte[] Buffer = new byte[8 + 26 + (CSocket.Client.SubClasses.Classes.Count * 3)];
Writer.WriteUInt16((ushort)(Buffer.Length - 8), 0, Buffer);
Writer.WriteUInt16(2320, 2, Buffer);
Writer.WriteUInt16((ushort)Type, 4, Buffer);
Writer.WriteUInt16(CSocket.Client.StudyPoints, 6, Buffer);
Writer.WriteUInt16((ushort)CSocket.Client.SubClasses.Classes.Count, 22, Buffer);
foreach (Struct.SubClass Class in CSocket.Client.SubClasses.Classes.Values)
{
Writer.WriteByte((byte)Class.ID, Position, Buffer); Position++;
Writer.WriteByte(Class.Phase, Position, Buffer); Position++;
Writer.WriteByte(Class.Level, Position, Buffer); Position++;
}
Writer.WriteString(Server.MainKey, (Buffer.Length - 8), Buffer);
return Buffer;
}
this is my subclass class... not fully released but the important part is:
Code:
public class Subclasses
{
uint mOwner = 0;
Character Owner { get { return Server.Pool[mOwner]; } }
public Dictionary<Struct.SubClassID, Struct.SubClass> Classes = null;
public Subclasses(uint owner)
{
mOwner = owner;
Classes = new Dictionary<Struct.SubClassID, Struct.SubClass>();
}
public void AppendNew(Struct.SubClass sClass)
{
if (!Classes.ContainsKey(sClass.ID))
{
Classes.Add(sClass.ID, sClass);
Owner.Owner.Send(ConquerPacket.SubClass(sClass, Struct.SubClassType.Learn));
}
}
}
Code:
#region SubClass [2320]
case 2320:
{
switch (Data[4])
{
#region [Restore/Switch]
case 0:
byte To = Data[6];
CSocket.Send(ConquerPacket.SubClass(new Struct.SubClass(), Struct.SubClassType.Activate));
if (To > 0)//Switch
{
#region [Effects-Removal]
switch (CSocket.Client.Active_SubClass)
{
case Struct.SubClassID.Apothecary:
{
CSocket.Client.Object_Status.Status_Redduction[StatusRedduction.Detoxication] -= (CSocket.Client.SubClasses.Classes[Struct.SubClassID.Apothecary].Phase * 8);
break;
}
}
#endregion
#region [Effects-Addition]
switch ((Struct.SubClassID)To)
{
case Struct.SubClassID.Apothecary:
{
CSocket.Client.Object_Status.Status_Redduction[StatusRedduction.Detoxication] += (CSocket.Client.SubClasses.Classes[Struct.SubClassID.Apothecary].Phase * 8);
break;
}
}
#endregion
CSocket.Client.Active_SubClass = (Struct.SubClassID)To;
CSocket.Send(ConquerPacket.SubClass(CSocket.Client.SubClasses.Classes[CSocket.Client.Active_SubClass], Struct.SubClassType.Activate));
CSocket.Send(ConquerPacket.SubClassesInfo(CSocket, Struct.SubClassType.Show));
}
else//Restore
{
#region [Effects-Removal]
switch (CSocket.Client.Active_SubClass)
{
case Struct.SubClassID.Apothecary:
{
CSocket.Client.Object_Status.Status_Redduction[StatusRedduction.Detoxication] -= (CSocket.Client.SubClasses.Classes[Struct.SubClassID.Apothecary].Phase * 8);
break;
}
}
#endregion
CSocket.Client.Active_SubClass = Struct.SubClassID.None;
CSocket.Send(ConquerPacket.SubClassesInfo(CSocket, Struct.SubClassType.Show));
}
ConquerPacket.ToLocal(CSocket.Client.Spawn, CSocket.Client.X, CSocket.Client.Y, (int)CSocket.Client.Map, 0, CSocket.Client.UID);
break;
#endregion
#region [Upgrade]
case 2:
{
byte Class = Data[6];
ushort Required = 0;
Struct.SubClass Sc = CSocket.Client.SubClasses.Classes[(Struct.SubClassID)Class];
#region [Set Required]
switch (Sc.ID)
{
case Struct.SubClassID.MartialArtist:
switch (Sc.Level)
{
case 1: Required = 300; break;
case 2: Required = 900; break;
case 3: Required = 1800; break;
case 4: Required = 2700; break;
case 5: Required = 3600; break;
case 6: Required = 5100; break;
case 7: Required = 6900; break;
case 8: Required = 8700; break;
case 9: Required = ushort.MaxValue; break;
}
break;
case Struct.SubClassID.Warlock:
switch (Sc.Level)
{
case 1: Required = 300; break;
case 2: Required = 900; break;
case 3: Required = 1800; break;
case 4: Required = 2700; break;
case 5: Required = 3600; break;
case 6: Required = 5100; break;
case 7: Required = 6900; break;
case 8: Required = 8700; break;
case 9: Required = ushort.MaxValue; break;
}
break;
case Struct.SubClassID.ChiMaster:
switch (Sc.Level)
{
case 1: Required = 600; break;
case 2: Required = 1800; break;
case 3: Required = 3600; break;
case 4: Required = 5400; break;
case 5: Required = 7200; break;
case 6: Required = 10200; break;
case 7: Required = 13800; break;
case 8: Required = 17400; break;
case 9: Required = ushort.MaxValue; break;
}
break;
case Struct.SubClassID.Sage:
switch (Sc.Level)
{
case 1: Required = 400; break;
case 2: Required = 1200; break;
case 3: Required = 2400; break;
case 4: Required = 3600; break;
case 5: Required = 4800; break;
case 6: Required = 6800; break;
case 7: Required = 9200; break;
case 8: Required = 11600; break;
case 9: Required = ushort.MaxValue; break;
}
break;
case Struct.SubClassID.Apothecary:
switch (Sc.Level)
{
case 1: Required = 100; break;
case 2: Required = 200; break;
case 3: Required = 300; break;
case 4: Required = 400; break;
case 5: Required = 500; break;
case 6: Required = 1000; break;
case 7: Required = 4000; break;
case 8: Required = 9000; break;
case 9: Required = ushort.MaxValue; break;
}
break;
case Struct.SubClassID.Performer:
switch (Sc.Level)
{
case 1: Required = 400; break;
case 2: Required = 1200; break;
case 3: Required = 2400; break;
case 4: Required = 3600; break;
case 5: Required = 4800; break;
case 6: Required = 6800; break;
case 7: Required = 9200; break;
case 8: Required = 11600; break;
case 9: Required = ushort.MaxValue; break;
}
break;
}
#endregion
if (CSocket.Client.StudyPoints >= Required)
{
CSocket.Client.StudyPoints -= Required;
CSocket.Client.SubClasses.Classes[(Struct.SubClassID)Class].Level++;
CSocket.Send(ConquerPacket.SubClass(CSocket.Client.SubClasses.Classes[(Struct.SubClassID)Class], Struct.SubClassType.Activate));
CSocket.Send(ConquerPacket.SubClassesInfo(CSocket, Struct.SubClassType.Show));
Database.UpdateSubClass(CSocket.Client.SubClasses.Classes[(Struct.SubClassID)Class], CSocket.Client.UID);
}
break;
}
#endregion
#region [Info]
case 6:
foreach (Struct.SubClass s in CSocket.Client.SubClasses.Classes.Values)
{
CSocket.Send(ConquerPacket.SubClass(s, Struct.SubClassType.Learn));
}
CSocket.Send(ConquerPacket.SubClassesInfo(CSocket, Struct.SubClassType.Show));
if (CSocket.Client.Active_SubClass != Struct.SubClassID.None)
CSocket.Send(ConquerPacket.SubClass(CSocket.Client.SubClasses.Classes[CSocket.Client.Active_SubClass], Struct.SubClassType.Activate));
break;
#endregion
default:
Console.WriteLine("Unknown 2320 packet type " + Data[4]);
Print(Data);
break;
}
break;
}
#endregion
//Edit:
//Nearly forgot something... this are the database commands:
Code:
public static void LoadSubClasses(Character Client)
{
MySqlCommand Command = new MySqlCommand(MySqlCommandType.SELECT);
Command.Select("pt_subclass").Where("owner", Client.UID).Execute();
MySqlReader Reader = new MySqlReader(Command);
while (Reader.Read())
{
Struct.SubClass s = new Struct.SubClass();
s.ID = (Struct.SubClassID)Reader.ReadByte("id");
s.Level = Reader.ReadByte("level");
s.Phase = Reader.ReadByte("phase");
Client.SubClasses.AppendNew(s);
}
}
public static void CreateSubClass(Struct.SubClass s, uint Uid)
{
MySqlCommand Command = new MySqlCommand(MySqlCommandType.INSERT);
Command.Insert("pt_subclass")
.Insert("owner", Uid)
.Insert("id", (byte)s.ID)
.Insert("level", s.Level)
.Insert("phase", s.Phase)
.Execute();
}
public static void UpdateSubClass(Struct.SubClass s, uint Uid)
{
MySqlCommand Command = new MySqlCommand(MySqlCommandType.UPDATE);
Command.Update("pt_subclass")
.Set("level", s.Level)
.Set("phase", s.Phase)
.Where("owner", Uid)
.And("id", (byte)s.ID)
.Execute();
}
Cya!






