vrtc / flowerpicker (public) (License: GPLv3) (since 2019-11-07) (hash sha1)
Flowerpicker is a GUI extension, that is an add-on, for World of Warcraft game client. It is under development and not yet ready for usage by players.
List of commits:
Subject Hash Author Date (UTC)
Add Luacheck static analysis with Gradle b9274ae52d8de1c6f3be31cd967d09d6f3ae1cf8 Vladyslav Bondarenko 2019-11-12 16:50:47
Apply LDoc with Gradle 3643910c9413638c6c5ef0224fe106758dcf18eb Vladyslav Bondarenko 2019-11-12 14:08:46
Add report at runtime mock 1401862377ee083669c51fb850c8b0a97154b68b Vladyslav Bondarenko 2019-11-11 20:30:53
Add basic fishing registration ec6c45c1c89890cad3ae591d2483c47b94cacf86 Vladyslav Bondarenko 2019-11-08 18:57:30
Add world resource node harvest registration 2c7e1542abf677efc70a616291921f92ed9c04dd Vladyslav Bondarenko 2019-11-07 12:16:39
Update registration of money operations f0b4ec71099900dd51b5a4c35ce688586d6ddbfe Vladyslav Bondarenko 2019-11-06 19:49:01
Add basic money income via looting registration 9cfb08138268bb6985db1729c160b444a5e4e56a Vladyslav Bondarenko 2019-11-06 14:07:53
Update event format 554e63f3490dc48befe37fbfacf5c8c9ad188451 Vladyslav Bondarenko 2019-11-06 09:59:18
Initial commit f014031ddd4b2422ef5d000f33ad6602e64c9b36 Vladyslav Bondarenko 2019-11-05 20:29:14
Commit b9274ae52d8de1c6f3be31cd967d09d6f3ae1cf8 - Add Luacheck static analysis with Gradle
The code was statycally checked by LuaCheck tool and fixed
accordinaly. LuaCheck tool is now included in the Gradle build
process.
Author: Vladyslav Bondarenko
Author date (UTC): 2019-11-12 16:50
Committer name: Vladyslav Bondarenko
Committer date (UTC): 2019-11-12 16:50
Parent(s): 7504b74dfaff72c0991df93541a096c3a690767c
Signer:
Signing key:
Signing status: N
Tree: 1b7b001c0d1fd4e14fd277b785ce44dc4fa590df
File Lines added Lines deleted
.luacheckrc 48 0
Flowerpicker.lua 74 57
README.md 25 4
build.gradle 7 0
File .luacheckrc added (mode: 100644) (index 0000000..ca05b1e)
1 -- http://luacheck.readthedocs.io/en/stable/config.html
2 stds.wow = {
3 globals = {}, -- these globals can be set and accessed.
4 read_globals = {
5 "CreateFrame",
6 "GetContainerItemID",
7 "GetContainerItemInfo",
8 "GetContainerNumSlots",
9 "GetItemInfo",
10 "GetLootSlotInfo",
11 "GetMoney",
12 "GetNumLootItems",
13 "GetRealmName",
14 "GetSpellInfo",
15 "GetSubZoneText",
16 "GetZoneText",
17 "HideUIPanel",
18 "LootSlotIsCoin",
19 "LootSlotIsItem",
20 "MerchantFrame",
21 "ShowUIPanel",
22 "StaticPopup_Show",
23 "UIParent",
24 "UnitIsDead",
25 "UnitName",
26 "UnitPlayerControlled",
27 "date",
28 "difftime",
29 "geterrorhandler",
30 "getglobal",
31 "hooksecurefunc",
32 "strtrim",
33 "time",
34 } -- these globals can only be accessed.
35 }
36
37 stds.flowerpicker = {
38 globals = {
39 "FlowerpickerAddOnFrame",
40 "FlowerpickerLootCache",
41 "FlowerpickerReportFrame",
42 "FlowerpickerSavedVariables",
43 },
44 read_globals = {
45 }
46 }
47
48 std = "min+wow+flowerpicker"
File Flowerpicker.lua changed (mode: 100644) (index d6c4356..cce23a4)
... ... Shared snippets, specifically for date manipulation and value validation.
12 12 @section util @section util
13 13 ]] ]]
14 14
15 --[[--
15 --[[--
16 16 Compute the difference in seconds between local time and UTC. Compute the difference in seconds between local time and UTC.
17 17 Modified to rely on WoW wrappers of Lua os.* functions. Modified to rely on WoW wrappers of Lua os.* functions.
18 `timezone = get_timezone()`
18 ```
19 timezone = get_timezone()
20 ```
19 21 @author Eric Feliksik @author Eric Feliksik
20 @see http://lua-users.org/wiki/TimeZone
22 @see http://lua-users.org/wiki/TimeZone
21 23 @function get_timezone @function get_timezone
22 24 @return number timezone number @return number timezone number
23 25 ]] ]]
 
