|
- ;; init note
-
- (if (> 1 (# itemdb))
- (print "Failed to load item database")
- (print "Item database loaded"))
-
- ;; 1a: coll utils
-
- (fn length-of [coll]
- (if coll
- (do
- (var c 0)
- (each [k (pairs coll)]
- (set c (+ c 1)))
- c)
- 0))
-
- (fn first [coll]
- (let [key (next coll)]
- (. coll key)))
-
- ;; 1b: str utils
-
- (fn starts-with [s patt]
- (= (string.sub s 1 (string.len patt)) patt))
-
- (fn un-quote [s]
- (string.gsub s "\'" ""))
-
- ;; 1c: number utils
-
- (fn max [a b]
- (if (> a b) a b))
-
- ;; 1d: fennel utils
-
- (fn matches [a b]
- (if (starts-with a "lte:")
- (>= (tonumber (string.sub a 5)) (tonumber b))
-
- (starts-with a "gte:")
- (<= (tonumber (string.sub a 5)) (tonumber b))
-
- (starts-with a "lt<:")
- (> (tonumber (string.sub a 5)) (tonumber b))
-
- (starts-with a "gt>:")
- (< (tonumber (string.sub a 5)) (tonumber b))
-
- (starts-with a "contains:")
- (string.match (string.sub a 9) b)
-
- (= a b)))
-
- ;; 2a: querying
-
- (lambda find-items [params ?sort]
- (let [results (icollect [_ row (ipairs itemdb)]
- (do
- (var hit true)
- (each [key param (pairs params)]
- (do
- (set hit (and hit (matches param (. row key))))))
- (if hit
- row)))]
- (if (and ?sort results)
- (do
- (table.sort results ?sort)
- results)
- results)))
-
- (lambda find-item [params ?sort]
- (let [results (find-items params ?sort)]
- (if results
- (. results 1))))
-
- ;; 2b: specialized querying
-
- (fn find-item-by-name [name]
- (find-item {8 (.. "contains:" name)}))
-
- (fn find-next-better-item [class subclass invtype lv ilv stat-position item-stat ?sort]
- (let [stat-comparison "gt>:%d"]
- (find-items {4 class
- 6 subclass
- 10 invtype
- 14 (string.format "lte:%d" lv)
- stat-position (string.format stat-comparison item-stat)}
- ?sort)))
-
- (lambda find-good-item [invtype lv stat-position stat-baseline ?sort]
- (find-items {10 invtype
- 14 (string.format "lte:%d" lv)
- stat-position (string.format "gte:%d" stat-baseline)}
- ?sort))
-
- ;; 3b: specialized parsing
-
- (fn parse-item-id [link]
- (tonumber (string.sub (string.match link "item:[%d+]+") 6)))
-
- ;; 3c: arg parsing
-
- (fn parse-opts [msg]
- (icollect [k v (string.gmatch msg "%w+")] v))
-
- ;; 4a: ui
-
- (fn ui-print [msg]
- (UIErrorsFrame:AddMessage msg))
-
- ;; 4b
- (fn stat-name [n]
- (let [stat-names ["Mana" "Health" "No Visible Effect"
- "Agility" "Strength" "Intellect"
- "Spirit" "Stamina" "No Visible Effect" "No Visible Effect"
-
- "No Visible Effect" "No Visible Effect*" "Defense Rating"
- "Dodge" "Parry Rating" "Shield Block Rating"
- "Melee Hit Rating" "Ranged Hit Rating" "Spell Hit Rating"
-
- "Melee Critical Strike" "Ranged Critical Strike" "Spell Critical Strike"
- "Melee Hit Avoidance" "Ranged Hit Avoidance" "Spell Hit Avoidance"
- "Melee Critical Avoidance" "Spell Critical Avoidance" "Melee Haste Rating"
-
- "Ranged Haste Rating" "Spell Haste Rating" "Hit Avoidance Rating"
- "Hit Rating" "Critical Strike" "Hit Avoidance Rating"
-
- "Critical Avoidance Rating" "Resilience" "Haste"
- "Expertise" "Attack Power" "Ranged Attack Power"
- "No Visible Effect" "Healing Done By Magical Spells and Effects up to value" "Damage Done By Magical Spells and Effects up to value"
-
- "Mana Regeneration (Ticks every 5 seconds)" "Armor Penetration Rating" "Spell Power"
- "Health Regeneration (Ticks every 5 seconds)" "Spell Penetration" "Block Value of Shield"
- "Mastery" "Armor" "Fire Resist"
-
- "Frost Resist" "Shadow Resist" "Nature Resist"
- "Arcane Resist"]]
- (.. (. stat-names (+ n 1)) " (" n ")")))
-
- (fn stat-print [item]
- (var val "")
- (for [n 22 56]
- (if (< 0 (. item n))
- (set val (.. val " " (stat-name (- n 21)) ": " (. item n)))))
- val)
-
- ;; 5: main
-
- (global
- main
- (fn main [msg]
- (let [opts (icollect [v (string.gmatch msg "%w+")] v)
- [slot stat gear-index] opts
-
- slot (.. slot "Slot") ;; omit the need to type it out
- stat (+ 21 (tonumber stat)) ;; stats start after field 21, so agility (3) is 22+3, etc
- gear-index (tonumber (or gear-index "1"))
-
- inv-slot (GetInventorySlotInfo slot)
- i-link (GetInventoryItemLink "player" inv-slot)
-
- i-id (if i-link (parse-item-id i-link))
- p-level (UnitLevel "player")]
-
- (if (not i-link)
- ;; empty
- (let [best (.
- (find-good-item
- inv-slot
- (UnitLevel "player")
- stat
- 0
- (fn [a b]
- (< (+ (. a 12) (. a stat))
- (+ (. b 12) (. b stat))) ))
- gear-index)]
- (if best
- (do
- (DEFAULT_CHAT_FRAME:AddMessage (string.format "\124Hitem:%d:0:0:0:0:0:0:0:0\124h[%s]\124h\124r" (. best 2) (. best 8)))
- (ui-print (.. "next best available: "
- (. best 8)
- " "
- (stat-print best)
- " at "
- (or (. best 20)) "N/A")))))
-
- ;; exists
- (let [i-name (GetItemInfo i-link)
- stats (find-item-by-name (un-quote i-name))]
-
- (if stats
- (let [i-class (. stats 4)
- i-subclass (. stats 6)
- i-invtype (. stats 10)
- i-level (. stats 12)
- i-stat (. stats stat)
- best (. (find-next-better-item i-class i-subclass i-invtype p-level i-level stat (max i-stat 0) (fn [a b]
- (< (+ (. a 12) (. a stat))
- (+ (. b 12) (. b stat)) ))) gear-index)]
- (if best
- (do
- (DEFAULT_CHAT_FRAME:AddMessage (string.format "\124Hitem:%d:0:0:0:0:0:0:0:0\124h[%s]\124h\124r" (. best 2) (. best 8)))
- (ui-print (.. "next best available: "
- (. best 8)
- " "
- (stat-print best)
- " at "
- (or (. best 20)) "N/A"))
-
- (ui-print (.. "currently equipped " i-name " " (or (. stats stat) "N/A"))))))
- (print (.. "Item " (un-quote i-name) " not found")))
- "ok")))))
-
- ;; unused
- (fn maxxed []
- (let [slots ["AmmoSlot"
- "BackSlot"
- "Bag0Slot"
- "Bag1Slot"
- "Bag2Slot"
- "Bag3Slot"
- "ChestSlot"
- "FeetSlot"
- "Finger0Slot"
- "Finger1Slot"
- "HandsSlot"
- "HeadSlot"
- "LegsSlot"
- "MainHandSlot"
- "NeckSlot"
- "RangedSlot"
- "SecondaryHandSlot"
- "ShirtSlot"
- "ShoulderSlot"
- "TabardSlot"
- "Trinket0Slot"
- "Trinket1Slot"
- "WaistSlot"
- "WristSlot"]]
- slots))
|