aboutsummaryrefslogtreecommitdiff
path: root/internal/game
diff options
context:
space:
mode:
authorhistoria <[not public]>2026-06-17 17:34:40 -0400
committerhistoria <[not public]>2026-06-17 17:34:40 -0400
commiteef5ddaa94f8cff6010d092c30fed53d2be01524 (patch)
tree3026ebb5fe34fd778c5f8f6b6d23aec337a99b99 /internal/game
parent04998e3e4eff075eee6d00850c752c3c73ab66b5 (diff)
downloadthehouseoficarus-eef5ddaa94f8cff6010d092c30fed53d2be01524.tar.gz
feat: began implementing smithing, ground item display fixes.
Diffstat (limited to 'internal/game')
-rw-r--r--internal/game/action.go2
-rw-r--r--internal/game/action_smelt.go153
-rw-r--r--internal/game/action_state.go3
-rw-r--r--internal/game/cmd_look.go125
-rw-r--r--internal/game/cmd_smelt.go230
-rw-r--r--internal/game/cmd_use.go33
-rw-r--r--internal/game/cmd_wear.go9
-rw-r--r--internal/game/game.go30
8 files changed, 538 insertions, 47 deletions
diff --git a/internal/game/action.go b/internal/game/action.go
index c08295c..608528d 100644
--- a/internal/game/action.go
+++ b/internal/game/action.go
@@ -227,6 +227,8 @@ func (g *Game) AdvanceActions() {
g.advanceSearch(sess, p)
case "cook":
g.advanceCook(sess, p)
+ case "smelt":
+ g.advanceSmelt(sess, p)
}
if p.Action == nil {
g.writePrompt(sess)
diff --git a/internal/game/action_smelt.go b/internal/game/action_smelt.go
new file mode 100644
index 0000000..75fb8a0
--- /dev/null
+++ b/internal/game/action_smelt.go
@@ -0,0 +1,153 @@
+package game
+
+import (
+ "fmt"
+ "math/rand"
+
+ "thehouseoficarus/internal/action"
+ "thehouseoficarus/internal/engine"
+ "thehouseoficarus/internal/net"
+ "thehouseoficarus/internal/player"
+)
+
+func (g *Game) startSmelt(sess *net.Session, p *player.Player, recipe *action.RecipeDef, stationName string) {
+ g.CancelAction(p)
+
+ if recipe.Skill != "" {
+ skillLevel := p.Level(player.SkillName(recipe.Skill))
+ if skillLevel < recipe.Level {
+ sess.WriteLine(fmt.Sprintf("You need level %d %s to smelt that.", recipe.Level, recipe.Skill))
+ return
+ }
+ }
+
+ if !recipe.HasAllItemsQty(p.CountItem) {
+ sess.WriteLine("You don't have the required ores.")
+ return
+ }
+
+ if p.FirstFreeSlot() == -1 {
+ sess.WriteLine("Your inventory is too full!")
+ return
+ }
+
+ wait := recipe.Wait
+ if wait <= 0 {
+ wait = 4
+ }
+
+ outputName := recipe.Output
+ if def, err := g.ItemStore.Load(recipe.Output); err == nil {
+ outputName = def.Name
+ }
+
+ p.Action = &action.Action{
+ Type: "smelt",
+ TargetID: recipe.ID,
+ TargetName: recipe.DisplayName(),
+ Data: map[string]any{
+ "recipe_id": recipe.ID,
+ "station_name": stationName,
+ "phase": 0,
+ "wait": wait,
+ },
+ WaitLeft: engine.ToTicks(1),
+ }
+
+ p.ActionState = &ActionState{Type: ActionSmelting, TargetName: outputName}
+}
+
+func (g *Game) advanceSmelt(sess *net.Session, p *player.Player) bool {
+ recipeID := p.Action.Data["recipe_id"].(string)
+ phase := p.Action.Data["phase"].(int)
+ wait := p.Action.Data["wait"].(float64)
+
+ all, err := g.RecipeStore.LoadAll()
+ if err != nil {
+ g.CancelAction(p)
+ return false
+ }
+ var recipe *action.RecipeDef
+ for _, r := range all {
+ if r.ID == recipeID {
+ recipe = &r
+ break
+ }
+ }
+ if recipe == nil {
+ g.CancelAction(p)
+ return false
+ }
+
+ if phase == 0 {
+ firstItem := recipe.FirstItemName(func(id string) (string, bool) {
+ def, err := g.ItemStore.Load(id)
+ if err != nil {
+ return id, false
+ }
+ return def.Name, true
+ })
+ sess.WriteLine(fmt.Sprintf("\nYou begin to process %s in the furnace.", firstItem))
+ p.Action.Data["phase"] = 1
+ p.Action.WaitLeft = engine.ToTicks(wait)
+ return true
+ }
+
+ skillLevel := p.Level(player.SkillName(recipe.Skill))
+ chance := 1.0
+ if recipe.Success != nil {
+ chance = action.SuccessChance(*recipe.Success, skillLevel, recipe.Level)
+ }
+
+ if rand.Float64() < chance {
+ freeSlot := p.FirstFreeSlot()
+ if freeSlot == -1 {
+ sess.WriteLine("Your inventory is too full!")
+ g.CancelAction(p)
+ return false
+ }
+
+ recipe.ConsumeAll(p.HasItem, p.RemoveItem)
+ p.SetInvSlot(freeSlot, &player.InventorySlot{ItemID: recipe.Output, Quantity: 1})
+
+ if recipe.XP > 0 {
+ if newLevel := p.AddSkillXP(player.SkillName(recipe.Skill), recipe.XP); newLevel > 0 {
+ sess.WriteLine(g.colorize(sess, "level_up", fmt.Sprintf("*** You are now level %d %s! ***", newLevel, recipe.Skill)))
+ }
+ }
+ g.AccountStore.SaveCharacter(p)
+
+ msg := recipe.Message
+ if msg == "" {
+ outputName := recipe.Output
+ if def, loadErr := g.ItemStore.Load(recipe.Output); loadErr == nil {
+ outputName = def.Name
+ }
+ msg = fmt.Sprintf("You remove a white hot %s!", outputName)
+ }
+ if p.OptionBool("xp_drops") && recipe.XP > 0 {
+ abbr := player.SkillAbbr[player.SkillName(recipe.Skill)]
+ msg += g.colorize(sess, "xp", fmt.Sprintf(" (+%dxp %s)", recipe.XP, abbr))
+ }
+ sess.WriteLine(msg)
+ } else {
+ recipe.ConsumeAll(p.HasItem, p.RemoveItem)
+ g.AccountStore.SaveCharacter(p)
+
+ msg := recipe.FailMessage
+ if msg == "" {
+ msg = "You fail to smelt a usable bar."
+ }
+ sess.WriteLine(g.colorize(sess, "damage", msg))
+ }
+
+ if recipe.HasAllItemsQty(p.CountItem) && p.FirstFreeSlot() >= 0 {
+ p.Action.Data["phase"] = 0
+ p.Action.WaitLeft = engine.ToTicks(wait)
+ return true
+ }
+
+ sess.WriteLine("\nYou've processed all the ore in your inventory.")
+ g.CancelAction(p)
+ return false
+}
diff --git a/internal/game/action_state.go b/internal/game/action_state.go
index b28e170..6ce3734 100644
--- a/internal/game/action_state.go
+++ b/internal/game/action_state.go
@@ -20,6 +20,7 @@ const (
ActionResting ActionType = "resting"
ActionWalking ActionType = "walking"
ActionCooking ActionType = "cooking"
+ ActionSmelting ActionType = "smelting"
ActionEating ActionType = "eating"
)
@@ -68,6 +69,8 @@ func (a *ActionState) Description() string {
return "walking somewhere with a purpose!"
case ActionCooking:
return "cooking some " + a.TargetName
+ case ActionSmelting:
+ return "smelting some " + a.TargetName
case ActionEating:
return "eating " + a.TargetName
}
diff --git a/internal/game/cmd_look.go b/internal/game/cmd_look.go
index 8cadfd3..77c8776 100644
--- a/internal/game/cmd_look.go
+++ b/internal/game/cmd_look.go
@@ -214,27 +214,24 @@ func (g *Game) doLook(sess *net.Session) {
ground := g.World.GroundItemsDetailed(p.RoomID)
if len(ground) > 0 {
- sort.Slice(ground, func(i, j int) bool {
- ni := ground[i].ItemID
- if def, err := g.ItemStore.Load(ground[i].ItemID); err == nil {
- ni = def.Name
- }
- nj := ground[j].ItemID
- if def, err := g.ItemStore.Load(ground[j].ItemID); err == nil {
- nj = def.Name
- }
- return strings.ToLower(ni) < strings.ToLower(nj)
- })
+ showDespawn := p.OptionBool("despawn")
+ showReserve := p.OptionBool("reserve")
- sess.WriteLine("")
- sess.WriteLine("On the ground:")
+ type displayLine struct {
+ name string
+ quantity int
+ colorName string
+ annotation string
+ }
- type groundLine struct {
- prefix string
- reserved string
+ type groupKey struct {
+ itemID string
+ despawnTimer int
}
- var lines []groundLine
- maxPrefix := 0
+
+ var lines []displayLine
+ groups := make(map[groupKey]*displayLine)
+ var groupOrder []groupKey
for _, info := range ground {
def, err := g.ItemStore.Load(info.ItemID)
@@ -243,37 +240,89 @@ func (g *Game) doLook(sess *net.Session) {
name = def.Name
}
coloredName := g.itemColorize(sess, def, name)
- prefix := ""
- if info.Quantity > 1 {
- prefix = fmt.Sprintf(" %d x %s", info.Quantity, coloredName)
- } else {
- prefix = fmt.Sprintf(" %s", coloredName)
- }
- if visibleLen(prefix) > maxPrefix {
- maxPrefix = visibleLen(prefix)
- }
- var parts []string
+
if info.ReservedFor != "" {
- if p.OptionBool("reserve") {
+ var parts []string
+ if showReserve {
parts = append(parts, fmt.Sprintf("reserved for %s %dt", info.ReservedFor, info.ReserveTimer))
} else {
parts = append(parts, "reserved")
}
+ if showDespawn && !info.IsSpawn {
+ parts = append(parts, fmt.Sprintf("despawns %dt", info.DespawnTimer))
+ }
+ annotation := ""
+ if len(parts) > 0 {
+ annotation = fmt.Sprintf(" (%s)", strings.Join(parts, ", "))
+ }
+ lines = append(lines, displayLine{
+ name: name,
+ quantity: info.Quantity,
+ colorName: coloredName,
+ annotation: annotation,
+ })
+ continue
+ }
+
+ timerKey := -1
+ if showDespawn && !info.IsSpawn {
+ timerKey = info.DespawnTimer
+ }
+ key := groupKey{itemID: info.ItemID, despawnTimer: timerKey}
+
+ if existing, ok := groups[key]; ok {
+ existing.quantity += info.Quantity
+ } else {
+ annotation := ""
+ if showDespawn && !info.IsSpawn {
+ annotation = fmt.Sprintf(" (despawns %dt)", info.DespawnTimer)
+ }
+ dl := &displayLine{
+ name: name,
+ quantity: info.Quantity,
+ colorName: coloredName,
+ annotation: annotation,
+ }
+ groups[key] = dl
+ groupOrder = append(groupOrder, key)
}
- if p.OptionBool("despawn") && !info.IsSpawn {
- parts = append(parts, fmt.Sprintf("despawns %dt", info.DespawnTimer))
+ }
+
+ for _, key := range groupOrder {
+ lines = append(lines, *groups[key])
+ }
+
+ sort.Slice(lines, func(i, j int) bool {
+ return strings.ToLower(lines[i].name) < strings.ToLower(lines[j].name)
+ })
+
+ sess.WriteLine("")
+ sess.WriteLine("On the ground:")
+
+ type fmtLine struct {
+ prefix string
+ annotation string
+ }
+ var fmtLines []fmtLine
+ maxPrefix := 0
+
+ for _, dl := range lines {
+ prefix := ""
+ if dl.quantity > 1 {
+ prefix = fmt.Sprintf(" %d x %s", dl.quantity, dl.colorName)
+ } else {
+ prefix = fmt.Sprintf(" %s", dl.colorName)
}
- reserved := ""
- if len(parts) > 0 {
- reserved = fmt.Sprintf(" (%s)", strings.Join(parts, ", "))
+ if visibleLen(prefix) > maxPrefix {
+ maxPrefix = visibleLen(prefix)
}
- lines = append(lines, groundLine{prefix, reserved})
+ fmtLines = append(fmtLines, fmtLine{prefix, dl.annotation})
}
- for _, l := range lines {
- if l.reserved != "" {
+ for _, l := range fmtLines {
+ if l.annotation != "" {
pad := maxPrefix + 1 + (len(l.prefix) - visibleLen(l.prefix))
- sess.WriteLine(fmt.Sprintf("%-*s%s", pad, l.prefix, l.reserved))
+ sess.WriteLine(fmt.Sprintf("%-*s%s", pad, l.prefix, l.annotation))
} else {
sess.WriteLine(l.prefix)
}
diff --git a/internal/game/cmd_smelt.go b/internal/game/cmd_smelt.go
new file mode 100644
index 0000000..a308352
--- /dev/null
+++ b/internal/game/cmd_smelt.go
@@ -0,0 +1,230 @@
+package game
+
+import (
+ "fmt"
+ "strconv"
+ "strings"
+
+ "thehouseoficarus/internal/action"
+ "thehouseoficarus/internal/net"
+ "thehouseoficarus/internal/player"
+)
+
+type smeltableEntry struct {
+ ItemName string
+ Recipe action.RecipeDef
+}
+
+func (g *Game) doSmelt(sess *net.Session, input string) {
+ p := sess.Player.(*player.Player)
+ g.CancelAction(p)
+
+ stationName := g.findFurnace(p.RoomID)
+ if stationName == "" {
+ sess.WriteLine("You need a furnace to smelt.")
+ return
+ }
+
+ allRecipes, err := g.RecipeStore.LoadAll()
+ if err != nil {
+ sess.WriteLine("Error loading recipes.")
+ return
+ }
+
+ if input == "" {
+ g.showSmeltMenu(sess, p, allRecipes, stationName)
+ return
+ }
+
+ matches := g.findInventoryMatches(input, p)
+ if len(matches) == 0 {
+ sess.WriteLine(fmt.Sprintf("You don't have any '%s'.", input))
+ return
+ }
+
+ unique := uniqueItemNames(matches)
+ if len(unique) > 1 {
+ sess.WriteLine("Which one?")
+ for _, name := range unique {
+ sess.WriteLine(fmt.Sprintf(" - %s", name))
+ }
+ return
+ }
+
+ itemID := matches[0].ID
+
+ var recipes []action.RecipeDef
+ for _, r := range allRecipes {
+ if r.Type != "smelting" {
+ continue
+ }
+ if !smeltStationOK(stationName, r.Station) {
+ continue
+ }
+ if !r.MatchesEntry(itemID) {
+ continue
+ }
+ if !r.HasAllItemsQty(p.CountItem) {
+ continue
+ }
+ skillLevel := p.Level(player.SkillName(r.Skill))
+ if skillLevel < r.Level {
+ continue
+ }
+ recipes = append(recipes, r)
+ }
+
+ if len(recipes) == 0 {
+ sess.WriteLine("You can't smelt that here.")
+ return
+ }
+
+ if len(recipes) == 1 {
+ g.startSmelt(sess, p, &recipes[0], stationName)
+ return
+ }
+
+ sess.PendingRecipeItem = itemID
+ sess.PendingCookMenu = smeltRecipesToMenuData(recipes)
+ sess.State = net.StateSmeltRecipe
+ sess.WriteLine("\nWhat would you like to smelt?")
+ for i, r := range recipes {
+ sess.WriteLine(fmt.Sprintf(" %d) %s", i+1, g.recipeName(sess, &r)))
+ }
+ sess.WriteLine(fmt.Sprintf(" %d) Nothing", len(recipes)+1))
+}
+
+func (g *Game) showSmeltMenu(sess *net.Session, p *player.Player, allRecipes []action.RecipeDef, stationName string) {
+ seen := make(map[string]bool)
+ var smeltables []smeltableEntry
+
+ for _, r := range allRecipes {
+ if r.Type != "smelting" {
+ continue
+ }
+ if !smeltStationOK(stationName, r.Station) {
+ continue
+ }
+ if seen[r.ID] {
+ continue
+ }
+ if !r.HasAllItemsQty(p.CountItem) {
+ continue
+ }
+ skillLevel := p.Level(player.SkillName(r.Skill))
+ if skillLevel < r.Level {
+ continue
+ }
+ seen[r.ID] = true
+ smeltables = append(smeltables, smeltableEntry{g.recipeName(sess, &r), r})
+ }
+
+ if len(smeltables) == 0 {
+ sess.WriteLine("You don't have anything you can smelt.")
+ return
+ }
+
+ if len(smeltables) == 1 {
+ g.startSmelt(sess, p, &smeltables[0].Recipe, stationName)
+ return
+ }
+
+ sess.PendingRecipeItem = ""
+ sess.State = net.StateSmeltRecipe
+ sess.WriteLine("\nWhat would you like to smelt?")
+ for i, s := range smeltables {
+ sess.WriteLine(fmt.Sprintf(" %d) %s", i+1, s.ItemName))
+ }
+ sess.WriteLine(fmt.Sprintf(" %d) Nothing", len(smeltables)+1))
+
+ sess.PendingCookMenu = makeSmeltMenuData(smeltables)
+}
+
+func (g *Game) handleSmeltRecipe(sess *net.Session, input string) {
+ p := sess.Player.(*player.Player)
+ input = strings.TrimSpace(input)
+ if input == "" {
+ return
+ }
+
+ choice, err := strconv.Atoi(input)
+ if err != nil {
+ sess.State = net.StateGame
+ sess.PendingRecipeItem = ""
+ sess.PendingCookMenu = nil
+ sess.WriteLine("You decide not to smelt anything.")
+ g.reprompt(sess)
+ return
+ }
+
+ if len(sess.PendingCookMenu) > 0 {
+ menuData := sess.PendingCookMenu
+ sess.PendingCookMenu = nil
+ if choice <= 0 || choice > len(menuData)+1 {
+ sess.WriteLine("Invalid choice.")
+ return
+ }
+ sess.State = net.StateGame
+ if choice == len(menuData)+1 {
+ sess.WriteLine("You decide not to smelt anything.")
+ g.reprompt(sess)
+ return
+ }
+ entry := menuData[choice-1]
+
+ all, loadErr := g.RecipeStore.LoadAll()
+ if loadErr != nil {
+ g.reprompt(sess)
+ return
+ }
+ for _, r := range all {
+ if r.ID == entry["recipe_id"] {
+ stationName := g.findFurnace(p.RoomID)
+ g.startSmelt(sess, p, &r, stationName)
+ return
+ }
+ }
+ g.reprompt(sess)
+ return
+ }
+
+ sess.State = net.StateGame
+ g.reprompt(sess)
+}
+
+func smeltStationOK(stationName string, recipeStations []string) bool {
+ for _, rs := range recipeStations {
+ if rs == "furnace" && stationName == "furnace" {
+ return true
+ }
+ }
+ return false
+}
+
+func (g *Game) findFurnace(roomID int) string {
+ for _, obj := range g.World.AllObjInstances(roomID) {
+ if obj.Depleted {
+ continue
+ }
+ if obj.DefID == "furnace" {
+ return "furnace"
+ }
+ }
+ return ""
+}
+
+func makeSmeltMenuData(smeltables []smeltableEntry) []map[string]string {
+ out := make([]map[string]string, len(smeltables))
+ for i, s := range smeltables {
+ out[i] = map[string]string{"recipe_id": s.Recipe.ID}
+ }
+ return out
+}
+
+func smeltRecipesToMenuData(recipes []action.RecipeDef) []map[string]string {
+ out := make([]map[string]string, len(recipes))
+ for i, r := range recipes {
+ out[i] = map[string]string{"recipe_id": r.ID}
+ }
+ return out
+}
diff --git a/internal/game/cmd_use.go b/internal/game/cmd_use.go
index 56aa5a1..247df72 100644
--- a/internal/game/cmd_use.go
+++ b/internal/game/cmd_use.go
@@ -74,6 +74,39 @@ func (g *Game) doUseItemOnTarget(sess *net.Session, p *player.Player, itemAName,
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" {
+ continue
+ }
+ if !r.HasAllItemsQty(p.CountItem) {
+ continue
+ }
+ skillLevel := p.Level(player.SkillName(r.Skill))
+ if skillLevel < r.Level {
+ continue
+ }
+ filtered = append(filtered, r)
+ }
+ if len(filtered) == 0 {
+ sess.WriteLine("You can't smelt that here.")
+ return
+ }
+ if len(filtered) == 1 {
+ g.startSmelt(sess, p, &filtered[0], def.Name)
+ return
+ }
+ sess.PendingRecipeItem = itemAID
+ sess.PendingCookMenu = smeltRecipesToMenuData(filtered)
+ sess.State = net.StateSmeltRecipe
+ sess.WriteLine("\nWhat would you like to smelt?")
+ for i, r := range filtered {
+ sess.WriteLine(fmt.Sprintf(" %d) %s", i+1, g.recipeName(sess, &r)))
+ }
+ sess.WriteLine(fmt.Sprintf(" %d) Nothing", len(filtered)+1))
+ return
+ }
if len(recipes) == 1 {
g.startCook(sess, p, &recipes[0], def.Name)
return
diff --git a/internal/game/cmd_wear.go b/internal/game/cmd_wear.go
index cbc2ff3..8910e75 100644
--- a/internal/game/cmd_wear.go
+++ b/internal/game/cmd_wear.go
@@ -31,6 +31,15 @@ func (g *Game) doWear(sess *net.Session, input string) {
return
}
+ unique := uniqueItemNames(matches)
+ if len(unique) > 1 {
+ sess.WriteLine("Equip what?")
+ for _, name := range unique {
+ sess.WriteLine(fmt.Sprintf(" - %s", name))
+ }
+ return
+ }
+
match := matches[0]
slot := p.InvSlot(match.Slot)
if slot == nil {
diff --git a/internal/game/game.go b/internal/game/game.go
index 5af35be..49d34b6 100644
--- a/internal/game/game.go
+++ b/internal/game/game.go
@@ -124,6 +124,8 @@ func (g *Game) HandleSession(sess *net.Session, input string) {
g.handleDropAllConfirm(sess, input)
case net.StateCookRecipe:
g.handleCookRecipe(sess, input)
+ case net.StateSmeltRecipe:
+ g.handleSmeltRecipe(sess, input)
case net.StateColorChoice:
g.handleColorChoice(sess, input)
}
@@ -132,18 +134,18 @@ func (g *Game) HandleSession(sess *net.Session, input string) {
func classifyCommand(cmd string) CommandClass {
switch cmd {
case "say", "score", "sc", "inventory", "i", "inv",
- "equipment", "eq", "look", "l", "exits", "help",
+ "look", "l", "exits", "help",
"map", "option", "options", "alias", "unalias",
"description", "desc", "queued", "color", "colors",
"colortable", "prompt", "style":
return ClassInstant
- case "wear", "wield", "remove", "unwear", "unwield":
+ case "equip", "eq", "equipment", "wear", "wield", "remove", "unwear", "unwield":
return ClassFree
case "get", "take", "grab", "pick", "drop",
"attack", "kill",
"north", "n", "south", "s", "east", "e",
"west", "w", "up", "u", "down", "d",
- "quit", "use", "burn", "stoke", "search", "walk", "cook":
+ "quit", "use", "burn", "stoke", "search", "walk", "cook", "smelt":
return ClassActive
case "eat":
return ClassFree
@@ -188,6 +190,16 @@ func (g *Game) handleGameCommand(sess *net.Session, input string) {
parts := strings.Fields(strings.ToLower(input))
cmd := parts[0]
+
+ if len(parts) == 1 {
+ switch cmd {
+ case "equip", "eq", "equipment", "wear", "wield":
+ g.doEquipment(sess)
+ g.writePrompt(sess)
+ return
+ }
+ }
+
class := classifyCommand(cmd)
if class == ClassInstant {
@@ -302,8 +314,6 @@ func (g *Game) executeCommand(sess *net.Session, cmd string, args []string, rawI
g.doScore(sess)
case "i", "inv", "inventory":
g.doInventory(sess)
- case "eq", "equipment":
- g.doEquipment(sess)
case "quit":
g.doQuit(sess)
return
@@ -358,6 +368,9 @@ func (g *Game) executeCommand(sess *net.Session, cmd string, args []string, rawI
case "cook":
g.doCook(sess, strings.Join(args, " "))
return
+ case "smelt":
+ g.doSmelt(sess, strings.Join(args, " "))
+ return
case "eat":
g.doEat(sess, strings.Join(args, " "))
return
@@ -394,7 +407,7 @@ func (g *Game) executeCommand(sess *net.Session, cmd string, args []string, rawI
case "walk":
g.doWalk(sess, args)
return
- case "wear", "wield":
+ case "eq", "equipment", "equip", "wear", "wield":
g.doWear(sess, strings.Join(args, " "))
return
case "remove", "unwear", "unwield":
@@ -446,7 +459,7 @@ func (g *Game) ProcessQueuedCommands() {
}
switch as.Type {
case ActionGathering, ActionCombating, ActionUsing, ActionTalking,
- ActionToggling, ActionBurning, ActionStoking, ActionResting, ActionWalking, ActionCooking:
+ ActionToggling, ActionBurning, ActionStoking, ActionResting, ActionWalking, ActionCooking, ActionSmelting:
default:
if as.Type != ActionMoving || p.MoveTicks <= 0 {
p.ActionState = nil
@@ -488,13 +501,12 @@ func (g *Game) ProcessQueuedCommands() {
if p.MoveTicks > 0 {
p.ClearMoveState()
}
- wasBusy := p.Action != nil || len(p.WalkSequence) > 0 || combat.GetCombat(p.Name) != nil
if len(parts) > 0 {
g.executeCommand(qc.Session, parts[0], parts[1:], qc.Command+" "+qc.Args)
}
isBusy := p.Action != nil || len(p.WalkSequence) > 0 || combat.GetCombat(p.Name) != nil || p.MoveTicks > 0
_, isResting := g.restTimers[p.Name]
- if !isResting && (wasBusy || !isBusy) {
+ if !isResting && !isBusy {
g.writePrompt(qc.Session)
}
}