367 lines
12 KiB
Go
367 lines
12 KiB
Go
package classes
|
|
|
|
import (
|
|
"strings"
|
|
"sync"
|
|
)
|
|
|
|
// Classes manages class information and lookups
|
|
// Converted from C++ Classes class
|
|
type Classes struct {
|
|
// Class name to ID mapping (uppercase keys)
|
|
classMap map[string]int8
|
|
|
|
// ID to display name mapping for friendly names
|
|
displayNameMap map[int8]string
|
|
|
|
// Thread safety
|
|
mutex sync.RWMutex
|
|
}
|
|
|
|
// NewClasses creates a new classes manager with all EQ2 classes
|
|
// Converted from C++ Classes::Classes constructor
|
|
func NewClasses() *Classes {
|
|
classes := &Classes{
|
|
classMap: make(map[string]int8),
|
|
displayNameMap: make(map[int8]string),
|
|
}
|
|
|
|
classes.initializeClasses()
|
|
return classes
|
|
}
|
|
|
|
// initializeClasses sets up all class mappings
|
|
func (c *Classes) initializeClasses() {
|
|
// Initialize class name to ID mappings (from C++ constructor)
|
|
c.classMap[ClassNameCommoner] = ClassCommoner
|
|
c.classMap[ClassNameFighter] = ClassFighter
|
|
c.classMap[ClassNameWarrior] = ClassWarrior
|
|
c.classMap[ClassNameGuardian] = ClassGuardian
|
|
c.classMap[ClassNameBerserker] = ClassBerserker
|
|
c.classMap[ClassNameBrawler] = ClassBrawler
|
|
c.classMap[ClassNameMonk] = ClassMonk
|
|
c.classMap[ClassNameBruiser] = ClassBruiser
|
|
c.classMap[ClassNameCrusader] = ClassCrusader
|
|
c.classMap[ClassNameShadowknight] = ClassShadowknight
|
|
c.classMap[ClassNamePaladin] = ClassPaladin
|
|
c.classMap[ClassNamePriest] = ClassPriest
|
|
c.classMap[ClassNameCleric] = ClassCleric
|
|
c.classMap[ClassNameTemplar] = ClassTemplar
|
|
c.classMap[ClassNameInquisitor] = ClassInquisitor
|
|
c.classMap[ClassNameDruid] = ClassDruid
|
|
c.classMap[ClassNameWarden] = ClassWarden
|
|
c.classMap[ClassNameFury] = ClassFury
|
|
c.classMap[ClassNameShaman] = ClassShaman
|
|
c.classMap[ClassNameMystic] = ClassMystic
|
|
c.classMap[ClassNameDefiler] = ClassDefiler
|
|
c.classMap[ClassNameMage] = ClassMage
|
|
c.classMap[ClassNameSorcerer] = ClassSorcerer
|
|
c.classMap[ClassNameWizard] = ClassWizard
|
|
c.classMap[ClassNameWarlock] = ClassWarlock
|
|
c.classMap[ClassNameEnchanter] = ClassEnchanter
|
|
c.classMap[ClassNameIllusionist] = ClassIllusionist
|
|
c.classMap[ClassNameCoercer] = ClassCoercer
|
|
c.classMap[ClassNameSummoner] = ClassSummoner
|
|
c.classMap[ClassNameConjuror] = ClassConjuror
|
|
c.classMap[ClassNameNecromancer] = ClassNecromancer
|
|
c.classMap[ClassNameScout] = ClassScout
|
|
c.classMap[ClassNameRogue] = ClassRogue
|
|
c.classMap[ClassNameSwashbuckler] = ClassSwashbuckler
|
|
c.classMap[ClassNameBrigand] = ClassBrigand
|
|
c.classMap[ClassNameBard] = ClassBard
|
|
c.classMap[ClassNameTroubador] = ClassTroubador
|
|
c.classMap[ClassNameDirge] = ClassDirge
|
|
c.classMap[ClassNamePredator] = ClassPredator
|
|
c.classMap[ClassNameRanger] = ClassRanger
|
|
c.classMap[ClassNameAssassin] = ClassAssassin
|
|
c.classMap[ClassNameAnimalist] = ClassAnimalist
|
|
c.classMap[ClassNameBeastlord] = ClassBeastlord
|
|
c.classMap[ClassNameShaper] = ClassShaper
|
|
c.classMap[ClassNameChanneler] = ClassChanneler
|
|
c.classMap[ClassNameArtisan] = ClassArtisan
|
|
c.classMap[ClassNameCraftsman] = ClassCraftsman
|
|
c.classMap[ClassNameProvisioner] = ClassProvisioner
|
|
c.classMap[ClassNameWoodworker] = ClassWoodworker
|
|
c.classMap[ClassNameCarpenter] = ClassCarpenter
|
|
c.classMap[ClassNameOutfitter] = ClassOutfitter
|
|
c.classMap[ClassNameArmorer] = ClassArmorer
|
|
c.classMap[ClassNameWeaponsmith] = ClassWeaponsmith
|
|
c.classMap[ClassNameTailor] = ClassTailor
|
|
c.classMap[ClassNameScholar] = ClassScholar
|
|
c.classMap[ClassNameJeweler] = ClassJeweler
|
|
c.classMap[ClassNameSage] = ClassSage
|
|
c.classMap[ClassNameAlchemist] = ClassAlchemist
|
|
|
|
// Initialize display names
|
|
c.displayNameMap[ClassCommoner] = DisplayNameCommoner
|
|
c.displayNameMap[ClassFighter] = DisplayNameFighter
|
|
c.displayNameMap[ClassWarrior] = DisplayNameWarrior
|
|
c.displayNameMap[ClassGuardian] = DisplayNameGuardian
|
|
c.displayNameMap[ClassBerserker] = DisplayNameBerserker
|
|
c.displayNameMap[ClassBrawler] = DisplayNameBrawler
|
|
c.displayNameMap[ClassMonk] = DisplayNameMonk
|
|
c.displayNameMap[ClassBruiser] = DisplayNameBruiser
|
|
c.displayNameMap[ClassCrusader] = DisplayNameCrusader
|
|
c.displayNameMap[ClassShadowknight] = DisplayNameShadowknight
|
|
c.displayNameMap[ClassPaladin] = DisplayNamePaladin
|
|
c.displayNameMap[ClassPriest] = DisplayNamePriest
|
|
c.displayNameMap[ClassCleric] = DisplayNameCleric
|
|
c.displayNameMap[ClassTemplar] = DisplayNameTemplar
|
|
c.displayNameMap[ClassInquisitor] = DisplayNameInquisitor
|
|
c.displayNameMap[ClassDruid] = DisplayNameDruid
|
|
c.displayNameMap[ClassWarden] = DisplayNameWarden
|
|
c.displayNameMap[ClassFury] = DisplayNameFury
|
|
c.displayNameMap[ClassShaman] = DisplayNameShaman
|
|
c.displayNameMap[ClassMystic] = DisplayNameMystic
|
|
c.displayNameMap[ClassDefiler] = DisplayNameDefiler
|
|
c.displayNameMap[ClassMage] = DisplayNameMage
|
|
c.displayNameMap[ClassSorcerer] = DisplayNameSorcerer
|
|
c.displayNameMap[ClassWizard] = DisplayNameWizard
|
|
c.displayNameMap[ClassWarlock] = DisplayNameWarlock
|
|
c.displayNameMap[ClassEnchanter] = DisplayNameEnchanter
|
|
c.displayNameMap[ClassIllusionist] = DisplayNameIllusionist
|
|
c.displayNameMap[ClassCoercer] = DisplayNameCoercer
|
|
c.displayNameMap[ClassSummoner] = DisplayNameSummoner
|
|
c.displayNameMap[ClassConjuror] = DisplayNameConjuror
|
|
c.displayNameMap[ClassNecromancer] = DisplayNameNecromancer
|
|
c.displayNameMap[ClassScout] = DisplayNameScout
|
|
c.displayNameMap[ClassRogue] = DisplayNameRogue
|
|
c.displayNameMap[ClassSwashbuckler] = DisplayNameSwashbuckler
|
|
c.displayNameMap[ClassBrigand] = DisplayNameBrigand
|
|
c.displayNameMap[ClassBard] = DisplayNameBard
|
|
c.displayNameMap[ClassTroubador] = DisplayNameTroubador
|
|
c.displayNameMap[ClassDirge] = DisplayNameDirge
|
|
c.displayNameMap[ClassPredator] = DisplayNamePredator
|
|
c.displayNameMap[ClassRanger] = DisplayNameRanger
|
|
c.displayNameMap[ClassAssassin] = DisplayNameAssassin
|
|
c.displayNameMap[ClassAnimalist] = DisplayNameAnimalist
|
|
c.displayNameMap[ClassBeastlord] = DisplayNameBeastlord
|
|
c.displayNameMap[ClassShaper] = DisplayNameShaper
|
|
c.displayNameMap[ClassChanneler] = DisplayNameChanneler
|
|
c.displayNameMap[ClassArtisan] = DisplayNameArtisan
|
|
c.displayNameMap[ClassCraftsman] = DisplayNameCraftsman
|
|
c.displayNameMap[ClassProvisioner] = DisplayNameProvisioner
|
|
c.displayNameMap[ClassWoodworker] = DisplayNameWoodworker
|
|
c.displayNameMap[ClassCarpenter] = DisplayNameCarpenter
|
|
c.displayNameMap[ClassOutfitter] = DisplayNameOutfitter
|
|
c.displayNameMap[ClassArmorer] = DisplayNameArmorer
|
|
c.displayNameMap[ClassWeaponsmith] = DisplayNameWeaponsmith
|
|
c.displayNameMap[ClassTailor] = DisplayNameTailor
|
|
c.displayNameMap[ClassScholar] = DisplayNameScholar
|
|
c.displayNameMap[ClassJeweler] = DisplayNameJeweler
|
|
c.displayNameMap[ClassSage] = DisplayNameSage
|
|
c.displayNameMap[ClassAlchemist] = DisplayNameAlchemist
|
|
}
|
|
|
|
// GetClassID returns the class ID for a given class name
|
|
// Converted from C++ Classes::GetClassID
|
|
func (c *Classes) GetClassID(name string) int8 {
|
|
c.mutex.RLock()
|
|
defer c.mutex.RUnlock()
|
|
|
|
className := strings.ToUpper(strings.TrimSpace(name))
|
|
if classID, exists := c.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 (c *Classes) GetClassName(classID int8) string {
|
|
c.mutex.RLock()
|
|
defer c.mutex.RUnlock()
|
|
|
|
// Search through class map to find the name
|
|
for name, id := range c.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 (c *Classes) GetClassNameCase(classID int8) string {
|
|
c.mutex.RLock()
|
|
defer c.mutex.RUnlock()
|
|
|
|
if displayName, exists := c.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 (c *Classes) 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 (c *Classes) 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 (c *Classes) GetTSBaseClass(classID int8) int8 {
|
|
if classID+42 >= ClassArtisan {
|
|
return ClassArtisan - 44
|
|
}
|
|
|
|
return classID
|
|
}
|
|
|
|
// GetSecondaryTSBaseClass returns the secondary tradeskill base class ID
|
|
// Converted from C++ Classes::GetSecondaryTSBaseClass
|
|
func (c *Classes) 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 (c *Classes) IsValidClassID(classID int8) bool {
|
|
return classID >= MinClassID && classID <= MaxClassID
|
|
}
|
|
|
|
// GetAllClasses returns all class IDs and their display names
|
|
func (c *Classes) GetAllClasses() map[int8]string {
|
|
c.mutex.RLock()
|
|
defer c.mutex.RUnlock()
|
|
|
|
result := make(map[int8]string)
|
|
for classID, displayName := range c.displayNameMap {
|
|
result[classID] = displayName
|
|
}
|
|
|
|
return result
|
|
}
|
|
|
|
// IsAdventureClass checks if a class is an adventure class
|
|
func (c *Classes) IsAdventureClass(classID int8) bool {
|
|
return classID >= ClassCommoner && classID <= ClassChanneler
|
|
}
|
|
|
|
// IsTradeskillClass checks if a class is a tradeskill class
|
|
func (c *Classes) IsTradeskillClass(classID int8) bool {
|
|
return classID >= ClassArtisan && classID <= ClassAlchemist
|
|
}
|
|
|
|
// GetClassType returns the type of class (adventure, tradeskill, etc.)
|
|
func (c *Classes) GetClassType(classID int8) string {
|
|
if c.IsAdventureClass(classID) {
|
|
return ClassTypeAdventure
|
|
}
|
|
if c.IsTradeskillClass(classID) {
|
|
return ClassTypeTradeskill
|
|
}
|
|
|
|
return ClassTypeSpecial
|
|
}
|
|
|
|
// GetClassCount returns the total number of classes
|
|
func (c *Classes) GetClassCount() int {
|
|
c.mutex.RLock()
|
|
defer c.mutex.RUnlock()
|
|
|
|
return len(c.displayNameMap)
|
|
}
|
|
|
|
// GetClassInfo returns comprehensive information about a class
|
|
func (c *Classes) GetClassInfo(classID int8) map[string]any {
|
|
c.mutex.RLock()
|
|
defer c.mutex.RUnlock()
|
|
|
|
info := make(map[string]any)
|
|
|
|
if !c.IsValidClassID(classID) {
|
|
info["valid"] = false
|
|
return info
|
|
}
|
|
|
|
info["valid"] = true
|
|
info["class_id"] = classID
|
|
info["name"] = c.GetClassName(classID)
|
|
info["display_name"] = c.GetClassNameCase(classID)
|
|
info["base_class"] = c.GetBaseClass(classID)
|
|
info["secondary_base_class"] = c.GetSecondaryBaseClass(classID)
|
|
info["type"] = c.GetClassType(classID)
|
|
info["is_adventure"] = c.IsAdventureClass(classID)
|
|
info["is_tradeskill"] = c.IsTradeskillClass(classID)
|
|
|
|
return info
|
|
}
|
|
|
|
// Global classes instance
|
|
var globalClasses *Classes
|
|
var initClassesOnce sync.Once
|
|
|
|
// GetGlobalClasses returns the global classes manager (singleton)
|
|
func GetGlobalClasses() *Classes {
|
|
initClassesOnce.Do(func() {
|
|
globalClasses = NewClasses()
|
|
})
|
|
return globalClasses
|
|
}
|