@blizzhackers/d2data 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintrc.js +59 -0
- package/LICENSE +21 -0
- package/README.md +12 -0
- package/_config.yml +1 -0
- package/compile.js +789 -0
- package/docs/Avqest.ttf +0 -0
- package/docs/_config.yml +1 -0
- package/docs/armor.js +134 -0
- package/docs/css/d2font.css +10 -0
- package/docs/drops/.vscode/extensions.json +3 -0
- package/docs/drops/README.md +7 -0
- package/docs/drops/dist/assets/index.12ae3c90.js +6675 -0
- package/docs/drops/dist/index.html +24 -0
- package/docs/drops/index.html +23 -0
- package/docs/drops/package-lock.json +1143 -0
- package/docs/drops/package.json +17 -0
- package/docs/drops/src/App.vue +870 -0
- package/docs/drops/src/main.js +4 -0
- package/docs/drops/vite.config.js +8 -0
- package/docs/drops.html +10 -0
- package/docs/effort.css +118 -0
- package/docs/effort.js +367 -0
- package/docs/elem-effort.html +130 -0
- package/docs/images/0-0.svg +18 -0
- package/docs/images/0-1.svg +17 -0
- package/docs/images/0-2.svg +17 -0
- package/docs/images/1-0.svg +18 -0
- package/docs/images/1-1.svg +18 -0
- package/docs/images/1-2.svg +17 -0
- package/docs/images/2-0.svg +17 -0
- package/docs/images/2-1.svg +11 -0
- package/docs/images/2-2.svg +18 -0
- package/docs/images/3-0.svg +17 -0
- package/docs/images/3-1.svg +18 -0
- package/docs/images/3-2.svg +18 -0
- package/docs/images/4-0.svg +18 -0
- package/docs/images/4-1.svg +18 -0
- package/docs/images/4-2.svg +18 -0
- package/docs/images/5-0.svg +18 -0
- package/docs/images/5-1.svg +18 -0
- package/docs/images/5-2.svg +14 -0
- package/docs/images/6-0.svg +17 -0
- package/docs/images/6-1.svg +17 -0
- package/docs/images/6-2.svg +17 -0
- package/docs/images/AmSkillicon.png +0 -0
- package/docs/images/AsSkillicon.png +0 -0
- package/docs/images/BaSkillicon.png +0 -0
- package/docs/images/DrSkillicon.png +0 -0
- package/docs/images/NeSkillicon.png +0 -0
- package/docs/images/PaSkillicon.png +0 -0
- package/docs/images/Skillicon.png +0 -0
- package/docs/images/SoSkillicon.png +0 -0
- package/docs/index.md +5 -0
- package/docs/items.html +170 -0
- package/docs/leveling/.vscode/extensions.json +3 -0
- package/docs/leveling/README.md +7 -0
- package/docs/leveling/dist/assets/index.f9765357.js +1 -0
- package/docs/leveling/dist/index.html +24 -0
- package/docs/leveling/index.html +23 -0
- package/docs/leveling/package-lock.json +1143 -0
- package/docs/leveling/package.json +17 -0
- package/docs/leveling/src/App.vue +526 -0
- package/docs/leveling/src/main.js +4 -0
- package/docs/leveling/vite.config.js +8 -0
- package/docs/runewords/.vscode/extensions.json +3 -0
- package/docs/runewords/README.md +7 -0
- package/docs/runewords/dist/assets/index.0838f27c.js +6673 -0
- package/docs/runewords/dist/assets/index.73bf3e23.css +1 -0
- package/docs/runewords/dist/index.html +25 -0
- package/docs/runewords/index.html +23 -0
- package/docs/runewords/package-lock.json +1143 -0
- package/docs/runewords/package.json +17 -0
- package/docs/runewords/src/App.vue +781 -0
- package/docs/runewords/src/main.js +4 -0
- package/docs/runewords/src/modorder.json +234 -0
- package/docs/runewords/vite.config.js +8 -0
- package/docs/skills.css +1250 -0
- package/docs/skills.html +63 -0
- package/docs/skills.js +2192 -0
- package/docs/vue-setup.js +12 -0
- package/docs/weapons.js +149 -0
- package/font-example.html +34 -0
- package/json/.gitkeep +0 -0
- package/json/actinfo.json +116 -0
- package/json/armor.json +17232 -0
- package/json/armtype.json +17 -0
- package/json/atomic.json +1026 -0
- package/json/automagic.json +696 -0
- package/json/automap.json +40732 -0
- package/json/belts.json +743 -0
- package/json/bodylocs.json +52 -0
- package/json/books.json +34 -0
- package/json/charstats.json +525 -0
- package/json/colors.json +107 -0
- package/json/compcode.json +577 -0
- package/json/composit.json +82 -0
- package/json/cubemain.json +2112 -0
- package/json/cubemod.json +57 -0
- package/json/difficultylevels.json +110 -0
- package/json/elemtypes.json +62 -0
- package/json/events.json +72 -0
- package/json/experience.json +1214 -0
- package/json/gamble.json +520 -0
- package/json/gems.json +1868 -0
- package/json/hireling.json +7640 -0
- package/json/hitclass.json +67 -0
- package/json/inventory.json +2148 -0
- package/json/itemratio.json +134 -0
- package/json/items.json +54705 -0
- package/json/itemstatcost.json +5503 -0
- package/json/itemtypes.json +2567 -0
- package/json/levels.json +15515 -0
- package/json/localestrings-chi.json +8717 -0
- package/json/localestrings-deu.json +8717 -0
- package/json/localestrings-eng.json +8722 -0
- package/json/localestrings-esp.json +8717 -0
- package/json/localestrings-fra.json +8718 -0
- package/json/localestrings-ita.json +8717 -0
- package/json/localestrings-kor.json +8715 -0
- package/json/localestrings-pol.json +8716 -0
- package/json/lowqualityitems.json +6 -0
- package/json/lvlmaze.json +910 -0
- package/json/lvlprest.json +28595 -0
- package/json/lvlsub.json +824 -0
- package/json/lvltypes.json +1377 -0
- package/json/lvlwarp.json +1515 -0
- package/json/magicprefix.json +12349 -0
- package/json/magicsuffix.json +13833 -0
- package/json/misc.json +11602 -0
- package/json/misscalc.json +217 -0
- package/json/missiles.json +23871 -0
- package/json/monai.json +1111 -0
- package/json/moncountest.json +642 -0
- package/json/monequip.json +361 -0
- package/json/monlvl.json +3665 -0
- package/json/monmode.json +98 -0
- package/json/monplace.json +39 -0
- package/json/monpopulationest.json +17383 -0
- package/json/monpreset.json +922 -0
- package/json/monprop.json +144 -0
- package/json/monseq.json +5211 -0
- package/json/monsounds.json +2530 -0
- package/json/monstats.json +66101 -0
- package/json/monstats2.json +34882 -0
- package/json/montype.json +274 -0
- package/json/monumod.json +504 -0
- package/json/npc.json +232 -0
- package/json/objects.json +87041 -0
- package/json/objgroup.json +3733 -0
- package/json/objmode.json +42 -0
- package/json/objpreset.json +2906 -0
- package/json/objtype.json +2457 -0
- package/json/overlay.json +8008 -0
- package/json/pettype.json +226 -0
- package/json/playerclass.json +39 -0
- package/json/plrmode.json +122 -0
- package/json/plrtype.json +39 -0
- package/json/properties.json +2823 -0
- package/json/qualityitems.json +149 -0
- package/json/rareprefix.json +296 -0
- package/json/raresuffix.json +921 -0
- package/json/runes.json +3280 -0
- package/json/setitems.json +3871 -0
- package/json/sets.json +1001 -0
- package/json/shrines.json +319 -0
- package/json/skillcalc.json +457 -0
- package/json/skilldesc.json +7532 -0
- package/json/skills.json +16717 -0
- package/json/soundenviron.json +2862 -0
- package/json/sounds.json +446543 -0
- package/json/states.json +1578 -0
- package/json/storepage.json +22 -0
- package/json/superuniques.json +1405 -0
- package/json/tcprecalc.json +29302 -0
- package/json/treasureclassex.json +14932 -0
- package/json/treasureclassgroupsex.json +711 -0
- package/json/uniqueappellation.json +27 -0
- package/json/uniqueitems.json +14171 -0
- package/json/uniqueprefix.json +55 -0
- package/json/uniquesuffix.json +71 -0
- package/json/wanderingmon.json +3 -0
- package/json/weapons.json +25875 -0
- package/objext.js +53 -0
- package/package.json +16 -0
- package/string.js +42 -0
package/docs/drops.html
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html>
|
|
3
|
+
<head>
|
|
4
|
+
<title>Diablo 2 (D2R 2.4) Drop Calculator</title>
|
|
5
|
+
<meta http-equiv="refresh" content="0;url=drops/dist/" />
|
|
6
|
+
</head>
|
|
7
|
+
<body>
|
|
8
|
+
<p>The drop calculator has moved! Redirecting to the new calculator...</p>
|
|
9
|
+
</body>
|
|
10
|
+
</html>
|
package/docs/effort.css
ADDED
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
html, body, div {
|
|
2
|
+
box-sizing: border-box;
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
html {
|
|
6
|
+
display: block;
|
|
7
|
+
padding: 0;
|
|
8
|
+
margin: 0;
|
|
9
|
+
min-width: 100%;
|
|
10
|
+
min-height: 100%;
|
|
11
|
+
font-size: 15px;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
body {
|
|
15
|
+
display: block;
|
|
16
|
+
height: auto;
|
|
17
|
+
min-height: 100%;
|
|
18
|
+
max-width: 1360px;
|
|
19
|
+
background-color: white;
|
|
20
|
+
margin: auto;
|
|
21
|
+
padding: 15px;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
@media screen and (min-width: 1375px) {
|
|
25
|
+
html {
|
|
26
|
+
background-color: #606060;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
body {
|
|
30
|
+
border-radius: 5px;
|
|
31
|
+
margin: 15px auto;
|
|
32
|
+
box-shadow: 5px 5px 10px black;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
.svg-wrapper {
|
|
37
|
+
padding-top: 50%;
|
|
38
|
+
position: relative;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
.svg-wrapper svg {
|
|
42
|
+
position: absolute;
|
|
43
|
+
top: 0;
|
|
44
|
+
left: 0;
|
|
45
|
+
width: 100%;
|
|
46
|
+
height: 100%;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
svg text {
|
|
50
|
+
font-size: 1em;
|
|
51
|
+
white-space: pre;
|
|
52
|
+
fill: black;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
svg text.debug {
|
|
56
|
+
fill: #0FF;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
svg line {
|
|
60
|
+
stroke: black;
|
|
61
|
+
stroke-width: 1;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
svg rect {
|
|
65
|
+
stroke: #000000;
|
|
66
|
+
stroke-width: 0;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
.element-select, .difficulty-select {
|
|
70
|
+
width: 12.5em;
|
|
71
|
+
height: 8.25em;
|
|
72
|
+
padding: 3px;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
.settings-bar {
|
|
76
|
+
display: flex;
|
|
77
|
+
flex-direction: row;
|
|
78
|
+
margin: 0 0 1em 0;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
.settings-bar > *:not(:first-child) {
|
|
82
|
+
margin-left: 1em;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
.settings-bar > .element-table {
|
|
86
|
+
flex: 0 0 35em;
|
|
87
|
+
box-sizing: border-box;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
.settings-bar > .element-table th {
|
|
91
|
+
white-space: pre;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
.settings-bar > .element-table * {
|
|
95
|
+
box-sizing: border-box;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
.settings-bar > .element-table input {
|
|
99
|
+
width: 100%;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
.expand-label {
|
|
103
|
+
display: flex;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
.expand-label > label {
|
|
107
|
+
flex: 1 1 auto;
|
|
108
|
+
margin-right: 0.5em;
|
|
109
|
+
}
|
|
110
|
+
.expand-label > :not(label) {
|
|
111
|
+
width: 5em;
|
|
112
|
+
flex: 0 0 auto;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
.vertically-spaced > * {
|
|
116
|
+
height: 1.8em;
|
|
117
|
+
line-height: 1.8em;
|
|
118
|
+
}
|
package/docs/effort.js
ADDED
|
@@ -0,0 +1,367 @@
|
|
|
1
|
+
'use strict'; /* global Vue */
|
|
2
|
+
|
|
3
|
+
let app;
|
|
4
|
+
|
|
5
|
+
function createLine(x1 = 0, y1 = 0, x2 = 0, y2 = 0, color = 'black') {
|
|
6
|
+
return {type: 'line', x1, y1, x2, y2, color};
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
function createRect(x = 0, y = 0, width = 0, height = 0, color = 'black') {
|
|
10
|
+
return {type: 'rect', x, y, width, height, color};
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
function createText(x = 0, y = 0, text = 'No Text', color = 'black') {
|
|
14
|
+
return {type: 'text', x, y, text, color};
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
let $ = document.querySelector.bind(document);
|
|
18
|
+
|
|
19
|
+
(function () {
|
|
20
|
+
app = new Vue({
|
|
21
|
+
el: '#effortapp',
|
|
22
|
+
data: {
|
|
23
|
+
dmgTypes: {
|
|
24
|
+
physical: 'Physical',
|
|
25
|
+
magic: 'Magic',
|
|
26
|
+
fire: 'Fire',
|
|
27
|
+
lightning: 'Lightning',
|
|
28
|
+
cold: 'Cold',
|
|
29
|
+
poison: 'Poison',
|
|
30
|
+
},
|
|
31
|
+
fontSize: 1,
|
|
32
|
+
d2: {
|
|
33
|
+
MonLvl: fetch('https://raw.githubusercontent.com/blizzhackers/d2data/master/json/monlvl.json').then(response => response.json()),
|
|
34
|
+
monstats: fetch('https://raw.githubusercontent.com/blizzhackers/d2data/master/json/monstats.json').then(response => response.json()),
|
|
35
|
+
Levels: fetch('https://raw.githubusercontent.com/blizzhackers/d2data/master/json/levels.json').then(response => response.json()),
|
|
36
|
+
},
|
|
37
|
+
requiredAreas: [ // Areas that we're forced to deal with through questing.
|
|
38
|
+
// Act 1
|
|
39
|
+
2,3,4,5,6,7,10,26,27,28,29,30,31,32,33,34,35,36,37,
|
|
40
|
+
// Act 2
|
|
41
|
+
41,42,43,44,45,46,50,51,52,53,54,56,57,58,60,61,62,63,64,66,67,68,69,70,71,72,73,74,
|
|
42
|
+
// Act 3
|
|
43
|
+
76,77,78,79,80,81,82,83,85,88,89,91,92,93,100,101,102,
|
|
44
|
+
// Act 4
|
|
45
|
+
104,105,106,107,108,
|
|
46
|
+
// Act 5
|
|
47
|
+
110,111,112,113,115,117,118,120,128,129,130,131,
|
|
48
|
+
],
|
|
49
|
+
svg: {
|
|
50
|
+
width: 100,
|
|
51
|
+
height: 100,
|
|
52
|
+
aspectRatio: 1,
|
|
53
|
+
elements: {},
|
|
54
|
+
},
|
|
55
|
+
debugMessage: '',
|
|
56
|
+
visible: false,
|
|
57
|
+
colorKey: {
|
|
58
|
+
physical: '#000000',
|
|
59
|
+
magic: '#C0C0C0',
|
|
60
|
+
fire: '#FF0000',
|
|
61
|
+
lightning: '#FFFF00',
|
|
62
|
+
cold: '#0000FF',
|
|
63
|
+
poison: '#00FF00',
|
|
64
|
+
},
|
|
65
|
+
textColorKey: {
|
|
66
|
+
physical: '#FFFFFF',
|
|
67
|
+
magic: '#000000',
|
|
68
|
+
fire: '#000000',
|
|
69
|
+
lightning: '#000000',
|
|
70
|
+
cold: '#FFFFFF',
|
|
71
|
+
poison: '#000000',
|
|
72
|
+
},
|
|
73
|
+
difficulty: {
|
|
74
|
+
0: true,
|
|
75
|
+
1: true,
|
|
76
|
+
2: true,
|
|
77
|
+
},
|
|
78
|
+
optionalAreas: false,
|
|
79
|
+
countImmunes: false,
|
|
80
|
+
skills: {
|
|
81
|
+
conviction: 0,
|
|
82
|
+
lowerResist: 0,
|
|
83
|
+
amplify: 0,
|
|
84
|
+
},
|
|
85
|
+
damage: {
|
|
86
|
+
min: {
|
|
87
|
+
physical: 1,
|
|
88
|
+
magic: 1,
|
|
89
|
+
fire: 1,
|
|
90
|
+
lightning: 1,
|
|
91
|
+
cold: 1,
|
|
92
|
+
poison: 1,
|
|
93
|
+
},
|
|
94
|
+
max: {
|
|
95
|
+
physical: 1,
|
|
96
|
+
magic: 1,
|
|
97
|
+
fire: 1,
|
|
98
|
+
lightning: 1,
|
|
99
|
+
cold: 1,
|
|
100
|
+
poison: 1,
|
|
101
|
+
},
|
|
102
|
+
avg: {
|
|
103
|
+
physical: 1,
|
|
104
|
+
magic: 1,
|
|
105
|
+
fire: 1,
|
|
106
|
+
lightning: 1,
|
|
107
|
+
cold: 1,
|
|
108
|
+
poison: 1,
|
|
109
|
+
},
|
|
110
|
+
hits: {
|
|
111
|
+
physical: 1,
|
|
112
|
+
magic: 1,
|
|
113
|
+
fire: 1,
|
|
114
|
+
lightning: 1,
|
|
115
|
+
cold: 1,
|
|
116
|
+
poison: 1,
|
|
117
|
+
},
|
|
118
|
+
aoe: {
|
|
119
|
+
physical: 1,
|
|
120
|
+
magic: 1,
|
|
121
|
+
fire: 1,
|
|
122
|
+
lightning: 1,
|
|
123
|
+
cold: 1,
|
|
124
|
+
poison: 1,
|
|
125
|
+
},
|
|
126
|
+
fpa: {
|
|
127
|
+
physical: 25,
|
|
128
|
+
magic: 25,
|
|
129
|
+
fire: 25,
|
|
130
|
+
lightning: 25,
|
|
131
|
+
cold: 25,
|
|
132
|
+
poison: 25,
|
|
133
|
+
},
|
|
134
|
+
},
|
|
135
|
+
pierce: {
|
|
136
|
+
physical: 0,
|
|
137
|
+
magic: 0,
|
|
138
|
+
fire: 0,
|
|
139
|
+
lightning: 0,
|
|
140
|
+
cold: 0,
|
|
141
|
+
poison: 0,
|
|
142
|
+
},
|
|
143
|
+
},
|
|
144
|
+
methods: {
|
|
145
|
+
updateGraphs: function () {
|
|
146
|
+
this.calculateEfforts();
|
|
147
|
+
},
|
|
148
|
+
calculateEfforts: function () {
|
|
149
|
+
let maxYield = 0.0000001, diffs = [0, 1, 2].filter(a => this.difficulty[a]);
|
|
150
|
+
|
|
151
|
+
for (let key in this.damage.avg) {
|
|
152
|
+
this.damage.avg[key] = (Number(this.damage.min[key]) + Number(this.damage.max[key])) / 2;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
Vue.set(this.svg, 'elements', {});
|
|
156
|
+
|
|
157
|
+
diffs.forEach((diff, diffindex) => {
|
|
158
|
+
let monprefix = ['mon', 'nmon', 'umon'][diff];
|
|
159
|
+
let diffabv = ['', '(N)', '(H)'][diff];
|
|
160
|
+
for (let index in this.d2.Levels) {
|
|
161
|
+
let level = this.d2.Levels[index], key, monid, mon;
|
|
162
|
+
let totalRarity = 0, stats = {
|
|
163
|
+
yield: {
|
|
164
|
+
physical: 0,
|
|
165
|
+
magic: 0,
|
|
166
|
+
fire: 0,
|
|
167
|
+
lightning: 0,
|
|
168
|
+
cold: 0,
|
|
169
|
+
poison: 0,
|
|
170
|
+
},
|
|
171
|
+
};
|
|
172
|
+
|
|
173
|
+
for (let c = 1; c <= 10; c++) {
|
|
174
|
+
key = monprefix + c;
|
|
175
|
+
if ((monid = level[key]) && (mon = this.d2.monstats[monid])) {
|
|
176
|
+
let party = [], minions = [this.d2.monstats[mon.minion1], this.d2.monstats[mon.minion2]].filter(Boolean);
|
|
177
|
+
mon.PartyMin = mon.PartyMin || 1;
|
|
178
|
+
mon.PartyMax = mon.PartyMax || 1;
|
|
179
|
+
mon.MinGrp = mon.MinGrp || 0;
|
|
180
|
+
mon.MaxGrp = mon.MaxGrp || 0;
|
|
181
|
+
mon.Rarity = mon.Rarity || 0;
|
|
182
|
+
party.push([mon, (mon.PartyMin + mon.PartyMax) * mon.Rarity / 2]);
|
|
183
|
+
|
|
184
|
+
let groupSize = (mon.PartyMin + mon.PartyMax + mon.MinGrp + mon.MaxGrp) / 2;
|
|
185
|
+
|
|
186
|
+
minions.forEach(minion => {
|
|
187
|
+
party.push([minion, (mon.MinGrp + mon.MaxGrp) * mon.Rarity / 2 / minions.length]);
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
party.forEach(mondata => {
|
|
191
|
+
let [mon, rarity] = mondata,
|
|
192
|
+
monlvl = this.d2.MonLvl[[mon.Level, level['MonLvlEx(N)'], level['MonLvlEx(H)']][diff]],
|
|
193
|
+
hp = ((mon.minHP || 0) + (mon.maxHP || 0)) / 200 * monlvl['HP' + diffabv],
|
|
194
|
+
xp = (mon.Exp || 0) / 100 * monlvl['XP' + diffabv];
|
|
195
|
+
let calc = (resKey, resName) => {
|
|
196
|
+
if (!xp || !rarity) {
|
|
197
|
+
return 0;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
if (!hp) {
|
|
201
|
+
return Infinity;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
let res = Number(mon[resKey]) || 0;
|
|
205
|
+
|
|
206
|
+
if (res >= 100) {
|
|
207
|
+
switch(resName) {
|
|
208
|
+
case 'fire':
|
|
209
|
+
case 'lightning':
|
|
210
|
+
case 'cold':
|
|
211
|
+
res -= (Number(this.skills.conviction) + Number(this.skills.lowerResist)) / 5;
|
|
212
|
+
break;
|
|
213
|
+
case 'poison':
|
|
214
|
+
res -= Number(this.skills.lowerResist) / 5;
|
|
215
|
+
break;
|
|
216
|
+
case 'physical':
|
|
217
|
+
res -= Number(this.skills.amplify) / 5;
|
|
218
|
+
break;
|
|
219
|
+
}
|
|
220
|
+
} else {
|
|
221
|
+
switch(resName) {
|
|
222
|
+
case 'fire':
|
|
223
|
+
case 'lightning':
|
|
224
|
+
case 'cold':
|
|
225
|
+
res -= Number(this.skills.conviction) + Number(this.skills.lowerResist);
|
|
226
|
+
break;
|
|
227
|
+
case 'poison':
|
|
228
|
+
res -= Number(this.skills.lowerResist);
|
|
229
|
+
break;
|
|
230
|
+
case 'physical':
|
|
231
|
+
res -= Number(this.skills.amplify);
|
|
232
|
+
break;
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
if (res < 100) {
|
|
237
|
+
res -= Number(this.pierce[resName]);
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
res = Math.min(100, Math.max(-100, res)) / 100;
|
|
241
|
+
|
|
242
|
+
if (this.countImmunes) {
|
|
243
|
+
if (res >= 1) {
|
|
244
|
+
return 1 * rarity;
|
|
245
|
+
} else {
|
|
246
|
+
return 0;
|
|
247
|
+
}
|
|
248
|
+
} else {
|
|
249
|
+
return Math.min(this.damage.aoe[resName], groupSize) * (xp / Math.ceil(hp / (this.damage.avg[resName] * this.damage.hits[resName]))) * (1 - res) * rarity / this.damage.fpa[resName];
|
|
250
|
+
}
|
|
251
|
+
};
|
|
252
|
+
|
|
253
|
+
stats.yield.physical += calc('ResDm' + diffabv, 'physical');
|
|
254
|
+
stats.yield.magic += calc('ResMa' + diffabv, 'magic');
|
|
255
|
+
stats.yield.fire += calc('ResFi' + diffabv, 'fire');
|
|
256
|
+
stats.yield.lightning += calc('ResLi' + diffabv, 'lightning');
|
|
257
|
+
stats.yield.cold += calc('ResCo' + diffabv, 'cold');
|
|
258
|
+
stats.yield.poison += calc('ResPo' + diffabv, 'poison');
|
|
259
|
+
totalRarity += rarity;
|
|
260
|
+
});
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
if (totalRarity) {
|
|
265
|
+
for (let key in stats.yield) {
|
|
266
|
+
stats.yield[key] /= totalRarity;
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
level['Calculations' + diffabv] = stats;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
let acts = [];
|
|
274
|
+
|
|
275
|
+
for (let lvlNum in this.d2.Levels) {
|
|
276
|
+
if (lvlNum > 0) {
|
|
277
|
+
let current = this.d2.Levels[lvlNum]['Calculations' + diffabv],
|
|
278
|
+
yields = Object.keys(current.yield).sort((a, b) => current.yield[a] - current.yield[b]),
|
|
279
|
+
act = this.d2.Levels[lvlNum].Act || 0;
|
|
280
|
+
acts[act] = acts[act] || {yields: {}};
|
|
281
|
+
|
|
282
|
+
yields.forEach(key => {
|
|
283
|
+
acts[act].yields[key] = acts[act].yields[key] || [0, 0];
|
|
284
|
+
if (this.optionalAreas || this.requiredAreas.includes(lvlNum|0)) {
|
|
285
|
+
acts[act].yields[key][0] += current.yield[key];
|
|
286
|
+
acts[act].yields[key][1] += 1;
|
|
287
|
+
}
|
|
288
|
+
});
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
acts = acts.map(current => {
|
|
293
|
+
for (let key in current.yields) {
|
|
294
|
+
if (current.yields[key][0]) {
|
|
295
|
+
current.yields[key] = current.yields[key][0] / current.yields[key][1];
|
|
296
|
+
}
|
|
297
|
+
else {
|
|
298
|
+
current.yields[key] = 0;
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
maxYield = Math.max(maxYield, current.yields[key]);
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
return current.yields;
|
|
305
|
+
});
|
|
306
|
+
|
|
307
|
+
let totalIndex = acts.length, width = 1 / (acts.length + 1), floor = (diffindex + 1) / diffs.length;
|
|
308
|
+
if (diffindex < diffs.length - 1) {
|
|
309
|
+
Vue.set(this.svg.elements, 'lvlfloor' + diffabv, createLine(0, floor, 1, floor, '#000000'));
|
|
310
|
+
}
|
|
311
|
+
acts[totalIndex] = {};
|
|
312
|
+
|
|
313
|
+
acts.forEach((current, index) => {
|
|
314
|
+
let keys = Object.keys(current).filter(key => Number(this.damage.avg[key])), subWidth = width / keys.length, text = '';
|
|
315
|
+
keys.forEach((key, subIndex) => {
|
|
316
|
+
if (index < totalIndex) {
|
|
317
|
+
acts[totalIndex][key] = acts[totalIndex][key] || 0;
|
|
318
|
+
acts[totalIndex][key] += current[key];
|
|
319
|
+
} else {
|
|
320
|
+
current[key] /= totalIndex;
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
let height = current[key] / maxYield / diffs.length,
|
|
324
|
+
x = width * index + subWidth * subIndex,
|
|
325
|
+
y = floor - height;
|
|
326
|
+
Vue.set(this.svg.elements, 'act' + index + key + diffindex, createRect(x, y, subWidth, height, this.colorKey[key] || '#000000'));
|
|
327
|
+
Vue.set(this.svg.elements, 'act' + index + key + '-caption' + diffindex, createText(x + subWidth / 2, (diffindex + 0.9) / diffs.length, key, this.textColorKey[key]));
|
|
328
|
+
});
|
|
329
|
+
|
|
330
|
+
if (index < totalIndex) {
|
|
331
|
+
text = 'Act ' + (index + 1) + ' ' + diffabv;
|
|
332
|
+
} else {
|
|
333
|
+
text = 'Average ' + diffabv;
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
if (index > 0) {
|
|
337
|
+
Vue.set(this.svg.elements, 'act' + index + 'divider' + diffindex, createLine(width * index, diffindex / diffs.length, width * index, floor, '#000000'));
|
|
338
|
+
}
|
|
339
|
+
Vue.set(this.svg.elements, 'act' + index + 'text' + diffindex, createText(width * (index + 0.5), (diffindex + 0.1) / diffs.length, text, '#000000'));
|
|
340
|
+
});
|
|
341
|
+
});
|
|
342
|
+
},
|
|
343
|
+
},
|
|
344
|
+
created: async function () {
|
|
345
|
+
for (let key in this.d2) {
|
|
346
|
+
this.d2[key] = await this.d2[key];
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
this.calculateEfforts();
|
|
350
|
+
this.visible = true;
|
|
351
|
+
|
|
352
|
+
let windowUpdate = () => {
|
|
353
|
+
let elem = $('#renderer');
|
|
354
|
+
if (elem) {
|
|
355
|
+
this.svg.width = elem.clientWidth;
|
|
356
|
+
this.svg.height = elem.clientHeight;
|
|
357
|
+
this.svg.aspectRatio = this.svg.width / this.svg.height;
|
|
358
|
+
this.fontSize = this.svg.width * 0.008;
|
|
359
|
+
this.debugMessage = this.svg.width + 'x' + this.svg.height;
|
|
360
|
+
}
|
|
361
|
+
window.requestAnimationFrame(windowUpdate);
|
|
362
|
+
};
|
|
363
|
+
|
|
364
|
+
windowUpdate();
|
|
365
|
+
},
|
|
366
|
+
});
|
|
367
|
+
})();
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html>
|
|
3
|
+
<head>
|
|
4
|
+
<title>Diablo 2 Elemental Effort Visualizer</title>
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
+
<script src="https://cdn.jsdelivr.net/npm/vue@2"></script>
|
|
7
|
+
<link rel="stylesheet" href="effort.css">
|
|
8
|
+
</head>
|
|
9
|
+
<body>
|
|
10
|
+
<div id="effortapp">
|
|
11
|
+
<div class="settings-bar">
|
|
12
|
+
<div class="vertically-spaced">
|
|
13
|
+
<div class="expand-label">
|
|
14
|
+
<label>Normal</label>
|
|
15
|
+
<input type="checkbox" v-model="difficulty[0]" @change="updateGraphs">
|
|
16
|
+
</div>
|
|
17
|
+
<div class="expand-label">
|
|
18
|
+
<label>Nightmare</label>
|
|
19
|
+
<input type="checkbox" v-model="difficulty[1]" @change="updateGraphs">
|
|
20
|
+
</div>
|
|
21
|
+
<div class="expand-label">
|
|
22
|
+
<label>Hell</label>
|
|
23
|
+
<input type="checkbox" v-model="difficulty[2]" @change="updateGraphs">
|
|
24
|
+
</div>
|
|
25
|
+
<div class="expand-label">
|
|
26
|
+
<label>Optional Areas</label>
|
|
27
|
+
<input type="checkbox" v-model="optionalAreas" @change="updateGraphs">
|
|
28
|
+
</div>
|
|
29
|
+
<div class="expand-label">
|
|
30
|
+
<label>Count Immunes</label>
|
|
31
|
+
<input type="checkbox" v-model="countImmunes" @change="updateGraphs">
|
|
32
|
+
</div>
|
|
33
|
+
</div>
|
|
34
|
+
<div class="vertically-spaced">
|
|
35
|
+
<div class="expand-label input-height">
|
|
36
|
+
<label>Conviction %</label>
|
|
37
|
+
<input type="number" step="5" min="0" v-model="skills.conviction" @change="updateGraphs">
|
|
38
|
+
</div>
|
|
39
|
+
<div class="expand-label input-height">
|
|
40
|
+
<label>Lower Resist %</label>
|
|
41
|
+
<input type="number" step="5" min="0" v-model="skills.lowerResist" @change="updateGraphs">
|
|
42
|
+
</div>
|
|
43
|
+
<div class="expand-label input-height">
|
|
44
|
+
<label>Amplify/Decrepify %</label>
|
|
45
|
+
<input type="number" step="50" min="0" max="100" v-model="skills.amplify" @change="updateGraphs">
|
|
46
|
+
</div>
|
|
47
|
+
<div> </div>
|
|
48
|
+
</div>
|
|
49
|
+
<table class="element-table">
|
|
50
|
+
<tr>
|
|
51
|
+
<td> </td>
|
|
52
|
+
<th>Physical</th>
|
|
53
|
+
<th>Magic</th>
|
|
54
|
+
<th>Fire</th>
|
|
55
|
+
<th>Lightning</th>
|
|
56
|
+
<th>Cold</th>
|
|
57
|
+
<th>Poison</th>
|
|
58
|
+
</tr>
|
|
59
|
+
<tr>
|
|
60
|
+
<th>Min Dmg</th>
|
|
61
|
+
<td><input type="number" step="1" min="0" v-model="damage.min.physical" @change="updateGraphs"></td>
|
|
62
|
+
<td><input type="number" step="1" min="0" v-model="damage.min.magic" @change="updateGraphs"></td>
|
|
63
|
+
<td><input type="number" step="1" min="0" v-model="damage.min.fire" @change="updateGraphs"></td>
|
|
64
|
+
<td><input type="number" step="1" min="0" v-model="damage.min.lightning" @change="updateGraphs"></td>
|
|
65
|
+
<td><input type="number" step="1" min="0" v-model="damage.min.cold" @change="updateGraphs"></td>
|
|
66
|
+
<td><input type="number" step="1" min="0" v-model="damage.min.poison" @change="updateGraphs"></td>
|
|
67
|
+
</tr>
|
|
68
|
+
<tr>
|
|
69
|
+
<th>Max Dmg</th>
|
|
70
|
+
<td><input type="number" step="1" min="0" v-model="damage.max.physical" @change="updateGraphs"></td>
|
|
71
|
+
<td><input type="number" step="1" min="0" v-model="damage.max.magic" @change="updateGraphs"></td>
|
|
72
|
+
<td><input type="number" step="1" min="0" v-model="damage.max.fire" @change="updateGraphs"></td>
|
|
73
|
+
<td><input type="number" step="1" min="0" v-model="damage.max.lightning" @change="updateGraphs"></td>
|
|
74
|
+
<td><input type="number" step="1" min="0" v-model="damage.max.cold" @change="updateGraphs"></td>
|
|
75
|
+
<td><input type="number" step="1" min="0" v-model="damage.max.poison" @change="updateGraphs"></td>
|
|
76
|
+
</tr>
|
|
77
|
+
<tr>
|
|
78
|
+
<th>Pierce %</th>
|
|
79
|
+
<td><input type="number" step="1" min="0" v-model="pierce.physical" @change="updateGraphs" disabled></td>
|
|
80
|
+
<td><input type="number" step="1" min="0" v-model="pierce.magic" @change="updateGraphs" disabled></td>
|
|
81
|
+
<td><input type="number" step="1" min="0" v-model="pierce.fire" @change="updateGraphs"></td>
|
|
82
|
+
<td><input type="number" step="1" min="0" v-model="pierce.lightning" @change="updateGraphs"></td>
|
|
83
|
+
<td><input type="number" step="1" min="0" v-model="pierce.cold" @change="updateGraphs"></td>
|
|
84
|
+
<td><input type="number" step="1" min="0" v-model="pierce.poison" @change="updateGraphs"></td>
|
|
85
|
+
</tr>
|
|
86
|
+
<tr>
|
|
87
|
+
<th>Hit Count</th>
|
|
88
|
+
<td><input type="number" step="1" min="1" v-model="damage.hits.physical" @change="updateGraphs"></td>
|
|
89
|
+
<td><input type="number" step="1" min="1" v-model="damage.hits.magic" @change="updateGraphs"></td>
|
|
90
|
+
<td><input type="number" step="1" min="1" v-model="damage.hits.fire" @change="updateGraphs"></td>
|
|
91
|
+
<td><input type="number" step="1" min="1" v-model="damage.hits.lightning" @change="updateGraphs"></td>
|
|
92
|
+
<td><input type="number" step="1" min="1" v-model="damage.hits.cold" @change="updateGraphs"></td>
|
|
93
|
+
<td><input type="number" step="1" min="1" v-model="damage.hits.poison" @change="updateGraphs"></td>
|
|
94
|
+
</tr>
|
|
95
|
+
<tr>
|
|
96
|
+
<th>AoE Max</th>
|
|
97
|
+
<td><input type="number" step="1" min="1" v-model="damage.aoe.physical" @change="updateGraphs"></td>
|
|
98
|
+
<td><input type="number" step="1" min="1" v-model="damage.aoe.magic" @change="updateGraphs"></td>
|
|
99
|
+
<td><input type="number" step="1" min="1" v-model="damage.aoe.fire" @change="updateGraphs"></td>
|
|
100
|
+
<td><input type="number" step="1" min="1" v-model="damage.aoe.lightning" @change="updateGraphs"></td>
|
|
101
|
+
<td><input type="number" step="1" min="1" v-model="damage.aoe.cold" @change="updateGraphs"></td>
|
|
102
|
+
<td><input type="number" step="1" min="1" v-model="damage.aoe.poison" @change="updateGraphs"></td>
|
|
103
|
+
</tr>
|
|
104
|
+
<tr>
|
|
105
|
+
<th>*FPA</th>
|
|
106
|
+
<td><input type="number" step="1" min="1" v-model="damage.fpa.physical" @change="updateGraphs"></td>
|
|
107
|
+
<td><input type="number" step="1" min="1" v-model="damage.fpa.magic" @change="updateGraphs"></td>
|
|
108
|
+
<td><input type="number" step="1" min="1" v-model="damage.fpa.fire" @change="updateGraphs"></td>
|
|
109
|
+
<td><input type="number" step="1" min="1" v-model="damage.fpa.lightning" @change="updateGraphs"></td>
|
|
110
|
+
<td><input type="number" step="1" min="1" v-model="damage.fpa.cold" @change="updateGraphs"></td>
|
|
111
|
+
<td><input type="number" step="1" min="1" v-model="damage.fpa.poison" @change="updateGraphs"></td>
|
|
112
|
+
</tr>
|
|
113
|
+
</table>
|
|
114
|
+
</div>
|
|
115
|
+
<p>Higher values mean more effectiveness. AoE max is capped at group size. *FPA = Frames Per Attack (25 frames = 1 second)</p>
|
|
116
|
+
<div class="svg-wrapper" v-if="visible">
|
|
117
|
+
<svg id="renderer" :height="svg.height" :width="svg.width" :style="`font-size:${fontSize}px`">
|
|
118
|
+
<template v-for="element in svg.elements">
|
|
119
|
+
<line v-if="element.type === 'line'" :x1="svg.width * element.x1" :y1="svg.height * element.y1" :x2="svg.width * element.x2" :y2="svg.height * element.y2" :style="'stroke:' + element.color" />
|
|
120
|
+
<rect v-else-if="element.type === 'rect'" :x="svg.width * element.x" :y="svg.height * element.y" :width="svg.width * element.width" :height="svg.height * element.height" :style="'fill:' + element.color" />
|
|
121
|
+
<text v-else-if="element.type === 'text'" :x="svg.width * element.x" :y="svg.height * element.y" :style="'fill:' + element.color" dominant-baseline="middle" text-anchor="middle">{{ element.text }}</text>
|
|
122
|
+
</template>
|
|
123
|
+
<text :x="5" :y="svg.height - 5" class="debug">{{ debugMessage }}</text>
|
|
124
|
+
</svg>
|
|
125
|
+
</div>
|
|
126
|
+
<p v-else>Loading...</p>
|
|
127
|
+
</div>
|
|
128
|
+
</body>
|
|
129
|
+
<script src="effort.js"></script>
|
|
130
|
+
</html>
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
|
3
|
+
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0.5 0.5 3 6">
|
|
4
|
+
<defs>
|
|
5
|
+
<marker id="arrowhead" markerWidth="1.5" markerHeight="2.5" refX="0.05" refY="1.25" orient="auto">
|
|
6
|
+
<polygon points="0 0, 1.5 1.25, 0 2.5" fill="#222" />
|
|
7
|
+
</marker>
|
|
8
|
+
</defs>
|
|
9
|
+
<line x1="2" y1="1" x2="2" y2="1.55" stroke="#222" stroke-width="0.1" marker-end="url(#arrowhead)"/>
|
|
10
|
+
<line x1="3" y1="1" x2="3" y2="2.55" stroke="#222" stroke-width="0.1" marker-end="url(#arrowhead)"/>
|
|
11
|
+
<line x1="1" y1="2" x2="1" y2="3.55" stroke="#222" stroke-width="0.1" marker-end="url(#arrowhead)"/>
|
|
12
|
+
<line x1="2" y1="2" x2="2" y2="3.55" stroke="#222" stroke-width="0.1" marker-end="url(#arrowhead)"/>
|
|
13
|
+
<line x1="3" y1="3" x2="3" y2="4.55" stroke="#222" stroke-width="0.1" marker-end="url(#arrowhead)"/>
|
|
14
|
+
<line x1="1" y1="4" x2="1" y2="5.55" stroke="#222" stroke-width="0.1" marker-end="url(#arrowhead)"/>
|
|
15
|
+
<line x1="2" y1="4" x2="2" y2="4.55" stroke="#222" stroke-width="0.1" marker-end="url(#arrowhead)"/>
|
|
16
|
+
<line x1="2" y1="2" x2="2.6" y2="2.6" stroke="#222" stroke-width="0.1" marker-end="url(#arrowhead)"/>
|
|
17
|
+
<line x1="1" y1="3" x2="1.6" y2="3.6" stroke="#222" stroke-width="0.1" marker-end="url(#arrowhead)"/>
|
|
18
|
+
</svg>
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
|
3
|
+
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0.5 0.5 3 6">
|
|
4
|
+
<defs>
|
|
5
|
+
<marker id="arrowhead" markerWidth="1.5" markerHeight="2.5" refX="0.05" refY="1.25" orient="auto">
|
|
6
|
+
<polygon points="0 0, 1.5 1.25, 0 2.5" fill="#222" />
|
|
7
|
+
</marker>
|
|
8
|
+
</defs>
|
|
9
|
+
<line x1="1" y1="1" x2="1" y2="2.55" stroke="#222" stroke-width="0.1" marker-end="url(#arrowhead)"/>
|
|
10
|
+
<line x1="1" y1="3" x2="1" y2="4.55" stroke="#222" stroke-width="0.1" marker-end="url(#arrowhead)"/>
|
|
11
|
+
<line x1="1" y1="5" x2="1" y2="5.55" stroke="#222" stroke-width="0.1" marker-end="url(#arrowhead)"/>
|
|
12
|
+
<line x1="2" y1="2" x2="2" y2="2.55" stroke="#222" stroke-width="0.1" marker-end="url(#arrowhead)"/>
|
|
13
|
+
<line x1="2" y1="3" x2="2" y2="4.55" stroke="#222" stroke-width="0.1" marker-end="url(#arrowhead)"/>
|
|
14
|
+
<line x1="3" y1="1" x2="3" y2="3.55" stroke="#222" stroke-width="0.1" marker-end="url(#arrowhead)"/>
|
|
15
|
+
<line x1="3" y1="4" x2="3" y2="5.55" stroke="#222" stroke-width="0.1" marker-end="url(#arrowhead)"/>
|
|
16
|
+
<line x1="2" y1="5" x2="1.4" y2="5.6" stroke="#222" stroke-width="0.1" marker-end="url(#arrowhead)"/>
|
|
17
|
+
</svg>
|