... ... end
29 31 --[[-- --[[--
30 32 Return a timezone string in ISO 8601:2000 standard form (+hhmm or -hhmm). Return a timezone string in ISO 8601:2000 standard form (+hhmm or -hhmm).
31 33 Modified to rely on WoW wrappers of Lua os.* functions. Modified to rely on WoW wrappers of Lua os.* functions.
32 `tzoffset = get_tzoffset(timezone)`
34 ```
35 tzoffset = get_tzoffset(timezone)
36 ```
33 37 @author Eric Feliksik @author Eric Feliksik
34 @see http://lua-users.org/wiki/TimeZone
38 @see http://lua-users.org/wiki/TimeZone
35 39 @function get_tzoffset @function get_tzoffset
36 40 @param timezone number timezone number returned by `get_timezone` @param timezone number timezone number returned by `get_timezone`
37 41 @return string timezone string @return string timezone string
 
... ... local function get_tzoffset(timezone)
41 45 return string.format("%+.4d", 100 * h + 60 * m) return string.format("%+.4d", 100 * h + 60 * m)
42 46 end end
43 47
44
45 48 --[[ debugging --[[ debugging
46 49 for _, tz in ipairs(arg) do for _, tz in ipairs(arg) do
47 50 if tz == '-' then if tz == '-' then
 
... ... end
56 59 --[[-- --[[--
57 60 Return the timezone offset in seconds, as it was on the time given by ts. Return the timezone offset in seconds, as it was on the time given by ts.
58 61 @author Eric Feliksik @author Eric Feliksik
59 @see http://lua-users.org/wiki/TimeZone
62 @see http://lua-users.org/wiki/TimeZone
60 63 @function get_timezone_offset @function get_timezone_offset
61 64 @param ts @param ts
62 65 @return number @return number
63 66 ]] ]]
64 67 local function get_timezone_offset(ts) local function get_timezone_offset(ts)
65 local utcdate = date("!*t", ts)
66 local localdate = date("*t", ts)
67 localdate.isdst = false --[[ this is the trick ]]--
68 return difftime(time(localdate), time(utcdate))
68 local utcdate = date("!*t", ts)
69 local localdate = date("*t", ts)
70 localdate.isdst = false --[[ this is the trick ]]--
71 return difftime(time(localdate), time(utcdate))
69 72 end end
73 --[[ Mute luacheck warning of unusued function. ]]--
74 assert (get_timezone_offset ~= nil)
70 75
71 76 --[[-- --[[--
72 77 Maps given value to a short integer if possible. Maps given value to a short integer if possible.
 
... ... Otherwise returns `nil`.
77 82 @return nil or short integer @return nil or short integer
78 83 ]] ]]
79 84 local function sanitiseShort(supposedNumber) local function sanitiseShort(supposedNumber)
80 local sane = nil
85 local sane
81 86 if nil == supposedNumber then if nil == supposedNumber then
82 87 sane = nil sane = nil
83 88 elseif 'number' == type(supposedNumber) then elseif 'number' == type(supposedNumber) then
 
... ... Otherwise returns `nil`.
97 102 @return nil or integer @return nil or integer
98 103 ]] ]]
99 104 local function sanitiseInteger(supposedNumber) local function sanitiseInteger(supposedNumber)
100 local sane = nil
105 local sane
101 106 if nil == supposedNumber then if nil == supposedNumber then
102 107 sane = nil sane = nil
103 108 elseif 'number' == type(supposedNumber) then elseif 'number' == type(supposedNumber) then
 
... ... end
110 115
111 116 --[[-- --[[--
112 117 Maps given value to a valid timestamp with timezone if possible. Maps given value to a valid timestamp with timezone if possible.
113 Given a string, trim whitespace and truncate to hold exactly a
118 Given a string, trim whitespace and truncate to hold exactly a
114 119 timestamp with timezone offset and return it. timestamp with timezone offset and return it.
115 120 Otherwise returns `nil`. Otherwise returns `nil`.
116 Timestamp format:
117 `date('%Y-%m-%d %H:%M:%S', time()) .. get_tzoffset(get_timezone())`.
121 Timestamp format:
122 ```
123 date('%Y-%m-%d %H:%M:%S', time()) .. get_tzoffset(get_timezone())
124 ```
118 125 For example "2019-11-12 13:44:45+0200". For example "2019-11-12 13:44:45+0200".
119 126 Note that "%z" usage is omited, and a custom snippet is used, Note that "%z" usage is omited, and a custom snippet is used,
120 127 to ensure portability of the code. to ensure portability of the code.
 
... ... to ensure portability of the code.
123 130 @return nil or timestamp with timezone offset string @return nil or timestamp with timezone offset string
124 131 ]] ]]
125 132 local function sanitiseTimestamp(supposedTimestamp) local function sanitiseTimestamp(supposedTimestamp)
126 local sane = nil
133 local sane
127 134 if nil == supposedTimestamp then if nil == supposedTimestamp then
135 sane = nil
128 136 elseif 'string' == type(supposedTimestamp) then elseif 'string' == type(supposedTimestamp) then
129 137 sane = string.sub(strtrim(supposedTimestamp), 1, 24) sane = string.sub(strtrim(supposedTimestamp), 1, 24)
130 138 else else
 
... ... Otherwise returns `nil`.
143 151 @return short string or nil @return short string or nil
144 152 ]] ]]
145 153 local function sanitiseAnyName(supposedName) local function sanitiseAnyName(supposedName)
146 local sane = nil
154 local sane
147 155 if nil == supposedName then if nil == supposedName then
148 156 sane = nil sane = nil
149 157 elseif 'string' == type(supposedName) then elseif 'string' == type(supposedName) then
 
