291 lines
8.2 KiB
Go
291 lines
8.2 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]interface{}) {
|
|
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]interface{} {
|
|
info := make(map[string]interface{})
|
|
|
|
// 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]interface{} {
|
|
if !ri.races.IsValidRaceID(raceID) {
|
|
return nil
|
|
}
|
|
|
|
entityData := make(map[string]interface{})
|
|
|
|
// 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]interface{} {
|
|
data := make(map[string]interface{})
|
|
|
|
// All available races
|
|
allRaces := ri.races.GetAllRaces()
|
|
raceList := make([]map[string]interface{}, 0, len(allRaces))
|
|
|
|
for raceID, friendlyName := range allRaces {
|
|
raceData := map[string]interface{}{
|
|
"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
|
|
} |