1 local default_colour_theme
=
2 {message_prefix
={0.4, 0.78, 1},
5 message_highlight
={0.73, 1, 0.84},
7 menu_text_highlight
={0, 0, 0},
9 menu_highlight
={0.3, 0.5, 0.7},
10 menu_title_text
={1, 1, 1},
11 menu_title_text_highlight
={1, 1, 1},
12 menu_title
={0, 0.2, 0.6},
13 menu_title_highlight
={0.1, 0.4, 0.8}}
15 local xmas_colour_theme
=
16 {message_prefix
={0.0, 0.7, 0.0},
17 message
={0.2, 1, 0.2},
18 tooltip
={0.4, 1, 0.4},
19 message_highlight
={1, 0.3, 0.1},
21 menu_text_highlight
={0, 0, 0},
23 menu_highlight
={1, 0.3, 0.3},
24 menu_title_text
={0.8, 1, 0.8},
25 menu_title_text_highlight
={1, 1, 1},
26 menu_title
={0.2, 0.6, 0.2},
27 menu_title_highlight
={0.4, 0.7, 0.4}}
29 function QuestHelper
:GetColourTheme()
30 if date("%b%d") == "Dec25" then
31 return xmas_colour_theme
34 return default_colour_theme
37 QuestHelper
.nop
= function () end -- Who wouldn't want a function that does nothing?
39 function QuestHelper
:HashString(text
)
40 -- Computes an Adler-32 checksum.
42 for i
=1,string.len(text
) do
43 a
= (a
+string.byte(text
,i
))%65521
49 function QuestHelper
:CreateUID()
51 local characters
= "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
52 math
.randomseed(math
.random(0, 2147483647)+GetTime()*100000)
53 local base
= GetUnitName("player")..":"..GetRealmName()..":"..math
.random(0, 2147483647)..":"..GetTime()..":"..time()
56 local pos
= 1+math
.floor(self
:HashString(result
..base
..math
.random(0, 2147483647))%string.len(characters
))
57 result
= result
.. string.sub(characters
, pos
, pos
)
63 function QuestHelper
:ZoneSanity()
66 for c
=1, select("#", GetMapContinents()) do
67 for z
=0, select("#", GetMapZones(c
)) do
71 name
= select(c
, GetMapContinents())
73 name
= select(z
, GetMapZones(c
))
78 if QuestHelper_Zones
[c
][z
] ~= name
then
80 QuestHelper
:TextOut("'"..name
.."' has the wrong ID.")
83 local pair
= QuestHelper_ZoneLookup
[name
]
85 if not pair
or c
~= pair
[1] or z
~= pair
[2] then
87 QuestHelper
:TextOut("ZoneLookup['"..name
.."'] maps to wrong pair.")
90 local index
= QuestHelper_IndexLookup
[name
]
91 if QuestHelper_ZoneLookup
[index
] ~= pair
then
93 QuestHelper
:TextOut("ZoneLookup['"..name
.."'] isn't equal to ZoneLookup["..index
.."]")
96 if not index
or QuestHelper_NameLookup
[index
] ~= name
then
98 QuestHelper
:TextOut("NameLookup["..(index
or "???").."'] doesn't equal '"..name
.."'")
106 function QuestHelper
:TextOut(text
)
107 local theme
= self
:GetColourTheme()
108 DEFAULT_CHAT_FRAME
:AddMessage(string.format("|cff%2x%2x%2xQuestHelper: |r%s", theme
.message_prefix
[1]*255,
109 theme
.message_prefix
[2]*255,
110 theme
.message_prefix
[3]*255, text
),
116 function QuestHelper
:Error(what
)
117 DEFAULT_CHAT_FRAME
:AddMessage("QuestHelper Error: "..(what
or "Unknown").."\n"..debugstack(2), 1,.5,0)
121 function QuestHelper
:HighlightText(text
)
122 local theme
= self
:GetColourTheme()
123 return string.format("|cff%2x%2x%2x%s|r", theme
.message_highlight
[1]*255,
124 theme
.message_highlight
[2]*255,
125 theme
.message_highlight
[3]*255, text
)
128 -- For future reference:
129 -- Hearthstone = 6948
130 -- Rune of Teleportation = 17031
131 -- Rune of Portals = 17032
133 function QuestHelper
:CountItem(item_id
)
136 for bag
= 0,NUM_BAG_SLOTS
do
137 for slot
= 1,GetContainerNumSlots(bag
) do
138 local link
= GetContainerItemLink(bag
, slot
)
139 if link
and string.find(link
, string.format("|Hitem:%d:", item_id
)) then
140 count
= count
+ (select(2, GetContainerItemInfo(bag
, slot
)) or 0)
148 function QuestHelper
:ItemCooldown(item_id
)
149 local now
= GetTime()
152 for bag
= 0,NUM_BAG_SLOTS
do
153 for slot
= 1,GetContainerNumSlots(bag
) do
154 local link
= GetContainerItemLink(bag
, slot
)
155 if link
and string.find(link
, string.format("|Hitem:%d:", item_id
)) then
156 local s
, d
, e
= GetContainerItemCooldown(bag
, slot
)
159 cooldown
= math
.min(cooldown
, math
.max(0, d
-now
+s
))
161 cooldown
= math
.max(0, d
-now
+s
)
173 function QuestHelper
:TimeString(seconds
)
174 local seconds
= math
.ceil(seconds
)
175 local h
, m
, s
= math
.floor(seconds
/(60*60)), math
.floor(seconds
/60)%60, seconds
%60
177 return string.format("|cffffffff%d|r:|cffffffff%02d|r:|cffffffff%02d|r", h
, m
, s
)
179 return string.format("|cffffffff%d|r:|cffffffff%02d|r", m
, s
)
183 function QuestHelper
:ProgressString(str
, pct
)
185 return string.format("|cff00ff00%s|r", str
)
187 return string.format("|cffff0000%s|r", str
)
188 elseif pct
> 0.5 then
189 return string.format("|cff%2xff00%s|r", 510-pct
*510, str
)
191 return string.format("|cffff%2x00%s|r", pct
*510, str
)
195 function QuestHelper
:PercentString(pct
)
197 return string.format("|cff00ff00%.1f%%|r", pct
*100)
199 return string.format("|cffff0000%.1f%%|r", pct
*100)
200 elseif pct
> 0.5 then
201 return string.format("|cff%2xff00%.1f%%|r", 510-pct
*510, pct
*100)
203 return string.format("|cffff%2x00%.1f%%|r", pct
*510, pct
*100)
207 function QuestHelper
:PlayerPosition()
208 return self
.i
, self
.x
, self
.y
211 function QuestHelper
:UnitPosition(unit
)
212 local c
, z
, x
, y
= self
.Astrolabe
:GetUnitPosition(unit
,true)
215 SetMapToCurrentZone()
216 z
= GetCurrentMapZone()
218 x
, y
= self
.Astrolabe
:TranslateWorldMapPosition(c
, 0, x
, y
, c
, z
)
221 return QuestHelper_IndexLookup
[c
][z
], x
, y
223 return self
:PlayerPosition()
227 function QuestHelper
:LocationString(i
, x
, y
)
228 return ("[|cffffffff%s|r:|cffffffff%d,%.3f,%.3f|r]"):format(QuestHelper_NameLookup
[i
] or "nil", i
, x
, y
)
231 function QuestHelper
:Distance(i1
, x1
, y1
, i2
, x2
, y2
)
232 local p1
, p2
= QuestHelper_ZoneLookup
[i1
], QuestHelper_ZoneLookup
[i2
]
233 return self
.Astrolabe
:ComputeDistance(p1
[1], p1
[2], x1
, y1
, p2
[1], p2
[2], x2
, y2
) or 10000
236 function QuestHelper
:AppendPosition(list
, index
, x
, y
, w
, min_dist
)
237 if (x
== 0 and y
== 0) or x
<= -0.1 or y
<= -0.1 or x
>= 1.1 or y
>= 1.1 then
238 return list
-- This isn't a real position.
241 local closest
, distance
= nil, 0
243 min_dist
= min_dist
or 200
245 for i
, p
in ipairs(list
) do
246 if index
== p
[1] then
247 local d
= self
:Distance(index
, x
, y
, p
[1], p
[2], p
[3])
248 if not closest
or d
< distance
then
249 closest
, distance
= i
, d
254 if closest
and distance
< min_dist
then
255 local p
= list
[closest
]
256 p
[2] = (p
[2]*p
[4]+x
*w
)/(p
[4]+w
)
257 p
[3] = (p
[3]*p
[4]+y
*w
)/(p
[4]+w
)
260 table.insert(list
, {index
, x
, y
, w
})
266 function QuestHelper
:PositionListDistance(list
, index
, x
, y
)
267 local closest
, distance
= nil, 0
268 for i
, p
in ipairs(list
) do
269 local d
= self
:Distance(index
, x
, y
, p
[1], p
[2], p
[3])
270 if not closest
or d
< distance
then
271 closest
, distance
= p
, d
275 return distance
, closest
[1], closest
[2], closest
[3]
279 function QuestHelper
:PositionListDistance2(list
, i1
, x1
, y1
, i2
, x2
, y2
)
280 local closest
, bd1
, bd2
, bdt
= nil, 0, 0, 0
281 for i
, p
in ipairs(list
) do
282 local d1
= self
:Distance(i1
, x1
, y1
, p
[1], p
[2], p
[3])
283 local d2
= self
:Distance(i2
, x2
, y2
, p
[1], p
[2], p
[3])
285 if not closest
or t
< bdt
then
286 closest
, bd1
, bd2
, bdt
= p
, d1
, d2
, t
290 return d1
, d2
, closest
[1], closest
[2], closest
[3]
294 function QuestHelper
:MergePositions(list1
, list2
)
295 for i
, p
in ipairs(list2
) do
296 self
:AppendPosition(list1
, unpack(p
))
300 function QuestHelper
:MergeDrops(list1
, list2
)
301 for element
, count
in pairs(list2
) do
302 list1
[element
] = (list1
[element
] or 0) + count