285 lines
5.7 KiB
Go

package items
import (
"fmt"
"dk/internal/database"
)
// Item represents an item in the game
type Item struct {
ID int `db:"id"`
Type int `db:"type"`
Name string `db:"name"`
Lore string `db:"lore"`
Value int `db:"value"`
Attack int `db:"attack"`
Defense int `db:"defense"`
Strength int `db:"strength"`
Dexterity int `db:"dexterity"`
MaxHP int `db:"max_hp"`
MaxMP int `db:"max_mp"`
ExpBonus int `db:"exp_bonus"`
GoldBonus int `db:"gold_bonus"`
Special string `db:"special"`
}
// ItemType constants for item types
const (
TypeWeapon = 1
TypeArmor = 2
TypeShield = 3
TypeAccessory = 4
)
// New creates a new Item with sensible defaults
func New() *Item {
return &Item{
Type: TypeWeapon,
Name: "",
Lore: "",
Value: 0,
Attack: 0,
Defense: 0,
Strength: 0,
Dexterity: 0,
MaxHP: 0,
MaxMP: 0,
ExpBonus: 0,
GoldBonus: 0,
Special: "",
}
}
// Validate checks if item has valid values
func (i *Item) Validate() error {
if i.Name == "" {
return fmt.Errorf("item name cannot be empty")
}
if i.Type < TypeWeapon || i.Type > TypeAccessory {
return fmt.Errorf("invalid item type: %d", i.Type)
}
if i.Value < 0 {
return fmt.Errorf("item value cannot be negative")
}
return nil
}
// CRUD operations
func (i *Item) Delete() error {
return database.Exec("DELETE FROM items WHERE id = %d", i.ID)
}
func (i *Item) Insert() error {
id, err := database.Insert("items", i, "id")
if err != nil {
return err
}
i.ID = int(id)
return nil
}
func (i *Item) Update() error {
fields := map[string]any{
"type": i.Type,
"name": i.Name,
"lore": i.Lore,
"value": i.Value,
"attack": i.Attack,
"defense": i.Defense,
"strength": i.Strength,
"dexterity": i.Dexterity,
"max_hp": i.MaxHP,
"max_mp": i.MaxMP,
"exp_bonus": i.ExpBonus,
"gold_bonus": i.GoldBonus,
"special": i.Special,
}
return database.Update("items", fields, "id", i.ID)
}
// Query functions
func Find(id int) (*Item, error) {
var item Item
err := database.Get(&item, "SELECT * FROM items WHERE id = %d", id)
if err != nil {
return nil, fmt.Errorf("item with ID %d not found", id)
}
return &item, nil
}
func All() ([]*Item, error) {
var items []*Item
err := database.Select(&items, "SELECT * FROM items ORDER BY type ASC, value ASC, id ASC")
return items, err
}
func ByType(itemType int) ([]*Item, error) {
var items []*Item
err := database.Select(&items, "SELECT * FROM items WHERE type = %d ORDER BY value ASC, id ASC", itemType)
return items, err
}
func ByValueRange(minValue, maxValue int) ([]*Item, error) {
var items []*Item
err := database.Select(&items, "SELECT * FROM items WHERE value >= %d AND value <= %d ORDER BY value ASC, id ASC", minValue, maxValue)
return items, err
}
func ByName(name string) (*Item, error) {
var item Item
err := database.Get(&item, "SELECT * FROM items WHERE name = %s COLLATE NOCASE", name)
if err != nil {
return nil, fmt.Errorf("item with name '%s' not found", name)
}
return &item, nil
}
// Helper methods
func (i *Item) IsWeapon() bool {
return i.Type == TypeWeapon
}
func (i *Item) IsArmor() bool {
return i.Type == TypeArmor
}
func (i *Item) IsShield() bool {
return i.Type == TypeShield
}
func (i *Item) IsAccessory() bool {
return i.Type == TypeAccessory
}
func (i *Item) TypeName() string {
switch i.Type {
case TypeWeapon:
return "Weapon"
case TypeArmor:
return "Armor"
case TypeShield:
return "Shield"
case TypeAccessory:
return "Accessory"
default:
return "Unknown"
}
}
func (i *Item) HasSpecial() bool {
return i.Special != ""
}
func (i *Item) IsEquippable() bool {
return i.Type >= TypeWeapon && i.Type <= TypeShield
}
func (i *Item) IsSlottable() bool {
return i.Type == TypeAccessory
}
func (i *Item) HasLore() bool {
return i.Lore != ""
}
// Stat bonus methods
func (i *Item) HasAttackBonus() bool {
return i.Attack != 0
}
func (i *Item) HasDefenseBonus() bool {
return i.Defense != 0
}
func (i *Item) HasStrengthBonus() bool {
return i.Strength != 0
}
func (i *Item) HasDexterityBonus() bool {
return i.Dexterity != 0
}
func (i *Item) HasHPBonus() bool {
return i.MaxHP != 0
}
func (i *Item) HasMPBonus() bool {
return i.MaxMP != 0
}
func (i *Item) HasExpBonus() bool {
return i.ExpBonus != 0
}
func (i *Item) HasGoldBonus() bool {
return i.GoldBonus != 0
}
// Returns true if the item provides any stat bonuses
func (i *Item) HasStatBonuses() bool {
return i.Attack != 0 || i.Defense != 0 || i.Strength != 0 ||
i.Dexterity != 0 || i.MaxHP != 0 || i.MaxMP != 0 ||
i.ExpBonus != 0 || i.GoldBonus != 0
}
func (i *Item) GetStatBonuses() map[string]int {
bonuses := make(map[string]int)
if i.Attack != 0 {
bonuses["Attack"] = i.Attack
}
if i.Defense != 0 {
bonuses["Defense"] = i.Defense
}
if i.Strength != 0 {
bonuses["Strength"] = i.Strength
}
if i.Dexterity != 0 {
bonuses["Dexterity"] = i.Dexterity
}
if i.MaxHP != 0 {
bonuses["Max HP"] = i.MaxHP
}
if i.MaxMP != 0 {
bonuses["Max MP"] = i.MaxMP
}
if i.ExpBonus != 0 {
bonuses["Exp Bonus"] = i.ExpBonus
}
if i.GoldBonus != 0 {
bonuses["Gold Bonus"] = i.GoldBonus
}
return bonuses
}
// GetPrimaryStatBonus returns the main stat bonus for the item type
func (i *Item) GetPrimaryStatBonus() int {
switch i.Type {
case TypeWeapon:
return i.Attack
case TypeArmor, TypeShield:
return i.Defense
case TypeAccessory:
// For accessories, return the highest stat bonus
max := 0
stats := []int{i.Attack, i.Defense, i.Strength, i.Dexterity, i.MaxHP, i.MaxMP}
for _, stat := range stats {
if abs(stat) > abs(max) {
max = stat
}
}
return max
default:
return 0
}
}
func abs(x int) int {
if x < 0 {
return -x
}
return x
}