d2s 0.1.1

Read and write Diablo 2 save files (.d2s character saves and .d2i shared stash files). Supports D2 LOD (version 96) and D2 Resurrected (version 97-105) formats.
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
//! Stat identifiers (rows of ItemStatCost.txt).

/// A stat identifier (row index in ItemStatCost.txt).
///
/// Stored as a 9-bit value in save files. Unknown or modded IDs are preserved as-is.
#[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Default)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "serde", serde(transparent))]
pub struct StatId(pub u16);

#[allow(missing_docs)]
impl StatId {
    pub const STRENGTH: StatId = StatId(0);
    pub const ENERGY: StatId = StatId(1);
    pub const DEXTERITY: StatId = StatId(2);
    pub const VITALITY: StatId = StatId(3);
    pub const STAT_POINTS: StatId = StatId(4);
    pub const SKILL_POINTS: StatId = StatId(5);
    pub const LIFE: StatId = StatId(6);
    pub const MAX_LIFE: StatId = StatId(7);
    pub const MANA: StatId = StatId(8);
    pub const MAX_MANA: StatId = StatId(9);
    pub const STAMINA: StatId = StatId(10);
    pub const MAX_STAMINA: StatId = StatId(11);
    pub const LEVEL: StatId = StatId(12);
    pub const EXPERIENCE: StatId = StatId(13);
    pub const GOLD: StatId = StatId(14);
    pub const STASH_GOLD: StatId = StatId(15);
    pub const ARMOR_PERCENT: StatId = StatId(16);
    pub const MAX_DAMAGE_PERCENT: StatId = StatId(17);
    pub const MIN_DAMAGE_PERCENT: StatId = StatId(18);
    pub const ATTACK_RATING: StatId = StatId(19);
    pub const CHANCE_TO_BLOCK: StatId = StatId(20);
    pub const MIN_DAMAGE: StatId = StatId(21);
    pub const MAX_DAMAGE: StatId = StatId(22);
    pub const SECOND_MIN_DAMAGE: StatId = StatId(23);
    pub const SECOND_MAX_DAMAGE: StatId = StatId(24);
    pub const DAMAGE_PERCENT: StatId = StatId(25);
    pub const MANA_RECOVERY: StatId = StatId(26);
    pub const MANA_RECOVERY_BONUS: StatId = StatId(27);
    pub const STAMINA_RECOVERY_BONUS: StatId = StatId(28);
    pub const LAST_EXP: StatId = StatId(29);
    pub const NEXT_EXP: StatId = StatId(30);
    pub const ARMOR_CLASS: StatId = StatId(31);
    pub const DEFENSE_VS_MISSILES: StatId = StatId(32);
    pub const DEFENSE_VS_HTH: StatId = StatId(33);
    pub const NORMAL_DAMAGE_REDUCTION: StatId = StatId(34);
    pub const MAGIC_DAMAGE_REDUCTION: StatId = StatId(35);
    pub const DAMAGE_REDUCED: StatId = StatId(36);
    pub const MAGIC_RESIST: StatId = StatId(37);
    pub const MAX_MAGIC_RESIST: StatId = StatId(38);
    pub const FIRE_RESIST: StatId = StatId(39);
    pub const MAX_FIRE_RESIST: StatId = StatId(40);
    pub const LIGHTNING_RESIST: StatId = StatId(41);
    pub const MAX_LIGHTNING_RESIST: StatId = StatId(42);
    pub const COLD_RESIST: StatId = StatId(43);
    pub const MAX_COLD_RESIST: StatId = StatId(44);
    pub const POISON_RESIST: StatId = StatId(45);
    pub const MAX_POISON_RESIST: StatId = StatId(46);
    pub const DAMAGE_AURA: StatId = StatId(47);
    pub const FIRE_MIN_DAMAGE: StatId = StatId(48);
    pub const FIRE_MAX_DAMAGE: StatId = StatId(49);
    pub const LIGHTNING_MIN_DAMAGE: StatId = StatId(50);
    pub const LIGHTNING_MAX_DAMAGE: StatId = StatId(51);
    pub const MAGIC_MIN_DAMAGE: StatId = StatId(52);
    pub const MAGIC_MAX_DAMAGE: StatId = StatId(53);
    pub const COLD_MIN_DAMAGE: StatId = StatId(54);
    pub const COLD_MAX_DAMAGE: StatId = StatId(55);
    pub const COLD_LENGTH: StatId = StatId(56);
    pub const POISON_MIN_DAMAGE: StatId = StatId(57);
    pub const POISON_MAX_DAMAGE: StatId = StatId(58);
    pub const POISON_LENGTH: StatId = StatId(59);
    pub const LIFE_STEAL: StatId = StatId(60);
    pub const LIFE_STEAL_MAX: StatId = StatId(61);
    pub const MANA_STEAL: StatId = StatId(62);
    pub const MANA_STEAL_MAX: StatId = StatId(63);
    pub const STAMINA_DRAIN_MIN_DAMAGE: StatId = StatId(64);
    pub const STAMINA_DRAIN_MAX_DAMAGE: StatId = StatId(65);
    pub const STUN_LENGTH: StatId = StatId(66);
    pub const VELOCITY_PERCENT: StatId = StatId(67);
    pub const ATTACK_RATE: StatId = StatId(68);
    pub const OTHER_ANIM_RATE: StatId = StatId(69);
    pub const QUANTITY: StatId = StatId(70);
    pub const VALUE: StatId = StatId(71);
    pub const DURABILITY: StatId = StatId(72);
    pub const MAX_DURABILITY: StatId = StatId(73);
    pub const HIT_POINT_REGENERATION: StatId = StatId(74);
    pub const MAX_DURABILITY_PERCENT: StatId = StatId(75);
    pub const MAX_HIT_POINT_PERCENT: StatId = StatId(76);
    pub const MAX_MANA_PERCENT: StatId = StatId(77);
    pub const ATTACKER_TAKES_DAMAGE: StatId = StatId(78);
    pub const GOLD_FIND: StatId = StatId(79);
    pub const MAGIC_FIND: StatId = StatId(80);
    pub const KNOCKBACK: StatId = StatId(81);
    pub const TIME_DURATION: StatId = StatId(82);
    pub const ADD_CLASS_SKILLS: StatId = StatId(83);
    pub const UNSENT_PARAM1: StatId = StatId(84);
    pub const ADD_EXPERIENCE: StatId = StatId(85);
    pub const HEAL_AFTER_KILL: StatId = StatId(86);
    pub const REDUCE_PRICES: StatId = StatId(87);
    pub const DOUBLE_HERB_DURATION: StatId = StatId(88);
    pub const LIGHT_RADIUS: StatId = StatId(89);
    pub const LIGHT_COLOR: StatId = StatId(90);
    pub const REQUIREMENT_PERCENT: StatId = StatId(91);
    pub const LEVEL_REQUIRE: StatId = StatId(92);
    pub const INCREASED_ATTACK_SPEED: StatId = StatId(93);
    pub const LEVEL_REQUIRE_PERCENT: StatId = StatId(94);
    pub const LAST_BLOCK_FRAME: StatId = StatId(95);
    pub const FASTER_RUN_WALK: StatId = StatId(96);
    pub const NON_CLASS_SKILL: StatId = StatId(97);
    pub const STATE: StatId = StatId(98);
    pub const FASTER_HIT_RECOVERY: StatId = StatId(99);
    pub const PLAYER_COUNT: StatId = StatId(100);
    pub const POISON_OVERRIDE_LENGTH: StatId = StatId(101);
    pub const FASTER_BLOCK_RATE: StatId = StatId(102);
    pub const BYPASS_UNDEAD: StatId = StatId(103);
    pub const BYPASS_DEMONS: StatId = StatId(104);
    pub const FASTER_CAST_RATE: StatId = StatId(105);
    pub const BYPASS_BEASTS: StatId = StatId(106);
    pub const SINGLE_SKILL: StatId = StatId(107);
    pub const SLAIN_MONSTERS_REST_IN_PEACE: StatId = StatId(108);
    pub const CURSE_RESISTANCE: StatId = StatId(109);
    pub const POISON_LENGTH_RESIST: StatId = StatId(110);
    pub const NORMAL_DAMAGE: StatId = StatId(111);
    pub const HOWL: StatId = StatId(112);
    pub const STUPIDITY: StatId = StatId(113);
    pub const DAMAGE_TAKEN_GOES_TO_MANA: StatId = StatId(114);
    pub const IGNORE_TARGET_DEFENSE: StatId = StatId(115);
    pub const FRACTIONAL_TARGET_DEFENSE: StatId = StatId(116);
    pub const PREVENT_MONSTER_HEAL: StatId = StatId(117);
    pub const HALF_FREEZE_DURATION: StatId = StatId(118);
    pub const ATTACK_RATING_PERCENT: StatId = StatId(119);
    pub const DAMAGE_TARGET_DEFENSE: StatId = StatId(120);
    pub const DEMON_DAMAGE_PERCENT: StatId = StatId(121);
    pub const UNDEAD_DAMAGE_PERCENT: StatId = StatId(122);
    pub const DEMON_ATTACK_RATING: StatId = StatId(123);
    pub const UNDEAD_ATTACK_RATING: StatId = StatId(124);
    pub const THROWABLE: StatId = StatId(125);
    pub const ELEM_SKILLS: StatId = StatId(126);
    pub const ALL_SKILLS: StatId = StatId(127);
    pub const ATTACKER_TAKES_LIGHT_DAMAGE: StatId = StatId(128);
    pub const IRON_MAIDEN_LEVEL: StatId = StatId(129);
    pub const LIFE_TAP_LEVEL: StatId = StatId(130);
    pub const THORNS_PERCENT: StatId = StatId(131);
    pub const BONE_ARMOR: StatId = StatId(132);
    pub const BONE_ARMOR_MAX: StatId = StatId(133);
    pub const FREEZE: StatId = StatId(134);
    pub const OPEN_WOUNDS: StatId = StatId(135);
    pub const CRUSHING_BLOW: StatId = StatId(136);
    pub const KICK_DAMAGE: StatId = StatId(137);
    pub const MANA_AFTER_KILL: StatId = StatId(138);
    pub const HEAL_AFTER_DEMON_KILL: StatId = StatId(139);
    pub const EXTRA_BLOOD: StatId = StatId(140);
    pub const DEADLY_STRIKE: StatId = StatId(141);
    pub const ABSORB_FIRE_PERCENT: StatId = StatId(142);
    pub const ABSORB_FIRE: StatId = StatId(143);
    pub const ABSORB_LIGHTNING_PERCENT: StatId = StatId(144);
    pub const ABSORB_LIGHTNING: StatId = StatId(145);
    pub const ABSORB_MAGIC_PERCENT: StatId = StatId(146);
    pub const ABSORB_MAGIC: StatId = StatId(147);
    pub const ABSORB_COLD_PERCENT: StatId = StatId(148);
    pub const ABSORB_COLD: StatId = StatId(149);
    pub const SLOW: StatId = StatId(150);
    pub const AURA: StatId = StatId(151);
    pub const INDESTRUCTIBLE: StatId = StatId(152);
    pub const CANNOT_BE_FROZEN: StatId = StatId(153);
    pub const STAMINA_DRAIN_PERCENT: StatId = StatId(154);
    pub const REANIMATE: StatId = StatId(155);
    pub const PIERCE: StatId = StatId(156);
    pub const MAGIC_ARROW: StatId = StatId(157);
    pub const EXPLOSIVE_ARROW: StatId = StatId(158);
    pub const THROW_MIN_DAMAGE: StatId = StatId(159);
    pub const THROW_MAX_DAMAGE: StatId = StatId(160);
    pub const SKILL_HAND_OF_ATHENA: StatId = StatId(161);
    pub const SKILL_STAMINA_PERCENT: StatId = StatId(162);
    pub const SKILL_PASSIVE_STAMINA_PERCENT: StatId = StatId(163);
    pub const SKILL_CONCENTRATION: StatId = StatId(164);
    pub const SKILL_ENCHANT: StatId = StatId(165);
    pub const SKILL_PIERCE: StatId = StatId(166);
    pub const SKILL_CONVICTION: StatId = StatId(167);
    pub const SKILL_CHILLING_ARMOR: StatId = StatId(168);
    pub const SKILL_FRENZY: StatId = StatId(169);
    pub const SKILL_DECREPIFY: StatId = StatId(170);
    pub const SKILL_ARMOR_PERCENT: StatId = StatId(171);
    pub const ALIGNMENT: StatId = StatId(172);
    pub const TARGET0: StatId = StatId(173);
    pub const TARGET1: StatId = StatId(174);
    pub const GOLD_LOST: StatId = StatId(175);
    pub const CONVERSION_LEVEL: StatId = StatId(176);
    pub const CONVERSION_MAX_HIT_POINTS: StatId = StatId(177);
    pub const UNIT_DO_OVERLAY: StatId = StatId(178);
    pub const ATTACK_VS_MON_TYPE: StatId = StatId(179);
    pub const DAMAGE_VS_MON_TYPE: StatId = StatId(180);
    pub const FADE: StatId = StatId(181);
    pub const ARMOR_OVERRIDE_PERCENT: StatId = StatId(182);
    pub const LAST_HIT_REACT_FRAME: StatId = StatId(183);
    pub const SEASON: StatId = StatId(184);
    pub const BONUS_MIN_DAMAGE: StatId = StatId(185);
    pub const BONUS_MAX_DAMAGE: StatId = StatId(186);
    pub const PIERCE_COLD_IMMUNITY: StatId = StatId(187);
    pub const ADD_SKILL_TAB: StatId = StatId(188);
    pub const PIERCE_FIRE_IMMUNITY: StatId = StatId(189);
    pub const PIERCE_LIGHT_IMMUNITY: StatId = StatId(190);
    pub const PIERCE_POISON_IMMUNITY: StatId = StatId(191);
    pub const PIERCE_DAMAGE_IMMUNITY: StatId = StatId(192);
    pub const PIERCE_MAGIC_IMMUNITY: StatId = StatId(193);
    pub const NUM_SOCKETS: StatId = StatId(194);
    pub const SKILL_ON_ATTACK: StatId = StatId(195);
    pub const SKILL_ON_KILL: StatId = StatId(196);
    pub const SKILL_ON_DEATH: StatId = StatId(197);
    pub const SKILL_ON_HIT: StatId = StatId(198);
    pub const SKILL_ON_LEVEL_UP: StatId = StatId(199);
    pub const CHARGE_NO_CONSUME: StatId = StatId(200);
    pub const SKILL_ON_GET_HIT: StatId = StatId(201);
    pub const MODIFIER_LIST_CAST_ID: StatId = StatId(202);
    pub const PASSIVE_MASTERY_ITEM_REQUIREMENT_PERCENT: StatId = StatId(203);
    pub const ITEM_CHARGED_SKILL: StatId = StatId(204);
    pub const NO_CONSUME: StatId = StatId(205);
    pub const PASSIVE_MASTERY_NO_CONSUME: StatId = StatId(206);
    pub const PASSIVE_MASTERY_REPLENISH_ON_CRIT: StatId = StatId(207);
    pub const MISSILE_THORNS_PERCENT: StatId = StatId(208);
    pub const PASSIVE_MASTERY_ITEM_LEVEL_REQUIREMENT_PERCENT: StatId = StatId(209);
    pub const UBER_ANCIENTS_ESCALATION: StatId = StatId(210);
    pub const UBER_ANCIENTS_DEFEATED: StatId = StatId(211);
    pub const UNUSED212: StatId = StatId(212);
    pub const PASSIVE_MASTERY_ATTACK_SPEED: StatId = StatId(213);
    pub const ARMOR_PER_LEVEL: StatId = StatId(214);
    pub const ARMOR_PERCENT_PER_LEVEL: StatId = StatId(215);
    pub const LIFE_PER_LEVEL: StatId = StatId(216);
    pub const MANA_PER_LEVEL: StatId = StatId(217);
    pub const MAX_DAMAGE_PER_LEVEL: StatId = StatId(218);
    pub const MAX_DAMAGE_PERCENT_PER_LEVEL: StatId = StatId(219);
    pub const STRENGTH_PER_LEVEL: StatId = StatId(220);
    pub const DEXTERITY_PER_LEVEL: StatId = StatId(221);
    pub const ENERGY_PER_LEVEL: StatId = StatId(222);
    pub const VITALITY_PER_LEVEL: StatId = StatId(223);
    pub const ATTACK_RATING_PER_LEVEL: StatId = StatId(224);
    pub const ATTACK_RATING_PERCENT_PER_LEVEL: StatId = StatId(225);
    pub const COLD_DAMAGE_MAX_PER_LEVEL: StatId = StatId(226);
    pub const FIRE_DAMAGE_MAX_PER_LEVEL: StatId = StatId(227);
    pub const LIGHTNING_DAMAGE_MAX_PER_LEVEL: StatId = StatId(228);
    pub const POISON_DAMAGE_MAX_PER_LEVEL: StatId = StatId(229);
    pub const RESIST_COLD_PER_LEVEL: StatId = StatId(230);
    pub const RESIST_FIRE_PER_LEVEL: StatId = StatId(231);
    pub const RESIST_LIGHTNING_PER_LEVEL: StatId = StatId(232);
    pub const RESIST_POISON_PER_LEVEL: StatId = StatId(233);
    pub const ABSORB_COLD_PER_LEVEL: StatId = StatId(234);
    pub const ABSORB_FIRE_PER_LEVEL: StatId = StatId(235);
    pub const ABSORB_LIGHTNING_PER_LEVEL: StatId = StatId(236);
    pub const ABSORB_POISON_PER_LEVEL: StatId = StatId(237);
    pub const THORNS_PER_LEVEL: StatId = StatId(238);
    pub const FIND_GOLD_PER_LEVEL: StatId = StatId(239);
    pub const MAGIC_FIND_PER_LEVEL: StatId = StatId(240);
    pub const REGEN_STAMINA_PER_LEVEL: StatId = StatId(241);
    pub const STAMINA_PER_LEVEL: StatId = StatId(242);
    pub const DAMAGE_DEMON_PER_LEVEL: StatId = StatId(243);
    pub const DAMAGE_UNDEAD_PER_LEVEL: StatId = StatId(244);
    pub const ATTACK_RATING_DEMON_PER_LEVEL: StatId = StatId(245);
    pub const ATTACK_RATING_UNDEAD_PER_LEVEL: StatId = StatId(246);
    pub const CRUSHING_BLOW_PER_LEVEL: StatId = StatId(247);
    pub const OPEN_WOUNDS_PER_LEVEL: StatId = StatId(248);
    pub const KICK_DAMAGE_PER_LEVEL: StatId = StatId(249);
    pub const DEADLY_STRIKE_PER_LEVEL: StatId = StatId(250);
    pub const FIND_GEMS_PER_LEVEL: StatId = StatId(251);
    pub const REPLENISH_DURABILITY: StatId = StatId(252);
    pub const REPLENISH_QUANTITY: StatId = StatId(253);
    pub const EXTRA_STACK: StatId = StatId(254);
    pub const FIND_ITEM: StatId = StatId(255);
    pub const SLASH_DAMAGE: StatId = StatId(256);
    pub const SLASH_DAMAGE_PERCENT: StatId = StatId(257);
    pub const CRUSH_DAMAGE: StatId = StatId(258);
    pub const CRUSH_DAMAGE_PERCENT: StatId = StatId(259);
    pub const THRUST_DAMAGE: StatId = StatId(260);
    pub const THRUST_DAMAGE_PERCENT: StatId = StatId(261);
    pub const ABSORB_SLASH: StatId = StatId(262);
    pub const ABSORB_CRUSH: StatId = StatId(263);
    pub const ABSORB_THRUST: StatId = StatId(264);
    pub const ABSORB_SLASH_PERCENT: StatId = StatId(265);
    pub const ABSORB_CRUSH_PERCENT: StatId = StatId(266);
    pub const ABSORB_THRUST_PERCENT: StatId = StatId(267);
    pub const ARMOR_BY_TIME: StatId = StatId(268);
    pub const ARMOR_PERCENT_BY_TIME: StatId = StatId(269);
    pub const LIFE_BY_TIME: StatId = StatId(270);
    pub const MANA_BY_TIME: StatId = StatId(271);
    pub const MAX_DAMAGE_BY_TIME: StatId = StatId(272);
    pub const MAX_DAMAGE_PERCENT_BY_TIME: StatId = StatId(273);
    pub const STRENGTH_BY_TIME: StatId = StatId(274);
    pub const DEXTERITY_BY_TIME: StatId = StatId(275);
    pub const ENERGY_BY_TIME: StatId = StatId(276);
    pub const VITALITY_BY_TIME: StatId = StatId(277);
    pub const ATTACK_RATING_BY_TIME: StatId = StatId(278);
    pub const ATTACK_RATING_PERCENT_BY_TIME: StatId = StatId(279);
    pub const COLD_DAMAGE_MAX_BY_TIME: StatId = StatId(280);
    pub const FIRE_DAMAGE_MAX_BY_TIME: StatId = StatId(281);
    pub const LIGHTNING_DAMAGE_MAX_BY_TIME: StatId = StatId(282);
    pub const POISON_DAMAGE_MAX_BY_TIME: StatId = StatId(283);
    pub const RESIST_COLD_BY_TIME: StatId = StatId(284);
    pub const RESIST_FIRE_BY_TIME: StatId = StatId(285);
    pub const RESIST_LIGHTNING_BY_TIME: StatId = StatId(286);
    pub const RESIST_POISON_BY_TIME: StatId = StatId(287);
    pub const ABSORB_COLD_BY_TIME: StatId = StatId(288);
    pub const ABSORB_FIRE_BY_TIME: StatId = StatId(289);
    pub const ABSORB_LIGHTNING_BY_TIME: StatId = StatId(290);
    pub const ABSORB_POISON_BY_TIME: StatId = StatId(291);
    pub const FIND_GOLD_BY_TIME: StatId = StatId(292);
    pub const MAGIC_FIND_BY_TIME: StatId = StatId(293);
    pub const REGEN_STAMINA_BY_TIME: StatId = StatId(294);
    pub const STAMINA_BY_TIME: StatId = StatId(295);
    pub const DAMAGE_DEMON_BY_TIME: StatId = StatId(296);
    pub const DAMAGE_UNDEAD_BY_TIME: StatId = StatId(297);
    pub const ATTACK_RATING_DEMON_BY_TIME: StatId = StatId(298);
    pub const ATTACK_RATING_UNDEAD_BY_TIME: StatId = StatId(299);
    pub const CRUSHING_BLOW_BY_TIME: StatId = StatId(300);
    pub const OPEN_WOUNDS_BY_TIME: StatId = StatId(301);
    pub const KICK_DAMAGE_BY_TIME: StatId = StatId(302);
    pub const DEADLY_STRIKE_BY_TIME: StatId = StatId(303);
    pub const FIND_GEMS_BY_TIME: StatId = StatId(304);
    pub const PIERCE_COLD: StatId = StatId(305);
    pub const PIERCE_FIRE: StatId = StatId(306);
    pub const PIERCE_LIGHTNING: StatId = StatId(307);
    pub const PIERCE_POISON: StatId = StatId(308);
    pub const DAMAGE_VS_MONSTER: StatId = StatId(309);
    pub const DAMAGE_PERCENT_VS_MONSTER: StatId = StatId(310);
    pub const ATTACK_RATING_VS_MONSTER: StatId = StatId(311);
    pub const ATTACK_RATING_PERCENT_VS_MONSTER: StatId = StatId(312);
    pub const AC_VS_MONSTER: StatId = StatId(313);
    pub const AC_PERCENT_VS_MONSTER: StatId = StatId(314);
    pub const FIRE_LENGTH: StatId = StatId(315);
    pub const BURNING_MIN: StatId = StatId(316);
    pub const BURNING_MAX: StatId = StatId(317);
    pub const PROGRESSIVE_DAMAGE: StatId = StatId(318);
    pub const PROGRESSIVE_STEAL: StatId = StatId(319);
    pub const PROGRESSIVE_OTHER: StatId = StatId(320);
    pub const PROGRESSIVE_FIRE: StatId = StatId(321);
    pub const PROGRESSIVE_COLD: StatId = StatId(322);
    pub const PROGRESSIVE_LIGHTNING: StatId = StatId(323);
    pub const EXTRA_CHARGES: StatId = StatId(324);
    pub const PROGRESSIVE_ATTACK_RATING: StatId = StatId(325);
    pub const POISON_COUNT: StatId = StatId(326);
    pub const DAMAGE_FRAME_RATE: StatId = StatId(327);
    pub const PIERCE_IDX: StatId = StatId(328);
    pub const FIRE_SKILL_DAMAGE: StatId = StatId(329);
    pub const LIGHTNING_SKILL_DAMAGE: StatId = StatId(330);
    pub const COLD_SKILL_DAMAGE: StatId = StatId(331);
    pub const POISON_SKILL_DAMAGE: StatId = StatId(332);
    pub const ENEMY_FIRE_RESIST: StatId = StatId(333);
    pub const ENEMY_LIGHTNING_RESIST: StatId = StatId(334);
    pub const ENEMY_COLD_RESIST: StatId = StatId(335);
    pub const ENEMY_POISON_RESIST: StatId = StatId(336);
    pub const PASSIVE_CRITICAL_STRIKE: StatId = StatId(337);
    pub const PASSIVE_DODGE: StatId = StatId(338);
    pub const PASSIVE_AVOID: StatId = StatId(339);
    pub const PASSIVE_EVADE: StatId = StatId(340);
    pub const PASSIVE_WARMTH: StatId = StatId(341);
    pub const PASSIVE_MASTERY_MELEE_ATTACK_RATING: StatId = StatId(342);
    pub const PASSIVE_MASTERY_MELEE_DAMAGE: StatId = StatId(343);
    pub const PASSIVE_MASTERY_MELEE_CRITICAL: StatId = StatId(344);
    pub const PASSIVE_MASTERY_THROW_ATTACK_RATING: StatId = StatId(345);
    pub const PASSIVE_MASTERY_THROW_DAMAGE: StatId = StatId(346);
    pub const PASSIVE_MASTERY_THROW_CRITICAL: StatId = StatId(347);
    pub const PASSIVE_WEAPON_BLOCK: StatId = StatId(348);
    pub const SUMMON_RESIST: StatId = StatId(349);
    pub const MODIFIER_LIST_SKILL: StatId = StatId(350);
    pub const MODIFIER_LIST_LEVEL: StatId = StatId(351);
    pub const LAST_SENT_HIT_POINT_PERCENT: StatId = StatId(352);
    pub const SOURCE_UNIT_TYPE: StatId = StatId(353);
    pub const SOURCE_UNIT_ID: StatId = StatId(354);
    pub const SHORT_PARAM1: StatId = StatId(355);
    pub const QUEST_ITEM_DIFFICULTY: StatId = StatId(356);
    pub const PASSIVE_MAGIC_MASTERY: StatId = StatId(357);
    pub const PASSIVE_MAGIC_PIERCE: StatId = StatId(358);
    pub const SKILL_COOLDOWN: StatId = StatId(359);
    pub const SKILL_MISSILE_DAMAGE_SCALE: StatId = StatId(360);
    pub const SKILL_PSYCHIC_WARD: StatId = StatId(361);
    pub const SKILL_PSYCHIC_WARD_MAX: StatId = StatId(362);
    pub const SKILL_CHANNELING_TICK: StatId = StatId(363);
    pub const CUSTOMIZATION_INDEX: StatId = StatId(364);
    pub const ITEM_MAGIC_DAMAGE_MAX_PER_LEVEL: StatId = StatId(365);
    pub const PASSIVE_DAMAGE_PIERCE: StatId = StatId(366);
    pub const HERALD_TIER: StatId = StatId(367);
    pub const TERMINATOR: StatId = StatId(511);
}

