-
Notifications
You must be signed in to change notification settings - Fork 2.4k
Expand file tree
/
Copy pathTestItemParse_spec.lua
More file actions
1024 lines (940 loc) · 34 KB
/
Copy pathTestItemParse_spec.lua
File metadata and controls
1024 lines (940 loc) · 34 KB
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
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
describe("TestItemParse", function()
local function raw(s, base)
base = base or "Plate Vest"
return "Rarity: Rare\nName\n"..base.."\n"..s
end
it("Rarity", function()
local item = new("Item", "Rarity: Normal\nCoral Ring")
assert.are.equals("NORMAL", item.rarity)
item = new("Item", "Rarity: Magic\nCoral Ring")
assert.are.equals("MAGIC", item.rarity)
item = new("Item", "Rarity: Rare\nName\nCoral Ring")
assert.are.equals("RARE", item.rarity)
item = new("Item", "Rarity: Unique\nName\nCoral Ring")
assert.are.equals("UNIQUE", item.rarity)
item = new("Item", "Rarity: Unique\nName\nCoral Ring\nFoil Unique (Verdant)")
assert.are.equals("RELIC", item.rarity)
end)
it("Superior/Synthesised", function()
local item = new("Item", raw("", "Superior Plate Vest"))
assert.are.equals("Plate Vest", item.baseName)
item = new("Item", raw("", "Synthesised Plate Vest"))
assert.are.equals("Plate Vest", item.baseName)
item = new("Item", raw("", "Superior Synthesised Plate Vest"))
assert.are.equals("Plate Vest", item.baseName)
end)
it("adds talisman base mods as enchants", function()
local baseName = "Test Talisman"
data.itemBases[baseName] = {
type = "Amulet",
subType = "Talisman",
tags = { amulet = true, talisman = true },
req = { },
enchant = "+10 to Strength",
enchantModTypes = { { "attribute" } },
cannotBeAnointed = true,
}
local item = new("Item", "Rarity: Normal\n" .. baseName)
assert.are.equals(1, #item.enchantModLines)
assert.are.equals("+10 to Strength", item.enchantModLines[1].line)
assert.truthy(item.enchantModLines[1].crafted)
assert.truthy(item.enchantModLines[1].implicit)
assert.are.same({ "attribute" }, item.enchantModLines[1].modTags)
assert.truthy(item.base.cannotBeAnointed)
item:BuildAndParseRaw()
assert.are.equals(1, #item.enchantModLines)
assert.truthy(item.enchantModLines[1].crafted)
assert.truthy(item.enchantModLines[1].implicit)
data.itemBases[baseName] = nil
end)
it("Two-Toned Boots", function()
local item = new("Item", raw("", "Two-Toned Boots"))
assert.are.equals("Two-Toned Boots (Armour/Energy Shield)", item.baseName)
item = new("Item", raw("Armour: 10\nEnergy Shield: 10", "Two-Toned Boots"))
assert.are.equals("Two-Toned Boots (Armour/Energy Shield)", item.baseName)
item = new("Item", raw("Armour: 10\nEvasion Rating: 10", "Two-Toned Boots"))
assert.are.equals("Two-Toned Boots (Armour/Evasion)", item.baseName)
item = new("Item", raw("Evasion Rating: 10\nEnergy Shield: 10", "Two-Toned Boots"))
assert.are.equals("Two-Toned Boots (Evasion/Energy Shield)", item.baseName)
end)
it("Magic Two-Toned Boots", function()
local item = new("Item", [[
Rarity: Magic
Stalwart Two-Toned Boots of Plunder
Armour: 100
Energy Shield: 100
]])
assert.are.equal("Two-Toned Boots (Armour/Energy Shield)", item.baseName)
assert.are.equal("Stalwart ", item.namePrefix)
assert.are.equal(" of Plunder", item.nameSuffix)
item = new("Item", [[
Rarity: Magic
Sanguine Two-Toned Boots of the Phoenix
Armour: 100
Evasion Rating: 100
]])
assert.are.equal("Two-Toned Boots (Armour/Evasion)", item.baseName)
assert.are.equal("Sanguine ", item.namePrefix)
assert.are.equal(" of the Phoenix", item.nameSuffix)
item = new("Item", [[
Rarity: Magic
Stout Two-Toned Boots of the Lightning
Evasion Rating: 100
Energy Shield: 100
]])
assert.are.equal("Two-Toned Boots (Evasion/Energy Shield)", item.baseName)
assert.are.equal("Stout ", item.namePrefix)
assert.are.equal(" of the Lightning", item.nameSuffix)
end)
it("Title", function()
local item = new("Item", [[
Rarity: Rare
Phoenix Paw
Iron Gauntlets
]])
assert.are.equal("Phoenix Paw", item.title)
assert.are.equal("Iron Gauntlets", item.baseName)
assert.are.equal("Phoenix Paw, Iron Gauntlets", item.name)
end)
it("Unique ID", function()
local item = new("Item", raw("Unique ID: 40f9711d5bd7ad2bcbddaf71c705607aef0eecd3dcadaafec6c0192f79b82863"))
assert.are.equals("40f9711d5bd7ad2bcbddaf71c705607aef0eecd3dcadaafec6c0192f79b82863", item.uniqueID)
end)
it("Item Level", function()
local item = new("Item", raw("Item Level: 10"))
assert.are.equals(10, item.itemLevel)
end)
it("Quality", function()
local item = new("Item", raw("Quality: 10"))
assert.are.equals(10, item.quality)
item = new("Item", raw("Quality: +12% (augmented)"))
assert.are.equals(12, item.quality)
end)
it("Sockets", function()
local item = new("Item", raw("Sockets: R-G R-B-W A"))
assert.are.same({
{ color = "R", group = 0 },
{ color = "G", group = 0 },
{ color = "R", group = 1 },
{ color = "B", group = 1 },
{ color = "W", group = 1 },
{ color = "A", group = 2 },
}, item.sockets)
end)
it("Jewel", function()
local item = new("Item", raw("Radius: Large\nLimited to: 2", "Cobalt Jewel"))
assert.are.equals("Large", item.jewelRadiusLabel)
assert.are.equals(2, item.limit)
end)
it("Variant name", function()
local item = new("Item", raw("Variant: Pre 3.19.0\nVariant: Current"))
assert.are.same({ "Pre 3.19.0", "Current" }, item.variantList)
end)
it("Talisman Tier", function()
local item = new("Item", raw("Talisman Tier: 3", "Rotfeather Talisman"))
assert.are.equals(3, item.talismanTier)
end)
it("Defence", function()
local item = new("Item", raw("Armour: 25"))
assert.are.equals(25, item.armourData.Armour)
item = new("Item", raw("Armour: 25 (augmented)"))
assert.are.equals(25, item.armourData.Armour)
item = new("Item", raw("Evasion Rating: 35", "Shabby Jerkin"))
assert.are.equals(35, item.armourData.Evasion)
item = new("Item", raw("Energy Shield: 15", "Simple Robe"))
assert.are.equals(15, item.armourData.EnergyShield)
item = new("Item", raw("Ward: 180", "Runic Crown"))
assert.are.equals(180, item.armourData.Ward)
end)
it("Defence BasePercentile", function()
local item = new("Item", raw("ArmourBasePercentile: 0.5"))
assert.are.equals(0.5, item.armourData.ArmourBasePercentile)
item = new("Item", raw("EvasionBasePercentile: 0.6", "Shabby Jerkin"))
assert.are.equals(0.6, item.armourData.EvasionBasePercentile)
item = new("Item", raw("EnergyShieldBasePercentile: 0.7", "Simple Robe"))
assert.are.equals(0.7, item.armourData.EnergyShieldBasePercentile)
item = new("Item", raw("WardBasePercentile: 0.8", "Runic Crown"))
assert.are.equals(0.8, item.armourData.WardBasePercentile)
end)
it("Requires Level", function()
local item = new("Item", raw("Requires Level 10"))
assert.are.equals(10, item.requirements.level)
item = new("Item", raw("Level: 10"))
assert.are.equals(10, item.requirements.level)
item = new("Item", raw("LevelReq: 10"))
assert.are.equals(10, item.requirements.level)
end)
it("Alt Variant", function()
local item = new("Item", raw([[
Has Alt Variant: true
Has Alt Variant Two: true
Has Alt Variant Three: true
Has Alt Variant Four: true
Has Alt Variant Five: true
Selected Variant: 10
Selected Alt Variant: 11
Selected Alt Variant Two: 12
Selected Alt Variant Three: 13
Selected Alt Variant Four: 14
Selected Alt Variant Five: 15
]]))
assert.truthy(item.hasAltVariant)
assert.truthy(item.hasAltVariant2)
assert.truthy(item.hasAltVariant3)
assert.truthy(item.hasAltVariant4)
assert.truthy(item.hasAltVariant5)
assert.are.equals(10, item.variant)
assert.are.equals(11, item.variantAlt)
assert.are.equals(12, item.variantAlt2)
assert.are.equals(13, item.variantAlt3)
assert.are.equals(14, item.variantAlt4)
assert.are.equals(15, item.variantAlt5)
end)
it("Prefix/Suffix", function()
local item = new("Item", raw([[
Prefix: {range:0.1}IncreasedLife1
Suffix: {range:0.2}ColdResist1
]]))
assert.are.equals("IncreasedLife1", item.prefixes[1].modId)
assert.are.equals(0.1, item.prefixes[1].range)
assert.are.equals("ColdResist1", item.suffixes[1].modId)
assert.are.equals(0.2, item.suffixes[1].range)
end)
it("Implicits", function()
local item = new("Item", raw([[
Implicits: 2
+8 to Strength
+10 to Intelligence
+12 to Dexterity
]]))
assert.are.equals(2, #item.implicitModLines)
assert.are.equals("+8 to Strength", item.implicitModLines[1].line)
assert.are.equals("+10 to Intelligence", item.implicitModLines[2].line)
assert.are.equals(1, #item.explicitModLines)
assert.are.equals("+12 to Dexterity", item.explicitModLines[1].line)
end)
it("League", function()
local item = new("Item", raw("League: Heist"))
assert.are.equals("Heist", item.league)
end)
it("Source", function()
local item = new("Item", raw("Source: No longer obtainable"))
assert.are.equals("No longer obtainable", item.source)
end)
it("Note", function()
local item = new("Item", raw("Note: ~price 1 chaos"))
assert.are.equals("~price 1 chaos", item.note)
end)
it("Attribute Requirements", function()
local item = new("Item", raw("Dex: 100"))
assert.are.equals(100, item.requirements.dex)
item = new("Item", raw("Int: 101"))
assert.are.equals(101, item.requirements.int)
item = new("Item", raw("Str: 102"))
assert.are.equals(102, item.requirements.str)
end)
it("Requires Class", function()
local item = new("Item", raw("Requires Class Witch"))
assert.are.equals("Witch", item.classRestriction)
item = new("Item", raw("Class:: Witch"))
assert.are.equals("Witch", item.classRestriction)
end)
it("Requires Class variant", function()
local item = new("Item", raw([[
Selected Variant: 2
+8 to Strength
{variant:1}Requires Class Witch
{variant:2}Requires Class Templar
]]))
assert.are.equals(2, item.variant)
assert.are.equals("Templar", item.classRestriction)
end)
it("Influence", function()
local item = new("Item", raw("Shaper Item"))
assert.truthy(item.shaper)
item = new("Item", raw("Elder Item"))
assert.truthy(item.elder)
item = new("Item", raw("Warlord Item"))
assert.truthy(item.adjudicator)
item = new("Item", raw("Hunter Item"))
assert.truthy(item.basilisk)
item = new("Item", raw("Crusader Item"))
assert.truthy(item.crusader)
item = new("Item", raw("Redeemer Item"))
assert.truthy(item.eyrie)
item = new("Item", raw("Searing Exarch Item"))
assert.truthy(item.cleansing)
item = new("Item", raw("Eater of Worlds Item"))
assert.truthy(item.tangle)
end)
it("short flags", function()
local item = new("Item", raw("Split"))
assert.truthy(item.split)
item = new("Item", raw("Mirrored"))
assert.truthy(item.mirrored)
item = new("Item", raw("Corrupted"))
assert.truthy(item.corrupted)
item = new("Item", raw("Fractured Item"))
assert.truthy(item.fractured)
item = new("Item", raw("Synthesised Item"))
assert.truthy(item.synthesised)
item = new("Item", raw("Crafted: true"))
assert.truthy(item.crafted)
item = new("Item", raw("Unreleased: true"))
assert.truthy(item.unreleased)
end)
it("long flags", function()
local item = new("Item", raw("This item can be anointed by Cassia"))
assert.truthy(item.canBeAnointed)
item = new("Item", raw("Can have a second Enchantment Modifier"))
assert.truthy(item.canHaveTwoEnchants)
item = new("Item", raw("Can have 1 additional Enchantment Modifiers"))
assert.truthy(item.canHaveTwoEnchants)
item = new("Item", raw("Can have 2 additional Enchantment Modifiers"))
assert.truthy(item.canHaveTwoEnchants)
assert.truthy(item.canHaveThreeEnchants)
item = new("Item", raw("Can have 3 additional Enchantment Modifiers"))
assert.truthy(item.canHaveTwoEnchants)
assert.truthy(item.canHaveThreeEnchants)
assert.truthy(item.canHaveFourEnchants)
item = new("Item", raw("Has a Crucible Passive Skill Tree with only Support Passive Skills"))
assert.truthy(item.canHaveOnlySupportSkillsCrucibleTree)
item = new("Item", raw("Has a Crucible Passive Skill Tree"))
assert.truthy(item.canHaveShieldCrucibleTree)
item = new("Item", raw("Has a Two Handed Sword Crucible Passive Skill Tree"))
assert.truthy(item.canHaveTwoHandedSwordCrucibleTree)
end)
it("tags", function()
local item = new("Item", raw("{tags:life,physical_damage}+8 to Strength"))
assert.are.same({ "life", "physical_damage" }, item.explicitModLines[1].modTags)
end)
it("variant", function()
local item = new("Item", raw([[
Selected Variant: 2
{variant:1}+8 to Strength
{variant:2,3}+10 to Strength
]]))
assert.are.equals(2, item.variant)
assert.are.same({ [1] = true }, item.explicitModLines[1].variantList)
assert.are.same({ [2] = true, [3] = true }, item.explicitModLines[2].variantList)
assert.are.equals(10, item.baseModList[1].value) -- variant 2 has +10 to Strength
end)
it("range", function()
local item = new("Item", raw("{range:0.8}+(8-12) to Strength"))
assert.are.equals(0.8, item.explicitModLines[1].range)
assert.are.equals(11, item.baseModList[1].value) -- range 0.8 of (8-12) = 11
end)
it("crafted", function()
local item = new("Item", raw("{crafted}+8 to Strength"))
assert.truthy(item.explicitModLines[1].crafted)
item = new("Item", raw("+8 to Strength (crafted)"))
assert.truthy(item.explicitModLines[1].crafted)
end)
it("crucible", function()
local item = new("Item", raw("{crucible}+8 to Strength"))
assert.truthy(item.crucibleModLines[1].crucible)
item = new("Item", raw("+8 to Strength (crucible)"))
assert.truthy(item.crucibleModLines[1].crucible)
end)
it("custom", function()
local item = new("Item", raw("{custom}+8 to Strength"))
assert.truthy(item.explicitModLines[1].custom)
end)
it("eater", function()
local item = new("Item", raw("{eater}+8 to Strength"))
assert.truthy(item.explicitModLines[1].eater)
end)
it("enchant", function()
local item = new("Item", raw("+8 to Strength (enchant)"))
assert.are.equals(1, #item.enchantModLines)
-- enchant also sets crafted and implicit
assert.truthy(item.enchantModLines[1].crafted)
assert.truthy(item.enchantModLines[1].implicit)
end)
it("exarch", function()
local item = new("Item", raw("{exarch}+8 to Strength"))
assert.truthy(item.explicitModLines[1].exarch)
end)
it("fractured", function()
local item = new("Item", raw("{fractured}+8 to Strength"))
assert.truthy(item.explicitModLines[1].fractured)
item = new("Item", raw("+8 to Strength (fractured)"))
assert.truthy(item.explicitModLines[1].fractured)
end)
it("implicit", function()
local item = new("Item", raw("+8 to Strength (implicit)"))
assert.truthy(item.implicitModLines[1].implicit)
end)
it("scourge", function()
local item = new("Item", raw("{scourge}+8 to Strength"))
assert.truthy(item.scourgeModLines[1].scourge)
item = new("Item", raw("+8 to Strength (scourge)"))
assert.truthy(item.scourgeModLines[1].scourge)
end)
it("synthesis", function()
local item = new("Item", raw("{synthesis}+8 to Strength"))
assert.truthy(item.explicitModLines[1].synthesis)
end)
it("unscalable", function()
local item = new("Item", raw("{unscalable}+8 to Strength"))
assert.truthy(item.explicitModLines[1].unscalable)
item = new("Item", raw("+8 to Strength - Unscalable Value"))
assert.truthy(item.explicitModLines[1].unscalable)
end)
it("multiple bases", function()
local item = new("Item", [[
Ashcaller
Selected Variant: 3
{variant:1,2,3}Quartz Wand
{variant:4}Carved Wand
]])
assert.are.same({
["Quartz Wand"] = { line = "Quartz Wand", variantList = { [1] = true, [2] = true, [3] = true } },
["Carved Wand"] = { line = "Carved Wand", variantList = { [4] = true } }
}, item.baseLines)
assert.are.equals("Quartz Wand", item.baseName)
item = new("Item", [[
Ashcaller
Selected Variant: 4
{variant:1,2,3}Quartz Wand
{variant:4}Carved Wand
]])
assert.are.equals("Carved Wand", item.baseName)
end)
it("parses text without armour value then changes quality and has correct final armour", function()
local item = new("Item", [[
Armour Gloves
Iron Gauntlets
Quality: 0
]])
local original = item.armourData.Armour
item.quality = 20
item:BuildAndParseRaw()
assert.are.equals(round(original * 1.2), item.armourData.Armour)
end)
it("magic item", function()
local item = new("Item", [[
Rarity: MAGIC
Name Prefix Iron Gauntlets -> +50 ignite chance
+50% chance to Ignite
]])
assert.are.equals("Name Prefix ", item.namePrefix)
assert.are.equals(" -> +50 ignite chance", item.nameSuffix)
assert.are.equals("Iron Gauntlets", item.baseName)
assert.are.equals(1, #item.explicitModLines)
assert.are.equals("+50% chance to Ignite", item.explicitModLines[1].line)
end)
it("Energy Blade", function()
local item = new("Item", [[
Item Class: One Hand Swords
Rarity: Magic
Superior Energy Blade
]])
assert.are.equal("Energy Blade One Handed", item.baseName)
item = new("Item", [[
Item Class: Two Hand Swords
Rarity: Magic
Superior Energy Blade
]])
assert.are.equal("Energy Blade Two Handed", item.baseName)
end)
it("Flask buff", function()
local item = new("Item", [[
Rarity: Magic
Chemist's Granite Flask of the Opossum
]])
assert.are.equal(1, #item.buffModLines)
assert.are.equal("+1500 to Armour", item.buffModLines[1].line)
end)
end)
describe("TestAdvancedItemParse #item", function()
local function raw(s, base)
base = base or "Plate Vest"
return "Rarity: Rare\nName\n"..base.."\n"..s
end
it("parses to craft", function()
local item = new("Item", raw([[
{ Prefix Modifier "Fecund" (Tier: 1) — Life }
+142(130-144) to maximum Life
]], "Cord Belt"))
assert.are.equals("IncreasedLife9", item.prefixes[1].modId)
assert.are.equals(0.857, item.prefixes[1].range)
assert.are.equals("life", item.explicitModLines[1].modTags[1])
item = new("Item", raw([[
{ Master Crafted Suffix Modifier "of Craft" (Rank: 3) — Elemental, Cold, Resistance }
+35(29-35)% to Cold Resistance
]], "Cord Belt"))
assert.truthy(item.explicitModLines[1].crafted)
end)
it("parses correct range", function()
local item = new("Item", raw([[
{ Prefix Modifier "Freezing" (Tier: 5) — Damage, Elemental, Cold, Caster — 8% Increased }
Adds 17(16-20) to 35(30-36) Cold Damage to Spells
]], "Void Sceptre"))
assert.are.equals("Adds 17 to 35 Cold Damage to Spells", item.explicitModLines[1].line)
end)
-- GGG scales each mod line separately here, but PoB scales them both together, so this parsing is a bit wonky
it("parses multi-line mod", function()
local item = new("Item", raw([[
{ Prefix Modifier "Warlock's" (Tier: 4) — Mana, Damage, Caster }
32(30-37)% increased Spell Damage
+46(42-47) to maximum Mana
]], "Royal Staff"))
assert.are.equals("SpellDamageAndManaOnTwoHandWeapon4", item.prefixes[1].modId)
assert.are.equals(0.286, item.prefixes[1].range)
assert.are.equals(0.8, item.explicitModLines[2].range)
end)
it("resets linePrefix", function()
local item = new("Item", raw([[
{ Prefix Modifier "Warlock's" (Tier: 4) — Mana, Damage, Caster }
32(30-37)% increased Spell Damage
+46(42-47) to maximum Mana
--------
+15 to maximum life
]], "Royal Staff"))
assert.are_not.equals("mana", item.explicitModLines[3].modTags[1])
end)
it("resets linePostfix", function()
local item = new("Item", raw([[
{ Corruption Enhancement — Mana }
24(20-30)% increased Mana Regeneration Rate
--------
+15 to maximum life
]]))
assert.falsy(item.explicitModLines[1].enchant)
end)
it("parses vaaled catalyst", function()
local item = new("Item", raw([[
Quality (Attribute Modifiers): +19% (augmented)
{ Unique Modifier — Attribute — 19% Increased }
+120(80-100) to all Attributes
(Attributes are Strength, Dexterity, and Intelligence)
]], "Onyx Amulet"))
assert.are.equals(142, item.baseModList[1].value)
-- assert.falsy(item.explicitModLines[1].range) -- Not sure why this is returning 0.5
assert.are.equals(6, item.catalyst)
assert.are.equals(19, item.catalystQuality)
end)
it("parses vaaled catalyst within range", function()
local item = new("Item", raw([[
Quality (Attribute Modifiers): +19% (augmented)
{ Unique Modifier — Attribute — 19% Increased }
+95(80-100) to all Attributes
(Attributes are Strength, Dexterity, and Intelligence)
]], "Onyx Amulet"))
assert.are.equals(113, item.baseModList[1].value)
assert.are.equals(0.75, item.explicitModLines[1].range)
assert.are.equals(6, item.catalyst)
assert.are.equals(19, item.catalystQuality)
end)
it("scales suffix (Dextral) catalyst", function()
local item = new("Item", raw([[
Quality (Suffix Modifiers): +20% (augmented)
{ Suffix Modifier — Attribute }
+90(80-100) to all Attributes
(Attributes are Strength, Dexterity, and Intelligence)
]], "Onyx Amulet"))
assert.are.equals(3, item.catalyst)
assert.are.equals(20, item.catalystQuality)
assert.are.equals(108, item.baseModList[1].value)
end)
it("scales prefix (Sinistral) catalyst when crafted on simplex", function()
build.itemsTab:CreateDisplayItemFromRaw(main.rareDB.list["Amulet, Simplex Amulet"].raw)
local item = build.itemsTab.displayItem
-- 26% spell damage
item.prefixes[1] = { modId = "SpellDamage5", range = 1 }
item:Craft()
assert.are.equals(52, item.baseModList[1].value)
build.itemsTab:UpdateAffixControls()
-- dextral is id 9, but selector has a "None" in position 1
build.itemsTab.controls.displayItemCatalyst:SetSel(10)
assert.are.equals(57, item.baseModList[1].value)
assert.are.equals(9, item.catalyst)
assert.are.equals(20, item.catalystQuality)
end)
it("scales prefix (Sinistral) catalyst", function()
local item = new("Item", raw([[
Quality (Prefix Modifiers): +20% (augmented)
{ Prefix Modifier — Attribute }
+90(80-100) to all Attributes
(Attributes are Strength, Dexterity, and Intelligence)
]], "Onyx Amulet"))
assert.are.equals(9, item.catalyst)
assert.are.equals(20, item.catalystQuality)
assert.are.equals(108, item.baseModList[1].value)
end)
it("suffix catalyst does not scale prefix mods", function()
local item = new("Item", raw([[
Quality (Suffix Modifiers): +20% (augmented)
{ Prefix Modifier — Attribute }
+90(80-100) to all Attributes
(Attributes are Strength, Dexterity, and Intelligence)
]], "Onyx Amulet"))
assert.are.equals(3, item.catalyst)
assert.are.equals(20, item.catalystQuality)
assert.are.equals(90, item.baseModList[1].value)
end)
it("doesn't scale unscalable", function()
local item = new("Item", raw([[
Quality (Life and Mana Modifiers): +20% (augmented)
{ Unique Modifier — Life, Defences, Energy Shield, Minion, Gem }
Socketed Golem Skills gain 20% of Maximum Life as Extra Maximum Energy Shield — Unscalable Value
]]))
assert.are.equals(20, item.baseModList[1].value.mod.value)
end)
it("correctly matches conqueror mod", function()
local item = new("Item", raw([[
{ Suffix Modifier "of the Conquest" (Tier: 1) — Elemental, Cold }
10(8-10)% chance to Avoid Cold Damage from Hits
(No chance to avoid damage can be higher than 75%)
Warlord Item
]]))
assert.are.equals(10, item.baseModList[1].value)
-- assert.are.equals(1, item.explicitModLines[1].range) -- Not sure why this is returning 0.5
end)
it("parses enchant correctly #enchant", function()
local item = new("Item", raw([[
{ Corrupted Enhancement }
+8(6-10)% to Fire Resistance
]]))
assert.are.equals(8, item.enchantModLines[1].modList[1].value)
end)
it("parses enchant with tags correctly #enchant", function()
local item = new("Item", raw([[
{ Corrupted Enhancement - Energy Shield }
+8(6-10)% to Fire Resistance
]]))
assert.are.equals(8, item.enchantModLines[1].modList[1].value)
assert.are.equals("energyshield", item.enchantModLines[1].modTags[1])
end)
it("parses junk", function()
local godTestItem = new("Item", [[
Item Class: Sceptres
Rarity: Unique
Nebulis
Synthesised Void Sceptre
--------
Sceptre
Physical Damage: 50-76
Critical Strike Chance: 7.30%
Attacks per Second: 1.25
Weapon Range: 1.1 metres
Memory Strands: 58
--------
Requirements:
Level: 68
Str: 104
Int: 122
--------
Sockets: B R
--------
Item Level: 87
--------
+30% to Fire Resistance (scourge)
22% reduced Global Defences (scourge)
(Armour, Evasion Rating and Energy Shield are the standard Defences) (scourge)
--------
8% increased Explicit Cold Modifier magnitudes (enchant)
Has 1 White Socket (enchant)
--------
{ Searing Exarch Implicit Modifier (Lesser) }
Tempest Shield has 15(15-17)% increased Buff Effect
{ Implicit Modifier — Damage, Critical — 106% Increased }
+15(15-17)% to Global Critical Strike Multiplier
--------
{ Prefix Modifier "Freezing" (Tier: 5) — Damage, Elemental, Cold, Caster — 8% Increased }
Adds 17(16-20) to 35(30-36) Cold Damage to Spells
{ Prefix Modifier "Beetle's" (Tier: 6) — Defences, Armour }
9(6-13)% increased Armour
7(6-7)% increased Stun and Block Recovery
{ Master Crafted Prefix Modifier "Upgraded" — Life, Defences, Armour }
21(18-21)% increased Armour
+18(17-19) to maximum Life
{ Unique Modifier }
106(60-120)% increased Implicit Modifier magnitudes — Unscalable Value
(Implicit Modifiers are those that come from an item's type, rather than its random properties)
{ Master Crafted Suffix Modifier "of Craft" (Rank: 3) — Elemental, Cold, Resistance }
+35(29-35)% to Cold Resistance
{ Fractured Prefix Modifier "Thorny" (Tier: 2) — Damage, Physical }
Reflects 3(1-4) Physical Damage to Melee Attackers
{ Prefix Modifier "Veiled" }
Veiled Prefix
Searing Exarch Item
--------
{ Allocated Crucible Passive Skill (Tier: 2) }
Adds 2 to 6 Physical Damage to Spells
--------
Synthesised Item
--------
Corrupted
--------
Scourged
--------
Hinekora's Lock
--------
Note: ~b/o 2 chaos
]])
end)
describe("mod magnitude scaling", function()
before_each(function()
newBuild()
runCallback("onFrame")
end)
local function chaosDamageInc()
return build.calcsTab.mainEnv.modDB:Sum("INC", nil, "ChaosDamage")
end
local function chaosResist()
return build.calcsTab.mainEnv.modDB:Sum("BASE", nil, "ChaosResist")
end
local function spellCrit()
return build.calcsTab.mainEnv.modDB:Sum("INC", { flags = ModFlag.Spell }, "CritChance")
end
local function spellDamage()
return build.calcsTab.mainEnv.modDB:Sum("INC", { flags = ModFlag.Spell }, "Damage")
end
it("scales matching implicit mods by modifier magnitude", function()
-- 130% * 1.7 = 221
build.itemsTab:CreateDisplayItemFromRaw([[
Rarity: RARE
Test Subject
Void Sceptre
LevelReq: 60
Implicits: 1
{range:0.5}(100-160)% increased Chaos Damage
{range:0.5}70% increased implicit Modifier magnitudes
]])
local item = build.itemsTab.displayItem
assert.is_true(item.advancedCopy)
build.itemsTab:AddDisplayItem()
runCallback("OnFrame")
assert.are.equals(221, chaosDamageInc())
end)
it("scales properly using old Eyes of the Greatwolf line", function()
build.itemsTab:CreateDisplayItemFromRaw([[
Rarity: UNIQUE
Eyes of the Greatwolf
Greatwolf Talisman
Quality (Caster Modifiers): +20% (augmented)
LevelReq: 60
Implicits: 1
{tags:caster}{range:0.5}(100-160)% increased Spell Damage
{range:0.5}Implicit Modifier magnitudes are doubled
]])
local item = build.itemsTab.displayItem
assert.is_true(item.advancedCopy)
build.itemsTab:AddDisplayItem()
runCallback("OnFrame")
assert.are.equals(312, spellDamage())
end)
it("scales properly using new Eyes of the Greatwolf line", function()
-- 130% * 1.7 = 221
build.itemsTab:CreateDisplayItemFromRaw([[
Rarity: RARE
Test Subject
Void Sceptre
LevelReq: 60
Implicits: 1
{range:0.5}{crafted}(100-160)% increased Chaos Damage
{range:0.5}(50-100)% increased Enchantment Modifier magnitudes
]])
local item = build.itemsTab.displayItem
assert.is_true(item.advancedCopy)
build.itemsTab:AddDisplayItem()
runCallback("OnFrame")
assert.are.equals(227, chaosDamageInc())
end)
it("does not rescale old format (baked) copies", function()
-- magnitude already baked in, so no rescale
build.itemsTab:CreateDisplayItemFromRaw([[
Rarity: RARE
Baked Subject
Imperial Staff
LevelReq: 60
Implicits: 0
{tags:chaos,damage}130% increased Chaos Damage
70% increased Chaos Modifier magnitudes
]])
local item = build.itemsTab.displayItem
assert.is_false(item.advancedCopy)
build.itemsTab:AddDisplayItem()
runCallback("OnFrame")
assert.are.equals(130, chaosDamageInc())
end)
it("only scales mods that share the magnitude mod's tags", function()
build.itemsTab:CreateDisplayItemFromRaw([[
Rarity: RARE
Test Subject
Sapphire Ring
LevelReq: 20
Implicits: 0
{tags:chaos,damage}{range:0.5}(100-160)% increased Chaos Damage
{tags:resistance}{range:0.5}+(20-40)% to Chaos Resistance
{range:0.5}100% increased resistance modifier magnitudes
]])
build.itemsTab:AddDisplayItem()
runCallback("OnFrame")
assert.are.equals(0, chaosResist())
assert.are.equals(130, chaosDamageInc())
newBuild()
build.itemsTab:CreateDisplayItemFromRaw([[
Rarity: RARE
Test Subject
Sapphire Ring
LevelReq: 20
Implicits: 0
{tags:chaos,damage}{range:0.5}(100-160)% increased Chaos Damage
{tags:defences}{range:0.5}+(20-40)% to Chaos Resistance
{range:0.5}100% increased defence modifier magnitudes
]])
build.itemsTab:AddDisplayItem()
runCallback("OnFrame")
assert.are.equals(0, chaosResist())
assert.are.equals(130, chaosDamageInc())
newBuild()
build.itemsTab:CreateDisplayItemFromRaw([[
Rarity: RARE
Test Subject
Sapphire Ring
LevelReq: 20
Implicits: 0
{tags:chaos,damage}{range:0.5}(100-160)% increased Chaos Damage
{tags:physical,damage}{range:0.5}+(20-40)% to Chaos Resistance
{tags:caster,damage}{range:0.5}(10-30)% increased spell damage
{range:0.5}100% increased Explicit Physical and Chaos Damage Modifier magnitudes
]])
build.itemsTab:AddDisplayItem()
runCallback("OnFrame")
assert.are.equals(0, chaosResist())
assert.are.equals(260, chaosDamageInc())
assert.are.equals(20, spellDamage())
end)
it("only scales the modifier type named by the magnitude mod", function()
build.itemsTab:CreateDisplayItemFromRaw([[
Rarity: RARE
Test Subject
Sapphire Ring
LevelReq: 20
Implicits: 1
{range:0.5}(100-160)% increased Chaos Damage
{range:0.5}+(20-40)% to Chaos Resistance
{range:0.5}100% increased explicit modifier magnitudes
]])
build.itemsTab:AddDisplayItem()
runCallback("OnFrame")
assert.are.equals(0, chaosResist())
assert.are.equals(130, chaosDamageInc())
end)
it("handles explicit physical and chaos modifier magnitudes", function()
build.itemsTab:CreateDisplayItemFromRaw([[
Rarity: RARE
Test Subject
Void Sceptre
LevelReq: 60
Implicits: 1
{tags:chaos,damage}{range:0.5}(100-160)% increased Chaos Damage
{tags:physical,chaos,damage}{range:0.5}(100-160)% increased Chaos Damage
{range:0.5}10% increased Explicit Physical and Chaos Damage Modifier magnitudes
]])
build.itemsTab:AddDisplayItem()
runCallback("OnFrame")
assert.are.equals(273, chaosDamageInc())
end)
it("does not scale unscalable modifiers", function()
build.itemsTab:CreateDisplayItemFromRaw([[
Rarity: RARE
Test Subject
Void Sceptre
LevelReq: 60
Implicits: 0
{tags:chaos,damage}{range:0.5}(100-160)% increased Chaos Damage — Unscalable Value
{range:0.5}100% increased Explicit Modifier magnitudes
]])
build.itemsTab:AddDisplayItem()
runCallback("OnFrame")
assert.are.equals(130, chaosDamageInc())
end)
it("reduces the modifier magnitude correctly", function()
build.itemsTab:CreateDisplayItemFromRaw([[
Rarity: RARE
Test Subject
Sapphire Ring
LevelReq: 20
Implicits: 0
{range:0.5}(100-160)% increased Chaos Damage
{range:0.5}+(20-40)% to Chaos Resistance
{range:0.5}50% reduced explicit modifier magnitudes
]])
build.itemsTab:AddDisplayItem()
runCallback("OnFrame")
assert.are.equals(-45, chaosResist())
assert.are.equals(65, chaosDamageInc())
end)
it("scales only prefixes for increased effect of prefixes", function()
build.itemsTab:CreateDisplayItemFromRaw([[
Rarity: RARE
Test Subject
Sapphire Ring
LevelReq: 20
Implicits: 0
{prefix}{range:0.5}(100-160)% increased Chaos Damage
{suffix}{range:0.5}+(20-40)% to Chaos Resistance
{range:0.5}50% increased effect of prefixes
]])
build.itemsTab:AddDisplayItem()
runCallback("OnFrame")
assert.are.equals(-30, chaosResist())
assert.are.equals(195, chaosDamageInc())
end)
-- actually a ring so we don't have to allocate a socket
local realJewel = [[
Rarity: Rare
Pandemonium Desire
Ruby Ring
--------
Quality (Caster Modifiers): +20% (augmented)
--------
Item Level: 80
--------
{ Corruption Enhancement — Elemental, Cold, Resistance }
+7(5-10)% to Cold Resistance
{ Corruption Enhancement — Attribute }
+6(4-6) to Intelligence
--------
{ Fractured Crafted Prefix Modifier "" }
60(40-60)% increased Effect of Suffixes — Unscalable Value
{ Prefix Modifier "Mystic" (Tier: 1) — Damage, Caster — 20% Increased }
7(5-15)% increased Spell Damage
{ Suffix Modifier "of Unmaking" (Tier: 1) — Damage, Caster, Critical — 80% Increased }
20(10-20)% increased Critical Spell Damage Bonus
{ Desecrated Suffix Modifier "of Annihilating" (Tier: 1) — Caster, Critical — 80% Increased }
15(5-15)% increased Critical Hit Chance for Spells
{ Suffix Modifier "of Potency" (Tier: 1) — Damage, Critical — 60% Increased }
20(10-20)% increased Critical Strike Multiplier
--------
Place into an allocated Jewel Socket on the Passive Skill Tree. Right click to remove from the Socket.
--------
Twice Corrupted
--------