aboutsummaryrefslogtreecommitdiff
path: root/internal/game/act_use.go
diff options
context:
space:
mode:
authorhistoria <[not public]>2026-06-25 15:40:48 -0400
committerhistoria <[not public]>2026-06-25 15:40:48 -0400
commitabd612c15799f604e671e83dc7c410ed2b44185f (patch)
tree0597ca92350de73aac2a7cf26b2f2d6595dac0cc /internal/game/act_use.go
parent2725e2927a1595c7b100d942d1f14146252adeb7 (diff)
downloadthehouseoficarus-abd612c15799f604e671e83dc7c410ed2b44185f.tar.gz
slop refactor
Diffstat (limited to 'internal/game/act_use.go')
-rw-r--r--internal/game/act_use.go123
1 files changed, 123 insertions, 0 deletions
diff --git a/internal/game/act_use.go b/internal/game/act_use.go
new file mode 100644
index 0000000..34f28c3
--- /dev/null
+++ b/internal/game/act_use.go
@@ -0,0 +1,123 @@
+package game
+
+import (
+ "fmt"
+ "math/rand"
+
+ "thehouseoficarus/internal/behavior"
+ "thehouseoficarus/internal/engine"
+ "thehouseoficarus/internal/net"
+ "thehouseoficarus/internal/object"
+ "thehouseoficarus/internal/player"
+)
+
+func (g *Game) startUse(sess *net.Session, p *player.Player, obj *object.ObjectDef) {
+ cfg := obj.Use
+ if cfg == nil {
+ sess.WriteLine("You can't use this.")
+ return
+ }
+
+ for itemID := range cfg.Consume {
+ if !p.HasItem(itemID) {
+ defName := itemID
+ if def, err := g.ItemStore.Load(itemID); err == nil {
+ defName = g.itemColorize(sess, def, def.Name)
+ }
+ sess.WriteLine(fmt.Sprintf("You need %s to use this.", defName))
+ return
+ }
+ }
+
+ if cfg.Success == nil && p.FirstFreeSlot() == -1 {
+ sess.WriteLine("Your inventory is full.")
+ return
+ }
+
+ g.broadcastAction(sess, "\n%s uses the %s.", p.Name, obj.Name)
+
+ p.Action = &behavior.Action{
+ Type: "use",
+ TargetID: obj.ID,
+ TargetName: obj.Name,
+ WaitLeft: engine.ToTicks(1),
+ Data: &behavior.UseData{Cfg: cfg, Step: 0},
+ }
+
+ sess.WriteLine(fmt.Sprintf("%s", cfg.Message))
+}
+
+func (g *Game) advanceUse(sess *net.Session, p *player.Player) {
+ d, ok := p.Action.Data.(*behavior.UseData)
+ if !ok || d == nil || d.Cfg == nil {
+ g.cancelAction(p)
+ return
+ }
+ cfg := d.Cfg
+
+ for itemID, qty := range cfg.Consume {
+ if !p.HasItem(itemID) {
+ defName := itemID
+ if def, err := g.ItemStore.Load(itemID); err == nil {
+ defName = g.itemColorize(sess, def, def.Name)
+ }
+ sess.WriteLine(fmt.Sprintf("You've run out of %s.", defName))
+ g.cancelAction(p)
+ return
+ }
+ if !p.RemoveItem(itemID, qty) {
+ sess.WriteLine(fmt.Sprintf("You need %d of %s.", qty, itemID))
+ g.cancelAction(p)
+ return
+ }
+ }
+
+ if cfg.Success != nil {
+ skillLevel := p.Level(player.SkillName(cfg.Skill))
+ chance := behavior.SuccessChance(*cfg.Success, skillLevel, cfg.Level)
+ if rand.Float64() >= chance {
+ if cfg.FailMsg != "" {
+ sess.WriteLine(cfg.FailMsg)
+ }
+ p.Action.WaitLeft = engine.ToTicks(cfg.Wait)
+ return
+ }
+ }
+
+ freeSlot := p.FirstFreeSlot()
+ if freeSlot == -1 {
+ sess.WriteLine("Your inventory is full.")
+ g.cancelAction(p)
+ return
+ }
+
+ qty := cfg.Reward.Quantity
+ if qty <= 0 {
+ qty = 1
+ }
+
+ p.SetInvSlot(freeSlot, &player.InventorySlot{ItemID: cfg.Reward.ItemID, Quantity: qty})
+ if cfg.XP > 0 {
+ g.awardSkillXP(sess, p, player.SkillName(cfg.Skill), cfg.XP)
+ }
+ g.AccountStore.SaveCharacter(p)
+
+ itemName := cfg.Reward.ItemID
+ rewardDef, _ := g.ItemStore.Load(cfg.Reward.ItemID)
+ if rewardDef != nil {
+ itemName = rewardDef.Name
+ }
+ line := fmt.Sprintf("You make a %s.", g.itemColorize(sess, rewardDef, itemName))
+ if cfg.XP > 0 && p.OptionBool("xp_drops") {
+ line += g.formatXpDropSingle(sess, p, player.SkillName(cfg.Skill), cfg.XP)
+ }
+ sess.WriteLine(line)
+
+ if p.FirstFreeSlot() == -1 {
+ sess.WriteLine("Your inventory is full.")
+ g.cancelAction(p)
+ return
+ }
+
+ p.Action.WaitLeft = engine.ToTicks(cfg.Wait)
+}