package game import ( "thehouseoficarus/internal/color" "thehouseoficarus/internal/config" "thehouseoficarus/internal/item" "thehouseoficarus/internal/net" "thehouseoficarus/internal/object" ) func (g *Game) colorMode(sess *net.Session) string { if p := sess.Player; p != nil { return p.OptionString("color") } return "none" } func (g *Game) resolveColor(sess *net.Session, category string) color.ColorSpec { if sess != nil && sess.Account != nil && sess.Account.Colors != nil { if val, ok := sess.Account.Colors[category]; ok { if val == "off" { return color.NoColor() } if val != "" { return color.Parse(val) } } } if g.ColorConfig != nil { if val, ok := (*g.ColorConfig)[category]; ok && val != "" { return color.Parse(val) } } if val, ok := config.DefaultColors()[category]; ok && val != "" { return color.Parse(val) } return color.NoColor() } func (g *Game) colorize(sess *net.Session, category, text string) string { spec := g.resolveColor(sess, category) return color.Render(g.colorMode(sess), spec, text) } // resolveConstant returns the live spec for a constant (player-invisible) // color category. Unlike resolveColor, it never consults the account's // per-player override map — constants are admin-tunable only — so players // have no way to change them. Falls back through the file's constant_colors // map, then to the built-in DefaultConstantColors. func (g *Game) resolveConstant(sess *net.Session, category string) color.ColorSpec { if g.ConstantColorConfig != nil { if val, ok := (*g.ConstantColorConfig)[category]; ok && val != "" { return color.Parse(val) } } if val, ok := config.DefaultConstantColors()[category]; ok && val != "" { return color.Parse(val) } return color.NoColor() } // colorizeConstant paints text with a constant color spec, bypassing the // player override tier entirely. func (g *Game) colorizeConstant(sess *net.Session, category, text string) string { spec := g.resolveConstant(sess, category) return color.Render(g.colorMode(sess), spec, text) } // levelColorSpec returns the color spec for the level-difference band shown // next to mob/player levels (green/red/white by how far the target is from // the viewer). Uses admin-tunable constant_colors; falls back to built-ins. func (g *Game) levelColorSpec(sess *net.Session, myLevel, theirLevel int) color.ColorSpec { diff := theirLevel - myLevel var name string switch { case diff == 0: name = "level_diff_equal" case diff > 0 && diff < 5: name = "level_diff_up_small" case diff >= 5: name = "level_diff_up_big" case diff < 0 && diff > -5: name = "level_diff_down_small" default: name = "level_diff_down_big" } return g.resolveConstant(sess, name) } func (g *Game) levelColorize(sess *net.Session, myLevel, theirLevel int, text string) string { spec := g.levelColorSpec(sess, myLevel, theirLevel) return color.Render(g.colorMode(sess), spec, text) } func (g *Game) objColorize(sess *net.Session, objDef *object.ObjectDef, text string) string { if objDef != nil && objDef.Color != "" { spec := color.Parse(objDef.Color) return color.Render(g.colorMode(sess), spec, text) } return text } func (g *Game) itemColorize(sess *net.Session, itemDef *item.ItemDef, text string) string { if itemDef != nil && itemDef.Color != "" { spec := color.Parse(itemDef.Color) return color.Render(g.colorMode(sess), spec, text) } return g.colorize(sess, "item", text) }