adjustment

This commit is contained in:
guiyomu-dev
2026-02-13 12:34:48 +01:00
parent 52f9079ba1
commit 828db2029f
12 changed files with 226 additions and 97 deletions

View File

@@ -2,7 +2,9 @@ package main
import ( import (
"bufio" "bufio"
"bytes"
"fmt" "fmt"
"go/format"
"os" "os"
"regexp" "regexp"
"strings" "strings"
@@ -10,15 +12,22 @@ import (
) )
func main() { func main() {
if err := run(); err != nil {
panic(err)
}
}
func run() error {
// Read items.go // Read items.go
f, err := os.Open("pkg/data/item/items.go") f, err := os.Open("pkg/data/item/items.go")
if err != nil { if err != nil {
panic(err) return err
} }
defer f.Close() defer f.Close()
nameRe := regexp.MustCompile(`Name:\s*"([^"]*)"`) nameRe := regexp.MustCompile(`Name:\s*"([^"]*)"`)
var names []string var names []string
seenNames := make(map[string]string)
scanner := bufio.NewScanner(f) scanner := bufio.NewScanner(f)
for scanner.Scan() { for scanner.Scan() {
@@ -27,37 +36,43 @@ func main() {
if m == nil { if m == nil {
continue continue
} }
raw := strings.TrimSpace(m[1]) raw := m[1]
// Remove apostrophes canonical := canonicalizeName(raw)
raw = strings.ReplaceAll(raw, "'", "") if canonical == "" {
// Split by whitespace, capitalize each word, join return fmt.Errorf("unable to generate canonical name for item %q", raw)
words := strings.Fields(raw)
var camel strings.Builder
for _, w := range words {
if len(w) == 0 {
continue
}
runes := []rune(w)
runes[0] = unicode.ToUpper(runes[0])
camel.WriteString(string(runes))
} }
names = append(names, camel.String())
if existingRaw, exists := seenNames[canonical]; exists && existingRaw != raw {
return fmt.Errorf("duplicate generated item name %q from %q and %q", canonical, existingRaw, raw)
}
if _, exists := seenNames[canonical]; !exists {
seenNames[canonical] = raw
}
names = append(names, canonical)
}
if err := scanner.Err(); err != nil {
return err
} }
fmt.Printf("Extracted %d names from items.go\n", len(names)) fmt.Printf("Extracted %d names from items.go\n", len(names))
// Write name.go // Write name.go
out, err := os.Create("pkg/data/item/name.go") var b bytes.Buffer
if err != nil { b.WriteString(`package item
panic(err)
}
defer out.Close()
w := bufio.NewWriter(out)
w.WriteString(`package item
import "strings" import "strings"
const (
ExpCharItemIDThreshold = 508
ExpCharItemIDOffset = 15
)
var ExpChar uint16
func SetExpChar(expChar uint16) {
ExpChar = expChar
}
const ( const (
ScrollOfTownPortal = "ScrollOfTownPortal" ScrollOfTownPortal = "ScrollOfTownPortal"
ScrollOfIdentify = "ScrollOfIdentify" ScrollOfIdentify = "ScrollOfIdentify"
@@ -67,15 +82,22 @@ const (
) )
func GetNameByEnum(itemNumber uint) Name { func GetNameByEnum(itemNumber uint) Name {
if int(itemNumber) >= len(Names) { idx := int(itemNumber)
if ExpChar >= 3 && idx >= ExpCharItemIDThreshold {
idx += ExpCharItemIDOffset
}
if idx < 0 || idx >= len(Names) {
return Name("") return Name("")
} }
return Name(Names[itemNumber]) return Name(Names[idx])
} }
func GetIDByName(itemName string) int { func GetIDByName(itemName string) int {
for i, name := range Names { for i, name := range Names {
if strings.EqualFold(name, itemName) { if strings.EqualFold(name, itemName) {
if ExpChar >= 3 && i >= ExpCharItemIDThreshold+ExpCharItemIDOffset {
return i - ExpCharItemIDOffset
}
return i return i
} }
} }
@@ -88,10 +110,42 @@ type Name string
var Names = []string{ var Names = []string{
`) `)
for _, n := range names { for _, n := range names {
fmt.Fprintf(w, "\t\"%s\",\n", n) fmt.Fprintf(&b, "\t\"%s\",\n", n)
}
b.WriteString("}\n")
formatted, err := format.Source(b.Bytes())
if err != nil {
return fmt.Errorf("formatting generated name.go: %w", err)
}
if err := os.WriteFile("pkg/data/item/name.go", formatted, 0644); err != nil {
return err
} }
w.WriteString("}\n")
w.Flush()
fmt.Println("Generated name.go successfully") fmt.Println("Generated name.go successfully")
return nil
}
func canonicalizeName(raw string) string {
raw = strings.TrimSpace(raw)
raw = strings.ReplaceAll(raw, "'", "")
var canonical strings.Builder
capitalizeNext := true
for _, r := range raw {
if unicode.IsLetter(r) || unicode.IsDigit(r) {
if capitalizeNext && unicode.IsLetter(r) {
r = unicode.ToUpper(r)
}
canonical.WriteRune(r)
capitalizeNext = false
continue
}
capitalizeNext = true
}
return canonical.String()
} }

View File

@@ -32,7 +32,7 @@ package skill
var Desc = map[SkillDesc]Description{ var Desc = map[SkillDesc]Description{
{{- range $key, $value := . }} {{- range $key, $value := . }}
{{- if and (contains (index $value "str name") "kill") (extractInt (index $value "str name")) }} {{- if index $value "str name" }}
{{- if ne (index $value "skilldesc") "townportal" }} {{- if ne (index $value "skilldesc") "townportal" }}
"{{ $value.skilldesc }}": {Page: {{ $value.SkillPage }}, Row: {{ $value.SkillRow }}, Column: {{ $value.SkillColumn }}, ListRow: {{ $value.ListRow }}, IconCel: {{ $value.IconCel }}}, "{{ $value.skilldesc }}": {Page: {{ $value.SkillPage }}, Row: {{ $value.SkillRow }}, Column: {{ $value.SkillColumn }}, ListRow: {{ $value.ListRow }}, IconCel: {{ $value.IconCel }}},
{{- end }} {{- end }}
@@ -242,7 +242,7 @@ type UniqueName string
const ( const (
None UniqueName = "" None UniqueName = ""
{{- range $key, $value := . }} {{- range $key, $value := . }}
{{- if and (ne $value.index "") (ne $value.enabled "0") (ne (index $value "lvl req") "") }} {{- if and (ne $value.index "") (ne $value.spawnable "0") (ne (index $value "lvl req") "") }}
{{- if eq $value.index "Rainbow Facet" }} {{- if eq $value.index "Rainbow Facet" }}
{{- if contains $value.prop4 "death-skill" }} {{- if contains $value.prop4 "death-skill" }}
RainbowFacet{{ replace $value.par4 " " "" }}Death UniqueName = "Rainbow Facet ({{ $value.par4 }} Death)" RainbowFacet{{ replace $value.par4 " " "" }}Death UniqueName = "Rainbow Facet ({{ $value.par4 }} Death)"
@@ -266,7 +266,7 @@ type UniqueItemInfo struct {
var UniqueItems = map[UniqueName]UniqueItemInfo{ var UniqueItems = map[UniqueName]UniqueItemInfo{
{{- range $key, $value := . }} {{- range $key, $value := . }}
{{- if and (ne $value.index "") (ne $value.enabled "0") (ne (index $value "lvl req") "") }} {{- if and (ne $value.index "") (ne $value.spawnable "0") (ne (index $value "lvl req") "") }}
{{- if eq $value.index "Rainbow Facet" }} {{- if eq $value.index "Rainbow Facet" }}
{{- if contains $value.prop4 "death-skill" }} {{- if contains $value.prop4 "death-skill" }}
RainbowFacet{{ replace $value.par4 " " "" }}Death: {Name: "Rainbow Facet", Code: "{{ $value.code }}", LevelReq: {{ index $value "lvl req" }}, Rarity: {{ $value.rarity }}, ID: {{ index $value "*ID" }}}, RainbowFacet{{ replace $value.par4 " " "" }}Death: {Name: "Rainbow Facet", Code: "{{ $value.code }}", LevelReq: {{ index $value "lvl req" }}, Rarity: {{ $value.rarity }}, ID: {{ index $value "*ID" }}},

View File

@@ -2,6 +2,17 @@ package item
import "strings" import "strings"
const (
ExpCharItemIDThreshold = 508
ExpCharItemIDOffset = 15
)
var ExpChar uint16
func SetExpChar(expChar uint16) {
ExpChar = expChar
}
const ( const (
ScrollOfTownPortal = "ScrollOfTownPortal" ScrollOfTownPortal = "ScrollOfTownPortal"
ScrollOfIdentify = "ScrollOfIdentify" ScrollOfIdentify = "ScrollOfIdentify"
@@ -11,15 +22,22 @@ const (
) )
func GetNameByEnum(itemNumber uint) Name { func GetNameByEnum(itemNumber uint) Name {
if int(itemNumber) >= len(Names) { idx := int(itemNumber)
if ExpChar >= 3 && idx >= ExpCharItemIDThreshold {
idx += ExpCharItemIDOffset
}
if idx < 0 || idx >= len(Names) {
return Name("") return Name("")
} }
return Name(Names[itemNumber]) return Name(Names[idx])
} }
func GetIDByName(itemName string) int { func GetIDByName(itemName string) int {
for i, name := range Names { for i, name := range Names {
if strings.EqualFold(name, itemName) { if strings.EqualFold(name, itemName) {
if ExpChar >= 3 && i >= ExpCharItemIDThreshold+ExpCharItemIDOffset {
return i - ExpCharItemIDOffset
}
return i return i
} }
} }
@@ -63,7 +81,7 @@ var Names = []string{
"BroadSword", "BroadSword",
"LongSword", "LongSword",
"WarSword", "WarSword",
"Two-HandedSword", "TwoHandedSword",
"Claymore", "Claymore",
"GiantSword", "GiantSword",
"BastardSword", "BastardSword",
@@ -184,7 +202,7 @@ var Names = []string{
"Bill", "Bill",
"BattleScythe", "BattleScythe",
"Partizan", "Partizan",
"Bec-de-Corbin", "BecDeCorbin",
"GrimScythe", "GrimScythe",
"JoStaff", "JoStaff",
"Quarterstaff", "Quarterstaff",
@@ -202,7 +220,7 @@ var Names = []string{
"Arbalest", "Arbalest",
"SiegeCrossbow", "SiegeCrossbow",
"Ballista", "Ballista",
"Chu-Ko-Nu", "ChuKoNu",
"KhalimsFlail", "KhalimsFlail",
"KhalimsWill", "KhalimsWill",
"Katar", "Katar",
@@ -232,7 +250,7 @@ var Names = []string{
"WarSpike", "WarSpike",
"BerserkerAxe", "BerserkerAxe",
"FeralAxe", "FeralAxe",
"Silver-edgedAxe", "SilverEdgedAxe",
"Decapitator", "Decapitator",
"ChampionAxe", "ChampionAxe",
"GloriousAxe", "GloriousAxe",

View File

@@ -35,7 +35,6 @@ const (
BloodCrescent UniqueName = "Blood Crescent" BloodCrescent UniqueName = "Blood Crescent"
KrintizsSkewer UniqueName = "Krintizs Skewer" KrintizsSkewer UniqueName = "Krintizs Skewer"
Gleamscythe UniqueName = "Gleamscythe" Gleamscythe UniqueName = "Gleamscythe"
AzurewrathCrystalSword UniqueName = "Azurewrath"
GriswoldsEdge UniqueName = "Griswolds Edge" GriswoldsEdge UniqueName = "Griswolds Edge"
Hellplague UniqueName = "Hellplague" Hellplague UniqueName = "Hellplague"
CulwensPoint UniqueName = "Culwens Point" CulwensPoint UniqueName = "Culwens Point"
@@ -267,7 +266,6 @@ const (
Doombringer UniqueName = "Doombringer" Doombringer UniqueName = "Doombringer"
TheGrandfather UniqueName = "The Grandfather" TheGrandfather UniqueName = "The Grandfather"
Wizardspike UniqueName = "Wizardspike" Wizardspike UniqueName = "Wizardspike"
ConstrictingRing UniqueName = "Constricting Ring"
Stormspire UniqueName = "Stormspire" Stormspire UniqueName = "Stormspire"
Eaglehorn UniqueName = "Eaglehorn" Eaglehorn UniqueName = "Eaglehorn"
Windforce UniqueName = "Windforce" Windforce UniqueName = "Windforce"
@@ -440,36 +438,35 @@ type UniqueItemInfo struct {
} }
var UniqueItems = map[UniqueName]UniqueItemInfo{ var UniqueItems = map[UniqueName]UniqueItemInfo{
TheGnasher: {Name: "The Gnasher", Code: "hax", LevelReq: 5, Rarity: 1, ID: 0}, TheGnasher: {Name: "The Gnasher", Code: "hax", LevelReq: 5, Rarity: 1, ID: 0},
Deathspade: {Name: "Deathspade", Code: "axe", LevelReq: 9, Rarity: 1, ID: 1}, Deathspade: {Name: "Deathspade", Code: "axe", LevelReq: 9, Rarity: 1, ID: 1},
Bladebone: {Name: "Bladebone", Code: "2ax", LevelReq: 15, Rarity: 1, ID: 2}, Bladebone: {Name: "Bladebone", Code: "2ax", LevelReq: 15, Rarity: 1, ID: 2},
Mindrend: {Name: "Mindrend", Code: "mpi", LevelReq: 21, Rarity: 1, ID: 3}, Mindrend: {Name: "Mindrend", Code: "mpi", LevelReq: 21, Rarity: 1, ID: 3},
Rakescar: {Name: "Rakescar", Code: "wax", LevelReq: 27, Rarity: 1, ID: 4}, Rakescar: {Name: "Rakescar", Code: "wax", LevelReq: 27, Rarity: 1, ID: 4},
FechmarsAxe: {Name: "Fechmars Axe", Code: "lax", LevelReq: 8, Rarity: 1, ID: 5}, FechmarsAxe: {Name: "Fechmars Axe", Code: "lax", LevelReq: 8, Rarity: 1, ID: 5},
Goreshovel: {Name: "Goreshovel", Code: "bax", LevelReq: 14, Rarity: 1, ID: 6}, Goreshovel: {Name: "Goreshovel", Code: "bax", LevelReq: 14, Rarity: 1, ID: 6},
TheChieftan: {Name: "The Chieftan", Code: "btx", LevelReq: 19, Rarity: 1, ID: 7}, TheChieftan: {Name: "The Chieftan", Code: "btx", LevelReq: 19, Rarity: 1, ID: 7},
Brainhew: {Name: "Brainhew", Code: "gax", LevelReq: 25, Rarity: 1, ID: 8}, Brainhew: {Name: "Brainhew", Code: "gax", LevelReq: 25, Rarity: 1, ID: 8},
TheHumongous: {Name: "The Humongous", Code: "gix", LevelReq: 29, Rarity: 1, ID: 9}, TheHumongous: {Name: "The Humongous", Code: "gix", LevelReq: 29, Rarity: 1, ID: 9},
IrosTorch: {Name: "Iros Torch", Code: "wnd", LevelReq: 5, Rarity: 1, ID: 10}, IrosTorch: {Name: "Iros Torch", Code: "wnd", LevelReq: 5, Rarity: 1, ID: 10},
Maelstromwrath: {Name: "Maelstromwrath", Code: "ywn", LevelReq: 14, Rarity: 1, ID: 11}, Maelstromwrath: {Name: "Maelstromwrath", Code: "ywn", LevelReq: 14, Rarity: 1, ID: 11},
Gravenspine: {Name: "Gravenspine", Code: "bwn", LevelReq: 20, Rarity: 1, ID: 12}, Gravenspine: {Name: "Gravenspine", Code: "bwn", LevelReq: 20, Rarity: 1, ID: 12},
UmesLament: {Name: "Umes Lament", Code: "gwn", LevelReq: 28, Rarity: 1, ID: 13}, UmesLament: {Name: "Umes Lament", Code: "gwn", LevelReq: 28, Rarity: 1, ID: 13},
Felloak: {Name: "Felloak", Code: "clb", LevelReq: 3, Rarity: 1, ID: 14}, Felloak: {Name: "Felloak", Code: "clb", LevelReq: 3, Rarity: 1, ID: 14},
KnellStriker: {Name: "Knell Striker", Code: "scp", LevelReq: 5, Rarity: 1, ID: 15}, KnellStriker: {Name: "Knell Striker", Code: "scp", LevelReq: 5, Rarity: 1, ID: 15},
Rusthandle: {Name: "Rusthandle", Code: "gsc", LevelReq: 17, Rarity: 1, ID: 16}, Rusthandle: {Name: "Rusthandle", Code: "gsc", LevelReq: 17, Rarity: 1, ID: 16},
Stormeye: {Name: "Stormeye", Code: "wsp", LevelReq: 23, Rarity: 1, ID: 17}, Stormeye: {Name: "Stormeye", Code: "wsp", LevelReq: 23, Rarity: 1, ID: 17},
Stoutnail: {Name: "Stoutnail", Code: "spc", LevelReq: 5, Rarity: 1, ID: 18}, Stoutnail: {Name: "Stoutnail", Code: "spc", LevelReq: 5, Rarity: 1, ID: 18},
Crushflange: {Name: "Crushflange", Code: "mac", LevelReq: 9, Rarity: 1, ID: 19}, Crushflange: {Name: "Crushflange", Code: "mac", LevelReq: 9, Rarity: 1, ID: 19},
Bloodrise: {Name: "Bloodrise", Code: "mst", LevelReq: 15, Rarity: 1, ID: 20}, Bloodrise: {Name: "Bloodrise", Code: "mst", LevelReq: 15, Rarity: 1, ID: 20},
TheGeneralsTanDoLiGa: {Name: "The Generals Tan Do Li Ga", Code: "fla", LevelReq: 21, Rarity: 1, ID: 21}, TheGeneralsTanDoLiGa: {Name: "The Generals Tan Do Li Ga", Code: "fla", LevelReq: 21, Rarity: 1, ID: 21},
Ironstone: {Name: "Ironstone", Code: "whm", LevelReq: 27, Rarity: 1, ID: 22}, Ironstone: {Name: "Ironstone", Code: "whm", LevelReq: 27, Rarity: 1, ID: 22},
Bonesob: {Name: "Bonesob", Code: "mau", LevelReq: 24, Rarity: 1, ID: 23}, Bonesob: {Name: "Bonesob", Code: "mau", LevelReq: 24, Rarity: 1, ID: 23},
Steeldriver: {Name: "Steeldriver", Code: "gma", LevelReq: 29, Rarity: 1, ID: 24}, Steeldriver: {Name: "Steeldriver", Code: "gma", LevelReq: 29, Rarity: 1, ID: 24},
RixotsKeen: {Name: "Rixots Keen", Code: "ssd", LevelReq: 2, Rarity: 1, ID: 25}, RixotsKeen: {Name: "Rixots Keen", Code: "ssd", LevelReq: 2, Rarity: 1, ID: 25},
BloodCrescent: {Name: "Blood Crescent", Code: "scm", LevelReq: 7, Rarity: 1, ID: 26}, BloodCrescent: {Name: "Blood Crescent", Code: "scm", LevelReq: 7, Rarity: 1, ID: 26},
KrintizsSkewer: {Name: "Krintizs Skewer", Code: "sbr", LevelReq: 10, Rarity: 1, ID: 27}, KrintizsSkewer: {Name: "Krintizs Skewer", Code: "sbr", LevelReq: 10, Rarity: 1, ID: 27},
Gleamscythe: {Name: "Gleamscythe", Code: "flc", LevelReq: 13, Rarity: 1, ID: 28}, Gleamscythe: {Name: "Gleamscythe", Code: "flc", LevelReq: 13, Rarity: 1, ID: 28},
// AzurewrathCrystalSword (ID: 29, Code: "crs") omitted: duplicate name with Phase Blade Azurewrath (ID: 301)
GriswoldsEdge: {Name: "Griswolds Edge", Code: "bsd", LevelReq: 17, Rarity: 1, ID: 30}, GriswoldsEdge: {Name: "Griswolds Edge", Code: "bsd", LevelReq: 17, Rarity: 1, ID: 30},
Hellplague: {Name: "Hellplague", Code: "lsd", LevelReq: 22, Rarity: 1, ID: 31}, Hellplague: {Name: "Hellplague", Code: "lsd", LevelReq: 22, Rarity: 1, ID: 31},
CulwensPoint: {Name: "Culwens Point", Code: "wsd", LevelReq: 29, Rarity: 1, ID: 32}, CulwensPoint: {Name: "Culwens Point", Code: "wsd", LevelReq: 29, Rarity: 1, ID: 32},
@@ -701,7 +698,6 @@ var UniqueItems = map[UniqueName]UniqueItemInfo{
Doombringer: {Name: "Doombringer", Code: "7b7", LevelReq: 69, Rarity: 1, ID: 260}, Doombringer: {Name: "Doombringer", Code: "7b7", LevelReq: 69, Rarity: 1, ID: 260},
TheGrandfather: {Name: "The Grandfather", Code: "7gd", LevelReq: 81, Rarity: 1, ID: 261}, TheGrandfather: {Name: "The Grandfather", Code: "7gd", LevelReq: 81, Rarity: 1, ID: 261},
Wizardspike: {Name: "Wizardspike", Code: "7dg", LevelReq: 61, Rarity: 1, ID: 262}, Wizardspike: {Name: "Wizardspike", Code: "7dg", LevelReq: 61, Rarity: 1, ID: 262},
ConstrictingRing: {Name: "Constricting Ring", Code: "rin", LevelReq: 95, Rarity: 1, ID: 263},
Stormspire: {Name: "Stormspire", Code: "7wc", LevelReq: 70, Rarity: 1, ID: 264}, Stormspire: {Name: "Stormspire", Code: "7wc", LevelReq: 70, Rarity: 1, ID: 264},
Eaglehorn: {Name: "Eaglehorn", Code: "6l7", LevelReq: 69, Rarity: 1, ID: 265}, Eaglehorn: {Name: "Eaglehorn", Code: "6l7", LevelReq: 69, Rarity: 1, ID: 265},
Windforce: {Name: "Windforce", Code: "6lw", LevelReq: 73, Rarity: 1, ID: 266}, Windforce: {Name: "Windforce", Code: "6lw", LevelReq: 73, Rarity: 1, ID: 266},

View File

@@ -120,7 +120,11 @@ type Drop struct {
} }
func (i Item) Desc() item.Description { func (i Item) Desc() item.Description {
return item.Desc[i.ID] id := i.ID
if item.ExpChar >= 3 && id >= item.ExpCharItemIDThreshold {
id += item.ExpCharItemIDOffset
}
return item.Desc[id]
} }
func (i Item) Type() item.Type { func (i Item) Type() item.Type {

View File

@@ -3,7 +3,9 @@
package skill package skill
var Desc = map[SkillDesc]Description{ var Desc = map[SkillDesc]Description{
"abyss": {Page: 3, Row: 6, Column: 3, ListRow: 3, IconCel: 58},
"amplify damage": {Page: 1, Row: 1, Column: 2, ListRow: 1, IconCel: 0}, "amplify damage": {Page: 1, Row: 1, Column: 2, ListRow: 1, IconCel: 0},
"apocalypse": {Page: 3, Row: 6, Column: 1, ListRow: 3, IconCel: 56},
"arctic blast": {Page: 3, Row: 2, Column: 3, ListRow: 3, IconCel: 36}, "arctic blast": {Page: 3, Row: 2, Column: 3, ListRow: 3, IconCel: 36},
"armageddon": {Page: 3, Row: 6, Column: 1, ListRow: 3, IconCel: 50}, "armageddon": {Page: 3, Row: 6, Column: 1, ListRow: 3, IconCel: 50},
"attack": {Page: 0, Row: 0, Column: 0, ListRow: 0, IconCel: 2}, "attack": {Page: 0, Row: 0, Column: 0, ListRow: 0, IconCel: 2},
@@ -15,15 +17,19 @@ var Desc = map[SkillDesc]Description{
"battle cry": {Page: 3, Row: 4, Column: 1, ListRow: 3, IconCel: 40}, "battle cry": {Page: 3, Row: 4, Column: 1, ListRow: 3, IconCel: 40},
"battle orders": {Page: 3, Row: 5, Column: 2, ListRow: 3, IconCel: 46}, "battle orders": {Page: 3, Row: 5, Column: 2, ListRow: 3, IconCel: 46},
"berserk": {Page: 1, Row: 6, Column: 2, ListRow: 1, IconCel: 52}, "berserk": {Page: 1, Row: 6, Column: 2, ListRow: 1, IconCel: 52},
"bind demon": {Page: 1, Row: 6, Column: 3, ListRow: 1, IconCel: 18},
"blade fury": {Page: 1, Row: 4, Column: 3, ListRow: 1, IconCel: 10}, "blade fury": {Page: 1, Row: 4, Column: 3, ListRow: 1, IconCel: 10},
"blade mastery": {Page: 2, Row: 1, Column: 1, ListRow: 2, IconCel: 2}, "blade mastery": {Page: 2, Row: 1, Column: 1, ListRow: 2, IconCel: 2},
"blade sentinel": {Page: 1, Row: 2, Column: 3, ListRow: 1, IconCel: 4}, "blade sentinel": {Page: 1, Row: 2, Column: 3, ListRow: 1, IconCel: 4},
"blade shield": {Page: 1, Row: 6, Column: 3, ListRow: 1, IconCel: 18}, "blade shield": {Page: 1, Row: 6, Column: 3, ListRow: 1, IconCel: 18},
"blade warp": {Page: 2, Row: 4, Column: 1, ListRow: 2, IconCel: 34},
"blades of ice": {Page: 3, Row: 5, Column: 1, ListRow: 3, IconCel: 52}, "blades of ice": {Page: 3, Row: 5, Column: 1, ListRow: 3, IconCel: 52},
"blaze": {Page: 1, Row: 3, Column: 1, ListRow: 1, IconCel: 20}, "blaze": {Page: 1, Row: 3, Column: 1, ListRow: 1, IconCel: 20},
"blessed aim": {Page: 2, Row: 3, Column: 1, ListRow: 2, IconCel: 24}, "blessed aim": {Page: 2, Row: 3, Column: 1, ListRow: 2, IconCel: 24},
"blessed hammer": {Page: 1, Row: 4, Column: 2, ListRow: 1, IconCel: 32}, "blessed hammer": {Page: 1, Row: 4, Column: 2, ListRow: 1, IconCel: 32},
"blizzard": {Page: 3, Row: 5, Column: 1, ListRow: 3, IconCel: 46}, "blizzard": {Page: 3, Row: 5, Column: 1, ListRow: 3, IconCel: 46},
"blood boil": {Page: 1, Row: 4, Column: 2, ListRow: 1, IconCel: 14},
"blood oath": {Page: 1, Row: 2, Column: 1, ListRow: 1, IconCel: 4},
"bloodgolem": {Page: 3, Row: 4, Column: 2, ListRow: 3, IconCel: 38}, "bloodgolem": {Page: 3, Row: 4, Column: 2, ListRow: 3, IconCel: 38},
"bone armor": {Page: 2, Row: 1, Column: 3, ListRow: 2, IconCel: 4}, "bone armor": {Page: 2, Row: 1, Column: 3, ListRow: 2, IconCel: 4},
"bone prison": {Page: 2, Row: 5, Column: 3, ListRow: 2, IconCel: 44}, "bone prison": {Page: 2, Row: 5, Column: 3, ListRow: 2, IconCel: 44},
@@ -42,6 +48,7 @@ var Desc = map[SkillDesc]Description{
"claws of thunder": {Page: 3, Row: 4, Column: 1, ListRow: 3, IconCel: 58}, "claws of thunder": {Page: 3, Row: 4, Column: 1, ListRow: 3, IconCel: 58},
"clay golem": {Page: 3, Row: 2, Column: 2, ListRow: 3, IconCel: 18}, "clay golem": {Page: 3, Row: 2, Column: 2, ListRow: 3, IconCel: 18},
"cleansing": {Page: 3, Row: 3, Column: 1, ListRow: 3, IconCel: 38}, "cleansing": {Page: 3, Row: 3, Column: 1, ListRow: 3, IconCel: 38},
"cleave": {Page: 2, Row: 2, Column: 2, ListRow: 2, IconCel: 36},
"cloak of shadows": {Page: 2, Row: 3, Column: 3, ListRow: 2, IconCel: 24}, "cloak of shadows": {Page: 2, Row: 3, Column: 3, ListRow: 2, IconCel: 24},
"cobra strike": {Page: 3, Row: 3, Column: 2, ListRow: 3, IconCel: 50}, "cobra strike": {Page: 3, Row: 3, Column: 2, ListRow: 3, IconCel: 50},
"cold arrow": {Page: 1, Row: 2, Column: 1, ListRow: 1, IconCel: 10}, "cold arrow": {Page: 1, Row: 2, Column: 1, ListRow: 1, IconCel: 10},
@@ -49,15 +56,20 @@ var Desc = map[SkillDesc]Description{
"concentrate": {Page: 1, Row: 4, Column: 2, ListRow: 1, IconCel: 36}, "concentrate": {Page: 1, Row: 4, Column: 2, ListRow: 1, IconCel: 36},
"concentration": {Page: 2, Row: 4, Column: 1, ListRow: 2, IconCel: 34}, "concentration": {Page: 2, Row: 4, Column: 1, ListRow: 2, IconCel: 34},
"confuse": {Page: 1, Row: 4, Column: 1, ListRow: 1, IconCel: 30}, "confuse": {Page: 1, Row: 4, Column: 1, ListRow: 1, IconCel: 30},
"consume": {Page: 1, Row: 6, Column: 1, ListRow: 1, IconCel: 16},
"conversion": {Page: 1, Row: 5, Column: 1, ListRow: 1, IconCel: 30}, "conversion": {Page: 1, Row: 5, Column: 1, ListRow: 1, IconCel: 30},
"conviction": {Page: 2, Row: 6, Column: 3, ListRow: 2, IconCel: 56}, "conviction": {Page: 2, Row: 6, Column: 3, ListRow: 2, IconCel: 56},
"corpse explosion": {Page: 2, Row: 2, Column: 2, ListRow: 2, IconCel: 16}, "corpse explosion": {Page: 2, Row: 2, Column: 2, ListRow: 2, IconCel: 16},
"critical strike": {Page: 2, Row: 1, Column: 3, ListRow: 2, IconCel: 6}, "critical strike": {Page: 2, Row: 1, Column: 3, ListRow: 2, IconCel: 6},
"cubeloot": {Page: 0, Row: 0, Column: 0, ListRow: 0, IconCel: 2},
"cycle of life": {Page: 1, Row: 3, Column: 3, ListRow: 1, IconCel: 8}, "cycle of life": {Page: 1, Row: 3, Column: 3, ListRow: 1, IconCel: 8},
"cyclone armor": {Page: 3, Row: 3, Column: 3, ListRow: 3, IconCel: 40}, "cyclone armor": {Page: 3, Row: 3, Column: 3, ListRow: 3, IconCel: 40},
"death mark": {Page: 1, Row: 2, Column: 2, ListRow: 1, IconCel: 6},
"death sentry": {Page: 1, Row: 6, Column: 1, ListRow: 1, IconCel: 16}, "death sentry": {Page: 1, Row: 6, Column: 1, ListRow: 1, IconCel: 16},
"decrepify": {Page: 1, Row: 5, Column: 3, ListRow: 1, IconCel: 42}, "decrepify": {Page: 1, Row: 5, Column: 3, ListRow: 1, IconCel: 42},
"defiance": {Page: 3, Row: 2, Column: 2, ListRow: 3, IconCel: 16}, "defiance": {Page: 3, Row: 2, Column: 2, ListRow: 3, IconCel: 16},
"delerium change": {Page: 0, Row: 0, Column: 0, ListRow: 0, IconCel: 2},
"demonic mastery": {Page: 1, Row: 1, Column: 1, ListRow: 1, IconCel: 0},
"dim vision": {Page: 1, Row: 2, Column: 1, ListRow: 1, IconCel: 10}, "dim vision": {Page: 1, Row: 2, Column: 1, ListRow: 1, IconCel: 10},
"dodge": {Page: 2, Row: 2, Column: 2, ListRow: 2, IconCel: 14}, "dodge": {Page: 2, Row: 2, Column: 2, ListRow: 2, IconCel: 14},
"dopplezon": {Page: 2, Row: 5, Column: 1, ListRow: 2, IconCel: 44}, "dopplezon": {Page: 2, Row: 5, Column: 1, ListRow: 2, IconCel: 44},
@@ -67,8 +79,13 @@ var Desc = map[SkillDesc]Description{
"dragon flight": {Page: 3, Row: 5, Column: 3, ListRow: 3, IconCel: 54}, "dragon flight": {Page: 3, Row: 5, Column: 3, ListRow: 3, IconCel: 54},
"dragon tail": {Page: 3, Row: 4, Column: 3, ListRow: 3, IconCel: 48}, "dragon tail": {Page: 3, Row: 4, Column: 3, ListRow: 3, IconCel: 48},
"dragon talon": {Page: 3, Row: 1, Column: 3, ListRow: 3, IconCel: 42}, "dragon talon": {Page: 3, Row: 1, Column: 3, ListRow: 3, IconCel: 42},
"echoing strike": {Page: 2, Row: 3, Column: 1, ListRow: 2, IconCel: 30},
"eldritchblast": {Page: 2, Row: 5, Column: 2, ListRow: 2, IconCel: 28},
"emotewheel": {Page: 0, Row: 0, Column: 0, ListRow: 0, IconCel: 2},
"enchant": {Page: 1, Row: 4, Column: 3, ListRow: 1, IconCel: 32}, "enchant": {Page: 1, Row: 4, Column: 3, ListRow: 1, IconCel: 32},
"energy shield": {Page: 2, Row: 5, Column: 3, ListRow: 2, IconCel: 44}, "energy shield": {Page: 2, Row: 5, Column: 3, ListRow: 2, IconCel: 44},
"engorge": {Page: 1, Row: 5, Column: 2, ListRow: 1, IconCel: 12},
"enhanced entropy": {Page: 3, Row: 5, Column: 3, ListRow: 3, IconCel: 54},
"eruption": {Page: 3, Row: 3, Column: 1, ListRow: 3, IconCel: 38}, "eruption": {Page: 3, Row: 3, Column: 1, ListRow: 3, IconCel: 38},
"evade": {Page: 2, Row: 5, Column: 2, ListRow: 2, IconCel: 46}, "evade": {Page: 2, Row: 5, Column: 2, ListRow: 2, IconCel: 46},
"exploding arrow": {Page: 1, Row: 3, Column: 3, ListRow: 1, IconCel: 20}, "exploding arrow": {Page: 1, Row: 3, Column: 3, ListRow: 1, IconCel: 20},
@@ -89,6 +106,7 @@ var Desc = map[SkillDesc]Description{
"firestorm": {Page: 3, Row: 1, Column: 1, ListRow: 3, IconCel: 32}, "firestorm": {Page: 3, Row: 1, Column: 1, ListRow: 3, IconCel: 32},
"fist of the heavens": {Page: 1, Row: 6, Column: 2, ListRow: 1, IconCel: 50}, "fist of the heavens": {Page: 1, Row: 6, Column: 2, ListRow: 1, IconCel: 50},
"fists of fire": {Page: 3, Row: 2, Column: 1, ListRow: 3, IconCel: 44}, "fists of fire": {Page: 3, Row: 2, Column: 1, ListRow: 3, IconCel: 44},
"flame wave": {Page: 3, Row: 4, Column: 1, ListRow: 3, IconCel: 50},
"freezing arrow": {Page: 1, Row: 6, Column: 1, ListRow: 1, IconCel: 50}, "freezing arrow": {Page: 1, Row: 6, Column: 1, ListRow: 1, IconCel: 50},
"frenzy": {Page: 1, Row: 5, Column: 3, ListRow: 1, IconCel: 42}, "frenzy": {Page: 1, Row: 5, Column: 3, ListRow: 1, IconCel: 42},
"frost nova": {Page: 3, Row: 2, Column: 1, ListRow: 3, IconCel: 16}, "frost nova": {Page: 3, Row: 2, Column: 1, ListRow: 3, IconCel: 16},
@@ -100,6 +118,9 @@ var Desc = map[SkillDesc]Description{
"grim ward": {Page: 3, Row: 5, Column: 3, ListRow: 3, IconCel: 48}, "grim ward": {Page: 3, Row: 5, Column: 3, ListRow: 3, IconCel: 48},
"guided arrow": {Page: 1, Row: 4, Column: 2, ListRow: 1, IconCel: 32}, "guided arrow": {Page: 1, Row: 4, Column: 2, ListRow: 1, IconCel: 32},
"heart of wolverine": {Page: 1, Row: 4, Column: 1, ListRow: 1, IconCel: 10}, "heart of wolverine": {Page: 1, Row: 4, Column: 1, ListRow: 1, IconCel: 10},
"hex bane": {Page: 2, Row: 1, Column: 3, ListRow: 2, IconCel: 24},
"hex purge": {Page: 2, Row: 3, Column: 3, ListRow: 2, IconCel: 32},
"hex siphon": {Page: 2, Row: 5, Column: 3, ListRow: 2, IconCel: 26},
"holy bolt": {Page: 1, Row: 2, Column: 2, ListRow: 1, IconCel: 10}, "holy bolt": {Page: 1, Row: 2, Column: 2, ListRow: 1, IconCel: 10},
"holy fire": {Page: 2, Row: 2, Column: 2, ListRow: 2, IconCel: 12}, "holy fire": {Page: 2, Row: 2, Column: 2, ListRow: 2, IconCel: 12},
"holy freeze": {Page: 2, Row: 4, Column: 2, ListRow: 2, IconCel: 36}, "holy freeze": {Page: 2, Row: 4, Column: 2, ListRow: 2, IconCel: 36},
@@ -119,6 +140,7 @@ var Desc = map[SkillDesc]Description{
"inferno": {Page: 1, Row: 2, Column: 1, ListRow: 1, IconCel: 10}, "inferno": {Page: 1, Row: 2, Column: 1, ListRow: 1, IconCel: 10},
"inferno sentry": {Page: 1, Row: 5, Column: 2, ListRow: 1, IconCel: 14}, "inferno sentry": {Page: 1, Row: 5, Column: 2, ListRow: 1, IconCel: 14},
"inner sight": {Page: 2, Row: 1, Column: 1, ListRow: 2, IconCel: 4}, "inner sight": {Page: 2, Row: 1, Column: 1, ListRow: 2, IconCel: 4},
"interact": {Page: 0, Row: 0, Column: 0, ListRow: 0, IconCel: 2},
"iron maiden": {Page: 1, Row: 3, Column: 2, ListRow: 1, IconCel: 20}, "iron maiden": {Page: 1, Row: 3, Column: 2, ListRow: 1, IconCel: 20},
"iron skin": {Page: 2, Row: 4, Column: 3, ListRow: 2, IconCel: 38}, "iron skin": {Page: 2, Row: 4, Column: 3, ListRow: 2, IconCel: 38},
"irongolem": {Page: 3, Row: 5, Column: 2, ListRow: 3, IconCel: 48}, "irongolem": {Page: 3, Row: 5, Column: 2, ListRow: 3, IconCel: 48},
@@ -128,6 +150,7 @@ var Desc = map[SkillDesc]Description{
"leap attack": {Page: 1, Row: 4, Column: 1, ListRow: 1, IconCel: 34}, "leap attack": {Page: 1, Row: 4, Column: 1, ListRow: 1, IconCel: 34},
"left hand swing": {Page: 0, Row: 0, Column: 0, ListRow: -1, IconCel: 10}, "left hand swing": {Page: 0, Row: 0, Column: 0, ListRow: -1, IconCel: 10},
"left hand throw": {Page: 0, Row: 0, Column: 0, ListRow: 0, IconCel: 12}, "left hand throw": {Page: 0, Row: 0, Column: 0, ListRow: 0, IconCel: 12},
"levitate": {Page: 2, Row: 1, Column: 1, ListRow: 2, IconCel: 20},
"life tap": {Page: 1, Row: 4, Column: 2, ListRow: 1, IconCel: 32}, "life tap": {Page: 1, Row: 4, Column: 2, ListRow: 1, IconCel: 32},
"lightning": {Page: 2, Row: 3, Column: 2, ListRow: 2, IconCel: 26}, "lightning": {Page: 2, Row: 3, Column: 2, ListRow: 2, IconCel: 26},
"lightning bolt": {Page: 3, Row: 3, Column: 3, ListRow: 3, IconCel: 28}, "lightning bolt": {Page: 3, Row: 3, Column: 3, ListRow: 3, IconCel: 28},
@@ -135,14 +158,21 @@ var Desc = map[SkillDesc]Description{
"lightning mastery": {Page: 2, Row: 6, Column: 2, ListRow: 2, IconCel: 54}, "lightning mastery": {Page: 2, Row: 6, Column: 2, ListRow: 2, IconCel: 54},
"lightning sentry": {Page: 1, Row: 5, Column: 1, ListRow: 1, IconCel: 12}, "lightning sentry": {Page: 1, Row: 5, Column: 1, ListRow: 1, IconCel: 12},
"lightning strike": {Page: 3, Row: 6, Column: 2, ListRow: 3, IconCel: 56}, "lightning strike": {Page: 3, Row: 6, Column: 2, ListRow: 3, IconCel: 56},
"loot": {Page: 0, Row: 0, Column: 0, ListRow: 0, IconCel: 2},
"lower resist": {Page: 1, Row: 6, Column: 2, ListRow: 1, IconCel: 50}, "lower resist": {Page: 1, Row: 6, Column: 2, ListRow: 1, IconCel: 50},
"mace mastery": {Page: 2, Row: 1, Column: 3, ListRow: 2, IconCel: 6}, "mace mastery": {Page: 2, Row: 1, Column: 3, ListRow: 2, IconCel: 6},
"magic arrow": {Page: 1, Row: 1, Column: 2, ListRow: 1, IconCel: 0}, "magic arrow": {Page: 1, Row: 1, Column: 2, ListRow: 1, IconCel: 0},
"map": {Page: 0, Row: 0, Column: 0, ListRow: 0, IconCel: 2},
"mark of the bear": {Page: 0, Row: 0, Column: 0, ListRow: 0, IconCel: 2},
"mark of the wolf": {Page: 0, Row: 0, Column: 0, ListRow: 0, IconCel: 2},
"maul": {Page: 2, Row: 3, Column: 3, ListRow: 2, IconCel: 56}, "maul": {Page: 2, Row: 3, Column: 3, ListRow: 2, IconCel: 56},
"meditation": {Page: 3, Row: 5, Column: 1, ListRow: 3, IconCel: 48}, "meditation": {Page: 3, Row: 5, Column: 1, ListRow: 3, IconCel: 48},
"meteor": {Page: 1, Row: 5, Column: 2, ListRow: 1, IconCel: 40}, "meteor": {Page: 1, Row: 5, Column: 2, ListRow: 1, IconCel: 40},
"miasma bolt": {Page: 3, Row: 1, Column: 3, ListRow: 3, IconCel: 46},
"miasma chains": {Page: 3, Row: 3, Column: 3, ListRow: 3, IconCel: 52},
"might": {Page: 2, Row: 1, Column: 1, ListRow: 2, IconCel: 4}, "might": {Page: 2, Row: 1, Column: 1, ListRow: 2, IconCel: 4},
"mind blast": {Page: 2, Row: 5, Column: 3, ListRow: 2, IconCel: 34}, "mind blast": {Page: 2, Row: 5, Column: 3, ListRow: 2, IconCel: 34},
"mirrored blades": {Page: 2, Row: 6, Column: 2, ListRow: 2, IconCel: 38},
"molten boulder": {Page: 3, Row: 2, Column: 1, ListRow: 3, IconCel: 34}, "molten boulder": {Page: 3, Row: 2, Column: 1, ListRow: 3, IconCel: 34},
"multiple shot": {Page: 1, Row: 2, Column: 2, ListRow: 1, IconCel: 12}, "multiple shot": {Page: 1, Row: 2, Column: 2, ListRow: 1, IconCel: 12},
"natural resistance": {Page: 2, Row: 6, Column: 3, ListRow: 2, IconCel: 54}, "natural resistance": {Page: 2, Row: 6, Column: 3, ListRow: 2, IconCel: 54},
@@ -161,6 +191,7 @@ var Desc = map[SkillDesc]Description{
"power strike": {Page: 3, Row: 2, Column: 2, ListRow: 3, IconCel: 16}, "power strike": {Page: 3, Row: 2, Column: 2, ListRow: 3, IconCel: 16},
"prayer": {Page: 3, Row: 1, Column: 1, ListRow: 3, IconCel: 6}, "prayer": {Page: 3, Row: 1, Column: 1, ListRow: 3, IconCel: 6},
"psychic hammer": {Page: 2, Row: 1, Column: 3, ListRow: 2, IconCel: 22}, "psychic hammer": {Page: 2, Row: 1, Column: 3, ListRow: 2, IconCel: 22},
"psychic ward": {Page: 2, Row: 4, Column: 2, ListRow: 2, IconCel: 22},
"quickness": {Page: 2, Row: 2, Column: 1, ListRow: 2, IconCel: 36}, "quickness": {Page: 2, Row: 2, Column: 1, ListRow: 2, IconCel: 36},
"rabies": {Page: 2, Row: 4, Column: 1, ListRow: 2, IconCel: 24}, "rabies": {Page: 2, Row: 4, Column: 1, ListRow: 2, IconCel: 24},
"raise skeletal mage": {Page: 3, Row: 3, Column: 3, ListRow: 3, IconCel: 28}, "raise skeletal mage": {Page: 3, Row: 3, Column: 3, ListRow: 3, IconCel: 28},
@@ -171,7 +202,9 @@ var Desc = map[SkillDesc]Description{
"resist fire": {Page: 3, Row: 1, Column: 3, ListRow: 3, IconCel: 8}, "resist fire": {Page: 3, Row: 1, Column: 3, ListRow: 3, IconCel: 8},
"resist lightning": {Page: 3, Row: 3, Column: 3, ListRow: 3, IconCel: 28}, "resist lightning": {Page: 3, Row: 3, Column: 3, ListRow: 3, IconCel: 28},
"revive": {Page: 3, Row: 6, Column: 3, ListRow: 3, IconCel: 58}, "revive": {Page: 3, Row: 6, Column: 3, ListRow: 3, IconCel: 58},
"ring of fire": {Page: 3, Row: 2, Column: 1, ListRow: 3, IconCel: 42},
"royal strike": {Page: 3, Row: 6, Column: 2, ListRow: 3, IconCel: 56}, "royal strike": {Page: 3, Row: 6, Column: 2, ListRow: 3, IconCel: 56},
"runtoggle": {Page: 0, Row: 0, Column: 0, ListRow: 0, IconCel: 2},
"sacrifice": {Page: 1, Row: 1, Column: 1, ListRow: 1, IconCel: 0}, "sacrifice": {Page: 1, Row: 1, Column: 1, ListRow: 1, IconCel: 0},
"salvation": {Page: 3, Row: 6, Column: 3, ListRow: 3, IconCel: 58}, "salvation": {Page: 3, Row: 6, Column: 3, ListRow: 3, IconCel: 58},
"sanctuary": {Page: 2, Row: 5, Column: 3, ListRow: 2, IconCel: 46}, "sanctuary": {Page: 2, Row: 5, Column: 3, ListRow: 2, IconCel: 46},
@@ -184,6 +217,10 @@ var Desc = map[SkillDesc]Description{
"shock field": {Page: 1, Row: 2, Column: 1, ListRow: 1, IconCel: 2}, "shock field": {Page: 1, Row: 2, Column: 1, ListRow: 1, IconCel: 2},
"shock wave": {Page: 2, Row: 5, Column: 3, ListRow: 2, IconCel: 28}, "shock wave": {Page: 2, Row: 5, Column: 3, ListRow: 2, IconCel: 28},
"shout": {Page: 3, Row: 2, Column: 2, ListRow: 3, IconCel: 24}, "shout": {Page: 3, Row: 2, Column: 2, ListRow: 3, IconCel: 24},
"showitems": {Page: 0, Row: 0, Column: 0, ListRow: 0, IconCel: 2},
"sigil death": {Page: 3, Row: 5, Column: 2, ListRow: 3, IconCel: 48},
"sigil lethargy": {Page: 3, Row: 2, Column: 2, ListRow: 3, IconCel: 40},
"sigil rancor": {Page: 3, Row: 3, Column: 2, ListRow: 3, IconCel: 44},
"skeleton mastery": {Page: 3, Row: 1, Column: 1, ListRow: 3, IconCel: 6}, "skeleton mastery": {Page: 3, Row: 1, Column: 1, ListRow: 3, IconCel: 6},
"slow missiles": {Page: 2, Row: 3, Column: 1, ListRow: 2, IconCel: 22}, "slow missiles": {Page: 2, Row: 3, Column: 1, ListRow: 2, IconCel: 22},
"smite": {Page: 1, Row: 1, Column: 3, ListRow: 1, IconCel: 2}, "smite": {Page: 1, Row: 1, Column: 3, ListRow: 1, IconCel: 2},
@@ -192,10 +229,14 @@ var Desc = map[SkillDesc]Description{
"static field": {Page: 2, Row: 2, Column: 1, ListRow: 2, IconCel: 12}, "static field": {Page: 2, Row: 2, Column: 1, ListRow: 2, IconCel: 12},
"strafe": {Page: 1, Row: 5, Column: 2, ListRow: 1, IconCel: 40}, "strafe": {Page: 1, Row: 5, Column: 2, ListRow: 1, IconCel: 40},
"stun": {Page: 1, Row: 3, Column: 2, ListRow: 1, IconCel: 26}, "stun": {Page: 1, Row: 3, Column: 2, ListRow: 1, IconCel: 26},
"summon defiler": {Page: 1, Row: 4, Column: 3, ListRow: 1, IconCel: 10},
"summon fenris": {Page: 1, Row: 4, Column: 2, ListRow: 1, IconCel: 12}, "summon fenris": {Page: 1, Row: 4, Column: 2, ListRow: 1, IconCel: 12},
"summon goatman": {Page: 1, Row: 1, Column: 3, ListRow: 1, IconCel: 2},
"summon grizzly": {Page: 1, Row: 6, Column: 2, ListRow: 1, IconCel: 18}, "summon grizzly": {Page: 1, Row: 6, Column: 2, ListRow: 1, IconCel: 18},
"summon resist": {Page: 3, Row: 5, Column: 1, ListRow: 3, IconCel: 46}, "summon resist": {Page: 3, Row: 5, Column: 1, ListRow: 3, IconCel: 46},
"summon spirit wolf": {Page: 1, Row: 2, Column: 2, ListRow: 1, IconCel: 6}, "summon spirit wolf": {Page: 1, Row: 2, Column: 2, ListRow: 1, IconCel: 6},
"summon tainted": {Page: 1, Row: 3, Column: 3, ListRow: 1, IconCel: 8},
"swapweapons": {Page: 0, Row: 0, Column: 0, ListRow: 0, IconCel: 2},
"taunt": {Page: 3, Row: 2, Column: 1, ListRow: 3, IconCel: 22}, "taunt": {Page: 3, Row: 2, Column: 1, ListRow: 3, IconCel: 22},
"teeth": {Page: 2, Row: 1, Column: 2, ListRow: 2, IconCel: 2}, "teeth": {Page: 2, Row: 1, Column: 2, ListRow: 2, IconCel: 2},
"telekinesis": {Page: 2, Row: 2, Column: 3, ListRow: 2, IconCel: 14}, "telekinesis": {Page: 2, Row: 2, Column: 3, ListRow: 2, IconCel: 14},

View File

@@ -20,6 +20,7 @@ type GameReader struct {
monstersLastUpdate time.Time monstersLastUpdate time.Time
inventoryLastUpdate time.Time inventoryLastUpdate time.Time
objectsLastUpdate time.Time objectsLastUpdate time.Time
ExpChar uint16
cachedMonsters data.Monsters cachedMonsters data.Monsters
cachedInventory data.Inventory cachedInventory data.Inventory

View File

@@ -14,6 +14,7 @@ import (
) )
func (gd *GameReader) Inventory(rawPlayerUnits RawPlayerUnits, hover data.HoverData) data.Inventory { func (gd *GameReader) Inventory(rawPlayerUnits RawPlayerUnits, hover data.HoverData) data.Inventory {
item.SetExpChar(gd.ExpChar)
mainPlayer := rawPlayerUnits.GetMainPlayer() mainPlayer := rawPlayerUnits.GetMainPlayer()
baseAddr := gd.Process.moduleBaseAddressPtr + gd.offset.UnitTable + (4 * 1024) baseAddr := gd.Process.moduleBaseAddressPtr + gd.offset.UnitTable + (4 * 1024)
unitTableBuffer := gd.Process.ReadBytesFromMemory(baseAddr, 128*8) unitTableBuffer := gd.Process.ReadBytesFromMemory(baseAddr, 128*8)
@@ -355,7 +356,7 @@ func (gd *GameReader) Inventory(rawPlayerUnits RawPlayerUnits, hover data.HoverD
if location == item.LocationSocket { if location == item.LocationSocket {
if itm.Desc().Code == "jew" { if itm.Desc().Code == "jew" {
// Base requirement for jewels // Base requirement for jewels
itm.LevelReq = item.Desc[itm.ID].RequiredLevel itm.LevelReq = itm.Desc().RequiredLevel
// For magic/rare jewels, check affixes // For magic/rare jewels, check affixes
if itm.Quality == item.QualityMagic || itm.Quality == item.QualityRare { if itm.Quality == item.QualityMagic || itm.Quality == item.QualityRare {
@@ -371,7 +372,7 @@ func (gd *GameReader) Inventory(rawPlayerUnits RawPlayerUnits, hover data.HoverD
} }
} else { } else {
// Normal socketed items (runes,gems) just use base requirement // Normal socketed items (runes,gems) just use base requirement
itm.LevelReq = item.Desc[itm.ID].RequiredLevel itm.LevelReq = itm.Desc().RequiredLevel
} }
itemExtraData := uintptr(gd.Process.ReadUInt(unitDataPtr+0xA0, Uint64)) itemExtraData := uintptr(gd.Process.ReadUInt(unitDataPtr+0xA0, Uint64))
if itemExtraData != 0 { if itemExtraData != 0 {
@@ -442,7 +443,7 @@ func (gd *GameReader) Inventory(rawPlayerUnits RawPlayerUnits, hover data.HoverD
// Build final inventory // Build final inventory
inventory.AllItems = make([]data.Item, len(allItems)) inventory.AllItems = make([]data.Item, len(allItems))
for i, itm := range allItems { for i, itm := range allItems {
baseDesc := item.Desc[itm.ID] baseDesc := itm.Desc()
maxReq := calculateItemLevelReq(itm, baseDesc) maxReq := calculateItemLevelReq(itm, baseDesc)
// Check magic/rare affixes // Check magic/rare affixes
@@ -452,7 +453,7 @@ func (gd *GameReader) Inventory(rawPlayerUnits RawPlayerUnits, hover data.HoverD
// Check socketed items // Check socketed items
for _, socketItem := range itm.Sockets { for _, socketItem := range itm.Sockets {
socketBaseDesc := item.Desc[socketItem.ID] socketBaseDesc := socketItem.Desc()
socketReq := calculateItemLevelReq(&socketItem, socketBaseDesc) socketReq := calculateItemLevelReq(&socketItem, socketBaseDesc)
if socketReq > maxReq { if socketReq > maxReq {

View File

@@ -12,6 +12,7 @@ func (gd *GameReader) GetKeyBindings() data.KeyBindings {
blobSkills := gd.ReadBytesFromMemory(gd.moduleBaseAddressPtr+gd.offset.KeyBindingsSkillsOffset, 0x500) blobSkills := gd.ReadBytesFromMemory(gd.moduleBaseAddressPtr+gd.offset.KeyBindingsSkillsOffset, 0x500)
skillsKB := [16]data.SkillBinding{} skillsKB := [16]data.SkillBinding{}
// Skills 0-6: slots 14-20
for i := 0; i < 7; i++ { for i := 0; i < 7; i++ {
skillsKB[i] = data.SkillBinding{ skillsKB[i] = data.SkillBinding{
SkillID: skill.ID(binary.LittleEndian.Uint32(blobSkills[i*0x1c : i*0x1c+4])), SkillID: skill.ID(binary.LittleEndian.Uint32(blobSkills[i*0x1c : i*0x1c+4])),
@@ -21,8 +22,20 @@ func (gd *GameReader) GetKeyBindings() data.KeyBindings {
}, },
} }
} }
for i := 0; i < 9; i++ { // Skills 7-13: slots 26-32
for i := 0; i < 7; i++ {
skillIdx := i + 7 skillIdx := i + 7
skillsKB[skillIdx] = data.SkillBinding{
SkillID: skill.ID(binary.LittleEndian.Uint32(blobSkills[skillIdx*0x1c : skillIdx*0x1c+4])),
KeyBinding: data.KeyBinding{
Key1: [2]byte{blob[0x208+(i*0x14)], blob[0x209+(i*0x14)]},
Key2: [2]byte{blob[0x212+(i*0x14)], blob[0x213+(i*0x14)]},
},
}
}
// Skills 14-15: slots 45-46
for i := 0; i < 2; i++ {
skillIdx := i + 14
skillsKB[skillIdx] = data.SkillBinding{ skillsKB[skillIdx] = data.SkillBinding{
SkillID: skill.ID(binary.LittleEndian.Uint32(blobSkills[skillIdx*0x1c : skillIdx*0x1c+4])), SkillID: skill.ID(binary.LittleEndian.Uint32(blobSkills[skillIdx*0x1c : skillIdx*0x1c+4])),
KeyBinding: data.KeyBinding{ KeyBinding: data.KeyBinding{

View File

@@ -26,61 +26,61 @@ type Offset struct {
func calculateOffsets(_ *Process) Offset { func calculateOffsets(_ *Process) Offset {
// UnitTable // UnitTable
unitTableOffset := uintptr(0x1D95AF0) unitTableOffset := uintptr(0x1E9B350)
// UI // UI
uiOffsetPtr := uintptr(0x1DA57DA) uiOffsetPtr := uintptr(0x1EAB042)
// Hover // Hover
hoverOffset := uintptr(0x1CE8400) hoverOffset := uintptr(0x1DEF000)
// Expansion // Expansion
expOffset := uintptr(0x1CE78D0) expOffset := uintptr(0x1DEE468)
// Party members offset // Party members offset
rosterOffset := uintptr(0x1DABD60) rosterOffset := uintptr(0x1EB1660)
// PanelManagerContainer // PanelManagerContainer
panelManagerContainerOffset := uintptr(0x1D00968) panelManagerContainerOffset := uintptr(0x1E05DC0)
// WidgetStates // WidgetStates
WidgetStatesOffset := uintptr(0x1DCDD40) WidgetStatesOffset := uintptr(0x1ED3678)
// Waypoints // Waypoints
WaypointTableOffset := uintptr(0x1C468B0) WaypointTableOffset := uintptr(0x1D4D3C0)
// FPS // FPS
fpsOffset := uintptr(0x1C46894) fpsOffset := uintptr(0x1D4D394)
// KeyBindings // KeyBindings
keyBindingsOffset := uintptr(0x18C2894) keyBindingsOffset := uintptr(0x19C65B4)
// KeyBindings Skills // KeyBindings Skills
keyBindingsSkillsOffset := uintptr(0x1CE8510) keyBindingsSkillsOffset := uintptr(0x1DEF110)
// QuestInfo // QuestInfo
questInfoOffset := uintptr(0x1DB23D8) questInfoOffset := uintptr(0x1EB7CD8)
// Terror Zones // Terror Zones
tzOffset := uintptr(0x248D430) tzOffset := uintptr(0x25A5AB0)
// Ping // Ping
pingOffset := uintptr(0x1CE78D0) pingOffset := uintptr(0x1DEE468)
// LegacyGraphics // LegacyGraphics
legacyGfxOffset := uintptr(0x1DB263E) legacyGfxOffset := uintptr(0x1EB7E7E)
// CharData // CharData
charDataOffset := uintptr(0x1CED5E8) charDataOffset := uintptr(0x1DF25F8)
// Selected Char Name // Selected Char Name
selectedCharNameOffset := uintptr(0x1C3D694) selectedCharNameOffset := uintptr(0x1D44195)
// Last Game Name // Last Game Name
lastGameNameOffset := uintptr(0x24D5A90) lastGameNameOffset := uintptr(0x25EE370)
// Last Game Password // Last Game Password
lastGamePasswordOffset := uintptr(0x24D5AE8) lastGamePasswordOffset := uintptr(0x25EE3C8)
return Offset{ return Offset{
UnitTable: unitTableOffset, UnitTable: unitTableOffset,

View File

@@ -38,8 +38,9 @@ func (gd *GameReader) GetRawPlayerUnits() RawPlayerUnits {
expCharPtr := uintptr(gd.Process.ReadUInt(gd.moduleBaseAddressPtr+gd.offset.Expansion, Uint64)) expCharPtr := uintptr(gd.Process.ReadUInt(gd.moduleBaseAddressPtr+gd.offset.Expansion, Uint64))
expChar := gd.Process.ReadUInt(expCharPtr+0x5C, Uint16) expChar := gd.Process.ReadUInt(expCharPtr+0x5C, Uint16)
gd.ExpChar = uint16(expChar)
isMainPlayer := gd.Process.ReadUInt(inventoryAddr+0x30, Uint16) isMainPlayer := gd.Process.ReadUInt(inventoryAddr+0x30, Uint16)
if expChar > 0 { if expChar >= 2 {
isMainPlayer = gd.Process.ReadUInt(inventoryAddr+0x70, Uint16) isMainPlayer = gd.Process.ReadUInt(inventoryAddr+0x70, Uint16)
} }
isCorpse := gd.Process.ReadUInt(playerUnit+0x1AE, Uint8) isCorpse := gd.Process.ReadUInt(playerUnit+0x1AE, Uint8)

View File

@@ -36,7 +36,7 @@ func TestRule_Evaluate(t *testing.T) {
}, },
args: args{ args: args{
item: data.Item{ item: data.Item{
ID: 603, ID: 618,
Name: "SmAlLCharM", Name: "SmAlLCharM",
Quality: item.QualityMagic, Quality: item.QualityMagic,
Identified: true, Identified: true,