... ... local function validateAnyName(supposedName, lengthMin, lengthMax)
180 188 elseif lengthMax < 0 then elseif lengthMax < 0 then
181 189 lengthMax = 32 lengthMax = 32
182 190 elseif lengthMax > 256 then elseif lengthMax > 256 then
183 lengthMax = 256
191 lengthMax = 256
184 192 end end
185 193 assert (lengthMin <= lengthMax, 'Illegal argument.') assert (lengthMin <= lengthMax, 'Illegal argument.')
186 local isValid = true
194 local isValid = true
187 195 local errorMsg = nil local errorMsg = nil
188 196
189 197 isValid = supposedName ~= nil and isValid isValid = supposedName ~= nil and isValid
 
... ... end
210 218
211 219 --[[-- --[[--
212 220 Timestamp with timezone offset string checker, that is used in assertions. Timestamp with timezone offset string checker, that is used in assertions.
213 Timestamp format:
214 `date('%Y-%m-%d %H:%M:%S', time()) .. get_tzoffset(get_timezone())`.
221 Timestamp format:
222 ```
223 date('%Y-%m-%d %H:%M:%S', time()) .. get_tzoffset(get_timezone())
224 ```
215 225 For example "2019-11-12 13:44:45+0200". For example "2019-11-12 13:44:45+0200".
216 226 Note that "%z" usage is omited, and a custom snippet is used, Note that "%z" usage is omited, and a custom snippet is used,
217 227 to ensure portability of the code. to ensure portability of the code.
 
... ... to ensure portability of the code.
221 231 otherwise `false` and error description string otherwise `false` and error description string
222 232 ]] ]]
223 233 local function validateTimestamp(t) local function validateTimestamp(t)
224 local isValid = true
225 local errorMsg = nil
234 local isValid
235 local errorMsg
226 236
227 237 isValid, errorMsg = validateAnyName(t, 24, 24) isValid, errorMsg = validateAnyName(t, 24, 24)
228 238 if not isValid then if not isValid then
 
