package game import ( "fmt" "strconv" "strings" "thehouseoficarus/internal/action" "thehouseoficarus/internal/net" "thehouseoficarus/internal/object" ) type recipeEntry struct { ItemName string Recipe action.RecipeDef } type productionTypeInfo struct { ActionType string DisplayVerb string } var productionTypes = map[string]productionTypeInfo{ "cooking": {"cook", "cooking"}, "smelting": {"smelt", "smelting"}, "smithing": {"smith", "smithing"}, "crafting": {"craft", "crafting"}, "combine": {"combine", "combining"}, "fletching": {"fletch", "fletching"}, "pharmacy": {"mix", "mixing"}, "construction": {"construct", "constructing"}, } var productionActionTypes map[string]bool func init() { productionActionTypes = make(map[string]bool) for _, pt := range productionTypes { productionActionTypes[pt.ActionType] = true } } func recipeMenuData(recipeIDs []string) []map[string]string { out := make([]map[string]string, len(recipeIDs)) for i, id := range recipeIDs { out[i] = map[string]string{"recipe_id": id} } return out } func recipeDefIDs(defs []action.RecipeDef) []string { ids := make([]string, len(defs)) for i, d := range defs { ids[i] = d.ID } return ids } func entryMenuData(entries []recipeEntry) []map[string]string { out := make([]map[string]string, len(entries)) for i, e := range entries { out[i] = map[string]string{"recipe_id": e.Recipe.ID} } return out } func (g *Game) promptHowMany(sess *net.Session, recipeID string) { sess.PendingRecipeID = recipeID sess.State = net.StateHowMany sess.Write("How many (return for all)?: ") } type recipeSelection struct { Recipe *action.RecipeDef Count int } func (g *Game) resolveRecipeByInput(input string, recipes []action.RecipeDef, lastRecipeID string) (sel recipeSelection, errMsg string) { if input == "" { if lastRecipeID == "" { return sel, "never_mind" } for i := range recipes { if recipes[i].ID == lastRecipeID { sel.Recipe = &recipes[i] return sel, "" } } return sel, "never_mind" } qty, productName := parseQty(input) productName = strings.TrimSpace(productName) if idx, err := strconv.Atoi(productName); err == nil && idx > 0 && idx <= len(recipes) { sel.Recipe = &recipes[idx-1] sel.Count = qty return sel, "" } matchCount := 0 for i := range recipes { outDef, _ := g.ItemStore.Load(recipes[i].Output) name := recipes[i].Output if outDef != nil { name = outDef.Name } if action.WordPrefixMatch(productName, name) { if matchCount == 0 { sel.Recipe = &recipes[i] sel.Count = qty } matchCount++ } } if matchCount > 1 { return sel, "ambiguous" } if sel.Recipe == nil { return sel, "never_mind" } return sel, "" } func (g *Game) showMenuTable(sess *net.Session, title string, names []string) { p := sess.Player tbl := &Table{Title: title} for i, name := range names { tbl.Rows = append(tbl.Rows, []string{fmt.Sprintf("%d", i+1), name}) } unicode := p.OptionBool("unicode") sess.WriteLine("") for _, line := range tbl.Render(unicode) { sess.WriteLine(line) } } func (g *Game) handleHowMany(sess *net.Session, input string) { p := sess.Player recipeID := sess.PendingRecipeID sess.PendingRecipeID = "" sess.State = net.StateGame input = strings.TrimSpace(input) var count int if input == "" { count = 0 } else if n, err := strconv.Atoi(input); err == nil && n > 0 { count = n } else { sess.WriteLine("Never mind.") g.reprompt(sess) return } var recipe *action.RecipeDef if strings.HasPrefix(recipeID, "combine_") { itemID := strings.TrimPrefix(recipeID, "combine_") itemDef, err := g.ItemStore.Load(itemID) if err != nil || len(itemDef.MadeFrom) == 0 { g.reprompt(sess) return } recipe = g.buildCombineRecipe(itemDef) } else { all, err := g.RecipeStore.LoadAll() if err != nil { g.reprompt(sess) return } for _, r := range all { if r.ID == recipeID { recipe = &r break } } } if recipe == nil { g.reprompt(sess) return } g.startProductionFromRecipe(sess, p, recipe, count) } func (g *Game) buildCombineRecipe(def *object.ItemDef) *action.RecipeDef { var consume []action.ConsumeEntry for _, mf := range def.MadeFrom { consume = append(consume, action.ConsumeEntry{ Items: mf.Items, Qty: mf.Qty, Byproducts: mf.Byproducts, }) } wait := def.Ticks if wait <= 0 { wait = 2 } return &action.RecipeDef{ ID: "combine_" + def.ID, Type: "combine", Wait: wait, Consume: consume, Output: def.ID, Message: fmt.Sprintf("You create %s.", def.Name), } }