eq2go/internal/races/integration.go

292 lines
8.1 KiB
Go

package races
import (
"fmt"
)
// RaceAware interface for entities that have race information
type RaceAware interface {
GetRace() int8
SetRace(int8)
}
// EntityWithRace interface extends RaceAware with additional entity properties
type EntityWithRace interface {
RaceAware
GetID() int32
GetName() string
}
// RaceIntegration provides race-related functionality for other systems
type RaceIntegration struct {
races *Races
utils *RaceUtils
}
// NewRaceIntegration creates a new race integration helper
func NewRaceIntegration() *RaceIntegration {
return &RaceIntegration{
races: GetGlobalRaces(),
utils: NewRaceUtils(),
}
}
// ValidateEntityRace validates an entity's race and provides detailed information
func (ri *RaceIntegration) ValidateEntityRace(entity RaceAware) (bool, string, map[string]any) {
raceID := entity.GetRace()
if !ri.races.IsValidRaceID(raceID) {
return false, fmt.Sprintf("Invalid race ID: %d", raceID), nil
}
raceInfo := ri.races.GetRaceInfo(raceID)
return true, "Valid race", raceInfo
}
// ApplyRacialBonuses applies racial stat bonuses to an entity
// This would integrate with the stat system when available
func (ri *RaceIntegration) ApplyRacialBonuses(entity RaceAware, stats map[string]*int16) {
raceID := entity.GetRace()
if !ri.races.IsValidRaceID(raceID) {
return
}
// Get racial modifiers
modifiers := ri.utils.GetRaceStatModifiers(raceID)
// Apply modifiers to stats
for statName, modifier := range modifiers {
if statPtr, exists := stats[statName]; exists && statPtr != nil {
*statPtr += int16(modifier)
}
}
}
// GetEntityRaceInfo returns comprehensive race information for an entity
func (ri *RaceIntegration) GetEntityRaceInfo(entity EntityWithRace) map[string]any {
info := make(map[string]any)
// Basic entity info
info["entity_id"] = entity.GetID()
info["entity_name"] = entity.GetName()
// Race information
raceID := entity.GetRace()
raceInfo := ri.races.GetRaceInfo(raceID)
info["race"] = raceInfo
// Additional race-specific info
info["description"] = ri.utils.GetRaceDescription(raceID)
info["starting_location"] = ri.utils.GetRaceStartingLocation(raceID)
info["stat_modifiers"] = ri.utils.GetRaceStatModifiers(raceID)
info["aliases"] = ri.utils.GetRaceAliases(raceID)
info["compatible_races"] = ri.utils.GetCompatibleRaces(raceID)
return info
}
// ChangeEntityRace changes an entity's race with validation
func (ri *RaceIntegration) ChangeEntityRace(entity RaceAware, newRaceID int8) error {
if !ri.races.IsValidRaceID(newRaceID) {
return fmt.Errorf("invalid race ID: %d", newRaceID)
}
oldRaceID := entity.GetRace()
// Validate the race transition
if valid, reason := ri.utils.ValidateRaceTransition(oldRaceID, newRaceID); !valid {
return fmt.Errorf("race change not allowed: %s", reason)
}
// Perform the race change
entity.SetRace(newRaceID)
return nil
}
// GetRandomRaceForEntity returns a random race appropriate for an entity
func (ri *RaceIntegration) GetRandomRaceForEntity(alignment string) int8 {
return ri.utils.GetRandomRaceByAlignment(alignment)
}
// CheckRaceCompatibility checks if two entities' races are compatible
func (ri *RaceIntegration) CheckRaceCompatibility(entity1, entity2 RaceAware) bool {
race1 := entity1.GetRace()
race2 := entity2.GetRace()
if !ri.races.IsValidRaceID(race1) || !ri.races.IsValidRaceID(race2) {
return false
}
// Same race is always compatible
if race1 == race2 {
return true
}
// Check alignment compatibility
alignment1 := ri.races.GetRaceAlignment(race1)
alignment2 := ri.races.GetRaceAlignment(race2)
// Neutral races are compatible with everyone
if alignment1 == AlignmentNeutral || alignment2 == AlignmentNeutral {
return true
}
// Same alignment races are compatible
return alignment1 == alignment2
}
// FormatEntityRace returns a formatted race name for an entity
func (ri *RaceIntegration) FormatEntityRace(entity RaceAware, format string) string {
raceID := entity.GetRace()
return ri.utils.FormatRaceName(raceID, format)
}
// GetEntityRaceAlignment returns an entity's race alignment
func (ri *RaceIntegration) GetEntityRaceAlignment(entity RaceAware) string {
raceID := entity.GetRace()
return ri.races.GetRaceAlignment(raceID)
}
// IsEntityGoodRace checks if an entity is a good-aligned race
func (ri *RaceIntegration) IsEntityGoodRace(entity RaceAware) bool {
raceID := entity.GetRace()
return ri.races.IsGoodRace(raceID)
}
// IsEntityEvilRace checks if an entity is an evil-aligned race
func (ri *RaceIntegration) IsEntityEvilRace(entity RaceAware) bool {
raceID := entity.GetRace()
return ri.races.IsEvilRace(raceID)
}
// IsEntityNeutralRace checks if an entity is a neutral race
func (ri *RaceIntegration) IsEntityNeutralRace(entity RaceAware) bool {
raceID := entity.GetRace()
return ri.races.IsNeutralRace(raceID)
}
// GetEntitiesByRace filters entities by race
func (ri *RaceIntegration) GetEntitiesByRace(entities []RaceAware, raceID int8) []RaceAware {
result := make([]RaceAware, 0)
for _, entity := range entities {
if entity.GetRace() == raceID {
result = append(result, entity)
}
}
return result
}
// GetEntitiesByAlignment filters entities by race alignment
func (ri *RaceIntegration) GetEntitiesByAlignment(entities []RaceAware, alignment string) []RaceAware {
result := make([]RaceAware, 0)
for _, entity := range entities {
entityAlignment := ri.GetEntityRaceAlignment(entity)
if entityAlignment == alignment {
result = append(result, entity)
}
}
return result
}
// ValidateRaceForClass checks if a race/class combination is valid
func (ri *RaceIntegration) ValidateRaceForClass(raceID, classID int8) (bool, string) {
if !ri.races.IsValidRaceID(raceID) {
return false, "Invalid race"
}
// Use the utility function (which currently allows all combinations)
if ri.utils.ValidateRaceForClass(raceID, classID) {
return true, ""
}
raceName := ri.races.GetRaceNameCase(raceID)
return false, fmt.Sprintf("Race %s cannot be class %d", raceName, classID)
}
// GetRaceStartingStats returns the starting stats for a race
func (ri *RaceIntegration) GetRaceStartingStats(raceID int8) map[string]int16 {
baseStats := map[string]int16{
"strength": 50,
"stamina": 50,
"agility": 50,
"wisdom": 50,
"intelligence": 50,
}
// Apply racial modifiers
modifiers := ri.utils.GetRaceStatModifiers(raceID)
for statName, modifier := range modifiers {
if baseStat, exists := baseStats[statName]; exists {
baseStats[statName] = baseStat + int16(modifier)
}
}
return baseStats
}
// CreateRaceSpecificEntity creates entity data with race-specific properties
func (ri *RaceIntegration) CreateRaceSpecificEntity(raceID int8) map[string]any {
if !ri.races.IsValidRaceID(raceID) {
return nil
}
entityData := make(map[string]any)
// Basic race info
entityData["race_id"] = raceID
entityData["race_name"] = ri.races.GetRaceNameCase(raceID)
entityData["alignment"] = ri.races.GetRaceAlignment(raceID)
// Starting stats
entityData["starting_stats"] = ri.GetRaceStartingStats(raceID)
// Starting location
entityData["starting_location"] = ri.utils.GetRaceStartingLocation(raceID)
// Race description
entityData["description"] = ri.utils.GetRaceDescription(raceID)
return entityData
}
// GetRaceSelectionData returns data for race selection UI
func (ri *RaceIntegration) GetRaceSelectionData() map[string]any {
data := make(map[string]any)
// All available races
allRaces := ri.races.GetAllRaces()
raceList := make([]map[string]any, 0, len(allRaces))
for raceID, friendlyName := range allRaces {
raceData := map[string]any{
"id": raceID,
"name": friendlyName,
"alignment": ri.races.GetRaceAlignment(raceID),
"description": ri.utils.GetRaceDescription(raceID),
"stats": ri.GetRaceStartingStats(raceID),
}
raceList = append(raceList, raceData)
}
data["races"] = raceList
data["statistics"] = ri.utils.GetRaceStatistics()
return data
}
// Global race integration instance
var globalRaceIntegration *RaceIntegration
// GetGlobalRaceIntegration returns the global race integration helper
func GetGlobalRaceIntegration() *RaceIntegration {
if globalRaceIntegration == nil {
globalRaceIntegration = NewRaceIntegration()
}
return globalRaceIntegration
}