move actions from town handlers to town actions file

This commit is contained in:
Sky Johnson 2025-08-29 07:14:29 -05:00
parent 4288619520
commit 78d0e5debe
2 changed files with 98 additions and 87 deletions

92
internal/actions/town.go Normal file
View File

@ -0,0 +1,92 @@
package actions
import (
"dk/internal/database"
"dk/internal/helpers"
"dk/internal/models/items"
"dk/internal/models/towns"
"dk/internal/models/users"
"fmt"
"maps"
)
// RestAtInn handles the inn resting logic
func RestAtInn(user *users.User, town *towns.Town) error {
if user.Gold < town.InnCost {
return fmt.Errorf("you can't afford to stay here tonight")
}
return database.Transaction(func() error {
return database.Update("users", map[string]any{
"gold": user.Gold - town.InnCost,
"hp": user.MaxHP,
"mp": user.MaxMP,
"tp": user.MaxTP,
}, "id", user.ID)
})
}
// BuyShopItem handles purchasing an item from a town shop
func BuyShopItem(user *users.User, town *towns.Town, itemID int) error {
// Validate item exists in shop
if !town.HasShopItem(itemID) {
return fmt.Errorf("the item doesn't exist in this shop")
}
// Get item details
item, err := items.Find(itemID)
if err != nil {
return fmt.Errorf("error purchasing item: %v", err)
}
// Check user has enough gold
if user.Gold < item.Value {
return fmt.Errorf("you don't have enough gold to buy %s", item.Name)
}
// Get equipment updates from existing actions
equipUpdates, err := UserEquipItem(user, item)
if err != nil {
return fmt.Errorf("cannot equip item: %v", err)
}
// Execute purchase transaction
return database.Transaction(func() error {
// Start with gold deduction
updates := map[string]any{
"gold": user.Gold - item.Value,
}
// Add equipment updates
maps.Copy(updates, equipUpdates)
return database.Update("users", updates, "id", user.ID)
})
}
// BuyTownMap handles purchasing a town map
func BuyTownMap(user *users.User, townID int) error {
// Get the town being mapped
mappedTown, err := towns.Find(townID)
if err != nil {
return fmt.Errorf("error purchasing map: %v", err)
}
// Check user has enough gold
if user.Gold < mappedTown.MapCost {
return fmt.Errorf("you don't have enough gold to buy the map to %s", mappedTown.Name)
}
// Get current town IDs and add new one
townIDs := user.GetTownIDs()
townIDs = append(townIDs, townID)
newTownsString := helpers.IntsToString(townIDs)
// Execute purchase transaction
return database.Transaction(func() error {
return database.Update("users", map[string]any{
"gold": user.Gold - mappedTown.MapCost,
"towns": newTownsString,
}, "id", user.ID)
})
}

View File

@ -3,9 +3,6 @@ package routes
import (
"dk/internal/actions"
"dk/internal/components"
"dk/internal/database"
"dk/internal/helpers"
"dk/internal/models/items"
"dk/internal/models/towns"
"dk/internal/models/users"
"fmt"
@ -95,22 +92,9 @@ func rest(ctx sushi.Ctx) {
town := ctx.UserValue("town").(*towns.Town)
user := ctx.GetCurrentUser().(*users.User)
if user.Gold < town.InnCost {
sess.SetFlash("error", "You can't afford to stay here tonight.")
ctx.Redirect("/town/inn")
return
}
err := database.Transaction(func() error {
return database.Update("users", map[string]any{
"gold": user.Gold - town.InnCost,
"hp": user.MaxHP,
"mp": user.MaxMP,
"tp": user.MaxTP,
}, "id", user.ID)
})
err := actions.RestAtInn(user, town)
if err != nil {
sess.SetFlash("error", "Failed to rest at inn.")
sess.SetFlash("error", err.Error())
ctx.Redirect("/town/inn")
return
}
@ -144,54 +128,13 @@ func showShop(ctx sushi.Ctx) {
func buyItem(ctx sushi.Ctx) {
sess := ctx.GetCurrentSession()
id := ctx.Param("id").Int()
town := ctx.UserValue("town").(*towns.Town)
if !town.HasShopItem(id) {
sess.SetFlash("error", "The item doesn't exist in this shop.")
ctx.Redirect("/town/shop")
return
}
item, err := items.Find(id)
if err != nil {
sess.SetFlash("error", "Error purchasing item; "+err.Error())
ctx.Redirect("/town/shop")
return
}
user := ctx.GetCurrentUser().(*users.User)
if user.Gold < item.Value {
sess.SetFlash("error", "You don't have enough gold to buy "+item.Name)
ctx.Redirect("/town/shop")
return
}
// Get equipment updates from actions
equipUpdates, err := actions.UserEquipItem(user, item)
err := actions.BuyShopItem(user, town, id)
if err != nil {
sess.SetFlash("error", "Cannot equip item: "+err.Error())
ctx.Redirect("/town/shop")
return
}
err = database.Transaction(func() error {
// Start with gold deduction
updates := map[string]any{
"gold": user.Gold - item.Value,
}
// Add equipment updates
for field, value := range equipUpdates {
updates[field] = value
}
return database.Update("users", updates, "id", user.ID)
})
if err != nil {
sess.SetFlash("error", "Failed to purchase item.")
sess.SetFlash("error", err.Error())
ctx.Redirect("/town/shop")
return
}
@ -224,36 +167,12 @@ func showMaps(ctx sushi.Ctx) {
func buyMap(ctx sushi.Ctx) {
sess := ctx.GetCurrentSession()
id := ctx.Param("id").Int()
mapped, err := towns.Find(id)
if err != nil {
sess.SetFlash("error", "Error purchasing map; "+err.Error())
ctx.Redirect("/town/maps")
return
}
user := ctx.GetCurrentUser().(*users.User)
if user.Gold < mapped.MapCost {
sess.SetFlash("error", "You don't have enough gold to buy the map to "+mapped.Name)
ctx.Redirect("/town/maps")
return
}
townIDs := user.GetTownIDs()
townIDs = append(townIDs, id)
newTownsString := helpers.IntsToString(townIDs)
err = database.Transaction(func() error {
return database.Update("users", map[string]any{
"gold": user.Gold - mapped.MapCost,
"towns": newTownsString,
}, "id", user.ID)
})
err := actions.BuyTownMap(user, id)
if err != nil {
sess.SetFlash("error", "Failed to purchase map.")
sess.SetFlash("error", err.Error())
ctx.Redirect("/town/maps")
return
}