... ... local function validateTimestamp(t)
234 244 -- ex, 2019-11-05 14:28:30+0200 -- ex, 2019-11-05 14:28:30+0200
235 245 ]]-- ]]--
236 246 isValid = t == string.match(t, '%d%d%d%d--%d%d--%d%d %d%d:%d%d:%d%d++%d%d%d%d') and isValid isValid = t == string.match(t, '%d%d%d%d--%d%d--%d%d %d%d:%d%d:%d%d++%d%d%d%d') and isValid
237 if not isVallid then
247 if not isValid then
238 248 errorMsg = 'Is not a timestamp.' errorMsg = 'Is not a timestamp.'
239 249 return isValid, errorMsg return isValid, errorMsg
240 250 end end
 
... ... Create a table that is an event and is to be later registered or discarded.
373 383 @param harvestedItemQuantity a short integer that is produced item quantity @param harvestedItemQuantity a short integer that is produced item quantity
374 384 @return table indexed by number @return table indexed by number
375 385 ]] ]]
376 local function createEventHarvest(realmName, harvesterName, zoneName, subzoneName, harvestTimestamp, harvestTypeDesignation, sourceName, harvestedItemName, harvestedItemQuantity)
386 local function createEventHarvest(realmName, harvesterName, zoneName, subzoneName, harvestTimestamp,
387 harvestTypeDesignation, sourceName, harvestedItemName, harvestedItemQuantity)
377 388 local r = sanitiseAnyName(realmName) local r = sanitiseAnyName(realmName)
378 389 local c = sanitiseAnyName(harvesterName) local c = sanitiseAnyName(harvesterName)
379 390 local z = sanitiseAnyName(zoneName) local z = sanitiseAnyName(zoneName)
 
... ... Take given spell name and return according event type designation.
412 423 local function mapSpellNameToHarvestTypeDesignation(spellName) local function mapSpellNameToHarvestTypeDesignation(spellName)
413 424 local s = sanitiseAnyName(spellName) local s = sanitiseAnyName(spellName)
414 425 assert (validateAnyName(s)) assert (validateAnyName(s))
415 local t = nil
426 local t
416 427
417 428 if 'Herb Gathering' == s then if 'Herb Gathering' == s then
418 429 t = 'HERBALISM' t = 'HERBALISM'
 
... ... local function query(dao)
505 516 r = resultTable[k] r = resultTable[k]
506 517 if eventType == r[1] and itemName == r[2] then if eventType == r[1] and itemName == r[2] then
507 518 r[3] = r[3] + itemQuantity r[3] = r[3] + itemQuantity
508 break
519 break
509 520 else else
510 r = nil
521 r = nil
511 522 end end
512 523 end end
513 524 if nil == r and #resultTable < 16 then if nil == r and #resultTable < 16 then
 
... ... local function updateLootCache(lootCache)
571 582 n = 0 n = 0
572 583 end end
573 584 local i = 1 local i = 1
574 local j = math.min(math.max(0, math.floor(n)), 1024)
585 local j = math.min(math.max(0, math.floor(n)), 1024)
575 586 local itemInfo local itemInfo
576 587 while (i <= j) do while (i <= j) do
577 588 itemInfo = {GetLootSlotInfo(i)} itemInfo = {GetLootSlotInfo(i)}
 
... ... Employ WoW SavedVariables mechanism to persist given value.
656 667 local function persistEventHarvest(event) local function persistEventHarvest(event)
657 668 assert (event ~= nil) assert (event ~= nil)
658 669 assert ('table' == type(event)) assert ('table' == type(event))
659 local dao = FlowerpickerSavedVariables
670 local dao = FlowerpickerSavedVariables
660 671 assert (dao ~= nil) assert (dao ~= nil)
661 672 assert ('table' == type(dao)) assert ('table' == type(dao))
662 673 table.insert(dao, event) table.insert(dao, event)
 
