diff options
| author | historia <[not public]> | 2026-06-18 20:26:03 -0400 |
|---|---|---|
| committer | historia <[not public]> | 2026-06-18 20:26:03 -0400 |
| commit | 97a1a908b9e6e6d3516628c139c9b64262b4fe08 (patch) | |
| tree | d82953974edbfb4051dff1a48f1b264b9c264d28 /internal/game/cmd_craft.go | |
| parent | 17e7725f252c7f5d3be2e9c37d62751c631f196f (diff) | |
| download | thehouseoficarus-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.go | 190 |
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 +} |
