2.4.3. addon, shows better gear by slot and stat type
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

242 lines
7.9KB

  1. ;; init note
  2. (if (> 1 (# itemdb))
  3. (print "Failed to load item database")
  4. (print "Item database loaded"))
  5. ;; 1a: coll utils
  6. (fn length-of [coll]
  7. (if coll
  8. (do
  9. (var c 0)
  10. (each [k (pairs coll)]
  11. (set c (+ c 1)))
  12. c)
  13. 0))
  14. (fn first [coll]
  15. (let [key (next coll)]
  16. (. coll key)))
  17. ;; 1b: str utils
  18. (fn starts-with [s patt]
  19. (= (string.sub s 1 (string.len patt)) patt))
  20. (fn un-quote [s]
  21. (string.gsub s "\'" ""))
  22. ;; 1c: number utils
  23. (fn max [a b]
  24. (if (> a b) a b))
  25. ;; 1d: fennel utils
  26. (fn matches [a b]
  27. (if (starts-with a "lte:")
  28. (>= (tonumber (string.sub a 5)) (tonumber b))
  29. (starts-with a "gte:")
  30. (<= (tonumber (string.sub a 5)) (tonumber b))
  31. (starts-with a "lt<:")
  32. (> (tonumber (string.sub a 5)) (tonumber b))
  33. (starts-with a "gt>:")
  34. (< (tonumber (string.sub a 5)) (tonumber b))
  35. (starts-with a "contains:")
  36. (string.match (string.sub a 9) b)
  37. (= a b)))
  38. ;; 2a: querying
  39. (lambda find-items [params ?sort]
  40. (let [results (icollect [_ row (ipairs itemdb)]
  41. (do
  42. (var hit true)
  43. (each [key param (pairs params)]
  44. (do
  45. (set hit (and hit (matches param (. row key))))))
  46. (if hit
  47. row)))]
  48. (if (and ?sort results)
  49. (do
  50. (table.sort results ?sort)
  51. results)
  52. results)))
  53. (lambda find-item [params ?sort]
  54. (let [results (find-items params ?sort)]
  55. (if results
  56. (. results 1))))
  57. ;; 2b: specialized querying
  58. (fn find-item-by-name [name]
  59. (find-item {8 (.. "contains:" name)}))
  60. (fn find-next-better-item [class subclass invtype lv ilv stat-position item-stat ?sort]
  61. (let [stat-comparison "gt>:%d"]
  62. (find-items {4 class
  63. 6 subclass
  64. 10 invtype
  65. 14 (string.format "lte:%d" lv)
  66. stat-position (string.format stat-comparison item-stat)}
  67. ?sort)))
  68. (lambda find-good-item [invtype lv stat-position stat-baseline ?sort]
  69. (find-items {10 invtype
  70. 14 (string.format "lte:%d" lv)
  71. stat-position (string.format "gte:%d" stat-baseline)}
  72. ?sort))
  73. ;; 3b: specialized parsing
  74. (fn parse-item-id [link]
  75. (tonumber (string.sub (string.match link "item:[%d+]+") 6)))
  76. ;; 3c: arg parsing
  77. (fn parse-opts [msg]
  78. (icollect [k v (string.gmatch msg "%w+")] v))
  79. ;; 4a: ui
  80. (fn ui-print [msg]
  81. (UIErrorsFrame:AddMessage msg))
  82. ;; 4b
  83. (fn stat-name [n]
  84. (let [stat-names ["Mana" "Health" "No Visible Effect"
  85. "Agility" "Strength" "Intellect"
  86. "Spirit" "Stamina" "No Visible Effect" "No Visible Effect"
  87. "No Visible Effect" "No Visible Effect*" "Defense Rating"
  88. "Dodge" "Parry Rating" "Shield Block Rating"
  89. "Melee Hit Rating" "Ranged Hit Rating" "Spell Hit Rating"
  90. "Melee Critical Strike" "Ranged Critical Strike" "Spell Critical Strike"
  91. "Melee Hit Avoidance" "Ranged Hit Avoidance" "Spell Hit Avoidance"
  92. "Melee Critical Avoidance" "Spell Critical Avoidance" "Melee Haste Rating"
  93. "Ranged Haste Rating" "Spell Haste Rating" "Hit Avoidance Rating"
  94. "Hit Rating" "Critical Strike" "Hit Avoidance Rating"
  95. "Critical Avoidance Rating" "Resilience" "Haste"
  96. "Expertise" "Attack Power" "Ranged Attack Power"
  97. "No Visible Effect" "Healing Done By Magical Spells and Effects up to value" "Damage Done By Magical Spells and Effects up to value"
  98. "Mana Regeneration (Ticks every 5 seconds)" "Armor Penetration Rating" "Spell Power"
  99. "Health Regeneration (Ticks every 5 seconds)" "Spell Penetration" "Block Value of Shield"
  100. "Mastery" "Armor" "Fire Resist"
  101. "Frost Resist" "Shadow Resist" "Nature Resist"
  102. "Arcane Resist"]]
  103. (.. (. stat-names (+ n 1)) " (" n ")")))
  104. (fn stat-print [item]
  105. (var val "")
  106. (for [n 22 56]
  107. (if (< 0 (. item n))
  108. (set val (.. val " " (stat-name (- n 21)) ": " (. item n)))))
  109. val)
  110. ;; 5: main
  111. (global
  112. main
  113. (fn main [msg]
  114. (let [opts (icollect [v (string.gmatch msg "%w+")] v)
  115. [slot stat gear-index] opts
  116. slot (.. slot "Slot") ;; omit the need to type it out
  117. stat (+ 21 (tonumber stat)) ;; stats start after field 21, so agility (3) is 22+3, etc
  118. gear-index (tonumber (or gear-index "1"))
  119. inv-slot (GetInventorySlotInfo slot)
  120. i-link (GetInventoryItemLink "player" inv-slot)
  121. i-id (if i-link (parse-item-id i-link))
  122. p-level (UnitLevel "player")]
  123. (if (not i-link)
  124. ;; empty
  125. (let [best (.
  126. (find-good-item
  127. inv-slot
  128. (UnitLevel "player")
  129. stat
  130. 0
  131. (fn [a b]
  132. (< (+ (. a 12) (. a stat))
  133. (+ (. b 12) (. b stat))) ))
  134. gear-index)]
  135. (if best
  136. (do
  137. (DEFAULT_CHAT_FRAME:AddMessage (string.format "\124Hitem:%d:0:0:0:0:0:0:0:0\124h[%s]\124h\124r" (. best 2) (. best 8)))
  138. (ui-print (.. "next best available: "
  139. (. best 8)
  140. " "
  141. (stat-print best)
  142. " at "
  143. (or (. best 20)) "N/A")))))
  144. ;; exists
  145. (let [i-name (GetItemInfo i-link)
  146. stats (find-item-by-name (un-quote i-name))]
  147. (if stats
  148. (let [i-class (. stats 4)
  149. i-subclass (. stats 6)
  150. i-invtype (. stats 10)
  151. i-level (. stats 12)
  152. i-stat (. stats stat)
  153. best (. (find-next-better-item i-class i-subclass i-invtype p-level i-level stat (max i-stat 0) (fn [a b]
  154. (< (+ (. a 12) (. a stat))
  155. (+ (. b 12) (. b stat)) ))) gear-index)]
  156. (if best
  157. (do
  158. (DEFAULT_CHAT_FRAME:AddMessage (string.format "\124Hitem:%d:0:0:0:0:0:0:0:0\124h[%s]\124h\124r" (. best 2) (. best 8)))
  159. (ui-print (.. "next best available: "
  160. (. best 8)
  161. " "
  162. (stat-print best)
  163. " at "
  164. (or (. best 20)) "N/A"))
  165. (ui-print (.. "currently equipped " i-name " " (or (. stats stat) "N/A"))))))
  166. (print (.. "Item " (un-quote i-name) " not found")))
  167. "ok")))))
  168. ;; unused
  169. (fn maxxed []
  170. (let [slots ["AmmoSlot"
  171. "BackSlot"
  172. "Bag0Slot"
  173. "Bag1Slot"
  174. "Bag2Slot"
  175. "Bag3Slot"
  176. "ChestSlot"
  177. "FeetSlot"
  178. "Finger0Slot"
  179. "Finger1Slot"
  180. "HandsSlot"
  181. "HeadSlot"
  182. "LegsSlot"
  183. "MainHandSlot"
  184. "NeckSlot"
  185. "RangedSlot"
  186. "SecondaryHandSlot"
  187. "ShirtSlot"
  188. "ShoulderSlot"
  189. "TabardSlot"
  190. "Trinket0Slot"
  191. "Trinket1Slot"
  192. "WaistSlot"
  193. "WristSlot"]]
  194. slots))