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.go202
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