@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.
Files changed (185) hide show
  1. package/.eslintrc.js +59 -0
  2. package/LICENSE +21 -0
  3. package/README.md +12 -0
  4. package/_config.yml +1 -0
  5. package/compile.js +789 -0
  6. package/docs/Avqest.ttf +0 -0
  7. package/docs/_config.yml +1 -0
  8. package/docs/armor.js +134 -0
  9. package/docs/css/d2font.css +10 -0
  10. package/docs/drops/.vscode/extensions.json +3 -0
  11. package/docs/drops/README.md +7 -0
  12. package/docs/drops/dist/assets/index.12ae3c90.js +6675 -0
  13. package/docs/drops/dist/index.html +24 -0
  14. package/docs/drops/index.html +23 -0
  15. package/docs/drops/package-lock.json +1143 -0
  16. package/docs/drops/package.json +17 -0
  17. package/docs/drops/src/App.vue +870 -0
  18. package/docs/drops/src/main.js +4 -0
  19. package/docs/drops/vite.config.js +8 -0
  20. package/docs/drops.html +10 -0
  21. package/docs/effort.css +118 -0
  22. package/docs/effort.js +367 -0
  23. package/docs/elem-effort.html +130 -0
  24. package/docs/images/0-0.svg +18 -0
  25. package/docs/images/0-1.svg +17 -0
  26. package/docs/images/0-2.svg +17 -0
  27. package/docs/images/1-0.svg +18 -0
  28. package/docs/images/1-1.svg +18 -0
  29. package/docs/images/1-2.svg +17 -0
  30. package/docs/images/2-0.svg +17 -0
  31. package/docs/images/2-1.svg +11 -0
  32. package/docs/images/2-2.svg +18 -0
  33. package/docs/images/3-0.svg +17 -0
  34. package/docs/images/3-1.svg +18 -0
  35. package/docs/images/3-2.svg +18 -0
  36. package/docs/images/4-0.svg +18 -0
  37. package/docs/images/4-1.svg +18 -0
  38. package/docs/images/4-2.svg +18 -0
  39. package/docs/images/5-0.svg +18 -0
  40. package/docs/images/5-1.svg +18 -0
  41. package/docs/images/5-2.svg +14 -0
  42. package/docs/images/6-0.svg +17 -0
  43. package/docs/images/6-1.svg +17 -0
  44. package/docs/images/6-2.svg +17 -0
  45. package/docs/images/AmSkillicon.png +0 -0
  46. package/docs/images/AsSkillicon.png +0 -0
  47. package/docs/images/BaSkillicon.png +0 -0
  48. package/docs/images/DrSkillicon.png +0 -0
  49. package/docs/images/NeSkillicon.png +0 -0
  50. package/docs/images/PaSkillicon.png +0 -0
  51. package/docs/images/Skillicon.png +0 -0
  52. package/docs/images/SoSkillicon.png +0 -0
  53. package/docs/index.md +5 -0
  54. package/docs/items.html +170 -0
  55. package/docs/leveling/.vscode/extensions.json +3 -0
  56. package/docs/leveling/README.md +7 -0
  57. package/docs/leveling/dist/assets/index.f9765357.js +1 -0
  58. package/docs/leveling/dist/index.html +24 -0
  59. package/docs/leveling/index.html +23 -0
  60. package/docs/leveling/package-lock.json +1143 -0
  61. package/docs/leveling/package.json +17 -0
  62. package/docs/leveling/src/App.vue +526 -0
  63. package/docs/leveling/src/main.js +4 -0
  64. package/docs/leveling/vite.config.js +8 -0
  65. package/docs/runewords/.vscode/extensions.json +3 -0
  66. package/docs/runewords/README.md +7 -0
  67. package/docs/runewords/dist/assets/index.0838f27c.js +6673 -0
  68. package/docs/runewords/dist/assets/index.73bf3e23.css +1 -0
  69. package/docs/runewords/dist/index.html +25 -0
  70. package/docs/runewords/index.html +23 -0
  71. package/docs/runewords/package-lock.json +1143 -0
  72. package/docs/runewords/package.json +17 -0
  73. package/docs/runewords/src/App.vue +781 -0
  74. package/docs/runewords/src/main.js +4 -0
  75. package/docs/runewords/src/modorder.json +234 -0
  76. package/docs/runewords/vite.config.js +8 -0
  77. package/docs/skills.css +1250 -0
  78. package/docs/skills.html +63 -0
  79. package/docs/skills.js +2192 -0
  80. package/docs/vue-setup.js +12 -0
  81. package/docs/weapons.js +149 -0
  82. package/font-example.html +34 -0
  83. package/json/.gitkeep +0 -0
  84. package/json/actinfo.json +116 -0
  85. package/json/armor.json +17232 -0
  86. package/json/armtype.json +17 -0
  87. package/json/atomic.json +1026 -0
  88. package/json/automagic.json +696 -0
  89. package/json/automap.json +40732 -0
  90. package/json/belts.json +743 -0
  91. package/json/bodylocs.json +52 -0
  92. package/json/books.json +34 -0
  93. package/json/charstats.json +525 -0
  94. package/json/colors.json +107 -0
  95. package/json/compcode.json +577 -0
  96. package/json/composit.json +82 -0
  97. package/json/cubemain.json +2112 -0
  98. package/json/cubemod.json +57 -0
  99. package/json/difficultylevels.json +110 -0
  100. package/json/elemtypes.json +62 -0
  101. package/json/events.json +72 -0
  102. package/json/experience.json +1214 -0
  103. package/json/gamble.json +520 -0
  104. package/json/gems.json +1868 -0
  105. package/json/hireling.json +7640 -0
  106. package/json/hitclass.json +67 -0
  107. package/json/inventory.json +2148 -0
  108. package/json/itemratio.json +134 -0
  109. package/json/items.json +54705 -0
  110. package/json/itemstatcost.json +5503 -0
  111. package/json/itemtypes.json +2567 -0
  112. package/json/levels.json +15515 -0
  113. package/json/localestrings-chi.json +8717 -0
  114. package/json/localestrings-deu.json +8717 -0
  115. package/json/localestrings-eng.json +8722 -0
  116. package/json/localestrings-esp.json +8717 -0
  117. package/json/localestrings-fra.json +8718 -0
  118. package/json/localestrings-ita.json +8717 -0
  119. package/json/localestrings-kor.json +8715 -0
  120. package/json/localestrings-pol.json +8716 -0
  121. package/json/lowqualityitems.json +6 -0
  122. package/json/lvlmaze.json +910 -0
  123. package/json/lvlprest.json +28595 -0
  124. package/json/lvlsub.json +824 -0
  125. package/json/lvltypes.json +1377 -0
  126. package/json/lvlwarp.json +1515 -0
  127. package/json/magicprefix.json +12349 -0
  128. package/json/magicsuffix.json +13833 -0
  129. package/json/misc.json +11602 -0
  130. package/json/misscalc.json +217 -0
  131. package/json/missiles.json +23871 -0
  132. package/json/monai.json +1111 -0
  133. package/json/moncountest.json +642 -0
  134. package/json/monequip.json +361 -0
  135. package/json/monlvl.json +3665 -0
  136. package/json/monmode.json +98 -0
  137. package/json/monplace.json +39 -0
  138. package/json/monpopulationest.json +17383 -0
  139. package/json/monpreset.json +922 -0
  140. package/json/monprop.json +144 -0
  141. package/json/monseq.json +5211 -0
  142. package/json/monsounds.json +2530 -0
  143. package/json/monstats.json +66101 -0
  144. package/json/monstats2.json +34882 -0
  145. package/json/montype.json +274 -0
  146. package/json/monumod.json +504 -0
  147. package/json/npc.json +232 -0
  148. package/json/objects.json +87041 -0
  149. package/json/objgroup.json +3733 -0
  150. package/json/objmode.json +42 -0
  151. package/json/objpreset.json +2906 -0
  152. package/json/objtype.json +2457 -0
  153. package/json/overlay.json +8008 -0
  154. package/json/pettype.json +226 -0
  155. package/json/playerclass.json +39 -0
  156. package/json/plrmode.json +122 -0
  157. package/json/plrtype.json +39 -0
  158. package/json/properties.json +2823 -0
  159. package/json/qualityitems.json +149 -0
  160. package/json/rareprefix.json +296 -0
  161. package/json/raresuffix.json +921 -0
  162. package/json/runes.json +3280 -0
  163. package/json/setitems.json +3871 -0
  164. package/json/sets.json +1001 -0
  165. package/json/shrines.json +319 -0
  166. package/json/skillcalc.json +457 -0
  167. package/json/skilldesc.json +7532 -0
  168. package/json/skills.json +16717 -0
  169. package/json/soundenviron.json +2862 -0
  170. package/json/sounds.json +446543 -0
  171. package/json/states.json +1578 -0
  172. package/json/storepage.json +22 -0
  173. package/json/superuniques.json +1405 -0
  174. package/json/tcprecalc.json +29302 -0
  175. package/json/treasureclassex.json +14932 -0
  176. package/json/treasureclassgroupsex.json +711 -0
  177. package/json/uniqueappellation.json +27 -0
  178. package/json/uniqueitems.json +14171 -0
  179. package/json/uniqueprefix.json +55 -0
  180. package/json/uniquesuffix.json +71 -0
  181. package/json/wanderingmon.json +3 -0
  182. package/json/weapons.json +25875 -0
  183. package/objext.js +53 -0
  184. package/package.json +16 -0
  185. package/string.js +42 -0
@@ -0,0 +1,4 @@
1
+ import { createApp } from 'vue';
2
+ import App from './App.vue';
3
+
4
+ createApp(App).mount('#app');
@@ -0,0 +1,8 @@
1
+ import { defineConfig } from 'vite'
2
+ import vue from '@vitejs/plugin-vue'
3
+
4
+ // https://vitejs.dev/config/
5
+ export default defineConfig({
6
+ base: '',
7
+ plugins: [vue()]
8
+ })
@@ -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>
@@ -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>&nbsp;</div>
48
+ </div>
49
+ <table class="element-table">
50
+ <tr>
51
+ <td>&nbsp</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>