359 lines
10 KiB
Go

package classes
import (
"strings"
)
// classMap contains the mapping of class names to IDs
var classMap = map[string]int8{
"COMMONER": ClassCommoner,
"FIGHTER": ClassFighter,
"WARRIOR": ClassWarrior,
"GUARDIAN": ClassGuardian,
"BERSERKER": ClassBerserker,
"BRAWLER": ClassBrawler,
"MONK": ClassMonk,
"BRUISER": ClassBruiser,
"CRUSADER": ClassCrusader,
"SHADOWKNIGHT": ClassShadowknight,
"PALADIN": ClassPaladin,
"PRIEST": ClassPriest,
"CLERIC": ClassCleric,
"TEMPLAR": ClassTemplar,
"INQUISITOR": ClassInquisitor,
"DRUID": ClassDruid,
"WARDEN": ClassWarden,
"FURY": ClassFury,
"SHAMAN": ClassShaman,
"MYSTIC": ClassMystic,
"DEFILER": ClassDefiler,
"MAGE": ClassMage,
"SORCERER": ClassSorcerer,
"WIZARD": ClassWizard,
"WARLOCK": ClassWarlock,
"ENCHANTER": ClassEnchanter,
"ILLUSIONIST": ClassIllusionist,
"COERCER": ClassCoercer,
"SUMMONER": ClassSummoner,
"CONJUROR": ClassConjuror,
"NECROMANCER": ClassNecromancer,
"SCOUT": ClassScout,
"ROGUE": ClassRogue,
"SWASHBUCKLER": ClassSwashbuckler,
"BRIGAND": ClassBrigand,
"BARD": ClassBard,
"TROUBADOR": ClassTroubador,
"DIRGE": ClassDirge,
"PREDATOR": ClassPredator,
"RANGER": ClassRanger,
"ASSASSIN": ClassAssassin,
"ANIMALIST": ClassAnimalist,
"BEASTLORD": ClassBeastlord,
"SHAPER": ClassShaper,
"CHANNELER": ClassChanneler,
"ARTISAN": ClassArtisan,
"CRAFTSMAN": ClassCraftsman,
"PROVISIONER": ClassProvisioner,
"WOODWORKER": ClassWoodworker,
"CARPENTER": ClassCarpenter,
"OUTFITTER": ClassOutfitter,
"ARMORER": ClassArmorer,
"WEAPONSMITH": ClassWeaponsmith,
"TAILOR": ClassTailor,
"SCHOLAR": ClassScholar,
"JEWELER": ClassJeweler,
"SAGE": ClassSage,
"ALCHEMIST": ClassAlchemist,
}
// displayNameMap contains the display names for each class ID
var displayNameMap = map[int8]string{
ClassCommoner: "Commoner",
ClassFighter: "Fighter",
ClassWarrior: "Warrior",
ClassGuardian: "Guardian",
ClassBerserker: "Berserker",
ClassBrawler: "Brawler",
ClassMonk: "Monk",
ClassBruiser: "Bruiser",
ClassCrusader: "Crusader",
ClassShadowknight: "Shadowknight",
ClassPaladin: "Paladin",
ClassPriest: "Priest",
ClassCleric: "Cleric",
ClassTemplar: "Templar",
ClassInquisitor: "Inquisitor",
ClassDruid: "Druid",
ClassWarden: "Warden",
ClassFury: "Fury",
ClassShaman: "Shaman",
ClassMystic: "Mystic",
ClassDefiler: "Defiler",
ClassMage: "Mage",
ClassSorcerer: "Sorcerer",
ClassWizard: "Wizard",
ClassWarlock: "Warlock",
ClassEnchanter: "Enchanter",
ClassIllusionist: "Illusionist",
ClassCoercer: "Coercer",
ClassSummoner: "Summoner",
ClassConjuror: "Conjuror",
ClassNecromancer: "Necromancer",
ClassScout: "Scout",
ClassRogue: "Rogue",
ClassSwashbuckler: "Swashbuckler",
ClassBrigand: "Brigand",
ClassBard: "Bard",
ClassTroubador: "Troubador",
ClassDirge: "Dirge",
ClassPredator: "Predator",
ClassRanger: "Ranger",
ClassAssassin: "Assassin",
ClassAnimalist: "Animalist",
ClassBeastlord: "Beastlord",
ClassShaper: "Shaper",
ClassChanneler: "Channeler",
ClassArtisan: "Artisan",
ClassCraftsman: "Craftsman",
ClassProvisioner: "Provisioner",
ClassWoodworker: "Woodworker",
ClassCarpenter: "Carpenter",
ClassOutfitter: "Outfitter",
ClassArmorer: "Armorer",
ClassWeaponsmith: "Weaponsmith",
ClassTailor: "Tailor",
ClassScholar: "Scholar",
ClassJeweler: "Jeweler",
ClassSage: "Sage",
ClassAlchemist: "Alchemist",
}
// GetClassID returns the class ID for a given class name
// Converted from C++ Classes::GetClassID
func GetClassID(name string) int8 {
className := strings.ToUpper(strings.TrimSpace(name))
if classID, exists := classMap[className]; exists {
return classID
}
return -1 // Invalid class
}
// GetClassName returns the uppercase class name for a given ID
// Converted from C++ Classes::GetClassName
func GetClassName(classID int8) string {
// Search through class map to find the name
for name, id := range classMap {
if id == classID {
return name
}
}
return "" // Invalid class ID
}
// GetClassNameCase returns the friendly display name for a given class ID
// Converted from C++ Classes::GetClassNameCase
func GetClassNameCase(classID int8) string {
if displayName, exists := displayNameMap[classID]; exists {
return displayName
}
return "" // Invalid class ID
}
// GetBaseClass returns the base class ID for a given class
// Converted from C++ Classes::GetBaseClass
func GetBaseClass(classID int8) int8 {
if classID >= ClassWarrior && classID <= ClassPaladin {
return ClassFighter
}
if (classID >= ClassCleric && classID <= ClassDefiler) || (classID == ClassShaper || classID == ClassChanneler) {
return ClassPriest
}
if classID >= ClassSorcerer && classID <= ClassNecromancer {
return ClassMage
}
if classID >= ClassRogue && classID <= ClassBeastlord {
return ClassScout
}
return ClassCommoner // Default for unknown classes
}
// GetSecondaryBaseClass returns the secondary base class ID for specialized classes
// Converted from C++ Classes::GetSecondaryBaseClass
func GetSecondaryBaseClass(classID int8) int8 {
switch classID {
case ClassGuardian, ClassBerserker:
return ClassWarrior
case ClassMonk, ClassBruiser:
return ClassBrawler
case ClassShadowknight, ClassPaladin:
return ClassCrusader
case ClassTemplar, ClassInquisitor:
return ClassCleric
case ClassWarden, ClassFury:
return ClassDruid
case ClassMystic, ClassDefiler:
return ClassShaman
case ClassWizard, ClassWarlock:
return ClassSorcerer
case ClassIllusionist, ClassCoercer:
return ClassEnchanter
case ClassConjuror, ClassNecromancer:
return ClassSummoner
case ClassSwashbuckler, ClassBrigand:
return ClassRogue
case ClassTroubador, ClassDirge:
return ClassBard
case ClassRanger, ClassAssassin:
return ClassPredator
case ClassBeastlord:
return ClassAnimalist
case ClassChanneler:
return ClassShaper
}
return ClassCommoner // Default for unknown classes
}
// GetTSBaseClass returns the tradeskill base class ID
// Converted from C++ Classes::GetTSBaseClass
func GetTSBaseClass(classID int8) int8 {
// This function maps tradeskill class IDs to their base tradeskill progression levels
// The C++ code uses offset of 42 between adventure and tradeskill class systems
if classID+42 >= ClassArtisan {
return ClassArtisan - 44 // Returns 1 (base artisan level)
}
return classID // For non-tradeskill classes, return as-is
}
// GetSecondaryTSBaseClass returns the secondary tradeskill base class ID
// Converted from C++ Classes::GetSecondaryTSBaseClass
func GetSecondaryTSBaseClass(classID int8) int8 {
ret := classID + 42
if ret == ClassArtisan {
return ClassArtisan - 44
} else if ret >= ClassCraftsman && ret < ClassOutfitter {
return ClassCraftsman - 44
} else if ret >= ClassOutfitter && ret < ClassScholar {
return ClassOutfitter - 44
} else if ret >= ClassScholar {
return ClassScholar - 44
}
return classID
}
// IsValidClassID checks if a class ID is valid
func IsValidClassID(classID int8) bool {
return classID >= MinClassID && classID <= MaxClassID
}
// IsAdventureClass checks if a class is an adventure class
func IsAdventureClass(classID int8) bool {
return classID >= ClassCommoner && classID <= ClassChanneler
}
// IsTradeskillClass checks if a class is a tradeskill class
func IsTradeskillClass(classID int8) bool {
return classID >= ClassArtisan && classID <= ClassAlchemist
}
// GetClassType returns the type of class (adventure, tradeskill, etc.)
func GetClassType(classID int8) string {
if IsAdventureClass(classID) {
return ClassTypeAdventure
}
if IsTradeskillClass(classID) {
return ClassTypeTradeskill
}
return ClassTypeSpecial
}
// GetAllClasses returns all class IDs and their display names
func GetAllClasses() map[int8]string {
result := make(map[int8]string)
for classID, displayName := range displayNameMap {
result[classID] = displayName
}
return result
}
// GetClassInfo returns comprehensive information about a class
func GetClassInfo(classID int8) map[string]any {
info := make(map[string]any)
if !IsValidClassID(classID) {
info["valid"] = false
return info
}
info["valid"] = true
info["class_id"] = classID
info["name"] = GetClassName(classID)
info["display_name"] = GetClassNameCase(classID)
info["base_class"] = GetBaseClass(classID)
info["secondary_base_class"] = GetSecondaryBaseClass(classID)
info["type"] = GetClassType(classID)
info["is_adventure"] = IsAdventureClass(classID)
info["is_tradeskill"] = IsTradeskillClass(classID)
return info
}
// GetClassHierarchy returns the full class hierarchy for a given class
func GetClassHierarchy(classID int8) []int8 {
if !IsValidClassID(classID) {
return nil
}
hierarchy := []int8{classID}
// Add secondary base class if it exists
secondary := GetSecondaryBaseClass(classID)
if secondary != ClassCommoner && secondary != classID {
hierarchy = append(hierarchy, secondary)
}
// Add base class
base := GetBaseClass(classID)
if base != ClassCommoner && base != classID {
// Check if base is already in hierarchy (from secondary)
found := false
for _, id := range hierarchy {
if id == base {
found = true
break
}
}
if !found {
hierarchy = append(hierarchy, base)
}
}
// Always add Commoner as the root
if classID != ClassCommoner {
hierarchy = append(hierarchy, ClassCommoner)
}
return hierarchy
}
// IsSameArchetype checks if two classes share the same base archetype
func IsSameArchetype(classID1, classID2 int8) bool {
if !IsValidClassID(classID1) || !IsValidClassID(classID2) {
return false
}
return GetBaseClass(classID1) == GetBaseClass(classID2)
}
// GetArchetypeClasses returns all classes of a given archetype
func GetArchetypeClasses(archetypeID int8) []int8 {
var classes []int8
for classID := MinClassID; classID <= MaxClassID; classID++ {
if GetBaseClass(classID) == archetypeID {
classes = append(classes, classID)
}
}
return classes
}