aboutsummaryrefslogtreecommitdiff
path: root/internal/game/core_production.go
diff options
context:
space:
mode:
authorhistoria <[not public]>2026-06-20 23:43:35 -0400
committerhistoria <[not public]>2026-06-20 23:43:35 -0400
commit470bc5bd99b793e46305310b5fbeb3068eba45f1 (patch)
treeff268fab1a8e7699cd6404e6e86c2d4bd1c6f2f6 /internal/game/core_production.go
parent010fa439399581391fcd509d2058191ff4fa74b3 (diff)
downloadthehouseoficarus-470bc5bd99b793e46305310b5fbeb3068eba45f1.tar.gz
refactor: removed separate crafting recipes and combined them into item YAML
Diffstat (limited to 'internal/game/core_production.go')
-rw-r--r--internal/game/core_production.go406
1 files changed, 187 insertions, 219 deletions
diff --git a/internal/game/core_production.go b/internal/game/core_production.go
index 59517d5..4aecc54 100644
--- a/internal/game/core_production.go
+++ b/internal/game/core_production.go
@@ -13,47 +13,61 @@ import (
"thehouseoficarus/internal/net"
"thehouseoficarus/internal/object"
"thehouseoficarus/internal/player"
-
)
-func (g *Game) startProduction(sess *net.Session, p *player.Player, recipe *action.RecipeDef, actionType, displayVerb, startMsg, endMsg string, count int) {
+func craftFirstItemName(c *object.CraftDef, load func(string) (string, bool)) string {
+ if c == nil {
+ return ""
+ }
+ for _, e := range c.Consume {
+ for _, id := range e.Items {
+ if name, ok := load(id); ok {
+ return name
+ }
+ return id
+ }
+ }
+ return ""
+}
+
+func (g *Game) startProduction(sess *net.Session, p *player.Player, item *object.ItemDef, craft *object.CraftDef, actionType, displayVerb, startMsg, endMsg string, count int) {
g.cancelAction(p)
g.cancelBgAction(p)
- skill := recipe.EffectiveSkill()
+ skill := craft.EffectiveSkill()
if skill != "" {
skillLevel := p.Level(player.SkillName(skill))
- if skillLevel < recipe.Level {
- sess.WriteLine(fmt.Sprintf("You need level %d %s to do that.", recipe.Level, skill))
+ if skillLevel < craft.Level {
+ sess.WriteLine(fmt.Sprintf("You need level %d %s to do that.", craft.Level, skill))
g.reprompt(sess)
return
}
}
- if !recipe.HasAllItemsQty(p.CountItem) {
+ if !craftHasAllItemsQty(craft, p.CountItem) {
sess.WriteLine("You don't have the required materials.")
g.reprompt(sess)
return
}
- outDef, _ := g.ItemStore.Load(recipe.Output)
+ outDef, _ := g.ItemStore.Load(item.ID)
- wait := recipe.Wait
+ wait := craft.Wait
if wait <= 0 {
wait = 4
}
- outputName := recipe.Output
+ outputName := item.ID
if outDef != nil {
outputName = outDef.Name
}
p.Action = &action.Action{
Type: actionType,
- TargetID: recipe.ID,
+ TargetID: item.ID,
TargetName: outputName,
Data: map[string]any{
- "recipe_id": recipe.ID,
+ "item_id": item.ID,
"phase": 0,
"wait": wait,
"start_msg": startMsg,
@@ -68,13 +82,18 @@ func (g *Game) startProduction(sess *net.Session, p *player.Player, recipe *acti
g.broadcastAction(sess, "\n%s starts %s.", p.Name, displayVerb)
}
-func (g *Game) startProductionFromRecipe(sess *net.Session, p *player.Player, recipe *action.RecipeDef, count int) {
- _, stationName := g.findStation(p.RoomID, recipe.Station)
+func (g *Game) startProductionFromItem(sess *net.Session, p *player.Player, item *object.ItemDef, count int) {
+ craft := item.FirstCraft()
+ if craft == nil {
+ return
+ }
+
+ _, stationName := g.findStation(p.RoomID, craft.Station)
if stationName == "" {
stationName = "inventory"
}
- firstItem := recipe.FirstItemName(func(id string) (string, bool) {
+ firstItem := craftFirstItemName(craft, func(id string) (string, bool) {
def, err := g.ItemStore.Load(id)
if err != nil {
return id, false
@@ -82,9 +101,9 @@ func (g *Game) startProductionFromRecipe(sess *net.Session, p *player.Player, re
return def.Name, true
})
- info, ok := productionTypes[recipe.Type]
+ info, ok := productionTypes[craft.Type]
if !ok {
- info = productionTypeInfo{recipe.Type, recipe.Type}
+ info = productionTypeInfo{craft.Type, craft.Type}
}
actionType := info.ActionType
displayVerb := info.DisplayVerb
@@ -97,67 +116,79 @@ func (g *Game) startProductionFromRecipe(sess *net.Session, p *player.Player, re
}
endMsg = fmt.Sprintf("You've finished %s.", displayVerb)
- g.startProduction(sess, p, recipe, actionType, displayVerb, startMsg, endMsg, count)
+ g.startProduction(sess, p, item, craft, actionType, displayVerb, startMsg, endMsg, count)
}
-func (g *Game) loadRecipe(recipeID string) *action.RecipeDef {
- if r := g.RecipeStore.GetByID(recipeID); r != nil {
- return r
+func (g *Game) loadCraftItem(itemID string) *object.ItemDef {
+ item, err := g.ItemStore.Load(itemID)
+ if err != nil || len(item.Craft) == 0 {
+ return nil
}
- if strings.HasPrefix(recipeID, "combine_") {
- itemID := strings.TrimPrefix(recipeID, "combine_")
- if itemDef, err := g.ItemStore.Load(itemID); err == nil && len(itemDef.MadeFrom) > 0 {
- return g.buildCombineRecipe(itemDef)
- }
- }
- return nil
+ return item
}
func (g *Game) advanceProduction(sess *net.Session, p *player.Player) bool {
- recipeID := p.Action.Data["recipe_id"].(string)
+ itemID := p.Action.Data["item_id"].(string)
phase := p.Action.Data["phase"].(int)
wait := p.Action.Data["wait"].(float64)
startMsg, _ := p.Action.Data["start_msg"].(string)
endMsg, _ := p.Action.Data["end_msg"].(string)
remaining, _ := p.Action.Data["remaining"].(int)
- recipe := g.loadRecipe(recipeID)
- if recipe == nil {
+ item := g.loadCraftItem(itemID)
+ if item == nil {
g.cancelAction(p)
return false
}
+ craft := item.FirstCraft()
if phase == 0 {
if startMsg != "" {
sess.WriteLine(fmt.Sprintf("\n%s", startMsg))
}
+ if len(craft.Steps) > 0 {
+ p.Action.Data["next_step_index"] = 0
+ p.Action.Data["steps_accumulated_ticks"] = float64(0)
+ }
p.Action.Data["phase"] = 1
p.Action.WaitLeft = engine.ToTicks(wait)
return true
}
- skill := recipe.EffectiveSkill()
+ if stepsIdx, ok := p.Action.Data["next_step_index"].(int); ok && stepsIdx < len(craft.Steps) {
+ accTicks, _ := p.Action.Data["steps_accumulated_ticks"].(float64)
+ accTicks += wait
+ p.Action.Data["steps_accumulated_ticks"] = accTicks
+ for i := stepsIdx; i < len(craft.Steps); i++ {
+ if accTicks >= craft.Steps[i].Tick {
+ sess.WriteLine(craft.Steps[i].Message)
+ p.Action.Data["next_step_index"] = i + 1
+ }
+ }
+ }
+
+ skill := craft.EffectiveSkill()
skillLevel := p.Level(player.SkillName(skill))
chance := 1.0
- if recipe.Success != nil {
- chance = action.SuccessChance(*recipe.Success, skillLevel, recipe.Level)
+ if craft.Success != nil {
+ chance = action.SuccessChance(action.SuccessFormula(*craft.Success), skillLevel, craft.Level)
}
if rand.Float64() < chance {
- outputQty := recipe.OutputQty
+ outputQty := craft.OutputQty
if outputQty <= 0 {
outputQty = 1
}
- byproducts := g.collectByproducts(p, recipe)
+ byproducts := g.collectByproducts(p, item)
placed := false
- outDef, _ := g.ItemStore.Load(recipe.Output)
+ outDef, _ := g.ItemStore.Load(item.ID)
if outDef != nil && outDef.Stackable {
for i := 0; i < 28; i++ {
slot := p.InvSlot(i)
- if slot != nil && slot.ItemID == recipe.Output {
- recipe.ConsumeAll(p.HasItem, p.RemoveItem)
+ if slot != nil && slot.ItemID == item.ID {
+ craftConsumeAll(craft, p.HasItem, p.RemoveItem)
slot.Quantity += outputQty
placed = true
break
@@ -165,14 +196,14 @@ func (g *Game) advanceProduction(sess *net.Session, p *player.Player) bool {
}
}
if !placed {
- recipe.ConsumeAll(p.HasItem, p.RemoveItem)
+ craftConsumeAll(craft, p.HasItem, p.RemoveItem)
freeSlot := p.FirstFreeSlot()
if freeSlot == -1 {
sess.WriteLine("Your inventory is too full!")
g.cancelAction(p)
return false
}
- p.SetInvSlot(freeSlot, &player.InventorySlot{ItemID: recipe.Output, Quantity: outputQty})
+ p.SetInvSlot(freeSlot, &player.InventorySlot{ItemID: item.ID, Quantity: outputQty})
}
for _, bp := range byproducts {
@@ -181,38 +212,38 @@ func (g *Game) advanceProduction(sess *net.Session, p *player.Player) bool {
}
}
- if recipe.XP > 0 {
- if newLevel := p.AddSkillXP(player.SkillName(skill), recipe.XP); newLevel > 0 {
+ if craft.XP > 0 {
+ if newLevel := p.AddSkillXP(player.SkillName(skill), craft.XP); newLevel > 0 {
sess.WriteLine(g.colorize(sess, "level_up", fmt.Sprintf("*** You are now level %d %s! ***", newLevel, skill)))
}
}
g.AccountStore.SaveCharacter(p)
- msg := recipe.Message
+ msg := craft.Message
if msg == "" {
- outputName := recipe.Output
+ outputName := item.ID
if outDef != nil {
outputName = outDef.Name
}
msg = fmt.Sprintf("You produce %s.", outputName)
}
- if p.OptionBool("xp_drops") && recipe.XP > 0 {
+ if p.OptionBool("xp_drops") && craft.XP > 0 {
abbr := player.SkillAbbr[player.SkillName(skill)]
- msg += g.colorize(sess, "xp", fmt.Sprintf(" (+%dxp %s)", recipe.XP, abbr))
+ msg += g.colorize(sess, "xp", fmt.Sprintf(" (+%dxp %s)", craft.XP, abbr))
}
sess.WriteLine(msg)
} else {
- recipe.ConsumeAll(p.HasItem, p.RemoveItem)
+ craftConsumeAll(craft, p.HasItem, p.RemoveItem)
- if recipe.Fail != "" {
+ if craft.Fail != "" {
freeSlot := p.FirstFreeSlot()
if freeSlot >= 0 {
- p.SetInvSlot(freeSlot, &player.InventorySlot{ItemID: recipe.Fail, Quantity: 1})
+ p.SetInvSlot(freeSlot, &player.InventorySlot{ItemID: craft.Fail, Quantity: 1})
}
}
g.AccountStore.SaveCharacter(p)
- msg := recipe.FailMessage
+ msg := craft.FailMessage
if msg == "" {
msg = "You fail and the materials are lost."
}
@@ -231,7 +262,7 @@ func (g *Game) advanceProduction(sess *net.Session, p *player.Player) bool {
}
}
- if g.canContinueProduction(p, recipe) {
+ if g.canContinueProduction(p, item) {
p.Action.WaitLeft = engine.ToTicks(wait)
return true
}
@@ -243,9 +274,13 @@ func (g *Game) advanceProduction(sess *net.Session, p *player.Player) bool {
return false
}
-func (g *Game) collectByproducts(p *player.Player, recipe *action.RecipeDef) []string {
+func (g *Game) collectByproducts(p *player.Player, item *object.ItemDef) []string {
+ craft := item.FirstCraft()
+ if craft == nil {
+ return nil
+ }
var byproducts []string
- for _, e := range recipe.Consume {
+ for _, e := range craft.Consume {
if len(e.Byproducts) == 0 {
continue
}
@@ -259,19 +294,23 @@ func (g *Game) collectByproducts(p *player.Player, recipe *action.RecipeDef) []s
return byproducts
}
-func (g *Game) canContinueProduction(p *player.Player, recipe *action.RecipeDef) bool {
- if !recipe.HasAllItemsQty(p.CountItem) {
+func (g *Game) canContinueProduction(p *player.Player, item *object.ItemDef) bool {
+ craft := item.FirstCraft()
+ if craft == nil {
return false
}
- outputQty := recipe.OutputQty
+ if !craftHasAllItemsQty(craft, p.CountItem) {
+ return false
+ }
+ outputQty := craft.OutputQty
if outputQty <= 0 {
outputQty = 1
}
- outDef, _ := g.ItemStore.Load(recipe.Output)
+ outDef, _ := g.ItemStore.Load(item.ID)
if outDef != nil && outDef.Stackable {
for i := 0; i < 28; i++ {
slot := p.InvSlot(i)
- if slot != nil && slot.ItemID == recipe.Output {
+ if slot != nil && slot.ItemID == item.ID {
return true
}
}
@@ -316,7 +355,7 @@ func (g *Game) handleRecipeChoice(sess *net.Session, input string) {
if name == "" {
continue
}
- if strings.ToLower(name) == lower || action.WordPrefixMatch(input, name) {
+ if strings.ToLower(name) == lower || object.WordPrefixMatch(input, name) {
if matchIdx >= 0 {
sess.WriteLine("That's ambiguous.")
return
@@ -338,21 +377,11 @@ func (g *Game) handleRecipeChoice(sess *net.Session, input string) {
}
func (g *Game) menuEntryName(entry map[string]string) string {
- if rid, ok := entry["recipe_id"]; ok {
- if r := g.RecipeStore.GetByID(rid); r != nil {
- if def, err := g.ItemStore.Load(r.Output); err == nil {
- return def.Name
- }
- return r.Output
- }
- }
- if rid, ok := entry["fletch_recipe_id"]; ok {
- if r := g.RecipeStore.GetByID(rid); r != nil {
- if def, err := g.ItemStore.Load(r.Output); err == nil {
- return def.Name
- }
- return r.Output
+ if iid, ok := entry["item_id"]; ok {
+ if def, _ := g.ItemStore.Load(iid); def != nil {
+ return def.Name
}
+ return iid
}
if barID, ok := entry["bar_id"]; ok {
if def, _ := g.ItemStore.Load(barID); def != nil {
@@ -360,51 +389,34 @@ func (g *Game) menuEntryName(entry map[string]string) string {
}
return barID
}
- if cid, ok := entry["combine_item"]; ok {
- if def, _ := g.ItemStore.Load(cid); def != nil {
- return def.Name
- }
- return cid
- }
return ""
}
func (g *Game) dispatchMenuEntry(sess *net.Session, entry map[string]string) {
- if cid, ok := entry["combine_item"]; ok {
- g.promptHowMany(sess, "combine_"+cid)
+ if iid, ok := entry["item_id"]; ok {
+ g.promptHowMany(sess, iid)
return
}
if barID, ok := entry["bar_id"]; ok {
- p := sess.Player
- allRecipes, _ := g.RecipeStore.LoadAll()
- g.showSmithTable(sess, p, barID, allRecipes)
- return
- }
- if rid, ok := entry["fletch_recipe_id"]; ok {
- p := sess.Player
- if r := g.RecipeStore.GetByID(rid); r != nil {
- g.startFletchAction(sess, p, r, 0)
- return
- }
- g.reprompt(sess)
- return
- }
- if rid, ok := entry["recipe_id"]; ok {
- g.promptHowMany(sess, rid)
+ g.showSmithTable(sess, sess.Player, barID)
return
}
g.reprompt(sess)
}
-func (g *Game) formatMaterials(r *action.RecipeDef) string {
+func (g *Game) formatMaterials(item *object.ItemDef) string {
+ craft := item.FirstCraft()
+ if craft == nil {
+ return ""
+ }
var parts []string
- for _, e := range r.Consume {
+ for _, e := range craft.Consume {
itemName := e.Items[0]
if def, err := g.ItemStore.Load(e.Items[0]); err == nil {
itemName = def.Name
}
- if e.Quantity > 1 {
- parts = append(parts, fmt.Sprintf("%s x%d", itemName, e.Quantity))
+ if e.Quantity > 1 {
+ parts = append(parts, fmt.Sprintf("%s x%d", itemName, e.Quantity))
} else {
parts = append(parts, itemName)
}
@@ -412,9 +424,9 @@ func (g *Game) formatMaterials(r *action.RecipeDef) string {
return strings.Join(parts, ", ")
}
-func (g *Game) showProductionTable(sess *net.Session, p *player.Player, recipes []action.RecipeDef, title, skill, lastFlagKey, promptVerb string, background bool) {
- sort.Slice(recipes, func(i, j int) bool {
- return recipes[i].Level < recipes[j].Level
+func (g *Game) showProductionTable(sess *net.Session, p *player.Player, items []*object.ItemDef, title, skill, lastFlagKey, promptVerb string, background bool) {
+ sort.Slice(items, func(i, j int) bool {
+ return items[i].FirstCraft().Level < items[j].FirstCraft().Level
})
mode := g.colorMode(sess)
@@ -426,14 +438,15 @@ func (g *Game) showProductionTable(sess *net.Session, p *player.Player, recipes
Columns: []string{"#", "Product", "Materials", "Level"},
}
- for i, r := range recipes {
- outDef, _ := g.ItemStore.Load(r.Output)
- productName := r.Output
+ for i, item := range items {
+ craft := item.FirstCraft()
+ outDef, _ := g.ItemStore.Load(item.ID)
+ productName := item.ID
if outDef != nil {
productName = outDef.Name
}
- outputQty := r.OutputQty
+ outputQty := craft.OutputQty
if outputQty <= 0 {
outputQty = 1
}
@@ -441,11 +454,11 @@ func (g *Game) showProductionTable(sess *net.Session, p *player.Player, recipes
productName = fmt.Sprintf("%s x%d", productName, outputQty)
}
- matStr := g.formatMaterials(&r)
- levelStr := fmt.Sprint(r.Level)
+ matStr := g.formatMaterials(item)
+ levelStr := fmt.Sprint(craft.Level)
numStr := fmt.Sprintf("%d", i+1)
- canMake := skillLevel >= r.Level && r.HasAllItemsQty(p.CountItem)
+ canMake := skillLevel >= craft.Level && craftHasAllItemsQty(craft, p.CountItem)
if canMake {
productName = g.itemColorize(sess, outDef, productName)
} else {
@@ -464,12 +477,12 @@ func (g *Game) showProductionTable(sess *net.Session, p *player.Player, recipes
sess.WriteLine(line)
}
- lastRecipeID, _ := p.Flags[lastFlagKey].(string)
+ lastItemID, _ := p.Flags[lastFlagKey].(string)
hint := ""
- if lastRecipeID != "" {
- for _, r := range recipes {
- if r.ID == lastRecipeID {
- if outDef, err := g.ItemStore.Load(r.Output); err == nil {
+ if lastItemID != "" {
+ for _, item := range items {
+ if item.ID == lastItemID {
+ if outDef, err := g.ItemStore.Load(item.ID); err == nil {
hint = outDef.Name
}
break
@@ -483,7 +496,7 @@ func (g *Game) showProductionTable(sess *net.Session, p *player.Player, recipes
sess.Write(fmt.Sprintf("%s what: ", promptVerb))
}
- sess.PendingMenu = recipeMenuData(recipeDefIDs(recipes))
+ sess.PendingMenu = itemMenuData(itemIDs(items))
sess.PendingSkill = skill
sess.PendingLastFlag = lastFlagKey
sess.PendingBackground = background
@@ -504,26 +517,26 @@ func (g *Game) handleProductChoice(sess *net.Session, input string) {
input = strings.TrimSpace(input)
- var recipes []action.RecipeDef
+ var items []*object.ItemDef
for _, entry := range menuData {
- rid := entry["recipe_id"]
- if r := g.RecipeStore.GetByID(rid); r != nil {
- recipes = append(recipes, *r)
+ iid := entry["item_id"]
+ if item := g.loadCraftItem(iid); item != nil {
+ items = append(items, item)
}
}
- if len(recipes) == 0 {
+ if len(items) == 0 {
g.reprompt(sess)
return
}
- sort.Slice(recipes, func(i, j int) bool {
- return recipes[i].Level < recipes[j].Level
+ sort.Slice(items, func(i, j int) bool {
+ return items[i].FirstCraft().Level < items[j].FirstCraft().Level
})
- lastRecipeID, _ := p.Flags[lastFlagKey].(string)
+ lastItemID, _ := p.Flags[lastFlagKey].(string)
- sel, errMsg := g.resolveRecipeByInput(input, recipes, lastRecipeID)
+ sel, errMsg := g.resolveCraftByInput(input, items, lastItemID)
switch errMsg {
case "ambiguous":
sess.WriteLine("That's ambiguous.")
@@ -535,26 +548,27 @@ func (g *Game) handleProductChoice(sess *net.Session, input string) {
return
}
+ craft := sel.Item.FirstCraft()
skillLevel := p.Level(player.SkillName(skill))
- if skillLevel < sel.Recipe.Level {
- sess.WriteLine(fmt.Sprintf("You need level %d %s to make that.", sel.Recipe.Level, skill))
+ if skillLevel < craft.Level {
+ sess.WriteLine(fmt.Sprintf("You need level %d %s to make that.", craft.Level, skill))
g.reprompt(sess)
return
}
- if !sel.Recipe.HasAllItemsQty(p.CountItem) {
+ if !craftHasAllItemsQty(craft, p.CountItem) {
sess.WriteLine("You don't have the materials for that.")
g.reprompt(sess)
return
}
p.EnsureFlags()
- p.Flags[lastFlagKey] = sel.Recipe.ID
+ p.Flags[lastFlagKey] = sel.Item.ID
g.AccountStore.SaveCharacter(p)
if background {
- g.startFletchAction(sess, p, sel.Recipe, sel.Count)
+ g.startFletchAction(sess, p, sel.Item, sel.Count)
} else {
- g.startProductionFromRecipe(sess, p, sel.Recipe, sel.Count)
+ g.startProductionFromItem(sess, p, sel.Item, sel.Count)
}
}
@@ -591,10 +605,6 @@ func (g *Game) hasToolType(p *player.Player, toolType string) bool {
_, _, found := g.findTool(p, []string{toolType})
return found
}
-type recipeEntry struct {
- ItemName string
- Recipe action.RecipeDef
-}
type productionTypeInfo struct {
ActionType string
@@ -621,15 +631,15 @@ func init() {
}
}
-func recipeMenuData(recipeIDs []string) []map[string]string {
- out := make([]map[string]string, len(recipeIDs))
- for i, id := range recipeIDs {
- out[i] = map[string]string{"recipe_id": id}
+func itemMenuData(itemIDs []string) []map[string]string {
+ out := make([]map[string]string, len(itemIDs))
+ for i, id := range itemIDs {
+ out[i] = map[string]string{"item_id": id}
}
return out
}
-func recipeDefIDs(defs []action.RecipeDef) []string {
+func itemIDs(defs []*object.ItemDef) []string {
ids := make([]string, len(defs))
for i, d := range defs {
ids[i] = d.ID
@@ -637,33 +647,25 @@ func recipeDefIDs(defs []action.RecipeDef) []string {
return ids
}
-func entryMenuData(entries []recipeEntry) []map[string]string {
- out := make([]map[string]string, len(entries))
- for i, e := range entries {
- out[i] = map[string]string{"recipe_id": e.Recipe.ID}
- }
- return out
-}
-
-func (g *Game) promptHowMany(sess *net.Session, recipeID string) {
- sess.PendingRecipeID = recipeID
+func (g *Game) promptHowMany(sess *net.Session, itemID string) {
+ sess.PendingItemID = itemID
sess.State = net.StateHowMany
sess.Write("How many (return for all)?: ")
}
-type recipeSelection struct {
- Recipe *action.RecipeDef
- Count int
+type craftSelection struct {
+ Item *object.ItemDef
+ Count int
}
-func (g *Game) resolveRecipeByInput(input string, recipes []action.RecipeDef, lastRecipeID string) (sel recipeSelection, errMsg string) {
+func (g *Game) resolveCraftByInput(input string, items []*object.ItemDef, lastItemID string) (sel craftSelection, errMsg string) {
if input == "" {
- if lastRecipeID == "" {
+ if lastItemID == "" {
return sel, "never_mind"
}
- for i := range recipes {
- if recipes[i].ID == lastRecipeID {
- sel.Recipe = &recipes[i]
+ for i := range items {
+ if items[i].ID == lastItemID {
+ sel.Item = items[i]
return sel, ""
}
}
@@ -673,22 +675,22 @@ func (g *Game) resolveRecipeByInput(input string, recipes []action.RecipeDef, la
qty, productName := parseQty(input)
productName = strings.TrimSpace(productName)
- if idx, err := strconv.Atoi(productName); err == nil && idx > 0 && idx <= len(recipes) {
- sel.Recipe = &recipes[idx-1]
+ if idx, err := strconv.Atoi(productName); err == nil && idx > 0 && idx <= len(items) {
+ sel.Item = items[idx-1]
sel.Count = qty
return sel, ""
}
matchCount := 0
- for i := range recipes {
- outDef, _ := g.ItemStore.Load(recipes[i].Output)
- name := recipes[i].Output
+ for i := range items {
+ outDef, _ := g.ItemStore.Load(items[i].ID)
+ name := items[i].ID
if outDef != nil {
name = outDef.Name
}
- if action.WordPrefixMatch(productName, name) {
+ if object.WordPrefixMatch(productName, name) {
if matchCount == 0 {
- sel.Recipe = &recipes[i]
+ sel.Item = items[i]
sel.Count = qty
}
matchCount++
@@ -697,7 +699,7 @@ func (g *Game) resolveRecipeByInput(input string, recipes []action.RecipeDef, la
if matchCount > 1 {
return sel, "ambiguous"
}
- if sel.Recipe == nil {
+ if sel.Item == nil {
return sel, "never_mind"
}
return sel, ""
@@ -716,41 +718,42 @@ func (g *Game) showMenuTable(sess *net.Session, title string, names []string) {
}
}
-func (g *Game) recipeName(sess *net.Session, r *action.RecipeDef) string {
- if r.Output != "" {
- if def, err := g.ItemStore.Load(r.Output); err == nil {
+func (g *Game) itemName(sess *net.Session, item *object.ItemDef) string {
+ if item != nil {
+ if def, err := g.ItemStore.Load(item.ID); err == nil {
return g.itemColorize(sess, def, def.Name)
}
+ return item.ID
}
- return r.DisplayName()
+ return ""
}
-func (g *Game) showRecipeChoice(sess *net.Session, p *player.Player, recipes []action.RecipeDef, emptyMsg, title string, autoOption string) {
- if len(recipes) == 0 {
+func (g *Game) showRecipeChoice(sess *net.Session, p *player.Player, items []*object.ItemDef, emptyMsg, title string, autoOption string) {
+ if len(items) == 0 {
sess.WriteLine(emptyMsg)
return
}
- if len(recipes) == 1 {
+ if len(items) == 1 {
if autoOption != "" && p.OptionBool(autoOption) {
- g.startProductionFromRecipe(sess, p, &recipes[0], 0)
+ g.startProductionFromItem(sess, p, items[0], 0)
return
}
- g.promptHowMany(sess, recipes[0].ID)
+ g.promptHowMany(sess, items[0].ID)
return
}
sess.State = net.StateRecipeChoice
- sess.PendingMenu = recipeMenuData(recipeDefIDs(recipes))
+ sess.PendingMenu = itemMenuData(itemIDs(items))
var names []string
- for i := range recipes {
- names = append(names, g.recipeName(sess, &recipes[i]))
+ for _, item := range items {
+ names = append(names, g.itemName(sess, item))
}
g.showMenuTable(sess, title, names)
}
func (g *Game) handleHowMany(sess *net.Session, input string) {
p := sess.Player
- recipeID := sess.PendingRecipeID
- sess.PendingRecipeID = ""
+ itemID := sess.PendingItemID
+ sess.PendingItemID = ""
sess.State = net.StateGame
input = strings.TrimSpace(input)
@@ -766,46 +769,11 @@ func (g *Game) handleHowMany(sess *net.Session, input string) {
return
}
- var recipe *action.RecipeDef
- if strings.HasPrefix(recipeID, "combine_") {
- itemID := strings.TrimPrefix(recipeID, "combine_")
- itemDef, err := g.ItemStore.Load(itemID)
- if err != nil || len(itemDef.MadeFrom) == 0 {
- g.reprompt(sess)
- return
- }
- recipe = g.buildCombineRecipe(itemDef)
- } else {
- recipe = g.RecipeStore.GetByID(recipeID)
- }
-
- if recipe == nil {
+ item := g.loadCraftItem(itemID)
+ if item == nil {
g.reprompt(sess)
return
}
- g.startProductionFromRecipe(sess, p, recipe, count)
-}
-
-func (g *Game) buildCombineRecipe(def *object.ItemDef) *action.RecipeDef {
- var consume []action.ConsumeEntry
- for _, mf := range def.MadeFrom {
- consume = append(consume, action.ConsumeEntry{
- Items: mf.Items,
- Quantity: mf.Quantity,
- Byproducts: mf.Byproducts,
- })
- }
- wait := def.Ticks
- if wait <= 0 {
- wait = 2
- }
- return &action.RecipeDef{
- ID: "combine_" + def.ID,
- Type: "combine",
- Wait: wait,
- Consume: consume,
- Output: def.ID,
- Message: fmt.Sprintf("You create %s.", def.Name),
- }
+ g.startProductionFromItem(sess, p, item, count)
}