... ... local function handleLootSlotCleared(lootCache, slotId, someSpellName, someCorps
809 820 assert (lootedItem ~= nil) assert (lootedItem ~= nil)
810 821 assert ('table' == type(lootedItem)) assert ('table' == type(lootedItem))
811 822
812 i = sanitiseAnyName(lootedItem[2])
823 local i = sanitiseAnyName(lootedItem[2])
813 824 assert (validateAnyName(i)) assert (validateAnyName(i))
814 q = sanitiseShort(lootedItem[3])
825 local q = sanitiseShort(lootedItem[3])
815 826 assert (validatePositiveAndNonZero(q)) assert (validatePositiveAndNonZero(q))
816 827
817 828 local d = mapSpellNameToHarvestTypeDesignation(sp) local d = mapSpellNameToHarvestTypeDesignation(sp)
818 829 assert (validateAnyName(d)) assert (validateAnyName(d))
819 830 assert (validateEnum(d, getPermissibleHarvestTypeSet())) assert (validateEnum(d, getPermissibleHarvestTypeSet()))
820 local s = sanitiseAnyName(someVictimName)
831 local s = sanitiseAnyName(someVictimName)
821 832 if nil == s or string.len(s) < 1 then if nil == s or string.len(s) < 1 then
822 833 s = GetSubZoneText() s = GetSubZoneText()
823 834 end end
 
... ... local function handleLootSlotCleared(lootCache, slotId, someSpellName, someCorps
829 840 assert (lootedItem ~= nil) assert (lootedItem ~= nil)
830 841 assert ('table' == type(lootedItem)) assert ('table' == type(lootedItem))
831 842
832 i = sanitiseAnyName(lootedItem[2])
843 local i = sanitiseAnyName(lootedItem[2])
833 844 assert (validateAnyName(i)) assert (validateAnyName(i))
834 q = sanitiseShort(lootedItem[3])
845 local q = sanitiseShort(lootedItem[3])
835 846 assert (validatePositiveAndNonZero(q)) assert (validatePositiveAndNonZero(q))
836 847
837 848 registerLootGainFromCorpse(i, q, cr) registerLootGainFromCorpse(i, q, cr)
 
... ... any reason.
859 870 @param merchantName conditional localised name of non-player merchant traded @param merchantName conditional localised name of non-player merchant traded
860 871 @return void @return void
861 872 ]] ]]
862 local function handlePlayerMoney(playerMoneyBefore, playerMoneyAfter, playerMoneyDiff, corpseName, gossiperName, merchantName)
863 local isMoneyGained = playerMoneyAfter > playerMoneyBefore and playerMoneyDiff > 0
864 local isMoneyLost = playerMoneyBefore > playerMoneyAfter and playerMoneyDiff < 0
865
873 local function handlePlayerMoney(playerMoneyBefore, playerMoneyAfter, playerMoneyDiff,
874 corpseName, gossiperName, merchantName)
875 local isMoneyGained = playerMoneyAfter > playerMoneyBefore and playerMoneyDiff > 0
876 local isMoneyLost = playerMoneyBefore > playerMoneyAfter and playerMoneyDiff < 0
877
866 878 if gossiperName ~= nil then if gossiperName ~= nil then
867 879 print('Gossip with ' .. gossiperName .. 'resulted in a money operation.') print('Gossip with ' .. gossiperName .. 'resulted in a money operation.')
868 880 elseif merchantName ~= nil then elseif merchantName ~= nil then
 
... ... The user may employ function objects made available publicly via the
895 907 @param event string that designates WoW event type that is received @param event string that designates WoW event type that is received
896 908 @return void @return void
897 909 ]] ]]
898 local function main(self, event, arg1, arg2, arg3, arg4, arg5)
910 local function main(self, event, arg1, arg2, arg3, arg4)
899 911 assert (self ~= nil) assert (self ~= nil)
900 912 assert ('table' == type(self)) assert ('table' == type(self))
901 913 assert (self.api ~= nil) assert (self.api ~= nil)
 
