aboutsummaryrefslogtreecommitdiff
path: root/internal/game/core_production.go
diff options
context:
space:
mode:
Diffstat (limited to 'internal/game/core_production.go')
-rw-r--r--internal/game/core_production.go779
1 files changed, 12 insertions, 767 deletions
diff --git a/internal/game/core_production.go b/internal/game/core_production.go
index 56d1ccc..8a38f36 100644
--- a/internal/game/core_production.go
+++ b/internal/game/core_production.go
@@ -1,622 +1,14 @@
package game
import (
- "fmt"
- "math/rand"
- "sort"
- "strconv"
- "strings"
-
- "thehouseoficarus/internal/action"
- "thehouseoficarus/internal/color"
- "thehouseoficarus/internal/engine"
- "thehouseoficarus/internal/net"
- "thehouseoficarus/internal/object"
+ "thehouseoficarus/internal/behavior"
+ "thehouseoficarus/internal/item"
"thehouseoficarus/internal/player"
)
-func (g *Game) resolveCraftVar(sess *net.Session, varSpec string, craft *object.CraftDef, outputID string, byproducts []string, hasItem func(string) bool) string {
- if !strings.Contains(varSpec, "%") {
- return varSpec
- }
-
- outDef, _ := g.ItemStore.Load(outputID)
- outputName := outputID
- if outDef != nil {
- outputName = g.itemColorize(sess, outDef, outDef.Name)
- }
- varSpec = strings.ReplaceAll(varSpec, "%n", outputName)
-
- for i, e := range craft.Consume {
- key := fmt.Sprintf("%%i%d", i+1)
- if !strings.Contains(varSpec, key) {
- continue
- }
- var matchedID string
- for _, id := range e.Items {
- if hasItem(id) {
- matchedID = id
- break
- }
- }
- if matchedID == "" && len(e.Items) > 0 {
- matchedID = e.Items[0]
- }
- if def, err := g.ItemStore.Load(matchedID); err == nil {
- varSpec = strings.ReplaceAll(varSpec, key, g.itemColorize(sess, def, def.Name))
- } else {
- varSpec = strings.ReplaceAll(varSpec, key, matchedID)
- }
- }
-
- for i, bpID := range byproducts {
- key := fmt.Sprintf("%%b%d", i+1)
- if !strings.Contains(varSpec, key) {
- continue
- }
- if def, err := g.ItemStore.Load(bpID); err == nil {
- varSpec = strings.ReplaceAll(varSpec, key, g.itemColorize(sess, def, def.Name))
- } else {
- varSpec = strings.ReplaceAll(varSpec, key, bpID)
- }
- }
-
- return color.ExpandTags(g.colorMode(sess), varSpec)
-}
-
-func (g *Game) resolveCraftMessage(sess *net.Session, itemMsg, defaultMsg string, craft *object.CraftDef, outputID string, byproducts []string, hasItem func(string) bool) string {
- msg := itemMsg
- if msg == "" {
- msg = defaultMsg
- }
- if msg == "" {
- return ""
- }
- return g.resolveCraftVar(sess, msg, craft, outputID, byproducts, hasItem)
-}
-
-func (g *Game) startProduction(sess *net.Session, p *player.Player, item *object.ItemDef, craft *object.CraftDef, actionType action.ActionType, displayVerb, startMsg, endMsg string, count int) {
- g.cancelAction(p)
- g.cancelBgAction(p)
-
- skill := craft.EffectiveSkill()
- if skill != "" {
- skillLevel := p.Level(player.SkillName(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 !craftHasAllItemsQty(craft, p.CountItem) {
- sess.WriteLine("You don't have the required materials.")
- g.reprompt(sess)
- return
- }
-
- outDef, _ := g.ItemStore.Load(item.ID)
-
- wait := craft.Wait
- if wait <= 0 {
- wait = 4
- }
-
- outputName := item.ID
- if outDef != nil {
- outputName = outDef.Name
- }
-
- p.Action = &action.Action{
- Type: actionType,
- TargetID: item.ID,
- TargetName: outputName,
- Data: &action.ProductionData{
- ItemID: item.ID,
- Phase: 0,
- Wait: wait,
- StartMsg: startMsg,
- EndMsg: endMsg,
- Remaining: count,
- },
- WaitLeft: engine.ToTicks(1),
- }
-
- g.broadcastAction(sess, "%s starts %s.", p.Name, displayVerb)
-}
-
-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"
- }
-
- info, ok := productionTypes[craft.Type]
- if !ok {
- info = productionTypeInfo{
- ActionType: action.ActionType(craft.Type),
- DisplayVerb: craft.Type,
- StartMessage: "You start " + craft.Type + " %i1.",
- SuccessMessage: "You produce %n.",
- EndMessage: "You've finished " + craft.Type + ".",
- }
- }
-
- startMsg := g.resolveCraftMessage(sess, craft.StartMessage, info.StartMessage, craft, item.ID, nil, p.HasItem)
- if stationName != "inventory" {
- startMsg += " on the " + stationName + "."
- }
-
- endMsg := g.resolveCraftMessage(sess, craft.EndMessage, info.EndMessage, craft, item.ID, nil, p.HasItem)
-
- g.startProduction(sess, p, item, craft, info.ActionType, info.DisplayVerb, startMsg, endMsg, count)
-}
-
-func (g *Game) loadCraftItem(itemID string) *object.ItemDef {
- item, err := g.ItemStore.Load(itemID)
- if err != nil || len(item.Craft) == 0 {
- return nil
- }
- return item
-}
-
-func (g *Game) advanceProduction(sess *net.Session, p *player.Player) bool {
- d, ok := p.Action.Data.(*action.ProductionData)
- if !ok {
- g.cancelAction(p)
- return false
- }
- itemID := d.ItemID
- phase := d.Phase
- wait := d.Wait
- startMsg := d.StartMsg
- endMsg := d.EndMsg
- remaining := d.Remaining
-
- item := g.loadCraftItem(itemID)
- if item == nil {
- g.cancelAction(p)
- return false
- }
- craft := item.FirstCraft()
-
- if phase == 0 {
- if startMsg != "" {
- sess.WriteLine(startMsg)
- }
- if len(craft.Steps) > 0 {
- d.NextStepIndex = 0
- d.StepsAccumulatedTicks = 0
- }
- d.Phase = 1
- p.Action.WaitLeft = engine.ToTicks(wait)
- return true
- }
-
- if stepsIdx := d.NextStepIndex; stepsIdx < len(craft.Steps) {
- accTicks := d.StepsAccumulatedTicks
- accTicks += wait
- d.StepsAccumulatedTicks = accTicks
- for i := stepsIdx; i < len(craft.Steps); i++ {
- if accTicks >= craft.Steps[i].Tick {
- sess.WriteLine(g.resolveCraftVar(sess, craft.Steps[i].Message, craft, item.ID, nil, p.HasItem))
- d.NextStepIndex = i + 1
- }
- }
- }
-
- skill := craft.EffectiveSkill()
- skillLevel := p.Level(player.SkillName(skill))
- chance := 1.0
- if craft.Success != nil {
- chance = action.SuccessChance(action.SuccessFormula(*craft.Success), skillLevel, craft.Level)
- }
-
- info, _ := productionTypes[craft.Type]
-
- if rand.Float64() < chance {
- outputQty := craft.OutputQty
- if outputQty <= 0 {
- outputQty = 1
- }
-
- byproducts := g.collectByproducts(p, item)
-
- placed := false
- 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 == item.ID {
- craftConsumeAll(craft, p.HasItem, p.RemoveItem)
- slot.Quantity += outputQty
- placed = true
- break
- }
- }
- }
- if !placed {
- 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: item.ID, Quantity: outputQty})
- }
-
- for _, bp := range byproducts {
- if slot := p.FirstFreeSlot(); slot >= 0 {
- p.SetInvSlot(slot, &player.InventorySlot{ItemID: bp, Quantity: 1})
- }
- }
-
- 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)
-
- var defaultSuccess string
- if info.SuccessMessage != "" {
- defaultSuccess = info.SuccessMessage
- } else {
- defaultSuccess = "You produce %n."
- }
- msg := g.resolveCraftMessage(sess, craft.Message, defaultSuccess, craft, item.ID, byproducts, p.HasItem)
- if p.OptionBool("xp_drops") && craft.XP > 0 {
- msg += g.formatXpDropSingle(sess, p, player.SkillName(skill), craft.XP)
- }
- sess.WriteLine(msg)
- } else {
- craftConsumeAll(craft, p.HasItem, p.RemoveItem)
-
- if craft.Fail != "" {
- freeSlot := p.FirstFreeSlot()
- if freeSlot >= 0 {
- p.SetInvSlot(freeSlot, &player.InventorySlot{ItemID: craft.Fail, Quantity: 1})
- }
- }
- g.AccountStore.SaveCharacter(p)
-
- msg := g.resolveCraftMessage(sess, craft.FailMessage, info.FailMessage, craft, item.ID, nil, p.HasItem)
- if msg != "" {
- sess.WriteLine(g.colorize(sess, "damage_taken", msg))
- }
- }
-
- if remaining > 0 {
- remaining--
- d.Remaining = remaining
- if remaining <= 0 {
- if endMsg != "" {
- sess.WriteLine(endMsg)
- }
- g.cancelAction(p)
- return false
- }
- }
-
- if g.canContinueProduction(p, item) {
- p.Action.WaitLeft = engine.ToTicks(wait)
- return true
- }
-
- if endMsg != "" {
- sess.WriteLine(endMsg)
- }
- g.cancelAction(p)
- return false
-}
-
-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 craft.Consume {
- if len(e.Byproducts) == 0 {
- continue
- }
- for i, id := range e.Items {
- if p.HasItem(id) && i < len(e.Byproducts) && e.Byproducts[i] != "" {
- byproducts = append(byproducts, e.Byproducts[i])
- break
- }
- }
- }
- return byproducts
-}
-
-func (g *Game) canContinueProduction(p *player.Player, item *object.ItemDef) bool {
- craft := item.FirstCraft()
- if craft == nil {
- return false
- }
- if !craftHasAllItemsQty(craft, p.CountItem) {
- return false
- }
- outputQty := craft.OutputQty
- if outputQty <= 0 {
- outputQty = 1
- }
- 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 == item.ID {
- return true
- }
- }
- }
- return p.FirstFreeSlot() >= 0
-}
-
-func (g *Game) handleRecipeChoice(sess *net.Session, input string) {
- input = strings.TrimSpace(input)
-
- menuData := sess.PendingMenu
- if len(menuData) == 0 {
- sess.State = net.StateGame
- g.reprompt(sess)
- return
- }
-
- if input == "" {
- sess.PendingMenu = nil
- sess.State = net.StateGame
- sess.WriteLine("Never mind.")
- g.reprompt(sess)
- return
- }
-
- if choice, err := strconv.Atoi(input); err == nil {
- sess.PendingMenu = nil
- sess.State = net.StateGame
- if choice <= 0 || choice > len(menuData) {
- sess.WriteLine("Never mind.")
- g.reprompt(sess)
- return
- }
- g.dispatchMenuEntry(sess, menuData[choice-1])
- return
- }
-
- lower := strings.ToLower(input)
- matchIdx := -1
- for i, entry := range menuData {
- name := g.menuEntryName(entry)
- if name == "" {
- continue
- }
- if strings.ToLower(name) == lower || object.WordPrefixMatch(input, name) {
- if matchIdx >= 0 {
- sess.WriteLine("That's ambiguous.")
- return
- }
- matchIdx = i
- }
- }
- if matchIdx >= 0 {
- sess.PendingMenu = nil
- sess.State = net.StateGame
- g.dispatchMenuEntry(sess, menuData[matchIdx])
- return
- }
-
- sess.PendingMenu = nil
- sess.State = net.StateGame
- sess.WriteLine("Never mind.")
- g.reprompt(sess)
-}
-
-func (g *Game) menuEntryName(entry map[string]string) string {
- 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 {
- return def.Name
- }
- return barID
- }
- return ""
-}
-
-func (g *Game) dispatchMenuEntry(sess *net.Session, entry map[string]string) {
- if iid, ok := entry["item_id"]; ok {
- g.promptHowMany(sess, iid)
- return
- }
- if barID, ok := entry["bar_id"]; ok {
- g.showSmithTable(sess, sess.Player, barID)
- return
- }
- g.reprompt(sess)
-}
-
-func (g *Game) formatMaterials(sess *net.Session, item *object.ItemDef) string {
- craft := item.FirstCraft()
- if craft == nil {
- return ""
- }
- var parts []string
- for _, e := range craft.Consume {
- itemName := e.Items[0]
- if def, err := g.ItemStore.Load(e.Items[0]); err == nil {
- itemName = g.itemColorize(sess, def, def.Name)
- }
- if e.Quantity > 1 {
- parts = append(parts, fmt.Sprintf("%s x%d", itemName, e.Quantity))
- } else {
- parts = append(parts, itemName)
- }
- }
- return strings.Join(parts, ", ")
-}
-
-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)
- skillLevel := p.Level(player.SkillName(skill))
- dimSpec := color.Parse("240")
-
- tbl := &Table{
- Title: title,
- Columns: []string{"#", "Product", "Materials", "Level"},
- }
-
- for i, item := range items {
- craft := item.FirstCraft()
- outDef, _ := g.ItemStore.Load(item.ID)
- productName := item.ID
- if outDef != nil {
- productName = outDef.Name
- }
-
- outputQty := craft.OutputQty
- if outputQty <= 0 {
- outputQty = 1
- }
- if outDef != nil && outDef.Stackable && outputQty > 1 {
- productName = fmt.Sprintf("%s x%d", productName, outputQty)
- }
-
- matStr := g.formatMaterials(sess, item)
- levelStr := fmt.Sprint(craft.Level)
- numStr := fmt.Sprintf("%d", i+1)
-
- canMake := skillLevel >= craft.Level && craftHasAllItemsQty(craft, p.CountItem)
- if canMake {
- productName = g.itemColorize(sess, outDef, productName)
- } else {
- productName = color.Render(mode, dimSpec, productName)
- matStr = color.Render(mode, dimSpec, matStr)
- levelStr = color.Render(mode, dimSpec, levelStr)
- numStr = color.Render(mode, dimSpec, numStr)
- }
-
- tbl.Rows = append(tbl.Rows, []string{numStr, productName, matStr, levelStr})
- }
-
- unicode := p.OptionBool("unicode")
- sess.WriteLine("")
- for _, line := range tbl.Render(unicode) {
- sess.WriteLine(line)
- }
-
- lastItemID, _ := p.Flags[lastFlagKey].(string)
- hint := ""
- if lastItemID != "" {
- for _, item := range items {
- if item.ID == lastItemID {
- if outDef, err := g.ItemStore.Load(item.ID); err == nil {
- hint = outDef.Name
- }
- break
- }
- }
- }
-
- if hint != "" {
- sess.Write(fmt.Sprintf("%s what (enter for all %s): ", promptVerb, hint))
- } else {
- sess.Write(fmt.Sprintf("%s what: ", promptVerb))
- }
-
- sess.PendingMenu = itemMenuData(itemIDs(items))
- sess.PendingSkill = skill
- sess.PendingLastFlag = lastFlagKey
- sess.PendingBackground = background
- sess.State = net.StateProductChoice
-}
-
-func (g *Game) handleProductChoice(sess *net.Session, input string) {
- p := sess.Player
- menuData := sess.PendingMenu
- skill := sess.PendingSkill
- lastFlagKey := sess.PendingLastFlag
- background := sess.PendingBackground
- sess.PendingMenu = nil
- sess.PendingSkill = ""
- sess.PendingLastFlag = ""
- sess.PendingBackground = false
- sess.State = net.StateGame
-
- input = strings.TrimSpace(input)
-
- var items []*object.ItemDef
- for _, entry := range menuData {
- iid := entry["item_id"]
- if item := g.loadCraftItem(iid); item != nil {
- items = append(items, item)
- }
- }
-
- if len(items) == 0 {
- g.reprompt(sess)
- return
- }
-
- sort.Slice(items, func(i, j int) bool {
- return items[i].FirstCraft().Level < items[j].FirstCraft().Level
- })
-
- lastItemID, _ := p.Flags[lastFlagKey].(string)
-
- sel, errMsg := g.resolveCraftByInput(input, items, lastItemID)
- switch errMsg {
- case "ambiguous":
- sess.WriteLine("That's ambiguous.")
- g.reprompt(sess)
- return
- case "never_mind":
- sess.WriteLine("Never mind.")
- g.reprompt(sess)
- return
- }
-
- craft := sel.Item.FirstCraft()
- skillLevel := p.Level(player.SkillName(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 !craftHasAllItemsQty(craft, p.CountItem) {
- sess.WriteLine("You don't have the materials for that.")
- g.reprompt(sess)
- return
- }
-
- p.EnsureFlags()
- p.Flags[lastFlagKey] = sel.Item.ID
- g.AccountStore.SaveCharacter(p)
-
- if background {
- g.startFletchAction(sess, p, sel.Item, sel.Count)
- } else {
- g.startProductionFromItem(sess, p, sel.Item, sel.Count)
- }
-}
-
func (g *Game) findTool(p *player.Player, toolTypes []string) (toolSpeed float64, toolName string, found bool) {
toolSpeed = -1
- if itemID, ok := p.Equipment[object.SlotMainHand]; ok {
+ if itemID, ok := p.Equipment[item.SlotMainHand]; ok {
if def, err := g.ItemStore.Load(itemID); err == nil {
for _, t := range toolTypes {
if def.ToolType == t {
@@ -649,7 +41,7 @@ func (g *Game) hasToolType(p *player.Player, toolType string) bool {
}
type productionTypeInfo struct {
- ActionType action.ActionType
+ ActionType behavior.ActionType
DisplayVerb string
StartMessage string
SuccessMessage string
@@ -659,7 +51,7 @@ type productionTypeInfo struct {
var productionTypes = map[string]productionTypeInfo{
"cooking": {
- ActionType: action.TypeCook,
+ ActionType: behavior.TypeCook,
DisplayVerb: "cooking",
StartMessage: "You start cooking %i1.",
SuccessMessage: "Cooked to perfection. %n looks great!",
@@ -667,7 +59,7 @@ var productionTypes = map[string]productionTypeInfo{
FailMessage: "You accidentally burn the %i1.",
},
"smelting": {
- ActionType: action.TypeSmelt,
+ ActionType: behavior.TypeSmelt,
DisplayVerb: "smelting",
StartMessage: "You place the %i1 into the furnace.",
SuccessMessage: "You remove a white hot %n!",
@@ -675,42 +67,42 @@ var productionTypes = map[string]productionTypeInfo{
FailMessage: "The %i1 is consumed by the flames.",
},
"smithing": {
- ActionType: action.TypeSmith,
+ ActionType: behavior.TypeSmith,
DisplayVerb: "smithing",
StartMessage: "You begin smithing %i1.",
SuccessMessage: "You smith a %n.",
EndMessage: "You've finished smithing.",
},
"crafting": {
- ActionType: action.TypeCraft,
+ ActionType: behavior.TypeCraft,
DisplayVerb: "crafting",
StartMessage: "You begin crafting %i1.",
SuccessMessage: "You craft a %n.",
EndMessage: "You've finished crafting.",
},
"combine": {
- ActionType: action.TypeCombine,
+ ActionType: behavior.TypeCombine,
DisplayVerb: "combining",
StartMessage: "You start combining %i1.",
SuccessMessage: "You produce %n.",
EndMessage: "You've finished combining.",
},
"fletching": {
- ActionType: action.TypeFletch,
+ ActionType: behavior.TypeFletch,
DisplayVerb: "fletching",
StartMessage: "You begin fletching %i1.",
SuccessMessage: "You fletch a %n.",
EndMessage: "You've finished fletching.",
},
"pharmacy": {
- ActionType: action.TypeMix,
+ ActionType: behavior.TypeMix,
DisplayVerb: "mixing",
StartMessage: "You start mixing %i1.",
SuccessMessage: "You mix a %n.",
EndMessage: "You've finished mixing.",
},
"construction": {
- ActionType: action.TypeConstruct,
+ ActionType: behavior.TypeConstruct,
DisplayVerb: "constructing",
StartMessage: "You begin constructing %i1.",
SuccessMessage: "You construct a %n.",
@@ -726,150 +118,3 @@ func init() {
productionActionTypes[string(pt.ActionType)] = true
}
}
-
-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 itemIDs(defs []*object.ItemDef) []string {
- ids := make([]string, len(defs))
- for i, d := range defs {
- ids[i] = d.ID
- }
- return ids
-}
-
-func (g *Game) promptHowMany(sess *net.Session, itemID string) {
- sess.PendingItemID = itemID
- sess.State = net.StateHowMany
- sess.Write("How many (return for all)?: ")
-}
-
-type craftSelection struct {
- Item *object.ItemDef
- Count int
-}
-
-func (g *Game) resolveCraftByInput(input string, items []*object.ItemDef, lastItemID string) (sel craftSelection, errMsg string) {
- if input == "" {
- if lastItemID == "" {
- return sel, "never_mind"
- }
- for i := range items {
- if items[i].ID == lastItemID {
- sel.Item = items[i]
- return sel, ""
- }
- }
- return sel, "never_mind"
- }
-
- qty, productName := parseQty(input)
- productName = strings.TrimSpace(productName)
-
- 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 items {
- outDef, _ := g.ItemStore.Load(items[i].ID)
- name := items[i].ID
- if outDef != nil {
- name = outDef.Name
- }
- if object.WordPrefixMatch(productName, name) {
- if matchCount == 0 {
- sel.Item = items[i]
- sel.Count = qty
- }
- matchCount++
- }
- }
- if matchCount > 1 {
- return sel, "ambiguous"
- }
- if sel.Item == nil {
- return sel, "never_mind"
- }
- return sel, ""
-}
-
-func (g *Game) showMenuTable(sess *net.Session, title string, names []string) {
- p := sess.Player
- tbl := &Table{Title: title}
- for i, name := range names {
- tbl.Rows = append(tbl.Rows, []string{fmt.Sprintf("%d", i+1), name})
- }
- unicode := p.OptionBool("unicode")
- sess.WriteLine("")
- for _, line := range tbl.Render(unicode) {
- sess.WriteLine(line)
- }
-}
-
-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 ""
-}
-
-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(items) == 1 {
- if autoOption != "" && p.OptionBool(autoOption) {
- g.startProductionFromItem(sess, p, items[0], 0)
- return
- }
- g.promptHowMany(sess, items[0].ID)
- return
- }
- sess.State = net.StateRecipeChoice
- sess.PendingMenu = itemMenuData(itemIDs(items))
- var names []string
- 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
- itemID := sess.PendingItemID
- sess.PendingItemID = ""
- sess.State = net.StateGame
-
- input = strings.TrimSpace(input)
-
- var count int
- if input == "" {
- count = 0
- } else if n, err := strconv.Atoi(input); err == nil && n > 0 {
- count = n
- } else {
- sess.WriteLine("Never mind.")
- g.reprompt(sess)
- return
- }
-
- item := g.loadCraftItem(itemID)
- if item == nil {
- g.reprompt(sess)
- return
- }
-
- g.startProductionFromItem(sess, p, item, count)
-}