353 lines
10 KiB
Go
353 lines
10 KiB
Go
package classes
|
|
|
|
import (
|
|
"fmt"
|
|
)
|
|
|
|
// ClassAware interface for entities that have class information
|
|
type ClassAware interface {
|
|
GetClass() int8
|
|
SetClass(int8)
|
|
}
|
|
|
|
// EntityWithClass interface extends ClassAware with additional entity properties
|
|
type EntityWithClass interface {
|
|
ClassAware
|
|
GetID() int32
|
|
GetName() string
|
|
GetLevel() int8
|
|
}
|
|
|
|
// ClassIntegration provides class-related functionality for other systems
|
|
type ClassIntegration struct {
|
|
classes *Classes
|
|
utils *ClassUtils
|
|
}
|
|
|
|
// NewClassIntegration creates a new class integration helper
|
|
func NewClassIntegration() *ClassIntegration {
|
|
return &ClassIntegration{
|
|
classes: GetGlobalClasses(),
|
|
utils: NewClassUtils(),
|
|
}
|
|
}
|
|
|
|
// ValidateEntityClass validates an entity's class and provides detailed information
|
|
func (ci *ClassIntegration) ValidateEntityClass(entity ClassAware) (bool, string, map[string]interface{}) {
|
|
classID := entity.GetClass()
|
|
|
|
if !ci.classes.IsValidClassID(classID) {
|
|
return false, fmt.Sprintf("Invalid class ID: %d", classID), nil
|
|
}
|
|
|
|
classInfo := ci.classes.GetClassInfo(classID)
|
|
return true, "Valid class", classInfo
|
|
}
|
|
|
|
// GetEntityClassInfo returns comprehensive class information for an entity
|
|
func (ci *ClassIntegration) GetEntityClassInfo(entity EntityWithClass) map[string]interface{} {
|
|
info := make(map[string]interface{})
|
|
|
|
// Basic entity info
|
|
info["entity_id"] = entity.GetID()
|
|
info["entity_name"] = entity.GetName()
|
|
info["entity_level"] = entity.GetLevel()
|
|
|
|
// Class information
|
|
classID := entity.GetClass()
|
|
classInfo := ci.classes.GetClassInfo(classID)
|
|
info["class"] = classInfo
|
|
|
|
// Additional class-specific info
|
|
info["description"] = ci.utils.GetClassDescription(classID)
|
|
info["eq_class_name"] = ci.utils.GetEQClassName(classID, entity.GetLevel())
|
|
info["progression"] = ci.utils.GetClassProgression(classID)
|
|
info["aliases"] = ci.utils.GetClassAliases(classID)
|
|
info["is_base_class"] = ci.utils.IsBaseClass(classID)
|
|
info["is_secondary_base"] = ci.utils.IsSecondaryBaseClass(classID)
|
|
|
|
return info
|
|
}
|
|
|
|
// ChangeEntityClass changes an entity's class with validation
|
|
func (ci *ClassIntegration) ChangeEntityClass(entity ClassAware, newClassID int8) error {
|
|
if !ci.classes.IsValidClassID(newClassID) {
|
|
return fmt.Errorf("invalid class ID: %d", newClassID)
|
|
}
|
|
|
|
oldClassID := entity.GetClass()
|
|
|
|
// Validate the class transition
|
|
if valid, reason := ci.utils.ValidateClassTransition(oldClassID, newClassID); !valid {
|
|
return fmt.Errorf("class change not allowed: %s", reason)
|
|
}
|
|
|
|
// Perform the class change
|
|
entity.SetClass(newClassID)
|
|
|
|
return nil
|
|
}
|
|
|
|
// GetRandomClassForEntity returns a random class appropriate for an entity
|
|
func (ci *ClassIntegration) GetRandomClassForEntity(classType string) int8 {
|
|
return ci.utils.GetRandomClassByType(classType)
|
|
}
|
|
|
|
// CheckClassCompatibility checks if two entities' classes are compatible for grouping
|
|
func (ci *ClassIntegration) CheckClassCompatibility(entity1, entity2 ClassAware) bool {
|
|
class1 := entity1.GetClass()
|
|
class2 := entity2.GetClass()
|
|
|
|
if !ci.classes.IsValidClassID(class1) || !ci.classes.IsValidClassID(class2) {
|
|
return false
|
|
}
|
|
|
|
// Same class is always compatible
|
|
if class1 == class2 {
|
|
return true
|
|
}
|
|
|
|
// Check if they share the same base class (good for grouping)
|
|
// base1 := ci.classes.GetBaseClass(class1)
|
|
// base2 := ci.classes.GetBaseClass(class2)
|
|
|
|
// Different base classes can group together (provides diversity)
|
|
// Same base class provides synergy
|
|
return true // For now, all classes are compatible for grouping
|
|
}
|
|
|
|
// FormatEntityClass returns a formatted class name for an entity
|
|
func (ci *ClassIntegration) FormatEntityClass(entity EntityWithClass, format string) string {
|
|
classID := entity.GetClass()
|
|
level := entity.GetLevel()
|
|
|
|
switch format {
|
|
case "eq":
|
|
return ci.utils.GetEQClassName(classID, level)
|
|
default:
|
|
return ci.utils.FormatClassName(classID, format)
|
|
}
|
|
}
|
|
|
|
// GetEntityBaseClass returns an entity's base class
|
|
func (ci *ClassIntegration) GetEntityBaseClass(entity ClassAware) int8 {
|
|
classID := entity.GetClass()
|
|
return ci.classes.GetBaseClass(classID)
|
|
}
|
|
|
|
// GetEntitySecondaryBaseClass returns an entity's secondary base class
|
|
func (ci *ClassIntegration) GetEntitySecondaryBaseClass(entity ClassAware) int8 {
|
|
classID := entity.GetClass()
|
|
return ci.classes.GetSecondaryBaseClass(classID)
|
|
}
|
|
|
|
// IsEntityAdventureClass checks if an entity has an adventure class
|
|
func (ci *ClassIntegration) IsEntityAdventureClass(entity ClassAware) bool {
|
|
classID := entity.GetClass()
|
|
return ci.classes.IsAdventureClass(classID)
|
|
}
|
|
|
|
// IsEntityTradeskillClass checks if an entity has a tradeskill class
|
|
func (ci *ClassIntegration) IsEntityTradeskillClass(entity ClassAware) bool {
|
|
classID := entity.GetClass()
|
|
return ci.classes.IsTradeskillClass(classID)
|
|
}
|
|
|
|
// GetEntitiesByClass filters entities by class
|
|
func (ci *ClassIntegration) GetEntitiesByClass(entities []ClassAware, classID int8) []ClassAware {
|
|
result := make([]ClassAware, 0)
|
|
|
|
for _, entity := range entities {
|
|
if entity.GetClass() == classID {
|
|
result = append(result, entity)
|
|
}
|
|
}
|
|
|
|
return result
|
|
}
|
|
|
|
// GetEntitiesByBaseClass filters entities by base class
|
|
func (ci *ClassIntegration) GetEntitiesByBaseClass(entities []ClassAware, baseClassID int8) []ClassAware {
|
|
result := make([]ClassAware, 0)
|
|
|
|
for _, entity := range entities {
|
|
if ci.GetEntityBaseClass(entity) == baseClassID {
|
|
result = append(result, entity)
|
|
}
|
|
}
|
|
|
|
return result
|
|
}
|
|
|
|
// GetEntitiesByClassType filters entities by class type (adventure/tradeskill)
|
|
func (ci *ClassIntegration) GetEntitiesByClassType(entities []ClassAware, classType string) []ClassAware {
|
|
result := make([]ClassAware, 0)
|
|
|
|
for _, entity := range entities {
|
|
classID := entity.GetClass()
|
|
if ci.classes.GetClassType(classID) == classType {
|
|
result = append(result, entity)
|
|
}
|
|
}
|
|
|
|
return result
|
|
}
|
|
|
|
// ValidateClassForRace checks if a class/race combination is valid
|
|
func (ci *ClassIntegration) ValidateClassForRace(classID, raceID int8) (bool, string) {
|
|
if !ci.classes.IsValidClassID(classID) {
|
|
return false, "Invalid class"
|
|
}
|
|
|
|
// Use the utility function (which currently allows all combinations)
|
|
if ci.utils.ValidateClassForRace(classID, raceID) {
|
|
return true, ""
|
|
}
|
|
|
|
className := ci.classes.GetClassNameCase(classID)
|
|
return false, fmt.Sprintf("Class %s cannot be race %d", className, raceID)
|
|
}
|
|
|
|
// GetClassStartingStats returns the starting stats for a class
|
|
func (ci *ClassIntegration) GetClassStartingStats(classID int8) map[string]int16 {
|
|
// Base stats that all classes start with
|
|
baseStats := map[string]int16{
|
|
"strength": 50,
|
|
"stamina": 50,
|
|
"agility": 50,
|
|
"wisdom": 50,
|
|
"intelligence": 50,
|
|
}
|
|
|
|
// Apply class modifiers based on class type and role
|
|
switch ci.classes.GetBaseClass(classID) {
|
|
case ClassFighter:
|
|
baseStats["strength"] += 5
|
|
baseStats["stamina"] += 5
|
|
baseStats["intelligence"] -= 3
|
|
case ClassPriest:
|
|
baseStats["wisdom"] += 5
|
|
baseStats["intelligence"] += 3
|
|
baseStats["strength"] -= 2
|
|
case ClassMage:
|
|
baseStats["intelligence"] += 5
|
|
baseStats["wisdom"] += 3
|
|
baseStats["strength"] -= 3
|
|
baseStats["stamina"] -= 2
|
|
case ClassScout:
|
|
baseStats["agility"] += 5
|
|
baseStats["stamina"] += 3
|
|
baseStats["wisdom"] -= 2
|
|
}
|
|
|
|
// Fine-tune for specific secondary base classes
|
|
switch ci.classes.GetSecondaryBaseClass(classID) {
|
|
case ClassWarrior:
|
|
baseStats["strength"] += 2
|
|
baseStats["stamina"] += 2
|
|
case ClassBrawler:
|
|
baseStats["agility"] += 2
|
|
baseStats["strength"] += 1
|
|
case ClassCrusader:
|
|
baseStats["wisdom"] += 2
|
|
baseStats["strength"] += 1
|
|
case ClassCleric:
|
|
baseStats["wisdom"] += 3
|
|
case ClassDruid:
|
|
baseStats["wisdom"] += 2
|
|
baseStats["intelligence"] += 1
|
|
case ClassShaman:
|
|
baseStats["wisdom"] += 2
|
|
baseStats["stamina"] += 1
|
|
case ClassSorcerer:
|
|
baseStats["intelligence"] += 3
|
|
case ClassEnchanter:
|
|
baseStats["intelligence"] += 2
|
|
baseStats["agility"] += 1
|
|
case ClassSummoner:
|
|
baseStats["intelligence"] += 2
|
|
baseStats["wisdom"] += 1
|
|
case ClassRogue:
|
|
baseStats["agility"] += 3
|
|
case ClassBard:
|
|
baseStats["agility"] += 2
|
|
baseStats["intelligence"] += 1
|
|
case ClassPredator:
|
|
baseStats["agility"] += 2
|
|
baseStats["stamina"] += 1
|
|
}
|
|
|
|
return baseStats
|
|
}
|
|
|
|
// CreateClassSpecificEntity creates entity data with class-specific properties
|
|
func (ci *ClassIntegration) CreateClassSpecificEntity(classID int8) map[string]interface{} {
|
|
if !ci.classes.IsValidClassID(classID) {
|
|
return nil
|
|
}
|
|
|
|
entityData := make(map[string]interface{})
|
|
|
|
// Basic class info
|
|
entityData["class_id"] = classID
|
|
entityData["class_name"] = ci.classes.GetClassNameCase(classID)
|
|
entityData["class_type"] = ci.classes.GetClassType(classID)
|
|
|
|
// Starting stats
|
|
entityData["starting_stats"] = ci.GetClassStartingStats(classID)
|
|
|
|
// Class progression
|
|
entityData["progression"] = ci.utils.GetClassProgression(classID)
|
|
|
|
// Class description
|
|
entityData["description"] = ci.utils.GetClassDescription(classID)
|
|
|
|
// Role information
|
|
entityData["base_class"] = ci.classes.GetBaseClass(classID)
|
|
entityData["secondary_base_class"] = ci.classes.GetSecondaryBaseClass(classID)
|
|
|
|
return entityData
|
|
}
|
|
|
|
// GetClassSelectionData returns data for class selection UI
|
|
func (ci *ClassIntegration) GetClassSelectionData() map[string]interface{} {
|
|
data := make(map[string]interface{})
|
|
|
|
// All available adventure classes (exclude tradeskill for character creation)
|
|
allClasses := ci.classes.GetAllClasses()
|
|
adventureClasses := make([]map[string]interface{}, 0)
|
|
|
|
for classID, displayName := range allClasses {
|
|
if ci.classes.IsAdventureClass(classID) {
|
|
classData := map[string]interface{}{
|
|
"id": classID,
|
|
"name": displayName,
|
|
"type": ci.classes.GetClassType(classID),
|
|
"description": ci.utils.GetClassDescription(classID),
|
|
"base_class": ci.classes.GetBaseClass(classID),
|
|
"secondary_base_class": ci.classes.GetSecondaryBaseClass(classID),
|
|
"starting_stats": ci.GetClassStartingStats(classID),
|
|
"progression": ci.utils.GetClassProgression(classID),
|
|
"is_base_class": ci.utils.IsBaseClass(classID),
|
|
}
|
|
adventureClasses = append(adventureClasses, classData)
|
|
}
|
|
}
|
|
|
|
data["adventure_classes"] = adventureClasses
|
|
data["statistics"] = ci.utils.GetClassStatistics()
|
|
|
|
return data
|
|
}
|
|
|
|
// Global class integration instance
|
|
var globalClassIntegration *ClassIntegration
|
|
|
|
// GetGlobalClassIntegration returns the global class integration helper
|
|
func GetGlobalClassIntegration() *ClassIntegration {
|
|
if globalClassIntegration == nil {
|
|
globalClassIntegration = NewClassIntegration()
|
|
}
|
|
return globalClassIntegration
|
|
}
|