aboutsummaryrefslogtreecommitdiff
path: root/internal/game/action_search.go
blob: 0f755a5e323dc53d0609685de50b851ea475f3e6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
package game

import (
	"fmt"

	"thehouseoficarus/internal/action"
	"thehouseoficarus/internal/engine"
	"thehouseoficarus/internal/net"
	"thehouseoficarus/internal/player"
)

func (g *Game) startSearch(sess *net.Session, p *player.Player, itemID string, slotIdx int) {
	def, err := g.ItemStore.Load(itemID)
	if err != nil || def.SearchTable == "" {
		sess.WriteLine("You can't search that.")
		return
	}

	ticks := def.SearchTicks
	if ticks <= 0 {
		ticks = 3
	}

	p.Action = &action.Action{
		Type:       "search",
		TargetID:   itemID,
		TargetName: def.Name,
		WaitLeft:   engine.ToTicks(ticks),
		Data: &action.SearchData{
			ItemID:  itemID,
			SlotIdx: slotIdx,
			Started: false,
		},
	}

	g.broadcastAction(sess, "\n%s searches a %s.", p.Name, def.Name)
}

func (g *Game) advanceSearch(sess *net.Session, p *player.Player) {
	d, ok := p.Action.Data.(*action.SearchData)
	if !ok || d == nil {
		sess.WriteLine("Something went wrong.")
		g.cancelAction(p)
		return
	}

	def, err := g.ItemStore.Load(d.ItemID)
	if err != nil {
		sess.WriteLine("Something went wrong.")
		g.cancelAction(p)
		return
	}

	if !d.Started {
		msg := def.SearchMessage
		if msg == "" {
			msg = fmt.Sprintf("digging through the %s", def.Name)
		}
		sess.WriteLine(fmt.Sprintf("You begin %s.", msg))
		d.Started = true
		return
	}

	slot := p.InvSlot(d.SlotIdx)
	if slot == nil || slot.ItemID != d.ItemID || slot.Quantity <= 0 {
		sess.WriteLine("The item is gone.")
		g.cancelAction(p)
		return
	}

	if slot.Quantity > 1 {
		slot.Quantity--
	} else {
		p.SetInvSlot(d.SlotIdx, nil)
	}

	dt, err := action.LoadDropTable(g.DataDir, def.SearchTable)
	if err == nil && len(dt.Drops) > 0 {
		drop := action.ResolveDrop(g.DataDir, dt.Drops)
		if drop != nil && drop.ItemID != "" {
			g.giveSearchLoot(sess, p, drop)
		}
	}

	if def.SearchMiscTable != "" {
		dt2, err := action.LoadDropTable(g.DataDir, def.SearchMiscTable)
		if err == nil && len(dt2.Drops) > 0 {
			drop := action.ResolveDrop(g.DataDir, dt2.Drops)
			if drop != nil && drop.ItemID != "" {
				g.giveSearchLoot(sess, p, drop)
			}
		}
	}

	g.AccountStore.SaveCharacter(p)
	g.cancelAction(p)
}

func (g *Game) giveSearchLoot(sess *net.Session, p *player.Player, drop *action.DropEntry) {
	qty := drop.Quantity
	if qty <= 0 {
		qty = 1
	}

	name := drop.ItemID
	lootDef, _ := g.ItemStore.Load(drop.ItemID)
	if lootDef != nil {
		name = lootDef.Name
	}

	if drop.ItemID == "credits" {
		p.Credits += qty
		sess.WriteLine(g.colorize(sess, "credits_pickup", fmt.Sprintf("You find %d credits.", qty)))
		return
	}

	freeSlot := p.FirstFreeSlot()
	if freeSlot == -1 {
		g.World.AddGroundItem(p.RoomID, drop.ItemID, qty)
		sess.WriteLine(fmt.Sprintf("You find %s. It falls to the ground.", g.itemColorize(sess, lootDef, name)))
		return
	}

	p.SetInvSlot(freeSlot, &player.InventorySlot{ItemID: drop.ItemID, Quantity: qty})
	sess.WriteLine(fmt.Sprintf("You find %s.", g.itemColorize(sess, lootDef, name)))
}