From a6f0ad79e2e3a5b7c11eef1ffc3233f3a2766f77 Mon Sep 17 00:00:00 2001 From: historia <[not public]> Date: Sun, 14 Jun 2026 22:38:23 -0400 Subject: feat: fractional ticks and server game_speed implemented. potentially insanely janky. --- internal/game/action_search.go | 122 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 122 insertions(+) create mode 100644 internal/game/action_search.go (limited to 'internal/game/action_search.go') 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)) +} -- cgit v1.2.3