package game import ( "fmt" "path/filepath" "strings" "gopkg.in/yaml.v3" "thehouseoficarus/internal/behavior" "thehouseoficarus/internal/net" "thehouseoficarus/internal/ui" ) type HelpDef struct { Name string `yaml:"name"` Category string `yaml:"category"` Content string `yaml:"description"` } type cmdEntry struct { Name string Type string Desc string } var commandList = []cmdEntry{ {"alias", "Instant", "Create command shortcuts"}, {"attack / kill", "Active", "Attack a mob"}, {"autotrigger / auto", "Instant", "Set a module to auto-trigger"}, {"bank", "Active", "Open bank interface"}, {"burn", "Active", "Start a fire"}, {"chop / cut", "Active", "Chop trees (Woodcutting)"}, {"clean", "Free", "Clean grimy herbs (Pharmacy)"}, {"color / colors", "Instant", "Customize display colors"}, {"colortable", "Instant", "Display color reference chart"}, {"construct / make", "Active", "Build furniture (Construction)"}, {"cook", "Active", "Cook raw food on a fire or range"}, {"craft", "Active", "Craft jewelry (Crafting)"}, {"description / desc", "Instant", "Set your character description"}, {"drink", "Free", "Drink a potion"}, {"drop", "Active", "Drop items to the ground"}, {"eat", "Free", "Eat food to restore hitpoints"}, {"equipment / eq", "Instant", "Show equipped items"}, {"exits", "Instant", "List available exits"}, {"farm", "Active", "Farm crops (Farming)"}, {"fish", "Active", "Fish at fishing spots (Fishing)"}, {"fletch", "Free", "Fletch logs into bows (Fletching)"}, {"get / take / pick", "Active", "Pick up items from the ground"}, {"global", "Instant", "Chat with everyone on the server"}, {"help", "Instant", "Show help topics"}, {"id / identify", "Active", "Identify herbs (Pharmacy)"}, {"inventory / i / inv", "Instant", "Show your inventory"}, {"jack / jackin", "Active", "Jack into a terminal (Hacking)"}, {"look / l", "Instant", "Look around or examine things"}, {"map", "Instant", "Display an ASCII map of the area"}, {"play", "Active", "Join a casino game in the current room"}, {"bet", "Active", "Place a casino wager (e.g. bet 100 on banker)"}, {"autobet / autospin", "Active", "Automatically repeat a casino wager"}, {"spin", "Active", "Spin the current casino wager"}, {"hit / stand / double / split", "Active", "Play a blackjack hand"}, {"insurance / surrender", "Active", "Use blackjack table options"}, {"mine", "Active", "Mine rocks (Mining)"}, {"mix", "Active", "Mix potions (Pharmacy)"}, {"mods / modlist", "Instant", "List available science modules"}, {"north / south / east / west / ne / nw / se / sw / up / down", "Active", "Move in a direction"}, {"option / options", "Instant", "View or change settings"}, {"prompt", "Instant", "Set custom command prompt"}, {"pull / push", "Active", "Interact with objects"}, {"queued", "Instant", "Show pending tick actions"}, {"quit", "Active", "Rest and disconnect"}, {"remove / unwear / unwield", "Free", "Unequip items"}, {"say", "Instant", "Chat with players in your room"}, {"score / sc", "Instant", "View your stats and skills"}, {"search", "Active", "Search items for loot"}, {"smelt", "Active", "Smelt ore into bars (Smithing)"}, {"smith", "Active", "Smith bars into items (Smithing)"}, {"sneak", "Instant", "Toggle sneak mode"}, {"steal", "Active", "Steal from mobs (Thieving)"}, {"stoke", "Active", "Add logs to a fire"}, {"style", "Instant", "Change combat style"}, {"symbol", "Instant", "Set custom map symbol for current room"}, {"talk / speak / ask", "Active", "Talk to mobs"}, {"tech", "Instant", "Toggle technology abilities"}, {"trigger", "Active", "Trigger a science module"}, {"unalias", "Instant", "Remove command shortcuts"}, {"use", "Active", "Use an object (crafting)"}, {"walk", "Active", "Pathfind to a room or multi-step walk"}, {"wear / wield", "Free", "Equip items"}, {"who", "Instant", "List everyone online and their combat level"}, } func LoadHelp(dataDir string) ([]HelpDef, error) { dir := filepath.Join(dataDir, "help") var helps []HelpDef behavior.WalkYAMLDir(dir, func(path, id string, data []byte) error { var h HelpDef if err := yaml.Unmarshal(data, &h); err != nil { return nil } helps = append(helps, h) return nil }) return helps, nil } func (g *Game) doHelp(sess *net.Session, topic string) { if topic == "" { unicode := true wrapWidth := 0 if p := sess.Player; p != nil { unicode = p.OptionBool("unicode") wrapWidth = p.OptionInt("wrap_width") } sess.WriteLine("") t := &ui.Table{ Title: "Commands", Columns: []string{"Command", "Type", "Description"}, } for _, c := range commandList { t.Rows = append(t.Rows, []string{c.Name, c.Type, c.Desc}) } for _, line := range t.Render(unicode, wrapWidth) { sess.WriteLine(line) } sess.WriteLine("") sess.WriteLine("Command types: Instant (runs immediately), Free (queued before active),") sess.WriteLine("Active (replaces current action, queued per tick).") sess.WriteLine("") sess.WriteLine("Use 'help ' for detailed usage of a specific command.") sess.WriteLine("Use 'option' to view and change settings, 'color' to customize colors.") return } helps, err := LoadHelp(g.DataDir) if err != nil || len(helps) == 0 { sess.WriteLine("No help available.") return } topic = strings.ToLower(topic) for _, h := range helps { if strings.ToLower(h.Name) == topic { sess.WriteLine(fmt.Sprintf(" %s", h.Content)) return } } sess.WriteLine(fmt.Sprintf("No help found for '%s'.", topic)) } func firstLine(s string) string { if idx := strings.Index(s, "\n"); idx >= 0 { return s[:idx] } return s } func (g *Game) executeHelp(sess *net.Session, args []string, rawInput string) { if len(args) == 0 { g.doHelp(sess, "") } else { g.doHelp(sess, strings.Join(args, " ")) } }