diff --git a/MapleLib/WzLib/WzStructure/Data/CharacterStructure/CharacterJobPreBBType.cs b/MapleLib/WzLib/WzStructure/Data/CharacterStructure/CharacterJobPreBBType.cs
new file mode 100644
index 0000000..6e45f45
--- /dev/null
+++ b/MapleLib/WzLib/WzStructure/Data/CharacterStructure/CharacterJobPreBBType.cs
@@ -0,0 +1,213 @@
+/*Copyright(c) 2024, LastBattle https://github.com/lastbattle/Harepacker-resurrected
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+*/
+
+using System.Collections.Generic;
+using System.Linq;
+using System.Text.RegularExpressions;
+
+namespace MapleLib.WzLib.WzStructure.Data.CharacterStructure
+{
+ ///
+ /// The bitfield values for job categories
+ /// for Quest Act.img 'job' WZ values before big-bang update.
+ ///
+ public enum CharacterJobPreBBType
+ {
+ None = 0x0,
+
+ // Basic Classes (0x1 - 0x20)
+ Beginner = 0x1, // 0
+ ExplorerWarrior = 0x2, // 100
+ ExplorerMagician = 0x4, // 200
+ ExplorerArcher = 0x8, // 300
+ ExplorerThief = 0x10, // 400
+ ExplorerPirate = 0x20, // 500
+
+ // Cygnus Knights (0x400 - 0x8000)
+ Noblesse = 0x400, // 1000
+ DawnWarrior = 0x800, // 1100
+ BlazeWizard = 0x1000, // 1200
+ WindArcher = 0x2000, // 1300
+ NightWalker = 0x4000, // 1400
+ ThunderBreaker = 0x8000, // 1500
+
+ // Heroes/Legends (0x20000 - 0x400000)
+ Evan = 0x20000, // 2001, 2200
+ Aran = 0x100000, // 2000, 2001
+ AranWarrior = 0x200000, // 2100
+ EvanMagician = 0x400000, // 2001, 2200
+
+ // Resistance (0x40000000)
+ Resistance = 0x40000000, // 3000, 3200, 3300, 3500
+
+ // Combined Group Masks
+ AllExplorers = ExplorerWarrior | ExplorerMagician | ExplorerArcher | ExplorerThief | ExplorerPirate,
+ AllCygnus = DawnWarrior | BlazeWizard | WindArcher | NightWalker | ThunderBreaker,
+ AllHeroes = Aran | AranWarrior | Evan | EvanMagician,
+
+ // Class Type Masks (for similar class types across factions)
+ AllWarriors = ExplorerWarrior | DawnWarrior | AranWarrior,
+ AllMagicians = ExplorerMagician | BlazeWizard | Evan | EvanMagician,
+ AllArchers = ExplorerArcher | WindArcher,
+ AllThieves = ExplorerThief | NightWalker,
+ AllPirates = ExplorerPirate | ThunderBreaker
+ }
+
+ public static class CharacterJobPreBBTypeExt
+ {
+ public static IEnumerable DecodeJobCodes(this CharacterJobPreBBType encoded)
+ {
+ var jobs = new List();
+
+ // Basic Classes
+ if (encoded.HasFlag(CharacterJobPreBBType.Beginner))
+ jobs.Add(CharacterJob.Beginner);
+ if (encoded.HasFlag(CharacterJobPreBBType.ExplorerWarrior))
+ jobs.Add(CharacterJob.Warrior);
+ if (encoded.HasFlag(CharacterJobPreBBType.ExplorerMagician))
+ jobs.Add(CharacterJob.Magician);
+ if (encoded.HasFlag(CharacterJobPreBBType.ExplorerArcher))
+ jobs.Add(CharacterJob.Archer);
+ if (encoded.HasFlag(CharacterJobPreBBType.ExplorerThief))
+ jobs.Add(CharacterJob.Rogue);
+ if (encoded.HasFlag(CharacterJobPreBBType.ExplorerPirate))
+ jobs.Add(CharacterJob.Pirate);
+
+ // Cygnus Knights
+ if (encoded.HasFlag(CharacterJobPreBBType.Noblesse))
+ jobs.Add(CharacterJob.Noblesse);
+ if (encoded.HasFlag(CharacterJobPreBBType.DawnWarrior))
+ jobs.Add(CharacterJob.DawnWarrior1);
+ if (encoded.HasFlag(CharacterJobPreBBType.BlazeWizard))
+ jobs.Add(CharacterJob.BlazeWizard1);
+ if (encoded.HasFlag(CharacterJobPreBBType.WindArcher))
+ jobs.Add(CharacterJob.WindArcher1);
+ if (encoded.HasFlag(CharacterJobPreBBType.NightWalker))
+ jobs.Add(CharacterJob.NightWalker1);
+ if (encoded.HasFlag(CharacterJobPreBBType.ThunderBreaker))
+ jobs.Add(CharacterJob.ThunderBreaker1);
+
+ // Heroes/Legends
+ if (encoded.HasFlag(CharacterJobPreBBType.Evan))
+ {
+ jobs.Add(CharacterJob.EvanBeginner);
+ jobs.Add(CharacterJob.Evan1);
+ }
+ if (encoded.HasFlag(CharacterJobPreBBType.Aran))
+ {
+ jobs.Add(CharacterJob.AranBeginner);
+ jobs.Add(CharacterJob.EvanBeginner);
+ }
+ if (encoded.HasFlag(CharacterJobPreBBType.AranWarrior))
+ jobs.Add(CharacterJob.Aran1);
+
+ if (encoded.HasFlag(CharacterJobPreBBType.EvanMagician))
+ {
+ jobs.Add(CharacterJob.EvanBeginner);
+ jobs.Add(CharacterJob.Evan1);
+ }
+
+ // Resistance
+ if (encoded.HasFlag(CharacterJobPreBBType.Resistance))
+ {
+ jobs.Add(CharacterJob.Citizen);
+ jobs.Add(CharacterJob.BattleMage1);
+ jobs.Add(CharacterJob.WildHunter1);
+ jobs.Add(CharacterJob.Mechanic1);
+ }
+
+ return jobs.Distinct().OrderBy(x => (int)x);
+ }
+
+ public static CharacterJobPreBBType EncodeJobs(IEnumerable jobs)
+ {
+ CharacterJobPreBBType encoded = CharacterJobPreBBType.None;
+
+ foreach (var job in jobs)
+ {
+ switch (job)
+ {
+ case 0: encoded |= CharacterJobPreBBType.Beginner; break;
+ case 100: encoded |= CharacterJobPreBBType.ExplorerWarrior; break;
+ case 200: encoded |= CharacterJobPreBBType.ExplorerMagician; break;
+ case 300: encoded |= CharacterJobPreBBType.ExplorerArcher; break;
+ case 400: encoded |= CharacterJobPreBBType.ExplorerThief; break;
+ case 500: encoded |= CharacterJobPreBBType.ExplorerPirate; break;
+ case 1000: encoded |= CharacterJobPreBBType.Noblesse; break;
+ case 1100: encoded |= CharacterJobPreBBType.DawnWarrior; break;
+ case 1200: encoded |= CharacterJobPreBBType.BlazeWizard; break;
+ case 1300: encoded |= CharacterJobPreBBType.WindArcher; break;
+ case 1400: encoded |= CharacterJobPreBBType.NightWalker; break;
+ case 1500: encoded |= CharacterJobPreBBType.ThunderBreaker; break;
+ case 2000:
+ encoded |= CharacterJobPreBBType.Aran;
+ break;
+ case 2100:
+ encoded |= CharacterJobPreBBType.AranWarrior;
+ break;
+ case 2001:
+ encoded |= CharacterJobPreBBType.Evan;
+ break;
+ case 2200:
+ encoded |= CharacterJobPreBBType.EvanMagician;
+ break;
+ case 3000:
+ case 3200:
+ case 3300:
+ case 3500:
+ encoded |= CharacterJobPreBBType.Resistance;
+ break;
+ }
+ }
+
+ return encoded;
+ }
+
+ ///
+ /// Gets the formatted job name from enum
+ ///
+ ///
+ ///
+ public static string GetFormattedJobName(this CharacterJobPreBBType job)
+ {
+ string jobName = job.ToString();
+
+ // Add spaces between words
+ jobName = string.Concat(jobName.Select(x => char.IsUpper(x) ? " " + x : x.ToString())).Trim();
+
+ return jobName;
+ }
+
+ // Helper methods for common job checks
+ public static bool IsExplorer(this CharacterJobPreBBType codes) => (codes & CharacterJobPreBBType.AllExplorers) != 0;
+ public static bool IsCygnus(this CharacterJobPreBBType codes) => (codes & CharacterJobPreBBType.AllCygnus) != 0;
+ public static bool IsHero(this CharacterJobPreBBType codes) => (codes & CharacterJobPreBBType.AllHeroes) != 0;
+
+ public static bool IsWarrior(this CharacterJobPreBBType codes) => (codes & CharacterJobPreBBType.AllWarriors) != 0;
+ public static bool IsMagician(this CharacterJobPreBBType codes) => (codes & CharacterJobPreBBType.AllMagicians) != 0;
+ public static bool IsArcher(this CharacterJobPreBBType codes) => (codes & CharacterJobPreBBType.AllArchers) != 0;
+ public static bool IsThief(this CharacterJobPreBBType codes) => (codes & CharacterJobPreBBType.AllThieves) != 0;
+ public static bool IsPirate(this CharacterJobPreBBType codes) => (codes & CharacterJobPreBBType.AllPirates) != 0;
+
+ // Helper method to convert from integer to JobCodes enum
+ public static CharacterJobPreBBType ToJobCodes(this int encoded) => (CharacterJobPreBBType)encoded;
+ }
+}