aboutsummaryrefslogtreecommitdiff
path: root/internal/game/cmd_consume.go
diff options
context:
space:
mode:
Diffstat (limited to 'internal/game/cmd_consume.go')
-rw-r--r--internal/game/cmd_consume.go293
1 files changed, 293 insertions, 0 deletions
diff --git a/internal/game/cmd_consume.go b/internal/game/cmd_consume.go
new file mode 100644
index 0000000..0a7d335
--- /dev/null
+++ b/internal/game/cmd_consume.go
@@ -0,0 +1,293 @@
+package game
+
+import (
+ "fmt"
+ "strings"
+ "time"
+
+ "thehouseoficarus/internal/engine"
+ "thehouseoficarus/internal/net"
+ "thehouseoficarus/internal/object"
+ "thehouseoficarus/internal/player"
+)
+
+func (g *Game) executeEat(sess *net.Session, args []string, rawInput string) {
+ g.doEat(sess, strings.Join(args, " "))
+}
+
+func (g *Game) executeDrink(sess *net.Session, args []string, rawInput string) {
+ g.doDrink(sess, args)
+}
+
+func (g *Game) doEat(sess *net.Session, input string) {
+ p := sess.Player
+
+ if input == "" {
+ sess.WriteLine("Eat what?")
+ return
+ }
+
+ qty, itemName := parseQty(input)
+ _ = qty
+
+ matches := g.findInventoryMatches(itemName, p)
+ if len(matches) == 0 {
+ sess.WriteLine(fmt.Sprintf("You don't have any '%s'.", itemName))
+ return
+ }
+
+ unique := uniqueItemNames(matches)
+ if len(unique) > 1 {
+ g.showWhichOne(sess, matches)
+ return
+ }
+
+ itemID := matches[0].ID
+ def, _ := g.ItemStore.Load(itemID)
+
+ if def == nil || def.EatMessage == "" {
+ sess.WriteLine("You can't eat that.")
+ return
+ }
+
+ if p.ConsumeCooldown > 0 {
+ sess.WriteLine("You're still digesting your last meal.")
+ return
+ }
+
+ g.cancelRest(p.Name)
+
+ if p.Action == nil && len(p.WalkSequence) == 0 {
+ g.doEatNow(sess, p, itemID, def)
+ return
+ }
+
+ g.cancelAction(p)
+
+ g.consumeQueue[p.Name] = &QueuedCommand{
+ Session: sess,
+ Command: "eat",
+ Args: itemID,
+ Timestamp: time.Now(),
+ }
+
+ if !p.OptionBool("queue_silently") {
+ sess.WriteLine(fmt.Sprintf("\nYou prepare to eat %s.", g.itemColorize(sess, def, def.Name)))
+ }
+}
+
+func (g *Game) doEatNow(sess *net.Session, p *player.Player, itemID string, def *object.ItemDef) {
+ if def == nil {
+ var err error
+ def, err = g.ItemStore.Load(itemID)
+ if err != nil || def.EatMessage == "" {
+ return
+ }
+ }
+
+ p.RemoveItem(itemID, 1)
+
+ p.HP += def.HealValue
+ maxHP := p.MaxHP()
+ if p.HP > maxHP {
+ p.HP = maxHP
+ }
+ if p.HP < 0 {
+ p.HP = 0
+ }
+
+ if def.HealValue != 0 {
+ p.StartRegen()
+ }
+
+ p.ConsumeCooldown = 3
+ g.AccountStore.SaveCharacter(p)
+
+ p.ActionState = &ActionState{Type: ActionEating, TargetName: def.Name}
+
+ sess.WriteLine(g.colorize(sess, "eat_food", def.EatMessage))
+
+ if p.HP <= 0 {
+ g.endCombat(sess, p, nil)
+ }
+}
+
+func (g *Game) processConsumeQueue(p *player.Player, sess *net.Session) bool {
+ qc, ok := g.consumeQueue[p.Name]
+ if !ok {
+ return false
+ }
+ delete(g.consumeQueue, p.Name)
+
+ itemID := qc.Args
+ def, err := g.ItemStore.Load(itemID)
+
+ if qc.Command == "drink" {
+ if err != nil || (def.PotionEffect == "" && def.HealValue <= 0) {
+ return false
+ }
+ if p.ConsumeCooldown > 0 {
+ return false
+ }
+ if !p.HasItem(itemID) {
+ sess.WriteLine("You no longer have that to drink.")
+ return false
+ }
+ g.applyPotion(sess, p, itemID, def)
+ return true
+ }
+
+ if err != nil || def.EatMessage == "" {
+ return false
+ }
+
+ if p.ConsumeCooldown > 0 {
+ return false
+ }
+
+ if !p.HasItem(itemID) {
+ sess.WriteLine("You no longer have that to eat.")
+ return false
+ }
+
+ g.doEatNow(sess, p, itemID, def)
+ return true
+}
+
+func (g *Game) doDrink(sess *net.Session, args []string) {
+ p := sess.Player
+
+ if len(args) == 0 {
+ sess.WriteLine("Drink what?")
+ return
+ }
+
+ input := strings.Join(args, " ")
+ 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 {
+ g.showWhichOne(sess, matches)
+ return
+ }
+
+ itemID := matches[0].ID
+ def, _ := g.ItemStore.Load(itemID)
+
+ if def == nil {
+ sess.WriteLine("Something went wrong.")
+ return
+ }
+
+ if def.PotionEffect == "" && def.HealValue <= 0 {
+ sess.WriteLine(fmt.Sprintf("You can't drink the %s.", g.itemColorize(sess, def, def.Name)))
+ return
+ }
+
+ if p.ConsumeCooldown > 0 {
+ sess.WriteLine("You're still recovering from your last drink.")
+ return
+ }
+
+ g.cancelRest(p.Name)
+
+ if p.Action == nil && len(p.WalkSequence) == 0 {
+ g.applyPotion(sess, p, itemID, def)
+ return
+ }
+
+ g.cancelAction(p)
+
+ g.consumeQueue[p.Name] = &QueuedCommand{
+ Session: sess,
+ Command: "drink",
+ Args: itemID,
+ Timestamp: time.Now(),
+ }
+
+ if !p.OptionBool("queue_silently") {
+ sess.WriteLine(fmt.Sprintf("\nYou prepare to drink the %s.", g.itemColorize(sess, def, def.Name)))
+ }
+}
+
+func (g *Game) applyPotion(sess *net.Session, p *player.Player, itemID string, def *object.ItemDef) {
+ if def == nil {
+ var err error
+ def, err = g.ItemStore.Load(itemID)
+ if err != nil || (def.PotionEffect == "" && def.HealValue <= 0) {
+ return
+ }
+ }
+
+ p.RemoveItem(itemID, 1)
+
+ effect := strings.ToLower(def.PotionEffect)
+
+ switch effect {
+ case "battery":
+ batteryRestore := def.PotionBonus
+ p.Battery += float64(batteryRestore)
+ if p.Battery > 100 {
+ p.Battery = 100
+ }
+ sess.WriteLine(fmt.Sprintf("\nYou drink the %s. Your battery is restored by %d%%.",
+ g.itemColorize(sess, def, def.Name), batteryRestore))
+
+ case "heal", "":
+ healAmount := def.PotionBonus
+ if healAmount <= 0 {
+ healAmount = def.HealValue
+ }
+ if healAmount <= 0 {
+ healAmount = 50
+ }
+ before := p.HP
+ maxHP := p.Level(player.Hitpoints)
+ if p.HP+healAmount > maxHP {
+ p.HP = maxHP
+ } else {
+ p.HP += healAmount
+ }
+ actualHeal := p.HP - before
+ sess.WriteLine(fmt.Sprintf("\nYou drink the %s. You restore %d hitpoints.",
+ g.itemColorize(sess, def, def.Name), actualHeal))
+
+ case "all_combat":
+ duration := engine.ToTicks(def.PotionDuration)
+ buffs := []string{"attack", "strength", "defense"}
+ for _, stat := range buffs {
+ p.ActiveBuffs = append(p.ActiveBuffs, player.PotionBuff{
+ Stat: stat,
+ BonusPercent: def.PotionBonus,
+ TicksLeft: duration,
+ })
+ }
+ sess.WriteLine(fmt.Sprintf("\nYou drink the %s. Your combat stats are boosted by %d%% for %d ticks.",
+ g.itemColorize(sess, def, def.Name), def.PotionBonus, duration))
+
+ default:
+ duration := engine.ToTicks(def.PotionDuration)
+ p.ActiveBuffs = append(p.ActiveBuffs, player.PotionBuff{
+ Stat: effect,
+ BonusPercent: def.PotionBonus,
+ TicksLeft: duration,
+ })
+ sess.WriteLine(fmt.Sprintf("\nYou drink the %s. Your %s is boosted by %d%% for %d ticks.",
+ g.itemColorize(sess, def, def.Name), effect, def.PotionBonus, duration))
+ }
+
+ p.ConsumeCooldown = 3
+ p.ActionState = &ActionState{Type: ActionEating}
+
+ if g.Hub != nil {
+ for _, other := range g.Hub.PlayersInRoom(p.RoomID) {
+ if other != sess && other.Player != nil {
+ other.WriteLine(g.colorize(other, "broadcast", fmt.Sprintf("\n%s drinks a %s.", p.Name, def.Name)))
+ }
+ }
+ }
+}