impl StatId {
    /// Returns the name of a known stat, e.g. `"FireResist"`.
    pub fn name(self) -> Option<&'static str> {
        Some(match self.0 {
            0 => "Strength",
            1 => "Energy",
            2 => "Dexterity",
            3 => "Vitality",
            4 => "StatPoints",
            5 => "SkillPoints",
            6 => "Life",
            7 => "MaxLife",
            8 => "Mana",
            9 => "MaxMana",
            10 => "Stamina",
            11 => "MaxStamina",
            12 => "Level",
            13 => "Experience",
            14 => "Gold",
            15 => "StashGold",
            16 => "ArmorPercent",
            17 => "MaxDamagePercent",
            18 => "MinDamagePercent",
            19 => "AttackRating",
            20 => "ChanceToBlock",
            21 => "MinDamage",
            22 => "MaxDamage",
            23 => "SecondMinDamage",
            24 => "SecondMaxDamage",
            25 => "DamagePercent",
            26 => "ManaRecovery",
            27 => "ManaRecoveryBonus",
            28 => "StaminaRecoveryBonus",
            29 => "LastExp",
            30 => "NextExp",
            31 => "ArmorClass",
            32 => "DefenseVsMissiles",
            33 => "DefenseVsHth",
            34 => "NormalDamageReduction",
            35 => "MagicDamageReduction",
            36 => "DamageReduced",
            37 => "MagicResist",
            38 => "MaxMagicResist",
            39 => "FireResist",
            40 => "MaxFireResist",
            41 => "LightningResist",
            42 => "MaxLightningResist",
            43 => "ColdResist",
            44 => "MaxColdResist",
            45 => "PoisonResist",
            46 => "MaxPoisonResist",
            47 => "DamageAura",
            48 => "FireMinDamage",
            49 => "FireMaxDamage",
            50 => "LightningMinDamage",
            51 => "LightningMaxDamage",
            52 => "MagicMinDamage",
            53 => "MagicMaxDamage",
            54 => "ColdMinDamage",
            55 => "ColdMaxDamage",
            56 => "ColdLength",
            57 => "PoisonMinDamage",
            58 => "PoisonMaxDamage",
            59 => "PoisonLength",
            60 => "LifeSteal",
            61 => "LifeStealMax",
            62 => "ManaSteal",
            63 => "ManaStealMax",
            64 => "StaminaDrainMinDamage",
            65 => "StaminaDrainMaxDamage",
            66 => "StunLength",
            67 => "VelocityPercent",
            68 => "AttackRate",
            69 => "OtherAnimRate",
            70 => "Quantity",
            71 => "Value",
            72 => "Durability",
            73 => "MaxDurability",
            74 => "HitPointRegeneration",
            75 => "MaxDurabilityPercent",
            76 => "MaxHitPointPercent",
            77 => "MaxManaPercent",
            78 => "AttackerTakesDamage",
            79 => "GoldFind",
            80 => "MagicFind",
            81 => "Knockback",
            82 => "TimeDuration",
            83 => "AddClassSkills",
            84 => "UnsentParam1",
            85 => "AddExperience",
            86 => "HealAfterKill",
            87 => "ReducePrices",
            88 => "DoubleHerbDuration",
            89 => "LightRadius",
            90 => "LightColor",
            91 => "RequirementPercent",
            92 => "LevelRequire",
            93 => "IncreasedAttackSpeed",
            94 => "LevelRequirePercent",
            95 => "LastBlockFrame",
            96 => "FasterRunWalk",
            97 => "NonClassSkill",
            98 => "State",
            99 => "FasterHitRecovery",
            100 => "PlayerCount",
            101 => "PoisonOverrideLength",
            102 => "FasterBlockRate",
            103 => "BypassUndead",
            104 => "BypassDemons",
            105 => "FasterCastRate",
            106 => "BypassBeasts",
            107 => "SingleSkill",
            108 => "SlainMonstersRestInPeace",
            109 => "CurseResistance",
            110 => "PoisonLengthResist",
            111 => "NormalDamage",
            112 => "Howl",
            113 => "Stupidity",
            114 => "DamageTakenGoesToMana",
            115 => "IgnoreTargetDefense",
            116 => "FractionalTargetDefense",
            117 => "PreventMonsterHeal",
            118 => "HalfFreezeDuration",
            119 => "AttackRatingPercent",
            120 => "DamageTargetDefense",
            121 => "DemonDamagePercent",
            122 => "UndeadDamagePercent",
            123 => "DemonAttackRating",
            124 => "UndeadAttackRating",
            125 => "Throwable",
            126 => "ElemSkills",
            127 => "AllSkills",
            128 => "AttackerTakesLightDamage",
            129 => "IronMaidenLevel",
            130 => "LifeTapLevel",
            131 => "ThornsPercent",
            132 => "BoneArmor",
            133 => "BoneArmorMax",
            134 => "Freeze",
            135 => "OpenWounds",
            136 => "CrushingBlow",
            137 => "KickDamage",
            138 => "ManaAfterKill",
            139 => "HealAfterDemonKill",
            140 => "ExtraBlood",
            141 => "DeadlyStrike",
            142 => "AbsorbFirePercent",
            143 => "AbsorbFire",
            144 => "AbsorbLightningPercent",
            145 => "AbsorbLightning",
            146 => "AbsorbMagicPercent",
            147 => "AbsorbMagic",
            148 => "AbsorbColdPercent",
            149 => "AbsorbCold",
            150 => "Slow",
            151 => "Aura",
            152 => "Indestructible",
            153 => "CannotBeFrozen",
            154 => "StaminaDrainPercent",
            155 => "Reanimate",
            156 => "Pierce",
            157 => "MagicArrow",
            158 => "ExplosiveArrow",
            159 => "ThrowMinDamage",
            160 => "ThrowMaxDamage",
            161 => "SkillHandOfAthena",
            162 => "SkillStaminaPercent",
            163 => "SkillPassiveStaminaPercent",
            164 => "SkillConcentration",
            165 => "SkillEnchant",
            166 => "SkillPierce",
            167 => "SkillConviction",
            168 => "SkillChillingArmor",
            169 => "SkillFrenzy",
            170 => "SkillDecrepify",
            171 => "SkillArmorPercent",
            172 => "Alignment",
            173 => "Target0",
            174 => "Target1",
            175 => "GoldLost",
            176 => "ConversionLevel",
            177 => "ConversionMaxHitPoints",
            178 => "UnitDoOverlay",
            179 => "AttackVsMonType",
            180 => "DamageVsMonType",
            181 => "Fade",
            182 => "ArmorOverridePercent",
            183 => "LastHitReactFrame",
            184 => "Season",
            185 => "BonusMinDamage",
            186 => "BonusMaxDamage",
            187 => "PierceColdImmunity",
            188 => "AddSkillTab",
            189 => "PierceFireImmunity",
            190 => "PierceLightImmunity",
            191 => "PiercePoisonImmunity",
            192 => "PierceDamageImmunity",
            193 => "PierceMagicImmunity",
            194 => "NumSockets",
            195 => "SkillOnAttack",
            196 => "SkillOnKill",
            197 => "SkillOnDeath",
            198 => "SkillOnHit",
            199 => "SkillOnLevelUp",
            200 => "ChargeNoConsume",
            201 => "SkillOnGetHit",
            202 => "ModifierListCastId",
            203 => "PassiveMasteryItemRequirementPercent",
            204 => "ItemChargedSkill",
            205 => "NoConsume",
            206 => "PassiveMasteryNoConsume",
            207 => "PassiveMasteryReplenishOnCrit",
            208 => "MissileThornsPercent",
            209 => "PassiveMasteryItemLevelRequirementPercent",
            210 => "UberAncientsEscalation",
            211 => "UberAncientsDefeated",
            212 => "Unused212",
            213 => "PassiveMasteryAttackSpeed",
            214 => "ArmorPerLevel",
            215 => "ArmorPercentPerLevel",
            216 => "LifePerLevel",
            217 => "ManaPerLevel",
            218 => "MaxDamagePerLevel",
            219 => "MaxDamagePercentPerLevel",
            220 => "StrengthPerLevel",
            221 => "DexterityPerLevel",
            222 => "EnergyPerLevel",
            223 => "VitalityPerLevel",
            224 => "AttackRatingPerLevel",
            225 => "AttackRatingPercentPerLevel",
            226 => "ColdDamageMaxPerLevel",
            227 => "FireDamageMaxPerLevel",
            228 => "LightningDamageMaxPerLevel",
            229 => "PoisonDamageMaxPerLevel",
            230 => "ResistColdPerLevel",
            231 => "ResistFirePerLevel",
            232 => "ResistLightningPerLevel",
            233 => "ResistPoisonPerLevel",
            234 => "AbsorbColdPerLevel",
            235 => "AbsorbFirePerLevel",
            236 => "AbsorbLightningPerLevel",
            237 => "AbsorbPoisonPerLevel",
            238 => "ThornsPerLevel",
            239 => "FindGoldPerLevel",
            240 => "MagicFindPerLevel",
            241 => "RegenStaminaPerLevel",
            242 => "StaminaPerLevel",
            243 => "DamageDemonPerLevel",
            244 => "DamageUndeadPerLevel",
            245 => "AttackRatingDemonPerLevel",
            246 => "AttackRatingUndeadPerLevel",
            247 => "CrushingBlowPerLevel",
            248 => "OpenWoundsPerLevel",
            249 => "KickDamagePerLevel",
            250 => "DeadlyStrikePerLevel",
            251 => "FindGemsPerLevel",
            252 => "ReplenishDurability",
            253 => "ReplenishQuantity",
            254 => "ExtraStack",
            255 => "FindItem",
            256 => "SlashDamage",
            257 => "SlashDamagePercent",
            258 => "CrushDamage",
            259 => "CrushDamagePercent",
            260 => "ThrustDamage",
            261 => "ThrustDamagePercent",
            262 => "AbsorbSlash",
            263 => "AbsorbCrush",
            264 => "AbsorbThrust",
            265 => "AbsorbSlashPercent",
            266 => "AbsorbCrushPercent",
            267 => "AbsorbThrustPercent",
            268 => "ArmorByTime",
            269 => "ArmorPercentByTime",
            270 => "LifeByTime",
            271 => "ManaByTime",
            272 => "MaxDamageByTime",
            273 => "MaxDamagePercentByTime",
            274 => "StrengthByTime",
            275 => "DexterityByTime",
            276 => "EnergyByTime",
            277 => "VitalityByTime",
            278 => "AttackRatingByTime",
            279 => "AttackRatingPercentByTime",
            280 => "ColdDamageMaxByTime",
            281 => "FireDamageMaxByTime",
            282 => "LightningDamageMaxByTime",
            283 => "PoisonDamageMaxByTime",
            284 => "ResistColdByTime",
            285 => "ResistFireByTime",
            286 => "ResistLightningByTime",
            287 => "ResistPoisonByTime",
            288 => "AbsorbColdByTime",
            289 => "AbsorbFireByTime",
            290 => "AbsorbLightningByTime",
            291 => "AbsorbPoisonByTime",
            292 => "FindGoldByTime",
            293 => "MagicFindByTime",
            294 => "RegenStaminaByTime",
            295 => "StaminaByTime",
            296 => "DamageDemonByTime",
            297 => "DamageUndeadByTime",
            298 => "AttackRatingDemonByTime",
            299 => "AttackRatingUndeadByTime",
            300 => "CrushingBlowByTime",
            301 => "OpenWoundsByTime",
            302 => "KickDamageByTime",
            303 => "DeadlyStrikeByTime",
            304 => "FindGemsByTime",
            305 => "PierceCold",
            306 => "PierceFire",
            307 => "PierceLightning",
            308 => "PiercePoison",
            309 => "DamageVsMonster",
            310 => "DamagePercentVsMonster",
            311 => "AttackRatingVsMonster",
            312 => "AttackRatingPercentVsMonster",
            313 => "AcVsMonster",
            314 => "AcPercentVsMonster",
            315 => "FireLength",
            316 => "BurningMin",
            317 => "BurningMax",
            318 => "ProgressiveDamage",
            319 => "ProgressiveSteal",
            320 => "ProgressiveOther",
            321 => "ProgressiveFire",
            322 => "ProgressiveCold",
            323 => "ProgressiveLightning",
            324 => "ExtraCharges",
            325 => "ProgressiveAttackRating",
            326 => "PoisonCount",
            327 => "DamageFrameRate",
            328 => "PierceIdx",
            329 => "FireSkillDamage",
            330 => "LightningSkillDamage",
            331 => "ColdSkillDamage",
            332 => "PoisonSkillDamage",
            333 => "EnemyFireResist",
            334 => "EnemyLightningResist",
            335 => "EnemyColdResist",
            336 => "EnemyPoisonResist",
            337 => "PassiveCriticalStrike",
            338 => "PassiveDodge",
            339 => "PassiveAvoid",
            340 => "PassiveEvade",
            341 => "PassiveWarmth",
            342 => "PassiveMasteryMeleeAttackRating",
            343 => "PassiveMasteryMeleeDamage",
            344 => "PassiveMasteryMeleeCritical",
            345 => "PassiveMasteryThrowAttackRating",
            346 => "PassiveMasteryThrowDamage",
            347 => "PassiveMasteryThrowCritical",
            348 => "PassiveWeaponBlock",
            349 => "SummonResist",
            350 => "ModifierListSkill",
            351 => "ModifierListLevel",
            352 => "LastSentHitPointPercent",
            353 => "SourceUnitType",
            354 => "SourceUnitId",
            355 => "ShortParam1",
            356 => "QuestItemDifficulty",
            357 => "PassiveMagicMastery",
            358 => "PassiveMagicPierce",
            359 => "SkillCooldown",
            360 => "SkillMissileDamageScale",
            361 => "SkillPsychicWard",
            362 => "SkillPsychicWardMax",
            363 => "SkillChannelingTick",
            364 => "CustomizationIndex",
            365 => "ItemMagicDamageMaxPerLevel",
            366 => "PassiveDamagePierce",
            367 => "HeraldTier",
            511 => "Terminator",
            _ => return None,
        })
    }

    /// Stats that follow this stat in item stat lists without their own ID.
    pub fn paired_stats(self) -> &'static [StatId] {
        match self {
            StatId::MAX_DAMAGE_PERCENT => &[StatId::MIN_DAMAGE_PERCENT],
            StatId::FIRE_MIN_DAMAGE => &[StatId::FIRE_MAX_DAMAGE],
            StatId::LIGHTNING_MIN_DAMAGE => &[StatId::LIGHTNING_MAX_DAMAGE],
            StatId::MAGIC_MIN_DAMAGE => &[StatId::MAGIC_MAX_DAMAGE],
            StatId::COLD_MIN_DAMAGE => &[StatId::COLD_MAX_DAMAGE, StatId::COLD_LENGTH],
            StatId::POISON_MIN_DAMAGE => &[StatId::POISON_MAX_DAMAGE, StatId::POISON_LENGTH],
            _ => &[],
        }
    }
}

impl std::fmt::Debug for StatId {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self.name() {
            Some(name) => f.write_str(name),
            None => write!(f, "StatId({})", self.0),
        }
    }
}

impl std::fmt::Display for StatId {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        std::fmt::Debug::fmt(self, f)
    }
}

impl From<u16> for StatId {
    fn from(v: u16) -> Self {
        StatId(v)
    }
}