aboutsummaryrefslogtreecommitdiff
path: root/internal/game/cmd_estate_directory.go
diff options
context:
space:
mode:
authorhistoria <[not public]>2026-06-19 13:28:06 -0400
committerhistoria <[not public]>2026-06-19 13:28:06 -0400
commit3a58125d14bb307f861b38c6c5b0a63babde7e08 (patch)
treebd89e866447d55e6dffd447d8ef5fabf9b8fbe9d /internal/game/cmd_estate_directory.go
parent575a71dcfed3b9fa44af244836f638a23df05a9a (diff)
downloadthehouseoficarus-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.go223
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)
+}