-
Notifications
You must be signed in to change notification settings - Fork 1
/
todbot.lua
168 lines (147 loc) · 5.95 KB
/
todbot.lua
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
require('common')
local settings = require('settings')
local chat = require('chat')
local nm_list = require('nm_list')
local gui = require("gui")
require("discord")
addon.name = 'todbot'
addon.author = 'gnubeardo'
addon.version = '1.4'
addon.desc = 'posts TOD of NMs to a Discord webhook'
addon.link = 'https://github.com/ErikDahlinghaus/todbot'
local default_settings = T{
webhookURL = "",
avatarURL = "",
debug = false
}
local todbot = T{
settings = settings.load(default_settings),
recent_monsters = T{}
}
settings.register('settings', 'settings_update', function (s)
if (s ~= nil) then
todbot.settings = s
end
settings.save()
end)
register_gui(todbot)
--[[
Ripped from https://github.com/AshitaXI/Ashita-v4beta/blob/main/addons/petinfo/petinfo.lua#L37-L51
per Thorny in discord when I asked why the range is 0, 2303:
"entities are stored in a data structure 0x900 wide,
so it is the range of indices in that data structure"
This allows us to get the Entity for what we killed
based on the mobID from the animation packet so we
can call entity.Name on it
]]
local function GetEntityByServerId(sid)
for x = 0, 2303 do
local ent = GetEntity(x)
if (ent ~= nil and ent.ServerId == sid) then
return ent
end
end
return nil
end
--[[
with a list that looks like
T{
{mobid = 123445, mobname = "name"}
}
should return the record if the name matches
otherwise return false
]]
local function detectMobInListByName(name, list)
for i, mob in ipairs(list) do
if mob.mobname == name then
return mob
end
end
return false
end
ashita.events.register('packet_in', 'death_animation', function (e)
--[[
TODO: This packet fires for entity animations, including mob despawning.
Unfortunately this means it also fires at morning when all the night mobs disappear.
Need to figure out how to fix that, I don't really want to just stop triggering
during night time. Maybe if I made a list of all the mobs that disappear on morning
and then correlate that with the time of day might be safe.
For now I'm leaving this bug.
https://github.com/Windower/Lua/blob/dev/addons/libs/packets/fields.lua#L2201-L2210
]]
local entity_animation_packet_id = 0x038
if (e.id == entity_animation_packet_id) then
local timestamp = os.time()
local animation = struct.unpack('c4', e.data_modified, 0x0C + 0x01) -- kesu
local mobIndex = struct.unpack('H', e.data_modified, 0x18 + 0x01)
local mobID = struct.unpack('I', e.data_modified, 0x04 + 0x01)
--[[
This animation name is usually either "deru" which means "spawning" and
"kesu" which means despawning. Although the packet is also used for other things.
We can safely ignore packets where animation ~= "kesu", however this does
not filter out all packets we don't want. Some other animations have
"kesu" in the animation field and are not monster despawn packets
]]
if( animation ~= "kesu" ) then
return
end
--[[
I'm not really certain what this number is, but when mobs despawn its
always 0. I was getting 17 in towns sometimes, have no idea what that is for.
]]
if( mobIndex ~= 0 ) then
return
end
if( mobID <= 0 ) then
return
end
local entity = GetEntityByServerId(mobID)
local name = string.format("MobID `%d`", mobID)
if( entity ~= nil ) then
name = entity.Name
end
--[[
Debug output
]]
if todbot.settings.debug then
local timestamp_format = "%Y-%m-%d %H:%M:%S %Z"
local timestamp_string = os.date(timestamp_format, timestamp)
local print_message = string.format("%s: %s", name, timestamp_string)
print(chat.header('todbot') .. chat.message(print_message));
local message = string.format("%s: <t:%d:T> <t:%d:R> ", name, timestamp, timestamp)
print(chat.header('todbot') .. chat.message(message));
table.insert(todbot.recent_monsters, {name = name, timestamp = timestamp})
end
--[[
I have a list of NMs in nm_list.lua but I would also like for
users to be able to configure their own lists.
]]
if( detectMobInListByName(name, nm_list) == false ) then
return
end
-- gui.lua uses todbot.recent_monsters to create a UI element
table.insert(todbot.recent_monsters, {name = name, timestamp = timestamp})
end
end)
ashita.events.register('unload', 'unload_cb', function()
settings.save()
end)
ashita.events.register('command', 'command_cb', function(e)
local command_args = e.command:lower():args()
if table.contains({'/todbot'}, command_args[1]) then
if table.contains({'config'}, command_args[2]) then
gui.is_open[1] = not gui.is_open[1]
elseif table.contains({'debug'}, command_args[2]) then
todbot.settings.debug = not todbot.settings.debug
print(chat.header('todbot') .. chat.message("Debug: " .. tostring(todbot.settings.debug)))
elseif table.contains({'insert'}, command_args[2]) then
local fake = command_args[3] or "Fake"
table.insert(todbot.recent_monsters, {name = fake, timestamp = os.time()})
else
print(chat.header('todbot') .. chat.message(todbot.settings.webhookURL))
print(chat.header('todbot') .. chat.message(todbot.settings.avatarURL))
print(chat.header('todbot') .. chat.message("Debug: " .. tostring(todbot.settings.debug)))
end
end
return false
end)