package game import ( "strings" "thehouseoficarus/internal/net" "thehouseoficarus/internal/object" "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.doStationSkill(sess, input, "crafting", player.Crafting, "last_craft", "Crafting", "craft", "Craft") } func (g *Game) doConstruct(sess *net.Session, input string) { g.doStationSkill(sess, input, "construction", player.Construction, "last_construct", "Construction", "construct", "Construct") } func (g *Game) doStationSkill(sess *net.Session, input string, recipeType string, skill player.SkillName, flagKey, label, verbPast, verbCap string) { p := sess.Player g.cancelAction(p) items := g.CraftIndex.ByType(recipeType) var filtered []*object.ItemDef for _, item := range items { if !g.itemVisible(p, item) { continue } filtered = append(filtered, item) } if input != "" { g.doWithInput(sess, p, filtered, input, skill, flagKey, label, verbCap) return } lastItemID, _ := p.Flags[flagKey].(string) if lastItemID != "" { for _, item := range filtered { if item.ID == lastItemID { if g.canDoItem(p, item, skill) { g.startItem(sess, p, item, 0, flagKey) return } break } } } available := g.availableItems(p, filtered) if len(available) == 0 { if recipeType == "pharmacy" && g.hasGrimyHerbs(p) { sess.WriteLine("Mix what? Grimy herbs? Clean those first!") return } sess.WriteLine("You don't have any materials to " + verbPast + ".") return } optionKey := verbPast + "_all" if p.OptionBool(optionKey) && len(available) == 1 { g.startItem(sess, p, available[0], 0, flagKey) return } g.showProductionTable(sess, p, available, label, recipeType, flagKey, verbCap, false) } func (g *Game) doWithInput(sess *net.Session, p *player.Player, items []*object.ItemDef, input string, skill player.SkillName, flagKey, label, verbCap string) { qty, productName := parseQty(input) productName = strings.TrimSpace(productName) var matched []*object.ItemDef for _, item := range items { if object.WordPrefixMatch(productName, item.Name) { matched = append(matched, item) } } if len(matched) == 0 { sess.WriteLine("You can't " + strings.ToLower(verbCap) + " that.") return } var available []*object.ItemDef for _, item := range matched { if g.canDoItem(p, item, skill) { available = append(available, item) } } if len(available) == 0 { sess.WriteLine("You don't have the materials or level for that.") return } if len(available) == 1 { g.startItem(sess, p, available[0], qty, flagKey) return } g.showProductionTable(sess, p, available, label, label, flagKey, verbCap, false) } func (g *Game) itemVisible(p *player.Player, item *object.ItemDef) bool { return item.FindCraft(func(c object.CraftDef) bool { if len(c.Station) > 0 { stID, _ := g.findStation(p.RoomID, c.Station) if stID == "" { return false } } if c.Tool != "" && !g.hasToolType(p, c.Tool) { return false } return true }) != nil } func (g *Game) canDoItem(p *player.Player, item *object.ItemDef, skill player.SkillName) bool { m := item.FindCraft(func(c object.CraftDef) bool { if p.Level(skill) < c.Level { return false } if !craftHasAllItemsQty(&c, p.CountItem) { return false } if len(c.Station) > 0 { stID, _ := g.findStation(p.RoomID, c.Station) if stID == "" { return false } } if c.Tool != "" && !g.hasToolType(p, c.Tool) { return false } return true }) return m != nil } func (g *Game) availableItems(p *player.Player, allItems []*object.ItemDef) []*object.ItemDef { var result []*object.ItemDef for _, item := range allItems { m := item.FindCraft(func(c object.CraftDef) bool { return craftHasAllItemsQty(&c, p.CountItem) }) if m != nil { result = append(result, item) } } return result } func (g *Game) startItem(sess *net.Session, p *player.Player, item *object.ItemDef, count int, flagKey string) { p.EnsureFlags() p.Flags[flagKey] = item.ID g.AccountStore.SaveCharacter(p) g.startProductionFromItem(sess, p, item, count) } func (g *Game) hasGrimyHerbs(p *player.Player) bool { items := g.CraftIndex.ByType("clean") for _, item := range items { if item.FindCraft(func(c object.CraftDef) bool { return craftHasAllItems(&c, p.HasItem) }) != nil { return true } } return false } func (g *Game) findCraftItems(p *player.Player, itemAID, itemBID string) []*object.ItemDef { items := g.CraftIndex.ByType("crafting") 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 []*object.ItemDef for _, item := range items { match := item.FindCraft(func(c object.CraftDef) bool { if c.Tool == "" { return false } if c.Tool == toolTypeA && craftMatchesEntry(&c, itemBID) { return true } if c.Tool == toolTypeB && craftMatchesEntry(&c, itemAID) { return true } return false }) if match != nil { matched = append(matched, item) } } return matched }