@sjtdev/koishi-plugin-dota2tracker 2.2.2 → 2.3.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 (106) hide show
  1. package/changelog.md +32 -0
  2. package/dist/index.js +1 -1
  3. package/lib/index.js +128 -94
  4. package/{queries → lib/queries}/MatchInfo.graphql +13 -0
  5. package/lib/templates/common/components/building_icons.ejs +20 -0
  6. package/lib/templates/common/styles/normalize.min.css +1 -0
  7. package/lib/templates/hero/hero_1.ejs +69 -0
  8. package/lib/templates/images/7.38_simple_minimap.png +0 -0
  9. package/lib/templates/item/item/recipe.ejs +9 -0
  10. package/lib/templates/item/item/style.css +1 -0
  11. package/lib/templates/item/item.ejs +52 -0
  12. package/lib/templates/item/itemlist.ejs +11 -0
  13. package/lib/templates/match/match_1/base.css +1 -0
  14. package/lib/templates/match/match_1/item.ejs +1 -0
  15. package/lib/templates/match/match_1/main.ejs +8 -0
  16. package/lib/templates/match/match_1/player.ejs +1 -0
  17. package/lib/templates/match/match_1/style.css +1 -0
  18. package/lib/templates/match/match_1.ejs +18 -0
  19. package/lib/templates/match/match_2/original.css +1 -0
  20. package/lib/templates/match/match_2/original.ejs +10 -0
  21. package/lib/templates/match/match_2+/charts.ejs +1 -0
  22. package/lib/templates/match/match_2+/extra.css +1 -0
  23. package/lib/templates/match/match_2+/lane_outcome.ejs +56 -0
  24. package/lib/templates/match/match_2+/map.ejs +160 -0
  25. package/lib/templates/match/match_2+.ejs +1 -0
  26. package/lib/templates/match/match_2.ejs +1 -0
  27. package/lib/templates/player/player_1/base.css +1 -0
  28. package/lib/templates/player/player_1/private.ejs +1 -0
  29. package/lib/templates/player/player_1.ejs +78 -0
  30. package/lib/templates/rank/rank_fun.ejs +1 -0
  31. package/lib/templates/report/daily/base.css +1 -0
  32. package/lib/templates/report/daily.ejs +29 -0
  33. package/package.json +2 -2
  34. package/template/hero/hero_1.ejs +0 -900
  35. package/template/item/item/recipe.ejs +0 -51
  36. package/template/item/item/style.css +0 -244
  37. package/template/item/item.ejs +0 -140
  38. package/template/item/itemlist.ejs +0 -99
  39. package/template/match/match_1/item.ejs +0 -11
  40. package/template/match/match_1/main.ejs +0 -37
  41. package/template/match/match_1/player.ejs +0 -154
  42. package/template/match/match_1/style.css +0 -764
  43. package/template/match/match_1.ejs +0 -56
  44. package/template/match/match_2/original.css +0 -463
  45. package/template/match/match_2/original.ejs +0 -192
  46. package/template/match/match_2+/charts.ejs +0 -261
  47. package/template/match/match_2+/extra.css +0 -143
  48. package/template/match/match_2+/lane_outcome.ejs +0 -157
  49. package/template/match/match_2+.ejs +0 -27
  50. package/template/match/match_2.ejs +0 -18
  51. package/template/player/player_1/private.ejs +0 -5
  52. package/template/player/player_1.ejs +0 -654
  53. package/template/rank/rank_fun.ejs +0 -131
  54. package/template/report/daily.ejs +0 -191
  55. /package/{queries → lib/queries}/Constants.graphql +0 -0
  56. /package/{queries → lib/queries}/GetWeeklyMetaByPosition.graphql +0 -0
  57. /package/{queries → lib/queries}/PlayerExtraInfo.graphql +0 -0
  58. /package/{queries → lib/queries}/PlayerInfoWith25Matches.graphql +0 -0
  59. /package/{queries → lib/queries}/PlayerPerformanceForHeroRecommendation.graphql +0 -0
  60. /package/{queries → lib/queries}/PlayersInfoWith10MatchesForGuild.graphql +0 -0
  61. /package/{queries → lib/queries}/PlayersLastmatchRankinfo.graphql +0 -0
  62. /package/{queries → lib/queries}/PlayersMatchesForDaily.graphql +0 -0
  63. /package/{queries → lib/queries}/RequestMatchDataAnalysis.graphql +0 -0
  64. /package/{queries → lib/queries}/VerifyingPlayer.graphql +0 -0
  65. /package/{template → lib/templates}/images/bei.jpg +0 -0
  66. /package/{template → lib/templates}/images/disconnected.png +0 -0
  67. /package/{template → lib/templates}/images/flag_dire.png +0 -0
  68. /package/{template → lib/templates}/images/flag_radiant.png +0 -0
  69. /package/{template → lib/templates}/images/hero_badge_1.png +0 -0
  70. /package/{template → lib/templates}/images/hero_badge_2.png +0 -0
  71. /package/{template → lib/templates}/images/hero_badge_3.png +0 -0
  72. /package/{template → lib/templates}/images/hero_badge_4.png +0 -0
  73. /package/{template → lib/templates}/images/hero_badge_5.png +0 -0
  74. /package/{template → lib/templates}/images/hero_badge_6.png +0 -0
  75. /package/{template → lib/templates}/images/lane_fail.svg +0 -0
  76. /package/{template → lib/templates}/images/lane_jungle.svg +0 -0
  77. /package/{template → lib/templates}/images/lane_stomp.svg +0 -0
  78. /package/{template → lib/templates}/images/lane_stomped.svg +0 -0
  79. /package/{template → lib/templates}/images/lane_tie.svg +0 -0
  80. /package/{template → lib/templates}/images/lane_victory.svg +0 -0
  81. /package/{template → lib/templates}/images/logo_dire.png +0 -0
  82. /package/{template → lib/templates}/images/logo_radiant.png +0 -0
  83. /package/{template → lib/templates}/images/medal_0.png +0 -0
  84. /package/{template → lib/templates}/images/medal_1.png +0 -0
  85. /package/{template → lib/templates}/images/medal_2.png +0 -0
  86. /package/{template → lib/templates}/images/medal_3.png +0 -0
  87. /package/{template → lib/templates}/images/medal_4.png +0 -0
  88. /package/{template → lib/templates}/images/medal_5.png +0 -0
  89. /package/{template → lib/templates}/images/medal_6.png +0 -0
  90. /package/{template → lib/templates}/images/medal_7.png +0 -0
  91. /package/{template → lib/templates}/images/medal_8.png +0 -0
  92. /package/{template → lib/templates}/images/medal_8b.png +0 -0
  93. /package/{template → lib/templates}/images/medal_8c.png +0 -0
  94. /package/{template → lib/templates}/images/scepter.png +0 -0
  95. /package/{template → lib/templates}/images/scepter_0.png +0 -0
  96. /package/{template → lib/templates}/images/scepter_1.png +0 -0
  97. /package/{template → lib/templates}/images/shard.png +0 -0
  98. /package/{template → lib/templates}/images/shard_0.png +0 -0
  99. /package/{template → lib/templates}/images/shard_1.png +0 -0
  100. /package/{template → lib/templates}/images/star_0.png +0 -0
  101. /package/{template → lib/templates}/images/star_1.png +0 -0
  102. /package/{template → lib/templates}/images/star_2.png +0 -0
  103. /package/{template → lib/templates}/images/star_3.png +0 -0
  104. /package/{template → lib/templates}/images/star_4.png +0 -0
  105. /package/{template → lib/templates}/images/star_5.png +0 -0
  106. /package/{template → lib/templates}/images/xi.jpg +0 -0
