diff --git a/_datafiles/html/static/public/audio/sound/combat/explosion1.mp3 b/_datafiles/html/static/public/audio/sound/combat/explosion1.mp3
new file mode 100644
index 00000000..f916eded
Binary files /dev/null and b/_datafiles/html/static/public/audio/sound/combat/explosion1.mp3 differ
diff --git a/_datafiles/html/static/public/audio/sound/combat/explosion2.mp3 b/_datafiles/html/static/public/audio/sound/combat/explosion2.mp3
index f916eded..d28a9bf4 100644
Binary files a/_datafiles/html/static/public/audio/sound/combat/explosion2.mp3 and b/_datafiles/html/static/public/audio/sound/combat/explosion2.mp3 differ
diff --git a/_datafiles/html/static/public/audio/sound/combat/explosion3.mp3 b/_datafiles/html/static/public/audio/sound/combat/explosion3.mp3
deleted file mode 100644
index d28a9bf4..00000000
Binary files a/_datafiles/html/static/public/audio/sound/combat/explosion3.mp3 and /dev/null differ
diff --git a/_datafiles/html/static/public/audio/sound/combat/explosion.mp3 b/_datafiles/html/static/public/audio/sound/other/change.mp3
similarity index 100%
rename from _datafiles/html/static/public/audio/sound/combat/explosion.mp3
rename to _datafiles/html/static/public/audio/sound/other/change.mp3
diff --git a/_datafiles/world/default/items/armor-20000/neck/20045-rat_skin_cape.yaml b/_datafiles/world/default/items/armor-20000/neck/20045-rat_skin_cape.yaml
new file mode 100755
index 00000000..e47c01c4
--- /dev/null
+++ b/_datafiles/world/default/items/armor-20000/neck/20045-rat_skin_cape.yaml
@@ -0,0 +1,10 @@
+itemid: 20045
+value: 100
+name: rat-skin cape
+namesimple: cape
+description: A patchwork cape made up of many rat hides.
+type: neck
+subtype: wearable
+damagereduction: 5
+wornbuffids:
+ - 3 # Cold Tolerant
\ No newline at end of file
diff --git a/_datafiles/world/default/keywords.yaml b/_datafiles/world/default/keywords.yaml
index 79270420..3f808ef8 100644
--- a/_datafiles/world/default/keywords.yaml
+++ b/_datafiles/world/default/keywords.yaml
@@ -129,6 +129,7 @@ help:
- build
- command
- deafen
+ - item
- grant
- locate
- modify
diff --git a/_datafiles/world/default/rooms/frostfang/611.yaml b/_datafiles/world/default/rooms/frostfang/611.yaml
index 884a01e8..6f94e63c 100755
--- a/_datafiles/world/default/rooms/frostfang/611.yaml
+++ b/_datafiles/world/default/rooms/frostfang/611.yaml
@@ -10,6 +10,9 @@ description: As you step into this residence, a sense of artistic flair is immed
the owner's artistic inclinations. This home feels like a personal retreat, a place
for creativity and relaxation amidst the harshness of Frostfang.
biome: house
+containers:
+ tattertail loom:
+ recipes: {20045: [20001, 20001, 20001, 20001, 20001, 20001, 20001, 20001, 20001]}
exits:
north:
roomid: 260
diff --git a/_datafiles/world/default/templates/descriptions/insidecontainer.template b/_datafiles/world/default/templates/descriptions/insidecontainer.template
index 530365d0..f87804e8 100644
--- a/_datafiles/world/default/templates/descriptions/insidecontainer.template
+++ b/_datafiles/world/default/templates/descriptions/insidecontainer.template
@@ -1,6 +1,8 @@
{{- $displayed := 0 -}}
{{- $itemCt := len . -}}
-Inside you see:
+ ┌─────────────────────────────────────────────────────────────────────────┐
+
+ Inside you see:
{{- if ne $itemCt 0 -}}
{{- range $index, $itemName := . -}}
{{- $displayed = add $displayed 1 -}}
@@ -9,3 +11,4 @@
{{ else -}}
Nothing
{{ end }}
+ └─────────────────────────────────────────────────────────────────────────┘
\ No newline at end of file
diff --git a/_datafiles/world/empty/keywords.yaml b/_datafiles/world/empty/keywords.yaml
index 79270420..3f808ef8 100644
--- a/_datafiles/world/empty/keywords.yaml
+++ b/_datafiles/world/empty/keywords.yaml
@@ -129,6 +129,7 @@ help:
- build
- command
- deafen
+ - item
- grant
- locate
- modify
diff --git a/_datafiles/world/empty/templates/descriptions/insidecontainer.template b/_datafiles/world/empty/templates/descriptions/insidecontainer.template
index 530365d0..7d201aeb 100644
--- a/_datafiles/world/empty/templates/descriptions/insidecontainer.template
+++ b/_datafiles/world/empty/templates/descriptions/insidecontainer.template
@@ -1,5 +1,7 @@
{{- $displayed := 0 -}}
{{- $itemCt := len . -}}
+ ┌─────────────────────────────────────────────────────────────────────────┐
+
Inside you see:
{{- if ne $itemCt 0 -}}
{{- range $index, $itemName := . -}}
@@ -9,3 +11,4 @@
{{ else -}}
Nothing
{{ end }}
+ └─────────────────────────────────────────────────────────────────────────┘
\ No newline at end of file
diff --git a/internal/rooms/container.go b/internal/rooms/container.go
index be984744..3f336fb5 100644
--- a/internal/rooms/container.go
+++ b/internal/rooms/container.go
@@ -10,6 +10,7 @@ type Container struct {
Items []items.Item `yaml:"items,omitempty"` // Save contents now, since players can put new items in there
Gold int `yaml:"gold,omitempty"` // Save contents now, since players can put new items in there
DespawnRound uint64 `yaml:"despawnround,omitempty"` // If this is set, it's a chest that will disappear with time.
+ Recipes map[int][]int `yaml:"recipes,omitempty,flow"` // Item Id's (key) that are created when the recipe is present in the container (values) and it is "used"
}
func (c Container) HasLock() bool {
@@ -44,3 +45,60 @@ func (c *Container) FindItem(itemName string) (items.Item, bool) {
return items.Item{}, false
}
+
+func (c *Container) FindItemById(itemId int) (items.Item, bool) {
+
+ // Search floor
+ for _, matchItem := range c.Items {
+ if matchItem.ItemId == itemId {
+ return matchItem, true
+ }
+ }
+
+ return items.Item{}, false
+}
+
+// Returns an itemId if it can produce one based on contents + recipe
+func (c *Container) RecipeReady() int {
+
+ if len(c.Recipes) == 0 {
+ return 0
+ }
+
+ for finalItemId, recipeList := range c.Recipes {
+
+ totalNeeded := 0
+ neededItems := map[int]int{}
+
+ for _, inputItemId := range recipeList {
+ neededItems[inputItemId] += 1
+ totalNeeded++
+ }
+
+ for _, containsItem := range c.Items {
+ if neededItems[containsItem.ItemId] > 0 {
+ neededItems[containsItem.ItemId] -= 1
+ totalNeeded--
+ }
+ if totalNeeded == 0 {
+ break
+ }
+ }
+
+ if totalNeeded < 1 {
+ return finalItemId
+ }
+ }
+
+ return 0
+}
+
+func (c *Container) Count(itemId int) int {
+ total := 0
+ for _, containsItem := range c.Items {
+ if containsItem.ItemId == itemId {
+ total++
+ }
+ }
+ return total
+}
diff --git a/internal/usercommands/get.go b/internal/usercommands/get.go
index a509cf61..c9b30523 100644
--- a/internal/usercommands/get.go
+++ b/internal/usercommands/get.go
@@ -190,6 +190,8 @@ func Get(rest string, user *users.UserRecord, room *rooms.Room) (bool, error) {
scripting.TryItemScriptEvent(`onFound`, matchItem, user.UserId)
+ return true, nil
+
} else {
user.SendText(
fmt.Sprintf(`You can't carry the %s.`, matchItem.DisplayName()),
@@ -314,7 +316,12 @@ func Get(rest string, user *users.UserRecord, room *rooms.Room) (bool, error) {
return true, nil
}
- user.SendText(fmt.Sprintf("You don't see a %s around.", rest))
+ containerName = room.FindContainerByName(rest)
+ if containerName != `` {
+ user.SendText(fmt.Sprintf(`You can't pick up the %s. Try looking at it.`, containerName))
+ } else {
+ user.SendText(fmt.Sprintf("You don't see a %s around.", rest))
+ }
return true, nil
}
diff --git a/internal/usercommands/look.go b/internal/usercommands/look.go
index a382d0e2..04588aeb 100644
--- a/internal/usercommands/look.go
+++ b/internal/usercommands/look.go
@@ -6,6 +6,7 @@ import (
"github.com/volte6/gomud/internal/buffs"
"github.com/volte6/gomud/internal/gametime"
+ "github.com/volte6/gomud/internal/items"
"github.com/volte6/gomud/internal/keywords"
"github.com/volte6/gomud/internal/mobs"
"github.com/volte6/gomud/internal/rooms"
@@ -165,10 +166,43 @@ func Look(rest string, user *users.UserRecord, room *rooms.Room) (bool, error) {
chestStuff = append(chestStuff, item.DisplayName())
}
+ if len(container.Recipes) > 0 {
+
+ user.SendText(``)
+ user.SendText(fmt.Sprintf(`You can use the %s if you put the following objects inside:`, containerName))
+
+ for finalItemId, recipeList := range container.Recipes {
+
+ neededItems := map[int]int{}
+
+ for _, inputItemId := range recipeList {
+ neededItems[inputItemId] += 1
+ }
+
+ user.SendText(``)
+
+ finalItem := items.New(finalItemId)
+ user.SendText(fmt.Sprintf(` To receive 1 %s: `, finalItem.DisplayName()))
+
+ for inputItemId, qtyNeeded := range neededItems {
+ tmpItem := items.New(inputItemId)
+ totalContained := container.Count(inputItemId)
+ colorClass := "9"
+ if totalContained == qtyNeeded {
+ colorClass = "14"
+ }
+ user.SendText(fmt.Sprintf(` [%d/%d] %s`, colorClass, totalContained, qtyNeeded, tmpItem.DisplayName()))
+ }
+
+ }
+
+ }
+
textOut, _ := templates.Process("descriptions/insidecontainer", chestStuff)
user.SendText(``)
user.SendText(textOut)
+ user.SendText(``)
return true, nil
}
diff --git a/internal/usercommands/use.go b/internal/usercommands/use.go
index c3e152b6..53b82f34 100644
--- a/internal/usercommands/use.go
+++ b/internal/usercommands/use.go
@@ -13,6 +13,54 @@ import (
func Use(rest string, user *users.UserRecord, room *rooms.Room) (bool, error) {
+ containerName := room.FindContainerByName(rest)
+ if containerName != `` {
+
+ container := room.Containers[containerName]
+
+ if len(container.Recipes) > 0 {
+
+ if container.Lock.IsLocked() {
+ user.SendText(``)
+ user.SendText(fmt.Sprintf(`The %s is locked.`, containerName))
+ user.SendText(``)
+ return true, nil
+ }
+
+ recipeReadyItemId := container.RecipeReady()
+
+ if recipeReadyItemId == 0 {
+ user.SendText("")
+ user.SendText(fmt.Sprintf(`The %s seems to be missing something.`, containerName))
+ user.SendText("")
+ return true, nil
+ }
+
+ for _, removeItem := range container.Recipes[recipeReadyItemId] {
+ if matchItem, found := container.FindItemById(removeItem); found {
+ container.RemoveItem(matchItem)
+ }
+ }
+
+ newItem := items.New(recipeReadyItemId)
+
+ container.AddItem(newItem)
+ room.Containers[containerName] = container
+
+ room.PlaySound(`sound/other/change.mp3`, `other`)
+
+ user.SendText(``)
+ user.SendText(fmt.Sprintf(`The %s produces a %s!`, containerName, newItem.DisplayName()))
+ user.SendText(``)
+
+ room.SendText(fmt.Sprintf(`%s does something with the %s.`, user.Character.Name, containerName), user.UserId)
+
+ return true, nil
+
+ }
+
+ }
+
// Check whether the user has an item in their inventory that matches
matchItem, found := user.Character.FindInBackpack(rest)