... ... local function main(self, event, arg1, arg2, arg3, arg4, arg5)
916 928 self.swap.lastSpellCastName = spellName self.swap.lastSpellCastName = spellName
917 929 end end
918 930 elseif 'UNIT_SPELLCAST_SENT' == event then elseif 'UNIT_SPELLCAST_SENT' == event then
931 assert (arg3 ~= nil)
919 932 self.swap.lastSpellTargetName = sanitiseAnyName(arg4) self.swap.lastSpellTargetName = sanitiseAnyName(arg4)
920 933 elseif 'LOOT_OPENED' == event then elseif 'LOOT_OPENED' == event then
921 934 updateLootCache(FlowerpickerLootCache) updateLootCache(FlowerpickerLootCache)
 
... ... local function main(self, event, arg1, arg2, arg3, arg4, arg5)
933 946 local lastSpellCastName = sanitiseAnyName(self.swap.lastSpellCastName) local lastSpellCastName = sanitiseAnyName(self.swap.lastSpellCastName)
934 947 local corpseName = sanitiseAnyName(self.swap.lastLootedCorpseName) local corpseName = sanitiseAnyName(self.swap.lastLootedCorpseName)
935 948 local nodeName = sanitiseAnyName(self.swap.lastSpellTargetName) local nodeName = sanitiseAnyName(self.swap.lastSpellTargetName)
936 self.swap.lootSlotId = slotId
949 self.swap.lootSlotId = slotId
937 950 handleLootSlotCleared(lootCache, slotId, lastSpellCastName, corpseName, nodeName) handleLootSlotCleared(lootCache, slotId, lastSpellCastName, corpseName, nodeName)
938 951 elseif 'LOOT_CLOSED' == event then elseif 'LOOT_CLOSED' == event then
939 952 clearLootCache(FlowerpickerLootCache) clearLootCache(FlowerpickerLootCache)
 
... ... local function main(self, event, arg1, arg2, arg3, arg4, arg5)
973 986
974 987 handlePlayerMoney(playerMoneyBefore, playerMoneyAfter, playerMoneyDiff, corpseName, gossiperName, merchantName) handlePlayerMoney(playerMoneyBefore, playerMoneyAfter, playerMoneyDiff, corpseName, gossiperName, merchantName)
975 988 else else
976 error('Unknown event encountered and ignored "' .. event .. '".')
989 local lootCache = FlowerpickerLootCache
990 error('Unknown event encountered and ignored "' .. event .. '".'
991 .. 'Loot cache: ' .. describeLootCache(lootCache))
977 992 end end
978 993 end end
979 994
 
... ... graphical user interface that is a report.
986 1001 @return void @return void
987 1002 ]] ]]
988 1003 local function reportRefresh() local function reportRefresh()
989 --[[ Lookup global table instead of reference frame table.
1004 --[[ Lookup global table instead of reference frame table.
990 1005 -- Frame table can be changed by the user easily. -- Frame table can be changed by the user easily.
991 1006 -- Declared global cannot be nullified by the user maybe??]]-- -- Declared global cannot be nullified by the user maybe??]]--
992 1007 local reportEntryTableSize = 16 local reportEntryTableSize = 16
993 local i = 0
1008 local i = 0
994 1009 local e local e
995 1010 local et local et
996 1011 local dao = FlowerpickerSavedVariables local dao = FlowerpickerSavedVariables
 
... ... local function initGUI(addonFrame)
1031 1046 local reportFrame = CreateFrame('FRAME', 'FlowerpickerReportFrame', addonFrame) local reportFrame = CreateFrame('FRAME', 'FlowerpickerReportFrame', addonFrame)
1032 1047 reportFrame:SetPoint('CENTER', UIParent, 'CENTER', 0, 0) reportFrame:SetPoint('CENTER', UIParent, 'CENTER', 0, 0)
1033 1048 reportFrame:SetSize(768, 512) reportFrame:SetSize(768, 512)
1034 reportFrame:SetBackdrop({bgFile = "Interface/Tooltips/UI-Tooltip-Background",
1035 edgeFile = "Interface/Tooltips/UI-Tooltip-Border",
1036 tile = true, tileSize = 16, edgeSize = 16,
1049 reportFrame:SetBackdrop({bgFile = "Interface/Tooltips/UI-Tooltip-Background",
1050 edgeFile = "Interface/Tooltips/UI-Tooltip-Border",
1051 tile = true, tileSize = 16, edgeSize = 16,
1037 1052 insets = { left = 4, right = 4, top = 4, bottom = 4 }}); insets = { left = 4, right = 4, top = 4, bottom = 4 }});
1038 1053 reportFrame:SetBackdropColor(0, 0, 0, 1); reportFrame:SetBackdropColor(0, 0, 0, 1);
1039 1054
 
