package game import ( "fmt" "strconv" "strings" "thehouseoficarus/internal/action" "thehouseoficarus/internal/net" "thehouseoficarus/internal/player" ) type smeltableEntry struct { ItemName string Recipe action.RecipeDef } func (g *Game) doSmelt(sess *net.Session, input string) { p := sess.Player.(*player.Player) g.CancelAction(p) stationName := g.findFurnace(p.RoomID) if stationName == "" { sess.WriteLine("You need a furnace to smelt.") return } allRecipes, err := g.RecipeStore.LoadAll() if err != nil { sess.WriteLine("Error loading recipes.") return } if input == "" { g.showSmeltMenu(sess, p, allRecipes, stationName) return } matches := g.findInventoryMatches(input, p) if len(matches) == 0 { sess.WriteLine(fmt.Sprintf("You don't have any '%s'.", input)) return } unique := uniqueItemNames(matches) if len(unique) > 1 { sess.WriteLine("Which one?") for _, name := range unique { sess.WriteLine(fmt.Sprintf(" - %s", name)) } return } itemID := matches[0].ID var recipes []action.RecipeDef for _, r := range allRecipes { if r.Type != "smelting" { continue } if !smeltStationOK(stationName, r.Station) { continue } if !r.MatchesEntry(itemID) { continue } if !r.HasAllItemsQty(p.CountItem) { continue } skillLevel := p.Level(player.SkillName(r.Skill)) if skillLevel < r.Level { continue } recipes = append(recipes, r) } if len(recipes) == 0 { sess.WriteLine("You can't smelt that here.") return } if len(recipes) == 1 { g.startSmelt(sess, p, &recipes[0], stationName) return } sess.PendingRecipeItem = itemID sess.PendingCookMenu = smeltRecipesToMenuData(recipes) sess.State = net.StateSmeltRecipe sess.WriteLine("\nWhat would you like to smelt?") for i, r := range recipes { sess.WriteLine(fmt.Sprintf(" %d) %s", i+1, g.recipeName(sess, &r))) } sess.WriteLine(fmt.Sprintf(" %d) Nothing", len(recipes)+1)) } func (g *Game) showSmeltMenu(sess *net.Session, p *player.Player, allRecipes []action.RecipeDef, stationName string) { seen := make(map[string]bool) var smeltables []smeltableEntry for _, r := range allRecipes { if r.Type != "smelting" { continue } if !smeltStationOK(stationName, r.Station) { continue } if seen[r.ID] { continue } if !r.HasAllItemsQty(p.CountItem) { continue } skillLevel := p.Level(player.SkillName(r.Skill)) if skillLevel < r.Level { continue } seen[r.ID] = true smeltables = append(smeltables, smeltableEntry{g.recipeName(sess, &r), r}) } if len(smeltables) == 0 { sess.WriteLine("You don't have anything you can smelt.") return } if len(smeltables) == 1 { g.startSmelt(sess, p, &smeltables[0].Recipe, stationName) return } sess.PendingRecipeItem = "" sess.State = net.StateSmeltRecipe sess.WriteLine("\nWhat would you like to smelt?") for i, s := range smeltables { sess.WriteLine(fmt.Sprintf(" %d) %s", i+1, s.ItemName)) } sess.WriteLine(fmt.Sprintf(" %d) Nothing", len(smeltables)+1)) sess.PendingCookMenu = makeSmeltMenuData(smeltables) } func (g *Game) handleSmeltRecipe(sess *net.Session, input string) { p := sess.Player.(*player.Player) input = strings.TrimSpace(input) if input == "" { return } choice, err := strconv.Atoi(input) if err != nil { sess.State = net.StateGame sess.PendingRecipeItem = "" sess.PendingCookMenu = nil sess.WriteLine("You decide not to smelt anything.") g.reprompt(sess) return } if len(sess.PendingCookMenu) > 0 { menuData := sess.PendingCookMenu sess.PendingCookMenu = nil if choice <= 0 || choice > len(menuData)+1 { sess.WriteLine("Invalid choice.") return } sess.State = net.StateGame if choice == len(menuData)+1 { sess.WriteLine("You decide not to smelt anything.") g.reprompt(sess) return } entry := menuData[choice-1] all, loadErr := g.RecipeStore.LoadAll() if loadErr != nil { g.reprompt(sess) return } for _, r := range all { if r.ID == entry["recipe_id"] { stationName := g.findFurnace(p.RoomID) g.startSmelt(sess, p, &r, stationName) return } } g.reprompt(sess) return } sess.State = net.StateGame g.reprompt(sess) } func smeltStationOK(stationName string, recipeStations []string) bool { for _, rs := range recipeStations { if rs == "furnace" && stationName == "furnace" { return true } } return false } func (g *Game) findFurnace(roomID int) string { for _, obj := range g.World.AllObjInstances(roomID) { if obj.Depleted { continue } if obj.DefID == "furnace" { return "furnace" } } return "" } func makeSmeltMenuData(smeltables []smeltableEntry) []map[string]string { out := make([]map[string]string, len(smeltables)) for i, s := range smeltables { out[i] = map[string]string{"recipe_id": s.Recipe.ID} } return out } func smeltRecipesToMenuData(recipes []action.RecipeDef) []map[string]string { out := make([]map[string]string, len(recipes)) for i, r := range recipes { out[i] = map[string]string{"recipe_id": r.ID} } return out }