aboutsummaryrefslogtreecommitdiff
path: root/internal/game/action_search.go
diff options
context:
space:
mode:
authorhistoria <[not public]>2026-06-14 22:38:23 -0400
committerhistoria <[not public]>2026-06-14 22:38:23 -0400
commita6f0ad79e2e3a5b7c11eef1ffc3233f3a2766f77 (patch)
tree89601a502bbfcb50302cf03f09b6febc6040eeb0 /internal/game/action_search.go
parent1aba2bdd23aebed4032333e74aa553c40a31fcbd (diff)
downloadthehouseoficarus-a6f0ad79e2e3a5b7c11eef1ffc3233f3a2766f77.tar.gz
feat: fractional ticks and server game_speed implemented. potentially insanely janky.
Diffstat (limited to 'internal/game/action_search.go')
-rw-r--r--internal/game/action_search.go122
1 files changed, 122 insertions, 0 deletions
diff --git a/internal/game/action_search.go b/internal/game/action_search.go
new file mode 100644
index 0000000..07bae44
--- /dev/null
+++ b/internal/game/action_search.go
@@ -0,0 +1,122 @@
+package game
+
+import (
+ "fmt"
+
+ "thirdcollapse/internal/action"
+ "thirdcollapse/internal/net"
+ "thirdcollapse/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: g.computeTicks(ticks),
+ Data: map[string]any{
+ "item_id": itemID,
+ "slot_idx": slotIdx,
+ "started": false,
+ },
+ }
+
+ p.ActionState = &ActionState{Type: ActionSearching, TargetName: def.Name}
+}
+
+func (g *Game) advanceSearch(sess *net.Session, p *player.Player) {
+ data := p.Action.Data
+ itemID := data["item_id"].(string)
+ slotIdx := data["slot_idx"].(int)
+ started := data["started"].(bool)
+
+ def, err := g.ItemStore.Load(itemID)
+ if err != nil {
+ sess.WriteLine("Something went wrong.")
+ g.CancelAction(p)
+ return
+ }
+
+ if !started {
+ msg := def.SearchMessage
+ if msg == "" {
+ msg = fmt.Sprintf("digging through the %s", def.Name)
+ }
+ sess.WriteLine(fmt.Sprintf("You begin %s.", msg))
+ data["started"] = true
+ return
+ }
+
+ slot := p.InvSlot(slotIdx)
+ if slot == nil || slot.ItemID != itemID || slot.Quantity <= 0 {
+ sess.WriteLine("The item is gone.")
+ g.CancelAction(p)
+ return
+ }
+
+ if slot.Quantity > 1 {
+ slot.Quantity--
+ } else {
+ p.SetInvSlot(slotIdx, nil)
+ }
+
+ dt, err := g.BehaviorStore.LoadDropTable(def.SearchTable)
+ if err == nil && len(dt.Drops) > 0 {
+ drop := g.BehaviorStore.ResolveDrop(dt.Drops)
+ if drop != nil && drop.ItemID != "" {
+ g.giveSearchLoot(sess, p, drop)
+ }
+ }
+
+ if def.SearchMiscTable != "" {
+ dt2, err := g.BehaviorStore.LoadDropTable(def.SearchMiscTable)
+ if err == nil && len(dt2.Drops) > 0 {
+ drop := g.BehaviorStore.ResolveDrop(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
+ if def, err := g.ItemStore.Load(drop.ItemID); err == nil {
+ name = def.Name
+ }
+
+ if drop.ItemID == "credits" {
+ p.Credits += qty
+ sess.WriteLine(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.", name))
+ return
+ }
+
+ p.SetInvSlot(freeSlot, &player.InventorySlot{ItemID: drop.ItemID, Quantity: qty})
+ sess.WriteLine(fmt.Sprintf("You find %s.", name))
+}