diff options
Diffstat (limited to 'internal/game/core_production.go')
| -rw-r--r-- | internal/game/core_production.go | 202 |
1 files changed, 148 insertions, 54 deletions
diff --git a/internal/game/core_production.go b/internal/game/core_production.go index 4aecc54..47a164c 100644 --- a/internal/game/core_production.go +++ b/internal/game/core_production.go @@ -15,19 +15,64 @@ import ( "thehouseoficarus/internal/player" ) -func craftFirstItemName(c *object.CraftDef, load func(string) (string, bool)) string { - if c == nil { - return "" +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 } - for _, e := range c.Consume { + + 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 name, ok := load(id); ok { - return name + if hasItem(id) { + matchedID = id + break } - return id + } + 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) } } - return "" + + 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, displayVerb, startMsg, endMsg string, count int) { @@ -79,7 +124,7 @@ func (g *Game) startProduction(sess *net.Session, p *player.Player, item *object p.ActionState = &ActionState{Type: ActionProducing, TargetName: outputName, Verb: displayVerb} - g.broadcastAction(sess, "\n%s starts %s.", p.Name, displayVerb) + g.broadcastAction(sess, "%s starts %s.", p.Name, displayVerb) } func (g *Game) startProductionFromItem(sess *net.Session, p *player.Player, item *object.ItemDef, count int) { @@ -93,30 +138,25 @@ func (g *Game) startProductionFromItem(sess *net.Session, p *player.Player, item stationName = "inventory" } - firstItem := craftFirstItemName(craft, func(id string) (string, bool) { - def, err := g.ItemStore.Load(id) - if err != nil { - return id, false - } - return def.Name, true - }) - info, ok := productionTypes[craft.Type] if !ok { - info = productionTypeInfo{craft.Type, craft.Type} + info = productionTypeInfo{ + ActionType: craft.Type, + DisplayVerb: craft.Type, + StartMessage: "You start " + craft.Type + " %i1.", + SuccessMessage: "You produce %n.", + EndMessage: "You've finished " + craft.Type + ".", + } } - actionType := info.ActionType - displayVerb := info.DisplayVerb - var startMsg, endMsg string + startMsg := g.resolveCraftMessage(sess, craft.StartMessage, info.StartMessage, craft, item.ID, nil, p.HasItem) if stationName != "inventory" { - startMsg = fmt.Sprintf("You start %s %s on the %s.", displayVerb, firstItem, stationName) - } else { - startMsg = fmt.Sprintf("You start %s %s.", displayVerb, firstItem) + startMsg += " on the " + stationName + "." } - endMsg = fmt.Sprintf("You've finished %s.", displayVerb) - g.startProduction(sess, p, item, craft, actionType, displayVerb, startMsg, endMsg, count) + 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 { @@ -144,7 +184,7 @@ func (g *Game) advanceProduction(sess *net.Session, p *player.Player) bool { if phase == 0 { if startMsg != "" { - sess.WriteLine(fmt.Sprintf("\n%s", startMsg)) + sess.WriteLine(startMsg) } if len(craft.Steps) > 0 { p.Action.Data["next_step_index"] = 0 @@ -161,7 +201,7 @@ func (g *Game) advanceProduction(sess *net.Session, p *player.Player) bool { 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) + sess.WriteLine(g.resolveCraftVar(sess, craft.Steps[i].Message, craft, item.ID, nil, p.HasItem)) p.Action.Data["next_step_index"] = i + 1 } } @@ -174,6 +214,8 @@ func (g *Game) advanceProduction(sess *net.Session, p *player.Player) bool { chance = action.SuccessChance(action.SuccessFormula(*craft.Success), skillLevel, craft.Level) } + info, _ := productionTypes[craft.Type] + if rand.Float64() < chance { outputQty := craft.OutputQty if outputQty <= 0 { @@ -219,14 +261,13 @@ func (g *Game) advanceProduction(sess *net.Session, p *player.Player) bool { } g.AccountStore.SaveCharacter(p) - msg := craft.Message - if msg == "" { - outputName := item.ID - if outDef != nil { - outputName = outDef.Name - } - msg = fmt.Sprintf("You produce %s.", outputName) + 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 { abbr := player.SkillAbbr[player.SkillName(skill)] msg += g.colorize(sess, "xp", fmt.Sprintf(" (+%dxp %s)", craft.XP, abbr)) @@ -243,11 +284,10 @@ func (g *Game) advanceProduction(sess *net.Session, p *player.Player) bool { } g.AccountStore.SaveCharacter(p) - msg := craft.FailMessage - if msg == "" { - msg = "You fail and the materials are lost." + msg := g.resolveCraftMessage(sess, craft.FailMessage, info.FailMessage, craft, item.ID, nil, p.HasItem) + if msg != "" { + sess.WriteLine(g.colorize(sess, "damage", msg)) } - sess.WriteLine(g.colorize(sess, "damage", msg)) } if remaining > 0 { @@ -255,7 +295,7 @@ func (g *Game) advanceProduction(sess *net.Session, p *player.Player) bool { p.Action.Data["remaining"] = remaining if remaining <= 0 { if endMsg != "" { - sess.WriteLine(fmt.Sprintf("\n%s", endMsg)) + sess.WriteLine(endMsg) } g.cancelAction(p) return false @@ -268,7 +308,7 @@ func (g *Game) advanceProduction(sess *net.Session, p *player.Player) bool { } if endMsg != "" { - sess.WriteLine(fmt.Sprintf("\n%s", endMsg)) + sess.WriteLine(endMsg) } g.cancelAction(p) return false @@ -404,7 +444,7 @@ func (g *Game) dispatchMenuEntry(sess *net.Session, entry map[string]string) { g.reprompt(sess) } -func (g *Game) formatMaterials(item *object.ItemDef) string { +func (g *Game) formatMaterials(sess *net.Session, item *object.ItemDef) string { craft := item.FirstCraft() if craft == nil { return "" @@ -413,7 +453,7 @@ func (g *Game) formatMaterials(item *object.ItemDef) string { for _, e := range craft.Consume { itemName := e.Items[0] if def, err := g.ItemStore.Load(e.Items[0]); err == nil { - itemName = def.Name + itemName = g.itemColorize(sess, def, def.Name) } if e.Quantity > 1 { parts = append(parts, fmt.Sprintf("%s x%d", itemName, e.Quantity)) @@ -454,7 +494,7 @@ func (g *Game) showProductionTable(sess *net.Session, p *player.Player, items [] productName = fmt.Sprintf("%s x%d", productName, outputQty) } - matStr := g.formatMaterials(item) + matStr := g.formatMaterials(sess, item) levelStr := fmt.Sprint(craft.Level) numStr := fmt.Sprintf("%d", i+1) @@ -607,19 +647,73 @@ func (g *Game) hasToolType(p *player.Player, toolType string) bool { } type productionTypeInfo struct { - ActionType string - DisplayVerb string + ActionType string + DisplayVerb string + StartMessage string + SuccessMessage string + EndMessage string + FailMessage string } var productionTypes = map[string]productionTypeInfo{ - "cooking": {"cook", "cooking"}, - "smelting": {"smelt", "smelting"}, - "smithing": {"smith", "smithing"}, - "crafting": {"craft", "crafting"}, - "combine": {"combine", "combining"}, - "fletching": {"fletch", "fletching"}, - "pharmacy": {"mix", "mixing"}, - "construction": {"construct", "constructing"}, + "cooking": { + ActionType: "cook", + DisplayVerb: "cooking", + StartMessage: "You start cooking %i1.", + SuccessMessage: "Cooked to perfection. %n looks great!", + EndMessage: "You've finished cooking.", + FailMessage: "You accidentally burn the %i1.", + }, + "smelting": { + ActionType: "smelt", + DisplayVerb: "smelting", + StartMessage: "You place the %i1 into the furnace.", + SuccessMessage: "You remove a white hot %n!", + EndMessage: "You've finished smelting.", + FailMessage: "The %i1 is consumed by the flames.", + }, + "smithing": { + ActionType: "smith", + DisplayVerb: "smithing", + StartMessage: "You begin smithing %i1.", + SuccessMessage: "You smith a %n.", + EndMessage: "You've finished smithing.", + }, + "crafting": { + ActionType: "craft", + DisplayVerb: "crafting", + StartMessage: "You begin crafting %i1.", + SuccessMessage: "You craft a %n.", + EndMessage: "You've finished crafting.", + }, + "combine": { + ActionType: "combine", + DisplayVerb: "combining", + StartMessage: "You start combining %i1.", + SuccessMessage: "You produce %n.", + EndMessage: "You've finished combining.", + }, + "fletching": { + ActionType: "fletch", + DisplayVerb: "fletching", + StartMessage: "You begin fletching %i1.", + SuccessMessage: "You fletch a %n.", + EndMessage: "You've finished fletching.", + }, + "pharmacy": { + ActionType: "mix", + DisplayVerb: "mixing", + StartMessage: "You start mixing %i1.", + SuccessMessage: "You mix a %n.", + EndMessage: "You've finished mixing.", + }, + "construction": { + ActionType: "construct", + DisplayVerb: "constructing", + StartMessage: "You begin constructing %i1.", + SuccessMessage: "You construct a %n.", + EndMessage: "You've finished constructing.", + }, } var productionActionTypes map[string]bool |
