aboutsummaryrefslogtreecommitdiff
path: root/internal/game/cmd_smelt.go
diff options
context:
space:
mode:
Diffstat (limited to 'internal/game/cmd_smelt.go')
-rw-r--r--internal/game/cmd_smelt.go230
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
+}