diff --git a/assets/dk.css b/assets/dk.css
index ed8341d..3060155 100644
--- a/assets/dk.css
+++ b/assets/dk.css
@@ -290,9 +290,21 @@ div#statbars {
background-color: white;
}
- hp > div.bar {
- background: #56ab2f;
- background: linear-gradient(to left, #a8e063, #56ab2f);
+ hp {
+ & > div.bar {
+ background: #56ab2f;
+ background: linear-gradient(to left, #a8e063, #56ab2f);
+ }
+
+ &.warning > div.bar {
+ background: #F2994A;
+ background: linear-gradient(to left, #F2C94C, #F2994A);
+ }
+
+ &.danger > div.bar {
+ background: #cb2d3e;
+ background: linear-gradient(to left, #ef473a, #cb2d3e);
+ }
}
mp > div.bar {
@@ -305,9 +317,5 @@ div#statbars {
background: linear-gradient(to right, #757f9a, #d7dde8);
}
}
-
- & > label {
-
- }
}
}
\ No newline at end of file
diff --git a/internal/helpers/convert.go b/internal/helpers/convert.go
new file mode 100644
index 0000000..833a265
--- /dev/null
+++ b/internal/helpers/convert.go
@@ -0,0 +1,28 @@
+package helpers
+
+import (
+ "strconv"
+ "strings"
+)
+
+// StringToInts converts comma-delimited string to int slice
+func StringToInts(s string) []int {
+ if s == "" {
+ return []int{}
+ }
+ parts := strings.Split(s, ",")
+ ints := make([]int, len(parts))
+ for i, part := range parts {
+ ints[i], _ = strconv.Atoi(part)
+ }
+ return ints
+}
+
+// IntToString converts int slice to comma-delimited string
+func IntsToString(ints []int) string {
+ strs := make([]string, len(ints))
+ for i, num := range ints {
+ strs[i] = strconv.Itoa(num)
+ }
+ return strings.Join(strs, ",")
+}
diff --git a/internal/template/components/asides.go b/internal/template/components/asides.go
index b1cb18c..20cb225 100644
--- a/internal/template/components/asides.go
+++ b/internal/template/components/asides.go
@@ -4,32 +4,23 @@ import (
"dk/internal/helpers"
"dk/internal/middleware"
"dk/internal/router"
+ "dk/internal/spells"
"dk/internal/template"
"dk/internal/towns"
- "dk/internal/users"
)
// LeftAside generates the left sidebar content
func LeftAside(ctx router.Ctx) string {
- if !middleware.IsAuthenticated(ctx) {
+ user := middleware.GetCurrentUser(ctx)
+ if user == nil {
return ""
}
- leftSideTmpl, err := template.Cache.Load("leftside.html")
+ tmpl, err := template.Cache.Load("leftside.html")
if err != nil {
return "leftside failed to load?"
}
- currentUser := middleware.GetCurrentUser(ctx)
- if currentUser == nil {
- return "no currentUser?"
- }
-
- user, err := users.Find(currentUser.ID)
- if err != nil {
- return "user not found?"
- }
-
cardinalX := "E"
if user.X < 0 {
cardinalX = "W"
@@ -46,18 +37,32 @@ func LeftAside(ctx router.Ctx) string {
if err != nil {
townname = "error finding town"
}
- townname = "In " + town.Name + ""
+ townname = "
In " + town.Name + "
"
}
- leftSideData := map[string]any{
+ townlist := ""
+ townIDs := user.GetTownIDs()
+ if len(townIDs) > 0 {
+ townlist = "Teleport to:
"
+ for _, id := range townIDs {
+ town, err := towns.Find(id)
+ if err != nil {
+ continue
+ }
+
+ townlist += `` + town.Name + "
"
+ }
+ } else {
+ townlist = "No town maps"
+ }
+
+ return tmpl.RenderNamed(map[string]any{
"user": user.ToMap(),
"cardinalX": cardinalX,
"cardinalY": cardinalY,
"townname": townname,
- "townlist": "@TODO",
- }
-
- return leftSideTmpl.RenderNamed(leftSideData)
+ "townlist": townlist,
+ })
}
// RightAside generates the right sidebar content
@@ -76,10 +81,72 @@ func RightAside(ctx router.Ctx) string {
mpPct := helpers.ClampPct(float64(user.MP), float64(user.MaxMP), 0, 100)
tpPct := helpers.ClampPct(float64(user.TP), float64(user.MaxTP), 0, 100)
+ hpColor := ""
+ if hpPct < 35 {
+ hpColor = "danger"
+ } else if hpPct < 75 {
+ hpColor = "warning"
+ }
+
+ weaponName := "No weapon"
+ if user.WeaponName != "" {
+ weaponName = user.WeaponName
+ }
+
+ armorName := "No armor"
+ if user.ArmorName != "" {
+ armorName = user.ArmorName
+ }
+
+ shieldName := "No shield"
+ if user.ShieldName != "" {
+ shieldName = user.ShieldName
+ }
+
+ slot1Name := ""
+ if user.Slot1Name != "" {
+ slot1Name = user.Slot1Name
+ }
+
+ slot2Name := ""
+ if user.Slot2Name != "" {
+ slot2Name = user.Slot2Name
+ }
+
+ slot3Name := ""
+ if user.Slot3Name != "" {
+ slot3Name = user.Slot3Name
+ }
+
+ magicList := ""
+ list := user.GetSpellIDs()
+ if len(list) > 0 {
+ for i := range list {
+ spell, err := spells.Find(i)
+ if err != nil {
+ continue
+ }
+
+ if spell.IsHealing() {
+ magicList += `` + spell.Name + ""
+ }
+ }
+ } else {
+ magicList = "No healing spells known"
+ }
+
return tmpl.RenderNamed(map[string]any{
- "user": user.ToMap(),
- "hppct": hpPct,
- "mppct": mpPct,
- "tppct": tpPct,
+ "user": user.ToMap(),
+ "hppct": hpPct,
+ "hpcolor": hpColor,
+ "mppct": mpPct,
+ "tppct": tpPct,
+ "weaponname": weaponName,
+ "armorname": armorName,
+ "shieldname": shieldName,
+ "slot1name": slot1Name,
+ "slot2name": slot2Name,
+ "slot3name": slot3Name,
+ "magiclist": magicList,
})
}
diff --git a/internal/users/users.go b/internal/users/users.go
index dc78107..f6a80a2 100644
--- a/internal/users/users.go
+++ b/internal/users/users.go
@@ -2,10 +2,11 @@ package users
import (
"fmt"
- "strings"
+ "slices"
"time"
"dk/internal/database"
+ "dk/internal/helpers"
"dk/internal/helpers/scanner"
"zombiezen.com/go/sqlite"
@@ -271,7 +272,7 @@ func (u *User) IsAdmin() bool {
}
func (u *User) IsModerator() bool {
- return u.Auth >= 2
+ return u.Auth >= 3
}
func (u *User) IsFighting() bool {
@@ -282,46 +283,28 @@ func (u *User) IsAlive() bool {
return u.HP > 0
}
-func (u *User) GetSpellIDs() []string {
- if u.Spells == "" {
- return []string{}
- }
- return strings.Split(u.Spells, ",")
+func (u *User) GetSpellIDs() []int {
+ return helpers.StringToInts(u.Spells)
}
-func (u *User) SetSpellIDs(spells []string) {
- u.Set("Spells", strings.Join(spells, ","))
+func (u *User) SetSpellIDs(spells []int) {
+ u.Set("Spells", helpers.IntsToString(spells))
}
-func (u *User) HasSpell(spellID string) bool {
- spells := u.GetSpellIDs()
- for _, spell := range spells {
- if strings.TrimSpace(spell) == spellID {
- return true
- }
- }
- return false
+func (u *User) HasSpell(spellID int) bool {
+ return slices.Contains(u.GetSpellIDs(), spellID)
}
-func (u *User) GetTownIDs() []string {
- if u.Towns == "" {
- return []string{}
- }
- return strings.Split(u.Towns, ",")
+func (u *User) GetTownIDs() []int {
+ return helpers.StringToInts(u.Towns)
}
-func (u *User) SetTownIDs(towns []string) {
- u.Set("Towns", strings.Join(towns, ","))
+func (u *User) SetTownIDs(towns []int) {
+ u.Set("Towns", helpers.IntsToString(towns))
}
-func (u *User) HasVisitedTown(townID string) bool {
- towns := u.GetTownIDs()
- for _, town := range towns {
- if strings.TrimSpace(town) == townID {
- return true
- }
- }
- return false
+func (u *User) HasTownMap(townID int) bool {
+ return slices.Contains(u.GetTownIDs(), townID)
}
func (u *User) GetEquipment() map[string]any {
diff --git a/templates/rightside.html b/templates/rightside.html
index fd4d75a..bf2bacc 100644
--- a/templates/rightside.html
+++ b/templates/rightside.html
@@ -5,24 +5,24 @@
Level: {user.Level}
Exp: {user.Exp}
Gold: {user.Gold}
- HP: {user.HP}
- MP: {user.MP}
- TP: {user.TP}
+ HP: {user.HP}/{user.MaxHP}
+ MP: {user.MP}/{user.MaxMP}
+ TP: {user.TP}/{user.MaxTP}