aboutsummaryrefslogtreecommitdiff
path: root/internal/game/action_use.go
diff options
context:
space:
mode:
authorhistoria <[not public]>2026-06-11 04:46:27 -0400
committerhistoria <[not public]>2026-06-11 08:58:37 +0000
commit1b9e2da3b3c438d8dc53d3489725dd5ba0022777 (patch)
tree62264f24420bf4cfaa734942c65cc8dd45ba3d3b /internal/game/action_use.go
parent06c02a697e5daf8832a462de5970dd4c0e13a02c (diff)
downloadthehouseoficarus-1b9e2da3b3c438d8dc53d3489725dd5ba0022777.tar.gz
feat: web client, get/drop updates and fixes
Diffstat (limited to 'internal/game/action_use.go')
-rw-r--r--internal/game/action_use.go120
1 files changed, 120 insertions, 0 deletions
diff --git a/internal/game/action_use.go b/internal/game/action_use.go
new file mode 100644
index 0000000..c1a07ed
--- /dev/null
+++ b/internal/game/action_use.go
@@ -0,0 +1,120 @@
+package game
+
+import (
+ "fmt"
+ "math/rand"
+
+ "thirdcollapse/internal/action"
+ "thirdcollapse/internal/net"
+ "thirdcollapse/internal/object"
+ "thirdcollapse/internal/player"
+)
+
+func (g *Game) startUse(sess *net.Session, p *player.Player, obj *object.ObjectDef) {
+ cfg, err := g.BehaviorStore.LoadUse(obj.BehaviorID)
+ if err != nil {
+ sess.WriteLine("You can't use this.")
+ return
+ }
+
+ for itemID, qty := range cfg.Consume {
+ if !p.HasItem(itemID) {
+ defName := itemID
+ if def, err := g.ItemStore.Load(itemID); err == nil {
+ defName = def.Name
+ }
+ sess.WriteLine(fmt.Sprintf("You need %s to use this.", defName))
+ return
+ }
+ _ = qty
+ }
+
+ if cfg.Success == nil && p.FirstFreeSlot() == -1 {
+ sess.WriteLine("Your inventory is full.")
+ return
+ }
+
+ p.Action = &action.Action{
+ Type: "use",
+ TargetID: obj.ID,
+ TargetName: obj.Name,
+ WaitLeft: 1,
+ Data: map[string]any{"step": 0, "behavior_id": obj.BehaviorID},
+ }
+
+ sess.WriteLine(fmt.Sprintf("\n%s", cfg.Message))
+}
+
+func (g *Game) advanceUse(sess *net.Session, p *player.Player) {
+ behaviorID := p.Action.Data["behavior_id"].(string)
+ cfg, err := g.BehaviorStore.LoadUse(behaviorID)
+ if err != nil {
+ g.CancelAction(p)
+ return
+ }
+
+ for itemID, qty := range cfg.Consume {
+ if !p.HasItem(itemID) {
+ defName := itemID
+ if def, err := g.ItemStore.Load(itemID); err == nil {
+ defName = 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 := action.SuccessChance(*cfg.Success, skillLevel, cfg.Level)
+ if rand.Float64() >= chance {
+ if cfg.FailMsg != "" {
+ sess.WriteLine(cfg.FailMsg)
+ }
+ p.Action.WaitLeft = 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 {
+ p.AddXP(player.SkillName(cfg.Skill), cfg.XP)
+ }
+ g.AccountStore.SaveCharacter(p)
+
+ itemName := cfg.Reward.ItemID
+ if def, err := g.ItemStore.Load(cfg.Reward.ItemID); err == nil {
+ itemName = def.Name
+ }
+ line := fmt.Sprintf("You make a %s.", itemName)
+ if cfg.XP > 0 && p.Toggles["xpdrops"] {
+ line += fmt.Sprintf(" (+%dxp %s)", cfg.XP, player.SkillAbbr[player.SkillName(cfg.Skill)])
+ }
+ sess.WriteLine(line)
+
+ if p.FirstFreeSlot() == -1 {
+ sess.WriteLine("Your inventory is full.")
+ g.CancelAction(p)
+ return
+ }
+
+ p.Action.WaitLeft = cfg.Wait
+}