package game import ( "strings" "thehouseoficarus/internal/action" "thehouseoficarus/internal/net" "thehouseoficarus/internal/player" ) func (g *Game) executeCraft(sess *net.Session, args []string, rawInput string) { g.doCraft(sess, strings.Join(args, " ")) } func (g *Game) executeConstruct(sess *net.Session, args []string, rawInput string) { g.doConstruct(sess, strings.Join(args, " ")) } func (g *Game) doCraft(sess *net.Session, input string) { g.doGenericStationSkill(sess, input, "crafting", player.Crafting, "last_craft", "Crafting", "craft", "Craft") } func (g *Game) doConstruct(sess *net.Session, input string) { g.doGenericStationSkill(sess, input, "construction", player.Construction, "last_construct", "Construction", "construct", "Construct") } func (g *Game) doGenericStationSkill(sess *net.Session, input string, recipeType string, skill player.SkillName, flagKey, label, verbPast, verbCap string) { p := sess.Player g.cancelAction(p) allRecipes, err := g.RecipeStore.LoadAll() if err != nil { sess.WriteLine("Error loading recipes.") return } var recipes []action.RecipeDef for _, r := range allRecipes { if r.Type != recipeType { continue } if !g.genericRecipeVisible(p, &r) { continue } recipes = append(recipes, r) } if input != "" { g.doGenericWithInput(sess, p, recipes, input, skill, flagKey, label, verbCap) return } lastRecipeID, _ := p.Flags[flagKey].(string) if lastRecipeID != "" { for i := range recipes { if recipes[i].ID == lastRecipeID { r := &recipes[i] if g.canDoGenericRecipe(p, r, skill) { g.startGenericRecipe(sess, p, r, 0, flagKey) return } break } } } available := g.availableGenericRecipes(p, recipes) if len(available) == 0 { sess.WriteLine("You don't have any materials to " + verbPast + ".") return } optionKey := verbPast + "_all" if p.OptionBool(optionKey) && len(available) == 1 { g.startGenericRecipe(sess, p, &available[0], 0, flagKey) return } g.showProductionTable(sess, p, available, label, recipeType, flagKey, verbCap, false) } func (g *Game) doGenericWithInput(sess *net.Session, p *player.Player, recipes []action.RecipeDef, input string, skill player.SkillName, flagKey, label, verbCap string) { qty, productName := parseQty(input) productName = strings.TrimSpace(productName) var matched []action.RecipeDef for _, r := range recipes { outDef, _ := g.ItemStore.Load(r.Output) name := r.Output if outDef != nil { name = outDef.Name } if action.WordPrefixMatch(productName, name) { matched = append(matched, r) } } if len(matched) == 0 { sess.WriteLine("You can't " + strings.ToLower(verbCap) + " that.") return } var available []action.RecipeDef for _, r := range matched { if g.canDoGenericRecipe(p, &r, skill) { 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.startGenericRecipe(sess, p, &available[0], qty, flagKey) return } g.showProductionTable(sess, p, available, label, label, flagKey, verbCap, false) } func (g *Game) genericRecipeVisible(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) canDoGenericRecipe(p *player.Player, r *action.RecipeDef, skill player.SkillName) bool { if p.Level(skill) < 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) availableGenericRecipes(p *player.Player, allRecipes []action.RecipeDef) []action.RecipeDef { var result []action.RecipeDef for _, r := range allRecipes { if r.HasAllItemsQty(p.CountItem) { result = append(result, r) } } return result } func (g *Game) startGenericRecipe(sess *net.Session, p *player.Player, recipe *action.RecipeDef, count int, flagKey string) { p.EnsureFlags() p.Flags[flagKey] = 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 }