package main import ( "log" "math/rand" "time" "gorm.io/driver/sqlite" "gorm.io/gorm" ) type DataBase struct { DB *gorm.DB } func OpenDB(filename string) (*DataBase, error) { db, err := gorm.Open(sqlite.Open(filename), &gorm.Config{}) if err != nil { return nil, err } DB := &DataBase{DB: db} err = DB.DB.AutoMigrate(&ShipModel{}, &Ship{}, &User{}) return DB, err } func (db *DataBase) Close() error { sqldb, err := db.DB.DB() if err != nil { return err } return sqldb.Close() } type Model struct { ID uint64 `gorm:"primaryKey"` CreatedAt time.Time UpdatedAt time.Time } type ShipModel struct { Model Name string `gorm:"unique"` BaseHull uint64 // Armor Plates bump this, typically by 4 points per plate BaseShields uint64 // Capacitors bump this, typically by 3 points per cap // Buying costs and limits Purchaseable bool // Determines if the ShipModel can be bought RequiredXp uint64 // Preventing Users from purchasing very powerful ships without doing any combat CostMetal uint64 // Normally selling a ship in metal is 40%, if it can't be bought however it's 60% CostCircuit uint64 // Noormally selling a ship in circuits is 50%, if it can't be bought however it's 75% // Limits MaxGuns uint64 MaxRocketLaunchers uint64 MaxArmorPlates uint64 MaxRepairBays uint64 MaxShieldCapacitors uint64 MaxShieldGenerators uint64 MaxEngines uint64 // Starting values, assigned to Ship once bought/created StartingGuns uint64 StartingRocketLaunchers uint64 StartingArmorPlates uint64 StartingRepairBays uint64 StartingRepairDrones uint64 StartingShieldCapacitors uint64 StartingShieldGenerators uint64 StartingEngines uint64 } func (db *DataBase) SaveShipModel(model *ShipModel) error { result := db.DB.Save(model) return result.Error } func (db *DataBase) GetShipModelById(id uint64) *ShipModel { var model *ShipModel result := db.DB.Find(model, id) if result.Error != nil { log.Printf("DataBase.GetShipModelById(id=%d) > %v", id, result.Error) return nil } return model } func (db *DataBase) GetShipModelByName(name string) *ShipModel { var model *ShipModel result := db.DB.Find(model, ShipModel{Name: name}) if result.Error != nil { log.Printf("DataBase.GetShipModelByName(name='%s') > %v", name, result.Error) return nil } return model } type Ship struct { Model UserID uint64 // Who owns this ship ShipModel uint64 // ShipModel.ID, Limits of the ship HullPoints uint64 // Current HP ShieldPoints uint64 // Current SP Guns uint64 // Guns deal 0-2 damage per gun RocketLaunchers uint64 // A "special" attack, Each rocket deals 0-10 damage per rocket ArmorPlates uint64 // Bumps HP up RepairBays uint64 // Allows you to hold Repair Drones to repair HP in combat RepairDrones uint64 // Each repair drone can repair 0-1 HP per turn in combat (but if you take damage there is a chance to loose a drone instead) ShieldCapacitors uint64 // Bumps SP up, each Capacitor also adds a resistance to the amount of SP regained in combat ShieldGenerators uint64 // Regains SP of 0-1 SP per turn, it is calculated together then applies a resistance rating based on the number of capacitors installed Engines uint64 // Affects dodge and escape chances, "mass" is the number of installed parts } func (s *Ship) Mass() uint64 { m := uint64(0) m += s.Guns m += s.RocketLaunchers m += (s.ArmorPlates * 2) // Armor is heavy m += s.RepairBays m += s.ShieldCapacitors // Shields are light m -= s.Engines return m } func (s *Ship) FireGuns() uint64 { total := 0 for range make([]byte, s.Guns) { total += rand.Intn(3) } return uint64(total) } func (s *Ship) DroneRepair() uint64 { total := 0 for range make([]byte, s.RepairDrones) { total += rand.Intn(2) } return uint64(total) } func (db *DataBase) SaveShip(ship *Ship) error { result := db.DB.Save(ship) return result.Error } type User struct { Model Name string `gorm:"unique"` // Nickname, commonly used RealName string `gorm:"UniqueIndex,colate:nocase"` // BBS Realname used to identify User, typically not used/displayed // Currency-likes Xp uint64 // How experienced the User is, determines how tough random opponents will be Metal uint64 // Common Currency Circuit uint64 // Rare Currency MetalBanked uint64 // Metal stored in the Bank, so it won't get lost CircuitBanked uint64 // Circuit stored in the Bank, so it won't get lost Rockets uint64 // Not a currency, a weapon, but there is technically no limit except the number that can be fired per "special" attack Fuel uint64 // Not a currency, amount of fights left (A normal fight will consume 2, a fight where you run away is 3, and a fight where you died consumes all but 1 and kicks you off) // Stuff Ship *Ship // Use UpdatedAt as LastOn } func (db *DataBase) SaveUser(u *User) error { result := db.DB.Save(u) return result.Error } func (db *DataBase) GetUserByName(name string) *User { var user *User result := db.DB.Find(user, User{RealName: name}) if result.Error != nil { log.Printf("DataBase.GetUserByName(name='%s') > %v", name, result.Error) return nil } return user }