... ... local function initGUI(addonFrame)
1041 1056 minimiseBtn:SetPoint('TOPRIGHT', reportFrame, 'TOPRIGHT', 0, 0) minimiseBtn:SetPoint('TOPRIGHT', reportFrame, 'TOPRIGHT', 0, 0)
1042 1057 minimiseBtn:SetSize(256, 32) minimiseBtn:SetSize(256, 32)
1043 1058 minimiseBtn:SetText('Toggle Flowerpicker') minimiseBtn:SetText('Toggle Flowerpicker')
1044 minimiseBtn:SetScript('OnClick', function(self, ...)
1045 local f = FlowerpickerReportFrame
1059 minimiseBtn:SetScript('OnClick', function()
1060 local f = FlowerpickerReportFrame
1046 1061 assert (f ~= nil) assert (f ~= nil)
1047 1062 assert ('table' == type(f)) assert ('table' == type(f))
1048 1063 if (1 == f:IsShown()) then if (1 == f:IsShown()) then
 
... ... local function initGUI(addonFrame)
1068 1083
1069 1084 reportFrame.entryTable = {} reportFrame.entryTable = {}
1070 1085 local maxEntryQuantityPerPage = 16 local maxEntryQuantityPerPage = 16
1086 local offseth
1087 local en
1071 1088 local ew = 512 local ew = 512
1072 1089 local eh = 32 local eh = 32
1073 1090 local i = 0 local i = 0
 
... ... local function initGUI(addonFrame)
1077 1094 offseth = -eh*i offseth = -eh*i
1078 1095 i = i + 1 i = i + 1
1079 1096 en = string.format('FlowerpickerEntry%02d', i) en = string.format('FlowerpickerEntry%02d', i)
1080 e = CreateFrame('FRAME', en, reportFrame)
1097 e = CreateFrame('FRAME', en, reportFrame)
1081 1098 e:SetSize(ew, eh) e:SetSize(ew, eh)
1082 1099 e:SetPoint('TOPLEFT', reportFrame, 'TOPLEFT', 0, offseth) e:SetPoint('TOPLEFT', reportFrame, 'TOPLEFT', 0, offseth)
1083 e:SetBackdrop({bgFile = "Interface/Tooltips/UI-Tooltip-Background",
1084 edgeFile = "Interface/Tooltips/UI-Tooltip-Border",
1085 tile = true, tileSize = 16, edgeSize = 16,
1100 e:SetBackdrop({bgFile = "Interface/Tooltips/UI-Tooltip-Background",
1101 edgeFile = "Interface/Tooltips/UI-Tooltip-Border",
1102 tile = true, tileSize = 16, edgeSize = 16,
1086 1103 insets = { left = 4, right = 4, top = 4, bottom = 4 }}); insets = { left = 4, right = 4, top = 4, bottom = 4 }});
1087 1104 e:SetBackdropColor(0, 0, 0, 1); e:SetBackdropColor(0, 0, 0, 1);
1088 1105
 
... ... local function init()
1155 1172 } }
1156 1173 addonFrame.swap = swap addonFrame.swap = swap
1157 1174
1158 MerchantFrame:HookScript('OnShow', function(...)
1175 MerchantFrame:HookScript('OnShow', function()
1159 1176 local f = FlowerpickerAddOnFrame local f = FlowerpickerAddOnFrame
1160 1177 assert (f ~= nil) assert (f ~= nil)
1161 1178 f.swap.isShopping = true f.swap.isShopping = true
 
... ... local function init()
1164 1181 end end
1165 1182 end) end)
1166 1183
1167 MerchantFrame:HookScript('OnHide', function(...)
1184 MerchantFrame:HookScript('OnHide', function()
1168 1185 local f = FlowerpickerAddOnFrame local f = FlowerpickerAddOnFrame
1169 1186 assert (f ~= nil) assert (f ~= nil)
1170 1187 f.swap.isShopping = false f.swap.isShopping = false
1171 1188 end) end)
1172
1189
1173 1190 initGUI(addonFrame) initGUI(addonFrame)
1174 1191 reportRefresh() reportRefresh()
1175 1192 end end
File README.md changed (mode: 100644) (index c5d0aed..a336ff5)
1 1 # Flowerpicker add-on # Flowerpicker add-on
2 Flowerpicker is an add-on under development for legacy World of Warcraft game client.
2 Flowerpicker is an unfinished add-on for legacy World of Warcraft
3 game client. The purpose of the add-on is to register all item
4 aquisition instances by the player during the game. For example,
5 note and remember every fishing, corpse looting and flower picking
6 activity the player conducted. Then, this data is aggregated
7 and displayed in a player-friendly format.
8
9 ## Development
10 The expected path to take to contribute to the development of the add-on
11 is as follows.
12 1. Obtain a copy of the code via Git repository or a distributed archive.
13 2. Install required tools: Java runtime, Gradle, Lua 5.1, LDoc, LuaCheck.
14 3. Introduce changes guided by Git workflow.
15 4. To build, that is check and package, run the following command from
16 the project directory.
17 ```
18 gradle clean build
19 ```
20
21 The generated documentation is placed under ${projectDir}/doc/ directory
22 and distributed archive in ${projectDir}/build/distributions/ directory.
23
3 24 ## TODO ## TODO
4 - [ ] Add 'nothing' option to 'LOOTCORPSE' event type, so that it is possible
5 to count how many enemies of a certain type was slain to obtain that
6 number of items.
25 - [ ] Add 'nothing' option to 'LOOTCORPSE' event type, so that
26 it is possible to count how many enemies of a certain type was
27 slain to obtain that number of items.
7 28 - [ ] Register exact location cooridnates of event occurrence. - [ ] Register exact location cooridnates of event occurrence.
File build.gradle changed (mode: 100644) (index 17a2487..9aeed48)
... ... tasks.create('ldoc', Exec) {
10 10 args "--dir=${projectDir}/doc/", "${projectDir}/" args "--dir=${projectDir}/doc/", "${projectDir}/"
11 11 } }
12 12
13 tasks.create('luacheck', Exec) {
14 executable 'luacheck'
15 args '--config .luacheckrc', 'Flowerpicker.lua'
16 }
17
13 18 tasks.create('distZip', Zip) { tasks.create('distZip', Zip) {
14 19 from("$projectDir") { from("$projectDir") {
20 include '.luacheckrc'
15 21 include 'DejaVuSansMono.ttf' include 'DejaVuSansMono.ttf'
16 22 include 'Flowerpicker.lua' include 'Flowerpicker.lua'
17 23 include 'README.md' include 'README.md'
 
... ... tasks.create('distZip', Zip) {
23 29 } }
24 30
25 31 distZip.dependsOn(ldoc) distZip.dependsOn(ldoc)
32 check.dependsOn(luacheck)
26 33 assemble.dependsOn(distZip) assemble.dependsOn(distZip)
Hints:
Before first commit, do not forget to setup your git environment:
git config --global user.name "your_name_here"
git config --global user.email "your@email_here"

Clone this repository using HTTP(S):
git clone https://rocketgit.com/user/vrtc/flowerpicker

Clone this repository using ssh (do not forget to upload a key first):
git clone ssh://rocketgit@ssh.rocketgit.com/user/vrtc/flowerpicker

Clone this repository using git:
git clone git://git.rocketgit.com/user/vrtc/flowerpicker

You are allowed to anonymously push to this repository.
This means that your pushed commits will automatically be transformed into a merge request:
... clone the repository ...
... make some changes and some commits ...
git push origin main