package game import ( "strings" "thehouseoficarus/internal/action" "thehouseoficarus/internal/net" "thehouseoficarus/internal/player" "thehouseoficarus/internal/world" ) func (g *Game) doConstruct(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 constructRecipes []action.RecipeDef for _, r := range allRecipes { if r.Type != "construction" { continue } if !g.constructRecipeVisible(p, &r) { continue } constructRecipes = append(constructRecipes, r) } if input != "" { g.doConstructWithInput(sess, p, constructRecipes, input) return } lastRecipeID, _ := p.Flags["last_construct"].(string) if lastRecipeID != "" { for i := range constructRecipes { if constructRecipes[i].ID == lastRecipeID { r := &constructRecipes[i] if g.canDoConstructRecipe(p, r) { g.startConstructRecipe(sess, p, r, 0) return } break } } } available := g.availableConstructRecipes(p, constructRecipes) if len(available) == 0 { sess.WriteLine("You don't have any materials to construct.") return } if p.OptionBool("construct_all") && len(available) == 1 { g.startConstructRecipe(sess, p, &available[0], 0) return } g.showProductionTable(sess, p, available, "Construction", "construction", "last_construct", "Construct", false) } func (g *Game) doConstructWithInput(sess *net.Session, p *player.Player, constructRecipes []action.RecipeDef, input string) { qty, productName := parseQty(input) productName = strings.TrimSpace(productName) var matched []action.RecipeDef for _, r := range constructRecipes { 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 construct that.") return } var available []action.RecipeDef for _, r := range matched { if g.canDoConstructRecipe(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.startConstructRecipe(sess, p, &available[0], qty) return } g.showProductionTable(sess, p, available, "Construction", "construction", "last_construct", "Construct", false) } func (g *Game) constructRecipeVisible(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) canDoConstructRecipe(p *player.Player, r *action.RecipeDef) bool { if p.Level(player.Construction) < 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) availableConstructRecipes(p *player.Player, allConstruct []action.RecipeDef) []action.RecipeDef { var result []action.RecipeDef for _, r := range allConstruct { if r.HasAllItemsQty(p.CountItem) { result = append(result, r) } } return result } func (g *Game) startConstructRecipe(sess *net.Session, p *player.Player, recipe *action.RecipeDef, count int) { if p.Flags == nil { p.Flags = make(map[string]any) } p.Flags["last_construct"] = recipe.ID g.AccountStore.SaveCharacter(p) g.startProductionFromRecipe(sess, p, recipe, count) }