package game import ( "fmt" "strings" "thehouseoficarus/internal/net" "thehouseoficarus/internal/object" "thehouseoficarus/internal/player" ) func (g *Game) doUse(sess *net.Session, input string) { p := sess.Player.(*player.Player) g.CancelAction(p) lower := strings.ToLower(input) sep := "" if strings.Contains(lower, " on ") { sep = " on " } else if strings.Contains(lower, " with ") { sep = " with " } if sep != "" { parts := strings.SplitN(lower, sep, 2) itemA := strings.TrimSpace(parts[0]) itemB := strings.TrimSpace(parts[1]) if itemA == itemB { sess.WriteLine("You can't use that with itself.") return } g.doUseItemOnTarget(sess, p, itemA, itemB) return } if len(strings.Fields(input)) >= 2 { g.doUseItemOnTarget(sess, p, strings.Fields(input)[0], strings.Join(strings.Fields(input)[1:], " ")) return } g.StartAction(sess, "use", input) } func (g *Game) doUseItemOnTarget(sess *net.Session, p *player.Player, itemAName, itemBName string) { matchesA := g.findInventoryMatches(itemAName, p) if len(matchesA) == 0 { sess.WriteLine(fmt.Sprintf("You don't have any '%s'.", itemAName)) return } uniqueA := uniqueItemNames(matchesA) if len(uniqueA) > 1 { sess.WriteLine("Which one?") for _, name := range uniqueA { sess.WriteLine(fmt.Sprintf(" - %s", name)) } return } itemAID := matchesA[0].ID matchesB := g.findInventoryMatches(itemBName, p) objInstances := g.World.FindObjInstances(p.RoomID, itemBName) if len(objInstances) > 0 { objSt := &objInstances[0] def, _ := g.ObjectStore.Load(objSt.DefID) if def == nil { g.StartAction(sess, "use", itemBName) return } stationIDs := []string{def.ID} recipes, err := g.RecipeStore.FindByStation(itemAID, stationIDs, "") if err == nil && len(recipes) > 0 { if recipes[0].Type == "smelting" { filtered := recipes[:0:0] for _, r := range recipes { if r.Type != "smelting" { continue } if !r.HasAllItemsQty(p.CountItem) { continue } skillLevel := p.Level(player.SkillName(r.Skill)) if skillLevel < r.Level { continue } filtered = append(filtered, r) } if len(filtered) == 0 { sess.WriteLine("You can't smelt that here.") return } if len(filtered) == 1 { g.startSmelt(sess, p, &filtered[0], def.Name) return } sess.PendingRecipeItem = itemAID sess.PendingCookMenu = smeltRecipesToMenuData(filtered) sess.State = net.StateSmeltRecipe sess.WriteLine("\nWhat would you like to smelt?") for i, r := range filtered { sess.WriteLine(fmt.Sprintf(" %d) %s", i+1, g.recipeName(sess, &r))) } sess.WriteLine(fmt.Sprintf(" %d) Nothing", len(filtered)+1)) return } if len(recipes) == 1 { g.startCook(sess, p, &recipes[0], def.Name) return } sess.PendingRecipeItem = itemAID sess.PendingCookMenu = recipesToMenuData(recipes) sess.State = net.StateCookRecipe sess.WriteLine(fmt.Sprintf("\nWhat would you like to make with %s on the %s?", itemAName, def.Name)) for i, r := range recipes { sess.WriteLine(fmt.Sprintf(" %d) %s", i+1, g.recipeName(sess, &r))) } return } g.StartAction(sess, "use", itemBName) return } matchesB = g.findInventoryMatches(itemBName, p) if len(matchesB) > 0 { uniqueB := uniqueItemNames(matchesB) if len(uniqueB) > 1 { sess.WriteLine("Which '" + itemBName + "'?") for _, name := range uniqueB { sess.WriteLine(fmt.Sprintf(" - %s", name)) } return } itemBID := matchesB[0].ID matched := g.findCombineResults(sess, p, itemAID, itemBID) if len(matched) == 1 { g.produceCombined(sess, p, matched[0]) return } if len(matched) > 1 { sess.PendingCookMenu = combineMenuData(matched) sess.State = net.StateCookRecipe sess.WriteLine("\nWhat would you like to make?") for i, def := range matched { sess.WriteLine(fmt.Sprintf(" %d) %s", i+1, g.itemColorize(sess, def, def.Name))) } return } sess.WriteLine("You can't combine those items.") return } sess.WriteLine(fmt.Sprintf("There's no '%s' here to use that on.", itemBName)) } func (g *Game) findCombineResults(sess *net.Session, p *player.Player, itemAID, itemBID string) []*object.ItemDef { items, err := g.ItemStore.LoadAll() if err != nil { return nil } var matched []*object.ItemDef for _, def := range items { if len(def.MadeFrom) == 0 { continue } aEntry := -1 bEntry := -1 for ei, entry := range def.MadeFrom { for _, id := range entry.Items { if id == itemAID && aEntry < 0 { aEntry = ei } if id == itemBID && bEntry < 0 { bEntry = ei } } } if aEntry >= 0 && bEntry >= 0 && aEntry != bEntry && madeFromItemsAvailable(p, def.MadeFrom) { matched = append(matched, def) } } return matched } func (g *Game) produceCombined(sess *net.Session, p *player.Player, def *object.ItemDef) { freeSlot := p.FirstFreeSlot() if freeSlot == -1 { sess.WriteLine("Your inventory is too full.") return } for _, entry := range def.MadeFrom { for _, id := range entry.Items { if p.HasItem(id) { p.RemoveItem(id, entry.Qty) break } } } p.SetInvSlot(freeSlot, &player.InventorySlot{ItemID: def.ID, Quantity: 1}) g.AccountStore.SaveCharacter(p) sess.WriteLine(fmt.Sprintf("You combine the ingredients and create %s.", g.itemColorize(sess, def, def.Name))) } func combineMenuData(defs []*object.ItemDef) []map[string]string { out := make([]map[string]string, len(defs)) for i, d := range defs { out[i] = map[string]string{"combine_item": d.ID} } return out } func madeFromItemsAvailable(p *player.Player, madeFrom []object.MadeFromEntry) bool { for _, entry := range madeFrom { found := false for _, id := range entry.Items { if p.HasItem(id) { found = true break } } if !found { return false } } return true }