D2Data and Quest data (#9)

This commit is contained in:
Héctor Giménez
2024-02-02 20:19:44 +09:00
committed by GitHub
parent f06c587c7a
commit db8fc7d6db
16 changed files with 25749 additions and 462 deletions

File diff suppressed because it is too large Load Diff

16906
cmd/d2data/d2data/skills.json Normal file

File diff suppressed because it is too large Load Diff

86
cmd/d2data/main.go Normal file
View File

@@ -0,0 +1,86 @@
package main
import (
"encoding/json"
"io"
"log"
"os"
"text/template"
)
const templateSkillDesc = `// Code generated by d2data. DO NOT EDIT.
// source: cmd/d2data/d2data/skilldesc.json
package skill
var Desc = map[ID]Description{
{{- range $key, $value := . }}
{{ $key }}: {Page: {{ $value.SkillPage }}, Row: {{ $value.SkillRow }}, Column: {{ $value.SkillColumn }}, ListRow: {{ $value.ListRow }}, IconCel: {{ $value.IconCel }} },
{{- end }}
}`
const templateSkills = `// Code generated by d2data. DO NOT EDIT.
// source: cmd/d2data/d2data/skills.json
package skill
var Skills = map[ID]Skill{
{{- range $key, $value := . }}
{{ $key }}: {Name: "{{ $value.Name }}", ID: {{ $key }}, LeftSkill: {{ if eq $value.Leftskill 1 }}true{{ else }}false{{ end }}, RightSkill: {{ if eq $value.Rightskill 1 }}true{{ else }}false{{ end }} },
{{- end }}
}`
type skillDesc struct {
Skilldesc string `json:"skilldesc"`
SkillPage int `json:"SkillPage"`
SkillRow int `json:"SkillRow"`
SkillColumn int `json:"SkillColumn"`
ListRow int `json:"ListRow"`
IconCel int `json:"IconCel"`
StrName string `json:"str name"`
StrShort string `json:"str short"`
StrLong string `json:"str long"`
StrAlt string `json:"str alt"`
}
type Skill struct {
Leftskill int `json:"leftskill"`
Rightskill int `json:"rightskill"`
Name string `json:"skill"`
}
// Generate static code from https://github.com/blizzhackers/d2data data files.
func main() {
err := generateFromFile(templateSkillDesc, "cmd/d2data/d2data/skilldesc.json", "pkg/data/skill/skilldesc.go", &map[string]skillDesc{})
if err != nil {
log.Fatal(err)
}
err = generateFromFile(templateSkills, "cmd/d2data/d2data/skills.json", "pkg/data/skill/skills.go", &map[string]Skill{})
if err != nil {
log.Fatal(err)
}
}
func generateFromFile(templateName, filePath, outPath string, unmarshallStruct interface{}) error {
jsonFile, err := os.Open(filePath)
if err != nil {
return err
}
defer jsonFile.Close()
byteValue, _ := io.ReadAll(jsonFile)
err = json.Unmarshal(byteValue, &unmarshallStruct)
if err != nil {
return err
}
t := template.Must(template.New("tpl").Parse(templateName))
file, err := os.Create(outPath)
if err != nil {
return err
}
defer file.Close()
return t.Execute(file, unmarshallStruct)
}

2
go.mod
View File

@@ -6,7 +6,7 @@ require (
github.com/faiface/beep v1.1.0 github.com/faiface/beep v1.1.0
github.com/stretchr/testify v1.8.4 github.com/stretchr/testify v1.8.4
github.com/winlabs/gowin32 v0.0.0-20221003142512-0d265587d3c9 github.com/winlabs/gowin32 v0.0.0-20221003142512-0d265587d3c9
golang.org/x/sys v0.13.0 golang.org/x/sys v0.16.0
) )
require ( require (

4
go.sum
View File

@@ -42,8 +42,8 @@ golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73r
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190429190828-d89cdac9e872/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190429190828-d89cdac9e872/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190626150813-e07cf5db2756/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190626150813-e07cf5db2756/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU=
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=

View File

@@ -1,6 +1,7 @@
package data package data
import ( import (
"github.com/hectorgimenez/d2go/pkg/data/quest"
"strings" "strings"
"github.com/hectorgimenez/d2go/pkg/data/area" "github.com/hectorgimenez/d2go/pkg/data/area"
@@ -64,6 +65,7 @@ type Data struct {
Roster Roster Roster Roster
HoverData HoverData HoverData HoverData
TerrorZones []area.Area TerrorZones []area.Area
Quests quest.Quests
} }
type Room struct { type Room struct {
@@ -162,11 +164,11 @@ type PlayerUnit struct {
Area area.Area Area area.Area
Position Position Position Position
Stats map[stat.ID]int Stats map[stat.ID]int
Skills map[skill.Skill]int Skills map[skill.ID]skill.Points
States state.States States state.States
Class Class Class Class
LeftSkill skill.Skill LeftSkill skill.ID
RightSkill skill.Skill RightSkill skill.ID
AvailableWaypoints []area.Area // Is only filled when WP menu is open and only for the specific selected tab AvailableWaypoints []area.Area // Is only filled when WP menu is open and only for the specific selected tab
} }

View File

@@ -50,7 +50,7 @@ func (m Monsters) FindOne(id npc.ID, t MonsterType) (Monster, bool) {
func (m Monsters) Enemies(filters ...MonsterFilter) []Monster { func (m Monsters) Enemies(filters ...MonsterFilter) []Monster {
monsters := make([]Monster, 0) monsters := make([]Monster, 0)
for _, mo := range m { for _, mo := range m {
if !mo.IsMerc() && mo.Name != npc.BaalTaunt && mo.Name != npc.Act5Combatant && mo.Name != npc.Act5Combatant2 && !mo.IsSkip() && !mo.IsGoodNPC() && mo.Stats[stat.Life] > 0 { if !mo.IsMerc() && !mo.IsSkip() && !mo.IsGoodNPC() && mo.Stats[stat.Life] > 0 {
monsters = append(monsters, mo) monsters = append(monsters, mo)
} }
} }
@@ -154,10 +154,10 @@ func (m Monster) IsMonsterRaiser() bool {
return false return false
} }
// Monster can`t be targeted normally // IsSkip monster can not be killed as a normal enemy, for example can not be targeted
func (m Monster) IsSkip() bool { func (m Monster) IsSkip() bool {
switch m.Name { switch m.Name {
case npc.WaterWatcherLimb, npc.WaterWatcherHead: case npc.WaterWatcherLimb, npc.WaterWatcherHead, npc.BaalTaunt, npc.Act5Combatant, npc.Act5Combatant2, npc.BarricadeTower:
return true return true
} }

51
pkg/data/quest/quest.go Normal file
View File

@@ -0,0 +1,51 @@
package quest
type Quest int16
type Status int16
type States []Status
func (s States) Completed() bool {
return s.HasStatus(StatusUpdateQuestLogCompleted)
}
func (s States) HasStatus(st Status) bool {
for _, state := range s {
if state == st {
return true
}
}
return false
}
const (
Act1DenOfEvil Quest = iota
Act1SistersBurialGrounds
Act1ToolsOfTheTrade
Act1TheSearchForCain
Act1TheForgottenTower
Act1SistersToTheSlaughter
Act2RadamentsLair
Act2TheHoradricStaff
Act2TaintedSun
Act2ArcaneSanctuary
Act2TheSummoner
Act2TheSevenTombs
Act3LamEsensTome
Act3KhalimsWill
Act3BladeOfTheOldReligion
Act3TheGoldenBird
Act3TheBlackenedTemple
Act3TheGuardian
Act4TheFallenAngel
Act4HellForge
Act4TerrorsEnd
Act5SiegeOnHarrogath
Act5RescueOnMountArreat
Act5PrisonOfIce
Act5BetrayalOfHarrogath
Act5RiteOfPassage
Act5EveOfDestruction
)
type Quests map[Quest]States

20
pkg/data/quest/status.go Normal file
View File

@@ -0,0 +1,20 @@
package quest
const (
StatusRewardGranted Status = iota
StatusRewardPending
StatusQuestInitiated
StatusLeaveTown
StatusEnterFirstArea
StatusInProgress1
StatusInProgress2
StatusInProgress3
StatusInProgress4
StatusInProgress5
StatusInProgress6
StatusInProgress7
StatusUpdateQuestLogCompleted
StatusPrimaryGoalCompleted
StatusUnknown1
StatusUnknown2
)

391
pkg/data/skill/skill.go Normal file
View File

@@ -0,0 +1,391 @@
package skill
type ID int16
type Description struct {
Name string
Page int
Row int
Column int
ListRow int
IconCel int
}
type Skill struct {
ID ID
Name string
LeftSkill bool
RightSkill bool
}
type Points struct {
Level uint
Quantity uint
Charges uint
}
func (sk Skill) Desc() Description {
return Desc[sk.ID]
}
const (
AttackSkill ID = iota
Kick
Throw
Unsummon
LeftHandThrow
LeftHandSwing
MagicArrow
FireArrow
InnerSight
CriticalStrike
Jab
ColdArrow
MultipleShot
Dodge
PowerStrike
PoisonJavelin
ExplodingArrow
SlowMissiles
Avoid
Impale
LightningBolt
IceArrow
GuidedArrow
Penetrate
ChargedStrike
PlagueJavelin
Strafe
ImmolationArrow
Decoy
Evade
Fend
FreezingArrow
Valkyrie
Pierce
LightningStrike
LightningFury
FireBolt
Warmth
ChargedBolt
IceBolt
FrozenArmor
Inferno
StaticField
Telekinesis
FrostNova
IceBlast
Blaze
FireBall
Nova
Lightning
ShiverArmor
FireWall
Enchant
ChainLightning
Teleport
GlacialSpike
Meteor
ThunderStorm
EnergyShield
Blizzard
ChillingArmor
FireMastery
Hydra
LightningMastery
FrozenOrb
ColdMastery
AmplifyDamage
Teeth
BoneArmor
SkeletonMastery
RaiseSkeleton
DimVision
Weaken
PoisonDagger
CorpseExplosion
ClayGolem
IronMaiden
Terror
BoneWall
GolemMastery
RaiseSkeletalMage
Confuse
LifeTap
PoisonExplosion
BoneSpear
BloodGolem
Attract
Decrepify
BonePrison
SummonResist
IronGolem
LowerResist
PoisonNova
BoneSpirit
FireGolem
Revive
Sacrifice
Smite
Might
Prayer
ResistFire
HolyBolt
HolyFire
Thorns
Defiance
ResistCold
Zeal
Charge
BlessedAim
Cleansing
ResistLightning
Vengeance
BlessedHammer
Concentration
HolyFreeze
Vigor
Conversion
HolyShield
HolyShock
Sanctuary
Meditation
FistOfTheHeavens
Fanaticism
Conviction
Redemption
Salvation
Bash
BladeMastery
AxeMastery
MaceMastery
Howl
FindPotion
Leap
DoubleSwing
PolearmMastery
ThrowingMastery
SpearMastery
Taunt
Shout
Stun
DoubleThrow
IncreasedStamina
FindItem
LeapAttack
Concentrate
IronSkin
BattleCry
Frenzy
IncreasedSpeed
BattleOrders
GrimWard
Whirlwind
Berserk
NaturalResistance
WarCry
BattleCommand
FireHit
UnHolyBolt
SkeletonRaise
MaggotEgg
ShamanFire
MagottUp
MagottDown
MagottLay
AndrialSpray
Jump
SwarmMove
Nest
QuickStrike
VampireFireball
VampireFirewall
VampireMeteor
GargoyleTrap
SpiderLay
VampireHeal
VampireRaise
Submerge
FetishAura
FetishInferno
ZakarumHeal
Emerge
Resurrect
Bestow
MissileSkill1
MonTeleport
PrimeLightning
PrimeBolt
PrimeBlaze
PrimeFirewall
PrimeSpike
PrimeIceNova
PrimePoisonball
PrimePoisonNova
DiabLight
DiabCold
DiabFire
FingerMageSpider
DiabWall
DiabRun
DiabPrison
PoisonBallTrap
AndyPoisonBolt
HireableMissile
DesertTurret
ArcaneTower
MonBlizzard
Mosquito
CursedBallTrapRight
CursedBallTrapLeft
MonFrozenArmor
MonBoneArmor
MonBoneSpirit
MonCurseCast
HellMeteor
RegurgitatorEat
MonFrenzy
QueenDeath
ScrollOfIdentify
TomeOfIdentify
ScrollOfTownPortal
TomeOfTownPortal
Raven
PoisonCreeper
Werewolf
Lycanthropy
Firestorm
OakSage
SummonSpiritWolf
Werebear
MoltenBoulder
ArcticBlast
CarrionVine
FeralRage
Maul
Fissure
CycloneArmor
HeartOfWolverine
SummonDireWolf
Rabies
FireClaws
Twister
SolarCreeper
Hunger
ShockWave
Volcano
Tornado
SpiritOfBarbs
SummonGrizzly
Fury
Armageddon
Hurricane
FireBlast
ClawMastery
PsychicHammer
TigerStrike
DragonTalon
ShockWeb
BladeSentinel
BurstOfSpeed
FistsOfFire
DragonClaw
ChargedBoltSentry
WakeOfFire
WeaponBlock
CloakOfShadows
CobraStrike
BladeFury
Fade
ShadowWarrior
ClawsOfThunder
DragonTail
LightningSentry
WakeOfInferno
MindBlast
BladesOfIce
DragonFlight
DeathSentry
BladeShield
Venom
ShadowMaster
PhoenixStrike
WakeOfDestructionSentry
ImpInferno
ImpFireball
BaalTaunt
BaalCorpseExplode
BaalMonsterSpawn
CatapultChargedBall
CatapultSpikeBall
SuckBlood
CryHelp
HealingVortex
Teleport2
SelfResurrect
VineAttack
OverseerWhip
BarbsAura
WolverineAura
OakSageAura
ImpFireMissile
Impregnate
SiegeBeastStomp
MinionSpawner
CatapultBlizzard
CatapultPlague
CatapultMeteor
BoltSentry
CorpseCycler
DeathMaul
DefenseCurse
BloodMana
monInfernoSentry
monDeathSentry
sentryLightning
fenrisRage
BaalTentacle
BaalNova
BaalInferno
BaalColdMissiles
MegademonInferno
EvilHutSpawner
CountessFirewall
ImpBolt
HorrorArcticBlast
deathSentryLtng
VineCycler
BearSmite
Resurrect2
BloodLordFrenzy
BaalTeleport
ImpTeleport
BaalCloneTeleport
ZakarumLightning
VampireMissile
MephistoMissile
DoomKnightMissile
RogueMissile
HydraMissile
NecromageMissile
MonBow
MonFireArrow
MonColdArrow
MonExplodingArrow
MonFreezingArrow
MonPowerStrike
SuccubusBolt
MephFrostNova
MonIceSpear
ShamanIce
Diablogeddon
DeleriumChange
NihlathakCorpseExplosion
SerpentCharge
TrapNova
UnHolyBoltEx
ShamanFireEx
ImpFireMissileEx
FixedSiegeBeastStomp
Unset ID = -1
)

238
pkg/data/skill/skilldesc.go Normal file
View File

@@ -0,0 +1,238 @@
// Code generated by d2data. DO NOT EDIT.
// source: cmd/d2data/d2data/skilldesc.json
package skill
var Desc = map[ID]Description{
0: {Page: 0, Row: 0, Column: 0, ListRow: 0, IconCel: 2},
1: {Page: 0, Row: 0, Column: 0, ListRow: -1, IconCel: 0},
10: {Page: 3, Row: 1, Column: 1, ListRow: 3, IconCel: 8},
100: {Page: 3, Row: 1, Column: 3, ListRow: 3, IconCel: 8},
101: {Page: 1, Row: 2, Column: 2, ListRow: 1, IconCel: 10},
102: {Page: 2, Row: 2, Column: 2, ListRow: 2, IconCel: 12},
103: {Page: 2, Row: 2, Column: 3, ListRow: 2, IconCel: 14},
104: {Page: 3, Row: 2, Column: 2, ListRow: 3, IconCel: 16},
105: {Page: 3, Row: 2, Column: 3, ListRow: 3, IconCel: 18},
106: {Page: 1, Row: 3, Column: 1, ListRow: 1, IconCel: 20},
107: {Page: 1, Row: 3, Column: 3, ListRow: 1, IconCel: 22},
108: {Page: 2, Row: 3, Column: 1, ListRow: 2, IconCel: 24},
109: {Page: 3, Row: 3, Column: 1, ListRow: 3, IconCel: 38},
11: {Page: 1, Row: 2, Column: 1, ListRow: 1, IconCel: 10},
110: {Page: 3, Row: 3, Column: 3, ListRow: 3, IconCel: 28},
111: {Page: 1, Row: 4, Column: 1, ListRow: 1, IconCel: 40},
112: {Page: 1, Row: 4, Column: 2, ListRow: 1, IconCel: 32},
113: {Page: 2, Row: 4, Column: 1, ListRow: 2, IconCel: 34},
114: {Page: 2, Row: 4, Column: 2, ListRow: 2, IconCel: 36},
115: {Page: 3, Row: 4, Column: 2, ListRow: 3, IconCel: 26},
116: {Page: 1, Row: 5, Column: 1, ListRow: 1, IconCel: 30},
117: {Page: 1, Row: 5, Column: 3, ListRow: 1, IconCel: 42},
118: {Page: 2, Row: 5, Column: 2, ListRow: 2, IconCel: 44},
119: {Page: 2, Row: 5, Column: 3, ListRow: 2, IconCel: 46},
12: {Page: 1, Row: 2, Column: 2, ListRow: 1, IconCel: 12},
120: {Page: 3, Row: 5, Column: 1, ListRow: 3, IconCel: 48},
121: {Page: 1, Row: 6, Column: 2, ListRow: 1, IconCel: 50},
122: {Page: 2, Row: 6, Column: 1, ListRow: 2, IconCel: 52},
123: {Page: 2, Row: 6, Column: 3, ListRow: 2, IconCel: 56},
124: {Page: 3, Row: 6, Column: 2, ListRow: 3, IconCel: 54},
125: {Page: 3, Row: 6, Column: 3, ListRow: 3, IconCel: 58},
126: {Page: 1, Row: 1, Column: 2, ListRow: 1, IconCel: 0},
127: {Page: 2, Row: 1, Column: 1, ListRow: 2, IconCel: 2},
128: {Page: 2, Row: 1, Column: 2, ListRow: 2, IconCel: 4},
129: {Page: 2, Row: 1, Column: 3, ListRow: 2, IconCel: 6},
13: {Page: 2, Row: 2, Column: 2, ListRow: 2, IconCel: 14},
130: {Page: 3, Row: 1, Column: 1, ListRow: 3, IconCel: 8},
131: {Page: 3, Row: 1, Column: 3, ListRow: 3, IconCel: 10},
132: {Page: 1, Row: 2, Column: 1, ListRow: 1, IconCel: 12},
133: {Page: 1, Row: 2, Column: 3, ListRow: 1, IconCel: 14},
134: {Page: 2, Row: 2, Column: 1, ListRow: 2, IconCel: 16},
135: {Page: 2, Row: 2, Column: 2, ListRow: 2, IconCel: 18},
136: {Page: 2, Row: 2, Column: 3, ListRow: 2, IconCel: 20},
137: {Page: 3, Row: 2, Column: 1, ListRow: 3, IconCel: 22},
138: {Page: 3, Row: 2, Column: 2, ListRow: 3, IconCel: 24},
139: {Page: 1, Row: 3, Column: 2, ListRow: 1, IconCel: 26},
14: {Page: 3, Row: 2, Column: 2, ListRow: 3, IconCel: 16},
140: {Page: 1, Row: 3, Column: 3, ListRow: 1, IconCel: 28},
141: {Page: 2, Row: 3, Column: 1, ListRow: 2, IconCel: 30},
142: {Page: 3, Row: 3, Column: 3, ListRow: 3, IconCel: 32},
143: {Page: 1, Row: 4, Column: 1, ListRow: 1, IconCel: 34},
144: {Page: 1, Row: 4, Column: 2, ListRow: 1, IconCel: 36},
145: {Page: 2, Row: 4, Column: 3, ListRow: 2, IconCel: 38},
146: {Page: 3, Row: 4, Column: 1, ListRow: 3, IconCel: 40},
147: {Page: 1, Row: 5, Column: 3, ListRow: 1, IconCel: 42},
148: {Page: 2, Row: 5, Column: 1, ListRow: 2, IconCel: 44},
149: {Page: 3, Row: 5, Column: 2, ListRow: 3, IconCel: 46},
15: {Page: 3, Row: 2, Column: 3, ListRow: 3, IconCel: 18},
150: {Page: 3, Row: 5, Column: 3, ListRow: 3, IconCel: 48},
151: {Page: 1, Row: 6, Column: 1, ListRow: 1, IconCel: 50},
152: {Page: 1, Row: 6, Column: 2, ListRow: 1, IconCel: 52},
153: {Page: 2, Row: 6, Column: 3, ListRow: 2, IconCel: 54},
154: {Page: 3, Row: 6, Column: 1, ListRow: 3, IconCel: 56},
155: {Page: 3, Row: 6, Column: 2, ListRow: 3, IconCel: 58},
156: {Page: 0, Row: 0, Column: 0, ListRow: 4, IconCel: 14},
157: {Page: 0, Row: 0, Column: 0, ListRow: 4, IconCel: 14},
158: {Page: 0, Row: 0, Column: 0, ListRow: 4, IconCel: 18},
159: {Page: 0, Row: 0, Column: 0, ListRow: 4, IconCel: 18},
16: {Page: 1, Row: 3, Column: 3, ListRow: 1, IconCel: 20},
160: {Page: 1, Row: 1, Column: 2, ListRow: 1, IconCel: 0},
161: {Page: 1, Row: 1, Column: 3, ListRow: 1, IconCel: 2},
162: {Page: 2, Row: 1, Column: 1, ListRow: 2, IconCel: 20},
163: {Page: 2, Row: 1, Column: 2, ListRow: 2, IconCel: 52},
164: {Page: 3, Row: 1, Column: 1, ListRow: 3, IconCel: 32},
165: {Page: 1, Row: 2, Column: 1, ListRow: 1, IconCel: 16},
166: {Page: 1, Row: 2, Column: 2, ListRow: 1, IconCel: 6},
167: {Page: 2, Row: 2, Column: 3, ListRow: 2, IconCel: 22},
168: {Page: 3, Row: 2, Column: 1, ListRow: 3, IconCel: 34},
169: {Page: 3, Row: 2, Column: 3, ListRow: 3, IconCel: 36},
17: {Page: 2, Row: 3, Column: 1, ListRow: 2, IconCel: 22},
170: {Page: 1, Row: 3, Column: 3, ListRow: 1, IconCel: 8},
171: {Page: 2, Row: 3, Column: 1, ListRow: 2, IconCel: 54},
172: {Page: 2, Row: 3, Column: 3, ListRow: 2, IconCel: 56},
173: {Page: 3, Row: 3, Column: 1, ListRow: 3, IconCel: 38},
174: {Page: 3, Row: 3, Column: 3, ListRow: 3, IconCel: 40},
175: {Page: 1, Row: 4, Column: 1, ListRow: 1, IconCel: 10},
176: {Page: 1, Row: 4, Column: 2, ListRow: 1, IconCel: 12},
177: {Page: 2, Row: 4, Column: 1, ListRow: 2, IconCel: 24},
178: {Page: 2, Row: 4, Column: 2, ListRow: 2, IconCel: 26},
179: {Page: 3, Row: 4, Column: 2, ListRow: 3, IconCel: 42},
18: {Page: 2, Row: 3, Column: 2, ListRow: 2, IconCel: 24},
180: {Page: 1, Row: 5, Column: 3, ListRow: 1, IconCel: 14},
181: {Page: 2, Row: 5, Column: 2, ListRow: 2, IconCel: 58},
182: {Page: 2, Row: 5, Column: 3, ListRow: 2, IconCel: 28},
183: {Page: 3, Row: 5, Column: 1, ListRow: 3, IconCel: 44},
184: {Page: 3, Row: 5, Column: 2, ListRow: 3, IconCel: 46},
185: {Page: 1, Row: 6, Column: 1, ListRow: 1, IconCel: 4},
186: {Page: 1, Row: 6, Column: 2, ListRow: 1, IconCel: 18},
187: {Page: 2, Row: 6, Column: 1, ListRow: 2, IconCel: 30},
188: {Page: 3, Row: 6, Column: 1, ListRow: 3, IconCel: 50},
189: {Page: 3, Row: 6, Column: 2, ListRow: 3, IconCel: 48},
19: {Page: 3, Row: 3, Column: 1, ListRow: 3, IconCel: 26},
190: {Page: 1, Row: 1, Column: 2, ListRow: 1, IconCel: 0},
191: {Page: 2, Row: 1, Column: 2, ListRow: 2, IconCel: 20},
192: {Page: 2, Row: 1, Column: 3, ListRow: 2, IconCel: 22},
193: {Page: 3, Row: 1, Column: 2, ListRow: 3, IconCel: 40},
194: {Page: 3, Row: 1, Column: 3, ListRow: 3, IconCel: 42},
195: {Page: 1, Row: 2, Column: 1, ListRow: 1, IconCel: 2},
196: {Page: 1, Row: 2, Column: 3, ListRow: 1, IconCel: 4},
197: {Page: 2, Row: 2, Column: 1, ListRow: 2, IconCel: 36},
198: {Page: 3, Row: 2, Column: 1, ListRow: 3, IconCel: 44},
199: {Page: 3, Row: 2, Column: 3, ListRow: 3, IconCel: 46},
2: {Page: 0, Row: 0, Column: 0, ListRow: 0, IconCel: 6},
20: {Page: 3, Row: 3, Column: 3, ListRow: 3, IconCel: 28},
200: {Page: 1, Row: 3, Column: 1, ListRow: 1, IconCel: 6},
201: {Page: 1, Row: 3, Column: 2, ListRow: 1, IconCel: 8},
202: {Page: 2, Row: 3, Column: 2, ListRow: 2, IconCel: 26},
203: {Page: 2, Row: 3, Column: 3, ListRow: 2, IconCel: 24},
204: {Page: 3, Row: 3, Column: 2, ListRow: 3, IconCel: 50},
205: {Page: 1, Row: 4, Column: 3, ListRow: 1, IconCel: 10},
206: {Page: 2, Row: 4, Column: 1, ListRow: 2, IconCel: 30},
207: {Page: 2, Row: 4, Column: 2, ListRow: 2, IconCel: 38},
208: {Page: 3, Row: 4, Column: 1, ListRow: 3, IconCel: 58},
209: {Page: 3, Row: 4, Column: 3, ListRow: 3, IconCel: 48},
21: {Page: 1, Row: 4, Column: 1, ListRow: 1, IconCel: 30},
210: {Page: 1, Row: 5, Column: 1, ListRow: 1, IconCel: 12},
211: {Page: 1, Row: 5, Column: 2, ListRow: 1, IconCel: 14},
212: {Page: 2, Row: 5, Column: 3, ListRow: 2, IconCel: 34},
213: {Page: 3, Row: 5, Column: 1, ListRow: 3, IconCel: 52},
214: {Page: 3, Row: 5, Column: 3, ListRow: 3, IconCel: 54},
215: {Page: 1, Row: 6, Column: 1, ListRow: 1, IconCel: 16},
216: {Page: 1, Row: 6, Column: 3, ListRow: 1, IconCel: 18},
217: {Page: 2, Row: 6, Column: 1, ListRow: 2, IconCel: 28},
218: {Page: 2, Row: 6, Column: 2, ListRow: 2, IconCel: 32},
219: {Page: 3, Row: 6, Column: 2, ListRow: 3, IconCel: 56},
22: {Page: 1, Row: 4, Column: 2, ListRow: 1, IconCel: 32},
220: {Page: 0, Row: 0, Column: 0, ListRow: 0, IconCel: 2},
221: {Page: 0, Row: 0, Column: 0, ListRow: 0, IconCel: 2},
222: {Page: 0, Row: 0, Column: 0, ListRow: 0, IconCel: 2},
223: {Page: 0, Row: 0, Column: 0, ListRow: 0, IconCel: 18},
224: {Page: 0, Row: 0, Column: 0, ListRow: 0, IconCel: 2},
225: {Page: 0, Row: 0, Column: 0, ListRow: 0, IconCel: 2},
226: {Page: 0, Row: 0, Column: 0, ListRow: 0, IconCel: 2},
227: {Page: 0, Row: 0, Column: 0, ListRow: 0, IconCel: 2},
228: {Page: 0, Row: 0, Column: 0, ListRow: 0, IconCel: 2},
229: {Page: 0, Row: 0, Column: 0, ListRow: 0, IconCel: 2},
23: {Page: 2, Row: 4, Column: 3, ListRow: 2, IconCel: 34},
230: {Page: 0, Row: 0, Column: 0, ListRow: 0, IconCel: 2},
231: {Page: 0, Row: 0, Column: 0, ListRow: 0, IconCel: 2},
24: {Page: 3, Row: 4, Column: 2, ListRow: 3, IconCel: 36},
25: {Page: 3, Row: 4, Column: 3, ListRow: 3, IconCel: 38},
26: {Page: 1, Row: 5, Column: 2, ListRow: 1, IconCel: 40},
27: {Page: 1, Row: 5, Column: 3, ListRow: 1, IconCel: 42},
28: {Page: 2, Row: 5, Column: 1, ListRow: 2, IconCel: 44},
29: {Page: 2, Row: 5, Column: 2, ListRow: 2, IconCel: 46},
3: {Page: 0, Row: 0, Column: 0, ListRow: 0, IconCel: 4},
30: {Page: 3, Row: 5, Column: 1, ListRow: 3, IconCel: 48},
31: {Page: 1, Row: 6, Column: 1, ListRow: 1, IconCel: 50},
32: {Page: 2, Row: 6, Column: 1, ListRow: 2, IconCel: 52},
33: {Page: 2, Row: 6, Column: 3, ListRow: 2, IconCel: 54},
34: {Page: 3, Row: 6, Column: 2, ListRow: 3, IconCel: 56},
35: {Page: 3, Row: 6, Column: 3, ListRow: 3, IconCel: 58},
36: {Page: 1, Row: 1, Column: 2, ListRow: 1, IconCel: 0},
37: {Page: 1, Row: 1, Column: 3, ListRow: 1, IconCel: 2},
38: {Page: 2, Row: 1, Column: 2, ListRow: 2, IconCel: 4},
39: {Page: 3, Row: 1, Column: 2, ListRow: 3, IconCel: 6},
4: {Page: 0, Row: 0, Column: 0, ListRow: 0, IconCel: 12},
40: {Page: 3, Row: 1, Column: 3, ListRow: 3, IconCel: 8},
41: {Page: 1, Row: 2, Column: 1, ListRow: 1, IconCel: 10},
42: {Page: 2, Row: 2, Column: 1, ListRow: 2, IconCel: 12},
43: {Page: 2, Row: 2, Column: 3, ListRow: 2, IconCel: 14},
44: {Page: 3, Row: 2, Column: 1, ListRow: 3, IconCel: 16},
45: {Page: 3, Row: 2, Column: 2, ListRow: 3, IconCel: 18},
46: {Page: 1, Row: 3, Column: 1, ListRow: 1, IconCel: 20},
47: {Page: 1, Row: 3, Column: 2, ListRow: 1, IconCel: 22},
48: {Page: 2, Row: 3, Column: 1, ListRow: 2, IconCel: 24},
49: {Page: 2, Row: 3, Column: 2, ListRow: 2, IconCel: 26},
5: {Page: 0, Row: 0, Column: 0, ListRow: -1, IconCel: 10},
50: {Page: 3, Row: 3, Column: 3, ListRow: 3, IconCel: 28},
51: {Page: 1, Row: 4, Column: 1, ListRow: 1, IconCel: 30},
52: {Page: 1, Row: 4, Column: 3, ListRow: 1, IconCel: 32},
53: {Page: 2, Row: 4, Column: 2, ListRow: 2, IconCel: 34},
54: {Page: 2, Row: 4, Column: 3, ListRow: 2, IconCel: 36},
55: {Page: 3, Row: 4, Column: 2, ListRow: 3, IconCel: 38},
56: {Page: 1, Row: 5, Column: 2, ListRow: 1, IconCel: 40},
57: {Page: 2, Row: 5, Column: 1, ListRow: 2, IconCel: 42},
58: {Page: 2, Row: 5, Column: 3, ListRow: 2, IconCel: 44},
59: {Page: 3, Row: 5, Column: 1, ListRow: 3, IconCel: 46},
6: {Page: 1, Row: 1, Column: 2, ListRow: 1, IconCel: 0},
60: {Page: 3, Row: 5, Column: 3, ListRow: 3, IconCel: 48},
61: {Page: 1, Row: 6, Column: 2, ListRow: 1, IconCel: 50},
62: {Page: 1, Row: 6, Column: 3, ListRow: 1, IconCel: 52},
63: {Page: 2, Row: 6, Column: 2, ListRow: 2, IconCel: 54},
64: {Page: 3, Row: 6, Column: 1, ListRow: 3, IconCel: 56},
65: {Page: 3, Row: 6, Column: 2, ListRow: 3, IconCel: 58},
66: {Page: 1, Row: 1, Column: 2, ListRow: 1, IconCel: 0},
67: {Page: 2, Row: 1, Column: 2, ListRow: 2, IconCel: 2},
68: {Page: 2, Row: 1, Column: 3, ListRow: 2, IconCel: 4},
69: {Page: 3, Row: 1, Column: 1, ListRow: 3, IconCel: 6},
7: {Page: 1, Row: 1, Column: 3, ListRow: 1, IconCel: 2},
70: {Page: 3, Row: 1, Column: 3, ListRow: 3, IconCel: 8},
71: {Page: 1, Row: 2, Column: 1, ListRow: 1, IconCel: 10},
72: {Page: 1, Row: 2, Column: 3, ListRow: 1, IconCel: 12},
73: {Page: 2, Row: 2, Column: 1, ListRow: 2, IconCel: 14},
74: {Page: 2, Row: 2, Column: 2, ListRow: 2, IconCel: 16},
75: {Page: 3, Row: 2, Column: 2, ListRow: 3, IconCel: 18},
76: {Page: 1, Row: 3, Column: 2, ListRow: 1, IconCel: 20},
77: {Page: 1, Row: 3, Column: 3, ListRow: 1, IconCel: 22},
78: {Page: 2, Row: 3, Column: 3, ListRow: 2, IconCel: 24},
79: {Page: 3, Row: 3, Column: 1, ListRow: 3, IconCel: 26},
8: {Page: 2, Row: 1, Column: 1, ListRow: 2, IconCel: 4},
80: {Page: 3, Row: 3, Column: 3, ListRow: 3, IconCel: 28},
81: {Page: 1, Row: 4, Column: 1, ListRow: 1, IconCel: 30},
82: {Page: 1, Row: 4, Column: 2, ListRow: 1, IconCel: 32},
83: {Page: 2, Row: 4, Column: 1, ListRow: 2, IconCel: 34},
84: {Page: 2, Row: 4, Column: 2, ListRow: 2, IconCel: 36},
85: {Page: 3, Row: 4, Column: 2, ListRow: 3, IconCel: 38},
86: {Page: 1, Row: 5, Column: 1, ListRow: 1, IconCel: 40},
87: {Page: 1, Row: 5, Column: 3, ListRow: 1, IconCel: 42},
88: {Page: 2, Row: 5, Column: 3, ListRow: 2, IconCel: 44},
89: {Page: 3, Row: 5, Column: 1, ListRow: 3, IconCel: 46},
9: {Page: 2, Row: 1, Column: 3, ListRow: 2, IconCel: 6},
90: {Page: 3, Row: 5, Column: 2, ListRow: 3, IconCel: 48},
91: {Page: 1, Row: 6, Column: 2, ListRow: 1, IconCel: 50},
92: {Page: 2, Row: 6, Column: 1, ListRow: 2, IconCel: 52},
93: {Page: 2, Row: 6, Column: 2, ListRow: 2, IconCel: 54},
94: {Page: 3, Row: 6, Column: 2, ListRow: 3, IconCel: 56},
95: {Page: 3, Row: 6, Column: 3, ListRow: 3, IconCel: 58},
96: {Page: 1, Row: 1, Column: 1, ListRow: 1, IconCel: 0},
97: {Page: 1, Row: 1, Column: 3, ListRow: 1, IconCel: 2},
98: {Page: 2, Row: 1, Column: 1, ListRow: 2, IconCel: 4},
99: {Page: 3, Row: 1, Column: 1, ListRow: 3, IconCel: 6},
}

View File

@@ -1,365 +1,379 @@
// Code generated by d2data. DO NOT EDIT.
// source: cmd/d2data/d2data/skills.json
package skill package skill
type Skill int16 var Skills = map[ID]Skill{
0: {Name: "Attack", ID: 0, LeftSkill: true, RightSkill: true},
const ( 1: {Name: "Kick", ID: 1, LeftSkill: false, RightSkill: false},
AttackSkill Skill = iota 10: {Name: "Jab", ID: 10, LeftSkill: true, RightSkill: true},
Kick 100: {Name: "Resist Fire", ID: 100, LeftSkill: false, RightSkill: true},
Throw 101: {Name: "Holy Bolt", ID: 101, LeftSkill: true, RightSkill: true},
Unsummon 102: {Name: "Holy Fire", ID: 102, LeftSkill: false, RightSkill: true},
LeftHandThrow 103: {Name: "Thorns", ID: 103, LeftSkill: false, RightSkill: true},
LeftHandSwing 104: {Name: "Defiance", ID: 104, LeftSkill: false, RightSkill: true},
MagicArrow 105: {Name: "Resist Cold", ID: 105, LeftSkill: false, RightSkill: true},
FireArrow 106: {Name: "Zeal", ID: 106, LeftSkill: true, RightSkill: true},
InnerSight 107: {Name: "Charge", ID: 107, LeftSkill: true, RightSkill: true},
CriticalStrike 108: {Name: "Blessed Aim", ID: 108, LeftSkill: false, RightSkill: true},
Jab 109: {Name: "Cleansing", ID: 109, LeftSkill: false, RightSkill: true},
ColdArrow 11: {Name: "Cold Arrow", ID: 11, LeftSkill: true, RightSkill: true},
MultipleShot 110: {Name: "Resist Lightning", ID: 110, LeftSkill: false, RightSkill: true},
Dodge 111: {Name: "Vengeance", ID: 111, LeftSkill: true, RightSkill: true},
PowerStrike 112: {Name: "Blessed Hammer", ID: 112, LeftSkill: true, RightSkill: true},
PoisonJavelin 113: {Name: "Concentration", ID: 113, LeftSkill: false, RightSkill: true},
ExplodingArrow 114: {Name: "Holy Freeze", ID: 114, LeftSkill: false, RightSkill: true},
SlowMissiles 115: {Name: "Vigor", ID: 115, LeftSkill: false, RightSkill: true},
Avoid 116: {Name: "Conversion", ID: 116, LeftSkill: true, RightSkill: true},
Impale 117: {Name: "Holy Shield", ID: 117, LeftSkill: false, RightSkill: true},
LightningBolt 118: {Name: "Holy Shock", ID: 118, LeftSkill: false, RightSkill: true},
IceArrow 119: {Name: "Sanctuary", ID: 119, LeftSkill: false, RightSkill: true},
GuidedArrow 12: {Name: "Multiple Shot", ID: 12, LeftSkill: true, RightSkill: true},
Penetrate 120: {Name: "Meditation", ID: 120, LeftSkill: false, RightSkill: true},
ChargedStrike 121: {Name: "Fist of the Heavens", ID: 121, LeftSkill: true, RightSkill: true},
PlagueJavelin 122: {Name: "Fanaticism", ID: 122, LeftSkill: false, RightSkill: true},
Strafe 123: {Name: "Conviction", ID: 123, LeftSkill: false, RightSkill: true},
ImmolationArrow 124: {Name: "Redemption", ID: 124, LeftSkill: false, RightSkill: true},
Decoy 125: {Name: "Salvation", ID: 125, LeftSkill: false, RightSkill: true},
Evade 126: {Name: "Bash", ID: 126, LeftSkill: true, RightSkill: true},
Fend 127: {Name: "Blade Mastery", ID: 127, LeftSkill: false, RightSkill: false},
FreezingArrow 128: {Name: "Axe Mastery", ID: 128, LeftSkill: false, RightSkill: false},
Valkyrie 129: {Name: "Mace Mastery", ID: 129, LeftSkill: false, RightSkill: false},
Pierce 13: {Name: "Dodge", ID: 13, LeftSkill: false, RightSkill: false},
LightningStrike 130: {Name: "Howl", ID: 130, LeftSkill: false, RightSkill: true},
LightningFury 131: {Name: "Find Potion", ID: 131, LeftSkill: false, RightSkill: true},
FireBolt 132: {Name: "Leap", ID: 132, LeftSkill: true, RightSkill: true},
Warmth 133: {Name: "Double Swing", ID: 133, LeftSkill: true, RightSkill: true},
ChargedBolt 134: {Name: "Pole Arm Mastery", ID: 134, LeftSkill: false, RightSkill: false},
IceBolt 135: {Name: "Throwing Mastery", ID: 135, LeftSkill: false, RightSkill: false},
FrozenArmor 136: {Name: "Spear Mastery", ID: 136, LeftSkill: false, RightSkill: false},
Inferno 137: {Name: "Taunt", ID: 137, LeftSkill: false, RightSkill: true},
StaticField 138: {Name: "Shout", ID: 138, LeftSkill: false, RightSkill: true},
Telekinesis 139: {Name: "Stun", ID: 139, LeftSkill: true, RightSkill: true},
FrostNova 14: {Name: "Power Strike", ID: 14, LeftSkill: true, RightSkill: true},
IceBlast 140: {Name: "Double Throw", ID: 140, LeftSkill: true, RightSkill: true},
Blaze 141: {Name: "Increased Stamina", ID: 141, LeftSkill: false, RightSkill: false},
FireBall 142: {Name: "Find Item", ID: 142, LeftSkill: false, RightSkill: true},
Nova 143: {Name: "Leap Attack", ID: 143, LeftSkill: true, RightSkill: true},
Lightning 144: {Name: "Concentrate", ID: 144, LeftSkill: true, RightSkill: true},
ShiverArmor 145: {Name: "Iron Skin", ID: 145, LeftSkill: false, RightSkill: false},
FireWall 146: {Name: "Battle Cry", ID: 146, LeftSkill: false, RightSkill: true},
Enchant 147: {Name: "Frenzy", ID: 147, LeftSkill: true, RightSkill: true},
ChainLightning 148: {Name: "Increased Speed", ID: 148, LeftSkill: false, RightSkill: false},
Teleport 149: {Name: "Battle Orders", ID: 149, LeftSkill: false, RightSkill: true},
GlacialSpike 15: {Name: "Poison Javelin", ID: 15, LeftSkill: true, RightSkill: true},
Meteor 150: {Name: "Grim Ward", ID: 150, LeftSkill: false, RightSkill: true},
ThunderStorm 151: {Name: "Whirlwind", ID: 151, LeftSkill: true, RightSkill: true},
EnergyShield 152: {Name: "Berserk", ID: 152, LeftSkill: true, RightSkill: true},
Blizzard 153: {Name: "Natural Resistance", ID: 153, LeftSkill: false, RightSkill: false},
ChillingArmor 154: {Name: "War Cry", ID: 154, LeftSkill: false, RightSkill: true},
FireMastery 155: {Name: "Battle Command", ID: 155, LeftSkill: false, RightSkill: true},
Hydra 156: {Name: "Fire Hit", ID: 156, LeftSkill: false, RightSkill: false},
LightningMastery 157: {Name: "UnHolyBolt", ID: 157, LeftSkill: false, RightSkill: false},
FrozenOrb 158: {Name: "SkeletonRaise", ID: 158, LeftSkill: false, RightSkill: false},
ColdMastery 159: {Name: "MaggotEgg", ID: 159, LeftSkill: false, RightSkill: false},
AmplifyDamage 16: {Name: "Exploding Arrow", ID: 16, LeftSkill: true, RightSkill: true},
Teeth 160: {Name: "ShamanFire", ID: 160, LeftSkill: false, RightSkill: false},
BoneArmor 161: {Name: "MagottUp", ID: 161, LeftSkill: false, RightSkill: false},
SkeletonMastery 162: {Name: "MagottDown", ID: 162, LeftSkill: false, RightSkill: false},
RaiseSkeleton 163: {Name: "MagottLay", ID: 163, LeftSkill: false, RightSkill: false},
DimVision 164: {Name: "AndrialSpray", ID: 164, LeftSkill: false, RightSkill: false},
Weaken 165: {Name: "Jump", ID: 165, LeftSkill: false, RightSkill: false},
PoisonDagger 166: {Name: "Swarm Move", ID: 166, LeftSkill: false, RightSkill: false},
CorpseExplosion 167: {Name: "Nest", ID: 167, LeftSkill: false, RightSkill: false},
ClayGolem 168: {Name: "Quick Strike", ID: 168, LeftSkill: false, RightSkill: false},
IronMaiden 169: {Name: "VampireFireball", ID: 169, LeftSkill: false, RightSkill: false},
Terror 17: {Name: "Slow Missiles", ID: 17, LeftSkill: false, RightSkill: true},
BoneWall 170: {Name: "VampireFirewall", ID: 170, LeftSkill: false, RightSkill: false},
GolemMastery 171: {Name: "VampireMeteor", ID: 171, LeftSkill: false, RightSkill: false},
RaiseSkeletalMage 172: {Name: "GargoyleTrap", ID: 172, LeftSkill: false, RightSkill: false},
Confuse 173: {Name: "SpiderLay", ID: 173, LeftSkill: false, RightSkill: false},
LifeTap 174: {Name: "VampireHeal", ID: 174, LeftSkill: false, RightSkill: false},
PoisonExplosion 175: {Name: "VampireRaise", ID: 175, LeftSkill: false, RightSkill: false},
BoneSpear 176: {Name: "Submerge", ID: 176, LeftSkill: false, RightSkill: false},
BloodGolem 177: {Name: "FetishAura", ID: 177, LeftSkill: false, RightSkill: false},
Attract 178: {Name: "FetishInferno", ID: 178, LeftSkill: false, RightSkill: false},
Decrepify 179: {Name: "ZakarumHeal", ID: 179, LeftSkill: false, RightSkill: false},
BonePrison 18: {Name: "Avoid", ID: 18, LeftSkill: false, RightSkill: false},
SummonResist 180: {Name: "Emerge", ID: 180, LeftSkill: false, RightSkill: false},
IronGolem 181: {Name: "Resurrect", ID: 181, LeftSkill: false, RightSkill: false},
LowerResist 182: {Name: "Bestow", ID: 182, LeftSkill: false, RightSkill: false},
PoisonNova 183: {Name: "MissileSkill1", ID: 183, LeftSkill: false, RightSkill: false},
BoneSpirit 184: {Name: "MonTeleport", ID: 184, LeftSkill: false, RightSkill: false},
FireGolem 185: {Name: "PrimeLightning", ID: 185, LeftSkill: false, RightSkill: false},
Revive 186: {Name: "PrimeBolt", ID: 186, LeftSkill: false, RightSkill: false},
Sacrifice 187: {Name: "PrimeBlaze", ID: 187, LeftSkill: false, RightSkill: false},
Smite 188: {Name: "PrimeFirewall", ID: 188, LeftSkill: false, RightSkill: false},
Might 189: {Name: "PrimeSpike", ID: 189, LeftSkill: false, RightSkill: false},
Prayer 19: {Name: "Impale", ID: 19, LeftSkill: true, RightSkill: true},
ResistFire 190: {Name: "PrimeIceNova", ID: 190, LeftSkill: false, RightSkill: false},
HolyBolt 191: {Name: "PrimePoisonball", ID: 191, LeftSkill: false, RightSkill: false},
HolyFire 192: {Name: "PrimePoisonNova", ID: 192, LeftSkill: false, RightSkill: false},
Thorns 193: {Name: "DiabLight", ID: 193, LeftSkill: false, RightSkill: false},
Defiance 194: {Name: "DiabCold", ID: 194, LeftSkill: false, RightSkill: false},
ResistCold 195: {Name: "DiabFire", ID: 195, LeftSkill: false, RightSkill: false},
Zeal 196: {Name: "FingerMageSpider", ID: 196, LeftSkill: false, RightSkill: false},
Charge 197: {Name: "DiabWall", ID: 197, LeftSkill: false, RightSkill: false},
BlessedAim 198: {Name: "DiabRun", ID: 198, LeftSkill: false, RightSkill: false},
Cleansing 199: {Name: "DiabPrison", ID: 199, LeftSkill: false, RightSkill: false},
ResistLightning 2: {Name: "Throw", ID: 2, LeftSkill: true, RightSkill: true},
Vengeance 20: {Name: "Lightning Bolt", ID: 20, LeftSkill: true, RightSkill: true},
BlessedHammer 200: {Name: "PoisonBallTrap", ID: 200, LeftSkill: false, RightSkill: false},
Concentration 201: {Name: "AndyPoisonBolt", ID: 201, LeftSkill: false, RightSkill: false},
HolyFreeze 202: {Name: "HireableMissile", ID: 202, LeftSkill: false, RightSkill: false},
Vigor 203: {Name: "DesertTurret", ID: 203, LeftSkill: false, RightSkill: false},
Conversion 204: {Name: "ArcaneTower", ID: 204, LeftSkill: false, RightSkill: false},
HolyShield 205: {Name: "MonBlizzard", ID: 205, LeftSkill: false, RightSkill: false},
HolyShock 206: {Name: "Mosquito", ID: 206, LeftSkill: false, RightSkill: false},
Sanctuary 207: {Name: "CursedBallTrapRight", ID: 207, LeftSkill: false, RightSkill: false},
Meditation 208: {Name: "CursedBallTrapLeft", ID: 208, LeftSkill: false, RightSkill: false},
FistOfTheHeavens 209: {Name: "MonFrozenArmor", ID: 209, LeftSkill: false, RightSkill: false},
Fanaticism 21: {Name: "Ice Arrow", ID: 21, LeftSkill: true, RightSkill: true},
Conviction 210: {Name: "MonBoneArmor", ID: 210, LeftSkill: false, RightSkill: false},
Redemption 211: {Name: "MonBoneSpirit", ID: 211, LeftSkill: false, RightSkill: false},
Salvation 212: {Name: "MonCurseCast", ID: 212, LeftSkill: false, RightSkill: false},
Bash 213: {Name: "HellMeteor", ID: 213, LeftSkill: false, RightSkill: false},
BladeMastery 214: {Name: "RegurgitatorEat", ID: 214, LeftSkill: false, RightSkill: false},
AxeMastery 215: {Name: "MonFrenzy", ID: 215, LeftSkill: false, RightSkill: false},
MaceMastery 216: {Name: "QueenDeath", ID: 216, LeftSkill: false, RightSkill: false},
Howl 217: {Name: "Scroll of Identify", ID: 217, LeftSkill: false, RightSkill: true},
FindPotion 218: {Name: "Book of Identify", ID: 218, LeftSkill: false, RightSkill: true},
Leap 219: {Name: "Scroll of Townportal", ID: 219, LeftSkill: false, RightSkill: true},
DoubleSwing 22: {Name: "Guided Arrow", ID: 22, LeftSkill: true, RightSkill: true},
PolearmMastery 220: {Name: "Book of Townportal", ID: 220, LeftSkill: false, RightSkill: true},
ThrowingMastery 221: {Name: "Raven", ID: 221, LeftSkill: false, RightSkill: true},
SpearMastery 222: {Name: "Plague Poppy", ID: 222, LeftSkill: false, RightSkill: true},
Taunt 223: {Name: "Wearwolf", ID: 223, LeftSkill: false, RightSkill: true},
Shout 224: {Name: "Shape Shifting", ID: 224, LeftSkill: false, RightSkill: false},
Stun 225: {Name: "Firestorm", ID: 225, LeftSkill: true, RightSkill: true},
DoubleThrow 226: {Name: "Oak Sage", ID: 226, LeftSkill: false, RightSkill: true},
IncreasedStamina 227: {Name: "Summon Spirit Wolf", ID: 227, LeftSkill: false, RightSkill: true},
FindItem 228: {Name: "Wearbear", ID: 228, LeftSkill: false, RightSkill: true},
LeapAttack 229: {Name: "Molten Boulder", ID: 229, LeftSkill: true, RightSkill: true},
Concentrate 23: {Name: "Penetrate", ID: 23, LeftSkill: false, RightSkill: false},
IronSkin 230: {Name: "Arctic Blast", ID: 230, LeftSkill: true, RightSkill: true},
BattleCry 231: {Name: "Cycle of Life", ID: 231, LeftSkill: false, RightSkill: true},
Frenzy 232: {Name: "Feral Rage", ID: 232, LeftSkill: true, RightSkill: true},
IncreasedSpeed 233: {Name: "Maul", ID: 233, LeftSkill: true, RightSkill: true},
BattleOrders 234: {Name: "Eruption", ID: 234, LeftSkill: false, RightSkill: true},
GrimWard 235: {Name: "Cyclone Armor", ID: 235, LeftSkill: false, RightSkill: true},
Whirlwind 236: {Name: "Heart of Wolverine", ID: 236, LeftSkill: false, RightSkill: true},
Berserk 237: {Name: "Summon Fenris", ID: 237, LeftSkill: false, RightSkill: true},
NaturalResistance 238: {Name: "Rabies", ID: 238, LeftSkill: true, RightSkill: true},
WarCry 239: {Name: "Fire Claws", ID: 239, LeftSkill: true, RightSkill: true},
BattleCommand 24: {Name: "Charged Strike", ID: 24, LeftSkill: true, RightSkill: true},
FireHit 240: {Name: "Twister", ID: 240, LeftSkill: true, RightSkill: true},
UnHolyBolt 241: {Name: "Vines", ID: 241, LeftSkill: false, RightSkill: true},
SkeletonRaise 242: {Name: "Hunger", ID: 242, LeftSkill: true, RightSkill: true},
MaggotEgg 243: {Name: "Shock Wave", ID: 243, LeftSkill: true, RightSkill: true},
ShamanFire 244: {Name: "Volcano", ID: 244, LeftSkill: false, RightSkill: true},
MagottUp 245: {Name: "Tornado", ID: 245, LeftSkill: true, RightSkill: true},
MagottDown 246: {Name: "Spirit of Barbs", ID: 246, LeftSkill: false, RightSkill: true},
MagottLay 247: {Name: "Summon Grizzly", ID: 247, LeftSkill: false, RightSkill: true},
AndrialSpray 248: {Name: "Fury", ID: 248, LeftSkill: true, RightSkill: true},
Jump 249: {Name: "Armageddon", ID: 249, LeftSkill: false, RightSkill: true},
SwarmMove 25: {Name: "Plague Javelin", ID: 25, LeftSkill: true, RightSkill: true},
Nest 250: {Name: "Hurricane", ID: 250, LeftSkill: false, RightSkill: true},
QuickStrike 251: {Name: "Fire Trauma", ID: 251, LeftSkill: true, RightSkill: true},
VampireFireball 252: {Name: "Claw Mastery", ID: 252, LeftSkill: false, RightSkill: false},
VampireFirewall 253: {Name: "Psychic Hammer", ID: 253, LeftSkill: false, RightSkill: true},
VampireMeteor 254: {Name: "Tiger Strike", ID: 254, LeftSkill: true, RightSkill: true},
GargoyleTrap 255: {Name: "Dragon Talon", ID: 255, LeftSkill: true, RightSkill: true},
SpiderLay 256: {Name: "Shock Field", ID: 256, LeftSkill: true, RightSkill: true},
VampireHeal 257: {Name: "Blade Sentinel", ID: 257, LeftSkill: true, RightSkill: true},
VampireRaise 258: {Name: "Quickness", ID: 258, LeftSkill: false, RightSkill: true},
Submerge 259: {Name: "Fists of Fire", ID: 259, LeftSkill: true, RightSkill: true},
FetishAura 26: {Name: "Strafe", ID: 26, LeftSkill: true, RightSkill: true},
FetishInferno 260: {Name: "Dragon Claw", ID: 260, LeftSkill: true, RightSkill: true},
ZakarumHeal 261: {Name: "Charged Bolt Sentry", ID: 261, LeftSkill: false, RightSkill: true},
Emerge 262: {Name: "Wake of Fire Sentry", ID: 262, LeftSkill: false, RightSkill: true},
Resurrect 263: {Name: "Weapon Block", ID: 263, LeftSkill: false, RightSkill: false},
Bestow 264: {Name: "Cloak of Shadows", ID: 264, LeftSkill: false, RightSkill: true},
MissileSkill1 265: {Name: "Cobra Strike", ID: 265, LeftSkill: true, RightSkill: true},
MonTeleport 266: {Name: "Blade Fury", ID: 266, LeftSkill: true, RightSkill: true},
PrimeLightning 267: {Name: "Fade", ID: 267, LeftSkill: false, RightSkill: true},
PrimeBolt 268: {Name: "Shadow Warrior", ID: 268, LeftSkill: false, RightSkill: true},
PrimeBlaze 269: {Name: "Claws of Thunder", ID: 269, LeftSkill: true, RightSkill: true},
PrimeFirewall 27: {Name: "Immolation Arrow", ID: 27, LeftSkill: true, RightSkill: true},
PrimeSpike 270: {Name: "Dragon Tail", ID: 270, LeftSkill: true, RightSkill: true},
PrimeIceNova 271: {Name: "Lightning Sentry", ID: 271, LeftSkill: false, RightSkill: true},
PrimePoisonball 272: {Name: "Inferno Sentry", ID: 272, LeftSkill: false, RightSkill: true},
PrimePoisonNova 273: {Name: "Mind Blast", ID: 273, LeftSkill: false, RightSkill: true},
DiabLight 274: {Name: "Blades of Ice", ID: 274, LeftSkill: true, RightSkill: true},
DiabCold 275: {Name: "Dragon Flight", ID: 275, LeftSkill: true, RightSkill: true},
DiabFire 276: {Name: "Death Sentry", ID: 276, LeftSkill: false, RightSkill: true},
FingerMageSpider 277: {Name: "Blade Shield", ID: 277, LeftSkill: false, RightSkill: true},
DiabWall 278: {Name: "Venom", ID: 278, LeftSkill: false, RightSkill: true},
DiabRun 279: {Name: "Shadow Master", ID: 279, LeftSkill: false, RightSkill: true},
DiabPrison 28: {Name: "Dopplezon", ID: 28, LeftSkill: false, RightSkill: true},
PoisonBallTrap 280: {Name: "Royal Strike", ID: 280, LeftSkill: true, RightSkill: true},
AndyPoisonBolt 281: {Name: "Wake Of Destruction Sentry", ID: 281, LeftSkill: false, RightSkill: false},
HireableMissile 282: {Name: "Imp Inferno", ID: 282, LeftSkill: false, RightSkill: false},
DesertTurret 283: {Name: "Imp Fireball", ID: 283, LeftSkill: false, RightSkill: false},
ArcaneTower 284: {Name: "Baal Taunt", ID: 284, LeftSkill: false, RightSkill: false},
MonBlizzard 285: {Name: "Baal Corpse Explode", ID: 285, LeftSkill: false, RightSkill: false},
Mosquito 286: {Name: "Baal Monster Spawn", ID: 286, LeftSkill: false, RightSkill: false},
CursedBallTrapRight 287: {Name: "Catapult Charged Ball", ID: 287, LeftSkill: false, RightSkill: false},
CursedBallTrapLeft 288: {Name: "Catapult Spike Ball", ID: 288, LeftSkill: false, RightSkill: false},
MonFrozenArmor 289: {Name: "Suck Blood", ID: 289, LeftSkill: false, RightSkill: false},
MonBoneArmor 29: {Name: "Evade", ID: 29, LeftSkill: false, RightSkill: false},
MonBoneSpirit 290: {Name: "Cry Help", ID: 290, LeftSkill: false, RightSkill: false},
MonCurseCast 291: {Name: "Healing Vortex", ID: 291, LeftSkill: false, RightSkill: false},
HellMeteor 292: {Name: "Teleport 2", ID: 292, LeftSkill: false, RightSkill: false},
RegurgitatorEat 293: {Name: "Self-resurrect", ID: 293, LeftSkill: false, RightSkill: false},
MonFrenzy 294: {Name: "Vine Attack", ID: 294, LeftSkill: false, RightSkill: false},
QueenDeath 295: {Name: "Overseer Whip", ID: 295, LeftSkill: false, RightSkill: false},
ScrollOfIdentify 296: {Name: "Barbs Aura", ID: 296, LeftSkill: false, RightSkill: false},
TomeOfIdentify 297: {Name: "Wolverine Aura", ID: 297, LeftSkill: false, RightSkill: false},
ScrollOfTownPortal 298: {Name: "Oak Sage Aura", ID: 298, LeftSkill: false, RightSkill: false},
TomeOfTownPortal 299: {Name: "Imp Fire Missile", ID: 299, LeftSkill: false, RightSkill: false},
Raven 3: {Name: "Unsummon", ID: 3, LeftSkill: false, RightSkill: true},
PoisonCreeper 30: {Name: "Fend", ID: 30, LeftSkill: true, RightSkill: true},
Werewolf 300: {Name: "Impregnate", ID: 300, LeftSkill: false, RightSkill: false},
Lycanthropy 301: {Name: "Siege Beast Stomp", ID: 301, LeftSkill: false, RightSkill: false},
Firestorm 302: {Name: "MinionSpawner", ID: 302, LeftSkill: false, RightSkill: false},
OakSage 303: {Name: "CatapultBlizzard", ID: 303, LeftSkill: false, RightSkill: false},
SummonSpiritWolf 304: {Name: "CatapultPlague", ID: 304, LeftSkill: false, RightSkill: false},
Werebear 305: {Name: "CatapultMeteor", ID: 305, LeftSkill: false, RightSkill: false},
MoltenBoulder 306: {Name: "BoltSentry", ID: 306, LeftSkill: false, RightSkill: false},
ArcticBlast 307: {Name: "CorpseCycler", ID: 307, LeftSkill: false, RightSkill: false},
CarrionVine 308: {Name: "DeathMaul", ID: 308, LeftSkill: false, RightSkill: false},
FeralRage 309: {Name: "Defense Curse", ID: 309, LeftSkill: false, RightSkill: false},
Maul 31: {Name: "Freezing Arrow", ID: 31, LeftSkill: true, RightSkill: true},
Fissure 310: {Name: "Blood Mana", ID: 310, LeftSkill: false, RightSkill: false},
CycloneArmor 311: {Name: "mon inferno sentry", ID: 311, LeftSkill: false, RightSkill: false},
HeartOfWolverine 312: {Name: "mon death sentry", ID: 312, LeftSkill: false, RightSkill: false},
SummonDireWolf 313: {Name: "sentry lightning", ID: 313, LeftSkill: false, RightSkill: false},
Rabies 314: {Name: "fenris rage", ID: 314, LeftSkill: false, RightSkill: false},
FireClaws 315: {Name: "Baal Tentacle", ID: 315, LeftSkill: false, RightSkill: false},
Twister 316: {Name: "Baal Nova", ID: 316, LeftSkill: false, RightSkill: false},
SolarCreeper 317: {Name: "Baal Inferno", ID: 317, LeftSkill: false, RightSkill: false},
Hunger 318: {Name: "Baal Cold Missiles", ID: 318, LeftSkill: false, RightSkill: false},
ShockWave 319: {Name: "MegademonInferno", ID: 319, LeftSkill: false, RightSkill: false},
Volcano 32: {Name: "Valkyrie", ID: 32, LeftSkill: false, RightSkill: true},
Tornado 320: {Name: "EvilHutSpawner", ID: 320, LeftSkill: false, RightSkill: false},
SpiritOfBarbs 321: {Name: "CountessFirewall", ID: 321, LeftSkill: false, RightSkill: false},
SummonGrizzly 322: {Name: "ImpBolt", ID: 322, LeftSkill: false, RightSkill: false},
Fury 323: {Name: "Horror Arctic Blast", ID: 323, LeftSkill: false, RightSkill: false},
Armageddon 324: {Name: "death sentry ltng", ID: 324, LeftSkill: false, RightSkill: false},
Hurricane 325: {Name: "VineCycler", ID: 325, LeftSkill: false, RightSkill: false},
FireBlast 326: {Name: "BearSmite", ID: 326, LeftSkill: false, RightSkill: false},
ClawMastery 327: {Name: "Resurrect2", ID: 327, LeftSkill: false, RightSkill: false},
PsychicHammer 328: {Name: "BloodLordFrenzy", ID: 328, LeftSkill: false, RightSkill: false},
TigerStrike 329: {Name: "Baal Teleport", ID: 329, LeftSkill: false, RightSkill: false},
DragonTalon 33: {Name: "Pierce", ID: 33, LeftSkill: false, RightSkill: false},
ShockWeb 330: {Name: "Imp Teleport", ID: 330, LeftSkill: false, RightSkill: false},
BladeSentinel 331: {Name: "Baal Clone Teleport", ID: 331, LeftSkill: false, RightSkill: false},
BurstOfSpeed 332: {Name: "ZakarumLightning", ID: 332, LeftSkill: false, RightSkill: false},
FistsOfFire 333: {Name: "VampireMissile", ID: 333, LeftSkill: false, RightSkill: false},
DragonClaw 334: {Name: "MephistoMissile", ID: 334, LeftSkill: false, RightSkill: false},
ChargedBoltSentry 335: {Name: "DoomKnightMissile", ID: 335, LeftSkill: false, RightSkill: false},
WakeOfFire 336: {Name: "RogueMissile", ID: 336, LeftSkill: false, RightSkill: false},
WeaponBlock 337: {Name: "HydraMissile", ID: 337, LeftSkill: false, RightSkill: false},
CloakOfShadows 338: {Name: "NecromageMissile", ID: 338, LeftSkill: false, RightSkill: false},
CobraStrike 339: {Name: "MonBow", ID: 339, LeftSkill: false, RightSkill: false},
BladeFury 34: {Name: "Lightning Strike", ID: 34, LeftSkill: true, RightSkill: true},
Fade 340: {Name: "MonFireArrow", ID: 340, LeftSkill: false, RightSkill: false},
ShadowWarrior 341: {Name: "MonColdArrow", ID: 341, LeftSkill: false, RightSkill: false},
ClawsOfThunder 342: {Name: "MonExplodingArrow", ID: 342, LeftSkill: false, RightSkill: false},
DragonTail 343: {Name: "MonFreezingArrow", ID: 343, LeftSkill: false, RightSkill: false},
LightningSentry 344: {Name: "MonPowerStrike", ID: 344, LeftSkill: false, RightSkill: false},
WakeOfInferno 345: {Name: "SuccubusBolt", ID: 345, LeftSkill: false, RightSkill: false},
MindBlast 346: {Name: "MephFrostNova", ID: 346, LeftSkill: false, RightSkill: false},
BladesOfIce 347: {Name: "MonIceSpear", ID: 347, LeftSkill: false, RightSkill: false},
DragonFlight 348: {Name: "ShamanIce", ID: 348, LeftSkill: false, RightSkill: false},
DeathSentry 349: {Name: "Diablogeddon", ID: 349, LeftSkill: false, RightSkill: false},
BladeShield 35: {Name: "Lightning Fury", ID: 35, LeftSkill: true, RightSkill: true},
Venom 350: {Name: "Delerium Change", ID: 350, LeftSkill: false, RightSkill: false},
ShadowMaster 351: {Name: "NihlathakCorpseExplosion", ID: 351, LeftSkill: false, RightSkill: false},
PhoenixStrike 352: {Name: "SerpentCharge", ID: 352, LeftSkill: false, RightSkill: false},
WakeOfDestructionSentry 353: {Name: "Trap Nova", ID: 353, LeftSkill: false, RightSkill: false},
ImpInferno 354: {Name: "UnHolyBoltEx", ID: 354, LeftSkill: false, RightSkill: false},
ImpFireball 355: {Name: "ShamanFireEx", ID: 355, LeftSkill: false, RightSkill: false},
BaalTaunt 356: {Name: "Imp Fire Missile Ex", ID: 356, LeftSkill: false, RightSkill: false},
BaalCorpseExplode 357: {Name: "Interact", ID: 357, LeftSkill: false, RightSkill: false},
BaalMonsterSpawn 358: {Name: "Loot", ID: 358, LeftSkill: false, RightSkill: false},
CatapultChargedBall 359: {Name: "TownPortal", ID: 359, LeftSkill: false, RightSkill: false},
CatapultSpikeBall 36: {Name: "Fire Bolt", ID: 36, LeftSkill: true, RightSkill: true},
SuckBlood 360: {Name: "EmoteWheel", ID: 360, LeftSkill: false, RightSkill: false},
CryHelp 361: {Name: "SwapWeapons", ID: 361, LeftSkill: false, RightSkill: false},
HealingVortex 362: {Name: "", ID: 362, LeftSkill: false, RightSkill: false},
Teleport2 363: {Name: "ShowItems", ID: 363, LeftSkill: false, RightSkill: false},
SelfResurrect 364: {Name: "RunToggle", ID: 364, LeftSkill: false, RightSkill: false},
VineAttack 365: {Name: "MonHolyFreeze", ID: 365, LeftSkill: false, RightSkill: true},
OverseerWhip 366: {Name: "MonLeap", ID: 366, LeftSkill: false, RightSkill: false},
BarbsAura 367: {Name: "MonLeapAttack", ID: 367, LeftSkill: false, RightSkill: false},
WolverineAura 368: {Name: "MonHolyFire", ID: 368, LeftSkill: false, RightSkill: true},
OakSageAura 369: {Name: "MonHolyShock", ID: 369, LeftSkill: false, RightSkill: true},
ImpFireMissile 37: {Name: "Warmth", ID: 37, LeftSkill: false, RightSkill: false},
Impregnate 370: {Name: "CubeLoot", ID: 370, LeftSkill: false, RightSkill: false},
SiegeBeastStomp 371: {Name: "Mark of the Bear", ID: 371, LeftSkill: false, RightSkill: false},
MinionSpawner 372: {Name: "Mark of the Wolf", ID: 372, LeftSkill: false, RightSkill: false},
CatapultBlizzard 38: {Name: "Charged Bolt", ID: 38, LeftSkill: true, RightSkill: true},
CatapultPlague 39: {Name: "Ice Bolt", ID: 39, LeftSkill: true, RightSkill: true},
CatapultMeteor 4: {Name: "Left Hand Throw", ID: 4, LeftSkill: true, RightSkill: true},
BoltSentry 40: {Name: "Frozen Armor", ID: 40, LeftSkill: false, RightSkill: true},
CorpseCycler 41: {Name: "Inferno", ID: 41, LeftSkill: true, RightSkill: true},
DeathMaul 42: {Name: "Static Field", ID: 42, LeftSkill: false, RightSkill: true},
DefenseCurse 43: {Name: "Telekinesis", ID: 43, LeftSkill: false, RightSkill: true},
BloodMana 44: {Name: "Frost Nova", ID: 44, LeftSkill: false, RightSkill: true},
monInfernoSentry 45: {Name: "Ice Blast", ID: 45, LeftSkill: true, RightSkill: true},
monDeathSentry 46: {Name: "Blaze", ID: 46, LeftSkill: false, RightSkill: true},
sentryLightning 47: {Name: "Fire Ball", ID: 47, LeftSkill: true, RightSkill: true},
fenrisRage 48: {Name: "Nova", ID: 48, LeftSkill: false, RightSkill: true},
BaalTentacle 49: {Name: "Lightning", ID: 49, LeftSkill: true, RightSkill: true},
BaalNova 5: {Name: "Left Hand Swing", ID: 5, LeftSkill: false, RightSkill: false},
BaalInferno 50: {Name: "Shiver Armor", ID: 50, LeftSkill: false, RightSkill: true},
BaalColdMissiles 51: {Name: "Fire Wall", ID: 51, LeftSkill: false, RightSkill: true},
MegademonInferno 52: {Name: "Enchant", ID: 52, LeftSkill: false, RightSkill: true},
EvilHutSpawner 53: {Name: "Chain Lightning", ID: 53, LeftSkill: true, RightSkill: true},
CountessFirewall 54: {Name: "Teleport", ID: 54, LeftSkill: false, RightSkill: true},
ImpBolt 55: {Name: "Glacial Spike", ID: 55, LeftSkill: true, RightSkill: true},
HorrorArcticBlast 56: {Name: "Meteor", ID: 56, LeftSkill: false, RightSkill: true},
deathSentryLtng 57: {Name: "Thunder Storm", ID: 57, LeftSkill: false, RightSkill: true},
VineCycler 58: {Name: "Energy Shield", ID: 58, LeftSkill: false, RightSkill: true},
BearSmite 59: {Name: "Blizzard", ID: 59, LeftSkill: false, RightSkill: true},
Resurrect2 6: {Name: "Magic Arrow", ID: 6, LeftSkill: true, RightSkill: true},
BloodLordFrenzy 60: {Name: "Chilling Armor", ID: 60, LeftSkill: false, RightSkill: true},
BaalTeleport 61: {Name: "Fire Mastery", ID: 61, LeftSkill: false, RightSkill: false},
ImpTeleport 62: {Name: "Hydra", ID: 62, LeftSkill: false, RightSkill: true},
BaalCloneTeleport 63: {Name: "Lightning Mastery", ID: 63, LeftSkill: false, RightSkill: false},
ZakarumLightning 64: {Name: "Frozen Orb", ID: 64, LeftSkill: true, RightSkill: true},
VampireMissile 65: {Name: "Cold Mastery", ID: 65, LeftSkill: false, RightSkill: false},
MephistoMissile 66: {Name: "Amplify Damage", ID: 66, LeftSkill: false, RightSkill: true},
DoomKnightMissile 67: {Name: "Teeth", ID: 67, LeftSkill: true, RightSkill: true},
RogueMissile 68: {Name: "Bone Armor", ID: 68, LeftSkill: false, RightSkill: true},
HydraMissile 69: {Name: "Skeleton Mastery", ID: 69, LeftSkill: false, RightSkill: false},
NecromageMissile 7: {Name: "Fire Arrow", ID: 7, LeftSkill: true, RightSkill: true},
MonBow 70: {Name: "Raise Skeleton", ID: 70, LeftSkill: false, RightSkill: true},
MonFireArrow 71: {Name: "Dim Vision", ID: 71, LeftSkill: false, RightSkill: true},
MonColdArrow 72: {Name: "Weaken", ID: 72, LeftSkill: false, RightSkill: true},
MonExplodingArrow 73: {Name: "Poison Dagger", ID: 73, LeftSkill: true, RightSkill: true},
MonFreezingArrow 74: {Name: "Corpse Explosion", ID: 74, LeftSkill: false, RightSkill: true},
MonPowerStrike 75: {Name: "Clay Golem", ID: 75, LeftSkill: false, RightSkill: true},
SuccubusBolt 76: {Name: "Iron Maiden", ID: 76, LeftSkill: false, RightSkill: true},
MephFrostNova 77: {Name: "Terror", ID: 77, LeftSkill: false, RightSkill: true},
MonIceSpear 78: {Name: "Bone Wall", ID: 78, LeftSkill: false, RightSkill: true},
ShamanIce 79: {Name: "Golem Mastery", ID: 79, LeftSkill: false, RightSkill: false},
Diablogeddon 8: {Name: "Inner Sight", ID: 8, LeftSkill: false, RightSkill: true},
DeleriumChange 80: {Name: "Raise Skeletal Mage", ID: 80, LeftSkill: false, RightSkill: true},
NihlathakCorpseExplosion 81: {Name: "Confuse", ID: 81, LeftSkill: false, RightSkill: true},
SerpentCharge 82: {Name: "Life Tap", ID: 82, LeftSkill: false, RightSkill: true},
TrapNova 83: {Name: "Poison Explosion", ID: 83, LeftSkill: false, RightSkill: true},
UnHolyBoltEx 84: {Name: "Bone Spear", ID: 84, LeftSkill: true, RightSkill: true},
ShamanFireEx 85: {Name: "BloodGolem", ID: 85, LeftSkill: false, RightSkill: true},
ImpFireMissileEx 86: {Name: "Attract", ID: 86, LeftSkill: false, RightSkill: true},
FixedSiegeBeastStomp 87: {Name: "Decrepify", ID: 87, LeftSkill: false, RightSkill: true},
Unset Skill = -1 88: {Name: "Bone Prison", ID: 88, LeftSkill: false, RightSkill: true},
) 89: {Name: "Summon Resist", ID: 89, LeftSkill: false, RightSkill: false},
9: {Name: "Critical Strike", ID: 9, LeftSkill: false, RightSkill: false},
90: {Name: "IronGolem", ID: 90, LeftSkill: false, RightSkill: true},
91: {Name: "Lower Resist", ID: 91, LeftSkill: false, RightSkill: true},
92: {Name: "Poison Nova", ID: 92, LeftSkill: false, RightSkill: true},
93: {Name: "Bone Spirit", ID: 93, LeftSkill: true, RightSkill: true},
94: {Name: "FireGolem", ID: 94, LeftSkill: false, RightSkill: true},
95: {Name: "Revive", ID: 95, LeftSkill: false, RightSkill: true},
96: {Name: "Sacrifice", ID: 96, LeftSkill: true, RightSkill: true},
97: {Name: "Smite", ID: 97, LeftSkill: true, RightSkill: true},
98: {Name: "Might", ID: 98, LeftSkill: false, RightSkill: true},
99: {Name: "Prayer", ID: 99, LeftSkill: false, RightSkill: true},
}

View File

@@ -1,84 +0,0 @@
package skill
var SorceressTree = Tree{
// Cold Spells
IceBolt: Position{Tab: 0, Row: 0, Column: 1},
FrozenArmor: Position{Tab: 0, Row: 0, Column: 2},
FrostNova: Position{Tab: 0, Row: 1, Column: 0},
IceBlast: Position{Tab: 0, Row: 1, Column: 1},
ShiverArmor: Position{Tab: 0, Row: 2, Column: 2},
GlacialSpike: Position{Tab: 0, Row: 3, Column: 1},
Blizzard: Position{Tab: 0, Row: 4, Column: 0},
ChillingArmor: Position{Tab: 0, Row: 4, Column: 2},
FrozenOrb: Position{Tab: 0, Row: 5, Column: 0},
ColdMastery: Position{Tab: 0, Row: 5, Column: 1},
// Lightning Spells
ChargedBolt: Position{Tab: 1, Row: 0, Column: 1},
StaticField: Position{Tab: 1, Row: 1, Column: 0},
Telekinesis: Position{Tab: 1, Row: 1, Column: 2},
Nova: Position{Tab: 1, Row: 2, Column: 0},
Lightning: Position{Tab: 1, Row: 2, Column: 1},
ChainLightning: Position{Tab: 1, Row: 3, Column: 1},
Teleport: Position{Tab: 1, Row: 3, Column: 2},
ThunderStorm: Position{Tab: 1, Row: 4, Column: 0},
EnergyShield: Position{Tab: 1, Row: 4, Column: 2},
LightningMastery: Position{Tab: 1, Row: 5, Column: 1},
// Fire Spells
FireBolt: Position{Tab: 2, Row: 0, Column: 1},
Warmth: Position{Tab: 2, Row: 0, Column: 2},
Inferno: Position{Tab: 2, Row: 1, Column: 0},
Blaze: Position{Tab: 2, Row: 2, Column: 1},
FireBall: Position{Tab: 2, Row: 2, Column: 1},
FireWall: Position{Tab: 2, Row: 3, Column: 0},
Enchant: Position{Tab: 2, Row: 3, Column: 2},
Meteor: Position{Tab: 2, Row: 4, Column: 1},
FireMastery: Position{Tab: 2, Row: 5, Column: 1},
Hydra: Position{Tab: 2, Row: 5, Column: 2},
}
var PaladinTree = Tree{
// Defensive Auras
Prayer: Position{Tab: 0, Row: 0, Column: 0},
ResistFire: Position{Tab: 0, Row: 0, Column: 2},
Defiance: Position{Tab: 0, Row: 1, Column: 1},
ResistCold: Position{Tab: 0, Row: 1, Column: 2},
Cleansing: Position{Tab: 0, Row: 2, Column: 0},
ResistLightning: Position{Tab: 0, Row: 2, Column: 2},
Vigor: Position{Tab: 0, Row: 3, Column: 1},
Meditation: Position{Tab: 0, Row: 4, Column: 0},
Redemption: Position{Tab: 0, Row: 5, Column: 1},
Salvation: Position{Tab: 0, Row: 5, Column: 2},
// Offensive Auras
Might: Position{Tab: 1, Row: 0, Column: 0},
HolyFire: Position{Tab: 1, Row: 1, Column: 1},
Thorns: Position{Tab: 1, Row: 1, Column: 2},
BlessedAim: Position{Tab: 1, Row: 2, Column: 0},
Concentration: Position{Tab: 1, Row: 3, Column: 0},
HolyFreeze: Position{Tab: 1, Row: 3, Column: 1},
HolyShock: Position{Tab: 1, Row: 4, Column: 1},
Sanctuary: Position{Tab: 1, Row: 4, Column: 2},
Fanaticism: Position{Tab: 1, Row: 5, Column: 0},
Conviction: Position{Tab: 1, Row: 5, Column: 2},
// Combat Skills
Sacrifice: Position{Tab: 2, Row: 0, Column: 0},
Smite: Position{Tab: 2, Row: 0, Column: 2},
HolyBolt: Position{Tab: 2, Row: 1, Column: 1},
Zeal: Position{Tab: 2, Row: 2, Column: 0},
Charge: Position{Tab: 2, Row: 2, Column: 2},
Vengeance: Position{Tab: 2, Row: 3, Column: 0},
BlessedHammer: Position{Tab: 2, Row: 3, Column: 1},
Conversion: Position{Tab: 2, Row: 4, Column: 0},
HolyShield: Position{Tab: 2, Row: 4, Column: 2},
FistOfTheHeavens: Position{Tab: 2, Row: 5, Column: 1},
}
type Tree map[Skill]Position
type Position struct {
Tab int
Row int
Column int
}

View File

@@ -30,6 +30,11 @@ func (gd *GameReader) GetData() data.Data {
pu := gd.GetPlayerUnit(playerUnitPtr) pu := gd.GetPlayerUnit(playerUnitPtr)
hover := gd.hoveredData() hover := gd.hoveredData()
// Quests
pUnitData := playerUnitPtr + 0x10
playerNameAddr := uintptr(gd.Process.ReadUInt(pUnitData, Uint64))
gameQuestsBytes := gd.Process.ReadBytesFromMemory(playerNameAddr-0x28D, 82)
d := data.Data{ d := data.Data{
Corpse: corpse, Corpse: corpse,
Monsters: gd.Monsters(pu.Position, hover), Monsters: gd.Monsters(pu.Position, hover),
@@ -40,6 +45,7 @@ func (gd *GameReader) GetData() data.Data {
Roster: roster, Roster: roster,
HoverData: hover, HoverData: hover,
TerrorZones: gd.TerrorZones(), TerrorZones: gd.TerrorZones(),
Quests: gd.getQuests(gameQuestsBytes),
} }
if playerUnitPtr == 0 { if playerUnitPtr == 0 {

View File

@@ -160,23 +160,29 @@ func (gd *GameReader) GetPlayerUnit(playerUnit uintptr) data.PlayerUnit {
Skills: skills, Skills: skills,
States: states, States: states,
Class: class, Class: class,
LeftSkill: skill.Skill(leftSkillId), LeftSkill: skill.ID(leftSkillId),
RightSkill: skill.Skill(rightSkillId), RightSkill: skill.ID(rightSkillId),
AvailableWaypoints: availableWPs, AvailableWaypoints: availableWPs,
} }
} }
func (gd *GameReader) getSkills(skillListPtr uintptr) map[skill.Skill]int { func (gd *GameReader) getSkills(skillListPtr uintptr) map[skill.ID]skill.Points {
skills := make(map[skill.Skill]int) skills := make(map[skill.ID]skill.Points)
skillPtr := uintptr(gd.Process.ReadUInt(skillListPtr, Uint64)) skillPtr := uintptr(gd.Process.ReadUInt(skillListPtr, Uint64))
for skillPtr != 0 { for skillPtr != 0 {
skillTxtPtr := uintptr(gd.Process.ReadUInt(skillPtr, Uint64)) skillTxtPtr := uintptr(gd.Process.ReadUInt(skillPtr, Uint64))
skillTxt := uintptr(gd.Process.ReadUInt(skillTxtPtr, Uint16)) skillTxt := uintptr(gd.Process.ReadUInt(skillTxtPtr, Uint16))
skillLvl := gd.Process.ReadUInt(skillPtr+0x38, Uint16) lvl := gd.Process.ReadUInt(skillPtr+0x38, Uint16)
quantity := gd.Process.ReadUInt(skillPtr+0x40, Uint16)
charges := gd.Process.ReadUInt(skillPtr+0x48, Uint16)
skills[skill.Skill(skillTxt)] = int(skillLvl) skills[skill.ID(skillTxt)] = skill.Points{
Level: lvl,
Quantity: quantity,
Charges: charges,
}
skillPtr = uintptr(gd.Process.ReadUInt(skillPtr+0x08, Uint64)) skillPtr = uintptr(gd.Process.ReadUInt(skillPtr+0x08, Uint64))
} }

60
pkg/memory/quests.go Normal file
View File

@@ -0,0 +1,60 @@
package memory
import (
"fmt"
"github.com/hectorgimenez/d2go/pkg/data/quest"
)
func (gd *GameReader) getQuests(questBytes []byte) quest.Quests {
return quest.Quests{
// Act 1
quest.Act1DenOfEvil: gd.getQuestStatus([2]byte(questBytes[0:2])),
quest.Act1SistersBurialGrounds: gd.getQuestStatus([2]byte(questBytes[2:4])),
quest.Act1ToolsOfTheTrade: gd.getQuestStatus([2]byte(questBytes[4:6])),
quest.Act1TheSearchForCain: gd.getQuestStatus([2]byte(questBytes[6:8])),
quest.Act1TheForgottenTower: gd.getQuestStatus([2]byte(questBytes[8:10])),
quest.Act1SistersToTheSlaughter: gd.getQuestStatus([2]byte(questBytes[10:12])),
// Act 2
quest.Act2RadamentsLair: gd.getQuestStatus([2]byte(questBytes[16:18])),
quest.Act2TheHoradricStaff: gd.getQuestStatus([2]byte(questBytes[18:20])),
quest.Act2TaintedSun: gd.getQuestStatus([2]byte(questBytes[20:22])),
quest.Act2ArcaneSanctuary: gd.getQuestStatus([2]byte(questBytes[22:24])),
quest.Act2TheSummoner: gd.getQuestStatus([2]byte(questBytes[24:26])),
quest.Act2TheSevenTombs: gd.getQuestStatus([2]byte(questBytes[26:28])),
// Act 3
quest.Act3LamEsensTome: gd.getQuestStatus([2]byte(questBytes[32:34])),
quest.Act3KhalimsWill: gd.getQuestStatus([2]byte(questBytes[34:36])),
quest.Act3BladeOfTheOldReligion: gd.getQuestStatus([2]byte(questBytes[36:38])),
quest.Act3TheGoldenBird: gd.getQuestStatus([2]byte(questBytes[38:40])),
quest.Act3TheBlackenedTemple: gd.getQuestStatus([2]byte(questBytes[40:42])),
quest.Act3TheGuardian: gd.getQuestStatus([2]byte(questBytes[42:44])),
// Act 4
quest.Act4TheFallenAngel: gd.getQuestStatus([2]byte(questBytes[48:50])),
quest.Act4TerrorsEnd: gd.getQuestStatus([2]byte(questBytes[50:52])),
quest.Act4HellForge: gd.getQuestStatus([2]byte(questBytes[52:54])),
// Act 5
quest.Act5SiegeOnHarrogath: gd.getQuestStatus([2]byte(questBytes[68:70])),
quest.Act5RescueOnMountArreat: gd.getQuestStatus([2]byte(questBytes[70:72])),
quest.Act5PrisonOfIce: gd.getQuestStatus([2]byte(questBytes[72:74])),
quest.Act5BetrayalOfHarrogath: gd.getQuestStatus([2]byte(questBytes[74:76])),
quest.Act5RiteOfPassage: gd.getQuestStatus([2]byte(questBytes[76:78])),
quest.Act5EveOfDestruction: gd.getQuestStatus([2]byte(questBytes[78:80])),
}
}
func (gd *GameReader) getQuestStatus(questBytes [2]byte) []quest.Status {
combinedValue := uint16(questBytes[0])<<8 | uint16(questBytes[1])
binaryRepresentation := fmt.Sprintf("%016b", combinedValue)
var activeStates []quest.Status
for i, char := range binaryRepresentation {
if char == '1' {
if 15-i >= 0 && i < 16 {
activeStates = append(activeStates, quest.Status(15-i))
}
}
}
return activeStates
}