@@ -1,900 +0,0 @@
1
- <!DOCTYPE html>
2
- <html lang="<%= languageTag %>">
3
- <head>
4
- <meta charset="UTF-8" />
5
- <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
- <title>Document</title>
7
- <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/normalize/8.0.1/normalize.min.css" />
8
- <style>
9
- html,
10
- body {
11
- background-color: black;
12
- color: white;
13
- width: 800px;
14
- }
15
-
16
- .wrapper > *:not(.skills) {
17
- margin: 5px;
18
- box-shadow: 0 0 5px #fff;
19
- display: flex;
20
- }
21
-
22
- img {
23
- width: 100%;
24
- vertical-align: middle;
25
- }
26
-
27
- p {
28
- margin: 0;
29
- }
30
-
31
- .hero {
32
- position: relative;
33
- }
34
-
35
- .hero img {
36
- /* flex-grow: 1; */
37
- width: 25%;
38
- }
39
-
40
- .hero .pri_attr {
41
- position: absolute;
42
- width: 48px;
43
- left: 25%;
44
- }
45
-
46
- .hero .info {
47
- display: flex;
48
- width: 75%;
49
- /* height: 100%; */
50
- flex-direction: column;
51
- justify-content: space-around;
52
- align-items: center;
53
- padding: 4px;
54
- }
55
-
56
- .hero .info .name {
57
- font-size: 24px;
58
- }
59
-
60
- .hero .info .roles .role {
61
- font-size: 14px;
62
- }
63
-
64
- .hero .info .roles .role:not(:last-child) {
65
- margin-right: 12px;
66
- }
67
-
68
- .hero .info .roles .role::after {
69
- margin-left: 3px;
70
- font-size: 22px;
71
- }
72
-
73
- .hero .info .roles .role.level1::after {
74
- content: "■□□";
75
- }
76
-
77
- .hero .info .roles .role.level2::after {
78
- content: "■■□";
79
- }
80
-
81
- .hero .info .roles .role.level3::after {
82
- content: "■■■";
83
- }
84
-
85
- .hero .info .attrs {
86
- height: 16px;
87
- font-size: 16px;
88
- line-height: 1;
89
- }
90
- .hero .info .attrs > span {
91
- margin: 0 8px;
92
- vertical-align: middle;
93
- }
94
-
95
- .hero .info .attrs > span::before {
96
- display: inline-block;
97
- content: "";
98
- background-size: 100%;
99
- width: 16px;
100
- height: 16px;
101
- vertical-align: top;
102
- }
103
-
104
- .hero .info .attrs > span.str::before {
105
- background-image: url("<%= getImageUrl('hero_strength', ImageType.Icons) %>");
106
- }
107
-
108
- .hero .info .attrs > span.agi::before {
109
- background-image: url("<%= getImageUrl('hero_agility', ImageType.Icons) %>");
110
- }
111
-
112
- .hero .info .attrs > span.int::before {
113
- background-image: url("<%= getImageUrl('hero_intelligence', ImageType.Icons) %>");
114
- }
115
-
116
- .details {
117
- flex-direction: row;
118
- }
119
-
120
- .details > * {
121
- width: 50%;
122
- }
123
-
124
- .wrapper .hype {
125
- display: block;
126
- padding: 8px;
127
- line-height: 1.25;
128
- }
129
-
130
- .wrapper .hype .npe {
131
- color: #a5e0f3;
132
- font-weight: bold;
133
- line-height: 1.25;
134
- margin-bottom: 8px;
135
- }
136
-
137
- .talents {
138
- display: grid;
139
- grid-template-rows: repeat(4, 35px);
140
- gap: 10px;
141
- border: #444 10px solid;
142
- box-sizing: border-box;
143
- position: relative; /* 添加相对定位 */
144
- }
145
-
146
- .talents::before {
147
- content: "";
148
- position: absolute;
149
- top: 0;
150
- left: 0;
151
- right: 0;
152
- bottom: 0;
153
- background: #444;
154
- pointer-events: none; /* 使伪元素不可点击 */
155
- box-sizing: border-box;
156
- width: 395px;
157
- transform: translate(-10px, -10px); /* 调整伪元素的位置 */
158
- }
159
-
160
- .talents .talent {
161
- width: 375px;
162
- text-align: center;
163
- display: flex;
164
- align-items: center;
165
- background: #000; /* 设置背景颜色以覆盖伪元素的背景 */
166
- position: relative; /* 添加相对定位 */
167
- }
168
-
169
- .talents .talent .left,
170
- .talents .talent .right {
171
- width: 170px;
172
- font-size: 12px;
173
- }
174
-
175
- .talents .talent .level {
176
- flex: 0 0 auto;
177
- width: 35px;
178
- height: 35px;
179
- font-size: 18px;
180
- line-height: 35px;
181
- text-align: center;
182
- box-sizing: border-box;
183
- border-radius: 100%;
184
- color: #e7d292;
185
- text-shadow: 0px 0px 8px #ff531c;
186
- background-color: #444;
187
- }
188
-
189
- .details .list table td {
190
- width: 50%;
191
- text-align: center;
192
- }
193
-
194
- .details .list table tr:nth-child(even) {
195
- background-color: #333;
196
- }
197
-
198
- .details .list {
199
- display: flex;
200
- flex-direction: column;
201
- padding: 6px;
202
- }
203
-
204
- .details .list > * {
205
- flex-grow: 1;
206
- }
207
-
208
- .details .bars {
209
- height: 64px;
210
- flex-grow: 0;
211
- }
212
-
213
- .details .bars > div {
214
- height: 28px;
215
- margin-bottom: 4px;
216
- border-radius: 5px; /* 可选:圆角效果 */
217
- box-shadow: inset 0 0 2px rgba(0, 0, 0, 0.5), 0 0 2px rgba(0, 0, 0, 0.3);
218
- position: relative;
219
- display: flex;
220
- align-items: center;
221
- }
222
- .details .bars .health {
223
- background: linear-gradient(to top, #279027 0%, #27a329 56%, #96e891 83%, #366a35 100%);
224
- }
225
- .details .bars .mana {
226
- background: linear-gradient(to top, #4676c4 0%, #2b76d5 56%, #95cdff 100%);
227
- }
228
- .details .bars .mana.zero {
229
- background: none;
230
- }
231
- .details .bars span {
232
- text-shadow: #000 1px 1px 4px;
233
- }
234
- .details .bars .number {
235
- font-size: 18px; /* 数字文本大小 */
236
- position: absolute; /* 绝对定位 */
237
- left: 50%; /* 左侧50% */
238
- transform: translateX(-50%); /* 水平居中 */
239
- }
240
- .details .bars .suffix {
241
- margin-left: auto; /* 将右侧文本推到容器的最右边 */
242
- font-size: 14px; /* 较小的字体 */
243
- padding-right: 10px; /* 右侧留些间距 */
244
- }
245
-
246
- .details .stats {
247
- display: flex;
248
- justify-content: space-around;
249
- line-height: 1.3;
250
- }
251
- .details .stats > .column > p{
252
- padding: 4px;
253
- color: #B2B2B2;
254
- }
255
- .details .stats .stat img {
256
- width: 20px;
257
- }
258
-
259
- .facets {
260
- display: flex;
261
- flex-wrap: wrap;
262
- gap: 10px; /* 可选:设置项目之间的间距 */
263
- }
264
-
265
- .facets > .facet,
266
- .skill > .facet {
267
- flex: 1 1 calc(50% - 10px); /* 每行两个项目 */
268
- box-sizing: border-box; /* 包含padding和border在宽度和高度的计算中 */
269
- background-color: #181f24;
270
- position: relative;
271
- border: 1px solid #2b2f33;
272
- }
273
-
274
- .facets > .facet:nth-child(odd):last-child {
275
- flex-basis: 100%; /* 最后一个奇数项目占据整行 */
276
- }
277
- .facets > .facet > .name_back,
278
- .skill > .facet > .name_back {
279
- position: absolute;
280
- height: 50px;
281
- width: 100%;
282
- }
283
- .facet > .name_back.type_0 {
284
- background: linear-gradient(to right, #9f3c3c, #4a2026);
285
- }
286
- .facet > .name_line.type_0 {
287
- filter: invert(22%) sepia(100%) saturate(100%) hue-rotate(316deg) brightness(98%) contrast(100%);
288
- }
289
- .facet > .name_back.type_1 {
290
- background: linear-gradient(to right, #c8a45c, #6f3d21);
291
- }
292
- .facet > .name_line.type_1 {
293
- filter: invert(54%) sepia(99%) saturate(100%) hue-rotate(0deg) brightness(97%) contrast(100%);
294
- }
295
- .facet > .name_back.type_2 {
296
- background: linear-gradient(to right, #a2b23e, #2d5a18);
297
- }
298
- .facet > .name_line.type_2 {
299
- filter: invert(57%) sepia(100%) saturate(100%) hue-rotate(32deg) brightness(93%) contrast(100%);
300
- }
301
- .facet > .name_back.type_3 {
302
- background: linear-gradient(to right, #547ea6, #2a385e);
303
- }
304
- .facet > .name_line.type_3 {
305
- filter: invert(39%) sepia(100%) saturate(99%) hue-rotate(167deg) brightness(99%) contrast(100%);
306
- }
307
- .facet > .name_back.type_4 {
308
- background: linear-gradient(to right, #675cae, #261c44);
309
- }
310
- .facet > .name_line.type_4 {
311
- filter: invert(33%) sepia(100%) saturate(100%) hue-rotate(207deg) brightness(99%) contrast(100%);
312
- }
313
- .facet > .name_back.type_5 {
314
- background: linear-gradient(to right, #adb6be, #4e5557);
315
- }
316
- .facet > .name_line.type_5 {
317
- filter: invert(73%) sepia(23%) saturate(99%) hue-rotate(166deg) brightness(93%) contrast(94%);
318
- }
319
- .facet > .name_line {
320
- position: absolute;
321
- background-size: cover;
322
- height: 50px;
323
- width: 100%;
324
- background-image: url("https://cdn.akamai.steamstatic.com/apps/dota2/images/dota_react/icons/facets/ripple_texture.png");
325
- }
326
- .facet > .name {
327
- height: 50px;
328
- line-height: 50px;
329
- z-index: 1;
330
- position: relative;
331
- display: flex;
332
- }
333
- .facet > .name > img {
334
- width: 24px;
335
- padding: 13px;
336
- background-color: #0003;
337
- }
338
- .facet > .name > span {
339
- margin-left: 16px;
340
- letter-spacing: 2px;
341
- text-shadow: 2px 2px 3px rgba(0, 0, 0, 0.3), 4px 4px 6px rgba(0, 0, 0, 0.2), 6px 6px 9px rgba(0, 0, 0, 0.1);
342
- }
343
- .facet > .content {
344
- padding: 12px;
345
-
346
- display: flex;
347
- flex-direction: column;
348
- gap: 12px;
349
- }
350
- .facet > .content > .ability {
351
- display: flex;
352
- flex-direction: column;
353
- gap: 12px;
354
- }
355
- .facet > .content > .ability > .name {
356
- background: linear-gradient(to right, #9bcdff17 0%, #9bcdff09 30%, #d0e8ff00 100%);
357
- line-height: 1;
358
- }
359
- .facet > .content > .ability > .name > img {
360
- width: 30px;
361
- }
362
- .facet > .content > .ability > .name > span {
363
- margin-left: 10px;
364
- font-size: 14px;
365
- /* font-weight: bold; */
366
- }
367
- .facet > .content .description {
368
- color: #9ab0cd;
369
- }
370
- .facet > .content > .ability > .attributes {
371
- font-size: 12px;
372
- display: flex;
373
- flex-direction: column;
374
- gap: 5px;
375
- }
376
- .facet > .content > .ability > .attributes .item {
377
- color: #737373;
378
- }
379
- .facet > .content .value {
380
- color: #fff;
381
- }
382
-
383
- .skills {
384
- width: 800px;
385
- display: flex;
386
- flex-wrap: wrap;
387
- }
388
-
389
- .skill {
390
- background-color: #141b1f;
391
- margin: 5px;
392
- box-shadow: 0 0 5px #fff;
393
- width: 390px;
394
- /* flex-direction: column; */
395
- }
396
-
397
- .skill > *:not(:nth-child(2)) {
398
- padding-left: 8px;
399
- }
400
-
401
- .skill > .title {
402
- position: relative;
403
- background-color: #1f272b;
404
- padding: 8px;
405
- font-weight: 100;
406
- height: auto;
407
- width: auto;
408
- }
409
- .skill > .title > .name {
410
- font-family: "KaiTi", "楷体", "楷体_GB2312", "STKaiti", serif;
411
- }
412
- .skill > .title > .is_innate {
413
- font-size: 14px;
414
- line-height: 18px;
415
- width: auto;
416
- display: inline;
417
- padding: 2px 8px;
418
- box-sizing: content-box;
419
- background-color: #5b93d1;
420
- }
421
-
422
- .skill > .title.name_back > img {
423
- width: 16px;
424
- }
425
-
426
- .skill img.scepter,
427
- .skill img.shard {
428
- position: absolute;
429
- width: 24px;
430
- right: 8px;
431
- top: 50%;
432
- transform: translateY(-50%);
433
- }
434
-
435
- .skill .img_stats {
436
- display: flex;
437
- color: #546780;
438
- margin-bottom: 16px;
439
- border-top: #2a363c 1px solid;
440
- border-bottom: #2a363c 1px solid;
441
- }
442
-
443
- .skill .img_stats img {
444
- width: 128px;
445
- }
446
-
447
- .skill .img_stats .stats {
448
- padding: 8px;
449
- }
450
-
451
- .skill .stats .dmg_type.Physical span {
452
- color: #ae2f28;
453
- }
454
-
455
- .skill .stats .dmg_type.Magical span {
456
- color: #5b93d1;
457
- }
458
-
459
- .skill .stats .dmg_type.Pure span {
460
- color: #c29c4a;
461
- }
462
-
463
- .skill .stats .dispellable.Yes span {
464
- /* color: #c29c4a; */
465
- }
466
-
467
- .skill .stats .dispellable.No span {
468
- color: #f00;
469
- }
470
-
471
- .skill .stats .dispellable.Strong span {
472
- color: #9828ae;
473
- }
474
-
475
- .skill .stats .bkbpierce.Yes span {
476
- color: #6add71;
477
- }
478
-
479
- .skill > .description {
480
- color: #9bb1ce;
481
- margin-bottom: 32px;
482
- }
483
-
484
- .skill > .facet {
485
- padding-left: 0;
486
- margin-bottom: 16px;
487
- }
488
-
489
- .skill .value {
490
- color: #fff;
491
- }
492
-
493
- .skill .aghanim_description {
494
- padding-left: 0;
495
- color: #9bb1ce;
496
- margin-bottom: 16px;
497
- border: #263945 solid 3px;
498
- box-sizing: border-box;
499
- }
500
-
501
- .skill .aghanim_description .title {
502
- /* content: "阿哈利姆魔晶"; */
503
- display: block;
504
- font-size: 20px;
505
- background-color: #263945;
506
- padding: 12px;
507
- }
508
-
509
- .skill .aghanim_description .desc {
510
- margin: 12px;
511
- display: block;
512
- }
513
-
514
- .skill .aghanim_description img {
515
- position: unset;
516
- transform: none;
517
- margin-right: 8px;
518
- }
519
-
520
- .skill .notes {
521
- padding: 12px;
522
- margin-bottom: 12px;
523
- color: #9fb7c6;
524
- background-color: #263945;
525
- }
526
-
527
- .skill .attributes {
528
- line-height: 1.2em;
529
- margin-bottom: 12px;
530
- }
531
-
532
- .skill .attributes .heading {
533
- color: #546780;
534
- }
535
-
536
- .skill .attributes .values {
537
- color: #4b525d;
538
- }
539
-
540
- .skill .attributes .values img {
541
- width: 16px;
542
- }
543
-
544
- .skill .attributes .facet {
545
- display: inline-flex;
546
- font-size: 1em;
547
- align-items: center;
548
- line-height: 1.2em;
549
- position: unset;
550
- color: #fff;
551
- }
552
-
553
- .skill .attributes .facet span {
554
- height: auto;
555
- width: auto;
556
- position: unset;
557
- padding: 0 2px;
558
- }
559
-
560
- .skill .attributes .facet img {
561
- width: auto;
562
- height: 1em;
563
- padding-right: 0.2em;
564
- }
565
-
566
- .skill .attributes .alternative .plus {
567
- display: none;
568
- }
569
-
570
- .skill .attributes .primary ~ .alternative .plus {
571
- display: inline;
572
- }
573
- .skill .attributes .primary ~ .alternative::before {
574
- content: "(";
575
- }
576
- .skill .attributes .primary ~ .alternative::after {
577
- content: ")";
578
- }
579
-
580
- .skill .cooldown {
581
- padding-right: 12px;
582
- }
583
-
584
- .skill .cooldown::before,
585
- .skill .mana_cost::before {
586
- content: "";
587
- background-size: 100%;
588
- width: 21px;
589
- height: 21px;
590
- display: inline-block;
591
- vertical-align: middle;
592
- }
593
-
594
- .skill .cooldown::before {
595
- background-image: url("data:image/webp;base64,UklGRnABAABXRUJQVlA4TGMBAAAvE8AEEE2QTdqmkI5pRP/DS2wBEIT/bw8R/U8Ddq1NipSvGnd3eXJ3d3kmEM+GTDwBciCBTQCd7qpCeokBQdu2cc6f8tcQEBT5P9oEIGiwYuMBECqAbCUVIIAa19Py1I/AQMrJVGEABACe+DRqcl2GUxeOwIAzQkAAMCBxyi3BRcbSkzAKyIDTciQOAAgwyx43JA4CWRkeQXAAQKkGEs5+/siARwFHAHCUiAGwPwAEAGQSDgCAoCQUQc7OkwMbhgAAJBIKEAtkE9enBgcABEUxAIwyZ6cOx/lTkPiHsX+mqCQTMQRwcmAszPLUoTiCkVAAbDKEAWWUjWlGMYyEAR4n4wMeiBk8W9M1lphIQmAsmWxBJ1vfAJZIBMAoJwNQ0JTN04/yRaCCftofwWBkAMAjQ6BILaWMsEkFFVTTk/qEETyQlYFXnh9jmABKbkgzNQgemYwnTOKFEgAAOGJAeUbyhQIAAA==");
596
- }
597
-
598
- .skill .mana_cost::before {
599
- background-image: url("data:image/webp;base64,UklGRsYAAABXRUJQVlA4TLkAAAAvE8AEEIfBOIDbtEmdpEDhS8G2kSTF0eteuLOebJz/0KDREgwBAGEu/89yqe5LCyEaDT03NBcLpEXnJgkZKS2dmlqAlNSCgJXURBoNCHAY2bbSvEP0fxzi7sGh//rslRDR/xQxS0bXRkRMmr5Ho8iISY5523Ztr2vabBuaZZLVE99wRqWAUgGFAv4K+Cngo4CXAp4KeCjgroCbAi4KVv7pOnFwF8aP9+fRXeAaMZ63GbXWiIhxGJ0bEQA=");
600
- }
601
-
602
- .skill .lore {
603
- font-size: 13px;
604
- color: #3e4f5b;
605
- padding: 8px;
606
- line-height: 1.25;
607
- }
608
-
609
- body .wrapper > .lore {
610
- /* flex-direction: column; */
611
- display: block;
612
- line-height: 1.25;
613
- padding: 8px;
614
- font-family: "KaiTi", "楷体", "楷体_GB2312", "STKaiti", serif;
615
- color: #aaa;
616
- }
617
- </style>
618
-
619
- <% if (fontFamily) { %>
620
- <%- "<style>" %>
621
- <%- `body { font-family: ${fontFamily}; }` %>
622
- <%- "</style>" %>
623
- <% } %>
624
- </head>
625
- <body>
626
- <% let hero = data; %>
627
- <% if (hero.primary_attr==3) {
628
- const base_damage = Math.floor((hero.str_base+hero.agi_base+hero.int_base)*0.45);
629
- hero.damage_max+=base_damage;
630
- hero.damage_min+=base_damage;
631
- } %>
632
- <% const primary_attrs = { "3": "hero_universal", "0": "hero_strength", "1": "hero_agility", "2": "hero_intelligence" }; %>
633
- <% const hero_dc = dotaconstants.heroes[hero.id]; %>
634
- <div class="wrapper">
635
- <%- `
636
- <div class="hero" id="${hero.id}">
637
- <img src="${getImageUrl(hero["name"].match(/^npc_dota_hero_(.+)$/)[1], ImageType.Heroes)}"/>
638
- <img class="pri_attr" src="${getImageUrl(primary_attrs[hero.primary_attr], ImageType.Icons)}"/>
639
- <div class="info">
640
- <p class="name">${hero.name_loc}</p>
641
- <p class="roles">
642
- ${hero.role_levels.map((item, index) => item>0?`<span class="role level${item}">${$t("dota2tracker.template.roles."+index)}</span>`:"").join("")}
643
- </p>
644
- <p class="attrs">
645
- <span class="str">${hero.str_base} <span class="gain">+${hero.str_gain.toFixed(1)}</span></span>
646
- <span class="agi">${hero.agi_base} <span class="gain">+${hero.agi_gain.toFixed(1)}</span></span>
647
- <span class="int">${hero.int_base} <span class="gain">+${hero.int_gain.toFixed(1)}</span></span>
648
- </p>
649
- </div>
650
- </div>
651
- <div class="hype">
652
- <p class="npe">${hero.npe_desc_loc}</p>
653
- ${hero.hype_loc}
654
- </div>
655
- <div class="details">
656
- <div class="talents">
657
- <div class="talent">
658
- <div class="left">${hero.talents[7].name_loc}</div>
659
- <div class="level">25</div>
660
- <div class="right">${hero.talents[6].name_loc}</div>
661
- </div>
662
- <div class="talent">
663
- <div class="left">${hero.talents[5].name_loc}</div>
664
- <div class="level">20</div>
665
- <div class="right">${hero.talents[4].name_loc}</div>
666
- </div>
667
- <div class="talent">
668
- <div class="left">${hero.talents[3].name_loc}</div>
669
- <div class="level">15</div>
670
- <div class="right">${hero.talents[2].name_loc}</div>
671
- </div>
672
- <div class="talent">
673
- <div class="left">${hero.talents[1].name_loc}</div>
674
- <div class="level">10</div>
675
- <div class="right">${hero.talents[0].name_loc}</div>
676
- </div>
677
- </div>
678
- <div class="list">
679
- <div class="bars">
680
- <div class="health"><span class="number">${hero.max_health}</span><span class="suffix">+${hero.health_regen.toFixed(1)}</span></div>
681
- <div class="mana${!hero.max_mana?" zero":""}"><span class="number">${hero.max_mana}</span><span class="suffix">+${hero.mana_regen.toFixed(1)}</span></div>
682
- </div>
683
- <div class="stats">
684
- <div class="column">
685
- <p>${$t("dota2tracker.template.attack")}</p>
686
- <div class="stat">
687
- <img src="${getImageUrl("icon_damage", ImageType.HeroStats)}"/>
688
- <span>${hero.damage_min}~${hero.damage_max}</span>
689
- </div>
690
- <div class="stat">
691
- <img src="${getImageUrl("icon_attack_time", ImageType.HeroStats)}"/>
692
- <span>${hero.attack_rate.toFixed(1)}</span>
693
- </div>
694
- <div class="stat">
695
- <img src="${getImageUrl("icon_attack_range", ImageType.HeroStats)}"/>
696
- <span>${hero.attack_range}</span>
697
- </div>
698
- <div class="stat${hero_dc.attack_type=="Melee"?" hide":""}">
699
- <img src="${getImageUrl("icon_projectile_speed", ImageType.HeroStats)}"/>
700
- <span>${hero.projectile_speed}</span>
701
- </div>
702
- </div>
703
- <div class="column">
704
- <p>${$t("dota2tracker.template.defense")}</p>
705
- <div class="stat">
706
- <img src="${getImageUrl("icon_armor", ImageType.HeroStats)}"/>
707
- <span>${hero.armor.toFixed(1)}</span>
708
- </div>
709
- <div class="stat">
710
- <img src="${getImageUrl("icon_magic_resist", ImageType.HeroStats)}"/>
711
- <span>${hero.magic_resistance}%</span>
712
- </div>
713
- </div>
714
- <div class="column">
715
- <p>${$t("dota2tracker.template.mobility")}</p>
716
- <div class="stat">
717
- <img src="${getImageUrl("icon_movement_speed", ImageType.HeroStats)}"/>
718
- <span>${hero.movement_speed}</span>
719
- </div>
720
- <div class="stat">
721
- <img src="${getImageUrl("icon_turn_rate", ImageType.HeroStats)}"/>
722
- <span>${hero.turn_rate.toFixed(1)}</span>
723
- </div>
724
- <div class="stat">
725
- <img src="${getImageUrl("icon_vision", ImageType.HeroStats)}"/>
726
- <span>${hero.sight_range_day} / ${hero.sight_range_night}</span>
727
- </div>
728
- </div>
729
- </div>
730
- </div>
731
- </div>
732
- <div class="facets">
733
- ${hero.facets.map(facet=>`
734
- <div class="facet">
735
- <div class="name_back type_${facet.color}"></div>
736
- <div class="name_line type_${facet.color}"></div>
737
- <p class="name">
738
- <img src="${getImageUrl(facet.icon, ImageType.IconsFacets)}"/>
739
- <span>${facet.title_loc}</span>
740
- </p>
741
- <div class="content">
742
- ${facet.description_loc && !facet.abilities?.some(ability => ability.description_ability_loc === facet.description_loc) ?`<p class="description">${facet.description_loc}</p>`:""}
743
- ${facet.abilities?facet.abilities.map(ability=>
744
- `<div class="ability">
745
- <div class="name">
746
- <img src="${getImageUrl(ability.name, ImageType.Abilities)}" onerror="this.onerror=null; this.src='${getImageUrl(`innate_icon`,ImageType.Icons)}';"/>
747
- <span>${ability.name_loc}</span>
748
- </div>
749
- ${ability.description_ability_loc?`<div class="description">${ability.description_ability_loc}</div>`:""}
750
- ${ability.attributes&&ability.attributes?.length ? ability.attributes.map(attr=>
751
- `<div class="attributes">
752
- <p><span class="item">${attr.heading_loc}</span><span class="values">${attr.values.map(value => value + (attr.is_percentage ? "%" : "")).join(" / ")}</span></p>
753
- </div>`).join(""):""}
754
- </div>`).join("")
755
- :""}
756
- </div>
757
- </div>
758
- `).join("")}
759
- </div>
760
- <div class="skills">
761
- ${hero.abilities//.filter((item) => dotaconstants.abilities[item.name]?.behavior != "Hidden")
762
- .map((item) => {const ability_dc = dotaconstants.abilities[item.name]; return `
763
- <div class="skill${item.facet?' facet':''}" data-innate="${item.ability_is_innate&&!item.ability_is_facet}">
764
- <p class="title${item.facet?(' name_back type_' + item.facet?.color):''}">
765
- ${item.facet?`<img src="${getImageUrl(item.facet?.icon, ImageType.IconsFacets)}">`:""}
766
- <span class="name">${item.name_loc}</span>
767
- ${item.ability_is_innate&&!item.ability_is_facet?`<span class="is_innate">${$t("dota2tracker.template.innate")}</span>`:""}
768
- ${item.ability_is_granted_by_scepter ?`<img src="${getImageUrl("scepter")}" class="scepter">`:""}
769
- ${item.ability_is_granted_by_shard ?`<img src="${getImageUrl("shard")}" class="shard">`:""}
770
- </p>
771
- <div class="img_stats">
772
- <img src="${getImageUrl(item.name, ImageType.Abilities)}" onerror="this.onerror=null; this.src='${getImageUrl(`innate_icon`,ImageType.Icons)}';"/>
773
- <div class="stats">
774
- <p class="behavior">${$t("dota2tracker.template.ability")}${[].concat(ability_dc?.behavior)
775
- .filter((beh) => beh !== "Hidden" || !(item.ability_is_granted_by_shard || item.ability_is_granted_by_scepter))
776
- .map((beh) => $t("dota2tracker.template.behavior."+beh)).join("/")}
777
- </p>
778
- ${ability_dc?.target_team ?
779
- `<p class="target_team">${$t("dota2tracker.template.affects")}${[].concat(ability_dc?.target_team)
780
- .map((tt) => $t("dota2tracker.template.target_team."+tt)).join("/")}
781
- </p>` : ""}
782
- ${!Array.isArray(ability_dc?.dmg_type) && ability_dc?.dmg_type ?
783
- `<p class="dmg_type ${ability_dc?.dmg_type}">${$t("dota2tracker.template.damage_type")}<span>${$t("dota2tracker.template.damage_type_"+ability_dc?.dmg_type)}</span></p>` : ""}
784
- ${ability_dc?.dispellable ?
785
- `<p class="dispellable ${ability_dc?.dispellable == "Strong Dispels Only" ? "Strong" : ability_dc?.dispellable}">${$t("dota2tracker.template.dispellable")}<span>${$t("dota2tracker.template."+(ability_dc?.dispellable == "Strong Dispels Only" ? "dispellable_Strong" : ability_dc?.dispellable))}</span></p>` : ""}
786
- ${!Array.isArray(ability_dc?.bkbpierce) && ability_dc?.bkbpierce ?
787
- `<p class="bkbpierce ${ability_dc?.bkbpierce}"> ${$t("dota2tracker.template.bkbpierce")}<span>${$t("dota2tracker.template."+ability_dc?.bkbpierce)}</span></p>` : ""}
788
- </div>
789
- </div>
790
- <p class="description">${item.desc_loc}</p>
791
- ${item.facets_loc
792
- .reduce((acc, facet_loc, index) => {
793
- index = index + (hero.facets.length - item.facets_loc.length);
794
- if (index >= 0) acc.push(facet_loc);
795
- return acc;},[])
796
- .map((facet_loc,index)=>(facet_loc!=""?`
797
- <div class="facet">
798
- <div class="name_back type_${hero.facets[index].color}"></div>
799
- <div class="name_line type_${hero.facets[index].color}"></div>
800
- <p class="name">
801
- <img src="${getImageUrl(hero.facets[index].icon, ImageType.IconsFacets)}" />
802
- <span>${hero.facets[index].title_loc}</span>
803
- </p>
804
- <div class="content">
805
- <div class="ability">
806
- <div class="description">${hero.facets[index].abilities.find(ab=>ab.id==item.id)?.description_ability_loc}</div>
807
- </div>
808
- </div>
809
- </div>
810
- `:"")).join("")}
811
- ${item.ability_has_scepter&&!item.ability_is_granted_by_scepter&&item.scepter_loc
812
- ? `<p class="aghanim_description">
813
- <span class="title"><img src="${getImageUrl("scepter")}"class="scepter">${$t("dota2tracker.template.scepter")}</span>
814
- <span class="desc">${item.scepter_loc}</span>
815
- </p>` : ""}
816
- ${item.ability_has_shard&&!item.ability_is_granted_by_shard&&item.shard_loc
817
- ? `<p class="aghanim_description">
818
- <span class="title"><img src="${getImageUrl("shard")}"class="shard">${$t("dota2tracker.template.shard")}</span>
819
- <span class="desc">${item.shard_loc}</span>
820
- </p>` : ""}
821
- <div class="notes"${!item.notes_loc.length ? ` style="display:none;"` : ""}>
822
- ${item.notes_loc.map((note) => `<p>${note}</p>`).join("")}
823
- </div>
824
- <div class="attributes">
825
- ${item.special_values
826
- .filter(sv => sv.heading_loc)
827
- .map((sv) =>
828
- `<p>
829
- <span class="heading">${sv.heading_loc}</span>
830
- <span class="values">
831
- ${!(sv.values_float?.every(value => value === 0) || sv.values_float.length == 0) ?
832
- `<span class="primary${(sv.values_float.every(value => value === 0) || sv.values_float.length == 0)?" empty":""}">
833
- ${(!((sv.values_float.every(value => value === 0) || sv.values_float.length == 0) && (sv.values_scepter.length || sv.values_shard.length || sv.facet_bonus.name))
834
- ? (sv.values_float.map(value => value + (sv.is_percentage ? "%" : "")).join(" / ")) : "")}
835
- </span>` : "" }
836
- ${sv.values_scepter && sv.values_scepter.length ?
837
- `<span class="alternative scepter">
838
- <img src="${getImageUrl("scepter")}"/>${sv.values_scepter.map(value => (value > 0 ? '<span class="plus">+</span>' : "") + value + (sv.is_percentage ? "%" : "")).join(" / ")}
839
- </span>` : "" }
840
- ${sv.values_shard && sv.values_shard.length ?
841
- `<span class="alternative shard">
842
- <img src="${getImageUrl("shard")}"/>${sv.values_shard.map(value => (value > 0 ? '<span class="plus">+</span>' : "") + value + (sv.is_percentage ? "%" : "")).join(" / ")}
843
- </span>` : "" }
844
- ${sv.facet_bonus.name && hero.facets.some(facet=>facet.name==sv.facet_bonus.name) ?
845
- `<span class="alternative facet">
846
- <span class="facet"><span class="name_back type_${hero.facets.find(facet=>facet.name==sv.facet_bonus.name).color}"><img src="${getImageUrl(hero.facets.find(facet=>facet.name==sv.facet_bonus.name).icon, ImageType.IconsFacets)}" />${sv.facet_bonus.values.map(value => value + (sv.is_percentage ? "%" : "")).join(" / ")}</span></span>
847
- </span>` : "" }
848
- ${sv.bonuses.length ?
849
- `<span class="alternative talent">
850
- ${sv.bonuses.map(bonus=>` <img src="${getImageUrl("talents","icons","svg")}"/>${(bonus.value>0?'<span class="plus">+</span>':"")+bonus.value+(sv.is_percentage?"%":"")}`).join(" ")}
851
- </span>` : "" }
852
- </span>
853
- </p>`)
854
- .join("")}
855
- </div>
856
- <p>
857
- ${item.special_values.find(sv=>sv.name=="AbilityCooldown")?.values_float.length && !(item.special_values.find(sv=>sv.name=="AbilityCooldown").values_float.length === 1 && item.special_values.find(sv=>sv.name=="AbilityCooldown").values_float[0] === 0) ?
858
- `<span class="cooldown"> ${item.special_values.find(sv=>sv.name=="AbilityCooldown").values_float.join(" / ")}
859
- </span>` : ""}
860
- ${item.special_values.find(sv=>sv.name=="AbilityManaCost")?.values_float.length && !(item.special_values.find(sv=>sv.name=="AbilityManaCost").values_float.length === 1 && item.special_values.find(sv=>sv.name=="AbilityManaCost").values_float[0] === 0) ?
861
- `<span class="mana_cost"> ${item.special_values.find(sv=>sv.name=="AbilityManaCost").values_float.join(" / ")}
862
- </span>` : ""}
863
- </p>
864
- <p class="lore"${!item.lore_loc ? ` style="display:none;"` : ""}>${item.lore_loc}</p>
865
- </div>`}).join("")}
866
- </div>
867
- <div class="lore">
868
- ${hero.bio_loc}
869
- </div>` %>
870
- </div>
871
- </body>
872
- <script>
873
- document.addEventListener('DOMContentLoaded', function() {
874
- const items = document.querySelectorAll('.skills > .skill');
875
- items.forEach(item => {
876
- // const name = item.getAttribute('data-name');
877
- const abilityIsInnate = item.getAttribute('data-innate') === 'true';
878
- const img = item.querySelector('.img_stats > img');
879
- const imageUrl = img.src;
880
-
881
- // Check if image exists
882
- const image = new Image();
883
- image.src = imageUrl;
884
- image.onload = function() {
885
- // Image exists, do nothing
886
- };
887
- image.onerror = function() {
888
- // Image doesn't exist
889
- if (abilityIsInnate) {
890
- item.style.order = -1;
891
- item.style.flexBasis = "100%";
892
- img.src = '<%- getImageUrl("innate_icon",ImageType.Icons) %>'; // Set backup image URL
893
- // item.querySelector(".cooldown").style.display = "none";
894
- // item.querySelector(".mana_cost").style.display = "none";
895
- }
896
- };
897
- });
898
- });
899
- </script>
900
- </html>