241 lines
6.1 KiB
Go

package factions
import (
"fmt"
"eq2emu/internal/database"
)
// Faction represents a single faction with its properties and embedded database operations
type Faction struct {
ID int32 // Faction ID
Name string // Faction name
Type string // Faction type/category
Description string // Faction description
NegativeChange int16 // Amount faction decreases by default
PositiveChange int16 // Amount faction increases by default
DefaultValue int32 // Default faction value for new characters
db *database.Database
isNew bool
}
// New creates a new faction with the given database connection
func New(db *database.Database) *Faction {
return &Faction{
db: db,
isNew: true,
}
}
// Load loads a faction from the database by ID
func Load(db *database.Database, id int32) (*Faction, error) {
faction := &Faction{
db: db,
isNew: false,
}
query := `SELECT id, name, type, description, negative_change, positive_change, default_value FROM factions WHERE id = ?`
row := db.QueryRow(query, id)
err := row.Scan(&faction.ID, &faction.Name, &faction.Type, &faction.Description,
&faction.NegativeChange, &faction.PositiveChange, &faction.DefaultValue)
if err != nil {
return nil, fmt.Errorf("failed to load faction %d: %w", id, err)
}
return faction, nil
}
// NewFaction creates a new faction with the given parameters (legacy helper)
func NewFaction(id int32, name, factionType, description string) *Faction {
return &Faction{
ID: id,
Name: name,
Type: factionType,
Description: description,
NegativeChange: 0,
PositiveChange: 0,
DefaultValue: 0,
isNew: true,
}
}
// GetID returns the faction ID
func (f *Faction) GetID() int32 {
return f.ID
}
// GetName returns the faction name
func (f *Faction) GetName() string {
return f.Name
}
// GetType returns the faction type
func (f *Faction) GetType() string {
return f.Type
}
// GetDescription returns the faction description
func (f *Faction) GetDescription() string {
return f.Description
}
// GetNegativeChange returns the default decrease amount
func (f *Faction) GetNegativeChange() int16 {
return f.NegativeChange
}
// GetPositiveChange returns the default increase amount
func (f *Faction) GetPositiveChange() int16 {
return f.PositiveChange
}
// GetDefaultValue returns the default faction value
func (f *Faction) GetDefaultValue() int32 {
return f.DefaultValue
}
// SetNegativeChange sets the default decrease amount
func (f *Faction) SetNegativeChange(amount int16) {
f.NegativeChange = amount
}
// SetPositiveChange sets the default increase amount
func (f *Faction) SetPositiveChange(amount int16) {
f.PositiveChange = amount
}
// SetDefaultValue sets the default faction value
func (f *Faction) SetDefaultValue(value int32) {
f.DefaultValue = value
}
// Save saves the faction to the database
func (f *Faction) Save() error {
if f.db == nil {
return fmt.Errorf("no database connection available")
}
if f.isNew {
return f.insert()
}
return f.update()
}
// Delete deletes the faction from the database
func (f *Faction) Delete() error {
if f.db == nil {
return fmt.Errorf("no database connection available")
}
if f.isNew {
return fmt.Errorf("cannot delete unsaved faction")
}
_, err := f.db.Exec(`DELETE FROM factions WHERE id = ?`, f.ID)
if err != nil {
return fmt.Errorf("failed to delete faction %d: %w", f.ID, err)
}
return nil
}
// Reload reloads the faction from the database
func (f *Faction) Reload() error {
if f.db == nil {
return fmt.Errorf("no database connection available")
}
if f.isNew {
return fmt.Errorf("cannot reload unsaved faction")
}
reloaded, err := Load(f.db, f.ID)
if err != nil {
return err
}
// Copy reloaded data
f.Name = reloaded.Name
f.Type = reloaded.Type
f.Description = reloaded.Description
f.NegativeChange = reloaded.NegativeChange
f.PositiveChange = reloaded.PositiveChange
f.DefaultValue = reloaded.DefaultValue
return nil
}
// IsNew returns true if this is a new faction not yet saved to database
func (f *Faction) IsNew() bool {
return f.isNew
}
// Clone creates a copy of the faction
func (f *Faction) Clone() *Faction {
return &Faction{
ID: f.ID,
Name: f.Name,
Type: f.Type,
Description: f.Description,
NegativeChange: f.NegativeChange,
PositiveChange: f.PositiveChange,
DefaultValue: f.DefaultValue,
db: f.db,
isNew: true, // Clone is always new
}
}
// insert inserts a new faction into the database
func (f *Faction) insert() error {
query := `INSERT INTO factions (id, name, type, description, negative_change, positive_change, default_value) VALUES (?, ?, ?, ?, ?, ?, ?)`
_, err := f.db.Exec(query, f.ID, f.Name, f.Type, f.Description, f.NegativeChange, f.PositiveChange, f.DefaultValue)
if err != nil {
return fmt.Errorf("failed to insert faction %d: %w", f.ID, err)
}
f.isNew = false
return nil
}
// update updates an existing faction in the database
func (f *Faction) update() error {
query := `UPDATE factions SET name = ?, type = ?, description = ?, negative_change = ?, positive_change = ?, default_value = ? WHERE id = ?`
result, err := f.db.Exec(query, f.Name, f.Type, f.Description, f.NegativeChange, f.PositiveChange, f.DefaultValue, f.ID)
if err != nil {
return fmt.Errorf("failed to update faction %d: %w", f.ID, err)
}
rowsAffected, err := result.RowsAffected()
if err != nil {
return fmt.Errorf("failed to get rows affected: %w", err)
}
if rowsAffected == 0 {
return fmt.Errorf("faction %d not found for update", f.ID)
}
return nil
}
// IsValid returns true if the faction has valid data
func (f *Faction) IsValid() bool {
return f.ID > 0 && len(f.Name) > 0
}
// IsSpecialFaction returns true if this is a special faction (ID <= 10)
func (f *Faction) IsSpecialFaction() bool {
return f.ID <= SpecialFactionIDMax
}
// CanIncrease returns true if this faction can be increased
func (f *Faction) CanIncrease() bool {
return !f.IsSpecialFaction() && f.PositiveChange != 0
}
// CanDecrease returns true if this faction can be decreased
func (f *Faction) CanDecrease() bool {
return !f.IsSpecialFaction() && f.NegativeChange != 0
}