package game import ( "strings" "thehouseoficarus/internal/action" "thehouseoficarus/internal/combat" "thehouseoficarus/internal/net" "thehouseoficarus/internal/player" ) func (g *Game) executeFletch(sess *net.Session, args []string, rawInput string) { g.doFletch(sess, strings.Join(args, " ")) } var fletchLogItems = map[string]bool{ "logs": true, "oak_logs": true, "willow_logs": true, "maple_logs": true, "yew_logs": true, "magic_logs": true, } var fletchGemItems = map[string]bool{ "uncut_sapphire": true, "uncut_emerald": true, "uncut_ruby": true, "uncut_diamond": true, } func fletchNeedsKnife(r *action.RecipeDef) bool { if r.Tool == "knife" { return true } for _, e := range r.Consume { for _, id := range e.Items { if fletchLogItems[id] { if strings.Contains(r.Output, "shaft") || strings.Contains(r.Output, "bow") { return true } } } } return false } func fletchNeedsChisel(r *action.RecipeDef) bool { if r.Tool == "chisel" { return true } for _, e := range r.Consume { for _, id := range e.Items { if fletchGemItems[id] { return true } } } return false } func (g *Game) doFletch(sess *net.Session, input string) { p := sess.Player if combat.GetCombat(p.Name) != nil { sess.WriteLine("You can't do that during combat!") return } if p.Action != nil { p.Action = nil p.ActionState = nil } allRecipes, err := g.RecipeStore.LoadAll() if err != nil { sess.WriteLine("Error loading recipes.") return } var fletchRecipes []action.RecipeDef for _, r := range allRecipes { if r.Type != "fletching" { continue } fletchRecipes = append(fletchRecipes, r) } if input != "" { g.doFletchWithInput(sess, p, fletchRecipes, input) return } lastRecipeID, _ := p.Flags["last_fletch"].(string) if lastRecipeID != "" { for i := range fletchRecipes { if fletchRecipes[i].ID == lastRecipeID { r := &fletchRecipes[i] if g.canDoFletchRecipe(p, r) { g.startFletchAction(sess, p, r, 0) return } break } } } available := g.availableFletchRecipes(p, fletchRecipes) if len(available) == 0 { sess.WriteLine("You don't have any materials to fletch.") return } if p.OptionBool("fletch_all") && len(available) == 1 { g.startFletchAction(sess, p, &available[0], 0) return } g.showProductionTable(sess, p, available, "Fletching", "fletching", "last_fletch", "Fletch", true) } func (g *Game) doFletchWithInput(sess *net.Session, p *player.Player, fletchRecipes []action.RecipeDef, input string) { qty, productName := parseQty(input) productName = strings.TrimSpace(productName) var matched []action.RecipeDef for _, r := range fletchRecipes { 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 fletch that.") return } var available []action.RecipeDef for _, r := range matched { if g.canDoFletchRecipe(p, &r) { available = append(available, r) } } if len(available) == 0 { sess.WriteLine("You don't have the materials for that.") return } if len(available) == 1 { count := qty g.startFletchAction(sess, p, &available[0], count) return } g.showProductionTable(sess, p, available, "Fletching", "fletching", "last_fletch", "Fletch", true) } func (g *Game) hasFletchTools(p *player.Player, r *action.RecipeDef) bool { if r.Tool != "" { return g.hasToolType(p, r.Tool) } if fletchNeedsKnife(r) && !g.hasToolType(p, "knife") { return false } if fletchNeedsChisel(r) && !g.hasToolType(p, "chisel") { return false } return true } func (g *Game) canDoFletchRecipe(p *player.Player, r *action.RecipeDef) bool { return p.Level(player.Fletching) >= r.Level && r.HasAllItemsQty(p.CountItem) && g.hasFletchTools(p, r) } func (g *Game) availableFletchRecipes(p *player.Player, allFletch []action.RecipeDef) []action.RecipeDef { var result []action.RecipeDef for _, r := range allFletch { if r.HasAllItemsQty(p.CountItem) && g.hasFletchTools(p, &r) { result = append(result, r) } } return result } func (g *Game) findFletchRecipes(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 } isToolA := toolTypeA == "knife" || toolTypeA == "chisel" isToolB := toolTypeB == "knife" || toolTypeB == "chisel" var matched []action.RecipeDef for _, r := range allRecipes { if r.Type != "fletching" { continue } if r.Tool != "" { if r.Tool == toolTypeA && r.MatchesEntry(itemBID) { matched = append(matched, r) continue } if r.Tool == toolTypeB && r.MatchesEntry(itemAID) { matched = append(matched, r) continue } } aMatch := false bMatch := false for _, e := range r.Consume { for _, id := range e.Items { if id == itemAID { aMatch = true } if id == itemBID { bMatch = true } } } if aMatch && bMatch { matched = append(matched, r) continue } if isToolA && bMatch { if (fletchNeedsKnife(&r) && toolTypeA == "knife") || (fletchNeedsChisel(&r) && toolTypeA == "chisel") { matched = append(matched, r) continue } } if isToolB && aMatch { if (fletchNeedsKnife(&r) && toolTypeB == "knife") || (fletchNeedsChisel(&r) && toolTypeB == "chisel") { matched = append(matched, r) continue } } } return matched }