aboutsummaryrefslogtreecommitdiff
path: root/internal/game/cmd_craft.go
diff options
context:
space:
mode:
authorhistoria <[not public]>2026-06-18 20:26:03 -0400
committerhistoria <[not public]>2026-06-18 20:26:03 -0400
commit97a1a908b9e6e6d3516628c139c9b64262b4fe08 (patch)
treed82953974edbfb4051dff1a48f1b264b9c264d28 /internal/game/cmd_craft.go
parent17e7725f252c7f5d3be2e9c37d62751c631f196f (diff)
downloadthehouseoficarus-97a1a908b9e6e6d3516628c139c9b64262b4fe08.tar.gz
feat: crafting roughly implemented (leather, gems, gold, clay, spinning).
Diffstat (limited to 'internal/game/cmd_craft.go')
-rw-r--r--internal/game/cmd_craft.go190
1 files changed, 190 insertions, 0 deletions
diff --git a/internal/game/cmd_craft.go b/internal/game/cmd_craft.go
new file mode 100644
index 0000000..50a99e0
--- /dev/null
+++ b/internal/game/cmd_craft.go
@@ -0,0 +1,190 @@
+package game
+
+import (
+ "strings"
+
+ "thehouseoficarus/internal/action"
+ "thehouseoficarus/internal/net"
+ "thehouseoficarus/internal/player"
+ "thehouseoficarus/internal/world"
+)
+
+func (g *Game) doCraft(sess *net.Session, input string) {
+ p := sess.Player.(*player.Player)
+ g.CancelAction(p)
+
+ allRecipes, err := g.RecipeStore.LoadAll()
+ if err != nil {
+ sess.WriteLine("Error loading recipes.")
+ return
+ }
+
+ var craftRecipes []action.RecipeDef
+ for _, r := range allRecipes {
+ if r.Type != "crafting" {
+ continue
+ }
+ if !g.craftRecipeVisible(p, &r) {
+ continue
+ }
+ craftRecipes = append(craftRecipes, r)
+ }
+
+ if input != "" {
+ g.doCraftWithInput(sess, p, craftRecipes, input)
+ return
+ }
+
+ lastRecipeID, _ := p.Flags["last_craft"].(string)
+ if lastRecipeID != "" {
+ for i := range craftRecipes {
+ if craftRecipes[i].ID == lastRecipeID {
+ r := &craftRecipes[i]
+ if g.canDoCraftRecipe(p, r) {
+ g.startCraftRecipe(sess, p, r, 0)
+ return
+ }
+ break
+ }
+ }
+ }
+
+ available := g.availableCraftRecipes(p, craftRecipes)
+ if len(available) == 0 {
+ sess.WriteLine("You don't have any materials to craft.")
+ return
+ }
+
+ if p.OptionBool("craft_all") && len(available) == 1 {
+ g.startCraftRecipe(sess, p, &available[0], 0)
+ return
+ }
+
+ g.showProductionTable(sess, p, available, "Crafting", "crafting", "last_craft", "Craft", false)
+}
+
+func (g *Game) doCraftWithInput(sess *net.Session, p *player.Player, craftRecipes []action.RecipeDef, input string) {
+ qty, productName := parseQty(input)
+ productName = strings.TrimSpace(productName)
+
+ var matched []action.RecipeDef
+ for _, r := range craftRecipes {
+ outDef, _ := g.ItemStore.Load(r.Output)
+ name := r.Output
+ if outDef != nil {
+ name = outDef.Name
+ }
+ if world.WordPrefixMatch(productName, name) {
+ matched = append(matched, r)
+ }
+ }
+
+ if len(matched) == 0 {
+ sess.WriteLine("You can't craft that.")
+ return
+ }
+
+ var available []action.RecipeDef
+ for _, r := range matched {
+ if g.canDoCraftRecipe(p, &r) {
+ available = append(available, r)
+ }
+ }
+
+ if len(available) == 0 {
+ sess.WriteLine("You don't have the materials or level for that.")
+ return
+ }
+
+ if len(available) == 1 {
+ g.startCraftRecipe(sess, p, &available[0], qty)
+ return
+ }
+
+ g.showProductionTable(sess, p, available, "Crafting", "crafting", "last_craft", "Craft", false)
+}
+
+func (g *Game) craftRecipeVisible(p *player.Player, r *action.RecipeDef) bool {
+ if len(r.Station) > 0 {
+ stID, _ := g.findStation(p.RoomID, r.Station)
+ if stID == "" {
+ return false
+ }
+ }
+ if r.Tool != "" && !g.hasToolType(p, r.Tool) {
+ return false
+ }
+ return true
+}
+
+func (g *Game) canDoCraftRecipe(p *player.Player, r *action.RecipeDef) bool {
+ if p.Level(player.Crafting) < r.Level {
+ return false
+ }
+ if !r.HasAllItemsQty(p.CountItem) {
+ return false
+ }
+ if len(r.Station) > 0 {
+ stID, _ := g.findStation(p.RoomID, r.Station)
+ if stID == "" {
+ return false
+ }
+ }
+ if r.Tool != "" && !g.hasToolType(p, r.Tool) {
+ return false
+ }
+ return true
+}
+
+func (g *Game) availableCraftRecipes(p *player.Player, allCraft []action.RecipeDef) []action.RecipeDef {
+ var result []action.RecipeDef
+ for _, r := range allCraft {
+ if r.HasAllItemsQty(p.CountItem) {
+ result = append(result, r)
+ }
+ }
+ return result
+}
+
+func (g *Game) startCraftRecipe(sess *net.Session, p *player.Player, recipe *action.RecipeDef, count int) {
+ if p.Flags == nil {
+ p.Flags = make(map[string]any)
+ }
+ p.Flags["last_craft"] = recipe.ID
+ g.AccountStore.SaveCharacter(p)
+
+ g.startProductionFromRecipe(sess, p, recipe, count)
+}
+
+func (g *Game) findCraftRecipesForItems(p *player.Player, itemAID, itemBID string) []action.RecipeDef {
+ allRecipes, err := g.RecipeStore.LoadAll()
+ if err != nil {
+ return nil
+ }
+
+ toolTypeA := ""
+ toolTypeB := ""
+ if defA, _ := g.ItemStore.Load(itemAID); defA != nil {
+ toolTypeA = defA.ToolType
+ }
+ if defB, _ := g.ItemStore.Load(itemBID); defB != nil {
+ toolTypeB = defB.ToolType
+ }
+
+ var matched []action.RecipeDef
+ for _, r := range allRecipes {
+ if r.Type != "crafting" {
+ continue
+ }
+ if r.Tool == "" {
+ continue
+ }
+
+ if r.Tool == toolTypeA && r.MatchesEntry(itemBID) {
+ matched = append(matched, r)
+ } else if r.Tool == toolTypeB && r.MatchesEntry(itemAID) {
+ matched = append(matched, r)
+ }
+ }
+ return matched
+}