finish implementing classes

This commit is contained in:
Sky Johnson 2025-08-22 14:34:27 -05:00
parent 02158041e8
commit 888fd70a6f
8 changed files with 74 additions and 22 deletions

Binary file not shown.

View File

@ -45,6 +45,7 @@ func RightAside(ctx sushi.Ctx) map[string]any {
} }
user := ctx.GetCurrentUser().(*users.User) user := ctx.GetCurrentUser().(*users.User)
data["_class"] = user.Class()
data["_expprog"] = fmt.Sprintf("%.1f", user.ExpProgress()) data["_expprog"] = fmt.Sprintf("%.1f", user.ExpProgress())

View File

@ -6,7 +6,7 @@ import (
"strings" "strings"
) )
type Classes struct { type Class struct {
ID int ID int
Name string Name string
Lore string Lore string
@ -20,8 +20,8 @@ type Classes struct {
RateDEX int RateDEX int
} }
func New() *Classes { func New() *Class {
return &Classes{ return &Class{
BaseHP: 15, BaseHP: 15,
BaseMP: 10, BaseMP: 10,
BaseSTR: 1, BaseSTR: 1,
@ -33,7 +33,7 @@ func New() *Classes {
} }
} }
func (c *Classes) Validate() error { func (c *Class) Validate() error {
if strings.TrimSpace(c.Name) == "" { if strings.TrimSpace(c.Name) == "" {
return fmt.Errorf("class name cannot be empty") return fmt.Errorf("class name cannot be empty")
} }
@ -64,6 +64,30 @@ func (c *Classes) Validate() error {
return nil return nil
} }
func (c *Classes) Delete() error { func (c *Class) Delete() error {
return database.Exec("DELETE FROM classes WHERE id = %d", c.ID) return database.Exec("DELETE FROM classes WHERE id = %d", c.ID)
} }
func (c *Class) Insert() error {
id, err := database.Insert("classes", c, "id")
if err != nil {
return err
}
c.ID = int(id)
return nil
}
func Find(id int) (*Class, error) {
var class Class
err := database.Get(&class, "SELECT * FROM classes WHERE id = %d", id)
if err != nil {
return nil, fmt.Errorf("class with ID %d not found", id)
}
return &class, nil
}
func All() ([]*Class, error) {
var classes []*Class
err := database.Select(&classes, "SELECT * FROM classes ORDER BY id DESC")
return classes, err
}

View File

@ -9,6 +9,7 @@ import (
"dk/internal/database" "dk/internal/database"
"dk/internal/helpers" "dk/internal/helpers"
"dk/internal/helpers/exp" "dk/internal/helpers/exp"
"dk/internal/models/classes"
) )
// User represents a user in the game // User represents a user in the game
@ -138,14 +139,6 @@ func Find(id int) (*User, error) {
return &user, nil return &user, nil
} }
func GetByID(id int) *User {
user, err := Find(id)
if err != nil {
return nil
}
return user
}
func All() ([]*User, error) { func All() ([]*User, error) {
var users []*User var users []*User
err := database.Select(&users, "SELECT * FROM users ORDER BY registered DESC, id DESC") err := database.Select(&users, "SELECT * FROM users ORDER BY registered DESC, id DESC")
@ -328,3 +321,15 @@ func (u *User) ExpProgress() float64 {
return float64(progressExp) / float64(nextLevelExp-currentLevelExp) * 100 return float64(progressExp) / float64(nextLevelExp-currentLevelExp) * 100
} }
func (u *User) Class() *classes.Class {
class, err := classes.Find(u.ClassID)
if err != nil {
class, err = classes.Find(1)
if err != nil {
panic("There should always be at least one class")
}
return class
}
return class
}

View File

@ -2,9 +2,11 @@ package routes
import ( import (
"fmt" "fmt"
"slices"
"strings" "strings"
"dk/internal/components" "dk/internal/components"
"dk/internal/models/classes"
"dk/internal/models/users" "dk/internal/models/users"
sushi "git.sharkk.net/Sharkk/Sushi" sushi "git.sharkk.net/Sharkk/Sushi"
@ -86,10 +88,14 @@ func showRegister(ctx sushi.Ctx) {
} }
sess.Delete("form_data") sess.Delete("form_data")
allClasses, _ := classes.All()
slices.Reverse(allClasses)
components.RenderPage(ctx, "Register", "auth/register.html", map[string]any{ components.RenderPage(ctx, "Register", "auth/register.html", map[string]any{
"username": username, "username": username,
"email": email, "email": email,
"error_message": sess.GetFlashMessage("error"), "error_message": sess.GetFlashMessage("error"),
"classes": allClasses,
}) })
} }
@ -99,6 +105,7 @@ func processRegister(ctx sushi.Ctx) {
email := strings.TrimSpace(ctx.Form("email").String()) email := strings.TrimSpace(ctx.Form("email").String())
userPassword := ctx.Form("password").String() userPassword := ctx.Form("password").String()
confirmPassword := ctx.Form("confirm_password").String() confirmPassword := ctx.Form("confirm_password").String()
classID := ctx.Form("class").Int()
formData := map[string]string{ formData := map[string]string{
"username": username, "username": username,
@ -125,13 +132,25 @@ func processRegister(ctx sushi.Ctx) {
return return
} }
// Ensure class ID exists (should always, unless someone modified the form)
class, err := classes.Find(classID)
if err != nil {
setFlashAndFormData(ctx, "Invalid class selected", formData)
ctx.Redirect("/register")
return
}
// Create new user // Create new user
user := users.New() user := users.New()
user.Username = username user.Username = username
user.Email = email user.Email = email
user.Password = password.HashPassword(userPassword) user.Password = password.HashPassword(userPassword)
user.ClassID = 1
user.Auth = 1 user.Auth = 1
user.ClassID = classID
user.HP, user.MaxHP = class.BaseHP, class.BaseHP
user.MP, user.MaxMP = class.BaseMP, class.BaseMP
user.Strength = class.BaseSTR
user.Dexterity = class.BaseDEX
// Validate before inserting // Validate before inserting
if err := user.Validate(); err != nil { if err := user.Validate(); err != nil {

View File

@ -126,5 +126,9 @@ func start(port string) error {
} }
func getUserByID(userID int) any { func getUserByID(userID int) any {
return users.GetByID(userID) user, err := users.Find(userID)
if err != nil {
panic(fmt.Sprintf("Error finding user ID %d", userID))
}
return user
} }

View File

@ -30,12 +30,11 @@
</div> </div>
<div class="row"> <div class="row">
<label for="charclass">Class</label> <label for="class">Class</label>
<select id="charclass" name="charclass"> <select id="class" name="class">
<option>Choose a Class</option> {for class in classes}
<option value="1">Mage</option> <option value="{class.ID}">{class.Name}</option>
<option value="2">Warrior</option> {/for}
<option value="3">Paladin</option>
</select> </select>
</div> </div>

View File

@ -2,7 +2,7 @@
<div class="title"><img src="/assets/images/button_character.gif" alt="Character" title="Character"></div> <div class="title"><img src="/assets/images/button_character.gif" alt="Character" title="Character"></div>
<ul class="unstyled"> <ul class="unstyled">
<li><b>{user.Username}</b></li> <li><b>{user.Username}</b></li>
<li>Level: {user.Level}</li> <li>Level {user.Level} {_class.Name}</li>
<li>Exp: {user.Exp} ({_expprog}%)</li> <li>Exp: {user.Exp} ({_expprog}%)</li>
<li>Gold: {user.Gold}</li> <li>Gold: {user.Gold}</li>
<li>HP: {user.HP}/{user.MaxHP}</li> <li>HP: {user.HP}/{user.MaxHP}</li>