aboutsummaryrefslogtreecommitdiff
path: root/internal/game/cmd_use.go
diff options
context:
space:
mode:
Diffstat (limited to 'internal/game/cmd_use.go')
-rw-r--r--internal/game/cmd_use.go264
1 files changed, 110 insertions, 154 deletions
diff --git a/internal/game/cmd_use.go b/internal/game/cmd_use.go
index e653c93..640e28b 100644
--- a/internal/game/cmd_use.go
+++ b/internal/game/cmd_use.go
@@ -4,7 +4,6 @@ import (
"fmt"
"strings"
- "thehouseoficarus/internal/action"
"thehouseoficarus/internal/net"
"thehouseoficarus/internal/object"
"thehouseoficarus/internal/player"
@@ -116,57 +115,42 @@ func (g *Game) useRoomObject(sess *net.Session, p *player.Player, input string)
return true
}
-func (g *Game) stationRecipes(p *player.Player, stationDefID string) []action.RecipeDef {
- allRecipes, err := g.RecipeStore.LoadAll()
- if err != nil {
- return nil
- }
- var results []action.RecipeDef
- for _, r := range allRecipes {
- if len(r.Station) == 0 {
- continue
- }
- stationMatch := false
- for _, sid := range r.Station {
- if sid == stationDefID {
- stationMatch = true
- break
- }
- }
- if !stationMatch {
+func (g *Game) stationRecipes(p *player.Player, stationDefID string) []*object.ItemDef {
+ items := g.CraftIndex.ByStation(stationDefID)
+ var results []*object.ItemDef
+ for _, item := range items {
+ c := item.FirstCraft()
+ if !craftHasAllItemsQty(c, p.CountItem) {
continue
}
- if !r.HasAllItemsQty(p.CountItem) {
+ skillName := player.SkillName(c.EffectiveSkill())
+ if p.Level(skillName) < c.Level {
continue
}
- skillName := player.SkillName(r.EffectiveSkill())
- if p.Level(skillName) < r.Level {
- continue
- }
- if r.Tool != "" && !g.hasToolType(p, r.Tool) {
+ if c.Tool != "" && !g.hasToolType(p, c.Tool) {
continue
}
if stationDefID == "anvil" && !g.hasToolType(p, "hammer") {
continue
}
- results = append(results, r)
+ results = append(results, item)
}
return results
}
-func (g *Game) showRecipeMenu(sess *net.Session, p *player.Player, recipes []action.RecipeDef, stationName string) {
- if len(recipes) == 0 {
+func (g *Game) showRecipeMenu(sess *net.Session, p *player.Player, items []*object.ItemDef, stationName string) {
+ if len(items) == 0 {
sess.WriteLine(fmt.Sprintf("You don't have anything you can make at the %s.", stationName))
return
}
- if len(recipes) == 1 {
- g.promptHowMany(sess, recipes[0].ID)
+ if len(items) == 1 {
+ g.promptHowMany(sess, items[0].ID)
return
}
needTypes := false
- for i := range recipes {
- for j := i + 1; j < len(recipes); j++ {
- if recipes[i].Type != recipes[j].Type {
+ for i := range items {
+ for j := i + 1; j < len(items); j++ {
+ if len(items[i].Craft) > 0 && len(items[j].Craft) > 0 && items[i].FirstCraft().Type != items[j].FirstCraft().Type {
needTypes = true
break
}
@@ -175,17 +159,23 @@ func (g *Game) showRecipeMenu(sess *net.Session, p *player.Player, recipes []act
break
}
}
- menu := recipeMenuData(recipeDefIDs(recipes))
+ menu := itemMenuData(itemIDs(items))
sess.PendingMenu = menu
sess.State = net.StateRecipeChoice
var names []string
- for _, r := range recipes {
- name := g.recipeName(sess, &r)
+ for _, item := range items {
+ cType := ""
+ if len(item.Craft) > 0 {
+ cType = item.FirstCraft().Type
+ }
+ if cType == "" {
+ cType = "combine"
+ }
+ typeLabel := strings.ToUpper(cType[:1]) + cType[1:]
if needTypes {
- typeLabel := strings.ToUpper(r.Type[:1]) + r.Type[1:]
- names = append(names, fmt.Sprintf("%s (%s)", name, typeLabel))
+ names = append(names, fmt.Sprintf("%s (%s)", g.itemName(sess, item), typeLabel))
} else {
- names = append(names, name)
+ names = append(names, g.itemName(sess, item))
}
}
g.showMenuTable(sess, fmt.Sprintf("What would you like to make at the %s?", stationName), names)
@@ -217,23 +207,28 @@ func (g *Game) doUseItemOnTarget(sess *net.Session, p *player.Player, itemAName,
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" {
+ recipes := g.CraftIndex.FindByStationInput(def.ID, itemAID)
+
+ if len(recipes) > 0 {
+ cType := ""
+ if len(recipes[0].Craft) > 0 {
+ cType = recipes[0].FirstCraft().Type
+ }
+ if cType == "smelting" {
+ var filtered []*object.ItemDef
+ for _, item := range recipes {
+ c := item.FirstCraft()
+ if c.Type != "smelting" {
continue
}
- if !r.HasAllItemsQty(p.CountItem) {
+ if !craftHasAllItemsQty(c, p.CountItem) {
continue
}
- skillLevel := p.Level(player.SkillName(r.EffectiveSkill()))
- if skillLevel < r.Level {
+ skillLevel := p.Level(player.SkillName(c.EffectiveSkill()))
+ if skillLevel < c.Level {
continue
}
- filtered = append(filtered, r)
+ filtered = append(filtered, item)
}
if len(filtered) == 0 {
sess.WriteLine("You can't smelt that here.")
@@ -243,36 +238,35 @@ func (g *Game) doUseItemOnTarget(sess *net.Session, p *player.Player, itemAName,
g.promptHowMany(sess, filtered[0].ID)
return
}
- sess.PendingMenu = recipeMenuData(recipeDefIDs(filtered))
- sess.State = net.StateRecipeChoice
- var names []string
- for _, r := range filtered {
- names = append(names, g.recipeName(sess, &r))
- }
- g.showMenuTable(sess, "What would you like to smelt?", names)
- return
+ sess.PendingMenu = itemMenuData(itemIDs(filtered))
+ sess.State = net.StateRecipeChoice
+ var names []string
+ for _, item := range filtered {
+ names = append(names, g.itemName(sess, item))
+ }
+ g.showMenuTable(sess, "What would you like to smelt?", names)
+ return
}
- if recipes[0].Type == "smithing" {
+ if cType == "smithing" {
if !g.hasToolType(p, "hammer") {
sess.WriteLine("You need a hammer to smith.")
return
}
- allRecipes, _ := g.RecipeStore.LoadAll()
- g.showSmithTable(sess, p, itemAID, allRecipes)
+ g.showSmithTable(sess, p, itemAID)
return
}
if len(recipes) == 1 {
g.promptHowMany(sess, recipes[0].ID)
return
}
- sess.PendingMenu = recipeMenuData(recipeDefIDs(recipes))
- sess.State = net.StateRecipeChoice
- var names []string
- for _, r := range recipes {
- names = append(names, g.recipeName(sess, &r))
- }
- g.showMenuTable(sess, fmt.Sprintf("What would you like to make with %s on the %s?", itemAName, def.Name), names)
- return
+ sess.PendingMenu = itemMenuData(itemIDs(recipes))
+ sess.State = net.StateRecipeChoice
+ var names []string
+ for _, item := range recipes {
+ names = append(names, g.itemName(sess, item))
+ }
+ g.showMenuTable(sess, fmt.Sprintf("What would you like to make with %s on the %s?", itemAName, def.Name), names)
+ return
}
for _, ui := range def.UseInteractions {
@@ -314,29 +308,19 @@ func (g *Game) doUseItemOnTarget(sess *net.Session, p *player.Player, itemAName,
itemBID := matchesB[0].ID
- craftRecipes := g.findCraftRecipes(p, itemAID, itemBID)
- fletchRecipes := g.findFletchRecipes(p, itemAID, itemBID)
+ craftItems := g.findCraftItems(p, itemAID, itemBID)
+ fletchItems := g.findFletchItems(p, itemAID, itemBID)
- if len(craftRecipes) > 0 && len(fletchRecipes) > 0 {
+ if len(craftItems) > 0 && len(fletchItems) > 0 {
var menu []map[string]string
var names []string
- for _, r := range craftRecipes {
- menu = append(menu, map[string]string{"recipe_id": r.ID})
- outDef, _ := g.ItemStore.Load(r.Output)
- name := r.Output
- if outDef != nil {
- name = outDef.Name
- }
- names = append(names, fmt.Sprintf("%s (Crafting)", name))
+ for _, item := range craftItems {
+ menu = append(menu, map[string]string{"item_id": item.ID})
+ names = append(names, fmt.Sprintf("%s (Crafting)", item.Name))
}
- for _, r := range fletchRecipes {
- menu = append(menu, map[string]string{"fletch_recipe_id": r.ID})
- outDef, _ := g.ItemStore.Load(r.Output)
- name := r.Output
- if outDef != nil {
- name = outDef.Name
- }
- names = append(names, fmt.Sprintf("%s (Fletching)", name))
+ for _, item := range fletchItems {
+ menu = append(menu, map[string]string{"item_id": item.ID})
+ names = append(names, fmt.Sprintf("%s (Fletching)", item.Name))
}
sess.PendingMenu = menu
sess.State = net.StateRecipeChoice
@@ -344,15 +328,15 @@ func (g *Game) doUseItemOnTarget(sess *net.Session, p *player.Player, itemAName,
return
}
- if len(craftRecipes) > 0 {
- var available []action.RecipeDef
- for _, r := range craftRecipes {
- if g.canDoRecipe(p, &r, player.Crafting) {
- available = append(available, r)
+ if len(craftItems) > 0 {
+ var available []*object.ItemDef
+ for _, item := range craftItems {
+ if g.canDoItem(p, item, player.Crafting) {
+ available = append(available, item)
}
}
if len(available) == 1 {
- g.startRecipe(sess, p, &available[0], 0, "last_craft")
+ g.startItem(sess, p, available[0], 0, "last_craft")
return
}
if len(available) > 1 {
@@ -361,15 +345,15 @@ func (g *Game) doUseItemOnTarget(sess *net.Session, p *player.Player, itemAName,
}
}
- if len(fletchRecipes) > 0 {
- var available []action.RecipeDef
- for _, r := range fletchRecipes {
- if g.canDoFletchRecipe(p, &r) {
- available = append(available, r)
+ if len(fletchItems) > 0 {
+ var available []*object.ItemDef
+ for _, item := range fletchItems {
+ if g.canDoFletchItem(p, item) {
+ available = append(available, item)
}
}
if len(available) == 1 {
- g.startFletchAction(sess, p, &available[0], 0)
+ g.startFletchAction(sess, p, available[0], 0)
return
}
if len(available) > 1 {
@@ -378,22 +362,33 @@ func (g *Game) doUseItemOnTarget(sess *net.Session, p *player.Player, itemAName,
}
}
- matched := g.findCombineResults(sess, p, itemAID, itemBID)
- if len(matched) == 1 {
- g.promptHowMany(sess, "combine_"+matched[0].ID)
+ matched := g.CraftIndex.FindByTwoInputs(itemAID, itemBID)
+ var matchable []*object.ItemDef
+ for _, item := range matched {
+ if craftHasAllItemsQty(item.FirstCraft(), p.CountItem) {
+ matchable = append(matchable, item)
+ }
+ }
+ if len(matchable) == 1 {
+ g.promptHowMany(sess, matchable[0].ID)
return
}
- if len(matched) > 1 {
- sess.PendingMenu = combineMenuData(matched)
+ if len(matchable) > 1 {
+ sess.PendingMenu = itemMenuData(itemIDs(matchable))
sess.State = net.StateRecipeChoice
var names []string
- for _, def := range matched {
- names = append(names, g.itemColorize(sess, def, def.Name))
+ for _, item := range matchable {
+ names = append(names, g.itemName(sess, item))
}
g.showMenuTable(sess, "What would you like to make?", names)
return
}
+ if g.isGrimyHerb(itemAID) && itemBID == "vial_of_water" {
+ sess.WriteLine("Don't put a grimy herb in there! Clean it first!")
+ return
+ }
+
sess.WriteLine("You can't combine those items.")
return
}
@@ -401,55 +396,16 @@ func (g *Game) doUseItemOnTarget(sess *net.Session, p *player.Player, itemAName,
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
+func (g *Game) isGrimyHerb(itemID string) bool {
+ items := g.CraftIndex.ByType("clean")
+ for _, item := range items {
+ for _, e := range item.FirstCraft().Consume {
+ for _, id := range e.Items {
+ if id == itemID {
+ return true
}
}
}
- if aEntry >= 0 && bEntry >= 0 && aEntry != bEntry && madeFromAvailable(p, def.MadeFrom) {
- matched = append(matched, def)
- }
}
- return matched
-}
-
-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 madeFromAvailable(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
+ return false
}