create drops package
This commit is contained in:
parent
0210e7dd28
commit
ace43e1053
147
internal/drops/doc.go
Normal file
147
internal/drops/doc.go
Normal file
@ -0,0 +1,147 @@
|
||||
/*
|
||||
Package drops is the active record implementation for drop items in the game.
|
||||
|
||||
# Basic Usage
|
||||
|
||||
To retrieve a drop by ID:
|
||||
|
||||
drop, err := drops.Find(db, 1)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
fmt.Printf("Found drop: %s (level: %d)\n", drop.Name, drop.Level)
|
||||
|
||||
To get all drops:
|
||||
|
||||
allDrops, err := drops.All(db)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
for _, drop := range allDrops {
|
||||
fmt.Printf("Drop: %s\n", drop.Name)
|
||||
}
|
||||
|
||||
To filter drops by level (items available at or below a level):
|
||||
|
||||
availableDrops, err := drops.ByLevel(db, 25)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
To filter drops by type:
|
||||
|
||||
consumables, err := drops.ByType(db, drops.TypeConsumable)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
# Creating Drops with Builder Pattern
|
||||
|
||||
The package provides a fluent builder interface for creating new drops:
|
||||
|
||||
drop, err := drops.NewBuilder(db).
|
||||
WithName("Ruby").
|
||||
WithLevel(50).
|
||||
WithType(drops.TypeConsumable).
|
||||
WithAtt("maxhp,150").
|
||||
Create()
|
||||
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
fmt.Printf("Created drop with ID: %d\n", drop.ID)
|
||||
|
||||
# Updating Drops
|
||||
|
||||
Drops can be modified and saved back to the database:
|
||||
|
||||
drop, _ := drops.Find(db, 1)
|
||||
drop.Name = "Enhanced Life Pebble"
|
||||
drop.Level = 5
|
||||
drop.Att = "maxhp,15"
|
||||
|
||||
err := drop.Save()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
# Deleting Drops
|
||||
|
||||
Drops can be removed from the database:
|
||||
|
||||
drop, _ := drops.Find(db, 1)
|
||||
err := drop.Delete()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
# Drop Types
|
||||
|
||||
The package defines drop type constants:
|
||||
|
||||
drops.TypeConsumable = 1 // Consumable items like potions, gems, etc.
|
||||
|
||||
Helper methods are available to check drop types:
|
||||
|
||||
if drop.IsConsumable() {
|
||||
fmt.Println("This is a consumable item")
|
||||
}
|
||||
fmt.Printf("Drop type: %s\n", drop.TypeName())
|
||||
|
||||
# Database Schema
|
||||
|
||||
The drops table has the following structure:
|
||||
|
||||
CREATE TABLE drops (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
name TEXT NOT NULL DEFAULT '',
|
||||
level INTEGER NOT NULL DEFAULT 0,
|
||||
type INTEGER NOT NULL DEFAULT 0,
|
||||
att TEXT NOT NULL DEFAULT ''
|
||||
)
|
||||
|
||||
Where:
|
||||
- id: Unique identifier
|
||||
- name: Display name of the drop
|
||||
- level: Minimum monster level to find this drop
|
||||
- type: Drop type (1=consumable)
|
||||
- att: Comma-separated attributes in "key,value,key,value" format
|
||||
|
||||
# Drop Attributes
|
||||
|
||||
The att field contains attribute bonuses in comma-separated "key,value" pairs:
|
||||
|
||||
"maxhp,10" // +10 max health
|
||||
"maxmp,25" // +25 max mana
|
||||
"strength,50" // +50 strength
|
||||
"defensepower,25" // +25 defense power
|
||||
"expbonus,10" // +10% experience bonus
|
||||
"goldbonus,5" // +5% gold bonus
|
||||
|
||||
Many drops have multiple attributes in a single field:
|
||||
|
||||
drop.Att = "maxhp,25,strength,25" // +25 max health AND +25 strength
|
||||
drop.Att = "maxmp,-50,strength,100" // -50 max mana AND +100 strength
|
||||
|
||||
The attributes are parsed as alternating key-value pairs separated by commas.
|
||||
|
||||
# Level Requirements
|
||||
|
||||
Drops have level requirements that determine when players can use them:
|
||||
|
||||
// Get all drops available from level 10 and above monsters
|
||||
availableDrops, err := drops.ByLevel(db, 10)
|
||||
|
||||
// This returns drops with level <= 10
|
||||
for _, drop := range availableDrops {
|
||||
fmt.Printf("%s (level %d)\n", drop.Name, drop.Level)
|
||||
}
|
||||
|
||||
# Error Handling
|
||||
|
||||
All functions return appropriate errors for common failure cases:
|
||||
- Drop not found (Find returns error for non-existent IDs)
|
||||
- Database connection issues
|
||||
- Invalid operations (e.g., saving/deleting drops without IDs)
|
||||
*/
|
||||
package drops
|
240
internal/drops/drops.go
Normal file
240
internal/drops/drops.go
Normal file
@ -0,0 +1,240 @@
|
||||
package drops
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"dk/internal/database"
|
||||
|
||||
"zombiezen.com/go/sqlite"
|
||||
)
|
||||
|
||||
// Drop represents a drop item in the database
|
||||
type Drop struct {
|
||||
ID int `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Level int `json:"level"`
|
||||
Type int `json:"type"`
|
||||
Att string `json:"att"`
|
||||
|
||||
db *database.DB
|
||||
}
|
||||
|
||||
// DropType constants for drop types
|
||||
const (
|
||||
TypeConsumable = 1
|
||||
)
|
||||
|
||||
// Find retrieves a drop by ID
|
||||
func Find(db *database.DB, id int) (*Drop, error) {
|
||||
drop := &Drop{db: db}
|
||||
|
||||
query := "SELECT id, name, level, type, att FROM drops WHERE id = ?"
|
||||
err := db.Query(query, func(stmt *sqlite.Stmt) error {
|
||||
drop.ID = stmt.ColumnInt(0)
|
||||
drop.Name = stmt.ColumnText(1)
|
||||
drop.Level = stmt.ColumnInt(2)
|
||||
drop.Type = stmt.ColumnInt(3)
|
||||
drop.Att = stmt.ColumnText(4)
|
||||
return nil
|
||||
}, id)
|
||||
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to find drop: %w", err)
|
||||
}
|
||||
|
||||
if drop.ID == 0 {
|
||||
return nil, fmt.Errorf("drop with ID %d not found", id)
|
||||
}
|
||||
|
||||
return drop, nil
|
||||
}
|
||||
|
||||
// All retrieves all drops
|
||||
func All(db *database.DB) ([]*Drop, error) {
|
||||
var drops []*Drop
|
||||
|
||||
query := "SELECT id, name, level, type, att FROM drops ORDER BY id"
|
||||
err := db.Query(query, func(stmt *sqlite.Stmt) error {
|
||||
drop := &Drop{
|
||||
ID: stmt.ColumnInt(0),
|
||||
Name: stmt.ColumnText(1),
|
||||
Level: stmt.ColumnInt(2),
|
||||
Type: stmt.ColumnInt(3),
|
||||
Att: stmt.ColumnText(4),
|
||||
db: db,
|
||||
}
|
||||
drops = append(drops, drop)
|
||||
return nil
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to retrieve all drops: %w", err)
|
||||
}
|
||||
|
||||
return drops, nil
|
||||
}
|
||||
|
||||
// ByLevel retrieves drops by minimum level requirement
|
||||
func ByLevel(db *database.DB, minLevel int) ([]*Drop, error) {
|
||||
var drops []*Drop
|
||||
|
||||
query := "SELECT id, name, level, type, att FROM drops WHERE level <= ? ORDER BY level, id"
|
||||
err := db.Query(query, func(stmt *sqlite.Stmt) error {
|
||||
drop := &Drop{
|
||||
ID: stmt.ColumnInt(0),
|
||||
Name: stmt.ColumnText(1),
|
||||
Level: stmt.ColumnInt(2),
|
||||
Type: stmt.ColumnInt(3),
|
||||
Att: stmt.ColumnText(4),
|
||||
db: db,
|
||||
}
|
||||
drops = append(drops, drop)
|
||||
return nil
|
||||
}, minLevel)
|
||||
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to retrieve drops by level: %w", err)
|
||||
}
|
||||
|
||||
return drops, nil
|
||||
}
|
||||
|
||||
// ByType retrieves drops by type
|
||||
func ByType(db *database.DB, dropType int) ([]*Drop, error) {
|
||||
var drops []*Drop
|
||||
|
||||
query := "SELECT id, name, level, type, att FROM drops WHERE type = ? ORDER BY level, id"
|
||||
err := db.Query(query, func(stmt *sqlite.Stmt) error {
|
||||
drop := &Drop{
|
||||
ID: stmt.ColumnInt(0),
|
||||
Name: stmt.ColumnText(1),
|
||||
Level: stmt.ColumnInt(2),
|
||||
Type: stmt.ColumnInt(3),
|
||||
Att: stmt.ColumnText(4),
|
||||
db: db,
|
||||
}
|
||||
drops = append(drops, drop)
|
||||
return nil
|
||||
}, dropType)
|
||||
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to retrieve drops by type: %w", err)
|
||||
}
|
||||
|
||||
return drops, nil
|
||||
}
|
||||
|
||||
// Builder provides a fluent interface for creating drops
|
||||
type Builder struct {
|
||||
drop *Drop
|
||||
db *database.DB
|
||||
}
|
||||
|
||||
// NewBuilder creates a new drop builder
|
||||
func NewBuilder(db *database.DB) *Builder {
|
||||
return &Builder{
|
||||
drop: &Drop{db: db},
|
||||
db: db,
|
||||
}
|
||||
}
|
||||
|
||||
// WithName sets the drop name
|
||||
func (b *Builder) WithName(name string) *Builder {
|
||||
b.drop.Name = name
|
||||
return b
|
||||
}
|
||||
|
||||
// WithLevel sets the drop level requirement
|
||||
func (b *Builder) WithLevel(level int) *Builder {
|
||||
b.drop.Level = level
|
||||
return b
|
||||
}
|
||||
|
||||
// WithType sets the drop type
|
||||
func (b *Builder) WithType(dropType int) *Builder {
|
||||
b.drop.Type = dropType
|
||||
return b
|
||||
}
|
||||
|
||||
// WithAtt sets the attributes
|
||||
func (b *Builder) WithAtt(att string) *Builder {
|
||||
b.drop.Att = att
|
||||
return b
|
||||
}
|
||||
|
||||
// Create saves the drop to the database and returns it
|
||||
func (b *Builder) Create() (*Drop, error) {
|
||||
// Use a transaction to ensure we can get the ID
|
||||
var drop *Drop
|
||||
err := b.db.Transaction(func(tx *database.Tx) error {
|
||||
query := `INSERT INTO drops (name, level, type, att)
|
||||
VALUES (?, ?, ?, ?)`
|
||||
|
||||
if err := tx.Exec(query, b.drop.Name, b.drop.Level, b.drop.Type, b.drop.Att); err != nil {
|
||||
return fmt.Errorf("failed to insert drop: %w", err)
|
||||
}
|
||||
|
||||
// Get the last inserted ID within the same transaction
|
||||
var lastID int
|
||||
err := tx.Query("SELECT last_insert_rowid()", func(stmt *sqlite.Stmt) error {
|
||||
lastID = stmt.ColumnInt(0)
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get last insert ID: %w", err)
|
||||
}
|
||||
|
||||
// Create the drop with the ID
|
||||
drop = &Drop{
|
||||
ID: lastID,
|
||||
Name: b.drop.Name,
|
||||
Level: b.drop.Level,
|
||||
Type: b.drop.Type,
|
||||
Att: b.drop.Att,
|
||||
db: b.db,
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create drop: %w", err)
|
||||
}
|
||||
|
||||
return drop, nil
|
||||
}
|
||||
|
||||
// Save updates an existing drop in the database
|
||||
func (d *Drop) Save() error {
|
||||
if d.ID == 0 {
|
||||
return fmt.Errorf("cannot save drop without ID")
|
||||
}
|
||||
|
||||
query := `UPDATE drops SET name = ?, level = ?, type = ?, att = ? WHERE id = ?`
|
||||
return d.db.Exec(query, d.Name, d.Level, d.Type, d.Att, d.ID)
|
||||
}
|
||||
|
||||
// Delete removes the drop from the database
|
||||
func (d *Drop) Delete() error {
|
||||
if d.ID == 0 {
|
||||
return fmt.Errorf("cannot delete drop without ID")
|
||||
}
|
||||
|
||||
query := "DELETE FROM drops WHERE id = ?"
|
||||
return d.db.Exec(query, d.ID)
|
||||
}
|
||||
|
||||
// IsConsumable returns true if the drop is a consumable item
|
||||
func (d *Drop) IsConsumable() bool {
|
||||
return d.Type == TypeConsumable
|
||||
}
|
||||
|
||||
// TypeName returns the string representation of the drop type
|
||||
func (d *Drop) TypeName() string {
|
||||
switch d.Type {
|
||||
case TypeConsumable:
|
||||
return "Consumable"
|
||||
default:
|
||||
return "Unknown"
|
||||
}
|
||||
}
|
270
internal/drops/drops_test.go
Normal file
270
internal/drops/drops_test.go
Normal file
@ -0,0 +1,270 @@
|
||||
package drops
|
||||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"dk/internal/database"
|
||||
)
|
||||
|
||||
func setupTestDB(t *testing.T) *database.DB {
|
||||
testDB := "test_drops.db"
|
||||
t.Cleanup(func() {
|
||||
os.Remove(testDB)
|
||||
})
|
||||
|
||||
db, err := database.Open(testDB)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to open test database: %v", err)
|
||||
}
|
||||
|
||||
// Create drops table
|
||||
createTable := `CREATE TABLE drops (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
name TEXT NOT NULL DEFAULT '',
|
||||
level INTEGER NOT NULL DEFAULT 0,
|
||||
type INTEGER NOT NULL DEFAULT 0,
|
||||
att TEXT NOT NULL DEFAULT ''
|
||||
)`
|
||||
|
||||
if err := db.Exec(createTable); err != nil {
|
||||
t.Fatalf("Failed to create drops table: %v", err)
|
||||
}
|
||||
|
||||
// Insert test data
|
||||
testDrops := `INSERT INTO drops (name, level, type, att) VALUES
|
||||
('Life Pebble', 1, 1, 'maxhp,10'),
|
||||
('Magic Stone', 10, 1, 'maxmp,25'),
|
||||
('Dragon''s Scale', 10, 1, 'defensepower,25'),
|
||||
('Angel''s Joy', 25, 1, 'maxhp,25,strength,25')`
|
||||
|
||||
if err := db.Exec(testDrops); err != nil {
|
||||
t.Fatalf("Failed to insert test drops: %v", err)
|
||||
}
|
||||
|
||||
return db
|
||||
}
|
||||
|
||||
func TestFind(t *testing.T) {
|
||||
db := setupTestDB(t)
|
||||
defer db.Close()
|
||||
|
||||
// Test finding existing drop
|
||||
drop, err := Find(db, 1)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to find drop: %v", err)
|
||||
}
|
||||
|
||||
if drop.ID != 1 {
|
||||
t.Errorf("Expected ID 1, got %d", drop.ID)
|
||||
}
|
||||
if drop.Name != "Life Pebble" {
|
||||
t.Errorf("Expected name 'Life Pebble', got '%s'", drop.Name)
|
||||
}
|
||||
if drop.Level != 1 {
|
||||
t.Errorf("Expected level 1, got %d", drop.Level)
|
||||
}
|
||||
if drop.Type != TypeConsumable {
|
||||
t.Errorf("Expected type %d, got %d", TypeConsumable, drop.Type)
|
||||
}
|
||||
if drop.Att != "maxhp,10" {
|
||||
t.Errorf("Expected att1 'maxhp,10', got '%s'", drop.Att)
|
||||
}
|
||||
|
||||
// Test finding non-existent drop
|
||||
_, err = Find(db, 999)
|
||||
if err == nil {
|
||||
t.Error("Expected error when finding non-existent drop")
|
||||
}
|
||||
}
|
||||
|
||||
func TestAll(t *testing.T) {
|
||||
db := setupTestDB(t)
|
||||
defer db.Close()
|
||||
|
||||
drops, err := All(db)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to get all drops: %v", err)
|
||||
}
|
||||
|
||||
if len(drops) != 4 {
|
||||
t.Errorf("Expected 4 drops, got %d", len(drops))
|
||||
}
|
||||
|
||||
// Check first drop
|
||||
if drops[0].Name != "Life Pebble" {
|
||||
t.Errorf("Expected first drop to be 'Life Pebble', got '%s'", drops[0].Name)
|
||||
}
|
||||
}
|
||||
|
||||
func TestByLevel(t *testing.T) {
|
||||
db := setupTestDB(t)
|
||||
defer db.Close()
|
||||
|
||||
// Test drops available at level 10
|
||||
drops, err := ByLevel(db, 10)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to get drops by level: %v", err)
|
||||
}
|
||||
|
||||
if len(drops) != 3 {
|
||||
t.Errorf("Expected 3 drops at level 10, got %d", len(drops))
|
||||
}
|
||||
|
||||
// Verify they are ordered by level
|
||||
if drops[0].Level != 1 {
|
||||
t.Errorf("Expected first drop level 1, got %d", drops[0].Level)
|
||||
}
|
||||
if drops[1].Level != 10 {
|
||||
t.Errorf("Expected second drop level 10, got %d", drops[1].Level)
|
||||
}
|
||||
|
||||
// Test drops available at level 1
|
||||
lowLevelDrops, err := ByLevel(db, 1)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to get drops by level 1: %v", err)
|
||||
}
|
||||
|
||||
if len(lowLevelDrops) != 1 {
|
||||
t.Errorf("Expected 1 drop at level 1, got %d", len(lowLevelDrops))
|
||||
}
|
||||
}
|
||||
|
||||
func TestByType(t *testing.T) {
|
||||
db := setupTestDB(t)
|
||||
defer db.Close()
|
||||
|
||||
consumables, err := ByType(db, TypeConsumable)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to get consumable drops: %v", err)
|
||||
}
|
||||
|
||||
if len(consumables) != 4 {
|
||||
t.Errorf("Expected 4 consumable drops, got %d", len(consumables))
|
||||
}
|
||||
|
||||
// Verify they are ordered by level, then ID
|
||||
if consumables[0].Level > consumables[1].Level {
|
||||
t.Error("Expected drops to be ordered by level")
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuilder(t *testing.T) {
|
||||
db := setupTestDB(t)
|
||||
defer db.Close()
|
||||
|
||||
// Create new drop using builder
|
||||
drop, err := NewBuilder(db).
|
||||
WithName("Test Drop").
|
||||
WithLevel(15).
|
||||
WithType(TypeConsumable).
|
||||
WithAtt("strength,20,dexterity,15").
|
||||
Create()
|
||||
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create drop with builder: %v", err)
|
||||
}
|
||||
|
||||
if drop.ID == 0 {
|
||||
t.Error("Expected non-zero ID after creation")
|
||||
}
|
||||
if drop.Name != "Test Drop" {
|
||||
t.Errorf("Expected name 'Test Drop', got '%s'", drop.Name)
|
||||
}
|
||||
if drop.Level != 15 {
|
||||
t.Errorf("Expected level 15, got %d", drop.Level)
|
||||
}
|
||||
if drop.Type != TypeConsumable {
|
||||
t.Errorf("Expected type %d, got %d", TypeConsumable, drop.Type)
|
||||
}
|
||||
if drop.Att != "strength,20,dexterity,15" {
|
||||
t.Errorf("Expected att 'strength,20,dexterity,15', got '%s'", drop.Att)
|
||||
}
|
||||
|
||||
// Verify it was saved to database
|
||||
foundDrop, err := Find(db, drop.ID)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to find created drop: %v", err)
|
||||
}
|
||||
|
||||
if foundDrop.Name != "Test Drop" {
|
||||
t.Errorf("Created drop not found in database")
|
||||
}
|
||||
}
|
||||
|
||||
func TestSave(t *testing.T) {
|
||||
db := setupTestDB(t)
|
||||
defer db.Close()
|
||||
|
||||
drop, err := Find(db, 1)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to find drop: %v", err)
|
||||
}
|
||||
|
||||
// Modify drop
|
||||
drop.Name = "Updated Life Pebble"
|
||||
drop.Level = 5
|
||||
drop.Att = "maxhp,15"
|
||||
|
||||
// Save changes
|
||||
err = drop.Save()
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to save drop: %v", err)
|
||||
}
|
||||
|
||||
// Verify changes were saved
|
||||
updatedDrop, err := Find(db, 1)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to find updated drop: %v", err)
|
||||
}
|
||||
|
||||
if updatedDrop.Name != "Updated Life Pebble" {
|
||||
t.Errorf("Expected updated name 'Updated Life Pebble', got '%s'", updatedDrop.Name)
|
||||
}
|
||||
if updatedDrop.Level != 5 {
|
||||
t.Errorf("Expected updated level 5, got %d", updatedDrop.Level)
|
||||
}
|
||||
if updatedDrop.Att != "maxhp,15" {
|
||||
t.Errorf("Expected updated att 'maxhp,15', got '%s'", updatedDrop.Att)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDelete(t *testing.T) {
|
||||
db := setupTestDB(t)
|
||||
defer db.Close()
|
||||
|
||||
drop, err := Find(db, 1)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to find drop: %v", err)
|
||||
}
|
||||
|
||||
// Delete drop
|
||||
err = drop.Delete()
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to delete drop: %v", err)
|
||||
}
|
||||
|
||||
// Verify drop was deleted
|
||||
_, err = Find(db, 1)
|
||||
if err == nil {
|
||||
t.Error("Expected error when finding deleted drop")
|
||||
}
|
||||
}
|
||||
|
||||
func TestDropMethods(t *testing.T) {
|
||||
db := setupTestDB(t)
|
||||
defer db.Close()
|
||||
|
||||
pebble, _ := Find(db, 1)
|
||||
|
||||
// Test IsConsumable
|
||||
if !pebble.IsConsumable() {
|
||||
t.Error("Expected pebble to be consumable")
|
||||
}
|
||||
|
||||
// Test TypeName
|
||||
if pebble.TypeName() != "Consumable" {
|
||||
t.Errorf("Expected pebble type name 'Consumable', got '%s'", pebble.TypeName())
|
||||
}
|
||||
|
||||
}
|
@ -78,8 +78,7 @@ func createTables(db *database.DB) error {
|
||||
name TEXT NOT NULL DEFAULT '',
|
||||
level INTEGER NOT NULL DEFAULT 0,
|
||||
type INTEGER NOT NULL DEFAULT 0,
|
||||
att1 TEXT NOT NULL DEFAULT '',
|
||||
att2 TEXT NOT NULL DEFAULT ''
|
||||
att TEXT NOT NULL DEFAULT ''
|
||||
)`},
|
||||
{"forum", `CREATE TABLE forum (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
@ -204,38 +203,38 @@ func populateData(db *database.DB) error {
|
||||
fmt.Println("✓ control table populated")
|
||||
|
||||
dropsSQL := `INSERT INTO drops VALUES
|
||||
(1, 'Life Pebble', 1, 1, 'maxhp,10', ''),
|
||||
(2, 'Life Stone', 10, 1, 'maxhp,25', ''),
|
||||
(3, 'Life Rock', 25, 1, 'maxhp,50', ''),
|
||||
(4, 'Magic Pebble', 1, 1, 'maxmp,10', ''),
|
||||
(5, 'Magic Stone', 10, 1, 'maxmp,25', ''),
|
||||
(6, 'Magic Rock', 25, 1, 'maxmp,50', ''),
|
||||
(7, 'Dragon''s Scale', 10, 1, 'defensepower,25', ''),
|
||||
(8, 'Dragon''s Plate', 30, 1, 'defensepower,50', ''),
|
||||
(9, 'Dragon''s Claw', 10, 1, 'attackpower,25', ''),
|
||||
(10, 'Dragon''s Tooth', 30, 1, 'attackpower,50', ''),
|
||||
(11, 'Dragon''s Tear', 35, 1, 'strength,50', ''),
|
||||
(12, 'Dragon''s Wing', 35, 1, 'dexterity,50', ''),
|
||||
(13, 'Demon''s Sin', 35, 1, 'maxhp,-50', 'strength,50'),
|
||||
(14, 'Demon''s Fall', 35, 1, 'maxmp,-50', 'strength,50'),
|
||||
(15, 'Demon''s Lie', 45, 1, 'maxhp,-100', 'strength,100'),
|
||||
(16, 'Demon''s Hate', 45, 1, 'maxmp,-100', 'strength,100'),
|
||||
(17, 'Angel''s Joy', 25, 1, 'maxhp,25', 'strength,25'),
|
||||
(18, 'Angel''s Rise', 30, 1, 'maxhp,50', 'strength,50'),
|
||||
(19, 'Angel''s Truth', 35, 1, 'maxhp,75', 'strength,75'),
|
||||
(20, 'Angel''s Love', 40, 1, 'maxhp,100', 'strength,100'),
|
||||
(21, 'Seraph''s Joy', 25, 1, 'maxmp,25', 'dexterity,25'),
|
||||
(22, 'Seraph''s Rise', 30, 1, 'maxmp,50', 'dexterity,50'),
|
||||
(23, 'Seraph''s Truth', 35, 1, 'maxmp,75', 'dexterity,75'),
|
||||
(24, 'Seraph''s Love', 40, 1, 'maxmp,100', 'dexterity,100'),
|
||||
(25, 'Ruby', 50, 1, 'maxhp,150', ''),
|
||||
(26, 'Pearl', 50, 1, 'maxmp,150', ''),
|
||||
(27, 'Emerald', 50, 1, 'strength,150', ''),
|
||||
(28, 'Topaz', 50, 1, 'dexterity,150', ''),
|
||||
(29, 'Obsidian', 50, 1, 'attackpower,150', ''),
|
||||
(30, 'Diamond', 50, 1, 'defensepower,150', ''),
|
||||
(31, 'Memory Drop', 5, 1, 'expbonus,10', ''),
|
||||
(32, 'Fortune Drop', 5, 1, 'goldbonus,10', '')`
|
||||
(1, 'Life Pebble', 1, 1, 'maxhp,10'),
|
||||
(2, 'Life Stone', 10, 1, 'maxhp,25'),
|
||||
(3, 'Life Rock', 25, 1, 'maxhp,50'),
|
||||
(4, 'Magic Pebble', 1, 1, 'maxmp,10'),
|
||||
(5, 'Magic Stone', 10, 1, 'maxmp,25'),
|
||||
(6, 'Magic Rock', 25, 1, 'maxmp,50'),
|
||||
(7, 'Dragon''s Scale', 10, 1, 'defensepower,25'),
|
||||
(8, 'Dragon''s Plate', 30, 1, 'defensepower,50'),
|
||||
(9, 'Dragon''s Claw', 10, 1, 'attackpower,25'),
|
||||
(10, 'Dragon''s Tooth', 30, 1, 'attackpower,50'),
|
||||
(11, 'Dragon''s Tear', 35, 1, 'strength,50'),
|
||||
(12, 'Dragon''s Wing', 35, 1, 'dexterity,50'),
|
||||
(13, 'Demon''s Sin', 35, 1, 'maxhp,-50,strength,50'),
|
||||
(14, 'Demon''s Fall', 35, 1, 'maxmp,-50,strength,50'),
|
||||
(15, 'Demon''s Lie', 45, 1, 'maxhp,-100,strength,100'),
|
||||
(16, 'Demon''s Hate', 45, 1, 'maxmp,-100,strength,100'),
|
||||
(17, 'Angel''s Joy', 25, 1, 'maxhp,25,strength,25'),
|
||||
(18, 'Angel''s Rise', 30, 1, 'maxhp,50,strength,50'),
|
||||
(19, 'Angel''s Truth', 35, 1, 'maxhp,75,strength,75'),
|
||||
(20, 'Angel''s Love', 40, 1, 'maxhp,100,strength,100'),
|
||||
(21, 'Seraph''s Joy', 25, 1, 'maxmp,25,dexterity,25'),
|
||||
(22, 'Seraph''s Rise', 30, 1, 'maxmp,50,dexterity,50'),
|
||||
(23, 'Seraph''s Truth', 35, 1, 'maxmp,75,dexterity,75'),
|
||||
(24, 'Seraph''s Love', 40, 1, 'maxmp,100,dexterity,100'),
|
||||
(25, 'Ruby', 50, 1, 'maxhp,150'),
|
||||
(26, 'Pearl', 50, 1, 'maxmp,150'),
|
||||
(27, 'Emerald', 50, 1, 'strength,150'),
|
||||
(28, 'Topaz', 50, 1, 'dexterity,150'),
|
||||
(29, 'Obsidian', 50, 1, 'attackpower,150'),
|
||||
(30, 'Diamond', 50, 1, 'defensepower,150'),
|
||||
(31, 'Memory Drop', 5, 1, 'expbonus,10'),
|
||||
(32, 'Fortune Drop', 5, 1, 'goldbonus,10')`
|
||||
if err := db.Exec(dropsSQL); err != nil {
|
||||
return fmt.Errorf("failed to populate drops table: %w", err)
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user