diff options
Diffstat (limited to 'internal/game/cmd_smelt.go')
| -rw-r--r-- | internal/game/cmd_smelt.go | 230 |
1 files changed, 230 insertions, 0 deletions
diff --git a/internal/game/cmd_smelt.go b/internal/game/cmd_smelt.go new file mode 100644 index 0000000..a308352 --- /dev/null +++ b/internal/game/cmd_smelt.go @@ -0,0 +1,230 @@ +package game + +import ( + "fmt" + "strconv" + "strings" + + "thehouseoficarus/internal/action" + "thehouseoficarus/internal/net" + "thehouseoficarus/internal/player" +) + +type smeltableEntry struct { + ItemName string + Recipe action.RecipeDef +} + +func (g *Game) doSmelt(sess *net.Session, input string) { + p := sess.Player.(*player.Player) + g.CancelAction(p) + + stationName := g.findFurnace(p.RoomID) + if stationName == "" { + sess.WriteLine("You need a furnace to smelt.") + return + } + + allRecipes, err := g.RecipeStore.LoadAll() + if err != nil { + sess.WriteLine("Error loading recipes.") + return + } + + if input == "" { + g.showSmeltMenu(sess, p, allRecipes, stationName) + return + } + + matches := g.findInventoryMatches(input, p) + if len(matches) == 0 { + sess.WriteLine(fmt.Sprintf("You don't have any '%s'.", input)) + return + } + + unique := uniqueItemNames(matches) + if len(unique) > 1 { + sess.WriteLine("Which one?") + for _, name := range unique { + sess.WriteLine(fmt.Sprintf(" - %s", name)) + } + return + } + + itemID := matches[0].ID + + var recipes []action.RecipeDef + for _, r := range allRecipes { + if r.Type != "smelting" { + continue + } + if !smeltStationOK(stationName, r.Station) { + continue + } + if !r.MatchesEntry(itemID) { + continue + } + if !r.HasAllItemsQty(p.CountItem) { + continue + } + skillLevel := p.Level(player.SkillName(r.Skill)) + if skillLevel < r.Level { + continue + } + recipes = append(recipes, r) + } + + if len(recipes) == 0 { + sess.WriteLine("You can't smelt that here.") + return + } + + if len(recipes) == 1 { + g.startSmelt(sess, p, &recipes[0], stationName) + return + } + + sess.PendingRecipeItem = itemID + sess.PendingCookMenu = smeltRecipesToMenuData(recipes) + sess.State = net.StateSmeltRecipe + sess.WriteLine("\nWhat would you like to smelt?") + for i, r := range recipes { + sess.WriteLine(fmt.Sprintf(" %d) %s", i+1, g.recipeName(sess, &r))) + } + sess.WriteLine(fmt.Sprintf(" %d) Nothing", len(recipes)+1)) +} + +func (g *Game) showSmeltMenu(sess *net.Session, p *player.Player, allRecipes []action.RecipeDef, stationName string) { + seen := make(map[string]bool) + var smeltables []smeltableEntry + + for _, r := range allRecipes { + if r.Type != "smelting" { + continue + } + if !smeltStationOK(stationName, r.Station) { + continue + } + if seen[r.ID] { + continue + } + if !r.HasAllItemsQty(p.CountItem) { + continue + } + skillLevel := p.Level(player.SkillName(r.Skill)) + if skillLevel < r.Level { + continue + } + seen[r.ID] = true + smeltables = append(smeltables, smeltableEntry{g.recipeName(sess, &r), r}) + } + + if len(smeltables) == 0 { + sess.WriteLine("You don't have anything you can smelt.") + return + } + + if len(smeltables) == 1 { + g.startSmelt(sess, p, &smeltables[0].Recipe, stationName) + return + } + + sess.PendingRecipeItem = "" + sess.State = net.StateSmeltRecipe + sess.WriteLine("\nWhat would you like to smelt?") + for i, s := range smeltables { + sess.WriteLine(fmt.Sprintf(" %d) %s", i+1, s.ItemName)) + } + sess.WriteLine(fmt.Sprintf(" %d) Nothing", len(smeltables)+1)) + + sess.PendingCookMenu = makeSmeltMenuData(smeltables) +} + +func (g *Game) handleSmeltRecipe(sess *net.Session, input string) { + p := sess.Player.(*player.Player) + input = strings.TrimSpace(input) + if input == "" { + return + } + + choice, err := strconv.Atoi(input) + if err != nil { + sess.State = net.StateGame + sess.PendingRecipeItem = "" + sess.PendingCookMenu = nil + sess.WriteLine("You decide not to smelt anything.") + g.reprompt(sess) + return + } + + if len(sess.PendingCookMenu) > 0 { + menuData := sess.PendingCookMenu + sess.PendingCookMenu = nil + if choice <= 0 || choice > len(menuData)+1 { + sess.WriteLine("Invalid choice.") + return + } + sess.State = net.StateGame + if choice == len(menuData)+1 { + sess.WriteLine("You decide not to smelt anything.") + g.reprompt(sess) + return + } + entry := menuData[choice-1] + + all, loadErr := g.RecipeStore.LoadAll() + if loadErr != nil { + g.reprompt(sess) + return + } + for _, r := range all { + if r.ID == entry["recipe_id"] { + stationName := g.findFurnace(p.RoomID) + g.startSmelt(sess, p, &r, stationName) + return + } + } + g.reprompt(sess) + return + } + + sess.State = net.StateGame + g.reprompt(sess) +} + +func smeltStationOK(stationName string, recipeStations []string) bool { + for _, rs := range recipeStations { + if rs == "furnace" && stationName == "furnace" { + return true + } + } + return false +} + +func (g *Game) findFurnace(roomID int) string { + for _, obj := range g.World.AllObjInstances(roomID) { + if obj.Depleted { + continue + } + if obj.DefID == "furnace" { + return "furnace" + } + } + return "" +} + +func makeSmeltMenuData(smeltables []smeltableEntry) []map[string]string { + out := make([]map[string]string, len(smeltables)) + for i, s := range smeltables { + out[i] = map[string]string{"recipe_id": s.Recipe.ID} + } + return out +} + +func smeltRecipesToMenuData(recipes []action.RecipeDef) []map[string]string { + out := make([]map[string]string, len(recipes)) + for i, r := range recipes { + out[i] = map[string]string{"recipe_id": r.ID} + } + return out +} |
