forked from aRTy42/POE-ItemInfo
-
Notifications
You must be signed in to change notification settings - Fork 188
/
Copy pathPOE-ItemInfo.ahk
executable file
·7703 lines (7117 loc) · 301 KB
/
POE-ItemInfo.ahk
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
; Path of Exile Item Info Tooltip
;
; Version: 1.9.2 (hazydoc / IGN:Sadou) Original Author
; Script is currently maintained by various people and kept up to date by aRTy42 / IGN: Erinyen
; Forum thread: https://www.pathofexile.com/forum/view-thread/1678678
;
; This script was originally based on the POE_iLVL_DPS-Revealer script (v1.2d) found here:
; https://www.pathofexile.com/forum/view-thread/594346
;
; Changes to the POE_iLVL_DPS-Revealer script as recent as it's version 1.4.1 have been
; brought over. Thank you Nipper4369 and Kislorod!
;
; The script has been added to substantially to enable the following features in addition to
; itemlevel and weapon DPS reveal:
;
; - show total affix statistic for rare items
; - show possible min-max ranges for all affixes on rare items
; - reveal the combination of difficult compound affixes (you might be surprised what you find)
; - show affix ranges for uniques
; - show map info (thank you, Kislorod and Necrolis)
; - show max socket info (thank you, Necrolis)
; - has the ability to convert currency items to chaos orbs (you can adjust the rates by editing
; <datadir>\CurrencyRates.txt)
; - adds a system tray icon and proper system tray description tooltip
;
; All of these features are user-adjustable by using a "database" of text files which come
; with the script and are easy to edit by non developers. See header comments in those files
; for format infos and data sources.
;
; Known issues:
;
; Even though there have been tons of tests made on composite affix combinations, I expect
; there to be edge cases still that may return an invalid or not found affix bracket.
; You can see these entries in the affix detail lines if they have the text "n/a" (not available)
; somewhere in them or if you see an empty range " - *". The star by the way marks ranges
; that have been added together for a guessed attempt as to the composition of a possible
; compound affix. If you see this star, take a closer look for a moment to check if the
; projection is correct. I expect these edge cases to be properly dealt with over time as the
; script matures. For now I'd estimate that at least 80% of the truly hard cases are correctly
; identified.
;
; Some background info: because the game concatenates values from multiple affix sources into
; one final entry on the ingame tooltip there is no reliable way to work backwards from the
; composite value to each individual part. For example, Stun Recovery can be added as suffix if
; it contributes alone, but can also be a prefix if it is a composite of Stun Recovery and
; Evasion Rating (or others). Because there is one final entry, while prefix and suffix can
; appear at the same time and will be added together, you can't reliably reverse engineer which
; affix contributed what part of the composite value. This is akin to taking a random source of
; numbers, adding them up to one value and then asking someone to work out backwards what the
; original source values were.
; Similarily, in cases like boosted Stun Recovery (1) and Evasion Rating (2) on an item in difficult
; cases there is no 100% reliable way to tell if the prefix "+ Evasion Rating / incr. Stun Recovery"
; contributed to both stats at once or if the suffix "+ Stun Recovery" contributed to (1)
; and the prefix "+ Evasion Rating" cotributed to (2) or possibly a combination of both.
; Often it is possible to make guesses by working your way backwards from both partial affixes, by
; looking at the affix bracket ranges and the item level to see what is even possible to be there and
; what isn't. In the worst case for a double compound affix, all four ranges will be possible to be
; combined.
;
; I have tested the tooltip on many, many items in game from my own stash and from trade chat
; and I can say that in the overwhelming majority of cases the tooltip does indeed work correctly.
;
; IMPORTANT: as you may know, the total amount of affixes (w/o implicit mods) can be 6, of which
; 3 at most are prefixes and likewise 3 at most are suffixes. Be especially weary, then of cases
; where this prefix/suffix limit is overcapped. It may happen that the tooltip shows 4 suffixes,
; and 3 prefixes total. In this case the most likely explanation is that the script failed to properly
; determine composite affixes. Composite affixes ("Comp. Prefix" or "Comp. Suffix" in the tooltip)
; are two affix lines on the ingame tooltip that together form one single composite affix.
; Edit v1.4: This hasn't happened for a longer time now, but I am leaving this important note in
; so end users stay vigilant (assuming anyone even reads this wall of text :)).
;
; - I do not know which affixes are affected by +% Item Quality. Currently I have functions in place
; that can boost a range or a single value to adjust for Item Quality but currently these aren't used
; much. Partially this is also because it is not easy to tell if out-of-bounds cases are the result
; of faulty input data (I initially pulled data from the PoE mods compendium but later made the PoE
; homepage the authoritative source overruling data from other sources) or of other unreckognized and
; unhandled entities or systems.
;
; Todo:
;
; - handle ranges for implicit mods
; - find a way to deal with master crafted mods (currently that's a tough one, probably won't be possible)
; - show max possible for guesstimated ranges
; - de-globalize the script (almost done)
; - refactor ParseAffixes into ParseAffixesSimple and ParseAffixesComplex (low priority)
;
; Slinkston edit for Todo for 2.0 additions for hazydoc or someone else knowledgable in coding:
; - FYI: All of the stuff I have edited has been marked with ; Slinkston edit. Some may need to be cleaned up or redone if
; they are done improperly/sloppy. I have tested all changes with stuff in my stash and with friends, but not every single possibility.
; - Accuracy is a nightmare. Anyhow, "of the Assassin - 321 to 360 Accuracy (80) (Bow and Wand)" needs
; to be addressed for 2.0 or not /shrug. I have passed on the request to GGG to perhaps mark up their affixes so they are decipherable.
; - Divination card info would be great such as a) what you can possibly get for the collection, b) where that card drops, and c) what supporter
; created it (if known).
; - Jewel support for min/max rolls and what is a suffix and what is a prefix so you know what you may be able to exalt. 9/15/2015 - I just noticed that
; GGG added jewel affixes, both prefix and suffix, for jewels to their item database.
; - Legacy item alert on the item would be useful for those players that take breaks and come back without reading all the patch notes and/or
; not recognizing some item may have changed or not. This alert can be placed along the bottom with 'quality, valuable, mirrored, etc.'
; I imagine that this would not be hard to do, but would require a lot of small detail work. Because all uniques are nerfed/buffed in
; specific ways, there is no 'quick' and easy way to do this. There would have to be a specific check for each specific unique item looking
; at the particular change(s) and compare it to the existing known unique setup vs the legacy setup. I would be willing to do all the small
; detail work required for each unique if someone would write the code required for this to work and how this would work with the current uniques.txt
; list. This is obviously less valuable of an addition to the PoE-Item-Info script than general upgrades/div cards/jewel support.
;
; Notes:
;
; - Global values marked with an inline comment "d" are globals for debugging so they can be easily
; (re-)enabled using global search and replace. Marking variables as global means they will show
; up in AHK's Variables and contents view of the script.
;
; Needs AutoHotKey v1.1.05 or later
; from http://ahkscript.org and NOT http://www.autohotkey.com
; the latter domain was apparently taken over by a for-profit company!
;
; Original credits:
;
; mcpower - for the base iLVL display of the script 5months ago before Immo.
; Immo - for the base iLVL display of the script.(Which was taken from mcpower.)
; olop4444 - for helping me figure out the calculations for Q20 items.
; Aeons - for a rewrite and fancy tooltips.
; kongyuyu - for base item level display.
; Fayted - for testing the script.
;
; Original author's comment:
;
; If you have any questions or comments please post them there as well. If you think you can help
; improve this project. I am looking for contributors. So Pm me if you think you can help.
;
; If you have a issue please post what version you are using.
; Reason being is that something that might be a issue might already be fixed.
;
; Run test suites (see end of script)
; Note: don't set this to true for normal every day use...
; This is just for fellow developers.
RunTests := False
#SingleInstance force
#NoEnv ; Recommended for performance and compatibility with future AutoHotkey releases.
#Persistent ; Stay open in background
SendMode Input ; Recommended for new scripts due to its superior speed and reliability.
;Define exe names for the regular and steam version, for later use at the very end of the script. This needs to be done early, in the "auto-execute section".
GroupAdd, PoEexe, ahk_exe PathOfExile.exe
GroupAdd, PoEexe, ahk_exe PathOfExileSteam.exe
#Include %A_ScriptDir%\data\Version.txt
MsgWrongAHKVersion := "AutoHotkey v" . AHKVersionRequired . " or later is needed to run this script. `n`nYou are using AutoHotkey v" . A_AhkVersion . " (installed at: " . A_AhkPath . ")`n`nPlease go to http://ahkscript.org to download the most recent version."
If (A_AhkVersion <= AHKVersionRequired)
{
MsgBox, 16, Wrong AutoHotkey Version, % MsgWrongAHKVersion
ExitApp
}
#Include %A_ScriptDir%\data\Messages.txt
; Instead of polluting the default namespace with Globals, create our own Globals "namespace".
class Globals {
Set(name, value) {
Globals[name] := value
}
Get(name, value_default="") {
result := Globals[name]
If (result == "") {
result := value_default
}
return result
}
}
Globals.Set("AHKVersionRequired", AHKVersionRequired)
Globals.Set("ReleaseVersion", ReleaseVersion)
Globals.Set("DataDir", A_ScriptDir . "\data")
global SuspendPOEItemScript = 0
class UserOptions {
OnlyActiveIfPOEIsFront := 1 ; Set to 1 to make it so the script does nothing if Path of Exile window isn't the frontmost.
; If 0, the script also works if PoE isn't frontmost. This is handy for have the script parse
; textual item representations appearing somewhere else, like in the forums or text files.
PutResultsOnClipboard := 0 ; Put result text on clipboard (overwriting the textual representation the game put there to begin with)
ShowItemLevel := 1 ; Show item level and the item type's base level (enabled by default change to 0 to disable)
ShowMaxSockets := 1 ; Show the max sockets based on ilvl and type
ShowDamageCalculations := 1 ; Show damage projections (for weapons only)
ShowAffixTotals := 1 ; Show total affix statistics
ShowAffixDetails := 1 ; Show detailed info about affixes
ShowAffixLevel := 0 ; Show item level of the affix
ShowAffixBracket := 1 ; Show range for the affix' bracket as is on the item
ShowAffixMaxPossible := 1 ; Show max possible bracket for an affix based on the item's item level
ShowAffixBracketTier := 1 ; Show a T# indicator of the tier the affix bracket is in.
; T1 being the highest possible, T2 second-to-highest and so on
ShowAffixBracketTierTotal := 1 ; Appends the total number of tiers for a given affix in parentheses T/#Total
; T4/8 would represent the fourth highest tier, in eight total tiers.
ShowDarkShrineInfo := 0 ; Appends info about DarkShrine effects of affixes to rares
TierRelativeToItemLevel := 0 ; When determining the affix bracket tier, take item level into consideration.
; However, this also means that the lower the item level the less the diversity
; of possible affix tiers since there aren't as many possibilities. This will
; give the illusion that a low level item might be really, really good when it
; has all T1 but in reality it can only have T1 since it's item level is so low
; it can only ever take the first bracket.
;
; If this option is set to 0, the tiers will always display relative to the full
; range of tiers available, ignoring the item level.
ShowCurrencyValueInChaos := 0 ; Convert the value of currency items into chaos orbs.
; This is based on the rates defined in <datadir>\CurrencyRates.txt
; You should edit this file with the current currency rates.
MaxSpanStartingFromFirst := 1 ; When showing max possible, don't just show the highest possible affix bracket
; but construct a pseudo range which spans the lower bound of the lowest possible
; bracket to the upper bound of the highest possible one.
;
; This is usually what you want to see when evaluating an item's worth. The exception
; being when you want to reroll an affix to the highest possible value within it's
; current bracket - then you need to see the affix range that is actually on the item
; right now.
CompactDoubleRanges := 1 ; Show double ranges as "1-172" instead of "1-8 to 160-172"
CompactAffixTypes := 1 ; Use compact affix type designations: Suffix = S, Prefix = P, Comp. Suffix = CS, Comp. Prefix = CP
MirrorAffixLines := 1 ; Show a copy of the affix line in question when showing affix details.
;
; For example, would display "Prefix, 5-250" instead of "+246 to Accuracy Rating, Prefix, 5-250".
; Since the affixes are processed in order one can attribute which is which to the ordering of
; the lines in the tooltip to the item data in game.
MirrorLineFieldWidth := 18 ; Mirrored affix line width. Set to a number above 0 to truncate (or pad) to this many characters.
; Appends AffixDetailEllipsis when truncating.
ValueRangeFieldWidth := 7 ; Width of field that displays the affix' value range(s). Set to a number larger than 0 to truncate (or pad) to this many characters.
;
; Keep in mind that there are sometimes double ranges to be displayed. Like for example on an axe, implicit physical damage might
; have a lower bound range and a upper bound range. In this case the lower bound range can have at most a 3 digit minimum value,
; and at most a 3 digit maximum value. To then display just the lower bound (which constitutes one value range field), you would need
; at least 7 characters (ex: 132-179). To complete the example here is how it would look like with 2 fields (lower and upper bound)
; 132-179 168-189. Note that you don't need to set 15 as option value to display both fields correctly. As the name implies the option
; is per field, so a value of 8 can display two 8 character wide fields correctly.
AffixDetailDelimiter := " " ; Field delimiter for affix detail lines. This is put between value range fields. If this value were set to a comma, the above
; double range example would become 132-179,168-189.
AffixDetailEllipsis := "…" ; If the MirrorLineFieldWidth is set to a value that is smaller than the actual length of the affix line text
; the affix line will be cut off and this text will be appended at the end to indicate tha the line was truncated.
;
; Usually this is set to the ASCII or Unicode value of the three dot ellipsis (alt code: 0133).
; Note that the correct display of text characters outside the ASCII standard depend on the file encoding and the
; AHK version used. For best results, save this file as ANSI encoding which can be read and displayed correctly by
; either ANSI based AutoHotkey or Unicode based AutoHotkey.
;
; Example: assume the affix line to be mirrored is '+#% increased Spell Damage'.
; If the MirrorLineFieldWidth is set to 18, this field would be shown as '+#% increased Spel…'
; Pixels mouse must move to auto-dismiss tooltip
MouseMoveThreshold := 40
; Set this to 1 if you want to have the tooltip disappear after the time frame set below.
; Otherwise you will have to move the mouse by 5 pixels for the tip to disappear.
UseTooltipTimeout := 0
;How many ticks to wait before removing tooltip. 1 tick = 100ms. Example, 50 ticks = 5secends, 75 Ticks = 7.5Secends
ToolTipTimeoutTicks := 150
; Font size for the tooltip, leave empty for default
FontSize := 11
; Displays the tooltip in virtual screen space at fixed coordinates.
; Virtual screen space means the complete desktop frame, including any secondary monitors.
DisplayToolTipAtFixedCoords := 0
; Coordinates relative to top left corner, increasing by going down and to the right.
; Only used if DisplayToolTipAtFixedCoords is 1.
ScreenOffsetX := 0
ScreenOffsetY := 0
ScanUI()
{
this.OnlyActiveIfPOEIsFront := GuiGet("OnlyActiveIfPOEIsFront")
this.PutResultsOnClipboard := GuiGet("PutResultsOnClipboard")
this.ShowItemLevel := GuiGet("ShowItemLevel")
this.ShowMaxSockets := GuiGet("ShowMaxSockets")
this.ShowDamageCalculations := GuiGet("ShowDamageCalculations")
this.ShowAffixTotals := GuiGet("ShowAffixTotals")
this.ShowAffixDetails := GuiGet("ShowAffixDetails")
this.ShowAffixLevel := GuiGet("ShowAffixLevel")
this.ShowAffixBracket := GuiGet("ShowAffixBracket")
this.ShowAffixMaxPossible := GuiGet("ShowAffixMaxPossible")
this.ShowAffixBracketTier := GuiGet("ShowAffixBracketTier")
this.ShowAffixBracketTierTotal := GuiGet("ShowAffixBracketTierTotal")
this.TierRelativeToItemLevel := GuiGet("TierRelativeToItemLevel")
this.ShowDarkShrineInfo := GuiGet("ShowDarkShrineInfo")
this.ShowCurrencyValueInChaos := GuiGet("ShowCurrencyValueInChaos")
this.DisplayToolTipAtFixedCoords := GuiGet("DisplayToolTipAtFixedCoords")
this.ScreenOffsetX := GuiGet("ScreenOffsetX")
this.ScreenOffsetY := GuiGet("ScreenOffsetY")
this.MaxSpanStartingFromFirst := GuiGet("MaxSpanStartingFromFirst")
this.CompactDoubleRanges := GuiGet("CompactDoubleRanges")
this.CompactAffixTypes := GuiGet("CompactAffixTypes")
this.MirrorAffixLines := GuiGet("MirrorAffixLines")
this.MirrorLineFieldWidth := GuiGet("MirrorLineFieldWidth")
this.ValueRangeFieldWidth := GuiGet("ValueRangeFieldWidth")
this.AffixDetailDelimiter := GuiGet("AffixDetailDelimiter")
this.AffixDetailEllipsis := GuiGet("AffixDetailEllipsis")
this.MouseMoveThreshold := GuiGet("MouseMoveThreshold")
this.UseTooltipTimeout := GuiGet("UseTooltipTimeout")
this.ToolTipTimeoutTicks := GuiGet("ToolTipTimeoutTicks")
this.FontSize := GuiGet("FontSize")
}
}
Opts := new UserOptions()
class Fonts {
Init(FontSizeFixed, FontSizeUI)
{
this.FontSizeFixed := FontSizeFixed
this.FontSizeUI := FontSizeUI
this.FixedFont := this.CreateFixedFont(FontSizeFixed)
this.UIFont := this.CreateUIFont(FontSizeUI)
}
CreateFixedFont(FontSize_)
{
Options :=
If (!(FontSize_ == ""))
{
Options = s%FontSize_%
}
Gui Font, %Options%, Courier New
Gui Font, %Options%, Consolas
Gui Add, Text, HwndHidden,
SendMessage, 0x31,,,, ahk_id %Hidden%
return ErrorLevel
}
CreateUIFont(FontSize_)
{
Options :=
If (!(FontSize_ == ""))
{
Options = s%FontSize_%
}
Gui Font, %Options%, Tahoma
Gui Font, %Options%, Segoe UI
Gui Add, Text, HwndHidden,
SendMessage, 0x31,,,, ahk_id %Hidden%
return ErrorLevel
}
Set(NewFont)
{
AhkExe := GetAhkExeFilename()
SendMessage, 0x30, NewFont, 1,, ahk_class tooltips_class32 ahk_exe %AhkExe%
; Development versions of AHK
SendMessage, 0x30, NewFont, 1,, ahk_class tooltips_class32 ahk_exe AutoHotkeyA32.exe
SendMessage, 0x30, NewFont, 1,, ahk_class tooltips_class32 ahk_exe AutoHotkeyU32.exe
SendMessage, 0x30, NewFont, 1,, ahk_class tooltips_class32 ahk_exe AutoHotkeyU64.exe
}
SetFixedFont(FontSize_=-1)
{
If (FontSize_ == -1)
{
FontSize_ := this.FontSizeFixed
}
Else
{
this.FontSizeFixed := FontSize_
this.FixedFont := this.CreateFixedFont(FontSize_)
}
this.Set(this.FixedFont)
}
SetUIFont(FontSize_=-1)
{
If (FontSize_ == -1)
{
FontSize_ := this.FontSizeUI
}
Else
{
this.FontSizeUI := FontSize_
this.UIFont := this.CreateUIFont(FontSize_)
}
this.Set(this.UIFont)
}
GetFixedFont()
{
return this.FixedFont
}
GetUIFont()
{
return this.UIFont
}
}
class ItemData_ {
Links := ""
Sockets := ""
Stats := ""
NamePlate := ""
Affixes := ""
FullText := ""
IndexAffixes := -1
IndexLast := -1
PartsLast := ""
Rarity := ""
Parts := []
ClearParts()
{
Loop, % this.Parts.MaxIndex()
{
this.Parts.Remove(this.Parts.MaxIndex())
}
}
}
ItemData := new ItemData_()
class Item {
Name := ""
TypeName := ""
Quality := ""
BaseLevel := ""
RarityLevel := ""
BaseType := ""
SubType := ""
GripType := ""
Level := ""
MapLevel := ""
MaxSockets := ""
IsUnidentified := ""
IsCorrupted := ""
IsGem := ""
IsCurrency := ""
IsUnique := ""
IsRare := ""
IsBow := ""
IsFlask := ""
IsBelt := ""
IsRing := ""
IsUnsetRing := ""
IsAmulet := ""
IsTalisman := ""
IsJewel := ""
IsDivinationCard := ""
IsSingleSocket := ""
IsFourSocket := ""
IsThreeSocket := ""
IsQuiver := ""
IsWeapon := ""
IsMap := ""
IsMirrored := ""
HasEffect := ""
}
Item := new Item()
class AffixTotals_ {
NumPrefixes := 0
NumSuffixes := 0
NumTotals := 0
Reset()
{
this.NumPrefixes := 0
this.NumSuffixes := 0
this.NumTotals := 0
}
}
AffixTotals := new AffixTotals_()
class AffixLines_ {
__New()
{
this.Length := 0
}
; Sets fields to empty string
Clear(Index)
{
this[Index] := ""
}
ClearAll()
{
Loop, % this.MaxIndex()
{
this.Clear(A_Index)
}
}
; Actually removes fields
Reset()
{
Loop, % this.MaxIndex()
{
this.Remove(this.MaxIndex())
}
this.Length := 0
}
Set(Index, Contents)
{
this[Index] := Contents
this.Length := this.MaxIndex()
}
}
AffixLines := new AffixLines_()
IfNotExist, %A_ScriptDir%\config.ini
{
IfNotExist, %A_ScriptDir%\data\defaults.ini
{
CreateDefaultConfig()
}
CopyDefaultConfig()
}
; Windows system tray icon
; possible values: poe.ico, poe-bw.ico, poe-web.ico, info.ico
; set before creating the settings UI so it gets used for the settigns dialog as well
Menu, Tray, Icon, %A_ScriptDir%\data\poe-bw.ico
ReadConfig()
Sleep, 100
CreateSettingsUI()
Menu, TextFiles, Add, Additional Macros, EditAdditionalMacros
Menu, TextFiles, Add, Currency Rates, EditCurrencyRates
; Menu tooltip
RelVer := Globals.Get("ReleaseVersion")
Menu, Tray, Tip, Path of Exile Item Info %RelVer%
Menu, Tray, NoStandard
Menu, Tray, Add, About..., MenuTray_About
Menu, Tray, Add, PoE Item Info Settings, ShowSettingsUI
Menu, Tray, Add ; Separator
Menu, Tray, Add, Edit, :TextFiles
Menu, Tray, Add ; Separator
Menu, Tray, Standard
Menu, Tray, Default, PoE Item Info Settings
IfNotExist, %A_ScriptDir%\data
{
MsgBox, 16, % Msg.DataDirNotFound
exit
}
#Include %A_ScriptDir%\data\MapList.txt
#Include %A_ScriptDir%\data\DivinationCardList.txt
#Include %A_ScriptDir%\data\GemQualityList.txt
Fonts.Init(Opts.FontSize, 9)
GetAhkExeFilename(Default_="AutoHotkey.exe")
{
AhkExeFilename := Default_
If (A_AhkPath)
{
StringSplit, AhkPathParts, A_AhkPath, \
Loop, % AhkPathParts0
{
IfInString, AhkPathParts%A_Index%, .exe
{
AhkExeFilename := AhkPathParts%A_Index%
Break
}
}
}
return AhkExeFilename
}
OpenCreateDataTextFile(Filename)
{
Filepath := A_ScriptDir . "\data\" . Filename
IfExist, % Filepath
{
Run, % Filepath
}
Else
{
File := FileOpen(Filepath, "w")
if !IsObject(File)
{
MsgBox, 16, Error, File not found and can't write new file.
return
}
File.Close()
Run, % Filepath
}
return
}
OpenMainDirFile(Filename)
{
Filepath := A_ScriptDir . "\" . Filename
IfExist, % Filepath
{
Run, % Filepath
}
Else
{
MsgBox, 16, Error, File not found.
return
}
return
}
ParseAddedDamage(String, DmgType, ByRef DmgLo, ByRef DmgHi)
{
If(RegExMatch(String, "Adds (\d+) to (\d+) " DmgType " Damage", Match))
{
;StringSplit, Arr, Match, %A_Space%
;StringSplit, Arr, Arr2, -
DmgLo := Match1
DmgHi := Match2
}
}
; Function that checks item type name against entries
; from ItemList.txt to get the item's base level
; Added by kongyuyu, changed by hazydoc, vdorie
CheckBaseLevel(ItemTypeName)
{
ItemListArray = 0
Loop, Read, %A_ScriptDir%\data\ItemList.txt
{
; This loop retrieves each line from the file, one at a time.
ItemListArray += 1 ; Keep track of how many items are in the array.
StringSplit, NameLevel, A_LoopReadLine, |,
Array%ItemListArray%1 := NameLevel1 ; Store this line in the next array element.
Array%ItemListArray%2 := NameLevel2
}
ResultLength := 0
ResultIndex := 0
Loop %ItemListArray% {
element := Array%A_Index%1
if (InStr(ItemTypeName, element) != 0 && StrLen(element) > ResultLength)
{
ResultIndex := A_Index
ResultLength := StrLen(element)
}
}
BaseLevel := ""
if (ResultIndex > 0) {
BaseLevel := Array%ResultIndex%2
}
return BaseLevel
}
CheckRarityLevel(RarityString)
{
IfInString, RarityString, Normal
return 1
IfInString, RarityString, Magic
return 2
IfInString, RarityString, Rare
return 3
IfInString, RarityString, Unique
return 4
return 0 ; unknown rarity. shouldn't happen!
}
ParseItemType(ItemDataStats, ItemDataNamePlate, ByRef BaseType, ByRef SubType, ByRef GripType)
{
; Grip type only matters for weapons at this point. For all others it will be 'None'.
GripType = None
; Check stats section first as weapons usually have their sub type as first line
Loop, Parse, ItemDataStats, `n, `r
{
IfInString, A_LoopField, One Handed Axe
{
BaseType = Weapon
SubType = Axe
GripType = 1H
return
}
IfInString, A_LoopField, Two Handed Axe
{
BaseType = Weapon
SubType = Axe
GripType = 2H
return
}
IfInString, A_LoopField, One Handed Mace
{
BaseType = Weapon
SubType = Mace
GripType = 1H
return
}
IfInString, A_LoopField, Two Handed Mace
{
BaseType = Weapon
SubType = Mace
GripType = 2H
return
}
IfInString, A_LoopField, Sceptre
{
BaseType = Weapon
SubType = Sceptre
GripType = 1H
return
}
IfInString, A_LoopField, Staff
{
BaseType = Weapon
SubType = Staff
GripType = 2H
return
}
IfInString, A_LoopField, One Handed Sword
{
BaseType = Weapon
SubType = Sword
GripType = 1H
return
}
IfInString, A_LoopField, Two Handed Sword
{
BaseType = Weapon
SubType = Sword
GripType = 2H
return
}
IfInString, A_LoopField, Dagger
{
BaseType = Weapon
SubType = Dagger
GripType = 1H
return
}
IfInString, A_LoopField, Claw
{
BaseType = Weapon
SubType = Claw
GripType = 1H
return
}
IfInString, A_LoopField, Bow
{
; Not really sure if I should classify bow as 2H (because that would make sense)
; but you can equip a quiver in 2nd hand slot, so it could be 1H?
BaseType = Weapon
SubType = Bow
GripType = 1H
return
}
IfInString, A_LoopField, Wand
{
BaseType = Weapon
SubType = Wand
GripType = 1H
return
}
}
; Check name plate section
Loop, Parse, ItemDataNamePlate, `n, `r
{
; Belts, Amulets, Rings, Quivers, Flasks
IfInString, A_LoopField, Rustic Sash
{
BaseType = Item
SubType = Belt
return
}
IfInString, A_LoopField, Belt
{
BaseType = Item
SubType = Belt
return
}
If (InStr(A_LoopField, "Amulet") or InStr(A_LoopField, "Talisman"))
{
BaseType = Item
SubType = Amulet
return
}
If(RegExMatch(A_LoopField, "\bRing\b"))
{
BaseType = Item
SubType = Ring
return
}
IfInString, A_LoopField, Quiver
{
BaseType = Item
SubType = Quiver
return
}
IfInString, A_LoopField, Flask
{
BaseType = Item
SubType = Flask
return
}
IfInString, A_LoopField, %A_Space%Map
{
Global matchList
BaseType = Map
Loop % matchList.MaxIndex()
{
Match := matchList[A_Index]
IfInString, A_LoopField, %Match%
{
SubType = %Match%
return
}
}
SubType = Unknown%A_Space%Map
return
}
; Dry Peninsula fix
IfInString, A_LoopField, Dry%A_Space%Peninsula
{
BaseType = Map
SubType = Dry%A_Space%Peninsula
return
}
; Jewels
IfInString, A_LoopField, Cobalt%A_Space%Jewel
{
BaseType = Jewel
SubType = Cobalt Jewel
return
}
IfInString, A_LoopField, Crimson%A_Space%Jewel
{
BaseType = Jewel
SubType = Crimson Jewel
return
}
IfInString, A_LoopField, Viridian%A_Space%Jewel
{
BaseType = Jewel
SubType = Viridian Jewel
return
}
IfInString, A_LoopField, Prismatic%A_Space%Jewel
{
BaseType = Jewel
SubType = Prismatic Jewel
return
}
; Matching armour types with regular expressions to reduce
; potential mismatches due to the huge base item name variety and
; the word lists used for the randomly assigned (first line) item name.
; "$" means line end, "|" is the usual "or" operator.
; Shields
If (RegExMatch(A_LoopField, "Buckler$|Bundle$|Shield$"))
{
BaseType = Armour
SubType = Shield
return
}
; Gloves
If (RegExMatch(A_LoopField, "Gauntlets$|Gloves$|Mitts$"))
{
BaseType = Armour
SubType = Gloves
return
}
; Boots
If (RegExMatch(A_LoopField, "Boots$|Greaves$|Slippers$"))
{
BaseType = Armour
SubType = Boots
return
}
; Helmets
If (RegExMatch(A_LoopField, "Bascinet$|Burgonet$|Cage$|Circlet$|Crown$|Hood$|Helm$|Helmet$|Mask$|Sallet$|Tricorne$"))
{
BaseType = Armour
SubType = Helmet
return
}
; Note: Body armours can have "Pelt" in their randomly assigned name,
; explicitly matching the three pelt base items to be safe.
If (RegExMatch(A_LoopField, "Iron Hat|Leather Cap|Rusted Coif|Wolf Pelt|Ursine Pelt|Lion Pelt"))
{
BaseType = Armour
SubType = Helmet
return
}
; BodyArmour
If (RegExMatch(A_LoopField, "Armour$|Brigandine$|Chainmail$|Coat$|Doublet$|Garb$|Hauberk$|Jacket$|Lamellar$|Leather$|Plate$|Raiment$|Regalia$|Ringmail$|Robe$|Tunic$|Vest$|Vestment$"))
{
BaseType = Armour
SubType = BodyArmour
return
}
If (RegExMatch(A_LoopField, "Chestplate|Full Dragonscale|Full Wyrmscale|Necromancer Silks|Shabby Jerkin|Silken Wrap"))
{
BaseType = Armour
SubType = BodyArmour
return
}
}
}
GetClipboardContents(DropNewlines=False)
{
Result =
If Not DropNewlines
{
Loop, Parse, Clipboard, `n, `r
{
IfInString, A_LoopField, note: ; new code added by Bahnzo - The ability to add prices to items causes issues. Building the code sent from the clipboard
{ ; differently, and ommiting the line with "Note:" on it partially fixes this. We also have to omit the \newline \return
break ; that gets added at the end
}
IfInString, A_LoopField, Map drop
{
break
}
If A_Index = 1 ; so we start with just adding the first line w/o either a `n or `r
{
Result := Result . A_LoopField
}
else
{
Result := Result . "`r`n" . A_LoopField ; and then adding those before adding lines. This makes sure there are no trailing `n or `r.
;Result := Result . A_LoopField . "`r`n" ; the original line, left in for clarity.
}
}
}
Else
{
Loop, Parse, Clipboard, `n, `r
{
IfInString, A_LoopField, note:
{
break
}
Result := Result . A_LoopField
}
}
return Result
}
SetClipboardContents(String)
{
Clipboard := String
}
; Splits StrInput on StrDelimiter. Returns an object that has a 'length' field
; containing the number of parts and 0 .. (length) fields containing the substrings.
; Example: if parts is the object returned by this function, then
; 'parts.length' gives the number of parts
; 'parts[1]' gives the first part (if there is one)
; Note: if StrDelimiter is not present in StrInput, length == 1 and parts[1] == StrInput
; Note2: as per AHK docs, parts.(Min|Max)Index() also work of course.
SplitString(StrInput, StrDelimiter)
{
TempDelim := "``"
Chunks := Object()
StringReplace, TempResult, StrInput, %StrDelimiter%, %TempDelim%, All
StringSplit, Parts, TempResult, %TempDelim%
Chunks["length"] := Parts0