aboutsummaryrefslogtreecommitdiff
path: root/internal/game/cmd_use.go
diff options
context:
space:
mode:
Diffstat (limited to 'internal/game/cmd_use.go')
-rw-r--r--internal/game/cmd_use.go200
1 files changed, 200 insertions, 0 deletions
diff --git a/internal/game/cmd_use.go b/internal/game/cmd_use.go
new file mode 100644
index 0000000..ef36e12
--- /dev/null
+++ b/internal/game/cmd_use.go
@@ -0,0 +1,200 @@
+package game
+
+import (
+ "fmt"
+ "strings"
+
+ "thirdcollapse/internal/net"
+ "thirdcollapse/internal/object"
+ "thirdcollapse/internal/player"
+)
+
+func (g *Game) doUse(sess *net.Session, input string) {
+ p := sess.Player.(*player.Player)
+ g.CancelAction(p)
+
+ lower := strings.ToLower(input)
+
+ sep := ""
+ if strings.Contains(lower, " on ") {
+ sep = " on "
+ } else if strings.Contains(lower, " with ") {
+ sep = " with "
+ }
+
+ if sep != "" {
+ parts := strings.SplitN(lower, sep, 2)
+ itemA := strings.TrimSpace(parts[0])
+ itemB := strings.TrimSpace(parts[1])
+ if itemA == itemB {
+ sess.WriteLine("You can't use that with itself.")
+ return
+ }
+ g.doUseItemOnTarget(sess, p, itemA, itemB)
+ return
+ }
+
+ if len(strings.Fields(input)) >= 2 {
+ g.doUseItemOnTarget(sess, p, strings.Fields(input)[0], strings.Join(strings.Fields(input)[1:], " "))
+ return
+ }
+
+ g.StartAction(sess, "use", input)
+}
+
+func (g *Game) doUseItemOnTarget(sess *net.Session, p *player.Player, itemAName, itemBName string) {
+ matchesA := g.findInventoryMatches(itemAName, p)
+ if len(matchesA) == 0 {
+ sess.WriteLine(fmt.Sprintf("You don't have any '%s'.", itemAName))
+ return
+ }
+
+ uniqueA := uniqueItemNames(matchesA)
+ if len(uniqueA) > 1 {
+ sess.WriteLine("Which one?")
+ for _, name := range uniqueA {
+ sess.WriteLine(fmt.Sprintf(" - %s", name))
+ }
+ return
+ }
+
+ itemAID := matchesA[0].ID
+
+ matchesB := g.findInventoryMatches(itemBName, p)
+
+ objInstances := g.World.FindObjInstances(p.RoomID, itemBName)
+ if len(objInstances) > 0 {
+ objSt := &objInstances[0]
+ def, _ := g.ObjectStore.Load(objSt.DefID)
+ if def == nil {
+ g.StartAction(sess, "use", itemBName)
+ return
+ }
+
+ stationIDs := []string{def.ID}
+ recipes, err := g.RecipeStore.FindByStation(itemAID, stationIDs, "")
+ if err == nil && len(recipes) > 0 {
+ if len(recipes) == 1 {
+ g.startCook(sess, p, &recipes[0], def.Name)
+ return
+ }
+ sess.PendingRecipeItem = itemAID
+ sess.PendingCookMenu = recipesToMenuData(recipes)
+ sess.State = net.StateCookRecipe
+ sess.WriteLine(fmt.Sprintf("\nWhat would you like to make with %s on the %s?", itemAName, def.Name))
+ for i, r := range recipes {
+ sess.WriteLine(fmt.Sprintf(" %d) %s", i+1, g.recipeName(sess, &r)))
+ }
+ return
+ }
+
+ g.StartAction(sess, "use", itemBName)
+ return
+ }
+
+ matchesB = g.findInventoryMatches(itemBName, p)
+ if len(matchesB) > 0 {
+ uniqueB := uniqueItemNames(matchesB)
+ if len(uniqueB) > 1 {
+ sess.WriteLine("Which '" + itemBName + "'?")
+ for _, name := range uniqueB {
+ sess.WriteLine(fmt.Sprintf(" - %s", name))
+ }
+ return
+ }
+
+ itemBID := matchesB[0].ID
+
+ matched := g.findCombineResults(sess, p, itemAID, itemBID)
+ if len(matched) == 1 {
+ g.produceCombined(sess, p, matched[0])
+ return
+ }
+ if len(matched) > 1 {
+ sess.PendingCookMenu = combineMenuData(matched)
+ sess.State = net.StateCookRecipe
+ sess.WriteLine("\nWhat would you like to make?")
+ for i, def := range matched {
+ sess.WriteLine(fmt.Sprintf(" %d) %s", i+1, g.itemColorize(sess, def, def.Name)))
+ }
+ return
+ }
+
+ sess.WriteLine("You can't combine those items.")
+ return
+ }
+
+ sess.WriteLine(fmt.Sprintf("There's no '%s' here to use that on.", itemBName))
+}
+
+func (g *Game) findCombineResults(sess *net.Session, p *player.Player, itemAID, itemBID string) []*object.ItemDef {
+ items, err := g.ItemStore.LoadAll()
+ if err != nil {
+ return nil
+ }
+ var matched []*object.ItemDef
+ for _, def := range items {
+ if len(def.MadeFrom) == 0 {
+ continue
+ }
+ aEntry := -1
+ bEntry := -1
+ for ei, entry := range def.MadeFrom {
+ for _, id := range entry.Items {
+ if id == itemAID && aEntry < 0 {
+ aEntry = ei
+ }
+ if id == itemBID && bEntry < 0 {
+ bEntry = ei
+ }
+ }
+ }
+ if aEntry >= 0 && bEntry >= 0 && aEntry != bEntry && madeFromItemsAvailable(p, def.MadeFrom) {
+ matched = append(matched, def)
+ }
+ }
+ return matched
+}
+
+func (g *Game) produceCombined(sess *net.Session, p *player.Player, def *object.ItemDef) {
+ freeSlot := p.FirstFreeSlot()
+ if freeSlot == -1 {
+ sess.WriteLine("Your inventory is too full.")
+ return
+ }
+ for _, entry := range def.MadeFrom {
+ for _, id := range entry.Items {
+ if p.HasItem(id) {
+ p.RemoveItem(id, entry.Qty)
+ break
+ }
+ }
+ }
+ p.SetInvSlot(freeSlot, &player.InventorySlot{ItemID: def.ID, Quantity: 1})
+ g.AccountStore.SaveCharacter(p)
+ sess.WriteLine(fmt.Sprintf("You combine the ingredients and create %s.", g.itemColorize(sess, def, def.Name)))
+}
+
+func combineMenuData(defs []*object.ItemDef) []map[string]string {
+ out := make([]map[string]string, len(defs))
+ for i, d := range defs {
+ out[i] = map[string]string{"combine_item": d.ID}
+ }
+ return out
+}
+
+func madeFromItemsAvailable(p *player.Player, madeFrom []object.MadeFromEntry) bool {
+ for _, entry := range madeFrom {
+ found := false
+ for _, id := range entry.Items {
+ if p.HasItem(id) {
+ found = true
+ break
+ }
+ }
+ if !found {
+ return false
+ }
+ }
+ return true
+}