diff options
| author | historia <[not public]> | 2026-06-19 13:28:06 -0400 |
|---|---|---|
| committer | historia <[not public]> | 2026-06-19 13:28:06 -0400 |
| commit | 3a58125d14bb307f861b38c6c5b0a63babde7e08 (patch) | |
| tree | bd89e866447d55e6dffd447d8ef5fabf9b8fbe9d /internal/game/cmd_estate_directory.go | |
| parent | 575a71dcfed3b9fa44af244836f638a23df05a9a (diff) | |
| download | thehouseoficarus-3a58125d14bb307f861b38c6c5b0a63babde7e08.tar.gz | |
feat: all skills kind of implemented, random prototype content added
Diffstat (limited to 'internal/game/cmd_estate_directory.go')
| -rw-r--r-- | internal/game/cmd_estate_directory.go | 223 |
1 files changed, 223 insertions, 0 deletions
diff --git a/internal/game/cmd_estate_directory.go b/internal/game/cmd_estate_directory.go new file mode 100644 index 0000000..6c66ca4 --- /dev/null +++ b/internal/game/cmd_estate_directory.go @@ -0,0 +1,223 @@ +package game + +import ( + "fmt" + "os" + "path/filepath" + "sort" + "strings" + + "thehouseoficarus/internal/action" + "thehouseoficarus/internal/net" + "thehouseoficarus/internal/player" + + "gopkg.in/yaml.v3" +) + +func (g *Game) startEstateDirectory(sess *net.Session, verb string) { + p := sess.Player.(*player.Player) + + if verb == "toggle" { + sess.WriteLine("You can't do that with the directory.") + return + } + + homeowners := g.scanHomeowners("owns_house_local_neighborhood") + ownedByMe := false + for _, h := range homeowners { + if h == p.Name { + ownedByMe = true + break + } + } + + if verb == "talk" { + g.showEstateDirectoryTalk(sess, p, homeowners, ownedByMe) + return + } + + if verb == "use" { + if ownedByMe { + houseRoom := g.getOwnedHouseRoom(p, "owns_house_local_neighborhood") + if houseRoom > 0 { + g.CancelAction(p) + g.teleportPlayer(sess, p, houseRoom) + return + } + } + sess.WriteLine("You don't own a house here. Talk to the estate broker to purchase one.") + return + } +} + +func (g *Game) lookEstateDirectory(sess *net.Session) { + homeowners := g.scanHomeowners("owns_house_local_neighborhood") + sess.WriteLine("") + sess.WriteLine(g.colorize(sess, "dialog", "Estate Directory")) + sess.WriteLine(fmt.Sprintf(" A holographic terminal displaying property records for the Local Neighborhood.")) + sess.WriteLine("") + if len(homeowners) == 0 { + sess.WriteLine(" No registered homeowners in this area.") + } else { + sess.WriteLine(" Registered homeowners:") + for i, name := range homeowners { + sess.WriteLine(fmt.Sprintf(" %d. %s", i+1, name)) + } + } + sess.WriteLine("") + sess.WriteLine(" Use the directory to enter your home, or talk to the estate broker to purchase.") +} + +func (g *Game) showEstateDirectoryTalk(sess *net.Session, p *player.Player, homeowners []string, ownedByMe bool) { + sess.WriteLine("") + sess.WriteLine(g.colorize(sess, "dialog", "The directory terminal hums quietly, displaying a list of registered homeowners...")) + + if ownedByMe { + sess.WriteLine("") + sess.WriteLine(" You are a registered homeowner in this neighborhood.") + sess.WriteLine(" Type 'enter' to go to your house, or 'leave' to step away.") + sess.State = net.StateTalk + p.ActionState = &ActionState{Type: ActionTalking, TargetName: "Estate Directory"} + p.Action = &action.Action{ + Type: "talk", + TargetID: "estate_directory", + TargetName: "Estate Directory", + Data: map[string]any{"node": "start", "behavior_id": "estate_directory_talk"}, + } + sess.Write("\nChoice: ") + return + } + + sess.WriteLine("") + if len(homeowners) > 0 { + sess.WriteLine(" Currently owned by: " + strings.Join(homeowners, ", ")) + } + sess.WriteLine(" You don't own a house here yet.") + sess.WriteLine(" Talk to the estate broker to purchase a plot for 10 credits.") +} + +func (g *Game) handleEstateDirectoryTalk(sess *net.Session, input string) { + input = strings.TrimSpace(strings.ToLower(input)) + + switch input { + case "enter": + p, ok := sess.Player.(*player.Player) + if !ok { + return + } + houseRoom := g.getOwnedHouseRoom(p, "owns_house_local_neighborhood") + if houseRoom > 0 { + sess.State = net.StateGame + p.Action = nil + p.ActionState = nil + g.teleportPlayer(sess, p, houseRoom) + return + } + sess.State = net.StateGame + p.Action = nil + p.ActionState = nil + g.writePrompt(sess) + case "leave", "bye", "exit", "quit": + p, ok := sess.Player.(*player.Player) + if ok { + p.Action = nil + p.ActionState = nil + } + sess.State = net.StateGame + g.writePrompt(sess) + default: + sess.WriteLine("Type 'enter' to go to your house, or 'leave' to step away.") + sess.Write("\nChoice: ") + } +} + +func (g *Game) scanHomeowners(flagKey string) []string { + var homeowners []string + + charsDir := filepath.Join(g.dataDir, "players", "characters") + entries, err := os.ReadDir(charsDir) + if err != nil { + return homeowners + } + + for _, entry := range entries { + if entry.IsDir() || !strings.HasSuffix(entry.Name(), ".yaml") { + continue + } + + name := strings.TrimSuffix(entry.Name(), ".yaml") + data, err := os.ReadFile(filepath.Join(charsDir, entry.Name())) + if err != nil { + continue + } + + var p struct { + Flags map[string]any `yaml:"flags"` + } + if err := yaml.Unmarshal(data, &p); err != nil { + continue + } + + if p.Flags != nil { + if val, ok := p.Flags[flagKey]; ok && val != nil { + owned := false + switch v := val.(type) { + case bool: + owned = v + case string: + owned = v != "" && v != "false" + } + if owned { + homeowners = append(homeowners, name) + } + } + } + } + + sort.Strings(homeowners) + return homeowners +} + +func (g *Game) getOwnedHouseRoom(p *player.Player, flagKey string) int { + if p.Flags == nil { + return 0 + } + val, ok := p.Flags[flagKey] + if !ok || val == nil { + return 0 + } + + v, ok := val.(string) + if !ok || v == "" { + return 0 + } + + houseMap := map[string]int{ + "local_neighborhood": 200, + } + return houseMap[v] +} + +func (g *Game) teleportPlayer(sess *net.Session, p *player.Player, roomID int) { + if g.Hub != nil { + for _, other := range g.Hub.PlayersInRoom(p.RoomID) { + if other != sess { + other.WriteLine(fmt.Sprintf("\n%s disappears in a shimmer of light.", p.Name)) + } + } + } + + p.RoomID = roomID + if g.Hub != nil { + g.Hub.LeaveRoom(sess) + g.Hub.EnterRoom(sess, p.RoomID) + } + + g.World.SeedGroundItems(p.RoomID) + g.seedRoomMobs(p.RoomID) + g.seedRoomObjects(p.RoomID) + g.AccountStore.SaveCharacter(p) + g.doLook(sess) + g.RunEnterSteps(sess, p.RoomID) + g.writePrompt(sess) +} |
