Compare commits
300 Commits
Author | SHA1 | Date | |
---|---|---|---|
7eee3a13a6 | |||
263cf8e2e4 | |||
ccbf0f8dc2 | |||
63027c2dcf | |||
d46c874604 | |||
fd4f707b6c | |||
1168876dcc | |||
bdf5afe436 | |||
85ff907f05 | |||
7ae9db030b | |||
edf8a12865 | |||
d081eedd47 | |||
8532db5a25 | |||
26e783ee2e | |||
4bd237abef | |||
0ab14de0e2 | |||
a25b6a20d5 | |||
e85c14ea45 | |||
a564178ca2 | |||
b4a4011b18 | |||
3f3d252104 | |||
287be2a31c | |||
3ef0e4c935 | |||
ce92e8e12c | |||
03597d1b5e | |||
36ad9783e5 | |||
565db30125 | |||
017cbf01f8 | |||
b16cf762ac | |||
0057ac3a5c | |||
0edf0561d8 | |||
1129d787b5 | |||
8a24496801 | |||
6cb918c13c | |||
e3eefadb75 | |||
eab562b36d | |||
20a7c0eead | |||
f70c5adfcf | |||
52246e2e16 | |||
4897a5b1a9 | |||
2381f68912 | |||
ad969e8604 | |||
31678f9a82 | |||
1785af4d9d | |||
69d7efe6f0 | |||
202c5d0f46 | |||
476e907205 | |||
724194abe2 | |||
d57b573683 | |||
5d8afe8db7 | |||
b14f1ff2f9 | |||
a1301abdb2 | |||
f897183920 | |||
c1885ce76a | |||
e676d53e97 | |||
f05156b257 | |||
c8f9d81b3e | |||
3a1639ab27 | |||
1da1e7bf9f | |||
304fbcbaae | |||
80f8500f6e | |||
78cbcbde9d | |||
![]() |
8db1cb179c | ||
a065e47545 | |||
5271029b84 | |||
7c4fb53baa | |||
1c2fb471a6 | |||
85f72b14e0 | |||
99261beb08 | |||
d34be4f18d | |||
3d26832e54 | |||
cd80c9fc0e | |||
672ca07782 | |||
b06313c4eb | |||
31be9b0ce8 | |||
d69a53b4c8 | |||
7aa5d50a6c | |||
d047c632ed | |||
9eb5c04a33 | |||
498432d968 | |||
e04eb57202 | |||
25fe8350a7 | |||
9a10386e65 | |||
75ab8646e8 | |||
37ef42e53d | |||
b2aa1b75f3 | |||
31bcd3481c | |||
966078c339 | |||
fdcd816235 | |||
054d8ab7ef | |||
0327359300 | |||
c61a4b0c04 | |||
950f95cef1 | |||
d40670fef6 | |||
d6e5e7941f | |||
a06e9027c6 | |||
8fb0595ef8 | |||
d3808a887e | |||
1ed379c23d | |||
0e66db1d8a | |||
bac16d22a9 | |||
8b4de82142 | |||
35930c52a4 | |||
293e71e619 | |||
7150189a0d | |||
0e951d7089 | |||
ef89c3001b | |||
b538c7b5de | |||
6c234e7fa4 | |||
407d8f2da2 | |||
9b755cd0be | |||
19f9d4bda9 | |||
de744337ad | |||
63ba6d2da1 | |||
79b77ee6c3 | |||
0e2935f844 | |||
0ad6a23daa | |||
35398ebf38 | |||
62b028cf56 | |||
ad676915bb | |||
61ebb22a85 | |||
8348b93b30 | |||
550e11b488 | |||
ed10ea496d | |||
6e5c7510d0 | |||
68d0393915 | |||
f1e07f0a3b | |||
90100f6f5b | |||
995966e952 | |||
a90eb8248f | |||
ffca28c67d | |||
20a2a95ce6 | |||
145fd02ba8 | |||
196a5a8cfa | |||
439e9b29d1 | |||
a3f1a0e96d | |||
c81e349e90 | |||
30068a5b11 | |||
036b6b23a8 | |||
128eb44003 | |||
0f72b2048e | |||
1e4045ab7a | |||
b871549087 | |||
58760831dc | |||
0a8ab00637 | |||
8396801d80 | |||
19af9894e5 | |||
7293f5a8fa | |||
9d12609147 | |||
2c7089504f | |||
8fbff23bee | |||
0c5078e3f3 | |||
d143a18838 | |||
ba889e442c | |||
4511ecbf0a | |||
fe37bebd2c | |||
d987436892 | |||
9f4e19104f | |||
c0568075e1 | |||
13415fb065 | |||
ca13d1e364 | |||
bf916dd8d5 | |||
4aa168ebcc | |||
2cea01f367 | |||
2ec0aea19c | |||
846584d6fe | |||
1b5912a1bf | |||
954dbfa425 | |||
42ec90a5df | |||
0b4350c8ae | |||
da28805882 | |||
6551e24069 | |||
28ef8cb33a | |||
d4b0dee037 | |||
799d3e1ddd | |||
e6f3bac946 | |||
05c7e71794 | |||
41b980d118 | |||
3efd99cdc8 | |||
119eb7965b | |||
f4421f0334 | |||
688f2f4b30 | |||
87300bf48a | |||
8cbad47acc | |||
241615238c | |||
319e6cdd77 | |||
d54e93ad85 | |||
efe0002e02 | |||
e58d92c399 | |||
fa18138c3b | |||
2a5d6e5157 | |||
c32549fa87 | |||
2689e39d70 | |||
25f2310c25 | |||
0bed5ecf41 | |||
ec2f146095 | |||
75a84baa42 | |||
1bc7ebc92a | |||
d620f577c1 | |||
7af1b40222 | |||
82f1539815 | |||
e38ba012a8 | |||
a0322718c1 | |||
01ca12f80e | |||
3376b4fa7c | |||
308b65e2f6 | |||
fa5b73b5fe | |||
0fd088320d | |||
a109c631cd | |||
cf61a74fa8 | |||
8fa4effb6b | |||
5ca69bbe24 | |||
8816468ba0 | |||
e9f17c585c | |||
373ca377a2 | |||
770420a5b2 | |||
22b1b6bc73 | |||
18fd4bb9d2 | |||
ca333a93e3 | |||
4c404225d2 | |||
9f86a4e0f9 | |||
6273263c4e | |||
0b6b8df1a9 | |||
fe730a19df | |||
636ef87cb1 | |||
d333901576 | |||
d104bcc1fa | |||
dbfbc2c347 | |||
dd620c14d3 | |||
744098abc7 | |||
d41554271d | |||
23bfbf9f4a | |||
f52ed8c791 | |||
604371a2e1 | |||
44cec2d2fb | |||
cbe9ef7303 | |||
002970484d | |||
f063ceb4e5 | |||
1eaefffe04 | |||
1291d21216 | |||
1c198f0133 | |||
23bf656f82 | |||
30fae67f6c | |||
2726955034 | |||
e433bc3319 | |||
71df812170 | |||
abb8540c12 | |||
12e0c23ea9 | |||
b98ecdd0a4 | |||
7314c67357 | |||
6b74e01f0a | |||
6becc08e18 | |||
f66a990103 | |||
c3b9772512 | |||
6bb1cc683c | |||
b5473e05e7 | |||
939ca47e3c | |||
c16e5f1e47 | |||
059f917acc | |||
43b08f22dd | |||
aa7e4a3d3e | |||
18f2b44941 | |||
b2925285a2 | |||
c0a6a3c082 | |||
7c7edcf959 | |||
dee5053345 | |||
58e071e77b | |||
a7e85acd67 | |||
176d184d91 | |||
32543d04a0 | |||
4b43ee86c0 | |||
25959be98f | |||
cb6680304f | |||
40646f16bc | |||
55e7ee2428 | |||
a2930577d3 | |||
e572f50de7 | |||
47b7f5d85a | |||
8ac29e4378 | |||
be81a31302 | |||
2e44a1ef31 | |||
d182cc1418 | |||
d3004019c6 | |||
fca49c6302 | |||
8b085009a9 | |||
2ba6d190f0 | |||
8c5a94a12a | |||
bf9e1f0319 | |||
903baf7f38 | |||
5b585ebba7 | |||
34bae5dc7b | |||
4f97859533 | |||
4c55e65863 | |||
016f0be480 | |||
fbf35d6d77 | |||
30ee1c717e | |||
e3286571b1 | |||
ece39790d2 | |||
eedadb0a3f | |||
00f7cba8fc |
2
.gitattributes
vendored
2
.gitattributes
vendored
@@ -1 +1,3 @@
|
|||||||
*.zip filter=lfs diff=lfs merge=lfs -text
|
*.zip filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.tga filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.ogg filter=lfs diff=lfs merge=lfs -text
|
||||||
|
2
.gitignore
vendored
2
.gitignore
vendored
@@ -1 +1 @@
|
|||||||
Meta
|
scratch.lua
|
||||||
|
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
[submodule "Meta"]
|
||||||
|
path = Meta
|
||||||
|
url = https://git.site.quack-lab.dev/dave/wow_Meta
|
5
.luacheckrc
Symbolic link
5
.luacheckrc
Symbolic link
@@ -0,0 +1,5 @@
|
|||||||
|
globals = { "CykaPersistentData", "CreateFrame", "GetItemInfo", "aura_env" }
|
||||||
|
unused_args = false
|
||||||
|
max_line_length = 500
|
||||||
|
exclude_files = { "Meta/" }
|
||||||
|
global = false
|
14
.luarc.json
Symbolic link
14
.luarc.json
Symbolic link
@@ -0,0 +1,14 @@
|
|||||||
|
{
|
||||||
|
"workspace": {
|
||||||
|
"library": [
|
||||||
|
"./Meta"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"diagnostics.disable": [
|
||||||
|
"unused-local",
|
||||||
|
"unused-vararg"
|
||||||
|
],
|
||||||
|
"diagnostics.globals": [
|
||||||
|
"aura_env"
|
||||||
|
]
|
||||||
|
}
|
5
.vscode/settings.json
vendored
5
.vscode/settings.json
vendored
@@ -1,5 +0,0 @@
|
|||||||
{
|
|
||||||
"Lua.diagnostics.globals": [
|
|
||||||
"UIParent"
|
|
||||||
]
|
|
||||||
}
|
|
527
Heimdall.lua
527
Heimdall.lua
@@ -2,15 +2,12 @@ local addonname, shared = ...
|
|||||||
---@cast shared HeimdallShared
|
---@cast shared HeimdallShared
|
||||||
---@cast addonname string
|
---@cast addonname string
|
||||||
|
|
||||||
-- TODO: Implement counting kills and display on whosniffer
|
local VERSION = "3.12.0"
|
||||||
-- Take last N seconds of combatlog into account ie. count who does damage to who
|
shared.VERSION = VERSION
|
||||||
-- Maybe even make an alert when someone does too much damage to someone else...
|
|
||||||
-- But that would not be trivial as of now, I can't think of a way to do it sensibly
|
|
||||||
|
|
||||||
local function init()
|
local function init()
|
||||||
---@class Heimdall_Data
|
---@class Heimdall_Data
|
||||||
---@field config HeimdallConfig
|
---@field config HeimdallConfig
|
||||||
---@field stinkies table<string, boolean>
|
|
||||||
if not Heimdall_Data then Heimdall_Data = {} end
|
if not Heimdall_Data then Heimdall_Data = {} end
|
||||||
|
|
||||||
---@class InitTable
|
---@class InitTable
|
||||||
@@ -21,26 +18,49 @@ local function init()
|
|||||||
---@field classColors table<string, string>
|
---@field classColors table<string, string>
|
||||||
---@field messenger HeimdallMessengerData
|
---@field messenger HeimdallMessengerData
|
||||||
---@field who HeimdallWhoData
|
---@field who HeimdallWhoData
|
||||||
---@field stinkyTracker HeimdallStinkyTrackerData
|
---@field stinkyTracker StinkyTrackerData
|
||||||
---@field dumpTable fun(table: any, depth?: number): nil
|
---@field agentTracker AgentTrackerData
|
||||||
|
---@field networkNodes string[]
|
||||||
|
---@field network HeimdallNetworkData
|
||||||
|
---@field networkMessenger HeimdallNetworkMessengerData
|
||||||
|
---@field stinkyCache HeimdallStinkyCacheData
|
||||||
|
---@field _L fun(key: string, locale: string): string
|
||||||
|
---@field _Locale Localization
|
||||||
|
---@field VERSION string
|
||||||
|
---@field dump fun(table: any, msg?: string, depth?: number): nil
|
||||||
---@field utf8len fun(input: string): number
|
---@field utf8len fun(input: string): number
|
||||||
---@field padString fun(input: string, targetLength: number, left?: boolean): string
|
---@field padString fun(input: string, targetLength: number, left?: boolean): string
|
||||||
---@field GetOrDefault fun(table: table<any, any>, keys: string[], default: any): any
|
---@field GetOrDefault fun(table: table<any, any>, keys: string[], default: any): any
|
||||||
---@field Whoer InitTable
|
---@field Split fun(input: string, deliminer: string): string[]
|
||||||
---@field Messenger InitTable
|
---@field IsStinky fun(name: string): boolean
|
||||||
---@field Spotter InitTable
|
---@field Memoize fun(f: function): function
|
||||||
---@field DeathReporter InitTable
|
---@field GetLocaleForChannel fun(channel: string): string
|
||||||
---@field Inviter InitTable
|
---@field WhoQueryService WhoQueryService
|
||||||
---@field Dueler InitTable
|
---@field AchievementSniffer AchievementSniffer
|
||||||
---@field Bully InitTable
|
---@field AgentTracker AgentTracker
|
||||||
---@field AgentTracker InitTable
|
---@field BonkDetector BonkDetector
|
||||||
---@field Emoter InitTable
|
---@field Bully Bully
|
||||||
---@field Echoer InitTable
|
---@field CombatAlerter CombatAlerter
|
||||||
---@field Macroer InitTable
|
---@field Commander Commander
|
||||||
---@field Commander InitTable
|
---@field Config Config
|
||||||
---@field StinkyTracker InitTable
|
---@field Configurator Configurator
|
||||||
---@field CombatAlerter InitTable
|
---@field DeathReporter DeathReporter
|
||||||
---@field Config InitTable
|
---@field Dueler Dueler
|
||||||
|
---@field Echoer Echoer
|
||||||
|
---@field Emoter Emoter
|
||||||
|
---@field Inviter Inviter
|
||||||
|
---@field Macroer Macroer
|
||||||
|
---@field Messenger Messenger
|
||||||
|
---@field MinimapTagger MinimapTagger
|
||||||
|
---@field Network Network
|
||||||
|
---@field NetworkMessenger NetworkMessenger
|
||||||
|
---@field Noter Noter
|
||||||
|
---@field Sniffer Sniffer
|
||||||
|
---@field Spotter Spotter
|
||||||
|
---@field StinkyCache StinkyCache
|
||||||
|
---@field StinkyTracker StinkyTracker
|
||||||
|
---@field Whoer Whoer
|
||||||
|
---@field ChatSniffer ChatSniffer
|
||||||
|
|
||||||
--- Config ---
|
--- Config ---
|
||||||
---@class HeimdallConfig
|
---@class HeimdallConfig
|
||||||
@@ -50,7 +70,6 @@ local function init()
|
|||||||
---@field deathReporter HeimdallDeathReporterConfig
|
---@field deathReporter HeimdallDeathReporterConfig
|
||||||
---@field inviter HeimdallInviterConfig
|
---@field inviter HeimdallInviterConfig
|
||||||
---@field dueler HeimdallDuelerConfig
|
---@field dueler HeimdallDuelerConfig
|
||||||
---@field bully HeimdallBullyConfig
|
|
||||||
---@field agentTracker HeimdallAgentTrackerConfig
|
---@field agentTracker HeimdallAgentTrackerConfig
|
||||||
---@field emoter HeimdallEmoterConfig
|
---@field emoter HeimdallEmoterConfig
|
||||||
---@field echoer HeimdallEchoerConfig
|
---@field echoer HeimdallEchoerConfig
|
||||||
@@ -58,102 +77,23 @@ local function init()
|
|||||||
---@field commander HeimdallCommanderConfig
|
---@field commander HeimdallCommanderConfig
|
||||||
---@field stinkyTracker HeimdallStinkyTrackerConfig
|
---@field stinkyTracker HeimdallStinkyTrackerConfig
|
||||||
---@field combatAlerter HeimdallCombatAlerterConfig
|
---@field combatAlerter HeimdallCombatAlerterConfig
|
||||||
|
---@field sniffer HeimdallSnifferConfig
|
||||||
|
---@field noter HeimdallNoterConfig
|
||||||
|
---@field network HeimdallNetworkConfig
|
||||||
|
---@field networkMessenger HeimdallNetworkMessengerConfig
|
||||||
|
---@field configurator HeimdallConfiguratorConfig
|
||||||
|
---@field stinkyCache HeimdallStinkyCacheConfig
|
||||||
|
---@field achievementSniffer HeimdallAchievementSnifferConfig
|
||||||
|
---@field chatSniffer HeimdallChatSnifferConfig
|
||||||
---@field whisperNotify table<string, string>
|
---@field whisperNotify table<string, string>
|
||||||
|
---@field addonPrefix string
|
||||||
---@field stinkies table<string, boolean>
|
---@field stinkies table<string, boolean>
|
||||||
---@field agents table<string, string>
|
---@field agents table<string, string>
|
||||||
|
---@field scale number
|
||||||
---@class HeimdallSpotterConfig
|
---@field notes table<string, Note[]>
|
||||||
---@field enabled boolean
|
---@field channelLocale table<string, string>
|
||||||
---@field everyone boolean
|
---@field locale string
|
||||||
---@field hostile boolean
|
---@field debug boolean
|
||||||
---@field alliance boolean
|
|
||||||
---@field stinky boolean
|
|
||||||
---@field notifyChannel string
|
|
||||||
---@field zoneOverride string?
|
|
||||||
---@field throttleTime number
|
|
||||||
|
|
||||||
---@class HeimdallWhoConfig
|
|
||||||
---@field enabled boolean
|
|
||||||
---@field ignored table<string, boolean>
|
|
||||||
---@field notifyChannel string
|
|
||||||
---@field ttl number
|
|
||||||
---@field doWhisper boolean
|
|
||||||
---@field zoneNotifyFor table<string, boolean>
|
|
||||||
|
|
||||||
---@class HeimdallMessengerConfig
|
|
||||||
---@field enabled boolean
|
|
||||||
---@field interval number
|
|
||||||
|
|
||||||
---@class HeimdallDeathReporterConfig
|
|
||||||
---@field enabled boolean
|
|
||||||
---@field throttle number
|
|
||||||
---@field doWhisper boolean
|
|
||||||
---@field notifyChannel string
|
|
||||||
---@field zoneOverride string?
|
|
||||||
---@field duelThrottle number
|
|
||||||
|
|
||||||
---@class HeimdallInviterConfig
|
|
||||||
---@field enabled boolean
|
|
||||||
---@field listeningChannel string
|
|
||||||
---@field keyword string
|
|
||||||
---@field allAssist boolean
|
|
||||||
---@field agentsAssist boolean
|
|
||||||
---@field throttle number
|
|
||||||
---@field kickOffline boolean
|
|
||||||
---@field cleanupInterval number
|
|
||||||
---@field afkThreshold number
|
|
||||||
|
|
||||||
---@class HeimdallDuelerConfig
|
|
||||||
---@field enabled boolean
|
|
||||||
---@field declineOther boolean
|
|
||||||
|
|
||||||
---@class HeimdallBullyConfig
|
|
||||||
---@field enabled boolean
|
|
||||||
|
|
||||||
---@class HeimdallAgentTrackerConfig
|
|
||||||
---@field enabled boolean
|
|
||||||
---@field masterChannel string
|
|
||||||
|
|
||||||
---@class HeimdallEmoterConfig
|
|
||||||
---@field enabled boolean
|
|
||||||
---@field masterChannel string
|
|
||||||
---@field prefix string
|
|
||||||
|
|
||||||
---@class HeimdallEchoerConfig
|
|
||||||
---@field enabled boolean
|
|
||||||
---@field masterChannel string
|
|
||||||
---@field prefix string
|
|
||||||
|
|
||||||
---@class HeimdallMacroerConfig
|
|
||||||
---@field enabled boolean
|
|
||||||
---@field priority string[]
|
|
||||||
|
|
||||||
---@class HeimdallCommanderConfig
|
|
||||||
---@field enabled boolean
|
|
||||||
---@field masterChannel string
|
|
||||||
---@field commander string
|
|
||||||
---@field commands table<string, boolean>
|
|
||||||
|
|
||||||
---@class HeimdallStinkyTrackerConfig
|
|
||||||
---@field enabled boolean
|
|
||||||
---@field masterChannel string
|
|
||||||
|
|
||||||
---@class HeimdallCombatAlerterConfig
|
|
||||||
---@field enabled boolean
|
|
||||||
---@field masterChannel string
|
|
||||||
|
|
||||||
--- Data ---
|
|
||||||
---@class HeimdallMessengerData
|
|
||||||
---@field queue table<string, Message>
|
|
||||||
---@field ticker number?
|
|
||||||
|
|
||||||
---@class HeimdallWhoData
|
|
||||||
---@field updateTicker number?
|
|
||||||
---@field whoTicker number?
|
|
||||||
---@field ignored table<string, boolean>
|
|
||||||
|
|
||||||
---@class HeimdallStinkyTrackerData
|
|
||||||
---@field stinkies ReactiveValue
|
|
||||||
|
|
||||||
shared.GetOrDefault = function(table, keys, default)
|
shared.GetOrDefault = function(table, keys, default)
|
||||||
local value = default
|
local value = default
|
||||||
@@ -169,35 +109,34 @@ local function init()
|
|||||||
break
|
break
|
||||||
end
|
end
|
||||||
|
|
||||||
if i == #keys then
|
if i == #keys then value = traverse end
|
||||||
value = traverse
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
return value
|
return value
|
||||||
end
|
end
|
||||||
|
|
||||||
shared.messenger = {
|
--/run Heimdall_Data.config.who.queries="g-\"БеспредеЛ\"|ally"
|
||||||
queue = {}
|
|
||||||
}
|
|
||||||
shared.who = {
|
|
||||||
ignored = {},
|
|
||||||
}
|
|
||||||
|
|
||||||
Heimdall_Data.config = {
|
Heimdall_Data.config = {
|
||||||
|
debug = shared.GetOrDefault(Heimdall_Data, { "config", "debug" }, false),
|
||||||
|
chatSniffer = {
|
||||||
|
enabled = shared.GetOrDefault(Heimdall_Data, { "config", "chatSniffer", "enabled" }, false),
|
||||||
|
debug = shared.GetOrDefault(Heimdall_Data, { "config", "chatSniffer", "debug" }, false),
|
||||||
|
},
|
||||||
spotter = {
|
spotter = {
|
||||||
enabled = shared.GetOrDefault(Heimdall_Data, { "config", "spotter", "enabled" }, true),
|
enabled = shared.GetOrDefault(Heimdall_Data, { "config", "spotter", "enabled" }, true),
|
||||||
|
debug = shared.GetOrDefault(Heimdall_Data, { "config", "spotter", "debug" }, false),
|
||||||
everyone = shared.GetOrDefault(Heimdall_Data, { "config", "spotter", "everyone" }, false),
|
everyone = shared.GetOrDefault(Heimdall_Data, { "config", "spotter", "everyone" }, false),
|
||||||
hostile = shared.GetOrDefault(Heimdall_Data, { "config", "spotter", "hostile" }, true),
|
hostile = shared.GetOrDefault(Heimdall_Data, { "config", "spotter", "hostile" }, true),
|
||||||
alliance = shared.GetOrDefault(Heimdall_Data, { "config", "spotter", "alliance" }, true),
|
alliance = shared.GetOrDefault(Heimdall_Data, { "config", "spotter", "alliance" }, true),
|
||||||
stinky = shared.GetOrDefault(Heimdall_Data, { "config", "spotter", "stinky" }, true),
|
stinky = shared.GetOrDefault(Heimdall_Data, { "config", "spotter", "stinky" }, true),
|
||||||
notifyChannel = shared.GetOrDefault(Heimdall_Data, { "config", "spotter", "notifyChannel" }, "Agent"),
|
channels = shared.GetOrDefault(Heimdall_Data, { "config", "spotter", "channels" }, { "Agent" }),
|
||||||
zoneOverride = shared.GetOrDefault(Heimdall_Data, { "config", "spotter", "zoneOverride" }, nil),
|
zoneOverride = shared.GetOrDefault(Heimdall_Data, { "config", "spotter", "zoneOverride" }, nil),
|
||||||
throttleTime = shared.GetOrDefault(Heimdall_Data, { "config", "spotter", "throttleTime" }, 10)
|
throttleTime = shared.GetOrDefault(Heimdall_Data, { "config", "spotter", "throttleTime" }, 10),
|
||||||
},
|
},
|
||||||
who = {
|
who = {
|
||||||
enabled = shared.GetOrDefault(Heimdall_Data, { "config", "who", "enabled" }, false),
|
enabled = shared.GetOrDefault(Heimdall_Data, { "config", "who", "enabled" }, false),
|
||||||
|
debug = shared.GetOrDefault(Heimdall_Data, { "config", "who", "debug" }, false),
|
||||||
ignored = shared.GetOrDefault(Heimdall_Data, { "config", "who", "ignored" }, {}),
|
ignored = shared.GetOrDefault(Heimdall_Data, { "config", "who", "ignored" }, {}),
|
||||||
notifyChannel = shared.GetOrDefault(Heimdall_Data, { "config", "who", "notifyChannel" }, "Agent"),
|
channels = shared.GetOrDefault(Heimdall_Data, { "config", "who", "channels" }, { "Agent" }),
|
||||||
ttl = shared.GetOrDefault(Heimdall_Data, { "config", "who", "ttl" }, 20),
|
ttl = shared.GetOrDefault(Heimdall_Data, { "config", "who", "ttl" }, 20),
|
||||||
doWhisper = shared.GetOrDefault(Heimdall_Data, { "config", "who", "doWhisper" }, true),
|
doWhisper = shared.GetOrDefault(Heimdall_Data, { "config", "who", "doWhisper" }, true),
|
||||||
zoneNotifyFor = shared.GetOrDefault(Heimdall_Data, { "config", "who", "zoneNotifyFor" }, {
|
zoneNotifyFor = shared.GetOrDefault(Heimdall_Data, { "config", "who", "zoneNotifyFor" }, {
|
||||||
@@ -208,24 +147,26 @@ local function init()
|
|||||||
["Echo Isles"] = true,
|
["Echo Isles"] = true,
|
||||||
["Valley of Trials"] = true,
|
["Valley of Trials"] = true,
|
||||||
}),
|
}),
|
||||||
|
queries = shared.GetOrDefault(Heimdall_Data, { "config", "who", "queries" }, ""),
|
||||||
},
|
},
|
||||||
messenger = {
|
messenger = {
|
||||||
enabled = shared.GetOrDefault(Heimdall_Data, { "config", "messenger", "enabled" }, true),
|
enabled = shared.GetOrDefault(Heimdall_Data, { "config", "messenger", "enabled" }, true),
|
||||||
|
debug = shared.GetOrDefault(Heimdall_Data, { "config", "messenger", "debug" }, false),
|
||||||
interval = shared.GetOrDefault(Heimdall_Data, { "config", "messenger", "interval" }, 0.2),
|
interval = shared.GetOrDefault(Heimdall_Data, { "config", "messenger", "interval" }, 0.2),
|
||||||
},
|
},
|
||||||
deathReporter = {
|
deathReporter = {
|
||||||
enabled = shared.GetOrDefault(Heimdall_Data, { "config", "deathReporter", "enabled" }, false),
|
enabled = shared.GetOrDefault(Heimdall_Data, { "config", "deathReporter", "enabled" }, false),
|
||||||
|
debug = shared.GetOrDefault(Heimdall_Data, { "config", "deathReporter", "debug" }, false),
|
||||||
throttle = shared.GetOrDefault(Heimdall_Data, { "config", "deathReporter", "throttle" }, 10),
|
throttle = shared.GetOrDefault(Heimdall_Data, { "config", "deathReporter", "throttle" }, 10),
|
||||||
doWhisper = shared.GetOrDefault(Heimdall_Data, { "config", "deathReporter", "doWhisper" }, true),
|
doWhisper = shared.GetOrDefault(Heimdall_Data, { "config", "deathReporter", "doWhisper" }, true),
|
||||||
notifyChannel = shared.GetOrDefault(Heimdall_Data, { "config", "deathReporter", "notifyChannel" }, "Agent"),
|
channels = shared.GetOrDefault(Heimdall_Data, { "config", "deathReporter", "channels" }, { "Agent" }),
|
||||||
zoneOverride = shared.GetOrDefault(Heimdall_Data, { "config", "deathReporter", "zoneOverride" }, nil),
|
zoneOverride = shared.GetOrDefault(Heimdall_Data, { "config", "deathReporter", "zoneOverride" }, nil),
|
||||||
duelThrottle = shared.GetOrDefault(Heimdall_Data, { "config", "deathReporter", "duelThrottle" }, 5),
|
duelThrottle = shared.GetOrDefault(Heimdall_Data, { "config", "deathReporter", "duelThrottle" }, 5),
|
||||||
},
|
},
|
||||||
whisperNotify = shared.GetOrDefault(Heimdall_Data, { "config", "whisperNotify" }, {}),
|
|
||||||
stinkies = shared.GetOrDefault(Heimdall_Data, { "config", "stinkies" }, {}),
|
|
||||||
inviter = {
|
inviter = {
|
||||||
enabled = shared.GetOrDefault(Heimdall_Data, { "config", "inviter", "enabled" }, false),
|
enabled = shared.GetOrDefault(Heimdall_Data, { "config", "inviter", "enabled" }, false),
|
||||||
listeningChannel = shared.GetOrDefault(Heimdall_Data, { "config", "inviter", "listeningChannel" }, "Agent"),
|
debug = shared.GetOrDefault(Heimdall_Data, { "config", "inviter", "debug" }, false),
|
||||||
|
channels = shared.GetOrDefault(Heimdall_Data, { "config", "inviter", "channels" }, { "Agent" }),
|
||||||
keyword = shared.GetOrDefault(Heimdall_Data, { "config", "inviter", "keyword" }, "+"),
|
keyword = shared.GetOrDefault(Heimdall_Data, { "config", "inviter", "keyword" }, "+"),
|
||||||
allAssist = shared.GetOrDefault(Heimdall_Data, { "config", "inviter", "allAssist" }, false),
|
allAssist = shared.GetOrDefault(Heimdall_Data, { "config", "inviter", "allAssist" }, false),
|
||||||
agentsAssist = shared.GetOrDefault(Heimdall_Data, { "config", "inviter", "agentsAssist" }, false),
|
agentsAssist = shared.GetOrDefault(Heimdall_Data, { "config", "inviter", "agentsAssist" }, false),
|
||||||
@@ -233,47 +174,200 @@ local function init()
|
|||||||
kickOffline = shared.GetOrDefault(Heimdall_Data, { "config", "inviter", "kickOffline" }, false),
|
kickOffline = shared.GetOrDefault(Heimdall_Data, { "config", "inviter", "kickOffline" }, false),
|
||||||
cleanupInterval = shared.GetOrDefault(Heimdall_Data, { "config", "inviter", "cleanupInterval" }, 10),
|
cleanupInterval = shared.GetOrDefault(Heimdall_Data, { "config", "inviter", "cleanupInterval" }, 10),
|
||||||
afkThreshold = shared.GetOrDefault(Heimdall_Data, { "config", "inviter", "afkThreshold" }, 300),
|
afkThreshold = shared.GetOrDefault(Heimdall_Data, { "config", "inviter", "afkThreshold" }, 300),
|
||||||
|
listeningChannel = shared.GetOrDefault(Heimdall_Data, { "config", "inviter", "listeningChannel" }, {}),
|
||||||
},
|
},
|
||||||
dueler = {
|
dueler = {
|
||||||
enabled = shared.GetOrDefault(Heimdall_Data, { "config", "dueler", "enabled" }, false),
|
enabled = shared.GetOrDefault(Heimdall_Data, { "config", "dueler", "enabled" }, false),
|
||||||
|
debug = shared.GetOrDefault(Heimdall_Data, { "config", "dueler", "debug" }, false),
|
||||||
declineOther = shared.GetOrDefault(Heimdall_Data, { "config", "dueler", "declineOther" }, false),
|
declineOther = shared.GetOrDefault(Heimdall_Data, { "config", "dueler", "declineOther" }, false),
|
||||||
},
|
},
|
||||||
bully = {
|
bully = {
|
||||||
enabled = shared.GetOrDefault(Heimdall_Data, { "config", "bully", "enabled" }, false),
|
enabled = shared.GetOrDefault(Heimdall_Data, { "config", "bully", "enabled" }, false),
|
||||||
|
debug = shared.GetOrDefault(Heimdall_Data, { "config", "bully", "debug" }, false),
|
||||||
},
|
},
|
||||||
agentTracker = {
|
agentTracker = {
|
||||||
enabled = shared.GetOrDefault(Heimdall_Data, { "config", "agentTracker", "enabled" }, false),
|
enabled = shared.GetOrDefault(Heimdall_Data, { "config", "agentTracker", "enabled" }, false),
|
||||||
masterChannel = shared.GetOrDefault(Heimdall_Data, { "config", "agentTracker", "masterChannel" }, "Agent"),
|
debug = shared.GetOrDefault(Heimdall_Data, { "config", "agentTracker", "debug" }, false),
|
||||||
|
channels = shared.GetOrDefault(Heimdall_Data, { "config", "agentTracker", "channels" }, { "Agent" }),
|
||||||
},
|
},
|
||||||
emoter = {
|
emoter = {
|
||||||
enabled = shared.GetOrDefault(Heimdall_Data, { "config", "emoter", "enabled" }, false),
|
enabled = shared.GetOrDefault(Heimdall_Data, { "config", "emoter", "enabled" }, false),
|
||||||
masterChannel = shared.GetOrDefault(Heimdall_Data, { "config", "emoter", "masterChannel" }, "Agent"),
|
debug = shared.GetOrDefault(Heimdall_Data, { "config", "emoter", "debug" }, false),
|
||||||
|
channels = shared.GetOrDefault(Heimdall_Data, { "config", "emoter", "channels" }, { "Agent" }),
|
||||||
prefix = shared.GetOrDefault(Heimdall_Data, { "config", "emoter", "prefix" }, ""),
|
prefix = shared.GetOrDefault(Heimdall_Data, { "config", "emoter", "prefix" }, ""),
|
||||||
},
|
},
|
||||||
echoer = {
|
echoer = {
|
||||||
enabled = shared.GetOrDefault(Heimdall_Data, { "config", "echoer", "enabled" }, false),
|
enabled = shared.GetOrDefault(Heimdall_Data, { "config", "echoer", "enabled" }, false),
|
||||||
masterChannel = shared.GetOrDefault(Heimdall_Data, { "config", "echoer", "masterChannel" }, "Agent"),
|
debug = shared.GetOrDefault(Heimdall_Data, { "config", "echoer", "debug" }, false),
|
||||||
|
channels = shared.GetOrDefault(Heimdall_Data, { "config", "echoer", "channels" }, { "Agent" }),
|
||||||
prefix = shared.GetOrDefault(Heimdall_Data, { "config", "echoer", "prefix" }, ""),
|
prefix = shared.GetOrDefault(Heimdall_Data, { "config", "echoer", "prefix" }, ""),
|
||||||
},
|
},
|
||||||
macroer = {
|
macroer = {
|
||||||
enabled = shared.GetOrDefault(Heimdall_Data, { "config", "macroer", "enabled" }, false),
|
enabled = shared.GetOrDefault(Heimdall_Data, { "config", "macroer", "enabled" }, false),
|
||||||
|
debug = shared.GetOrDefault(Heimdall_Data, { "config", "macroer", "debug" }, false),
|
||||||
priority = shared.GetOrDefault(Heimdall_Data, { "config", "macroer", "priority" }, {}),
|
priority = shared.GetOrDefault(Heimdall_Data, { "config", "macroer", "priority" }, {}),
|
||||||
},
|
},
|
||||||
agents = shared.GetOrDefault(Heimdall_Data, { "config", "agents" }, {}),
|
agents = shared.GetOrDefault(Heimdall_Data, { "config", "agents" }, {}),
|
||||||
commander = {
|
commander = {
|
||||||
enabled = shared.GetOrDefault(Heimdall_Data, { "config", "commander", "enabled" }, false),
|
enabled = shared.GetOrDefault(Heimdall_Data, { "config", "commander", "enabled" }, false),
|
||||||
masterChannel = shared.GetOrDefault(Heimdall_Data, { "config", "commander", "masterChannel" }, "Agent"),
|
debug = shared.GetOrDefault(Heimdall_Data, { "config", "commander", "debug" }, false),
|
||||||
|
channels = shared.GetOrDefault(Heimdall_Data, { "config", "commander", "channels" }, { "Agent" }),
|
||||||
commander = shared.GetOrDefault(Heimdall_Data, { "config", "commander", "commander" }, "Heimdállr"),
|
commander = shared.GetOrDefault(Heimdall_Data, { "config", "commander", "commander" }, "Heimdállr"),
|
||||||
commands = shared.GetOrDefault(Heimdall_Data, { "config", "commander", "commands" }, {}),
|
commands = shared.GetOrDefault(Heimdall_Data, { "config", "commander", "commands" }, {}),
|
||||||
},
|
},
|
||||||
stinkyTracker = {
|
stinkyTracker = {
|
||||||
enabled = shared.GetOrDefault(Heimdall_Data, { "config", "stinkyTracker", "enabled" }, false),
|
enabled = shared.GetOrDefault(Heimdall_Data, { "config", "stinkyTracker", "enabled" }, false),
|
||||||
masterChannel = shared.GetOrDefault(Heimdall_Data, { "config", "stinkyTracker", "masterChannel" }, "Agent"),
|
debug = shared.GetOrDefault(Heimdall_Data, { "config", "stinkyTracker", "debug" }, false),
|
||||||
|
channels = shared.GetOrDefault(Heimdall_Data, { "config", "stinkyTracker", "channels" }, { "Agent" }),
|
||||||
|
ignoredTimeout = shared.GetOrDefault(Heimdall_Data, { "config", "stinkyTracker", "ignoredTimeout" }, 600),
|
||||||
},
|
},
|
||||||
combatAlerter = {
|
combatAlerter = {
|
||||||
enabled = shared.GetOrDefault(Heimdall_Data, { "config", "combatAlerter", "enabled" }, false),
|
enabled = shared.GetOrDefault(Heimdall_Data, { "config", "combatAlerter", "enabled" }, false),
|
||||||
masterChannel = shared.GetOrDefault(Heimdall_Data, { "config", "combatAlerter", "masterChannel" }, "Agent"),
|
debug = shared.GetOrDefault(Heimdall_Data, { "config", "combatAlerter", "debug" }, false),
|
||||||
|
channels = shared.GetOrDefault(Heimdall_Data, { "config", "combatAlerter", "channels" }, { "Agent" }),
|
||||||
},
|
},
|
||||||
|
messageDelegator = {
|
||||||
|
enabled = shared.GetOrDefault(Heimdall_Data, { "config", "messageDelegator", "enabled" }, false),
|
||||||
|
debug = shared.GetOrDefault(Heimdall_Data, { "config", "messageDelegator", "debug" }, false),
|
||||||
|
delegates = shared.GetOrDefault(Heimdall_Data, { "config", "messageDelegator", "delegates" }, {}),
|
||||||
|
masterChannel = shared.GetOrDefault(
|
||||||
|
Heimdall_Data,
|
||||||
|
{ "config", "messageDelegator", "masterChannel" },
|
||||||
|
"Agent"
|
||||||
|
),
|
||||||
|
},
|
||||||
|
sniffer = {
|
||||||
|
enabled = shared.GetOrDefault(Heimdall_Data, { "config", "sniffer", "enabled" }, false),
|
||||||
|
debug = shared.GetOrDefault(Heimdall_Data, { "config", "sniffer", "debug" }, false),
|
||||||
|
channels = shared.GetOrDefault(Heimdall_Data, { "config", "sniffer", "channels" }, { "Agent" }),
|
||||||
|
throttle = shared.GetOrDefault(Heimdall_Data, { "config", "sniffer", "throttle" }, 10),
|
||||||
|
zoneOverride = shared.GetOrDefault(Heimdall_Data, { "config", "sniffer", "zoneOverride" }, nil),
|
||||||
|
stinky = shared.GetOrDefault(Heimdall_Data, { "config", "sniffer", "stinky" }, true),
|
||||||
|
},
|
||||||
|
minimapTagger = {
|
||||||
|
enabled = shared.GetOrDefault(Heimdall_Data, { "config", "minimapTagger", "enabled" }, false),
|
||||||
|
debug = shared.GetOrDefault(Heimdall_Data, { "config", "minimapTagger", "debug" }, false),
|
||||||
|
channels = shared.GetOrDefault(Heimdall_Data, { "config", "minimapTagger", "channels" }, { "Agent" }),
|
||||||
|
throttle = shared.GetOrDefault(Heimdall_Data, { "config", "minimapTagger", "throttle" }, 10),
|
||||||
|
scale = shared.GetOrDefault(Heimdall_Data, { "config", "minimapTagger", "scale" }, 3),
|
||||||
|
tagTTL = shared.GetOrDefault(Heimdall_Data, { "config", "minimapTagger", "tagTTL" }, 1),
|
||||||
|
tagSound = shared.GetOrDefault(Heimdall_Data, { "config", "minimapTagger", "tagSound" }, false),
|
||||||
|
tagSoundFile = shared.GetOrDefault(
|
||||||
|
Heimdall_Data,
|
||||||
|
{ "config", "minimapTagger", "tagSoundFile" },
|
||||||
|
"MGSSpot.ogg"
|
||||||
|
),
|
||||||
|
tagSoundThrottle = shared.GetOrDefault(Heimdall_Data, { "config", "minimapTagger", "tagSoundThrottle" }, 0),
|
||||||
|
tagTextureFile = shared.GetOrDefault(
|
||||||
|
Heimdall_Data,
|
||||||
|
{ "config", "minimapTagger", "tagTextureFile" },
|
||||||
|
"Aura4.tga"
|
||||||
|
),
|
||||||
|
---
|
||||||
|
alertTTL = shared.GetOrDefault(Heimdall_Data, { "config", "minimapTagger", "alertTTL" }, 1),
|
||||||
|
alertSound = shared.GetOrDefault(Heimdall_Data, { "config", "minimapTagger", "alertSound" }, false),
|
||||||
|
alertSoundFile = shared.GetOrDefault(
|
||||||
|
Heimdall_Data,
|
||||||
|
{ "config", "minimapTagger", "alertSoundFile" },
|
||||||
|
"OOF.ogg"
|
||||||
|
),
|
||||||
|
alertSoundThrottle = shared.GetOrDefault(
|
||||||
|
Heimdall_Data,
|
||||||
|
{ "config", "minimapTagger", "alertSoundThrottle" },
|
||||||
|
0
|
||||||
|
),
|
||||||
|
alertTextureFile = shared.GetOrDefault(
|
||||||
|
Heimdall_Data,
|
||||||
|
{ "config", "minimapTagger", "alertTextureFile" },
|
||||||
|
"Aura27.tga"
|
||||||
|
),
|
||||||
|
---
|
||||||
|
combatTTL = shared.GetOrDefault(Heimdall_Data, { "config", "minimapTagger", "combatTTL" }, 1),
|
||||||
|
combatSound = shared.GetOrDefault(Heimdall_Data, { "config", "minimapTagger", "combatSound" }, false),
|
||||||
|
combatSoundFile = shared.GetOrDefault(
|
||||||
|
Heimdall_Data,
|
||||||
|
{ "config", "minimapTagger", "combatSoundFile" },
|
||||||
|
"StarScream.ogg"
|
||||||
|
),
|
||||||
|
combatSoundThrottle = shared.GetOrDefault(
|
||||||
|
Heimdall_Data,
|
||||||
|
{ "config", "minimapTagger", "combatSoundThrottle" },
|
||||||
|
2
|
||||||
|
),
|
||||||
|
combatTextureFile = shared.GetOrDefault(
|
||||||
|
Heimdall_Data,
|
||||||
|
{ "config", "minimapTagger", "combatTextureFile" },
|
||||||
|
"Aura58.tga"
|
||||||
|
),
|
||||||
|
---
|
||||||
|
helpTTL = shared.GetOrDefault(Heimdall_Data, { "config", "minimapTagger", "helpTTL" }, 1),
|
||||||
|
helpSound = shared.GetOrDefault(Heimdall_Data, { "config", "minimapTagger", "helpSound" }, false),
|
||||||
|
helpSoundFile = shared.GetOrDefault(
|
||||||
|
Heimdall_Data,
|
||||||
|
{ "config", "minimapTagger", "helpSoundFile" },
|
||||||
|
"MedicGangsterParadise.ogg"
|
||||||
|
),
|
||||||
|
helpSoundThrottle = shared.GetOrDefault(
|
||||||
|
Heimdall_Data,
|
||||||
|
{ "config", "minimapTagger", "helpSoundThrottle" },
|
||||||
|
2
|
||||||
|
),
|
||||||
|
helpTextureFile = shared.GetOrDefault(
|
||||||
|
Heimdall_Data,
|
||||||
|
{ "config", "minimapTagger", "helpTextureFile" },
|
||||||
|
"Aura68.tga"
|
||||||
|
),
|
||||||
|
},
|
||||||
|
whisperNotify = shared.GetOrDefault(Heimdall_Data, { "config", "whisperNotify" }, {}),
|
||||||
|
stinkies = shared.GetOrDefault(Heimdall_Data, { "config", "stinkies" }, {}),
|
||||||
|
notes = shared.GetOrDefault(Heimdall_Data, { "config", "notes" }, {}),
|
||||||
|
scale = shared.GetOrDefault(Heimdall_Data, { "config", "scale" }, 1),
|
||||||
|
locale = shared.GetOrDefault(Heimdall_Data, { "config", "locale" }, "en"),
|
||||||
|
bonkDetector = {
|
||||||
|
enabled = shared.GetOrDefault(Heimdall_Data, { "config", "bonkDetector", "enabled" }, false),
|
||||||
|
debug = shared.GetOrDefault(Heimdall_Data, { "config", "bonkDetector", "debug" }, false),
|
||||||
|
channels = shared.GetOrDefault(Heimdall_Data, { "config", "bonkDetector", "channels" }, { "Agent" }),
|
||||||
|
throttle = shared.GetOrDefault(Heimdall_Data, { "config", "bonkDetector", "throttle" }, 5),
|
||||||
|
},
|
||||||
|
noter = {
|
||||||
|
enabled = shared.GetOrDefault(Heimdall_Data, { "config", "noter", "enabled" }, false),
|
||||||
|
debug = shared.GetOrDefault(Heimdall_Data, { "config", "noter", "debug" }, false),
|
||||||
|
channels = shared.GetOrDefault(Heimdall_Data, { "config", "noter", "channels" }, { "Agent" }),
|
||||||
|
lastNotes = shared.GetOrDefault(Heimdall_Data, { "config", "noter", "lastNotes" }, 5),
|
||||||
|
},
|
||||||
|
network = {
|
||||||
|
enabled = shared.GetOrDefault(Heimdall_Data, { "config", "network", "enabled" }, false),
|
||||||
|
debug = shared.GetOrDefault(Heimdall_Data, { "config", "network", "debug" }, false),
|
||||||
|
members = shared.GetOrDefault(Heimdall_Data, { "config", "network", "members" }, {}),
|
||||||
|
updateInterval = shared.GetOrDefault(Heimdall_Data, { "config", "network", "updateInterval" }, 10),
|
||||||
|
},
|
||||||
|
networkMessenger = {
|
||||||
|
enabled = shared.GetOrDefault(Heimdall_Data, { "config", "networkMessenger", "enabled" }, false),
|
||||||
|
debug = shared.GetOrDefault(Heimdall_Data, { "config", "networkMessenger", "debug" }, false),
|
||||||
|
interval = shared.GetOrDefault(Heimdall_Data, { "config", "networkMessenger", "interval" }, 0.01),
|
||||||
|
},
|
||||||
|
configurator = {
|
||||||
|
enabled = shared.GetOrDefault(Heimdall_Data, { "config", "configurator", "enabled" }, false),
|
||||||
|
debug = shared.GetOrDefault(Heimdall_Data, { "config", "configurator", "debug" }, false),
|
||||||
|
},
|
||||||
|
stinkyCache = {
|
||||||
|
enabled = shared.GetOrDefault(Heimdall_Data, { "config", "stinkyCache", "enabled" }, false),
|
||||||
|
debug = shared.GetOrDefault(Heimdall_Data, { "config", "stinkyCache", "debug" }, false),
|
||||||
|
commander = shared.GetOrDefault(Heimdall_Data, { "config", "stinkyCache", "commander" }, "Heimdállr"),
|
||||||
|
ttl = shared.GetOrDefault(Heimdall_Data, { "config", "stinkyCache", "ttl" }, 10),
|
||||||
|
},
|
||||||
|
achievementSniffer = {
|
||||||
|
enabled = shared.GetOrDefault(Heimdall_Data, { "config", "achievementSniffer", "enabled" }, false),
|
||||||
|
debug = shared.GetOrDefault(Heimdall_Data, { "config", "achievementSniffer", "debug" }, false),
|
||||||
|
--texture = shared.GetOrDefault(Heimdall_Data, { "config", "achievementSniffer", "texture" }, "Aura53.tga"),
|
||||||
|
--offsetX = shared.GetOrDefault(Heimdall_Data, { "config", "achievementSniffer", "offsetX" }, 0),
|
||||||
|
--offsetY = shared.GetOrDefault(Heimdall_Data, { "config", "achievementSniffer", "offsetY" }, 0),
|
||||||
|
rescan = shared.GetOrDefault(Heimdall_Data, { "config", "achievementSniffer", "rescan" }, false),
|
||||||
|
scanInterval = shared.GetOrDefault(Heimdall_Data, { "config", "achievementSniffer", "scanInterval" }, 1),
|
||||||
|
--iconScale = shared.GetOrDefault(Heimdall_Data, { "config", "achievementSniffer", "iconScale" }, 1),
|
||||||
|
},
|
||||||
|
addonPrefix = shared.GetOrDefault(Heimdall_Data, { "config", "addonPrefix" }, "HEIMDALL"),
|
||||||
|
channelLocale = shared.GetOrDefault(Heimdall_Data, { "config", "channelLocale" }, {}),
|
||||||
}
|
}
|
||||||
|
|
||||||
shared.raceMap = {
|
shared.raceMap = {
|
||||||
@@ -297,7 +391,7 @@ local function init()
|
|||||||
["Void Elf"] = "Alliance",
|
["Void Elf"] = "Alliance",
|
||||||
["Lightforged Draenei"] = "Alliance",
|
["Lightforged Draenei"] = "Alliance",
|
||||||
["Mechagnome"] = "Alliance",
|
["Mechagnome"] = "Alliance",
|
||||||
["Mag'har Orc"] = "Horde"
|
["Mag'har Orc"] = "Horde",
|
||||||
}
|
}
|
||||||
|
|
||||||
shared.classColors = {
|
shared.classColors = {
|
||||||
@@ -312,15 +406,13 @@ local function init()
|
|||||||
["Warlock"] = "8788EE",
|
["Warlock"] = "8788EE",
|
||||||
["Monk"] = "00FF98",
|
["Monk"] = "00FF98",
|
||||||
["Druid"] = "FF7C0A",
|
["Druid"] = "FF7C0A",
|
||||||
["Demon Hunter"] = "A330C9"
|
["Demon Hunter"] = "A330C9",
|
||||||
}
|
}
|
||||||
|
|
||||||
---@param input string
|
---@param input string
|
||||||
---@return number
|
---@return number
|
||||||
shared.utf8len = function(input)
|
shared.utf8len = function(input)
|
||||||
if not input then
|
if not input then return 0 end
|
||||||
return 0
|
|
||||||
end
|
|
||||||
local len = 0
|
local len = 0
|
||||||
local i = 1
|
local i = 1
|
||||||
local n = #input
|
local n = #input
|
||||||
@@ -358,6 +450,73 @@ local function init()
|
|||||||
return input
|
return input
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param input string
|
||||||
|
---@param deliminer string
|
||||||
|
---@return table<number, string>
|
||||||
|
shared.Split = function(input, deliminer)
|
||||||
|
if deliminer == nil then deliminer = "%s" end
|
||||||
|
local t = {}
|
||||||
|
for str in string.gmatch(input, "([^" .. deliminer .. "]+)") do
|
||||||
|
table.insert(t, str)
|
||||||
|
end
|
||||||
|
return t
|
||||||
|
end
|
||||||
|
---@param name string
|
||||||
|
---@return boolean
|
||||||
|
shared.IsStinky = function(name)
|
||||||
|
return Heimdall_Data.config.stinkies[name] ~= nil or shared.StinkyCache[name] ~= nil
|
||||||
|
end
|
||||||
|
|
||||||
|
---@param f function
|
||||||
|
---@return function
|
||||||
|
shared.Memoize = function(f)
|
||||||
|
local mem = {} -- memoizing table
|
||||||
|
setmetatable(mem, { __mode = "kv" }) -- make it weak
|
||||||
|
return function(x) -- new version of 'f', with memoizing
|
||||||
|
if Heimdall_Data.config.debug then print(string.format("[Heimdall] Memoize %s", tostring(x))) end
|
||||||
|
local r = mem[x]
|
||||||
|
if r == nil then -- no previous result?
|
||||||
|
if Heimdall_Data.config.debug then
|
||||||
|
print(string.format("[Heimdall] Memoize %s is nil, calling original function", tostring(x)))
|
||||||
|
end
|
||||||
|
r = f(x) -- calls original function
|
||||||
|
if Heimdall_Data.config.debug then
|
||||||
|
print(string.format("[Heimdall] Memoized result for %s: %s", tostring(x), tostring(r)))
|
||||||
|
end
|
||||||
|
mem[x] = r -- store result for reuse
|
||||||
|
end
|
||||||
|
if Heimdall_Data.config.debug then
|
||||||
|
print(string.format("[Heimdall] Memoize %s is %s", tostring(x), tostring(r)))
|
||||||
|
end
|
||||||
|
return r
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
---@param channel string
|
||||||
|
---@return string
|
||||||
|
shared.GetLocaleForChannel = function(channel) return Heimdall_Data.config.channelLocale[channel] or "en" end
|
||||||
|
|
||||||
|
---@param key string
|
||||||
|
---@param locale string
|
||||||
|
---@return string
|
||||||
|
shared._L = function(key, locale)
|
||||||
|
local localeTable = shared._Locale[locale]
|
||||||
|
if not localeTable then
|
||||||
|
if Heimdall_Data.config.debug then
|
||||||
|
print(string.format("[Heimdall] Locale %s not found", tostring(locale)))
|
||||||
|
end
|
||||||
|
return key
|
||||||
|
end
|
||||||
|
local value = localeTable[key]
|
||||||
|
if not value then
|
||||||
|
if Heimdall_Data.config.debug then
|
||||||
|
print(string.format("[Heimdall] Key %s not found in locale %s", tostring(key), tostring(locale)))
|
||||||
|
end
|
||||||
|
return key
|
||||||
|
end
|
||||||
|
return value
|
||||||
|
end
|
||||||
|
|
||||||
shared.Messenger.Init()
|
shared.Messenger.Init()
|
||||||
shared.StinkyTracker.Init()
|
shared.StinkyTracker.Init()
|
||||||
shared.AgentTracker.Init()
|
shared.AgentTracker.Init()
|
||||||
@@ -371,13 +530,87 @@ local function init()
|
|||||||
shared.Commander.Init()
|
shared.Commander.Init()
|
||||||
shared.CombatAlerter.Init()
|
shared.CombatAlerter.Init()
|
||||||
shared.Config.Init()
|
shared.Config.Init()
|
||||||
|
shared.MinimapTagger.Init()
|
||||||
|
shared.BonkDetector.Init()
|
||||||
|
shared.Sniffer.Init()
|
||||||
|
shared.Noter.Init()
|
||||||
|
shared.Network.Init()
|
||||||
|
shared.NetworkMessenger.Init()
|
||||||
|
shared.Configurator.Init()
|
||||||
|
shared.StinkyCache.Init()
|
||||||
|
shared.AchievementSniffer.Init()
|
||||||
|
shared.ChatSniffer.Init()
|
||||||
print("Heimdall loaded!")
|
print("Heimdall loaded!")
|
||||||
end
|
end
|
||||||
|
|
||||||
local loadedFrame = CreateFrame("Frame")
|
local loadedFrame = CreateFrame("Frame")
|
||||||
loadedFrame:RegisterEvent("ADDON_LOADED")
|
loadedFrame:RegisterEvent("ADDON_LOADED")
|
||||||
loadedFrame:SetScript("OnEvent", function(self, event, addonName)
|
loadedFrame:SetScript("OnEvent", function(self, event, addonName)
|
||||||
if addonName == addonname then
|
if addonName == addonname then init() end
|
||||||
init()
|
|
||||||
end
|
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
-- Create the import/export frame
|
||||||
|
local ccpFrame = CreateFrame("Frame", "CCPFrame", UIParent)
|
||||||
|
ccpFrame:SetSize(512 * 1.5, 512 * 1.5)
|
||||||
|
ccpFrame:SetPoint("CENTER")
|
||||||
|
ccpFrame:SetFrameStrata("HIGH")
|
||||||
|
ccpFrame:EnableMouse(true)
|
||||||
|
ccpFrame:SetMovable(true)
|
||||||
|
ccpFrame:SetResizable(false)
|
||||||
|
ccpFrame:SetBackdrop({
|
||||||
|
bgFile = "Interface/Tooltips/UI-Tooltip-Background",
|
||||||
|
edgeFile = "Interface/Tooltips/UI-Tooltip-Border",
|
||||||
|
tile = true,
|
||||||
|
tileSize = 4,
|
||||||
|
edgeSize = 4,
|
||||||
|
insets = {
|
||||||
|
left = 4,
|
||||||
|
right = 4,
|
||||||
|
top = 4,
|
||||||
|
bottom = 4,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
ccpFrame:SetBackdropColor(0, 0, 0, 0.8)
|
||||||
|
ccpFrame:SetBackdropBorderColor(0.5, 0.5, 0.5, 1)
|
||||||
|
|
||||||
|
ccpFrame:SetMovable(true)
|
||||||
|
ccpFrame:EnableMouse(true)
|
||||||
|
ccpFrame:RegisterForDrag("LeftButton")
|
||||||
|
ccpFrame:SetScript("OnDragStart", function(self) self:StartMoving() end)
|
||||||
|
ccpFrame:SetScript("OnDragStop", function(self) self:StopMovingOrSizing() end)
|
||||||
|
ccpFrame:SetScript("OnShow", function(self) self:SetScale(1) end)
|
||||||
|
ccpFrame:Hide()
|
||||||
|
|
||||||
|
-- Create scroll frame
|
||||||
|
local scrollFrame = CreateFrame("ScrollFrame", "CCPFrameScrollFrame", ccpFrame, "UIPanelScrollFrameTemplate")
|
||||||
|
scrollFrame:SetPoint("TOPLEFT", ccpFrame, "TOPLEFT", 10, -10)
|
||||||
|
scrollFrame:SetPoint("BOTTOMRIGHT", ccpFrame, "BOTTOMRIGHT", -30, 10)
|
||||||
|
|
||||||
|
-- Create the text box
|
||||||
|
local ccpFrameTextBox = CreateFrame("EditBox", "CCPFrameTextBox", scrollFrame)
|
||||||
|
ccpFrameTextBox:SetSize(512 * 1.5 - 40, 512 * 1.5 - 20)
|
||||||
|
ccpFrameTextBox:SetPoint("TOPLEFT", scrollFrame, "TOPLEFT", 0, 0)
|
||||||
|
ccpFrameTextBox:SetFont("Fonts\\FRIZQT__.ttf", 12)
|
||||||
|
ccpFrameTextBox:SetTextColor(1, 1, 1, 1)
|
||||||
|
ccpFrameTextBox:SetTextInsets(10, 10, 10, 10)
|
||||||
|
ccpFrameTextBox:SetMultiLine(true)
|
||||||
|
ccpFrameTextBox:SetAutoFocus(true)
|
||||||
|
ccpFrameTextBox:SetMaxLetters(1000000)
|
||||||
|
ccpFrameTextBox:SetScript("OnEscapePressed", function(self) ccpFrame:Hide() end)
|
||||||
|
|
||||||
|
-- Set the scroll frame's scroll child
|
||||||
|
scrollFrame:SetScrollChild(ccpFrameTextBox)
|
||||||
|
|
||||||
|
CCP = function(window)
|
||||||
|
window = window or 1
|
||||||
|
local charFrame = _G["ChatFrame" .. window]
|
||||||
|
local maxLines = charFrame:GetNumMessages() or 0
|
||||||
|
local chat = {}
|
||||||
|
for i = 1, maxLines do
|
||||||
|
local currentMsg = charFrame:GetMessageInfo(i)
|
||||||
|
chat[#chat + 1] = currentMsg
|
||||||
|
end
|
||||||
|
ccpFrameTextBox:SetText(table.concat(chat, "\n"))
|
||||||
|
ccpFrame:Show()
|
||||||
|
ccpFrameTextBox:SetFocus()
|
||||||
|
end
|
||||||
|
16
Heimdall.toc
16
Heimdall.toc
@@ -1,17 +1,18 @@
|
|||||||
## Interface: 70300
|
## Interface: 70300
|
||||||
## Title: Heimdall
|
## Title: Heimdall
|
||||||
## Version: 3.0.0
|
## Version: 3.12.0
|
||||||
## Notes: Watches over areas and alerts when hostiles spotted
|
## Notes: Watches over areas and alerts when hostiles spotted
|
||||||
## Author: Cyka
|
## Author: Cyka
|
||||||
## SavedVariables: Heimdall_Data
|
## SavedVariables: Heimdall_Data, Heimdall_Achievements, Heimdall_Chat
|
||||||
|
|
||||||
#core
|
_L.lua
|
||||||
Modules/CLEUParser.lua
|
Modules/CLEUParser.lua
|
||||||
Modules/ReactiveValue.lua
|
Modules/ReactiveValue.lua
|
||||||
Modules/DumpTable.lua
|
Modules/DumpTable.lua
|
||||||
Modules/Spotter.lua
|
Modules/Spotter.lua
|
||||||
Modules/Whoer.lua
|
Modules/Whoer.lua
|
||||||
Modules/Messenger.lua
|
Modules/Messenger.lua
|
||||||
|
Modules/Network.lua
|
||||||
Modules/DeathReporter.lua
|
Modules/DeathReporter.lua
|
||||||
Modules/Inviter.lua
|
Modules/Inviter.lua
|
||||||
Modules/Dueler.lua
|
Modules/Dueler.lua
|
||||||
@@ -23,5 +24,14 @@ Modules/Macroer.lua
|
|||||||
Modules/Commander.lua
|
Modules/Commander.lua
|
||||||
Modules/StinkyTracker.lua
|
Modules/StinkyTracker.lua
|
||||||
Modules/CombatAlerter.lua
|
Modules/CombatAlerter.lua
|
||||||
|
Modules/MinimapTagger.lua
|
||||||
Modules/Config.lua
|
Modules/Config.lua
|
||||||
|
Modules/BonkDetector.lua
|
||||||
|
Modules/Sniffer.lua
|
||||||
|
Modules/Noter.lua
|
||||||
|
Modules/NetworkMessenger.lua
|
||||||
|
Modules/StinkyCache.lua
|
||||||
|
Modules/Configurator.lua
|
||||||
|
Modules/AchievementSniffer.lua
|
||||||
|
Modules/ChatSniffer.lua
|
||||||
Heimdall.lua
|
Heimdall.lua
|
BIN
Heimdall.zip
(Stored with Git LFS)
BIN
Heimdall.zip
(Stored with Git LFS)
Binary file not shown.
1
Meta
Submodule
1
Meta
Submodule
Submodule Meta added at eee043a846
304
Modules/AchievementSniffer.lua
Normal file
304
Modules/AchievementSniffer.lua
Normal file
@@ -0,0 +1,304 @@
|
|||||||
|
local _, shared = ...
|
||||||
|
---@cast shared HeimdallShared
|
||||||
|
local ModuleName = "AchievementSniffer"
|
||||||
|
|
||||||
|
---@class HeimdallAchievementSnifferConfig
|
||||||
|
---@field enabled boolean
|
||||||
|
---@field debug boolean
|
||||||
|
-----@field texture string
|
||||||
|
-----@field offsetX number
|
||||||
|
-----@field offsetY number
|
||||||
|
---@field rescan boolean
|
||||||
|
---@field scanInterval number
|
||||||
|
-----@field iconScale number
|
||||||
|
|
||||||
|
-- local HeimdallRoot = "Interface\\AddOns\\Heimdall\\"
|
||||||
|
-- local TextureRoot = HeimdallRoot .. "Texture\\"
|
||||||
|
|
||||||
|
local Achievements = {
|
||||||
|
15,
|
||||||
|
958,
|
||||||
|
1266,
|
||||||
|
2078,
|
||||||
|
2141,
|
||||||
|
2200,
|
||||||
|
4958,
|
||||||
|
5456,
|
||||||
|
5749,
|
||||||
|
6460,
|
||||||
|
6753,
|
||||||
|
7382,
|
||||||
|
7383,
|
||||||
|
7384,
|
||||||
|
8929,
|
||||||
|
8982,
|
||||||
|
9017,
|
||||||
|
9038,
|
||||||
|
9493,
|
||||||
|
10059,
|
||||||
|
10079,
|
||||||
|
10278,
|
||||||
|
10657,
|
||||||
|
10672,
|
||||||
|
10684,
|
||||||
|
10688,
|
||||||
|
10689,
|
||||||
|
10692,
|
||||||
|
10693,
|
||||||
|
10698,
|
||||||
|
10790,
|
||||||
|
10875,
|
||||||
|
11124,
|
||||||
|
11126,
|
||||||
|
11127,
|
||||||
|
11128,
|
||||||
|
11153,
|
||||||
|
11157,
|
||||||
|
11164,
|
||||||
|
11188,
|
||||||
|
11189,
|
||||||
|
11190,
|
||||||
|
11446,
|
||||||
|
11473,
|
||||||
|
11610,
|
||||||
|
11657,
|
||||||
|
11658,
|
||||||
|
11659,
|
||||||
|
11660,
|
||||||
|
11674,
|
||||||
|
11992,
|
||||||
|
11993,
|
||||||
|
11994,
|
||||||
|
11995,
|
||||||
|
11996,
|
||||||
|
11997,
|
||||||
|
11998,
|
||||||
|
11999,
|
||||||
|
12000,
|
||||||
|
12001,
|
||||||
|
12020,
|
||||||
|
12026,
|
||||||
|
12074,
|
||||||
|
12445,
|
||||||
|
12447,
|
||||||
|
12448,
|
||||||
|
}
|
||||||
|
|
||||||
|
---@class AchievementSniffer
|
||||||
|
shared.AchievementSniffer = {
|
||||||
|
Init = function()
|
||||||
|
if Heimdall_Data.config.achievementSniffer.debug then
|
||||||
|
print(string.format("[%s] Module initialized", ModuleName))
|
||||||
|
end
|
||||||
|
local guidMap = {}
|
||||||
|
|
||||||
|
---@class AchievementData
|
||||||
|
---@field id number
|
||||||
|
---@field date string
|
||||||
|
---@field completed boolean
|
||||||
|
|
||||||
|
---@class Heimdall_Achievements
|
||||||
|
---@field players table<string, table<number, AchievementData>>
|
||||||
|
---@field alreadySeen table<string, boolean>
|
||||||
|
---@field rescan boolean
|
||||||
|
if not Heimdall_Achievements then Heimdall_Achievements = {} end
|
||||||
|
if not Heimdall_Achievements.players then Heimdall_Achievements.players = {} end
|
||||||
|
if not Heimdall_Achievements.alreadySeen then Heimdall_Achievements.alreadySeen = {} end
|
||||||
|
|
||||||
|
--local framePool = {}
|
||||||
|
--for i = 1, 40 do
|
||||||
|
-- local frame = CreateFrame("Frame", "HeimdallAchievementSnifferNameplate" .. i, UIParent)
|
||||||
|
-- local texture = frame:CreateTexture(nil, "ARTWORK")
|
||||||
|
-- texture:SetAllPoints(frame)
|
||||||
|
-- texture:SetTexture(TextureRoot .. Heimdall_Data.config.achievementSniffer.texture)
|
||||||
|
-- frame.texture = texture
|
||||||
|
-- frame:Hide()
|
||||||
|
-- table.insert(framePool, frame)
|
||||||
|
--end
|
||||||
|
|
||||||
|
---@param name string
|
||||||
|
---@return boolean
|
||||||
|
local function ShouldInspect(name)
|
||||||
|
local should = false
|
||||||
|
if not Heimdall_Achievements.players[name] then
|
||||||
|
if Heimdall_Data.config.achievementSniffer.debug then
|
||||||
|
print(string.format("[%s] Player %s does not have prior achievement data", ModuleName, name))
|
||||||
|
end
|
||||||
|
should = true
|
||||||
|
end
|
||||||
|
if Heimdall_Achievements.alreadySeen[name] then
|
||||||
|
if Heimdall_Data.config.achievementSniffer.debug then
|
||||||
|
print(string.format("[%s] Player %s has already been seen", ModuleName, name))
|
||||||
|
end
|
||||||
|
-- Save some memory
|
||||||
|
Heimdall_Achievements.players[name] = nil
|
||||||
|
should = false
|
||||||
|
end
|
||||||
|
if Heimdall_Data.config.achievementSniffer.rescan then
|
||||||
|
if Heimdall_Data.config.achievementSniffer.debug then
|
||||||
|
print(string.format("[%s] Rescan is enabled", ModuleName))
|
||||||
|
end
|
||||||
|
should = true
|
||||||
|
end
|
||||||
|
return should
|
||||||
|
end
|
||||||
|
|
||||||
|
-- It's not working well AT ALL
|
||||||
|
-- I don't know how to do it better
|
||||||
|
-- It simply just does not work...
|
||||||
|
--local function UpdateFrames()
|
||||||
|
-- for i, frame in ipairs(framePool) do
|
||||||
|
-- local unit = "nameplate" .. i
|
||||||
|
-- if not UnitExists(unit) then
|
||||||
|
-- --if Heimdall_Data.config.achievementSniffer.debug then
|
||||||
|
-- -- print(string.format("[%s] Unit %s does not exist, hiding frame", ModuleName, unit))
|
||||||
|
-- --end
|
||||||
|
-- frame:Hide()
|
||||||
|
-- else
|
||||||
|
-- --local unitFrame = _G[string.format("ElvUI_NamePlate%dHealthBar", i)]
|
||||||
|
-- local unitFrame = _G[string.format("NamePlate%d", i)]
|
||||||
|
-- if unitFrame == nil then
|
||||||
|
-- if Heimdall_Data.config.achievementSniffer.debug then
|
||||||
|
-- print(string.format("[%s] Unit frame for %s not found", ModuleName, unit))
|
||||||
|
-- end
|
||||||
|
-- frame:Hide()
|
||||||
|
-- else
|
||||||
|
-- local unitName = UnitName(unit)
|
||||||
|
-- if Heimdall_Data.config.achievementSniffer.debug then
|
||||||
|
-- print(string.format("[%s] Unit frame found for %s (%s)", ModuleName, unit, unitName))
|
||||||
|
-- end
|
||||||
|
-- frame:Show()
|
||||||
|
-- frame:SetSize(32, 32)
|
||||||
|
-- frame:SetFrameStrata("HIGH")
|
||||||
|
-- frame:SetFrameLevel(100)
|
||||||
|
-- frame:SetScale(Heimdall_Data.config.achievementSniffer.iconScale)
|
||||||
|
-- frame.texture:SetTexture(TextureRoot .. Heimdall_Data.config.achievementSniffer.texture)
|
||||||
|
-- frame:SetPoint("CENTER", unitFrame, "CENTER",
|
||||||
|
-- Heimdall_Data.config.achievementSniffer.offsetX,
|
||||||
|
-- Heimdall_Data.config.achievementSniffer.offsetY)
|
||||||
|
-- frame:SetParent(unitFrame)
|
||||||
|
-- frame:SetAlpha(1)
|
||||||
|
-- local exists = ShouldInspect(unitName)
|
||||||
|
-- if exists then
|
||||||
|
-- frame.texture:SetVertexColor(1, 0, 0, 1)
|
||||||
|
-- else
|
||||||
|
-- frame.texture:SetVertexColor(0, 1, 0, 1)
|
||||||
|
-- end
|
||||||
|
-- if Heimdall_Data.config.achievementSniffer.debug then
|
||||||
|
-- print(string.format("[%s] Frame updated for %s", ModuleName, unitName))
|
||||||
|
-- end
|
||||||
|
-- end
|
||||||
|
-- end
|
||||||
|
-- end
|
||||||
|
--end
|
||||||
|
|
||||||
|
---@param unit string
|
||||||
|
local function TryInspect(unit)
|
||||||
|
local targetPlayer = UnitIsPlayer(unit)
|
||||||
|
if not targetPlayer then return end
|
||||||
|
local targetName = UnitName(unit)
|
||||||
|
local targetGuid = UnitGUID(unit)
|
||||||
|
guidMap[targetGuid] = targetName
|
||||||
|
|
||||||
|
if not ShouldInspect(targetName) then
|
||||||
|
if Heimdall_Data.config.achievementSniffer.debug then
|
||||||
|
print(string.format("[%s] Not inspecting player: %s", ModuleName, targetName))
|
||||||
|
end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local canInspect = CheckInteractDistance(unit, 1)
|
||||||
|
if canInspect then
|
||||||
|
if Heimdall_Data.config.achievementSniffer.debug then
|
||||||
|
print(string.format("[%s] Inspecting player: %s", ModuleName, targetName))
|
||||||
|
end
|
||||||
|
SetAchievementComparisonUnit(unit)
|
||||||
|
else
|
||||||
|
if Heimdall_Data.config.achievementSniffer.debug then
|
||||||
|
print(string.format("[%s] Cannot inspect player (too far?): %s", ModuleName, targetName))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
---@param name string
|
||||||
|
local function Scan(name)
|
||||||
|
if Heimdall_Data.config.achievementSniffer.debug then
|
||||||
|
print(string.format("[%s] Scanning achievements for %s", ModuleName, name))
|
||||||
|
end
|
||||||
|
Heimdall_Achievements.players[name] = {}
|
||||||
|
for i, aid in ipairs(Achievements) do
|
||||||
|
local completed, month, day, year = GetAchievementComparisonInfo(aid)
|
||||||
|
if completed then
|
||||||
|
---@type string
|
||||||
|
local yearstr = "" .. year
|
||||||
|
if year < 100 then yearstr = "20" .. year end
|
||||||
|
|
||||||
|
local date = string.format("%04d-%02d-%02d", yearstr, month, day)
|
||||||
|
|
||||||
|
local data = {
|
||||||
|
id = aid,
|
||||||
|
date = date,
|
||||||
|
completed = completed,
|
||||||
|
}
|
||||||
|
if Heimdall_Data.config.achievementSniffer.debug then
|
||||||
|
print(string.format("[%s] Achievement %d completed on %s", ModuleName, aid, date))
|
||||||
|
end
|
||||||
|
Heimdall_Achievements.players[name][aid] = data
|
||||||
|
end
|
||||||
|
end
|
||||||
|
--UpdateFrames()
|
||||||
|
end
|
||||||
|
|
||||||
|
local nameplateFrame = CreateFrame("Frame")
|
||||||
|
nameplateFrame:RegisterEvent("NAME_PLATE_UNIT_ADDED")
|
||||||
|
nameplateFrame:RegisterEvent("NAME_PLATE_UNIT_REMOVED")
|
||||||
|
nameplateFrame:SetScript("OnEvent", function(self, event, unit)
|
||||||
|
if not Heimdall_Data.config.achievementSniffer.enabled then return end
|
||||||
|
if Heimdall_Data.config.achievementSniffer.debug then
|
||||||
|
print(string.format("[%s] Event triggered: %s for unit: %s", ModuleName, event, unit))
|
||||||
|
end
|
||||||
|
if event == "NAME_PLATE_UNIT_ADDED" then TryInspect(unit) end
|
||||||
|
--UpdateFrames()
|
||||||
|
end)
|
||||||
|
|
||||||
|
local inspectFrame = CreateFrame("Frame")
|
||||||
|
inspectFrame:RegisterEvent("INSPECT_ACHIEVEMENT_READY")
|
||||||
|
inspectFrame:SetScript("OnEvent", function(self, event, guid)
|
||||||
|
if not Heimdall_Data.config.achievementSniffer.enabled then return end
|
||||||
|
local name = guidMap[guid]
|
||||||
|
if not name then
|
||||||
|
if Heimdall_Data.config.achievementSniffer.debug then
|
||||||
|
print(string.format("[%s] No name found for guid: %s", ModuleName, guid))
|
||||||
|
end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
if Heimdall_Data.config.achievementSniffer.debug then
|
||||||
|
print(string.format("[%s] Event triggered: %s for player: %s", ModuleName, event, name))
|
||||||
|
end
|
||||||
|
Scan(name)
|
||||||
|
end)
|
||||||
|
|
||||||
|
local function Tick()
|
||||||
|
C_Timer.NewTimer(Heimdall_Data.config.achievementSniffer.scanInterval, Tick)
|
||||||
|
if not Heimdall_Data.config.achievementSniffer.enabled then return end
|
||||||
|
|
||||||
|
if Heimdall_Data.config.achievementSniffer.debug then
|
||||||
|
print(string.format("[%s] Scanning achievements for everyone on screen", ModuleName))
|
||||||
|
end
|
||||||
|
for i = 1, 40 do
|
||||||
|
local unit = "nameplate" .. i
|
||||||
|
if UnitExists(unit) then
|
||||||
|
TryInspect(unit)
|
||||||
|
--else
|
||||||
|
-- if Heimdall_Data.config.achievementSniffer.debug then
|
||||||
|
-- print(string.format("[%s] Unit %s does not exist, nothing to inspect", ModuleName, unit))
|
||||||
|
-- end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
--UpdateFrames()
|
||||||
|
end
|
||||||
|
Tick()
|
||||||
|
|
||||||
|
print(string.format("[%s] Module initialized", ModuleName))
|
||||||
|
end,
|
||||||
|
}
|
@@ -1,39 +1,144 @@
|
|||||||
local addonname, shared = ...
|
local _, shared = ...
|
||||||
---@cast shared HeimdallShared
|
---@cast shared HeimdallShared
|
||||||
---@cast addonname string
|
local ModuleName = "AgentTracker"
|
||||||
|
|
||||||
---@diagnostic disable-next-line: missing-fields
|
---@class AgentTrackerData
|
||||||
shared.AgentTracker = {}
|
---@field agents ReactiveValue<table<string, string>>
|
||||||
function shared.AgentTracker.Init()
|
|
||||||
|
---@class HeimdallAgentTrackerConfig
|
||||||
|
---@field enabled boolean
|
||||||
|
---@field debug boolean
|
||||||
|
---@field channels string[]
|
||||||
|
|
||||||
|
---@class AgentTracker
|
||||||
|
shared.AgentTracker = {
|
||||||
|
---@param name string
|
||||||
|
---@return boolean
|
||||||
|
Track = function(name)
|
||||||
|
if not name then return false end
|
||||||
|
local exists = shared.AgentTracker.IsAgent(name)
|
||||||
|
if exists then return false end
|
||||||
|
shared.agentTracker.agents[name] = date("%Y-%m-%dT%H:%M:%S")
|
||||||
|
-- Heimdall_Data.config.agents[name] = date("%Y-%m-%dT%H:%M:%S")
|
||||||
|
if Heimdall_Data.config.agentTracker.debug then
|
||||||
|
print(string.format("[%s] Tracking new agent: %s", ModuleName, name))
|
||||||
|
shared.dump(shared.agentTracker.agents)
|
||||||
|
end
|
||||||
|
return true
|
||||||
|
end,
|
||||||
|
---@param name string
|
||||||
|
---@return boolean
|
||||||
|
IsAgent = function(name)
|
||||||
|
if not name then return false end
|
||||||
|
return shared.agentTracker.agents[name] ~= nil
|
||||||
|
end,
|
||||||
|
---@param callback fun(agent: string)
|
||||||
|
OnChange = function(callback) shared.agentTracker.agents:onChange(callback) end,
|
||||||
|
---@param callback fun(agent: string)
|
||||||
|
ForEach = function(callback)
|
||||||
|
---@type table<string, string>
|
||||||
|
local agents = shared.agentTracker.agents:get()
|
||||||
|
for name, _ in pairs(agents) do
|
||||||
|
callback(name)
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
---@return nil
|
||||||
|
Init = function()
|
||||||
|
shared.agentTracker = {
|
||||||
|
agents = ReactiveValue.new(Heimdall_Data.config.agents),
|
||||||
|
}
|
||||||
|
|
||||||
|
--/run Heimdall_Data.config.agents["Cyheuraeth"]=date("%Y-%m-%dT%H:%M:%S")
|
||||||
---@type table<string, boolean>
|
---@type table<string, boolean>
|
||||||
local channelRosterFrame = CreateFrame("Frame")
|
local channelRosterFrame = CreateFrame("Frame")
|
||||||
channelRosterFrame:RegisterEvent("CHANNEL_ROSTER_UPDATE")
|
channelRosterFrame:RegisterEvent("CHANNEL_ROSTER_UPDATE")
|
||||||
channelRosterFrame:SetScript("OnEvent", function(self, event, index)
|
channelRosterFrame:SetScript("OnEvent", function(self, event, index)
|
||||||
if not Heimdall_Data.config.agentTracker.enabled then return end
|
if Heimdall_Data.config.agentTracker.debug then
|
||||||
|
print(string.format("[%s] Channel roster update received", ModuleName))
|
||||||
|
end
|
||||||
|
if not Heimdall_Data.config.agentTracker.enabled then
|
||||||
|
if Heimdall_Data.config.agentTracker.debug then
|
||||||
|
print(string.format("[%s] Module disabled, ignoring roster update", ModuleName))
|
||||||
|
end
|
||||||
|
return
|
||||||
|
end
|
||||||
local name = GetChannelDisplayInfo(index)
|
local name = GetChannelDisplayInfo(index)
|
||||||
if name ~= Heimdall_Data.config.agentTracker.masterChannel then return end
|
if Heimdall_Data.config.agentTracker.debug then
|
||||||
|
print(string.format("[%s] Processing channel update: %s (index: %d)", ModuleName, name or "nil", index))
|
||||||
|
end
|
||||||
|
if name ~= Heimdall_Data.config.agentTracker.masterChannel then
|
||||||
|
if Heimdall_Data.config.agentTracker.debug then
|
||||||
|
print(string.format("[%s] Ignoring non-master channel: %s", ModuleName, name or "nil"))
|
||||||
|
end
|
||||||
|
return
|
||||||
|
end
|
||||||
local count = select(5, GetChannelDisplayInfo(index))
|
local count = select(5, GetChannelDisplayInfo(index))
|
||||||
|
if Heimdall_Data.config.agentTracker.debug then
|
||||||
|
print(string.format("[%s] Processing %d members in channel", ModuleName, count))
|
||||||
|
end
|
||||||
|
|
||||||
|
local newAgents = 0
|
||||||
for i = 1, count do
|
for i = 1, count do
|
||||||
local name = GetChannelRosterInfo(index, i)
|
name = GetChannelRosterInfo(index, i)
|
||||||
if name then
|
shared.AgentTracker.Track(name)
|
||||||
Heimdall_Data.config.agents[name] = date("%Y-%m-%dT%H:%M:%S")
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if Heimdall_Data.config.agentTracker.debug then
|
||||||
|
print(string.format("[%s] Roster update complete - Added %d new agents", ModuleName, newAgents))
|
||||||
end
|
end
|
||||||
--shared.dumpTable(Heimdall_Data.config.agents)
|
|
||||||
end)
|
end)
|
||||||
|
|
||||||
local agentTrackerChannelSniffer = CreateFrame("Frame")
|
local agentTrackerChannelSniffer = CreateFrame("Frame")
|
||||||
agentTrackerChannelSniffer:RegisterEvent("CHAT_MSG_CHANNEL")
|
agentTrackerChannelSniffer:RegisterEvent("CHAT_MSG_CHANNEL")
|
||||||
agentTrackerChannelSniffer:SetScript("OnEvent", function(self, event, msg, sender, ...)
|
agentTrackerChannelSniffer:SetScript("OnEvent", function(self, event, msg, sender, ...)
|
||||||
if not Heimdall_Data.config.agentTracker.enabled then return end
|
-- if Heimdall_Data.config.agentTracker.debug then
|
||||||
|
-- print(string.format("[%s] Channel message received from: %s", ModuleName, sender))
|
||||||
|
-- end
|
||||||
|
if not Heimdall_Data.config.agentTracker.enabled then
|
||||||
|
-- if Heimdall_Data.config.agentTracker.debug then
|
||||||
|
-- print(string.format("[%s] Module disabled, ignoring channel message", ModuleName))
|
||||||
|
-- end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
local channelId = select(6, ...)
|
local channelId = select(6, ...)
|
||||||
local channelname = GetChannelName(channelId)
|
local _, channelname = GetChannelName(channelId)
|
||||||
if not channelname then return end
|
local ok = false
|
||||||
if channelname ~= Heimdall_Data.config.who.notifyChannel then return end
|
for _, channel in pairs(Heimdall_Data.config.agentTracker.channels) do
|
||||||
local agentName = sender
|
if channel == channelname then
|
||||||
if not agentName then return end
|
ok = true
|
||||||
Heimdall_Data.config.agents[agentName] = date("%Y-%m-%dT%H:%M:%S")
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if not ok then
|
||||||
|
if Heimdall_Data.config.agentTracker.debug then
|
||||||
|
print(string.format("[%s] Channel name does not match any of the channels", ModuleName))
|
||||||
|
end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
if Heimdall_Data.config.agentTracker.debug then
|
||||||
|
print(string.format("[%s] Processing message from master channel: %s", ModuleName, sender))
|
||||||
|
end
|
||||||
|
|
||||||
|
sender = string.match(sender, "^[^-]+")
|
||||||
|
local new = shared.AgentTracker.Track(sender)
|
||||||
|
|
||||||
|
if Heimdall_Data.config.agentTracker.debug then
|
||||||
|
print(
|
||||||
|
string.format(
|
||||||
|
"[%s] %s agent from message: %s",
|
||||||
|
ModuleName,
|
||||||
|
new and "Added new" or "Updated existing",
|
||||||
|
sender
|
||||||
|
)
|
||||||
|
)
|
||||||
|
end
|
||||||
end)
|
end)
|
||||||
|
|
||||||
print("Heimdall - AgentTracker loaded")
|
if Heimdall_Data.config.agentTracker.debug then
|
||||||
end
|
print(string.format("[%s] Module initialized", ModuleName))
|
||||||
|
shared.dump(shared.agentTracker.agents:get(), "Agents")
|
||||||
|
end
|
||||||
|
print(string.format("[%s] Module initialized", ModuleName))
|
||||||
|
end,
|
||||||
|
}
|
||||||
|
142
Modules/BonkDetector.lua
Normal file
142
Modules/BonkDetector.lua
Normal file
@@ -0,0 +1,142 @@
|
|||||||
|
local _, shared = ...
|
||||||
|
---@cast shared HeimdallShared
|
||||||
|
local ModuleName = "BonkDetector"
|
||||||
|
|
||||||
|
---@class HeimdallBonkDetectorConfig
|
||||||
|
---@field enabled boolean
|
||||||
|
---@field debug boolean
|
||||||
|
---@field channels string[]
|
||||||
|
---@field throttle number
|
||||||
|
|
||||||
|
---@class BonkDetector
|
||||||
|
shared.BonkDetector = {
|
||||||
|
---@return nil
|
||||||
|
Init = function()
|
||||||
|
---@type table<string, number>
|
||||||
|
local lastReportTime = {}
|
||||||
|
|
||||||
|
local frame = CreateFrame("Frame")
|
||||||
|
frame:RegisterEvent("COMBAT_LOG_EVENT_UNFILTERED")
|
||||||
|
frame:SetScript("OnEvent", function(self, event, ...)
|
||||||
|
-- if Heimdall_Data.config.bonkDetector.debug then
|
||||||
|
-- print(string.format("[%s] Combat log event received", ModuleName))
|
||||||
|
-- end
|
||||||
|
if not Heimdall_Data.config.bonkDetector.enabled then
|
||||||
|
-- if Heimdall_Data.config.bonkDetector.debug then
|
||||||
|
-- print(string.format("[%s] Module disabled, ignoring combat event", ModuleName))
|
||||||
|
-- end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local subevent = select(2, ...)
|
||||||
|
if not subevent:find("_DAMAGE") then
|
||||||
|
if Heimdall_Data.config.bonkDetector.debug then
|
||||||
|
print(string.format("[%s] Not a damage event, ignoring: %s", ModuleName, subevent))
|
||||||
|
end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
---@type string|nil, string, string, string, string
|
||||||
|
local err, source, sourceGUID, destination, destinationGUID
|
||||||
|
|
||||||
|
source, err = CLEUParser.GetSourceName(...)
|
||||||
|
if err then
|
||||||
|
if Heimdall_Data.config.bonkDetector.debug then
|
||||||
|
print(string.format("[%s] Error getting source name: %s", ModuleName, err))
|
||||||
|
end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
sourceGUID, err = CLEUParser.GetSourceGUID(...)
|
||||||
|
if err then
|
||||||
|
if Heimdall_Data.config.bonkDetector.debug then
|
||||||
|
print(string.format("[%s] Error getting source GUID: %s", ModuleName, err))
|
||||||
|
end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
if not string.find(sourceGUID, "Player") then
|
||||||
|
if Heimdall_Data.config.bonkDetector.debug then
|
||||||
|
print(string.format("[%s] Source %s is not a player, nothing to do", ModuleName, source))
|
||||||
|
end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
destination, err = CLEUParser.GetDestName(...)
|
||||||
|
if err then
|
||||||
|
if Heimdall_Data.config.bonkDetector.debug then
|
||||||
|
print(string.format("[%s] Error getting destination name: %s", ModuleName, err))
|
||||||
|
end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
destinationGUID, err = CLEUParser.GetDestGUID(...)
|
||||||
|
if err then
|
||||||
|
if Heimdall_Data.config.bonkDetector.debug then
|
||||||
|
print(string.format("[%s] Error getting destination GUID: %s", ModuleName, err))
|
||||||
|
end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
if not string.find(destinationGUID, "Player") then
|
||||||
|
if Heimdall_Data.config.bonkDetector.debug then
|
||||||
|
print(string.format("[%s] Destination %s is not a player, nothing to do", ModuleName, destination))
|
||||||
|
end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
if source == destination then
|
||||||
|
if Heimdall_Data.config.bonkDetector.debug then
|
||||||
|
print(string.format("[%s] Source and destination are the same, ignoring event", ModuleName))
|
||||||
|
end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local currentTime = GetTime()
|
||||||
|
local throttle = Heimdall_Data.config.bonkDetector.throttle
|
||||||
|
|
||||||
|
if lastReportTime[source] and (currentTime - lastReportTime[source]) < throttle then
|
||||||
|
if Heimdall_Data.config.bonkDetector.debug then
|
||||||
|
local timeLeft = throttle - (currentTime - lastReportTime[source])
|
||||||
|
print(
|
||||||
|
string.format(
|
||||||
|
"[%s] Damage report throttled for %s (%.1f seconds remaining)",
|
||||||
|
ModuleName,
|
||||||
|
source,
|
||||||
|
timeLeft
|
||||||
|
)
|
||||||
|
)
|
||||||
|
end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
lastReportTime[source] = currentTime
|
||||||
|
|
||||||
|
if Heimdall_Data.config.bonkDetector.debug then
|
||||||
|
print(
|
||||||
|
string.format(
|
||||||
|
"[%s] Processing damage event - Source: %s, Target: %s, Type: %s",
|
||||||
|
ModuleName,
|
||||||
|
source,
|
||||||
|
destination,
|
||||||
|
subevent
|
||||||
|
)
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
for _, channel in pairs(Heimdall_Data.config.bonkDetector.channels) do
|
||||||
|
local locale = shared.GetLocaleForChannel(channel)
|
||||||
|
local msg = string.format(shared._L("bonkDetected", locale), source, destination, subevent)
|
||||||
|
---@type Message
|
||||||
|
local message = {
|
||||||
|
channel = "C",
|
||||||
|
data = channel,
|
||||||
|
message = msg,
|
||||||
|
}
|
||||||
|
if Heimdall_Data.config.bonkDetector.debug then
|
||||||
|
print(string.format("[%s] Queuing bonk detector message", ModuleName))
|
||||||
|
shared.dump(message)
|
||||||
|
end
|
||||||
|
table.insert(shared.messenger.queue, message)
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
print(string.format("[%s] Module initialized", ModuleName))
|
||||||
|
end,
|
||||||
|
}
|
@@ -1,9 +1,16 @@
|
|||||||
local addonname, shared = ...
|
local _, shared = ...
|
||||||
---@cast shared HeimdallShared
|
---@cast shared HeimdallShared
|
||||||
---@cast addonname string
|
local ModuleName = "Bully"
|
||||||
|
|
||||||
---@diagnostic disable-next-line: missing-fields
|
---@class HeimdallBullyConfig
|
||||||
shared.Bully = {}
|
---@field enabled boolean
|
||||||
function shared.Bully.Init()
|
---@field debug boolean
|
||||||
print("Heimdall - Bully loaded")
|
|
||||||
end
|
---@class Bully
|
||||||
|
shared.Bully = {
|
||||||
|
---@return nil
|
||||||
|
Init = function()
|
||||||
|
if Heimdall_Data.config.bully.debug then print(string.format("[%s] Module initialized", ModuleName)) end
|
||||||
|
print(string.format("[%s] Module initialized", ModuleName))
|
||||||
|
end,
|
||||||
|
}
|
||||||
|
@@ -12,12 +12,12 @@ local function Init()
|
|||||||
["destGUID"] = 8,
|
["destGUID"] = 8,
|
||||||
["destName"] = 9,
|
["destName"] = 9,
|
||||||
["destFlags"] = 10,
|
["destFlags"] = 10,
|
||||||
["destRaidFlags"] = 11
|
["destRaidFlags"] = 11,
|
||||||
},
|
},
|
||||||
["GENERIC_SPELL"] = {
|
["GENERIC_SPELL"] = {
|
||||||
["spellId"] = 12,
|
["spellId"] = 12,
|
||||||
["spellName"] = 13,
|
["spellName"] = 13,
|
||||||
["spellSchool"] = 14
|
["spellSchool"] = 14,
|
||||||
},
|
},
|
||||||
["GENERIC_DAMAGE"] = {
|
["GENERIC_DAMAGE"] = {
|
||||||
["amount"] = 15,
|
["amount"] = 15,
|
||||||
@@ -29,19 +29,19 @@ local function Init()
|
|||||||
["critical"] = 21,
|
["critical"] = 21,
|
||||||
["glancing"] = 22,
|
["glancing"] = 22,
|
||||||
["crushing"] = 23,
|
["crushing"] = 23,
|
||||||
["isOffHand"] = 24
|
["isOffHand"] = 24,
|
||||||
},
|
},
|
||||||
["GENERIC_MISSED"] = {
|
["GENERIC_MISSED"] = {
|
||||||
["missType"] = 15,
|
["missType"] = 15,
|
||||||
["isOffHand"] = 16,
|
["isOffHand"] = 16,
|
||||||
["amountMissed"] = 17,
|
["amountMissed"] = 17,
|
||||||
["critical"] = 18
|
["critical"] = 18,
|
||||||
},
|
},
|
||||||
["GENERIC_HEAL"] = {
|
["GENERIC_HEAL"] = {
|
||||||
["amount"] = 15,
|
["amount"] = 15,
|
||||||
["overhealing"] = 16,
|
["overhealing"] = 16,
|
||||||
["absorbed"] = 17,
|
["absorbed"] = 17,
|
||||||
["critical"] = 18
|
["critical"] = 18,
|
||||||
},
|
},
|
||||||
["GENERIC_HEAL_ABSORBED"] = {
|
["GENERIC_HEAL_ABSORBED"] = {
|
||||||
["extraGUID"] = 15,
|
["extraGUID"] = 15,
|
||||||
@@ -52,44 +52,44 @@ local function Init()
|
|||||||
["extraSpellName"] = 20,
|
["extraSpellName"] = 20,
|
||||||
["extraSchool"] = 21,
|
["extraSchool"] = 21,
|
||||||
["absorbedAmount"] = 22,
|
["absorbedAmount"] = 22,
|
||||||
["totalAmount"] = 23
|
["totalAmount"] = 23,
|
||||||
},
|
},
|
||||||
["GENERIC_ENERGIZE"] = {
|
["GENERIC_ENERGIZE"] = {
|
||||||
["amount"] = 15,
|
["amount"] = 15,
|
||||||
["overEnergize"] = 16,
|
["overEnergize"] = 16,
|
||||||
["powerType"] = 17
|
["powerType"] = 17,
|
||||||
},
|
},
|
||||||
["GENERIC_DRAIN"] = {
|
["GENERIC_DRAIN"] = {
|
||||||
["amount"] = 15,
|
["amount"] = 15,
|
||||||
["powerType"] = 16,
|
["powerType"] = 16,
|
||||||
["extraAmount"] = 17
|
["extraAmount"] = 17,
|
||||||
},
|
},
|
||||||
["GENERIC_LEECH"] = {
|
["GENERIC_LEECH"] = {
|
||||||
["amount"] = 15,
|
["amount"] = 15,
|
||||||
["powerType"] = 16,
|
["powerType"] = 16,
|
||||||
["extraAmount"] = 17
|
["extraAmount"] = 17,
|
||||||
},
|
},
|
||||||
["GENERIC_INTERRUPT"] = {
|
["GENERIC_INTERRUPT"] = {
|
||||||
["extraSpellId"] = 15,
|
["extraSpellId"] = 15,
|
||||||
["extraSpellName"] = 16,
|
["extraSpellName"] = 16,
|
||||||
["extraSchool"] = 17
|
["extraSchool"] = 17,
|
||||||
},
|
},
|
||||||
["GENERIC_DISPEL"] = {
|
["GENERIC_DISPEL"] = {
|
||||||
["extraSpellId"] = 15,
|
["extraSpellId"] = 15,
|
||||||
["extraSpellName"] = 16,
|
["extraSpellName"] = 16,
|
||||||
["extraSchool"] = 17,
|
["extraSchool"] = 17,
|
||||||
["auraType"] = 18
|
["auraType"] = 18,
|
||||||
},
|
},
|
||||||
["GENERIC_DISPEL_FAILED"] = {
|
["GENERIC_DISPEL_FAILED"] = {
|
||||||
["extraSpellId"] = 15,
|
["extraSpellId"] = 15,
|
||||||
["extraSpellName"] = 16,
|
["extraSpellName"] = 16,
|
||||||
["extraSchool"] = 17
|
["extraSchool"] = 17,
|
||||||
},
|
},
|
||||||
["GENERIC_STOLEN"] = {
|
["GENERIC_STOLEN"] = {
|
||||||
["extraSpellId"] = 15,
|
["extraSpellId"] = 15,
|
||||||
["extraSpellName"] = 16,
|
["extraSpellName"] = 16,
|
||||||
["extraSchool"] = 17,
|
["extraSchool"] = 17,
|
||||||
["auraType"] = 18
|
["auraType"] = 18,
|
||||||
},
|
},
|
||||||
["GENERIC_EXTRA_ATTACKS"] = { ["amount"] = 15 },
|
["GENERIC_EXTRA_ATTACKS"] = { ["amount"] = 15 },
|
||||||
["GENERIC_AURA_APPLIED"] = { ["auraType"] = 15, ["amount"] = 16 },
|
["GENERIC_AURA_APPLIED"] = { ["auraType"] = 15, ["amount"] = 16 },
|
||||||
@@ -102,38 +102,32 @@ local function Init()
|
|||||||
["extraSpellId"] = 15,
|
["extraSpellId"] = 15,
|
||||||
["extraSpellName"] = 16,
|
["extraSpellName"] = 16,
|
||||||
["extraSchool"] = 17,
|
["extraSchool"] = 17,
|
||||||
["auraType"] = 18
|
["auraType"] = 18,
|
||||||
},
|
},
|
||||||
["GENERIC_CAST_START"] = {},
|
["GENERIC_CAST_START"] = {},
|
||||||
["GENERIC_CAST_SUCCESS"] = {},
|
["GENERIC_CAST_SUCCESS"] = {},
|
||||||
["GENERIC_CAST_FAILED"] = {}
|
["GENERIC_CAST_FAILED"] = {},
|
||||||
}
|
}
|
||||||
|
|
||||||
CLEUEventInfo["SWING_DAMAGE"] = CLEUEventInfo["GENERIC_DAMAGE"]
|
CLEUEventInfo["SWING_DAMAGE"] = CLEUEventInfo["GENERIC_DAMAGE"]
|
||||||
CLEUEventInfo["SWING_MISSED"] = CLEUEventInfo["GENERIC_MISSED"]
|
CLEUEventInfo["SWING_MISSED"] = CLEUEventInfo["GENERIC_MISSED"]
|
||||||
CLEUEventInfo["SWING_HEAL"] = CLEUEventInfo["GENERIC_HEAL"]
|
CLEUEventInfo["SWING_HEAL"] = CLEUEventInfo["GENERIC_HEAL"]
|
||||||
CLEUEventInfo["SWING_HEAL_ABSORBED"] =
|
CLEUEventInfo["SWING_HEAL_ABSORBED"] = CLEUEventInfo["GENERIC_HEAL_ABSORBED"]
|
||||||
CLEUEventInfo["GENERIC_HEAL_ABSORBED"]
|
|
||||||
CLEUEventInfo["SWING_ENERGIZE"] = CLEUEventInfo["GENERIC_ENERGIZE"]
|
CLEUEventInfo["SWING_ENERGIZE"] = CLEUEventInfo["GENERIC_ENERGIZE"]
|
||||||
CLEUEventInfo["SWING_DRAIN"] = CLEUEventInfo["GENERIC_DRAIN"]
|
CLEUEventInfo["SWING_DRAIN"] = CLEUEventInfo["GENERIC_DRAIN"]
|
||||||
CLEUEventInfo["SWING_LEECH"] = CLEUEventInfo["GENERIC_LEECH"]
|
CLEUEventInfo["SWING_LEECH"] = CLEUEventInfo["GENERIC_LEECH"]
|
||||||
CLEUEventInfo["SWING_INTERRUPT"] = CLEUEventInfo["GENERIC_INTERRUPT"]
|
CLEUEventInfo["SWING_INTERRUPT"] = CLEUEventInfo["GENERIC_INTERRUPT"]
|
||||||
CLEUEventInfo["SWING_DISPEL"] = CLEUEventInfo["GENERIC_DISPEL"]
|
CLEUEventInfo["SWING_DISPEL"] = CLEUEventInfo["GENERIC_DISPEL"]
|
||||||
CLEUEventInfo["SWING_DISPEL_FAILED"] =
|
CLEUEventInfo["SWING_DISPEL_FAILED"] = CLEUEventInfo["GENERIC_DISPEL_FAILED"]
|
||||||
CLEUEventInfo["GENERIC_DISPEL_FAILED"]
|
|
||||||
CLEUEventInfo["SWING_STOLEN"] = CLEUEventInfo["GENERIC_STOLEN"]
|
CLEUEventInfo["SWING_STOLEN"] = CLEUEventInfo["GENERIC_STOLEN"]
|
||||||
CLEUEventInfo["SWING_EXTRA_ATTACKS"] =
|
CLEUEventInfo["SWING_EXTRA_ATTACKS"] = CLEUEventInfo["GENERIC_EXTRA_ATTACKS"]
|
||||||
CLEUEventInfo["GENERIC_EXTRA_ATTACKS"]
|
|
||||||
CLEUEventInfo["SWING_AURA_APPLIED"] = CLEUEventInfo["GENERIC_AURA_APPLIED"]
|
CLEUEventInfo["SWING_AURA_APPLIED"] = CLEUEventInfo["GENERIC_AURA_APPLIED"]
|
||||||
CLEUEventInfo["SWING_AURA_REMOVED"] = CLEUEventInfo["GENERIC_AURA_REMOVED"]
|
CLEUEventInfo["SWING_AURA_REMOVED"] = CLEUEventInfo["GENERIC_AURA_REMOVED"]
|
||||||
CLEUEventInfo["SWING_AURA_APPLIED_DOSE"] =
|
CLEUEventInfo["SWING_AURA_APPLIED_DOSE"] = CLEUEventInfo["GENERIC_AURA_APPLIED_DOSE"]
|
||||||
CLEUEventInfo["GENERIC_AURA_APPLIED_DOSE"]
|
CLEUEventInfo["SWING_AURA_REMOVED_DOSE"] = CLEUEventInfo["GENERIC_AURA_REMOVED_DOSE"]
|
||||||
CLEUEventInfo["SWING_AURA_REMOVED_DOSE"] =
|
|
||||||
CLEUEventInfo["GENERIC_AURA_REMOVED_DOSE"]
|
|
||||||
CLEUEventInfo["SWING_AURA_REFRESH"] = CLEUEventInfo["GENERIC_AURA_REFRESH"]
|
CLEUEventInfo["SWING_AURA_REFRESH"] = CLEUEventInfo["GENERIC_AURA_REFRESH"]
|
||||||
CLEUEventInfo["SWING_AURA_BROKEN"] = CLEUEventInfo["GENERIC_AURA_BROKEN"]
|
CLEUEventInfo["SWING_AURA_BROKEN"] = CLEUEventInfo["GENERIC_AURA_BROKEN"]
|
||||||
CLEUEventInfo["SWING_AURA_BROKEN_SPELL"] =
|
CLEUEventInfo["SWING_AURA_BROKEN_SPELL"] = CLEUEventInfo["GENERIC_AURA_BROKEN_SPELL"]
|
||||||
CLEUEventInfo["GENERIC_AURA_BROKEN_SPELL"]
|
|
||||||
CLEUEventInfo["SWING_CAST_START"] = CLEUEventInfo["GENERIC_CAST_START"]
|
CLEUEventInfo["SWING_CAST_START"] = CLEUEventInfo["GENERIC_CAST_START"]
|
||||||
CLEUEventInfo["SWING_CAST_SUCCESS"] = CLEUEventInfo["GENERIC_CAST_SUCCESS"]
|
CLEUEventInfo["SWING_CAST_SUCCESS"] = CLEUEventInfo["GENERIC_CAST_SUCCESS"]
|
||||||
CLEUEventInfo["SWING_CAST_FAILED"] = CLEUEventInfo["GENERIC_CAST_FAILED"]
|
CLEUEventInfo["SWING_CAST_FAILED"] = CLEUEventInfo["GENERIC_CAST_FAILED"]
|
||||||
@@ -141,28 +135,22 @@ local function Init()
|
|||||||
CLEUEventInfo["RANGE_DAMAGE"] = CLEUEventInfo["GENERIC_DAMAGE"]
|
CLEUEventInfo["RANGE_DAMAGE"] = CLEUEventInfo["GENERIC_DAMAGE"]
|
||||||
CLEUEventInfo["RANGE_MISSED"] = CLEUEventInfo["GENERIC_MISSED"]
|
CLEUEventInfo["RANGE_MISSED"] = CLEUEventInfo["GENERIC_MISSED"]
|
||||||
CLEUEventInfo["RANGE_HEAL"] = CLEUEventInfo["GENERIC_HEAL"]
|
CLEUEventInfo["RANGE_HEAL"] = CLEUEventInfo["GENERIC_HEAL"]
|
||||||
CLEUEventInfo["RANGE_HEAL_ABSORBED"] =
|
CLEUEventInfo["RANGE_HEAL_ABSORBED"] = CLEUEventInfo["GENERIC_HEAL_ABSORBED"]
|
||||||
CLEUEventInfo["GENERIC_HEAL_ABSORBED"]
|
|
||||||
CLEUEventInfo["RANGE_ENERGIZE"] = CLEUEventInfo["GENERIC_ENERGIZE"]
|
CLEUEventInfo["RANGE_ENERGIZE"] = CLEUEventInfo["GENERIC_ENERGIZE"]
|
||||||
CLEUEventInfo["RANGE_DRAIN"] = CLEUEventInfo["GENERIC_DRAIN"]
|
CLEUEventInfo["RANGE_DRAIN"] = CLEUEventInfo["GENERIC_DRAIN"]
|
||||||
CLEUEventInfo["RANGE_LEECH"] = CLEUEventInfo["GENERIC_LEECH"]
|
CLEUEventInfo["RANGE_LEECH"] = CLEUEventInfo["GENERIC_LEECH"]
|
||||||
CLEUEventInfo["RANGE_INTERRUPT"] = CLEUEventInfo["GENERIC_INTERRUPT"]
|
CLEUEventInfo["RANGE_INTERRUPT"] = CLEUEventInfo["GENERIC_INTERRUPT"]
|
||||||
CLEUEventInfo["RANGE_DISPEL"] = CLEUEventInfo["GENERIC_DISPEL"]
|
CLEUEventInfo["RANGE_DISPEL"] = CLEUEventInfo["GENERIC_DISPEL"]
|
||||||
CLEUEventInfo["RANGE_DISPEL_FAILED"] =
|
CLEUEventInfo["RANGE_DISPEL_FAILED"] = CLEUEventInfo["GENERIC_DISPEL_FAILED"]
|
||||||
CLEUEventInfo["GENERIC_DISPEL_FAILED"]
|
|
||||||
CLEUEventInfo["RANGE_STOLEN"] = CLEUEventInfo["GENERIC_STOLEN"]
|
CLEUEventInfo["RANGE_STOLEN"] = CLEUEventInfo["GENERIC_STOLEN"]
|
||||||
CLEUEventInfo["RANGE_EXTRA_ATTACKS"] =
|
CLEUEventInfo["RANGE_EXTRA_ATTACKS"] = CLEUEventInfo["GENERIC_EXTRA_ATTACKS"]
|
||||||
CLEUEventInfo["GENERIC_EXTRA_ATTACKS"]
|
|
||||||
CLEUEventInfo["RANGE_AURA_APPLIED"] = CLEUEventInfo["GENERIC_AURA_APPLIED"]
|
CLEUEventInfo["RANGE_AURA_APPLIED"] = CLEUEventInfo["GENERIC_AURA_APPLIED"]
|
||||||
CLEUEventInfo["RANGE_AURA_REMOVED"] = CLEUEventInfo["GENERIC_AURA_REMOVED"]
|
CLEUEventInfo["RANGE_AURA_REMOVED"] = CLEUEventInfo["GENERIC_AURA_REMOVED"]
|
||||||
CLEUEventInfo["RANGE_AURA_APPLIED_DOSE"] =
|
CLEUEventInfo["RANGE_AURA_APPLIED_DOSE"] = CLEUEventInfo["GENERIC_AURA_APPLIED_DOSE"]
|
||||||
CLEUEventInfo["GENERIC_AURA_APPLIED_DOSE"]
|
CLEUEventInfo["RANGE_AURA_REMOVED_DOSE"] = CLEUEventInfo["GENERIC_AURA_REMOVED_DOSE"]
|
||||||
CLEUEventInfo["RANGE_AURA_REMOVED_DOSE"] =
|
|
||||||
CLEUEventInfo["GENERIC_AURA_REMOVED_DOSE"]
|
|
||||||
CLEUEventInfo["RANGE_AURA_REFRESH"] = CLEUEventInfo["GENERIC_AURA_REFRESH"]
|
CLEUEventInfo["RANGE_AURA_REFRESH"] = CLEUEventInfo["GENERIC_AURA_REFRESH"]
|
||||||
CLEUEventInfo["RANGE_AURA_BROKEN"] = CLEUEventInfo["GENERIC_AURA_BROKEN"]
|
CLEUEventInfo["RANGE_AURA_BROKEN"] = CLEUEventInfo["GENERIC_AURA_BROKEN"]
|
||||||
CLEUEventInfo["RANGE_AURA_BROKEN_SPELL"] =
|
CLEUEventInfo["RANGE_AURA_BROKEN_SPELL"] = CLEUEventInfo["GENERIC_AURA_BROKEN_SPELL"]
|
||||||
CLEUEventInfo["GENERIC_AURA_BROKEN_SPELL"]
|
|
||||||
CLEUEventInfo["RANGE_CAST_START"] = CLEUEventInfo["GENERIC_CAST_START"]
|
CLEUEventInfo["RANGE_CAST_START"] = CLEUEventInfo["GENERIC_CAST_START"]
|
||||||
CLEUEventInfo["RANGE_CAST_SUCCESS"] = CLEUEventInfo["GENERIC_CAST_SUCCESS"]
|
CLEUEventInfo["RANGE_CAST_SUCCESS"] = CLEUEventInfo["GENERIC_CAST_SUCCESS"]
|
||||||
CLEUEventInfo["RANGE_CAST_FAILED"] = CLEUEventInfo["GENERIC_CAST_FAILED"]
|
CLEUEventInfo["RANGE_CAST_FAILED"] = CLEUEventInfo["GENERIC_CAST_FAILED"]
|
||||||
@@ -170,28 +158,22 @@ local function Init()
|
|||||||
CLEUEventInfo["SPELL_DAMAGE"] = CLEUEventInfo["GENERIC_DAMAGE"]
|
CLEUEventInfo["SPELL_DAMAGE"] = CLEUEventInfo["GENERIC_DAMAGE"]
|
||||||
CLEUEventInfo["SPELL_MISSED"] = CLEUEventInfo["GENERIC_MISSED"]
|
CLEUEventInfo["SPELL_MISSED"] = CLEUEventInfo["GENERIC_MISSED"]
|
||||||
CLEUEventInfo["SPELL_HEAL"] = CLEUEventInfo["GENERIC_HEAL"]
|
CLEUEventInfo["SPELL_HEAL"] = CLEUEventInfo["GENERIC_HEAL"]
|
||||||
CLEUEventInfo["SPELL_HEAL_ABSORBED"] =
|
CLEUEventInfo["SPELL_HEAL_ABSORBED"] = CLEUEventInfo["GENERIC_HEAL_ABSORBED"]
|
||||||
CLEUEventInfo["GENERIC_HEAL_ABSORBED"]
|
|
||||||
CLEUEventInfo["SPELL_ENERGIZE"] = CLEUEventInfo["GENERIC_ENERGIZE"]
|
CLEUEventInfo["SPELL_ENERGIZE"] = CLEUEventInfo["GENERIC_ENERGIZE"]
|
||||||
CLEUEventInfo["SPELL_DRAIN"] = CLEUEventInfo["GENERIC_DRAIN"]
|
CLEUEventInfo["SPELL_DRAIN"] = CLEUEventInfo["GENERIC_DRAIN"]
|
||||||
CLEUEventInfo["SPELL_LEECH"] = CLEUEventInfo["GENERIC_LEECH"]
|
CLEUEventInfo["SPELL_LEECH"] = CLEUEventInfo["GENERIC_LEECH"]
|
||||||
CLEUEventInfo["SPELL_INTERRUPT"] = CLEUEventInfo["GENERIC_INTERRUPT"]
|
CLEUEventInfo["SPELL_INTERRUPT"] = CLEUEventInfo["GENERIC_INTERRUPT"]
|
||||||
CLEUEventInfo["SPELL_DISPEL"] = CLEUEventInfo["GENERIC_DISPEL"]
|
CLEUEventInfo["SPELL_DISPEL"] = CLEUEventInfo["GENERIC_DISPEL"]
|
||||||
CLEUEventInfo["SPELL_DISPEL_FAILED"] =
|
CLEUEventInfo["SPELL_DISPEL_FAILED"] = CLEUEventInfo["GENERIC_DISPEL_FAILED"]
|
||||||
CLEUEventInfo["GENERIC_DISPEL_FAILED"]
|
|
||||||
CLEUEventInfo["SPELL_STOLEN"] = CLEUEventInfo["GENERIC_STOLEN"]
|
CLEUEventInfo["SPELL_STOLEN"] = CLEUEventInfo["GENERIC_STOLEN"]
|
||||||
CLEUEventInfo["SPELL_EXTRA_ATTACKS"] =
|
CLEUEventInfo["SPELL_EXTRA_ATTACKS"] = CLEUEventInfo["GENERIC_EXTRA_ATTACKS"]
|
||||||
CLEUEventInfo["GENERIC_EXTRA_ATTACKS"]
|
|
||||||
CLEUEventInfo["SPELL_AURA_APPLIED"] = CLEUEventInfo["GENERIC_AURA_APPLIED"]
|
CLEUEventInfo["SPELL_AURA_APPLIED"] = CLEUEventInfo["GENERIC_AURA_APPLIED"]
|
||||||
CLEUEventInfo["SPELL_AURA_REMOVED"] = CLEUEventInfo["GENERIC_AURA_REMOVED"]
|
CLEUEventInfo["SPELL_AURA_REMOVED"] = CLEUEventInfo["GENERIC_AURA_REMOVED"]
|
||||||
CLEUEventInfo["SPELL_AURA_APPLIED_DOSE"] =
|
CLEUEventInfo["SPELL_AURA_APPLIED_DOSE"] = CLEUEventInfo["GENERIC_AURA_APPLIED_DOSE"]
|
||||||
CLEUEventInfo["GENERIC_AURA_APPLIED_DOSE"]
|
CLEUEventInfo["SPELL_AURA_REMOVED_DOSE"] = CLEUEventInfo["GENERIC_AURA_REMOVED_DOSE"]
|
||||||
CLEUEventInfo["SPELL_AURA_REMOVED_DOSE"] =
|
|
||||||
CLEUEventInfo["GENERIC_AURA_REMOVED_DOSE"]
|
|
||||||
CLEUEventInfo["SPELL_AURA_REFRESH"] = CLEUEventInfo["GENERIC_AURA_REFRESH"]
|
CLEUEventInfo["SPELL_AURA_REFRESH"] = CLEUEventInfo["GENERIC_AURA_REFRESH"]
|
||||||
CLEUEventInfo["SPELL_AURA_BROKEN"] = CLEUEventInfo["GENERIC_AURA_BROKEN"]
|
CLEUEventInfo["SPELL_AURA_BROKEN"] = CLEUEventInfo["GENERIC_AURA_BROKEN"]
|
||||||
CLEUEventInfo["SPELL_AURA_BROKEN_SPELL"] =
|
CLEUEventInfo["SPELL_AURA_BROKEN_SPELL"] = CLEUEventInfo["GENERIC_AURA_BROKEN_SPELL"]
|
||||||
CLEUEventInfo["GENERIC_AURA_BROKEN_SPELL"]
|
|
||||||
CLEUEventInfo["SPELL_CAST_START"] = CLEUEventInfo["GENERIC_CAST_START"]
|
CLEUEventInfo["SPELL_CAST_START"] = CLEUEventInfo["GENERIC_CAST_START"]
|
||||||
CLEUEventInfo["SPELL_CAST_SUCCESS"] = CLEUEventInfo["GENERIC_CAST_SUCCESS"]
|
CLEUEventInfo["SPELL_CAST_SUCCESS"] = CLEUEventInfo["GENERIC_CAST_SUCCESS"]
|
||||||
CLEUEventInfo["SPELL_CAST_FAILED"] = CLEUEventInfo["GENERIC_CAST_FAILED"]
|
CLEUEventInfo["SPELL_CAST_FAILED"] = CLEUEventInfo["GENERIC_CAST_FAILED"]
|
||||||
@@ -199,39 +181,25 @@ local function Init()
|
|||||||
CLEUEventInfo["SPELL_PERIODIC_DAMAGE"] = CLEUEventInfo["GENERIC_DAMAGE"]
|
CLEUEventInfo["SPELL_PERIODIC_DAMAGE"] = CLEUEventInfo["GENERIC_DAMAGE"]
|
||||||
CLEUEventInfo["SPELL_PERIODIC_MISSED"] = CLEUEventInfo["GENERIC_MISSED"]
|
CLEUEventInfo["SPELL_PERIODIC_MISSED"] = CLEUEventInfo["GENERIC_MISSED"]
|
||||||
CLEUEventInfo["SPELL_PERIODIC_HEAL"] = CLEUEventInfo["GENERIC_HEAL"]
|
CLEUEventInfo["SPELL_PERIODIC_HEAL"] = CLEUEventInfo["GENERIC_HEAL"]
|
||||||
CLEUEventInfo["SPELL_PERIODIC_HEAL_ABSORBED"] =
|
CLEUEventInfo["SPELL_PERIODIC_HEAL_ABSORBED"] = CLEUEventInfo["GENERIC_HEAL_ABSORBED"]
|
||||||
CLEUEventInfo["GENERIC_HEAL_ABSORBED"]
|
|
||||||
CLEUEventInfo["SPELL_PERIODIC_ENERGIZE"] = CLEUEventInfo["GENERIC_ENERGIZE"]
|
CLEUEventInfo["SPELL_PERIODIC_ENERGIZE"] = CLEUEventInfo["GENERIC_ENERGIZE"]
|
||||||
CLEUEventInfo["SPELL_PERIODIC_DRAIN"] = CLEUEventInfo["GENERIC_DRAIN"]
|
CLEUEventInfo["SPELL_PERIODIC_DRAIN"] = CLEUEventInfo["GENERIC_DRAIN"]
|
||||||
CLEUEventInfo["SPELL_PERIODIC_LEECH"] = CLEUEventInfo["GENERIC_LEECH"]
|
CLEUEventInfo["SPELL_PERIODIC_LEECH"] = CLEUEventInfo["GENERIC_LEECH"]
|
||||||
CLEUEventInfo["SPELL_PERIODIC_INTERRUPT"] =
|
CLEUEventInfo["SPELL_PERIODIC_INTERRUPT"] = CLEUEventInfo["GENERIC_INTERRUPT"]
|
||||||
CLEUEventInfo["GENERIC_INTERRUPT"]
|
|
||||||
CLEUEventInfo["SPELL_PERIODIC_DISPEL"] = CLEUEventInfo["GENERIC_DISPEL"]
|
CLEUEventInfo["SPELL_PERIODIC_DISPEL"] = CLEUEventInfo["GENERIC_DISPEL"]
|
||||||
CLEUEventInfo["SPELL_PERIODIC_DISPEL_FAILED"] =
|
CLEUEventInfo["SPELL_PERIODIC_DISPEL_FAILED"] = CLEUEventInfo["GENERIC_DISPEL_FAILED"]
|
||||||
CLEUEventInfo["GENERIC_DISPEL_FAILED"]
|
|
||||||
CLEUEventInfo["SPELL_PERIODIC_STOLEN"] = CLEUEventInfo["GENERIC_STOLEN"]
|
CLEUEventInfo["SPELL_PERIODIC_STOLEN"] = CLEUEventInfo["GENERIC_STOLEN"]
|
||||||
CLEUEventInfo["SPELL_PERIODIC_EXTRA_ATTACKS"] =
|
CLEUEventInfo["SPELL_PERIODIC_EXTRA_ATTACKS"] = CLEUEventInfo["GENERIC_EXTRA_ATTACKS"]
|
||||||
CLEUEventInfo["GENERIC_EXTRA_ATTACKS"]
|
CLEUEventInfo["SPELL_PERIODIC_AURA_APPLIED"] = CLEUEventInfo["GENERIC_AURA_APPLIED"]
|
||||||
CLEUEventInfo["SPELL_PERIODIC_AURA_APPLIED"] =
|
CLEUEventInfo["SPELL_PERIODIC_AURA_REMOVED"] = CLEUEventInfo["GENERIC_AURA_REMOVED"]
|
||||||
CLEUEventInfo["GENERIC_AURA_APPLIED"]
|
CLEUEventInfo["SPELL_PERIODIC_AURA_APPLIED_DOSE"] = CLEUEventInfo["GENERIC_AURA_APPLIED_DOSE"]
|
||||||
CLEUEventInfo["SPELL_PERIODIC_AURA_REMOVED"] =
|
CLEUEventInfo["SPELL_PERIODIC_AURA_REMOVED_DOSE"] = CLEUEventInfo["GENERIC_AURA_REMOVED_DOSE"]
|
||||||
CLEUEventInfo["GENERIC_AURA_REMOVED"]
|
CLEUEventInfo["SPELL_PERIODIC_AURA_REFRESH"] = CLEUEventInfo["GENERIC_AURA_REFRESH"]
|
||||||
CLEUEventInfo["SPELL_PERIODIC_AURA_APPLIED_DOSE"] =
|
CLEUEventInfo["SPELL_PERIODIC_AURA_BROKEN"] = CLEUEventInfo["GENERIC_AURA_BROKEN"]
|
||||||
CLEUEventInfo["GENERIC_AURA_APPLIED_DOSE"]
|
CLEUEventInfo["SPELL_PERIODIC_AURA_BROKEN_SPELL"] = CLEUEventInfo["GENERIC_AURA_BROKEN_SPELL"]
|
||||||
CLEUEventInfo["SPELL_PERIODIC_AURA_REMOVED_DOSE"] =
|
CLEUEventInfo["SPELL_PERIODIC_CAST_START"] = CLEUEventInfo["GENERIC_CAST_START"]
|
||||||
CLEUEventInfo["GENERIC_AURA_REMOVED_DOSE"]
|
CLEUEventInfo["SPELL_PERIODIC_CAST_SUCCESS"] = CLEUEventInfo["GENERIC_CAST_SUCCESS"]
|
||||||
CLEUEventInfo["SPELL_PERIODIC_AURA_REFRESH"] =
|
CLEUEventInfo["SPELL_PERIODIC_CAST_FAILED"] = CLEUEventInfo["GENERIC_CAST_FAILED"]
|
||||||
CLEUEventInfo["GENERIC_AURA_REFRESH"]
|
|
||||||
CLEUEventInfo["SPELL_PERIODIC_AURA_BROKEN"] =
|
|
||||||
CLEUEventInfo["GENERIC_AURA_BROKEN"]
|
|
||||||
CLEUEventInfo["SPELL_PERIODIC_AURA_BROKEN_SPELL"] =
|
|
||||||
CLEUEventInfo["GENERIC_AURA_BROKEN_SPELL"]
|
|
||||||
CLEUEventInfo["SPELL_PERIODIC_CAST_START"] =
|
|
||||||
CLEUEventInfo["GENERIC_CAST_START"]
|
|
||||||
CLEUEventInfo["SPELL_PERIODIC_CAST_SUCCESS"] =
|
|
||||||
CLEUEventInfo["GENERIC_CAST_SUCCESS"]
|
|
||||||
CLEUEventInfo["SPELL_PERIODIC_CAST_FAILED"] =
|
|
||||||
CLEUEventInfo["GENERIC_CAST_FAILED"]
|
|
||||||
|
|
||||||
---@class CLEUParser
|
---@class CLEUParser
|
||||||
CLEUParser = {
|
CLEUParser = {
|
||||||
@@ -239,132 +207,88 @@ local function Init()
|
|||||||
---@return number, nil|string
|
---@return number, nil|string
|
||||||
GetTimestamp = function(...)
|
GetTimestamp = function(...)
|
||||||
local val = select(CLEUEventInfo["GENERIC"]["timestamp"], ...)
|
local val = select(CLEUEventInfo["GENERIC"]["timestamp"], ...)
|
||||||
if val == nil then
|
if val == nil then return 0, "Timestamp is nil or missing" end
|
||||||
return 0, "Timestamp is nil or missing"
|
if type(val) ~= "number" then return 0, "Timestamp is not a number" end
|
||||||
end
|
|
||||||
if type(val) ~= "number" then
|
|
||||||
return 0, "Timestamp is not a number"
|
|
||||||
end
|
|
||||||
return val, nil
|
return val, nil
|
||||||
end,
|
end,
|
||||||
---@param ... any
|
---@param ... any
|
||||||
---@return string, nil|string
|
---@return string, nil|string
|
||||||
GetSubevent = function(...)
|
GetSubevent = function(...)
|
||||||
local val = select(CLEUEventInfo["GENERIC"]["subevent"], ...)
|
local val = select(CLEUEventInfo["GENERIC"]["subevent"], ...)
|
||||||
if val == nil then
|
if val == nil then return "", "Subevent is nil or missing" end
|
||||||
return "", "Subevent is nil or missing"
|
if type(val) ~= "string" then return "", "Subevent is not a string" end
|
||||||
end
|
|
||||||
if type(val) ~= "string" then
|
|
||||||
return "", "Subevent is not a string"
|
|
||||||
end
|
|
||||||
return val, nil
|
return val, nil
|
||||||
end,
|
end,
|
||||||
---@param ... any
|
---@param ... any
|
||||||
---@return boolean, nil|string
|
---@return boolean, nil|string
|
||||||
GetHideCaster = function(...)
|
GetHideCaster = function(...)
|
||||||
local val = select(CLEUEventInfo["GENERIC"]["hideCaster"], ...)
|
local val = select(CLEUEventInfo["GENERIC"]["hideCaster"], ...)
|
||||||
if val == nil then
|
if val == nil then return false, "HideCaster is nil or missing" end
|
||||||
return false, "HideCaster is nil or missing"
|
if type(val) ~= "boolean" then return false, "HideCaster is not a boolean" end
|
||||||
end
|
|
||||||
if type(val) ~= "boolean" then
|
|
||||||
return false, "HideCaster is not a boolean"
|
|
||||||
end
|
|
||||||
return val, nil
|
return val, nil
|
||||||
end,
|
end,
|
||||||
---@param ... any
|
---@param ... any
|
||||||
---@return string, nil|string
|
---@return string, nil|string
|
||||||
GetSourceGUID = function(...)
|
GetSourceGUID = function(...)
|
||||||
local val = select(CLEUEventInfo["GENERIC"]["sourceGUID"], ...)
|
local val = select(CLEUEventInfo["GENERIC"]["sourceGUID"], ...)
|
||||||
if val == nil then
|
if val == nil then return "", "SourceGUID is nil or missing" end
|
||||||
return "", "SourceGUID is nil or missing"
|
if type(val) ~= "string" then return "", "SourceGUID is not a string" end
|
||||||
end
|
|
||||||
if type(val) ~= "string" then
|
|
||||||
return "", "SourceGUID is not a string"
|
|
||||||
end
|
|
||||||
return val, nil
|
return val, nil
|
||||||
end,
|
end,
|
||||||
---@param ... any
|
---@param ... any
|
||||||
---@return string, nil|string
|
---@return string, nil|string
|
||||||
GetSourceName = function(...)
|
GetSourceName = function(...)
|
||||||
local val = select(CLEUEventInfo["GENERIC"]["sourceName"], ...)
|
local val = select(CLEUEventInfo["GENERIC"]["sourceName"], ...)
|
||||||
if val == nil then
|
if val == nil then return "", "SourceName is nil or missing" end
|
||||||
return "", "SourceName is nil or missing"
|
if type(val) ~= "string" then return "", "SourceName is not a string" end
|
||||||
end
|
|
||||||
if type(val) ~= "string" then
|
|
||||||
return "", "SourceName is not a string"
|
|
||||||
end
|
|
||||||
return val, nil
|
return val, nil
|
||||||
end,
|
end,
|
||||||
---@param ... any
|
---@param ... any
|
||||||
---@return number, nil|string
|
---@return number, nil|string
|
||||||
GetSourceFlags = function(...)
|
GetSourceFlags = function(...)
|
||||||
local val = select(CLEUEventInfo["GENERIC"]["sourceFlags"], ...)
|
local val = select(CLEUEventInfo["GENERIC"]["sourceFlags"], ...)
|
||||||
if val == nil then
|
if val == nil then return 0, "SourceFlags is nil or missing" end
|
||||||
return 0, "SourceFlags is nil or missing"
|
if type(val) ~= "number" then return 0, "SourceFlags is not a number" end
|
||||||
end
|
|
||||||
if type(val) ~= "number" then
|
|
||||||
return 0, "SourceFlags is not a number"
|
|
||||||
end
|
|
||||||
return val, nil
|
return val, nil
|
||||||
end,
|
end,
|
||||||
---@param ... any
|
---@param ... any
|
||||||
---@return number, nil|string
|
---@return number, nil|string
|
||||||
GetSourceRaidFlags = function(...)
|
GetSourceRaidFlags = function(...)
|
||||||
local val = select(CLEUEventInfo["GENERIC"]["sourceRaidFlags"], ...)
|
local val = select(CLEUEventInfo["GENERIC"]["sourceRaidFlags"], ...)
|
||||||
if val == nil then
|
if val == nil then return 0, "SourceRaidFlags is nil or missing" end
|
||||||
return 0, "SourceRaidFlags is nil or missing"
|
if type(val) ~= "number" then return 0, "SourceRaidFlags is not a number" end
|
||||||
end
|
|
||||||
if type(val) ~= "number" then
|
|
||||||
return 0, "SourceRaidFlags is not a number"
|
|
||||||
end
|
|
||||||
return val, nil
|
return val, nil
|
||||||
end,
|
end,
|
||||||
---@param ... any
|
---@param ... any
|
||||||
---@return string, nil|string
|
---@return string, nil|string
|
||||||
GetDestGUID = function(...)
|
GetDestGUID = function(...)
|
||||||
local val = select(CLEUEventInfo["GENERIC"]["destGUID"], ...)
|
local val = select(CLEUEventInfo["GENERIC"]["destGUID"], ...)
|
||||||
if val == nil then
|
if val == nil then return "", "DestGUID is nil or missing" end
|
||||||
return "", "DestGUID is nil or missing"
|
if type(val) ~= "string" then return "", "DestGUID is not a string" end
|
||||||
end
|
|
||||||
if type(val) ~= "string" then
|
|
||||||
return "", "DestGUID is not a string"
|
|
||||||
end
|
|
||||||
return val, nil
|
return val, nil
|
||||||
end,
|
end,
|
||||||
---@param ... any
|
---@param ... any
|
||||||
---@return string, nil|string
|
---@return string, nil|string
|
||||||
GetDestName = function(...)
|
GetDestName = function(...)
|
||||||
local val = select(CLEUEventInfo["GENERIC"]["destName"], ...)
|
local val = select(CLEUEventInfo["GENERIC"]["destName"], ...)
|
||||||
if val == nil then
|
if val == nil then return "", "DestName is nil or missing" end
|
||||||
return "", "DestName is nil or missing"
|
if type(val) ~= "string" then return "", "DestName is not a string" end
|
||||||
end
|
|
||||||
if type(val) ~= "string" then
|
|
||||||
return "", "DestName is not a string"
|
|
||||||
end
|
|
||||||
return val, nil
|
return val, nil
|
||||||
end,
|
end,
|
||||||
---@param ... any
|
---@param ... any
|
||||||
---@return number, nil|string
|
---@return number, nil|string
|
||||||
GetDestFlags = function(...)
|
GetDestFlags = function(...)
|
||||||
local val = select(CLEUEventInfo["GENERIC"]["destFlags"], ...)
|
local val = select(CLEUEventInfo["GENERIC"]["destFlags"], ...)
|
||||||
if val == nil then
|
if val == nil then return 0, "DestFlags is nil or missing" end
|
||||||
return 0, "DestFlags is nil or missing"
|
if type(val) ~= "number" then return 0, "DestFlags is not a number" end
|
||||||
end
|
|
||||||
if type(val) ~= "number" then
|
|
||||||
return 0, "DestFlags is not a number"
|
|
||||||
end
|
|
||||||
return val, nil
|
return val, nil
|
||||||
end,
|
end,
|
||||||
---@param ... any
|
---@param ... any
|
||||||
---@return number, nil|string
|
---@return number, nil|string
|
||||||
GetDestRaidFlags = function(...)
|
GetDestRaidFlags = function(...)
|
||||||
local val = select(CLEUEventInfo["GENERIC"]["destRaidFlags"], ...)
|
local val = select(CLEUEventInfo["GENERIC"]["destRaidFlags"], ...)
|
||||||
if val == nil then
|
if val == nil then return 0, "DestRaidFlags is nil or missing" end
|
||||||
return 0, "DestRaidFlags is nil or missing"
|
if type(val) ~= "number" then return 0, "DestRaidFlags is not a number" end
|
||||||
end
|
|
||||||
if type(val) ~= "number" then
|
|
||||||
return 0, "DestRaidFlags is not a number"
|
|
||||||
end
|
|
||||||
return val, nil
|
return val, nil
|
||||||
end,
|
end,
|
||||||
|
|
||||||
@@ -380,9 +304,7 @@ local function Init()
|
|||||||
GetSpellId = function(...)
|
GetSpellId = function(...)
|
||||||
local val = select(CLEUEventInfo["GENERIC_SPELL"]["spellId"], ...)
|
local val = select(CLEUEventInfo["GENERIC_SPELL"]["spellId"], ...)
|
||||||
if val == nil then return 0, "SpellId is nil or missing" end
|
if val == nil then return 0, "SpellId is nil or missing" end
|
||||||
if type(val) ~= "number" then
|
if type(val) ~= "number" then return 0, "SpellId is not a number" end
|
||||||
return 0, "SpellId is not a number"
|
|
||||||
end
|
|
||||||
return val, nil
|
return val, nil
|
||||||
end,
|
end,
|
||||||
--- Specific to subevents prefixed by:
|
--- Specific to subevents prefixed by:
|
||||||
@@ -396,12 +318,8 @@ local function Init()
|
|||||||
---@return string, nil|string
|
---@return string, nil|string
|
||||||
GetSpellName = function(...)
|
GetSpellName = function(...)
|
||||||
local val = select(CLEUEventInfo["GENERIC_SPELL"]["spellName"], ...)
|
local val = select(CLEUEventInfo["GENERIC_SPELL"]["spellName"], ...)
|
||||||
if val == nil then
|
if val == nil then return "", "SpellName is nil or missing" end
|
||||||
return "", "SpellName is nil or missing"
|
if type(val) ~= "string" then return "", "SpellName is not a string" end
|
||||||
end
|
|
||||||
if type(val) ~= "string" then
|
|
||||||
return "", "SpellName is not a string"
|
|
||||||
end
|
|
||||||
return val, nil
|
return val, nil
|
||||||
end,
|
end,
|
||||||
--- Specific to subevents prefixed by:
|
--- Specific to subevents prefixed by:
|
||||||
@@ -414,14 +332,9 @@ local function Init()
|
|||||||
---@param ... any
|
---@param ... any
|
||||||
---@return number, nil|string
|
---@return number, nil|string
|
||||||
GetSpellSchool = function(...)
|
GetSpellSchool = function(...)
|
||||||
local val = select(CLEUEventInfo["GENERIC_SPELL"]["spellSchool"],
|
local val = select(CLEUEventInfo["GENERIC_SPELL"]["spellSchool"], ...)
|
||||||
...)
|
if val == nil then return 0, "SpellSchool is nil or missing" end
|
||||||
if val == nil then
|
if type(val) ~= "number" then return 0, "SpellSchool is not a number" end
|
||||||
return 0, "SpellSchool is nil or missing"
|
|
||||||
end
|
|
||||||
if type(val) ~= "number" then
|
|
||||||
return 0, "SpellSchool is not a number"
|
|
||||||
end
|
|
||||||
return val, nil
|
return val, nil
|
||||||
end,
|
end,
|
||||||
|
|
||||||
@@ -451,15 +364,10 @@ local function Init()
|
|||||||
---@return number, nil|string
|
---@return number, nil|string
|
||||||
GetAmount = function(...)
|
GetAmount = function(...)
|
||||||
local subevent, err = CLEUParser.GetSubevent(...)
|
local subevent, err = CLEUParser.GetSubevent(...)
|
||||||
if err then
|
if err then return 0, string.format("Failed getting subevent due to: %s", err) end
|
||||||
return 0,
|
|
||||||
string.format("Failed getting subevent due to: %s", err)
|
|
||||||
end
|
|
||||||
local val = select(CLEUEventInfo[subevent]["amount"], ...)
|
local val = select(CLEUEventInfo[subevent]["amount"], ...)
|
||||||
if val == nil then return 0, "Amount is nil or missing" end
|
if val == nil then return 0, "Amount is nil or missing" end
|
||||||
if type(val) ~= "number" then
|
if type(val) ~= "number" then return 0, "Amount is not a number" end
|
||||||
return 0, "Amount is not a number"
|
|
||||||
end
|
|
||||||
return val, nil
|
return val, nil
|
||||||
end,
|
end,
|
||||||
--- Specific to subevents prefixed by:
|
--- Specific to subevents prefixed by:
|
||||||
@@ -479,21 +387,12 @@ local function Init()
|
|||||||
---@return number, nil|string
|
---@return number, nil|string
|
||||||
GetOverkill = function(...)
|
GetOverkill = function(...)
|
||||||
local subevent, err = CLEUParser.GetSubevent(...)
|
local subevent, err = CLEUParser.GetSubevent(...)
|
||||||
if err then
|
if err then return 0, string.format("Failed getting subevent due to: %s", err) end
|
||||||
return 0,
|
if not CLEUEventInfo[subevent] then return 0, "Subevent is not a valid event" end
|
||||||
string.format("Failed getting subevent due to: %s", err)
|
if not CLEUEventInfo[subevent]["overkill"] then return 0, "Overkill is nil or missing" end
|
||||||
end
|
|
||||||
if not CLEUEventInfo[subevent] then
|
|
||||||
return 0, "Subevent is not a valid event"
|
|
||||||
end
|
|
||||||
if not CLEUEventInfo[subevent]["overkill"] then
|
|
||||||
return 0, "Overkill is nil or missing"
|
|
||||||
end
|
|
||||||
local val = select(CLEUEventInfo[subevent]["overkill"], ...)
|
local val = select(CLEUEventInfo[subevent]["overkill"], ...)
|
||||||
if val == nil then return 0, "Overkill is nil or missing" end
|
if val == nil then return 0, "Overkill is nil or missing" end
|
||||||
if type(val) ~= "number" then
|
if type(val) ~= "number" then return 0, "Overkill is not a number" end
|
||||||
return 0, "Overkill is not a number"
|
|
||||||
end
|
|
||||||
return val, nil
|
return val, nil
|
||||||
end,
|
end,
|
||||||
--- Specific to subevents prefixed by:
|
--- Specific to subevents prefixed by:
|
||||||
@@ -513,15 +412,10 @@ local function Init()
|
|||||||
---@return number, nil|string
|
---@return number, nil|string
|
||||||
GetSchool = function(...)
|
GetSchool = function(...)
|
||||||
local subevent, err = CLEUParser.GetSubevent(...)
|
local subevent, err = CLEUParser.GetSubevent(...)
|
||||||
if err then
|
if err then return 0, string.format("Failed getting subevent due to: %s", err) end
|
||||||
return 0,
|
|
||||||
string.format("Failed getting subevent due to: %s", err)
|
|
||||||
end
|
|
||||||
local val = select(CLEUEventInfo[subevent]["school"], ...)
|
local val = select(CLEUEventInfo[subevent]["school"], ...)
|
||||||
if val == nil then return 0, "School is nil or missing" end
|
if val == nil then return 0, "School is nil or missing" end
|
||||||
if type(val) ~= "number" then
|
if type(val) ~= "number" then return 0, "School is not a number" end
|
||||||
return 0, "School is not a number"
|
|
||||||
end
|
|
||||||
return val, nil
|
return val, nil
|
||||||
end,
|
end,
|
||||||
--- Specific to subevents prefixed by:
|
--- Specific to subevents prefixed by:
|
||||||
@@ -543,17 +437,10 @@ local function Init()
|
|||||||
---@return boolean, nil|string
|
---@return boolean, nil|string
|
||||||
GetResisted = function(...)
|
GetResisted = function(...)
|
||||||
local subevent, err = CLEUParser.GetSubevent(...)
|
local subevent, err = CLEUParser.GetSubevent(...)
|
||||||
if err then
|
if err then return false, string.format("Failed getting subevent due to: %s", err) end
|
||||||
return false,
|
|
||||||
string.format("Failed getting subevent due to: %s", err)
|
|
||||||
end
|
|
||||||
local val = select(CLEUEventInfo[subevent]["resisted"], ...)
|
local val = select(CLEUEventInfo[subevent]["resisted"], ...)
|
||||||
if val == nil then
|
if val == nil then return false, "Resisted is nil or missing" end
|
||||||
return false, "Resisted is nil or missing"
|
if type(val) ~= "boolean" then return false, "Resisted is not a boolean" end
|
||||||
end
|
|
||||||
if type(val) ~= "boolean" then
|
|
||||||
return false, "Resisted is not a boolean"
|
|
||||||
end
|
|
||||||
return val, nil
|
return val, nil
|
||||||
end,
|
end,
|
||||||
--- Specific to subevents prefixed by:
|
--- Specific to subevents prefixed by:
|
||||||
@@ -575,17 +462,10 @@ local function Init()
|
|||||||
---@return boolean, nil|string
|
---@return boolean, nil|string
|
||||||
GetBlocked = function(...)
|
GetBlocked = function(...)
|
||||||
local subevent, err = CLEUParser.GetSubevent(...)
|
local subevent, err = CLEUParser.GetSubevent(...)
|
||||||
if err then
|
if err then return false, string.format("Failed getting subevent due to: %s", err) end
|
||||||
return false,
|
|
||||||
string.format("Failed getting subevent due to: %s", err)
|
|
||||||
end
|
|
||||||
local val = select(CLEUEventInfo[subevent]["blocked"], ...)
|
local val = select(CLEUEventInfo[subevent]["blocked"], ...)
|
||||||
if val == nil then
|
if val == nil then return false, "Blocked is nil or missing" end
|
||||||
return false, "Blocked is nil or missing"
|
if type(val) ~= "boolean" then return false, "Blocked is not a boolean" end
|
||||||
end
|
|
||||||
if type(val) ~= "boolean" then
|
|
||||||
return false, "Blocked is not a boolean"
|
|
||||||
end
|
|
||||||
return val, nil
|
return val, nil
|
||||||
end,
|
end,
|
||||||
--- Specific to subevents prefixed by:
|
--- Specific to subevents prefixed by:
|
||||||
@@ -608,17 +488,10 @@ local function Init()
|
|||||||
---@return boolean, nil|string
|
---@return boolean, nil|string
|
||||||
GetAbsorbed = function(...)
|
GetAbsorbed = function(...)
|
||||||
local subevent, err = CLEUParser.GetSubevent(...)
|
local subevent, err = CLEUParser.GetSubevent(...)
|
||||||
if err then
|
if err then return false, string.format("Failed getting subevent due to: %s", err) end
|
||||||
return false,
|
|
||||||
string.format("Failed getting subevent due to: %s", err)
|
|
||||||
end
|
|
||||||
local val = select(CLEUEventInfo[subevent]["absorbed"], ...)
|
local val = select(CLEUEventInfo[subevent]["absorbed"], ...)
|
||||||
if val == nil then
|
if val == nil then return false, "Absorbed is nil or missing" end
|
||||||
return false, "Absorbed is nil or missing"
|
if type(val) ~= "boolean" then return false, "Absorbed is not a boolean" end
|
||||||
end
|
|
||||||
if type(val) ~= "boolean" then
|
|
||||||
return false, "Absorbed is not a boolean"
|
|
||||||
end
|
|
||||||
return val, nil
|
return val, nil
|
||||||
end,
|
end,
|
||||||
--- Specific to subevents prefixed by:
|
--- Specific to subevents prefixed by:
|
||||||
@@ -640,17 +513,10 @@ local function Init()
|
|||||||
---@return boolean, nil|string
|
---@return boolean, nil|string
|
||||||
GetCritical = function(...)
|
GetCritical = function(...)
|
||||||
local subevent, err = CLEUParser.GetSubevent(...)
|
local subevent, err = CLEUParser.GetSubevent(...)
|
||||||
if err then
|
if err then return false, string.format("Failed getting subevent due to: %s", err) end
|
||||||
return false,
|
|
||||||
string.format("Failed getting subevent due to: %s", err)
|
|
||||||
end
|
|
||||||
local val = select(CLEUEventInfo[subevent]["critical"], ...)
|
local val = select(CLEUEventInfo[subevent]["critical"], ...)
|
||||||
if val == nil then
|
if val == nil then return false, "Critical is nil or missing" end
|
||||||
return false, "Critical is nil or missing"
|
if type(val) ~= "boolean" then return false, "Critical is not a boolean" end
|
||||||
end
|
|
||||||
if type(val) ~= "boolean" then
|
|
||||||
return false, "Critical is not a boolean"
|
|
||||||
end
|
|
||||||
return val, nil
|
return val, nil
|
||||||
end,
|
end,
|
||||||
--- Specific to subevents prefixed by:
|
--- Specific to subevents prefixed by:
|
||||||
@@ -670,17 +536,10 @@ local function Init()
|
|||||||
---@return boolean, nil|string
|
---@return boolean, nil|string
|
||||||
GetGlancing = function(...)
|
GetGlancing = function(...)
|
||||||
local subevent, err = CLEUParser.GetSubevent(...)
|
local subevent, err = CLEUParser.GetSubevent(...)
|
||||||
if err then
|
if err then return false, string.format("Failed getting subevent due to: %s", err) end
|
||||||
return false,
|
|
||||||
string.format("Failed getting subevent due to: %s", err)
|
|
||||||
end
|
|
||||||
local val = select(CLEUEventInfo[subevent]["glancing"], ...)
|
local val = select(CLEUEventInfo[subevent]["glancing"], ...)
|
||||||
if val == nil then
|
if val == nil then return false, "Glancing is nil or missing" end
|
||||||
return false, "Glancing is nil or missing"
|
if type(val) ~= "boolean" then return false, "Glancing is not a boolean" end
|
||||||
end
|
|
||||||
if type(val) ~= "boolean" then
|
|
||||||
return false, "Glancing is not a boolean"
|
|
||||||
end
|
|
||||||
return val, nil
|
return val, nil
|
||||||
end,
|
end,
|
||||||
--- Specific to subevents prefixed by:
|
--- Specific to subevents prefixed by:
|
||||||
@@ -700,17 +559,10 @@ local function Init()
|
|||||||
---@return boolean, nil|string
|
---@return boolean, nil|string
|
||||||
GetCrushing = function(...)
|
GetCrushing = function(...)
|
||||||
local subevent, err = CLEUParser.GetSubevent(...)
|
local subevent, err = CLEUParser.GetSubevent(...)
|
||||||
if err then
|
if err then return false, string.format("Failed getting subevent due to: %s", err) end
|
||||||
return false,
|
|
||||||
string.format("Failed getting subevent due to: %s", err)
|
|
||||||
end
|
|
||||||
local val = select(CLEUEventInfo[subevent]["crushing"], ...)
|
local val = select(CLEUEventInfo[subevent]["crushing"], ...)
|
||||||
if val == nil then
|
if val == nil then return false, "Crushing is nil or missing" end
|
||||||
return false, "Crushing is nil or missing"
|
if type(val) ~= "boolean" then return false, "Crushing is not a boolean" end
|
||||||
end
|
|
||||||
if type(val) ~= "boolean" then
|
|
||||||
return false, "Crushing is not a boolean"
|
|
||||||
end
|
|
||||||
return val, nil
|
return val, nil
|
||||||
end,
|
end,
|
||||||
--- Specific to subevents prefixed by:
|
--- Specific to subevents prefixed by:
|
||||||
@@ -731,17 +583,10 @@ local function Init()
|
|||||||
---@return boolean, nil|string
|
---@return boolean, nil|string
|
||||||
GetIsOffHand = function(...)
|
GetIsOffHand = function(...)
|
||||||
local subevent, err = CLEUParser.GetSubevent(...)
|
local subevent, err = CLEUParser.GetSubevent(...)
|
||||||
if err then
|
if err then return false, string.format("Failed getting subevent due to: %s", err) end
|
||||||
return false,
|
|
||||||
string.format("Failed getting subevent due to: %s", err)
|
|
||||||
end
|
|
||||||
local val = select(CLEUEventInfo[subevent]["isOffHand"], ...)
|
local val = select(CLEUEventInfo[subevent]["isOffHand"], ...)
|
||||||
if val == nil then
|
if val == nil then return false, "IsOffHand is nil or missing" end
|
||||||
return false, "IsOffHand is nil or missing"
|
if type(val) ~= "boolean" then return false, "IsOffHand is not a boolean" end
|
||||||
end
|
|
||||||
if type(val) ~= "boolean" then
|
|
||||||
return false, "IsOffHand is not a boolean"
|
|
||||||
end
|
|
||||||
return val, nil
|
return val, nil
|
||||||
end,
|
end,
|
||||||
|
|
||||||
@@ -764,17 +609,10 @@ local function Init()
|
|||||||
---@return string, nil|string
|
---@return string, nil|string
|
||||||
GetMissType = function(...)
|
GetMissType = function(...)
|
||||||
local subevent, err = CLEUParser.GetSubevent(...)
|
local subevent, err = CLEUParser.GetSubevent(...)
|
||||||
if err then
|
if err then return "", string.format("Failed getting subevent due to: %s", err) end
|
||||||
return "",
|
|
||||||
string.format("Failed getting subevent due to: %s", err)
|
|
||||||
end
|
|
||||||
local val = select(CLEUEventInfo[subevent]["missType"], ...)
|
local val = select(CLEUEventInfo[subevent]["missType"], ...)
|
||||||
if val == nil then
|
if val == nil then return "", "MissType is nil or missing" end
|
||||||
return "", "MissType is nil or missing"
|
if type(val) ~= "string" then return "", "MissType is not a string" end
|
||||||
end
|
|
||||||
if type(val) ~= "string" then
|
|
||||||
return "", "MissType is not a string"
|
|
||||||
end
|
|
||||||
return val, nil
|
return val, nil
|
||||||
end,
|
end,
|
||||||
|
|
||||||
@@ -797,17 +635,10 @@ local function Init()
|
|||||||
--- return type is unconfirmed!
|
--- return type is unconfirmed!
|
||||||
GetAmountMissed = function(...)
|
GetAmountMissed = function(...)
|
||||||
local subevent, err = CLEUParser.GetSubevent(...)
|
local subevent, err = CLEUParser.GetSubevent(...)
|
||||||
if err then
|
if err then return 0, string.format("Failed getting subevent due to: %s", err) end
|
||||||
return 0,
|
|
||||||
string.format("Failed getting subevent due to: %s", err)
|
|
||||||
end
|
|
||||||
local val = select(CLEUEventInfo[subevent]["amountMissed"], ...)
|
local val = select(CLEUEventInfo[subevent]["amountMissed"], ...)
|
||||||
if val == nil then
|
if val == nil then return 0, "AmountMissed is nil or missing" end
|
||||||
return 0, "AmountMissed is nil or missing"
|
if type(val) ~= "number" then return 0, "AmountMissed is not a number" end
|
||||||
end
|
|
||||||
if type(val) ~= "number" then
|
|
||||||
return 0, "AmountMissed is not a number"
|
|
||||||
end
|
|
||||||
return val, nil
|
return val, nil
|
||||||
end,
|
end,
|
||||||
|
|
||||||
@@ -830,17 +661,10 @@ local function Init()
|
|||||||
---@return number, nil|string
|
---@return number, nil|string
|
||||||
GetOverhealing = function(...)
|
GetOverhealing = function(...)
|
||||||
local subevent, err = CLEUParser.GetSubevent(...)
|
local subevent, err = CLEUParser.GetSubevent(...)
|
||||||
if err then
|
if err then return 0, string.format("Failed getting subevent due to: %s", err) end
|
||||||
return 0,
|
|
||||||
string.format("Failed getting subevent due to: %s", err)
|
|
||||||
end
|
|
||||||
local val = select(CLEUEventInfo[subevent]["overhealing"], ...)
|
local val = select(CLEUEventInfo[subevent]["overhealing"], ...)
|
||||||
if val == nil then
|
if val == nil then return 0, "Overhealing is nil or missing" end
|
||||||
return 0, "Overhealing is nil or missing"
|
if type(val) ~= "number" then return 0, "Overhealing is not a number" end
|
||||||
end
|
|
||||||
if type(val) ~= "number" then
|
|
||||||
return 0, "Overhealing is not a number"
|
|
||||||
end
|
|
||||||
return val, nil
|
return val, nil
|
||||||
end,
|
end,
|
||||||
|
|
||||||
@@ -861,17 +685,10 @@ local function Init()
|
|||||||
---@return string, nil|string
|
---@return string, nil|string
|
||||||
GetExtraGUID = function(...)
|
GetExtraGUID = function(...)
|
||||||
local subevent, err = CLEUParser.GetSubevent(...)
|
local subevent, err = CLEUParser.GetSubevent(...)
|
||||||
if err then
|
if err then return "", string.format("Failed getting subevent due to: %s", err) end
|
||||||
return "",
|
|
||||||
string.format("Failed getting subevent due to: %s", err)
|
|
||||||
end
|
|
||||||
local val = select(CLEUEventInfo[subevent]["extraGUID"], ...)
|
local val = select(CLEUEventInfo[subevent]["extraGUID"], ...)
|
||||||
if val == nil then
|
if val == nil then return "", "ExtraGUID is nil or missing" end
|
||||||
return "", "ExtraGUID is nil or missing"
|
if type(val) ~= "string" then return "", "ExtraGUID is not a string" end
|
||||||
end
|
|
||||||
if type(val) ~= "string" then
|
|
||||||
return "", "ExtraGUID is not a string"
|
|
||||||
end
|
|
||||||
return val, nil
|
return val, nil
|
||||||
end,
|
end,
|
||||||
|
|
||||||
@@ -892,17 +709,10 @@ local function Init()
|
|||||||
---@return string, nil|string
|
---@return string, nil|string
|
||||||
GetExtraName = function(...)
|
GetExtraName = function(...)
|
||||||
local subevent, err = CLEUParser.GetSubevent(...)
|
local subevent, err = CLEUParser.GetSubevent(...)
|
||||||
if err then
|
if err then return "", string.format("Failed getting subevent due to: %s", err) end
|
||||||
return "",
|
|
||||||
string.format("Failed getting subevent due to: %s", err)
|
|
||||||
end
|
|
||||||
local val = select(CLEUEventInfo[subevent]["extraName"], ...)
|
local val = select(CLEUEventInfo[subevent]["extraName"], ...)
|
||||||
if val == nil then
|
if val == nil then return "", "ExtraName is nil or missing" end
|
||||||
return "", "ExtraName is nil or missing"
|
if type(val) ~= "string" then return "", "ExtraName is not a string" end
|
||||||
end
|
|
||||||
if type(val) ~= "string" then
|
|
||||||
return "", "ExtraName is not a string"
|
|
||||||
end
|
|
||||||
return val, nil
|
return val, nil
|
||||||
end,
|
end,
|
||||||
|
|
||||||
@@ -923,17 +733,10 @@ local function Init()
|
|||||||
---@return number, nil|string
|
---@return number, nil|string
|
||||||
GetExtraFlags = function(...)
|
GetExtraFlags = function(...)
|
||||||
local subevent, err = CLEUParser.GetSubevent(...)
|
local subevent, err = CLEUParser.GetSubevent(...)
|
||||||
if err then
|
if err then return 0, string.format("Failed getting subevent due to: %s", err) end
|
||||||
return 0,
|
|
||||||
string.format("Failed getting subevent due to: %s", err)
|
|
||||||
end
|
|
||||||
local val = select(CLEUEventInfo[subevent]["extraFlags"], ...)
|
local val = select(CLEUEventInfo[subevent]["extraFlags"], ...)
|
||||||
if val == nil then
|
if val == nil then return 0, "ExtraFlags is nil or missing" end
|
||||||
return 0, "ExtraFlags is nil or missing"
|
if type(val) ~= "number" then return 0, "ExtraFlags is not a number" end
|
||||||
end
|
|
||||||
if type(val) ~= "number" then
|
|
||||||
return 0, "ExtraFlags is not a number"
|
|
||||||
end
|
|
||||||
return val, nil
|
return val, nil
|
||||||
end,
|
end,
|
||||||
|
|
||||||
@@ -954,17 +757,10 @@ local function Init()
|
|||||||
---@return number, nil|string
|
---@return number, nil|string
|
||||||
GetExtraRaidFlags = function(...)
|
GetExtraRaidFlags = function(...)
|
||||||
local subevent, err = CLEUParser.GetSubevent(...)
|
local subevent, err = CLEUParser.GetSubevent(...)
|
||||||
if err then
|
if err then return 0, string.format("Failed getting subevent due to: %s", err) end
|
||||||
return 0,
|
|
||||||
string.format("Failed getting subevent due to: %s", err)
|
|
||||||
end
|
|
||||||
local val = select(CLEUEventInfo[subevent]["extraRaidFlags"], ...)
|
local val = select(CLEUEventInfo[subevent]["extraRaidFlags"], ...)
|
||||||
if val == nil then
|
if val == nil then return 0, "ExtraRaidFlags is nil or missing" end
|
||||||
return 0, "ExtraRaidFlags is nil or missing"
|
if type(val) ~= "number" then return 0, "ExtraRaidFlags is not a number" end
|
||||||
end
|
|
||||||
if type(val) ~= "number" then
|
|
||||||
return 0, "ExtraRaidFlags is not a number"
|
|
||||||
end
|
|
||||||
return val, nil
|
return val, nil
|
||||||
end,
|
end,
|
||||||
|
|
||||||
@@ -989,17 +785,10 @@ local function Init()
|
|||||||
---@return number, nil|string
|
---@return number, nil|string
|
||||||
GetExtraSpellID = function(...)
|
GetExtraSpellID = function(...)
|
||||||
local subevent, err = CLEUParser.GetSubevent(...)
|
local subevent, err = CLEUParser.GetSubevent(...)
|
||||||
if err then
|
if err then return 0, string.format("Failed getting subevent due to: %s", err) end
|
||||||
return 0,
|
|
||||||
string.format("Failed getting subevent due to: %s", err)
|
|
||||||
end
|
|
||||||
local val = select(CLEUEventInfo[subevent]["extraSpellID"], ...)
|
local val = select(CLEUEventInfo[subevent]["extraSpellID"], ...)
|
||||||
if val == nil then
|
if val == nil then return 0, "ExtraSpellID is nil or missing" end
|
||||||
return 0, "ExtraSpellID is nil or missing"
|
if type(val) ~= "number" then return 0, "ExtraSpellID is not a number" end
|
||||||
end
|
|
||||||
if type(val) ~= "number" then
|
|
||||||
return 0, "ExtraSpellID is not a number"
|
|
||||||
end
|
|
||||||
return val, nil
|
return val, nil
|
||||||
end,
|
end,
|
||||||
|
|
||||||
@@ -1025,17 +814,10 @@ local function Init()
|
|||||||
---@return string, nil|string
|
---@return string, nil|string
|
||||||
GetExtraSpellName = function(...)
|
GetExtraSpellName = function(...)
|
||||||
local subevent, err = CLEUParser.GetSubevent(...)
|
local subevent, err = CLEUParser.GetSubevent(...)
|
||||||
if err then
|
if err then return "", string.format("Failed getting subevent due to: %s", err) end
|
||||||
return "",
|
|
||||||
string.format("Failed getting subevent due to: %s", err)
|
|
||||||
end
|
|
||||||
local val = select(CLEUEventInfo[subevent]["extraSpellName"], ...)
|
local val = select(CLEUEventInfo[subevent]["extraSpellName"], ...)
|
||||||
if val == nil then
|
if val == nil then return "", "extraSpellName is nil or missing" end
|
||||||
return "", "extraSpellName is nil or missing"
|
if type(val) ~= "string" then return "", "extraSpellName is not a string" end
|
||||||
end
|
|
||||||
if type(val) ~= "string" then
|
|
||||||
return "", "extraSpellName is not a string"
|
|
||||||
end
|
|
||||||
return val, nil
|
return val, nil
|
||||||
end,
|
end,
|
||||||
|
|
||||||
@@ -1061,17 +843,10 @@ local function Init()
|
|||||||
---@return number, nil|string
|
---@return number, nil|string
|
||||||
GetExtraSchool = function(...)
|
GetExtraSchool = function(...)
|
||||||
local subevent, err = CLEUParser.GetSubevent(...)
|
local subevent, err = CLEUParser.GetSubevent(...)
|
||||||
if err then
|
if err then return 0, string.format("Failed getting subevent due to: %s", err) end
|
||||||
return 0,
|
|
||||||
string.format("Failed getting subevent due to: %s", err)
|
|
||||||
end
|
|
||||||
local val = select(CLEUEventInfo[subevent]["extraSchool"], ...)
|
local val = select(CLEUEventInfo[subevent]["extraSchool"], ...)
|
||||||
if val == nil then
|
if val == nil then return 0, "ExtraSchool is nil or missing" end
|
||||||
return 0, "ExtraSchool is nil or missing"
|
if type(val) ~= "number" then return 0, "ExtraSchool is not a number" end
|
||||||
end
|
|
||||||
if type(val) ~= "number" then
|
|
||||||
return 0, "ExtraSchool is not a number"
|
|
||||||
end
|
|
||||||
return val, nil
|
return val, nil
|
||||||
end,
|
end,
|
||||||
|
|
||||||
@@ -1092,17 +867,10 @@ local function Init()
|
|||||||
---@return number, nil|string
|
---@return number, nil|string
|
||||||
GetAbsorbedAmount = function(...)
|
GetAbsorbedAmount = function(...)
|
||||||
local subevent, err = CLEUParser.GetSubevent(...)
|
local subevent, err = CLEUParser.GetSubevent(...)
|
||||||
if err then
|
if err then return 0, string.format("Failed getting subevent due to: %s", err) end
|
||||||
return 0,
|
|
||||||
string.format("Failed getting subevent due to: %s", err)
|
|
||||||
end
|
|
||||||
local val = select(CLEUEventInfo[subevent]["absorbedAmount"], ...)
|
local val = select(CLEUEventInfo[subevent]["absorbedAmount"], ...)
|
||||||
if val == nil then
|
if val == nil then return 0, "AbsorbedAmount is nil or missing" end
|
||||||
return 0, "AbsorbedAmount is nil or missing"
|
if type(val) ~= "number" then return 0, "AbsorbedAmount is not a number" end
|
||||||
end
|
|
||||||
if type(val) ~= "number" then
|
|
||||||
return 0, "AbsorbedAmount is not a number"
|
|
||||||
end
|
|
||||||
return val, nil
|
return val, nil
|
||||||
end,
|
end,
|
||||||
|
|
||||||
@@ -1123,17 +891,10 @@ local function Init()
|
|||||||
---@return number, nil|string
|
---@return number, nil|string
|
||||||
GetOverEnergize = function(...)
|
GetOverEnergize = function(...)
|
||||||
local subevent, err = CLEUParser.GetSubevent(...)
|
local subevent, err = CLEUParser.GetSubevent(...)
|
||||||
if err then
|
if err then return 0, string.format("Failed getting subevent due to: %s", err) end
|
||||||
return 0,
|
|
||||||
string.format("Failed getting subevent due to: %s", err)
|
|
||||||
end
|
|
||||||
local val = select(CLEUEventInfo[subevent]["overEnergize"], ...)
|
local val = select(CLEUEventInfo[subevent]["overEnergize"], ...)
|
||||||
if val == nil then
|
if val == nil then return 0, "OverEnergize is nil or missing" end
|
||||||
return 0, "OverEnergize is nil or missing"
|
if type(val) ~= "number" then return 0, "OverEnergize is not a number" end
|
||||||
end
|
|
||||||
if type(val) ~= "number" then
|
|
||||||
return 0, "OverEnergize is not a number"
|
|
||||||
end
|
|
||||||
return val, nil
|
return val, nil
|
||||||
end,
|
end,
|
||||||
|
|
||||||
@@ -1158,17 +919,10 @@ local function Init()
|
|||||||
---@return number, nil|string
|
---@return number, nil|string
|
||||||
GetPowerType = function(...)
|
GetPowerType = function(...)
|
||||||
local subevent, err = CLEUParser.GetSubevent(...)
|
local subevent, err = CLEUParser.GetSubevent(...)
|
||||||
if err then
|
if err then return 0, string.format("Failed getting subevent due to: %s", err) end
|
||||||
return 0,
|
|
||||||
string.format("Failed getting subevent due to: %s", err)
|
|
||||||
end
|
|
||||||
local val = select(CLEUEventInfo[subevent]["powerType"], ...)
|
local val = select(CLEUEventInfo[subevent]["powerType"], ...)
|
||||||
if val == nil then
|
if val == nil then return 0, "PowerType is nil or missing" end
|
||||||
return 0, "PowerType is nil or missing"
|
if type(val) ~= "number" then return 0, "PowerType is not a number" end
|
||||||
end
|
|
||||||
if type(val) ~= "number" then
|
|
||||||
return 0, "PowerType is not a number"
|
|
||||||
end
|
|
||||||
return val, nil
|
return val, nil
|
||||||
end,
|
end,
|
||||||
|
|
||||||
@@ -1190,17 +944,10 @@ local function Init()
|
|||||||
---@return number, nil|string
|
---@return number, nil|string
|
||||||
GetExtraAmount = function(...)
|
GetExtraAmount = function(...)
|
||||||
local subevent, err = CLEUParser.GetSubevent(...)
|
local subevent, err = CLEUParser.GetSubevent(...)
|
||||||
if err then
|
if err then return 0, string.format("Failed getting subevent due to: %s", err) end
|
||||||
return 0,
|
|
||||||
string.format("Failed getting subevent due to: %s", err)
|
|
||||||
end
|
|
||||||
local val = select(CLEUEventInfo[subevent]["extraAmount"], ...)
|
local val = select(CLEUEventInfo[subevent]["extraAmount"], ...)
|
||||||
if val == nil then
|
if val == nil then return 0, "ExtraAmount is nil or missing" end
|
||||||
return 0, "ExtraAmount is nil or missing"
|
if type(val) ~= "number" then return 0, "ExtraAmount is not a number" end
|
||||||
end
|
|
||||||
if type(val) ~= "number" then
|
|
||||||
return 0, "ExtraAmount is not a number"
|
|
||||||
end
|
|
||||||
return val, nil
|
return val, nil
|
||||||
end,
|
end,
|
||||||
|
|
||||||
@@ -1229,17 +976,10 @@ local function Init()
|
|||||||
---@return number, nil|string
|
---@return number, nil|string
|
||||||
GetExtraSpellId = function(...)
|
GetExtraSpellId = function(...)
|
||||||
local subevent, err = CLEUParser.GetSubevent(...)
|
local subevent, err = CLEUParser.GetSubevent(...)
|
||||||
if err then
|
if err then return 0, string.format("Failed getting subevent due to: %s", err) end
|
||||||
return 0,
|
|
||||||
string.format("Failed getting subevent due to: %s", err)
|
|
||||||
end
|
|
||||||
local val = select(CLEUEventInfo[subevent]["extraSpellId"], ...)
|
local val = select(CLEUEventInfo[subevent]["extraSpellId"], ...)
|
||||||
if val == nil then
|
if val == nil then return 0, "ExtraSpellId is nil or missing" end
|
||||||
return 0, "ExtraSpellId is nil or missing"
|
if type(val) ~= "number" then return 0, "ExtraSpellId is not a number" end
|
||||||
end
|
|
||||||
if type(val) ~= "number" then
|
|
||||||
return 0, "ExtraSpellId is not a number"
|
|
||||||
end
|
|
||||||
return val, nil
|
return val, nil
|
||||||
end,
|
end,
|
||||||
|
|
||||||
@@ -1268,17 +1008,12 @@ local function Init()
|
|||||||
---@return number, nil|string
|
---@return number, nil|string
|
||||||
GetExtraAuraType = function(...)
|
GetExtraAuraType = function(...)
|
||||||
local subevent, err = CLEUParser.GetSubevent(...)
|
local subevent, err = CLEUParser.GetSubevent(...)
|
||||||
if err then
|
if err then return 0, string.format("Failed getting subevent due to: %s", err) end
|
||||||
return 0,
|
|
||||||
string.format("Failed getting subevent due to: %s", err)
|
|
||||||
end
|
|
||||||
local val = select(CLEUEventInfo[subevent]["auraType"], ...)
|
local val = select(CLEUEventInfo[subevent]["auraType"], ...)
|
||||||
if val == nil then return 0, "AuraType is nil or missing" end
|
if val == nil then return 0, "AuraType is nil or missing" end
|
||||||
if type(val) ~= "number" then
|
if type(val) ~= "number" then return 0, "AuraType is not a number" end
|
||||||
return 0, "AuraType is not a number"
|
|
||||||
end
|
|
||||||
return val, nil
|
return val, nil
|
||||||
end
|
end,
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -1286,7 +1021,5 @@ local frame = CreateFrame("Frame")
|
|||||||
frame:RegisterEvent("PLAYER_LOGIN")
|
frame:RegisterEvent("PLAYER_LOGIN")
|
||||||
frame:RegisterEvent("PLAYER_ENTERING_WORLD")
|
frame:RegisterEvent("PLAYER_ENTERING_WORLD")
|
||||||
frame:RegisterEvent("GUILD_ROSTER_UPDATE")
|
frame:RegisterEvent("GUILD_ROSTER_UPDATE")
|
||||||
frame:SetScript("OnEvent", function(self, event, ...)
|
frame:SetScript("OnEvent", function(self, event, ...) Init() end)
|
||||||
Init()
|
|
||||||
end)
|
|
||||||
Init()
|
Init()
|
49
Modules/ChatSniffer.lua
Normal file
49
Modules/ChatSniffer.lua
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
local _, shared = ...
|
||||||
|
---@cast shared HeimdallShared
|
||||||
|
local ModuleName = "ChatSniffer"
|
||||||
|
|
||||||
|
---@class HeimdallChatSnifferConfig
|
||||||
|
---@field enabled boolean
|
||||||
|
---@field debug boolean
|
||||||
|
|
||||||
|
---@class ChatSniffer
|
||||||
|
shared.ChatSniffer = {
|
||||||
|
Init = function()
|
||||||
|
Heimdall_Chat = Heimdall_Chat or {}
|
||||||
|
local frame = CreateFrame("Frame")
|
||||||
|
frame:RegisterEvent("CHAT_MSG_SAY")
|
||||||
|
frame:RegisterEvent("CHAT_MSG_YELL")
|
||||||
|
frame:RegisterEvent("CHAT_MSG_CHANNEL")
|
||||||
|
frame:RegisterEvent("CHAT_MSG_WHISPER")
|
||||||
|
frame:RegisterEvent("CHAT_MSG_CHANNEL_JOIN")
|
||||||
|
frame:RegisterEvent("CHAT_MSG_CHANNEL_LEAVE")
|
||||||
|
frame:RegisterEvent("CHAT_MSG_EMOTE")
|
||||||
|
frame:RegisterEvent("CHAT_MSG_PARTY")
|
||||||
|
frame:RegisterEvent("CHAT_MSG_PARTY_LEADER")
|
||||||
|
frame:RegisterEvent("CHAT_MSG_RAID")
|
||||||
|
frame:RegisterEvent("CHAT_MSG_RAID_LEADER")
|
||||||
|
frame:RegisterEvent("CHAT_MSG_RAID_WARNING")
|
||||||
|
frame:RegisterEvent("CHAT_MSG_SYSTEM")
|
||||||
|
frame:RegisterEvent("CHAT_MSG_TEXT_EMOTE")
|
||||||
|
frame:RegisterEvent("CHAT_MSG_YELL")
|
||||||
|
frame:SetScript("OnEvent", function(self, event, msg, sender, language, channel)
|
||||||
|
if not Heimdall_Data.config.chatSniffer.enabled then return end
|
||||||
|
if not Heimdall_Data.config.chatSniffer.debug then
|
||||||
|
shared.dump(string.format("[%s] got message", { event, msg, sender, language, channel }))
|
||||||
|
end
|
||||||
|
local timestamp = date("%Y-%m-%d %H:%M:%S")
|
||||||
|
local log = string.format(
|
||||||
|
"%s|%s|%s|%s|%s|%s",
|
||||||
|
tostring(timestamp),
|
||||||
|
tostring(event),
|
||||||
|
tostring(sender),
|
||||||
|
tostring(msg),
|
||||||
|
tostring(language),
|
||||||
|
tostring(channel)
|
||||||
|
)
|
||||||
|
Heimdall_Chat[#Heimdall_Chat + 1] = log
|
||||||
|
end)
|
||||||
|
|
||||||
|
print(string.format("[%s] Module initialized", ModuleName))
|
||||||
|
end,
|
||||||
|
}
|
@@ -1,49 +1,141 @@
|
|||||||
local addonname, shared = ...
|
local _, shared = ...
|
||||||
---@cast shared HeimdallShared
|
---@cast shared HeimdallShared
|
||||||
---@cast addonname string
|
local ModuleName = "CombatAlerter"
|
||||||
|
|
||||||
---@diagnostic disable-next-line: missing-fields
|
---@class HeimdallCombatAlerterConfig
|
||||||
shared.CombatAlerter = {}
|
---@field enabled boolean
|
||||||
function shared.CombatAlerter.Init()
|
---@field debug boolean
|
||||||
|
---@field channels string[]
|
||||||
|
|
||||||
|
---@class CombatAlerter
|
||||||
|
shared.CombatAlerter = {
|
||||||
|
Init = function()
|
||||||
local alerted = {}
|
local alerted = {}
|
||||||
local combatAlerterFrame = CreateFrame("Frame")
|
local combatAlerterFrame = CreateFrame("Frame")
|
||||||
combatAlerterFrame:RegisterEvent("COMBAT_LOG_EVENT_UNFILTERED")
|
combatAlerterFrame:RegisterEvent("COMBAT_LOG_EVENT_UNFILTERED")
|
||||||
combatAlerterFrame:SetScript("OnEvent", function(self, event, ...)
|
combatAlerterFrame:SetScript("OnEvent", function(self, event, ...)
|
||||||
if not Heimdall_Data.config.combatAlerter.enabled then return end
|
if Heimdall_Data.config.combatAlerter.debug then
|
||||||
local destination, err = CLEUParser.GetDestName(...)
|
print(string.format("[%s] Combat log event received", ModuleName))
|
||||||
if err then return end
|
end
|
||||||
if destination ~= UnitName("player") then return end
|
if not Heimdall_Data.config.combatAlerter.enabled then
|
||||||
local source, err = CLEUParser.GetSourceName(...)
|
if Heimdall_Data.config.combatAlerter.debug then
|
||||||
if err then source = "unknown" end
|
print(string.format("[%s] Module disabled, ignoring combat event", ModuleName))
|
||||||
|
end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
if shared.stinkyTracker.stinkies and shared.stinkyTracker.stinkies[source] then
|
---@type string|nil, string, string
|
||||||
|
local err, source, destination
|
||||||
|
|
||||||
|
destination, err = CLEUParser.GetDestName(...)
|
||||||
|
if err then
|
||||||
|
if Heimdall_Data.config.combatAlerter.debug then
|
||||||
|
print(string.format("[%s] Error getting destination: %s", ModuleName, err))
|
||||||
|
end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
if Heimdall_Data.config.combatAlerter.debug then
|
||||||
|
print(string.format("[%s] Combat event destination: %s", ModuleName, destination))
|
||||||
|
end
|
||||||
|
|
||||||
|
if destination ~= UnitName("player") then
|
||||||
|
if Heimdall_Data.config.combatAlerter.debug then
|
||||||
|
print(string.format("[%s] Ignoring event - not targeted at player", ModuleName))
|
||||||
|
end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
source, err = CLEUParser.GetSourceName(...)
|
||||||
|
if err then
|
||||||
|
if Heimdall_Data.config.combatAlerter.debug then
|
||||||
|
print(string.format("[%s] Error getting source, using 'unknown': %s", ModuleName, err))
|
||||||
|
end
|
||||||
|
source = "unknown"
|
||||||
|
end
|
||||||
|
|
||||||
|
if Heimdall_Data.config.combatAlerter.debug then
|
||||||
|
print(string.format("[%s] Combat event source: %s", ModuleName, source))
|
||||||
|
end
|
||||||
|
|
||||||
|
if shared.StinkyTracker.IsStinky(source) then
|
||||||
|
if Heimdall_Data.config.combatAlerter.debug then
|
||||||
|
print(
|
||||||
|
string.format(
|
||||||
|
"[%s] Source is tracked stinky: %s (Already alerted: %s)",
|
||||||
|
ModuleName,
|
||||||
|
source,
|
||||||
|
tostring(alerted[source] or false)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
end
|
||||||
if alerted[source] then return end
|
if alerted[source] then return end
|
||||||
|
|
||||||
alerted[source] = true
|
alerted[source] = true
|
||||||
local x, y = GetPlayerMapPosition("player")
|
local x, y = GetPlayerMapPosition("player")
|
||||||
|
local zone, subZone = GetZoneText(), GetSubZoneText()
|
||||||
|
|
||||||
|
if Heimdall_Data.config.combatAlerter.debug then
|
||||||
|
print(
|
||||||
|
string.format(
|
||||||
|
"[%s] Player location: %s/%s at %.2f,%.2f",
|
||||||
|
ModuleName,
|
||||||
|
zone,
|
||||||
|
subZone,
|
||||||
|
x * 100,
|
||||||
|
y * 100
|
||||||
|
)
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
SetMapToCurrentZone()
|
||||||
|
SetMapByID(GetCurrentMapAreaID())
|
||||||
|
local areaId = GetCurrentMapAreaID()
|
||||||
|
|
||||||
|
for _, channel in pairs(Heimdall_Data.config.combatAlerter.channels) do
|
||||||
|
local locale = shared.GetLocaleForChannel(channel)
|
||||||
|
local text = string.format(
|
||||||
|
shared._L("combatAlerterInCombat", locale),
|
||||||
|
source,
|
||||||
|
shared._L("zone", locale),
|
||||||
|
shared._L("subZone", locale),
|
||||||
|
tostring(areaId),
|
||||||
|
x * 100,
|
||||||
|
y * 100
|
||||||
|
)
|
||||||
---@type Message
|
---@type Message
|
||||||
local msg = {
|
local msg = {
|
||||||
channel = "CHANNEL",
|
channel = "C",
|
||||||
data = Heimdall_Data.config.combatAlerter.masterChannel,
|
data = channel,
|
||||||
message = string.format("%s is attacking me in %s(%s) at %2.2f,%2.2f ",
|
message = text,
|
||||||
source,
|
|
||||||
GetZoneText(), GetSubZoneText(),
|
|
||||||
x * 100, y * 100
|
|
||||||
),
|
|
||||||
}
|
}
|
||||||
|
if Heimdall_Data.config.combatAlerter.debug then
|
||||||
|
print(string.format("[%s] Queuing alert message", ModuleName))
|
||||||
|
shared.dump(msg)
|
||||||
|
end
|
||||||
table.insert(shared.messenger.queue, msg)
|
table.insert(shared.messenger.queue, msg)
|
||||||
end
|
end
|
||||||
|
elseif Heimdall_Data.config.combatAlerter.debug then
|
||||||
|
print(string.format("[%s] Source not in stinky list, ignoring: %s", ModuleName, source))
|
||||||
|
end
|
||||||
end)
|
end)
|
||||||
|
|
||||||
local combatTriggerFrame = CreateFrame("Frame")
|
local combatTriggerFrame = CreateFrame("Frame")
|
||||||
combatTriggerFrame:RegisterEvent("PLAYER_REGEN_DISABLED")
|
combatTriggerFrame:RegisterEvent("PLAYER_REGEN_DISABLED")
|
||||||
combatTriggerFrame:RegisterEvent("PLAYER_REGEN_ENABLED")
|
combatTriggerFrame:RegisterEvent("PLAYER_REGEN_ENABLED")
|
||||||
-- We want to only alert once per target per combat encounter
|
|
||||||
-- Even a small throttle would probably spam too much here
|
|
||||||
-- ....but maybe we can call it a 120 second throttle or something?
|
|
||||||
-- We will see
|
|
||||||
combatTriggerFrame:SetScript("OnEvent", function(self, event, ...)
|
combatTriggerFrame:SetScript("OnEvent", function(self, event, ...)
|
||||||
|
if Heimdall_Data.config.combatAlerter.debug then
|
||||||
|
print(string.format("[%s] Combat state changed: %s", ModuleName, event))
|
||||||
|
if event == "PLAYER_REGEN_DISABLED" then
|
||||||
|
print(string.format("[%s] Entered combat - Resetting alerts", ModuleName))
|
||||||
|
else
|
||||||
|
print(string.format("[%s] Left combat - Resetting alerts", ModuleName))
|
||||||
|
end
|
||||||
|
end
|
||||||
alerted = {}
|
alerted = {}
|
||||||
end)
|
end)
|
||||||
|
|
||||||
print("Heimdall - CombatAlerter loaded")
|
if Heimdall_Data.config.combatAlerter.debug then print(string.format("[%s] Module initialized", ModuleName)) end
|
||||||
end
|
print(string.format("[%s] Module initialized", ModuleName))
|
||||||
|
end,
|
||||||
|
}
|
||||||
|
@@ -1,14 +1,27 @@
|
|||||||
local addonname, shared = ...
|
local _, shared = ...
|
||||||
---@cast shared HeimdallShared
|
---@cast shared HeimdallShared
|
||||||
---@cast addonname string
|
local ModuleName = "Commander"
|
||||||
|
|
||||||
|
---@class HeimdallCommanderConfig
|
||||||
|
---@field enabled boolean
|
||||||
|
---@field debug boolean
|
||||||
|
---@field channels string[]
|
||||||
|
---@field commander string
|
||||||
|
---@field commands table<string, boolean>
|
||||||
|
|
||||||
local helpMessages = {
|
local helpMessages = {
|
||||||
ru = {
|
ru = {
|
||||||
"1) who - пишет вам никнеймы текущих врагов в отслеживаемых локациях по порядку и локацию.",
|
"1) who - пишет вам никнеймы текущих врагов и локу.",
|
||||||
"2) classes = пишет какие классы. (например 1 паладин 1 прист 1 рога.",
|
"2) classes - покажет классы врагов и число.",
|
||||||
"3) howmany - общее число врагов (например дуротар 4 . оргримар 2 ) ",
|
"3) howmany - общее число врагов (дурик 4 . огри 2 ) ",
|
||||||
"4) + - автоматическое приглашение в группу с дуельным рогой для сброса кд и общего сбора. ",
|
"4) + - атоинвайт в сбор пати и сброса кд.",
|
||||||
"5) ++ - автоматическое приглашение в группу альянса. (если нужен рефрак)",
|
"5) ++ -автоинвайт в пати аликов (если нужен рефрак)",
|
||||||
|
"6 ) note Никнейм текст - добавление заметки.",
|
||||||
|
"7) note Никнейм - посмотреть последние заметки.",
|
||||||
|
"8) note Никнейм 5 - посмотреть конкретную заметку.",
|
||||||
|
"9) note Никнейм 1..5 - посмотреть заметки от 1 до 5",
|
||||||
|
"10) note Никнейм delete 1 - удалить заметку номер 1",
|
||||||
|
"11) note Никнейм delete 1..5 - удалить заметки 1 до 5",
|
||||||
},
|
},
|
||||||
en = {
|
en = {
|
||||||
"1) who - reports currently tracked stinkies in orgrimmar and durotar",
|
"1) who - reports currently tracked stinkies in orgrimmar and durotar",
|
||||||
@@ -16,12 +29,18 @@ local helpMessages = {
|
|||||||
"3) howmany - reports stinkies grouped by zone",
|
"3) howmany - reports stinkies grouped by zone",
|
||||||
"4) + - automatically invites to group with duel rogue for cd reset",
|
"4) + - automatically invites to group with duel rogue for cd reset",
|
||||||
"5) ++ - automatically invites to alliance group",
|
"5) ++ - automatically invites to alliance group",
|
||||||
}
|
"6) note <name> <note> - adds a note for the specified character.",
|
||||||
|
"7) note <name> - lists the last N notes for the character.",
|
||||||
|
"8) note <name> i - lists the i-th note for the character.",
|
||||||
|
"9) note <name> i..j - lists notes from i to j for the character.",
|
||||||
|
"10) note <name> delete i - deletes the i-th note for the character.",
|
||||||
|
"11) note <name> delete i..j - deletes notes from i to j for the character.",
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
---@diagnostic disable-next-line: missing-fields
|
---@class Commander
|
||||||
shared.Commander = {}
|
shared.Commander = {
|
||||||
function shared.Commander.Init()
|
Init = function()
|
||||||
---@param text string
|
---@param text string
|
||||||
---@param size number
|
---@param size number
|
||||||
---@return string[]
|
---@return string[]
|
||||||
@@ -38,16 +57,12 @@ function shared.Commander.Init()
|
|||||||
if #currentChunk + #word + 1 <= size then
|
if #currentChunk + #word + 1 <= size then
|
||||||
currentChunk = currentChunk .. (currentChunk == "" and word or " " .. word)
|
currentChunk = currentChunk .. (currentChunk == "" and word or " " .. word)
|
||||||
else
|
else
|
||||||
if #currentChunk > 0 then
|
if #currentChunk > 0 then ret[#ret + 1] = currentChunk end
|
||||||
ret[#ret + 1] = currentChunk
|
|
||||||
end
|
|
||||||
currentChunk = word
|
currentChunk = word
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if #currentChunk > 0 then
|
if #currentChunk > 0 then ret[#ret + 1] = currentChunk end
|
||||||
ret[#ret + 1] = currentChunk
|
|
||||||
end
|
|
||||||
|
|
||||||
return ret
|
return ret
|
||||||
end
|
end
|
||||||
@@ -56,9 +71,7 @@ function shared.Commander.Init()
|
|||||||
local function Count(arr)
|
local function Count(arr)
|
||||||
local ret = {}
|
local ret = {}
|
||||||
for _, player in pairs(arr) do
|
for _, player in pairs(arr) do
|
||||||
if Heimdall_Data.config.who.zoneNotifyFor[player.zone] then
|
if shared.Whoer.ShouldNotifyForZone(player.zone) then ret[player.zone] = (ret[player.zone] or 0) + 1 end
|
||||||
ret[player.zone] = (ret[player.zone] or 0) + 1
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
local text = {}
|
local text = {}
|
||||||
for zone, count in pairs(ret) do
|
for zone, count in pairs(ret) do
|
||||||
@@ -71,6 +84,7 @@ function shared.Commander.Init()
|
|||||||
local function CountPartitioned(arr)
|
local function CountPartitioned(arr)
|
||||||
local count = Count(arr)
|
local count = Count(arr)
|
||||||
local text = {}
|
local text = {}
|
||||||
|
---@diagnostic disable-next-line: param-type-mismatch something wrong with luals, it's picking up the "wrong" unpack
|
||||||
for _, line in pairs(Partition(strjoin(", ", unpack(count)), 200)) do
|
for _, line in pairs(Partition(strjoin(", ", unpack(count)), 200)) do
|
||||||
text[#text + 1] = line
|
text[#text + 1] = line
|
||||||
end
|
end
|
||||||
@@ -81,11 +95,45 @@ function shared.Commander.Init()
|
|||||||
local function Who(arr)
|
local function Who(arr)
|
||||||
local ret = {}
|
local ret = {}
|
||||||
for _, player in pairs(arr) do
|
for _, player in pairs(arr) do
|
||||||
if Heimdall_Data.config.who.zoneNotifyFor[player.zone] then
|
if shared.Whoer.ShouldNotifyForZone(player.zone) then
|
||||||
ret[#ret + 1] = string.format("%s/%s (%s) %s", player.name, player.class, player.zone,
|
ret[#ret + 1] = string.format(
|
||||||
player.stinky and "(!!!!)" or "")
|
"%s/%s (%s) %s",
|
||||||
|
player.name,
|
||||||
|
player.class,
|
||||||
|
player.zone,
|
||||||
|
player.stinky and "(!!!!)" or ""
|
||||||
|
)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
if Heimdall_Data.config.commander.debug then
|
||||||
|
print(string.format("[%s] Command result: %s", ModuleName, strjoin(", ", unpack(ret))))
|
||||||
|
end
|
||||||
|
return ret
|
||||||
|
end
|
||||||
|
-- This is really ugly, duplicating methods like this
|
||||||
|
-- But I have no better idea
|
||||||
|
-- We would have to drag reference channel all the way here
|
||||||
|
-- And then in here do some kind of deciding based on the fucking channel locale
|
||||||
|
-- That's also a nasty solution... I guess adding "kto" is better
|
||||||
|
---@param arr table<string, Player>
|
||||||
|
---@return string[]
|
||||||
|
local function WhoRu(arr)
|
||||||
|
local ret = {}
|
||||||
|
for _, player in pairs(arr) do
|
||||||
|
if shared.Whoer.ShouldNotifyForZone(player.zone) then
|
||||||
|
shared.dump(player)
|
||||||
|
ret[#ret + 1] = string.format(
|
||||||
|
"%s/%s (%s) %s",
|
||||||
|
player.name,
|
||||||
|
shared._L(player.class, "ru"),
|
||||||
|
shared._L(player.zone, "ru"),
|
||||||
|
player.stinky and "(!!!!)" or ""
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if Heimdall_Data.config.commander.debug then
|
||||||
|
print(string.format("[%s] Command result: %s", ModuleName, strjoin(", ", unpack(ret))))
|
||||||
|
end
|
||||||
return ret
|
return ret
|
||||||
end
|
end
|
||||||
---@param arr table<string, Player>
|
---@param arr table<string, Player>
|
||||||
@@ -93,8 +141,20 @@ function shared.Commander.Init()
|
|||||||
local function WhoPartitioned(arr)
|
local function WhoPartitioned(arr)
|
||||||
local who = Who(arr)
|
local who = Who(arr)
|
||||||
local text = {}
|
local text = {}
|
||||||
|
---@diagnostic disable-next-line: param-type-mismatch something wrong with luals, it's picking up the "wrong" unpack
|
||||||
for _, line in pairs(Partition(strjoin(", ", unpack(who)), 200)) do
|
for _, line in pairs(Partition(strjoin(", ", unpack(who)), 200)) do
|
||||||
text[#text + 1] = line
|
text[#text + 1] = "who: " .. line
|
||||||
|
end
|
||||||
|
return text
|
||||||
|
end
|
||||||
|
---@param arr table<string, Player>
|
||||||
|
---@return string[]
|
||||||
|
local function WhoPartitionedRu(arr)
|
||||||
|
local who = WhoRu(arr)
|
||||||
|
local text = {}
|
||||||
|
---@diagnostic disable-next-line: param-type-mismatch something wrong with luals, it's picking up the "wrong" unpack
|
||||||
|
for _, line in pairs(Partition(strjoin(", ", unpack(who)), 200)) do
|
||||||
|
text[#text + 1] = "кто: " .. line
|
||||||
end
|
end
|
||||||
return text
|
return text
|
||||||
end
|
end
|
||||||
@@ -103,7 +163,7 @@ function shared.Commander.Init()
|
|||||||
local function CountClass(arr)
|
local function CountClass(arr)
|
||||||
local ret = {}
|
local ret = {}
|
||||||
for _, player in pairs(arr) do
|
for _, player in pairs(arr) do
|
||||||
if Heimdall_Data.config.who.zoneNotifyFor[player.zone] then
|
if shared.Whoer.ShouldNotifyForZone(player.zone) then
|
||||||
ret[player.class] = (ret[player.class] or 0) + 1
|
ret[player.class] = (ret[player.class] or 0) + 1
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -111,6 +171,9 @@ function shared.Commander.Init()
|
|||||||
for class, count in pairs(ret) do
|
for class, count in pairs(ret) do
|
||||||
text[#text + 1] = string.format("%s: %d", class, count)
|
text[#text + 1] = string.format("%s: %d", class, count)
|
||||||
end
|
end
|
||||||
|
if Heimdall_Data.config.commander.debug then
|
||||||
|
print(string.format("[%s] Message text: %s", ModuleName, strjoin(", ", unpack(text))))
|
||||||
|
end
|
||||||
return text
|
return text
|
||||||
end
|
end
|
||||||
---@param arr table<string, Player>
|
---@param arr table<string, Player>
|
||||||
@@ -118,106 +181,258 @@ function shared.Commander.Init()
|
|||||||
local function CountClassPartitioned(arr)
|
local function CountClassPartitioned(arr)
|
||||||
local countClass = CountClass(arr)
|
local countClass = CountClass(arr)
|
||||||
local text = {}
|
local text = {}
|
||||||
|
---@diagnostic disable-next-line: param-type-mismatch something wrong with luals, it's picking up the "wrong" unpack
|
||||||
for _, line in pairs(Partition(strjoin(", ", unpack(countClass)), 200)) do
|
for _, line in pairs(Partition(strjoin(", ", unpack(countClass)), 200)) do
|
||||||
text[#text + 1] = line
|
text[#text + 1] = line
|
||||||
end
|
end
|
||||||
return text
|
return text
|
||||||
end
|
end
|
||||||
local function CountClassPartitionedStinkies()
|
local function CountClassPartitionedStinkies()
|
||||||
local res = CountClassPartitioned(HeimdallStinkies)
|
if Heimdall_Data.config.commander.debug then
|
||||||
if #res == 0 then
|
print(string.format("[%s] Executing: CountClassPartitionedStinkies", ModuleName))
|
||||||
return { "No stinkies found" }
|
|
||||||
end
|
end
|
||||||
|
local res = CountClassPartitioned(HeimdallStinkies)
|
||||||
|
if #res == 0 then return { "No stinkies found" } end
|
||||||
return res
|
return res
|
||||||
end
|
end
|
||||||
local function WhoPartitionedStinkies()
|
local function WhoPartitionedStinkies()
|
||||||
local res = WhoPartitioned(HeimdallStinkies)
|
if Heimdall_Data.config.commander.debug then
|
||||||
if #res == 0 then
|
print(string.format("[%s] Executing: WhoPartitionedStinkies", ModuleName))
|
||||||
return { "No stinkies found" }
|
shared.dump(HeimdallStinkies)
|
||||||
end
|
end
|
||||||
|
local res = WhoPartitioned(HeimdallStinkies)
|
||||||
|
if #res == 0 then return { "No stinkies found" } end
|
||||||
|
return res
|
||||||
|
end
|
||||||
|
local function WhoPartitionedStinkiesRu()
|
||||||
|
if Heimdall_Data.config.commander.debug then
|
||||||
|
print(string.format("[%s] Executing: WhoPartitionedStinkies", ModuleName))
|
||||||
|
shared.dump(HeimdallStinkies)
|
||||||
|
end
|
||||||
|
local res = WhoPartitionedRu(HeimdallStinkies)
|
||||||
|
if #res == 0 then return { "No stinkies found" } end
|
||||||
return res
|
return res
|
||||||
end
|
end
|
||||||
local function CountPartitionedStinkies()
|
local function CountPartitionedStinkies()
|
||||||
local res = CountPartitioned(HeimdallStinkies)
|
if Heimdall_Data.config.commander.debug then
|
||||||
if #res == 0 then
|
print(string.format("[%s] Executing: CountPartitionedStinkies", ModuleName))
|
||||||
return { "No stinkies found" }
|
|
||||||
end
|
end
|
||||||
|
local res = CountPartitioned(HeimdallStinkies)
|
||||||
|
if #res == 0 then return { "No stinkies found" } end
|
||||||
return res
|
return res
|
||||||
end
|
end
|
||||||
local function HelpRu() return helpMessages.ru end
|
local function HelpRu()
|
||||||
local function HelpEn() return helpMessages.en end
|
if Heimdall_Data.config.commander.debug then print(string.format("[%s] Executing: HelpRu", ModuleName)) end
|
||||||
|
return helpMessages.ru
|
||||||
|
end
|
||||||
|
local function HelpEn()
|
||||||
|
if Heimdall_Data.config.commander.debug then print(string.format("[%s] Executing: HelpEn", ModuleName)) end
|
||||||
|
return helpMessages.en
|
||||||
|
end
|
||||||
local groupInviteFrame = CreateFrame("Frame")
|
local groupInviteFrame = CreateFrame("Frame")
|
||||||
groupInviteFrame:SetScript("OnEvent", function(self, event, ...)
|
groupInviteFrame:SetScript("OnEvent", function(self, event, ...)
|
||||||
|
if Heimdall_Data.config.commander.debug then print(string.format("[%s] Event received", ModuleName)) end
|
||||||
AcceptGroup()
|
AcceptGroup()
|
||||||
groupInviteFrame:UnregisterEvent("PARTY_INVITE_REQUEST")
|
groupInviteFrame:UnregisterEvent("PARTY_INVITE_REQUEST")
|
||||||
C_Timer.NewTimer(0.1, function()
|
C_Timer.NewTimer(0.1, function()
|
||||||
|
if Heimdall_Data.config.commander.debug then
|
||||||
|
print(string.format("[%s] Click event triggered", ModuleName))
|
||||||
|
end
|
||||||
_G["StaticPopup1Button1"]:Click()
|
_G["StaticPopup1Button1"]:Click()
|
||||||
end, 1)
|
end, 1)
|
||||||
end)
|
end)
|
||||||
local function JoinGroup()
|
local function JoinGroup()
|
||||||
|
if Heimdall_Data.config.commander.debug then
|
||||||
|
print(string.format("[%s] JoinGroup command received", ModuleName))
|
||||||
|
end
|
||||||
groupInviteFrame:RegisterEvent("PARTY_INVITE_REQUEST")
|
groupInviteFrame:RegisterEvent("PARTY_INVITE_REQUEST")
|
||||||
C_Timer.NewTimer(10, function()
|
C_Timer.NewTimer(10, function() groupInviteFrame:UnregisterEvent("PARTY_INVITE_REQUEST") end, 1)
|
||||||
groupInviteFrame:UnregisterEvent("PARTY_INVITE_REQUEST")
|
|
||||||
end, 1)
|
|
||||||
return { "+" }
|
return { "+" }
|
||||||
end
|
end
|
||||||
local function LeaveGroup()
|
local function LeaveGroup()
|
||||||
|
if Heimdall_Data.config.commander.debug then
|
||||||
|
print(string.format("[%s] LeaveGroup command received", ModuleName))
|
||||||
|
end
|
||||||
LeaveParty()
|
LeaveParty()
|
||||||
return {}
|
return {}
|
||||||
end
|
end
|
||||||
---@param target string
|
---@param target string
|
||||||
local function FollowTarget(target)
|
local function FollowTarget(target)
|
||||||
|
if Heimdall_Data.config.commander.debug then
|
||||||
|
print(string.format("[%s] Following target: %s", ModuleName, target))
|
||||||
|
end
|
||||||
if not target then return end
|
if not target then return end
|
||||||
FollowUnit(target)
|
FollowUnit(target)
|
||||||
return {}
|
return {}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param args string[]
|
||||||
|
local function MacroTarget(args)
|
||||||
|
if Heimdall_Data.config.commander.debug then
|
||||||
|
---@diagnostic disable-next-line: param-type-mismatch something wrong with luals, it's picking up the "wrong" unpack
|
||||||
|
print(string.format("[%s] Macroing: %s", ModuleName, strjoin(" ", unpack(args))))
|
||||||
|
end
|
||||||
|
if #args < 2 or #args % 2 ~= 0 then
|
||||||
|
if #args < 2 or #args % 2 ~= 0 then
|
||||||
|
if Heimdall_Data.config.commander.debug then
|
||||||
|
print(string.format("[%s] Invalid number of arguments for MacroTarget", ModuleName))
|
||||||
|
end
|
||||||
|
return {}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
table.remove(args, 1)
|
||||||
|
|
||||||
|
for i = 1, #args do
|
||||||
|
local stinky = strtrim(args[i])
|
||||||
|
local name = stinky:match("([^/]+)")
|
||||||
|
local class = stinky:match("/([^ $]+)")
|
||||||
|
if Heimdall_Data.config.commander.debug then
|
||||||
|
print(string.format("[%s] Adding stinky: %s/%s", ModuleName, name, tostring(class)))
|
||||||
|
end
|
||||||
|
shared.StinkyTracker.Track({
|
||||||
|
name = name,
|
||||||
|
class = class or "unknown",
|
||||||
|
seenAt = GetTime(),
|
||||||
|
hostile = true,
|
||||||
|
})
|
||||||
|
if Heimdall_Data.config.commander.debug then
|
||||||
|
print(string.format("[%s] Added stinky: %s/%s", ModuleName, name, tostring(class)))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return {}
|
||||||
|
end
|
||||||
|
|
||||||
|
---@param args string[]
|
||||||
|
local function IgnoreMacroTarget(args)
|
||||||
|
if Heimdall_Data.config.commander.debug then
|
||||||
|
---@diagnostic disable-next-line: param-type-mismatch something wrong with luals, it's picking up the "wrong" unpack
|
||||||
|
print(string.format("[%s] Macroing: %s", ModuleName, strjoin(" ", unpack(args))))
|
||||||
|
end
|
||||||
|
if #args < 1 then
|
||||||
|
if Heimdall_Data.config.commander.debug then
|
||||||
|
print(string.format("[%s] Invalid number of arguments for IgnoreMacroTarget", ModuleName))
|
||||||
|
end
|
||||||
|
return {}
|
||||||
|
end
|
||||||
|
table.remove(args, 1)
|
||||||
|
|
||||||
|
for i = 1, #args do
|
||||||
|
local stinky = strtrim(args[i])
|
||||||
|
local name = stinky:match("([^/]+)")
|
||||||
|
if Heimdall_Data.config.commander.debug then
|
||||||
|
print(string.format("[%s] Ignoring stinky: %s", ModuleName, name))
|
||||||
|
end
|
||||||
|
shared.StinkyTracker.Ignore(name)
|
||||||
|
end
|
||||||
|
return {}
|
||||||
|
end
|
||||||
|
|
||||||
---@class Command
|
---@class Command
|
||||||
---@field keywordRe string
|
---@field keywordRe string
|
||||||
---@field commanderOnly boolean
|
---@field commanderOnly boolean
|
||||||
---@field callback fun(...: any): string[]
|
---@field callback fun(...: any): string[]
|
||||||
|
|
||||||
local commands = {
|
local commands = {
|
||||||
{ keywordRe = "^who", commanderOnly = false, callback = WhoPartitionedStinkies },
|
{ keywordRe = "^who$", commanderOnly = false, callback = WhoPartitionedStinkies },
|
||||||
{ keywordRe = "^howmany", commanderOnly = false, callback = CountPartitionedStinkies },
|
{ keywordRe = "^кто$", commanderOnly = false, callback = WhoPartitionedStinkiesRu },
|
||||||
{ keywordRe = "^classes", commanderOnly = false, callback = CountClassPartitionedStinkies },
|
{ keywordRe = "^howmany$", commanderOnly = false, callback = CountPartitionedStinkies },
|
||||||
{ keywordRe = "^help", commanderOnly = false, callback = HelpRu },
|
{ keywordRe = "^classes$", commanderOnly = false, callback = CountClassPartitionedStinkies },
|
||||||
{ keywordRe = "^helpen", commanderOnly = false, callback = HelpEn },
|
{ keywordRe = "^help$", commanderOnly = false, callback = HelpRu },
|
||||||
{ keywordRe = "^joingroup", commanderOnly = false, callback = JoinGroup },
|
{ keywordRe = "^helpen$", commanderOnly = false, callback = HelpEn },
|
||||||
{ keywordRe = "^leavegroup", commanderOnly = false, callback = LeaveGroup },
|
{ keywordRe = "^joingroup$", commanderOnly = false, callback = JoinGroup },
|
||||||
{ keywordRe = "^follow", commanderOnly = false, callback = FollowTarget },
|
{ keywordRe = "^leavegroup$", commanderOnly = false, callback = LeaveGroup },
|
||||||
|
{ keywordRe = "^follow$", commanderOnly = false, callback = FollowTarget },
|
||||||
|
{ keywordRe = "^macro", commanderOnly = false, callback = MacroTarget },
|
||||||
|
{ keywordRe = "^ignore", commanderOnly = false, callback = IgnoreMacroTarget },
|
||||||
}
|
}
|
||||||
|
|
||||||
local commanderChannelFrame = CreateFrame("Frame")
|
local commanderChannelFrame = CreateFrame("Frame")
|
||||||
commanderChannelFrame:RegisterEvent("CHAT_MSG_CHANNEL")
|
commanderChannelFrame:RegisterEvent("CHAT_MSG_CHANNEL")
|
||||||
commanderChannelFrame:SetScript("OnEvent", function(self, event, msg, sender, ...)
|
commanderChannelFrame:SetScript("OnEvent", function(self, event, msg, sender, ...)
|
||||||
if not Heimdall_Data.config.commander.enabled then return end
|
--if Heimdall_Data.config.commander.debug then
|
||||||
|
-- print(string.format("[%s] Event received", ModuleName))
|
||||||
|
-- shared.dump(Heimdall_Data.config.commander)
|
||||||
|
--end
|
||||||
|
if not Heimdall_Data.config.commander.enabled then
|
||||||
|
--if Heimdall_Data.config.commander.debug then
|
||||||
|
-- print(string.format("[%s] Module disabled, ignoring event", ModuleName))
|
||||||
|
--end
|
||||||
|
return
|
||||||
|
end
|
||||||
local channelId = select(6, ...)
|
local channelId = select(6, ...)
|
||||||
local _, channelname = GetChannelName(channelId)
|
local _, channelname = GetChannelName(channelId)
|
||||||
if channelname ~= Heimdall_Data.config.commander.masterChannel then return end
|
local ok = false
|
||||||
|
for _, channel in pairs(Heimdall_Data.config.commander.channels) do
|
||||||
|
if channel == channelname then
|
||||||
|
ok = true
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if not ok then
|
||||||
|
if Heimdall_Data.config.commander.debug then
|
||||||
|
print(
|
||||||
|
string.format(
|
||||||
|
"[%s] Channel name '%s' does not match any of the channels '%s'",
|
||||||
|
ModuleName,
|
||||||
|
channelname,
|
||||||
|
table.concat(Heimdall_Data.config.commander.channels, ", ")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
sender = string.match(sender, "^[^-]+")
|
sender = string.match(sender, "^[^-]+")
|
||||||
|
if Heimdall_Data.config.commander.debug then
|
||||||
|
print(string.format("[%s] Message from: %s", ModuleName, sender))
|
||||||
|
shared.dump(Heimdall_Data.config.commander)
|
||||||
|
end
|
||||||
|
|
||||||
for _, command in ipairs(commands) do
|
for _, command in ipairs(commands) do
|
||||||
local enabled = Heimdall_Data.config.commander.commands[command.keywordRe] == true or false
|
local enabled = Heimdall_Data.config.commander.commands[command.keywordRe] == true or false
|
||||||
if enabled and
|
if Heimdall_Data.config.commander.debug then
|
||||||
(not command.commanderOnly
|
print(
|
||||||
or (command.commanderOnly
|
string.format("[%s] Command match: %s = %s", ModuleName, command.keywordRe, tostring(enabled))
|
||||||
and sender == Heimdall_Data.config.commander.commander)) then
|
)
|
||||||
|
end
|
||||||
|
if
|
||||||
|
enabled
|
||||||
|
and (
|
||||||
|
not command.commanderOnly
|
||||||
|
-- if Heimdall_Data.config.commander.debug then print(string.format("[%s] Ignoring command, sender %s not commander %s", ModuleName, sender, Heimdall_Data.config.commander.commander)) end
|
||||||
|
|
||||||
|
or (command.commanderOnly and sender == Heimdall_Data.config.commander.commander)
|
||||||
|
)
|
||||||
|
then
|
||||||
if msg:match(command.keywordRe) then
|
if msg:match(command.keywordRe) then
|
||||||
local messages = command.callback({ strsplit(" ", msg) })
|
---@diagnostic disable-next-line: redundant-parameter Currently luals does not support variadic functions as a @field
|
||||||
|
local messages = command.callback({ strsplit(",", msg) })
|
||||||
|
if Heimdall_Data.config.commander.debug then
|
||||||
|
print(string.format("[%s] Messages to send: %s", ModuleName, #messages))
|
||||||
|
shared.dump(messages)
|
||||||
|
end
|
||||||
for _, message in ipairs(messages) do
|
for _, message in ipairs(messages) do
|
||||||
---@type Message
|
---@type Message
|
||||||
local msg = {
|
local returnmsg = {
|
||||||
channel = "CHANNEL",
|
channel = "C",
|
||||||
data = channelname,
|
data = channelname,
|
||||||
message = message
|
message = message,
|
||||||
}
|
}
|
||||||
table.insert(shared.messenger.queue, msg)
|
if Heimdall_Data.config.commander.debug then
|
||||||
|
print(string.format("[%s] Queuing message", ModuleName))
|
||||||
|
shared.dump(msg)
|
||||||
|
end
|
||||||
|
if Heimdall_Data.config.networkMessenger.enabled then
|
||||||
|
shared.NetworkMessenger.Enqueue(returnmsg)
|
||||||
|
elseif Heimdall_Data.config.messenger.enabled then
|
||||||
|
shared.Messenger.Enqueue(returnmsg)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
|
|
||||||
print("Heimdall - Commander loaded")
|
print(string.format("[%s] Module initialized", ModuleName))
|
||||||
end
|
end,
|
||||||
|
}
|
||||||
|
2245
Modules/Config.lua
2245
Modules/Config.lua
File diff suppressed because it is too large
Load Diff
12
Modules/Configurator.lua
Normal file
12
Modules/Configurator.lua
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
local _, shared = ...
|
||||||
|
---@cast shared HeimdallShared
|
||||||
|
local ModuleName = "Configurator"
|
||||||
|
|
||||||
|
---@class HeimdallConfiguratorConfig
|
||||||
|
---@field enabled boolean
|
||||||
|
---@field debug boolean
|
||||||
|
|
||||||
|
---@class Configurator
|
||||||
|
shared.Configurator = {
|
||||||
|
Init = function() print(string.format("[%s] Module initialized", ModuleName)) end,
|
||||||
|
}
|
@@ -1,10 +1,19 @@
|
|||||||
local addonname, shared = ...
|
local _, shared = ...
|
||||||
---@cast shared HeimdallShared
|
---@cast shared HeimdallShared
|
||||||
---@cast addonname string
|
local ModuleName = "DeathReporter"
|
||||||
|
|
||||||
---@diagnostic disable-next-line: missing-fields
|
---@class HeimdallDeathReporterConfig
|
||||||
shared.DeathReporter = {}
|
---@field enabled boolean
|
||||||
function shared.DeathReporter.Init()
|
---@field debug boolean
|
||||||
|
---@field throttle number
|
||||||
|
---@field doWhisper boolean
|
||||||
|
---@field channels string[]
|
||||||
|
---@field zoneOverride string?
|
||||||
|
---@field duelThrottle number
|
||||||
|
|
||||||
|
---@class DeathReporter
|
||||||
|
shared.DeathReporter = {
|
||||||
|
Init = function()
|
||||||
---@type table<string, number>
|
---@type table<string, number>
|
||||||
local recentDeaths = {}
|
local recentDeaths = {}
|
||||||
---@type table<string, number>
|
---@type table<string, number>
|
||||||
@@ -14,64 +23,164 @@ function shared.DeathReporter.Init()
|
|||||||
---@param destination string
|
---@param destination string
|
||||||
---@param spellName string
|
---@param spellName string
|
||||||
local function RegisterDeath(source, destination, spellName)
|
local function RegisterDeath(source, destination, spellName)
|
||||||
if not Heimdall_Data.config.deathReporter.enabled then return end
|
if Heimdall_Data.config.deathReporter.debug then
|
||||||
if recentDeaths[destination]
|
print(
|
||||||
and GetTime() - recentDeaths[destination] < Heimdall_Data.config.deathReporter.throttle then
|
string.format(
|
||||||
|
"[%s] Processing death event - Source: %s, Target: %s, Spell: %s",
|
||||||
|
ModuleName,
|
||||||
|
source,
|
||||||
|
destination,
|
||||||
|
spellName
|
||||||
|
)
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
if not Heimdall_Data.config.deathReporter.enabled then
|
||||||
|
if Heimdall_Data.config.deathReporter.debug then
|
||||||
|
print(string.format("[%s] Module disabled, ignoring death event", ModuleName))
|
||||||
|
end
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
if recentDuels[destination]
|
if
|
||||||
and GetTime() - recentDuels[destination] < Heimdall_Data.config.deathReporter.duelThrottle then
|
recentDeaths[destination]
|
||||||
print(string.format("Cancelling death reports for %s and %s because of recent duel", source, destination))
|
and GetTime() - recentDeaths[destination] < Heimdall_Data.config.deathReporter.throttle
|
||||||
return
|
then
|
||||||
|
if Heimdall_Data.config.deathReporter.debug then
|
||||||
|
local timeLeft = Heimdall_Data.config.deathReporter.throttle
|
||||||
|
- (GetTime() - recentDeaths[destination])
|
||||||
|
print(
|
||||||
|
string.format(
|
||||||
|
"[%s] Death report throttled for %s (%.1f seconds remaining)",
|
||||||
|
ModuleName,
|
||||||
|
destination,
|
||||||
|
timeLeft
|
||||||
|
)
|
||||||
|
)
|
||||||
end
|
end
|
||||||
if recentDuels[source]
|
|
||||||
and GetTime() - recentDuels[source] < Heimdall_Data.config.deathReporter.duelThrottle then
|
|
||||||
print(string.format("Cancelling death reports for %s and %s because of recent duel", source, destination))
|
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if
|
||||||
|
recentDuels[destination]
|
||||||
|
and GetTime() - recentDuels[destination] < Heimdall_Data.config.deathReporter.duelThrottle
|
||||||
|
then
|
||||||
|
if Heimdall_Data.config.deathReporter.debug then
|
||||||
|
print(
|
||||||
|
string.format(
|
||||||
|
"[%s] Ignoring death report - Recent duel detected for target: %s",
|
||||||
|
ModuleName,
|
||||||
|
destination
|
||||||
|
)
|
||||||
|
)
|
||||||
|
end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
if
|
||||||
|
recentDuels[source]
|
||||||
|
and GetTime() - recentDuels[source] < Heimdall_Data.config.deathReporter.duelThrottle
|
||||||
|
then
|
||||||
|
if Heimdall_Data.config.deathReporter.debug then
|
||||||
|
print(
|
||||||
|
string.format(
|
||||||
|
"[%s] Ignoring death report - Recent duel detected for source: %s",
|
||||||
|
ModuleName,
|
||||||
|
source
|
||||||
|
)
|
||||||
|
)
|
||||||
|
end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
if Heimdall_Data.config.deathReporter.debug then
|
||||||
|
print(string.format("[%s] Recording death for %s", ModuleName, destination))
|
||||||
|
end
|
||||||
recentDeaths[destination] = GetTime()
|
recentDeaths[destination] = GetTime()
|
||||||
|
|
||||||
C_Timer.NewTimer(3, function()
|
C_Timer.NewTimer(3, function()
|
||||||
if recentDuels[destination]
|
if
|
||||||
and GetTime() - recentDuels[destination] < Heimdall_Data.config.deathReporter.duelThrottle then
|
recentDuels[destination]
|
||||||
print(string.format("Cancelling death reports for %s and %s because of recent duel", source, destination))
|
and GetTime() - recentDuels[destination] < Heimdall_Data.config.deathReporter.duelThrottle
|
||||||
return
|
then
|
||||||
|
if Heimdall_Data.config.deathReporter.debug then
|
||||||
|
print(
|
||||||
|
string.format(
|
||||||
|
"[%s] Cancelling delayed death report - Recent duel detected for: %s",
|
||||||
|
ModuleName,
|
||||||
|
destination
|
||||||
|
)
|
||||||
|
)
|
||||||
end
|
end
|
||||||
if recentDuels[source]
|
|
||||||
and GetTime() - recentDuels[source] < Heimdall_Data.config.deathReporter.duelThrottle then
|
|
||||||
print(string.format("Cancelling death reports for %s and %s because of recent duel", source, destination))
|
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
local zone = Heimdall_Data.config.deathReporter.zoneOverride
|
if
|
||||||
if zone == nil or zone == "" then
|
recentDuels[source]
|
||||||
zone = string.format("%s (%s)", GetZoneText(), GetSubZoneText())
|
and GetTime() - recentDuels[source] < Heimdall_Data.config.deathReporter.duelThrottle
|
||||||
|
then
|
||||||
|
if Heimdall_Data.config.deathReporter.debug then
|
||||||
|
print(
|
||||||
|
string.format(
|
||||||
|
"[%s] Cancelling delayed death report - Recent duel detected for: %s",
|
||||||
|
ModuleName,
|
||||||
|
source
|
||||||
|
)
|
||||||
|
)
|
||||||
|
end
|
||||||
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
local text = string.format("%s killed %s with %s in %s",
|
if Heimdall_Data.config.deathReporter.debug then
|
||||||
tostring(source),
|
print(
|
||||||
tostring(destination),
|
string.format(
|
||||||
tostring(spellName),
|
"[%s] Sending death report - %s killed %s with %s",
|
||||||
tostring(zone))
|
ModuleName,
|
||||||
|
source,
|
||||||
|
destination,
|
||||||
|
spellName
|
||||||
|
)
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
local zone, subzone = GetZoneText() or "Unknown", GetSubZoneText() or "Unknown"
|
||||||
|
if Heimdall_Data.config.spotter.zoneOverride then
|
||||||
|
zone = Heimdall_Data.config.spotter.zoneOverride or ""
|
||||||
|
subzone = ""
|
||||||
|
end
|
||||||
|
|
||||||
|
local x, y = GetPlayerMapPosition("player")
|
||||||
|
if Heimdall_Data.config.deathReporter.debug then
|
||||||
|
print(string.format("[%s] Player coordinates: %.2f, %.2f", ModuleName, x * 100, y * 100))
|
||||||
|
end
|
||||||
|
SetMapToCurrentZone()
|
||||||
|
SetMapByID(GetCurrentMapAreaID())
|
||||||
|
local zoneId = GetCurrentMapAreaID()
|
||||||
|
|
||||||
|
for _, channel in pairs(Heimdall_Data.config.deathReporter.channels) do
|
||||||
|
local locale = shared.GetLocaleForChannel(channel)
|
||||||
|
local text = string.format(
|
||||||
|
shared._L("killed", locale),
|
||||||
|
source,
|
||||||
|
destination,
|
||||||
|
shared._L(spellName, locale),
|
||||||
|
shared._L(zone, locale),
|
||||||
|
shared._L(subzone, locale),
|
||||||
|
zoneId,
|
||||||
|
x * 100,
|
||||||
|
y * 100
|
||||||
|
)
|
||||||
---@type Message
|
---@type Message
|
||||||
local msg = {
|
local msg = {
|
||||||
channel = "CHANNEL",
|
channel = "C",
|
||||||
data = Heimdall_Data.config.deathReporter.notifyChannel,
|
data = channel,
|
||||||
message = text,
|
message = text,
|
||||||
}
|
}
|
||||||
table.insert(shared.messenger.queue, msg)
|
if Heimdall_Data.config.deathReporter.debug then
|
||||||
|
print(string.format("[%s] Queuing death report message", ModuleName))
|
||||||
if Heimdall_Data.config.deathReporter.doWhisper then
|
shared.dump(msg)
|
||||||
for _, name in pairs(Heimdall_Data.config.whisperNotify) do
|
|
||||||
local msg = {
|
|
||||||
channel = "WHISPER",
|
|
||||||
data = name,
|
|
||||||
message = text,
|
|
||||||
}
|
|
||||||
table.insert(shared.messenger.queue, msg)
|
|
||||||
end
|
end
|
||||||
|
table.insert(shared.messenger.queue, msg)
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
@@ -79,18 +188,37 @@ function shared.DeathReporter.Init()
|
|||||||
local cleuFrame = CreateFrame("Frame")
|
local cleuFrame = CreateFrame("Frame")
|
||||||
cleuFrame:RegisterEvent("COMBAT_LOG_EVENT_UNFILTERED")
|
cleuFrame:RegisterEvent("COMBAT_LOG_EVENT_UNFILTERED")
|
||||||
cleuFrame:SetScript("OnEvent", function(self, event, ...)
|
cleuFrame:SetScript("OnEvent", function(self, event, ...)
|
||||||
|
-- if Heimdall_Data.config.deathReporter.debug then
|
||||||
|
-- print(string.format("[%s] Received combat log event", ModuleName))
|
||||||
|
-- end
|
||||||
if not Heimdall_Data.config.deathReporter.enabled then return end
|
if not Heimdall_Data.config.deathReporter.enabled then return end
|
||||||
local overkill, err = CLEUParser.GetOverkill(...)
|
local overkill, source, destination, spellName, sourceGUID, destinationGUID, err
|
||||||
|
overkill, err = CLEUParser.GetOverkill(...)
|
||||||
if not err and overkill > 0 then
|
if not err and overkill > 0 then
|
||||||
local source, err = CLEUParser.GetSourceName(...)
|
source, err = CLEUParser.GetSourceName(...)
|
||||||
if err then source = "unknown" end
|
if err then
|
||||||
local destination, err = CLEUParser.GetDestName(...)
|
source = "unknown"
|
||||||
if err then destination = "unknown" end
|
if Heimdall_Data.config.deathReporter.debug then
|
||||||
local spellName, err = CLEUParser.GetSpellName(...)
|
print(string.format("[%s] Error getting source name", ModuleName))
|
||||||
if err then spellName = "unknown" end
|
end
|
||||||
local sourceGUID, err = CLEUParser.GetSourceGUID(...)
|
end
|
||||||
|
destination, err = CLEUParser.GetDestName(...)
|
||||||
|
if err then
|
||||||
|
destination = "unknown"
|
||||||
|
if Heimdall_Data.config.deathReporter.debug then
|
||||||
|
print(string.format("[%s] Error getting destination name", ModuleName))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
spellName, err = CLEUParser.GetSpellName(...)
|
||||||
|
if err then
|
||||||
|
spellName = "unknown"
|
||||||
|
if Heimdall_Data.config.deathReporter.debug then
|
||||||
|
print(string.format("[%s] Error getting spell name", ModuleName))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
sourceGUID, err = CLEUParser.GetSourceGUID(...)
|
||||||
if err or not string.match(sourceGUID, "Player") then return end
|
if err or not string.match(sourceGUID, "Player") then return end
|
||||||
local destinationGUID, err = CLEUParser.GetDestGUID(...)
|
destinationGUID, err = CLEUParser.GetDestGUID(...)
|
||||||
if err or not string.match(destinationGUID, "Player") then return end
|
if err or not string.match(destinationGUID, "Player") then return end
|
||||||
RegisterDeath(source, destination, spellName)
|
RegisterDeath(source, destination, spellName)
|
||||||
end
|
end
|
||||||
@@ -101,16 +229,40 @@ function shared.DeathReporter.Init()
|
|||||||
systemMessageFrame:SetScript("OnEvent", function(self, event, msg)
|
systemMessageFrame:SetScript("OnEvent", function(self, event, msg)
|
||||||
if not Heimdall_Data.config.deathReporter.enabled then return end
|
if not Heimdall_Data.config.deathReporter.enabled then return end
|
||||||
local source, destination = string.match(msg, "([^ ]+) has defeated ([^ ]+) in a duel")
|
local source, destination = string.match(msg, "([^ ]+) has defeated ([^ ]+) in a duel")
|
||||||
|
if Heimdall_Data.config.deathReporter.debug then
|
||||||
|
print(string.format("[%s] Received system message: %s", ModuleName, msg))
|
||||||
|
print(
|
||||||
|
string.format(
|
||||||
|
"[%s] Source: %s, Destination: %s",
|
||||||
|
ModuleName,
|
||||||
|
tostring(source),
|
||||||
|
tostring(destination)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
end
|
||||||
if not source or not destination then return end
|
if not source or not destination then return end
|
||||||
source = string.match(source, "([^-]+)")
|
source = string.match(source, "([^-]+)")
|
||||||
destination = string.match(destination, "([^-]+)")
|
destination = string.match(destination, "([^-]+)")
|
||||||
if source and destination then
|
if source and destination then
|
||||||
print(string.format("Detected duel between %s and %s", source, destination))
|
if Heimdall_Data.config.deathReporter.debug then
|
||||||
|
print(string.format("[%s] Detected duel between %s and %s", ModuleName, source, destination))
|
||||||
|
end
|
||||||
local now = GetTime()
|
local now = GetTime()
|
||||||
recentDuels[source] = now
|
recentDuels[source] = now
|
||||||
recentDuels[destination] = now
|
recentDuels[destination] = now
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
|
|
||||||
print("Heimdall - DeathReporter loaded")
|
if Heimdall_Data.config.deathReporter.debug then
|
||||||
end
|
print(
|
||||||
|
string.format(
|
||||||
|
"[%s] Module initialized with throttle: %.1fs, duel throttle: %.1fs",
|
||||||
|
ModuleName,
|
||||||
|
Heimdall_Data.config.deathReporter.throttle,
|
||||||
|
Heimdall_Data.config.deathReporter.duelThrottle
|
||||||
|
)
|
||||||
|
)
|
||||||
|
end
|
||||||
|
print(string.format("[%s] Module initialized", ModuleName))
|
||||||
|
end,
|
||||||
|
}
|
||||||
|
@@ -1,25 +1,63 @@
|
|||||||
local addonname, shared = ...
|
local _, shared = ...
|
||||||
---@cast shared HeimdallShared
|
---@cast shared HeimdallShared
|
||||||
---@cast addonname string
|
local ModuleName = "Dueler"
|
||||||
|
|
||||||
---@diagnostic disable-next-line: missing-fields
|
---@class HeimdallDuelerConfig
|
||||||
shared.Dueler = {}
|
---@field enabled boolean
|
||||||
function shared.Dueler.Init()
|
---@field debug boolean
|
||||||
|
---@field declineOther boolean
|
||||||
|
|
||||||
|
---@class Dueler
|
||||||
|
shared.Dueler = {
|
||||||
|
Init = function()
|
||||||
local frame = CreateFrame("Frame")
|
local frame = CreateFrame("Frame")
|
||||||
frame:RegisterEvent("DUEL_REQUESTED")
|
frame:RegisterEvent("DUEL_REQUESTED")
|
||||||
frame:SetScript("OnEvent", function(self, event, sender)
|
frame:SetScript("OnEvent", function(self, event, sender)
|
||||||
if not Heimdall_Data.config.dueler.enabled then return end
|
if Heimdall_Data.config.dueler.debug then
|
||||||
local allow = Heimdall_Data.config.agents[sender]
|
print(string.format("[%s] Duel request received from: %s", ModuleName, sender))
|
||||||
|
end
|
||||||
|
if not Heimdall_Data.config.dueler.enabled then
|
||||||
|
if Heimdall_Data.config.dueler.debug then
|
||||||
|
print(string.format("[%s] Module disabled, ignoring duel request", ModuleName))
|
||||||
|
end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
if Heimdall_Data.config.dueler.debug then
|
||||||
|
print(string.format("[%s] Checking if sender '%s' is in agents list", ModuleName, sender))
|
||||||
|
end
|
||||||
|
|
||||||
|
local allow = shared.AgentTracker.IsAgent(sender)
|
||||||
if allow then
|
if allow then
|
||||||
print("Heimdall - Dueler - Accepting duel from " .. sender)
|
if Heimdall_Data.config.dueler.debug then
|
||||||
|
print(string.format("[%s] Accepting duel from trusted agent: %s", ModuleName, sender))
|
||||||
|
end
|
||||||
AcceptDuel()
|
AcceptDuel()
|
||||||
else
|
else
|
||||||
if Heimdall_Data.config.dueler.autoDecline then
|
if Heimdall_Data.config.dueler.declineOther then
|
||||||
print("Heimdall - Dueler - Auto declining duel from " .. sender)
|
if Heimdall_Data.config.dueler.debug then
|
||||||
|
print(string.format("[%s] Auto-declining duel from untrusted sender: %s", ModuleName, sender))
|
||||||
|
end
|
||||||
CancelDuel()
|
CancelDuel()
|
||||||
|
else
|
||||||
|
if Heimdall_Data.config.dueler.debug then
|
||||||
|
print(
|
||||||
|
string.format("[%s] Leaving duel request from %s for manual response", ModuleName, sender)
|
||||||
|
)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
|
|
||||||
print("Heimdall - Dueler loaded")
|
if Heimdall_Data.config.dueler.debug then
|
||||||
end
|
print(
|
||||||
|
string.format(
|
||||||
|
"[%s] Module initialized with auto-decline: %s",
|
||||||
|
ModuleName,
|
||||||
|
tostring(Heimdall_Data.config.dueler.declineOther)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
end
|
||||||
|
print(string.format("[%s] Module initialized", ModuleName))
|
||||||
|
end,
|
||||||
|
}
|
||||||
|
@@ -1,28 +1,31 @@
|
|||||||
local addonname, shared = ...
|
local _, shared = ...
|
||||||
---@cast shared HeimdallShared
|
---@cast shared HeimdallShared
|
||||||
---@cast addonname string
|
|
||||||
|
|
||||||
if not shared.dumpTable then
|
if not shared.dump then
|
||||||
---@param table table
|
---@param value any
|
||||||
|
---@param msg string?
|
||||||
---@param depth number?
|
---@param depth number?
|
||||||
shared.dumpTable = function(table, depth)
|
shared.dump = function(value, msg, depth)
|
||||||
if not table then
|
if not value then
|
||||||
print(tostring(table))
|
print(tostring(value))
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
if depth == nil then
|
if type(value) ~= "table" then
|
||||||
depth = 0
|
print(tostring(value))
|
||||||
end
|
|
||||||
if (depth > 200) then
|
|
||||||
print("Error: Depth > 200 in dumpTable()")
|
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
for k, v in pairs(table) do
|
if msg then print(msg) end
|
||||||
if (type(v) == "table") then
|
if depth == nil then depth = 0 end
|
||||||
print(string.rep(" ", depth) .. k .. ":")
|
if depth > 200 then
|
||||||
shared.dumpTable(v, depth + 1)
|
print("Error: Depth > 200 in dump()")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
for k, v in pairs(value) do
|
||||||
|
if type(v) == "table" then
|
||||||
|
print(string.rep(" ", depth) .. tostring(k) .. ":")
|
||||||
|
shared.dump(v, msg, depth + 1)
|
||||||
else
|
else
|
||||||
print(string.rep(" ", depth) .. k .. ": ", v)
|
print(string.rep(" ", depth) .. tostring(k) .. ": " .. tostring(v))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@@ -1,36 +1,65 @@
|
|||||||
local addonname, shared = ...
|
local _, shared = ...
|
||||||
---@cast shared HeimdallShared
|
---@cast shared HeimdallShared
|
||||||
---@cast addonname string
|
local ModuleName = "Echoer"
|
||||||
|
|
||||||
---@diagnostic disable-next-line: missing-fields
|
---@class HeimdallEchoerConfig
|
||||||
shared.Echoer = {}
|
---@field enabled boolean
|
||||||
function shared.Echoer.Init()
|
---@field debug boolean
|
||||||
|
---@field channels string[]
|
||||||
|
---@field prefix string
|
||||||
|
|
||||||
|
---@class Echoer
|
||||||
|
shared.Echoer = {
|
||||||
|
Init = function()
|
||||||
local frame = CreateFrame("Frame")
|
local frame = CreateFrame("Frame")
|
||||||
frame:RegisterEvent("CHAT_MSG_CHANNEL")
|
frame:RegisterEvent("CHAT_MSG_CHANNEL")
|
||||||
frame:SetScript("OnEvent", function(self, event, msg, sender, ...)
|
frame:SetScript("OnEvent", function(self, event, msg, sender, ...)
|
||||||
if not Heimdall_Data.config.echoer.enabled then return end
|
--if Heimdall_Data.config.echoer.debug then
|
||||||
|
-- print(string.format("[%s] Channel message received from: %s", ModuleName, sender))
|
||||||
|
--end
|
||||||
|
|
||||||
|
if not Heimdall_Data.config.echoer.enabled then
|
||||||
|
--if Heimdall_Data.config.echoer.debug then
|
||||||
|
-- print(string.format("[%s] Module disabled, ignoring message", ModuleName))
|
||||||
|
--end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
local channelId = select(6, ...)
|
local channelId = select(6, ...)
|
||||||
local channelname = ""
|
local _, channelname = GetChannelName(channelId)
|
||||||
---@type any[]
|
local ok = false
|
||||||
local channels = { GetChannelList() }
|
for _, channel in pairs(Heimdall_Data.config.echoer.channels) do
|
||||||
for i = 1, #channels, 2 do
|
if channel == channelname then
|
||||||
---@type number
|
ok = true
|
||||||
local id = channels[i]
|
break
|
||||||
---@type string
|
|
||||||
local name = channels[i + 1]
|
|
||||||
if id == channelId then
|
|
||||||
channelname = name
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
if not ok then
|
||||||
if channelname ~= Heimdall_Data.config.echoer.masterChannel then return end
|
if Heimdall_Data.config.echoer.debug then
|
||||||
|
print(string.format("[%s] Channel name does not match any of the channels", ModuleName))
|
||||||
|
end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
if Heimdall_Data.config.echoer.debug then
|
||||||
|
print(string.format("[%s] Processing message from master channel: %s", ModuleName, sender))
|
||||||
|
shared.dump(Heimdall_Data.config.echoer)
|
||||||
|
end
|
||||||
|
|
||||||
if string.find(msg, "^" .. Heimdall_Data.config.echoer.prefix) then
|
if string.find(msg, "^" .. Heimdall_Data.config.echoer.prefix) then
|
||||||
local msg = string.sub(msg, string.len(Heimdall_Data.config.echoer.prefix) + 1)
|
if Heimdall_Data.config.echoer.debug then
|
||||||
SendChatMessage(msg, "SAY")
|
print(string.format("[%s] Found echo command in message: %s", ModuleName, msg))
|
||||||
|
end
|
||||||
|
local echomsg = string.sub(msg, string.len(Heimdall_Data.config.echoer.prefix) + 1)
|
||||||
|
if Heimdall_Data.config.echoer.debug then
|
||||||
|
print(string.format("[%s] Echoing message: %s", ModuleName, echomsg))
|
||||||
|
end
|
||||||
|
SendChatMessage(echomsg, "SAY")
|
||||||
|
elseif Heimdall_Data.config.echoer.debug then
|
||||||
|
print(string.format("[%s] Message does not start with echo prefix", ModuleName))
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
|
|
||||||
print("Heimdall - Echoer loaded")
|
if Heimdall_Data.config.echoer.debug then print(string.format("[%s] Module initialized", ModuleName)) end
|
||||||
end
|
print(string.format("[%s] Module initialized", ModuleName))
|
||||||
|
end,
|
||||||
|
}
|
||||||
|
@@ -1,35 +1,66 @@
|
|||||||
local addonname, shared = ...
|
local _, shared = ...
|
||||||
---@cast shared HeimdallShared
|
---@cast shared HeimdallShared
|
||||||
---@cast addonname string
|
local ModuleName = "Emoter"
|
||||||
|
|
||||||
---@diagnostic disable-next-line: missing-fields
|
---@class HeimdallEmoterConfig
|
||||||
shared.Emoter = {}
|
---@field enabled boolean
|
||||||
function shared.Emoter.Init()
|
---@field debug boolean
|
||||||
|
---@field channels string[]
|
||||||
|
---@field prefix string
|
||||||
|
|
||||||
|
---@class Emoter
|
||||||
|
shared.Emoter = {
|
||||||
|
Init = function()
|
||||||
local frame = CreateFrame("Frame")
|
local frame = CreateFrame("Frame")
|
||||||
frame:RegisterEvent("CHAT_MSG_CHANNEL")
|
frame:RegisterEvent("CHAT_MSG_CHANNEL")
|
||||||
frame:SetScript("OnEvent", function(self, event, msg, sender, ...)
|
frame:SetScript("OnEvent", function(self, event, msg, sender, ...)
|
||||||
if not Heimdall_Data.config.emoter.enabled then return end
|
--if Heimdall_Data.config.emoter.debug then
|
||||||
|
-- print(string.format("[%s] Channel message received from: %s", ModuleName, sender))
|
||||||
|
--end
|
||||||
|
|
||||||
|
if not Heimdall_Data.config.emoter.enabled then
|
||||||
|
--if Heimdall_Data.config.emoter.debug then
|
||||||
|
-- print(string.format("[%s] Module disabled, ignoring message", ModuleName))
|
||||||
|
--end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
local channelId = select(6, ...)
|
local channelId = select(6, ...)
|
||||||
local channelname = ""
|
local _, channelname = GetChannelName(channelId)
|
||||||
---@type any[]
|
local ok = false
|
||||||
local channels = { GetChannelList() }
|
for _, channel in pairs(Heimdall_Data.config.emoter.channels) do
|
||||||
for i = 1, #channels, 2 do
|
if channel == channelname then
|
||||||
---@type number
|
ok = true
|
||||||
local id = channels[i]
|
break
|
||||||
---@type string
|
|
||||||
local name = channels[i + 1]
|
|
||||||
if id == channelId then
|
|
||||||
channelname = name
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
if not ok then
|
||||||
|
if Heimdall_Data.config.emoter.debug then
|
||||||
|
print(string.format("[%s] Channel name does not match any of the channels", ModuleName))
|
||||||
|
end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
if channelname ~= Heimdall_Data.config.emoter.masterChannel then return end
|
if Heimdall_Data.config.emoter.debug then
|
||||||
|
print(string.format("[%s] Processing message from master channel: %s", ModuleName, sender))
|
||||||
|
shared.dump(Heimdall_Data.config.emoter)
|
||||||
|
end
|
||||||
|
|
||||||
if string.find(msg, "^" .. Heimdall_Data.config.emoter.prefix) then
|
if string.find(msg, "^" .. Heimdall_Data.config.emoter.prefix) then
|
||||||
|
if Heimdall_Data.config.emoter.debug then
|
||||||
|
print(string.format("[%s] Found emote command in message: %s", ModuleName, msg))
|
||||||
|
end
|
||||||
local emote = string.sub(msg, string.len(Heimdall_Data.config.emoter.prefix) + 1)
|
local emote = string.sub(msg, string.len(Heimdall_Data.config.emoter.prefix) + 1)
|
||||||
|
if Heimdall_Data.config.emoter.debug then
|
||||||
|
print(string.format("[%s] Performing emote: %s", ModuleName, emote))
|
||||||
|
end
|
||||||
DoEmote(emote)
|
DoEmote(emote)
|
||||||
|
elseif Heimdall_Data.config.emoter.debug then
|
||||||
|
print(string.format("[%s] Message does not start with emote prefix", ModuleName))
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
print("Heimdall - Emoter loaded")
|
|
||||||
end
|
if Heimdall_Data.config.emoter.debug then print(string.format("[%s] Module initialized", ModuleName)) end
|
||||||
|
print(string.format("[%s] Module initialized", ModuleName))
|
||||||
|
end,
|
||||||
|
}
|
||||||
|
@@ -1,59 +1,143 @@
|
|||||||
local addonname, shared = ...
|
local _, shared = ...
|
||||||
---@cast shared HeimdallShared
|
---@cast shared HeimdallShared
|
||||||
---@cast addonname string
|
local ModuleName = "Inviter"
|
||||||
|
|
||||||
---@diagnostic disable-next-line: missing-fields
|
---@class HeimdallInviterConfig
|
||||||
shared.Inviter = {}
|
---@field enabled boolean
|
||||||
function shared.Inviter.Init()
|
---@field debug boolean
|
||||||
|
---@field channels string[]
|
||||||
|
---@field keyword string
|
||||||
|
---@field allAssist boolean
|
||||||
|
---@field agentsAssist boolean
|
||||||
|
---@field throttle number
|
||||||
|
---@field kickOffline boolean
|
||||||
|
---@field cleanupInterval number
|
||||||
|
---@field afkThreshold number
|
||||||
|
---@field listeningChannel table<string, boolean>
|
||||||
|
|
||||||
|
---@class Inviter
|
||||||
|
shared.Inviter = {
|
||||||
|
Init = function()
|
||||||
|
-- Fallback for old config
|
||||||
|
if type(Heimdall_Data.config.inviter.listeningChannel) == "string" then
|
||||||
|
Heimdall_Data.config.inviter.listeningChannel = {
|
||||||
|
[Heimdall_Data.config.inviter.listeningChannel] = true,
|
||||||
|
}
|
||||||
|
end
|
||||||
---@type Timer
|
---@type Timer
|
||||||
local updateTimer = nil
|
local updateTimer = nil
|
||||||
|
|
||||||
local function FixGroup()
|
local function FixGroup()
|
||||||
if not IsInRaid() then ConvertToRaid() end
|
if Heimdall_Data.config.inviter.debug then
|
||||||
if Heimdall_Data.config.inviter.allAssist then SetEveryoneIsAssistant() end
|
print(string.format("[%s] Checking and fixing group configuration", ModuleName))
|
||||||
--shared.dumpTable(Heimdall_Data.config.inviter)
|
end
|
||||||
|
|
||||||
|
if not IsInRaid() then
|
||||||
|
if Heimdall_Data.config.inviter.debug then
|
||||||
|
print(string.format("[%s] Converting party to raid", ModuleName))
|
||||||
|
end
|
||||||
|
ConvertToRaid()
|
||||||
|
end
|
||||||
|
|
||||||
|
if Heimdall_Data.config.inviter.allAssist then
|
||||||
|
if Heimdall_Data.config.inviter.debug then
|
||||||
|
print(string.format("[%s] Setting all members to assistant", ModuleName))
|
||||||
|
end
|
||||||
|
SetEveryoneIsAssistant()
|
||||||
|
end
|
||||||
|
|
||||||
if Heimdall_Data.config.inviter.agentsAssist then
|
if Heimdall_Data.config.inviter.agentsAssist then
|
||||||
--shared.dumpTable(Heimdall_Data.config.agents)
|
if Heimdall_Data.config.inviter.debug then
|
||||||
for name, _ in pairs(Heimdall_Data.config.agents) do
|
print(string.format("[%s] Processing agents for assistant promotion", ModuleName))
|
||||||
if UnitInParty(name)
|
end
|
||||||
and not UnitIsGroupLeader(name)
|
|
||||||
and not UnitIsRaidOfficer(name) then
|
shared.AgentTracker.ForEach(function(agent)
|
||||||
print("Promoting " .. name .. " to assistant")
|
if UnitInParty(agent) and not UnitIsGroupLeader(agent) and not UnitIsRaidOfficer(agent) then
|
||||||
PromoteToAssistant(name, true)
|
if Heimdall_Data.config.inviter.debug then
|
||||||
|
print(string.format("[%s] Promoting agent to assistant: %s", ModuleName, agent))
|
||||||
|
end
|
||||||
|
PromoteToAssistant(agent, true)
|
||||||
|
elseif Heimdall_Data.config.inviter.debug then
|
||||||
|
if not UnitInParty(agent) then
|
||||||
|
print(string.format("[%s] Agent not in party: %s", ModuleName, agent))
|
||||||
|
elseif UnitIsGroupLeader(agent) then
|
||||||
|
print(string.format("[%s] Agent is already leader: %s", ModuleName, agent))
|
||||||
|
elseif UnitIsRaidOfficer(agent) then
|
||||||
|
print(string.format("[%s] Agent is already assistant: %s", ModuleName, agent))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
if Heimdall_Data.config.inviter.debug then
|
||||||
|
print(string.format("[%s] Group configuration update complete", ModuleName))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local framePool = {}
|
|
||||||
---@param name string
|
---@param name string
|
||||||
local function OverlayKickButtonElvUI(name)
|
---@return Frame?
|
||||||
|
local function FindPlayerRaidFrame(name)
|
||||||
for group = 1, 8 do
|
for group = 1, 8 do
|
||||||
for player = 1, 5 do
|
for player = 1, 5 do
|
||||||
local button = _G[string.format("ElvUF_RaidGroup%dUnitButton%d", group, player)]
|
local button = _G[string.format("ElvUF_RaidGroup%dUnitButton%d", group, player)]
|
||||||
|
if Heimdall_Data.config.inviter.debug then
|
||||||
|
print(string.format("[%s] button = %s", ModuleName, tostring(button)))
|
||||||
|
end
|
||||||
|
|
||||||
local unitName = button and button.unit and UnitName(button.unit)
|
local unitName = button and button.unit and UnitName(button.unit)
|
||||||
|
if Heimdall_Data.config.inviter.debug then
|
||||||
|
print(string.format("[%s] unitName = %s", ModuleName, tostring(unitName)))
|
||||||
|
end
|
||||||
if unitName == name then
|
if unitName == name then
|
||||||
local overlayButton = framePool[button.unit] or
|
if Heimdall_Data.config.inviter.debug then
|
||||||
CreateFrame("Button",
|
print(string.format("[%s] unitName == name", ModuleName))
|
||||||
string.format("HeimdallKickButton%s", button.unit, button, "SecureActionButtonTemplate"))
|
end
|
||||||
framePool[button.unit] = overlayButton
|
return button
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
overlayButton:SetSize(button.UNIT_WIDTH/2, button.UNIT_HEIGHT/2)
|
local framePool = {}
|
||||||
overlayButton:SetPoint("CENTER", button, "CENTER", 0, 0)
|
local playerButtons = {}
|
||||||
overlayButton:SetNormalTexture("Interface\\Buttons\\UI-GroupLoot-KickIcon")
|
setmetatable(playerButtons, { __mode = "kv" })
|
||||||
overlayButton:SetHighlightTexture("Interface\\Buttons\\UI-GroupLoot-KickIcon")
|
---@param players string[]
|
||||||
overlayButton:SetPushedTexture("Interface\\Buttons\\UI-GroupLoot-KickIcon")
|
local function OverlayKickButtons(players)
|
||||||
overlayButton:SetDisabledTexture("Interface\\Buttons\\UI-GroupLoot-KickIcon")
|
for _, frame in pairs(framePool) do
|
||||||
overlayButton:SetAlpha(0.5)
|
frame:Hide()
|
||||||
overlayButton:Show()
|
end
|
||||||
overlayButton:SetScript("OnClick", function()
|
for _, name in pairs(players) do
|
||||||
|
local frame = FindPlayerRaidFrame(name)
|
||||||
|
if frame then
|
||||||
|
playerButtons[name] = frame
|
||||||
|
-- All of these are ELVUI specific so they won't be in our meta...
|
||||||
|
---@diagnostic disable-next-line: undefined-field
|
||||||
|
local button = framePool[frame.unit]
|
||||||
|
or CreateFrame(
|
||||||
|
"Button",
|
||||||
|
---@diagnostic disable-next-line: undefined-field
|
||||||
|
string.format("HeimdallKickButton%s", frame.unit, frame, "SecureActionButtonTemplate")
|
||||||
|
)
|
||||||
|
---@diagnostic disable-next-line: undefined-field
|
||||||
|
framePool[frame.unit] = button
|
||||||
|
|
||||||
|
---@diagnostic disable-next-line: undefined-field
|
||||||
|
button:SetSize(frame.UNIT_WIDTH / 2, frame.UNIT_HEIGHT / 2)
|
||||||
|
button:SetPoint("CENTER", frame, "CENTER", 0, 0)
|
||||||
|
button:SetNormalTexture("Interface\\Buttons\\UI-GroupLoot-KickIcon")
|
||||||
|
button:SetHighlightTexture("Interface\\Buttons\\UI-GroupLoot-KickIcon")
|
||||||
|
button:SetPushedTexture("Interface\\Buttons\\UI-GroupLoot-KickIcon")
|
||||||
|
button:SetDisabledTexture("Interface\\Buttons\\UI-GroupLoot-KickIcon")
|
||||||
|
button:SetAlpha(0.5)
|
||||||
|
button:Show()
|
||||||
|
button:SetScript("OnClick", function()
|
||||||
UninviteUnit(name)
|
UninviteUnit(name)
|
||||||
overlayButton:Hide()
|
button:Hide()
|
||||||
end)
|
end)
|
||||||
-- button:SetAttribute("type", "macro")
|
else
|
||||||
-- button:SetAttribute("macrotext", "/kick " .. unit)
|
if Heimdall_Data.config.inviter.debug then
|
||||||
return
|
print(string.format("[%s] Frame for player %s not found", ModuleName, name))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -77,38 +161,50 @@ function shared.Inviter.Init()
|
|||||||
groupMembers[name] = now
|
groupMembers[name] = now
|
||||||
else
|
else
|
||||||
local online = UnitIsConnected(unit)
|
local online = UnitIsConnected(unit)
|
||||||
if online then
|
if online then groupMembers[name] = now end
|
||||||
groupMembers[name] = now
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
local afkPlayers = {}
|
||||||
for name, time in pairs(groupMembers) do
|
for name, time in pairs(groupMembers) do
|
||||||
if time < now - Heimdall_Data.config.inviter.afkThreshold then
|
|
||||||
print(string.format("Kicking %s for being offline", name))
|
|
||||||
-- Blyat this is protected...
|
|
||||||
-- UninviteUnit(name)
|
|
||||||
OverlayKickButtonElvUI(name)
|
|
||||||
end
|
|
||||||
if not UnitInParty(name) then
|
if not UnitInParty(name) then
|
||||||
print(string.format("%s no longer in party", name))
|
print(string.format("%s no longer in party", name))
|
||||||
groupMembers[name] = nil
|
groupMembers[name] = nil
|
||||||
|
else
|
||||||
|
if time < now - Heimdall_Data.config.inviter.afkThreshold then
|
||||||
|
print(string.format("Kicking %s for being offline", name))
|
||||||
|
afkPlayers[#afkPlayers + 1] = name
|
||||||
|
-- Blyat this is protected...
|
||||||
|
-- UninviteUnit(name)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
OverlayKickButtons(afkPlayers)
|
||||||
|
end
|
||||||
local function Tick()
|
local function Tick()
|
||||||
CleanGroups()
|
CleanGroups()
|
||||||
C_Timer.NewTimer(Heimdall_Data.config.inviter.cleanupInterval, Tick, 1)
|
C_Timer.NewTimer(Heimdall_Data.config.inviter.cleanupInterval, Tick, 1)
|
||||||
end
|
end
|
||||||
Tick()
|
Tick()
|
||||||
|
|
||||||
local inviterGroupFrame = CreateFrame("Frame")
|
local groupRosterUpdateFrame = CreateFrame("Frame")
|
||||||
inviterGroupFrame:RegisterEvent("GROUP_ROSTER_UPDATE")
|
groupRosterUpdateFrame:RegisterEvent("GROUP_ROSTER_UPDATE")
|
||||||
inviterGroupFrame:SetScript("OnEvent", function(self, event, ...)
|
groupRosterUpdateFrame:SetScript("OnEvent", function(self, event, ...)
|
||||||
if not Heimdall_Data.config.inviter.enabled then return end
|
if Heimdall_Data.config.inviter.debug then
|
||||||
if not UnitIsGroupLeader("player") then return end
|
print(string.format("[%s] Event received: %s", ModuleName, event))
|
||||||
|
end
|
||||||
|
|
||||||
|
if not Heimdall_Data.config.inviter.enabled then
|
||||||
|
if Heimdall_Data.config.inviter.debug then
|
||||||
|
print(string.format("[%s] Module disabled, ignoring event", ModuleName))
|
||||||
|
end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
if Heimdall_Data.config.inviter.debug then
|
||||||
|
print(string.format("[%s] Group roster changed - Checking configuration", ModuleName))
|
||||||
|
end
|
||||||
if updateTimer then updateTimer:Cancel() end
|
if updateTimer then updateTimer:Cancel() end
|
||||||
updateTimer = C_Timer.NewTimer(Heimdall_Data.config.inviter.throttle, FixGroup)
|
updateTimer = C_Timer.NewTimer(Heimdall_Data.config.inviter.throttle, FixGroup)
|
||||||
end)
|
end)
|
||||||
@@ -116,24 +212,64 @@ function shared.Inviter.Init()
|
|||||||
local inviterChannelFrame = CreateFrame("Frame")
|
local inviterChannelFrame = CreateFrame("Frame")
|
||||||
inviterChannelFrame:RegisterEvent("CHAT_MSG_CHANNEL")
|
inviterChannelFrame:RegisterEvent("CHAT_MSG_CHANNEL")
|
||||||
inviterChannelFrame:SetScript("OnEvent", function(self, event, msg, sender, ...)
|
inviterChannelFrame:SetScript("OnEvent", function(self, event, msg, sender, ...)
|
||||||
|
--if Heimdall_Data.config.inviter.debug then
|
||||||
|
-- print(string.format("[%s] Chat message received: %s", ModuleName, msg))
|
||||||
|
-- shared.dump(Heimdall_Data.config.inviter)
|
||||||
|
--end
|
||||||
if not Heimdall_Data.config.inviter.enabled then return end
|
if not Heimdall_Data.config.inviter.enabled then return end
|
||||||
local channelId = select(6, ...)
|
local channelId = select(6, ...)
|
||||||
local channelname = ""
|
local _, channelname = GetChannelName(channelId)
|
||||||
---@type any[]
|
if Heimdall_Data.config.inviter.debug then
|
||||||
local channels = { GetChannelList() }
|
print(string.format("[%s] Channel name: %s", ModuleName, channelname))
|
||||||
for i = 1, #channels, 2 do
|
end
|
||||||
---@type number
|
|
||||||
local id = channels[i]
|
local ok = false
|
||||||
---@type string
|
for _, channel in pairs(Heimdall_Data.config.inviter.channels) do
|
||||||
local name = channels[i + 1]
|
if channel == channelname then
|
||||||
if id == channelId then
|
ok = true
|
||||||
channelname = name
|
break
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if channelname ~= Heimdall_Data.config.inviter.listeningChannel then return end
|
if not ok then
|
||||||
if msg == Heimdall_Data.config.inviter.keyword then InviteUnit(sender) end
|
if Heimdall_Data.config.inviter.debug then
|
||||||
|
print(string.format("[%s] Channel name does not match any of the channels", ModuleName))
|
||||||
|
end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
if msg == Heimdall_Data.config.inviter.keyword then
|
||||||
|
if Heimdall_Data.config.inviter.debug then
|
||||||
|
print(string.format("[%s] Inviting %s", ModuleName, sender))
|
||||||
|
end
|
||||||
|
InviteUnit(sender)
|
||||||
|
else
|
||||||
|
if Heimdall_Data.config.inviter.debug then
|
||||||
|
print(string.format("[%s] Message does not match keyword", ModuleName))
|
||||||
|
end
|
||||||
|
end
|
||||||
end)
|
end)
|
||||||
|
|
||||||
print("Heimdall - Inviter loaded")
|
if Heimdall_Data.config.inviter.debug then
|
||||||
end
|
print(
|
||||||
|
string.format(
|
||||||
|
"[%s] Module initialized - All assist: %s, Agents assist: %s",
|
||||||
|
ModuleName,
|
||||||
|
tostring(Heimdall_Data.config.inviter.allAssist),
|
||||||
|
tostring(Heimdall_Data.config.inviter.agentsAssist)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
if Heimdall_Data.config.inviter.debug then
|
||||||
|
print(
|
||||||
|
string.format(
|
||||||
|
"[%s] Module initialized - All assist: %s, Agents assist: %s",
|
||||||
|
ModuleName,
|
||||||
|
tostring(Heimdall_Data.config.inviter.allAssist),
|
||||||
|
tostring(Heimdall_Data.config.inviter.agentsAssist)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
end
|
||||||
|
print(string.format("[%s] Module initialized", ModuleName))
|
||||||
|
end,
|
||||||
|
}
|
||||||
|
@@ -1,32 +1,49 @@
|
|||||||
local addonname, shared = ...
|
local _, shared = ...
|
||||||
---@cast shared HeimdallShared
|
---@cast shared HeimdallShared
|
||||||
---@cast addonname string
|
local ModuleName = "Macroer"
|
||||||
|
|
||||||
---@diagnostic disable-next-line: missing-fields
|
---@class HeimdallMacroerConfig
|
||||||
shared.Macroer = {}
|
---@field enabled boolean
|
||||||
function shared.Macroer.Init()
|
---@field debug boolean
|
||||||
---@class stinky
|
---@field priority string[]
|
||||||
---@field name string
|
|
||||||
---@field class string
|
|
||||||
---@field seenAt number
|
|
||||||
---@field hostile boolean
|
|
||||||
|
|
||||||
---@type table<string, stinky>
|
|
||||||
local recentStinkies = {}
|
|
||||||
|
|
||||||
|
---@class Macroer
|
||||||
|
shared.Macroer = {
|
||||||
|
Init = function()
|
||||||
local function FindOrCreateMacro(macroName)
|
local function FindOrCreateMacro(macroName)
|
||||||
|
if Heimdall_Data.config.macroer.debug then
|
||||||
|
print(string.format("[%s] Finding or creating macro: %s", ModuleName, macroName))
|
||||||
|
end
|
||||||
local idx = GetMacroIndexByName(macroName)
|
local idx = GetMacroIndexByName(macroName)
|
||||||
if idx == 0 then
|
if idx == 0 then
|
||||||
|
if Heimdall_Data.config.macroer.debug then
|
||||||
|
print(string.format("[%s] Creating new macro: %s", ModuleName, macroName))
|
||||||
|
end
|
||||||
CreateMacro(macroName, "INV_Misc_QuestionMark", "")
|
CreateMacro(macroName, "INV_Misc_QuestionMark", "")
|
||||||
end
|
end
|
||||||
idx = GetMacroIndexByName(macroName)
|
idx = GetMacroIndexByName(macroName)
|
||||||
|
if Heimdall_Data.config.macroer.debug then print(string.format("[%s] Macro index: %d", ModuleName, idx)) end
|
||||||
return idx
|
return idx
|
||||||
end
|
end
|
||||||
|
|
||||||
---@param stinkies table<string, stinky>
|
---@param stinkies table<string, Stinky>
|
||||||
local function FixMacro(stinkies)
|
local function FixMacro(stinkies)
|
||||||
if not Heimdall_Data.config.macroer.enabled then return end
|
if Heimdall_Data.config.macroer.debug then
|
||||||
if InCombatLockdown() then return end
|
print(string.format("[%s] Fixing macro with %d stinkies", ModuleName, #stinkies))
|
||||||
|
end
|
||||||
|
if not Heimdall_Data.config.macroer.enabled then
|
||||||
|
if Heimdall_Data.config.macroer.debug then
|
||||||
|
print(string.format("[%s] Module disabled, skipping macro update", ModuleName))
|
||||||
|
end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
if InCombatLockdown() then
|
||||||
|
if Heimdall_Data.config.macroer.debug then
|
||||||
|
print(string.format("[%s] In combat, skipping macro update", ModuleName))
|
||||||
|
end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
local priorityMap = {}
|
local priorityMap = {}
|
||||||
for priority, className in ipairs(Heimdall_Data.config.macroer.priority) do
|
for priority, className in ipairs(Heimdall_Data.config.macroer.priority) do
|
||||||
priorityMap[className] = priority
|
priorityMap[className] = priority
|
||||||
@@ -35,7 +52,11 @@ function shared.Macroer.Init()
|
|||||||
|
|
||||||
local sortedStinkies = {}
|
local sortedStinkies = {}
|
||||||
for _, stinky in pairs(stinkies) do
|
for _, stinky in pairs(stinkies) do
|
||||||
table.insert(sortedStinkies, stinky)
|
if not shared.AgentTracker.IsAgent(stinky.name) then sortedStinkies[#sortedStinkies + 1] = stinky end
|
||||||
|
end
|
||||||
|
|
||||||
|
if Heimdall_Data.config.macroer.debug then
|
||||||
|
print(string.format("[%s] Processing %d non-agent stinkies", ModuleName, #sortedStinkies))
|
||||||
end
|
end
|
||||||
|
|
||||||
table.sort(sortedStinkies, function(a, b)
|
table.sort(sortedStinkies, function(a, b)
|
||||||
@@ -44,22 +65,37 @@ function shared.Macroer.Init()
|
|||||||
return aPriority > bPriority
|
return aPriority > bPriority
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
if Heimdall_Data.config.macroer.debug then
|
||||||
|
print(string.format("[%s] Sorted stinkies: %d", ModuleName, #sortedStinkies))
|
||||||
|
shared.dump(sortedStinkies)
|
||||||
|
end
|
||||||
local lines = { "/targetenemy" }
|
local lines = { "/targetenemy" }
|
||||||
for _, stinky in pairs(sortedStinkies) do
|
for _, stinky in pairs(sortedStinkies) do
|
||||||
if stinky.seenAt > GetTime() - 600 then
|
if stinky.seenAt > GetTime() - 600 then
|
||||||
print(string.format("Macroing %s", stinky.name))
|
if Heimdall_Data.config.macroer.debug then
|
||||||
|
print(string.format("[%s] Adding target macro for: %s", ModuleName, stinky.name))
|
||||||
|
end
|
||||||
lines[#lines + 1] = string.format("/tar %s", stinky.name)
|
lines[#lines + 1] = string.format("/tar %s", stinky.name)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local idx = FindOrCreateMacro("HeimdallTarget")
|
local idx = FindOrCreateMacro("HeimdallTarget")
|
||||||
|
---@diagnostic disable-next-line: param-type-mismatch
|
||||||
local body = strjoin("\n", unpack(lines))
|
local body = strjoin("\n", unpack(lines))
|
||||||
|
if Heimdall_Data.config.macroer.debug then
|
||||||
|
print(string.format("[%s] Updating macro with %d lines", ModuleName, #lines))
|
||||||
|
end
|
||||||
EditMacro(idx, "HeimdallTarget", "INV_Misc_QuestionMark", body)
|
EditMacro(idx, "HeimdallTarget", "INV_Misc_QuestionMark", body)
|
||||||
end
|
end
|
||||||
|
|
||||||
shared.stinkyTracker.stinkies:onChange(function(value)
|
shared.StinkyTracker.OnChange(function(stinkies)
|
||||||
FixMacro(value)
|
if Heimdall_Data.config.macroer.debug then
|
||||||
|
print(string.format("[%s] Stinkies changed, updating macro", ModuleName))
|
||||||
|
shared.dump(stinkies)
|
||||||
|
end
|
||||||
|
FixMacro(stinkies)
|
||||||
end)
|
end)
|
||||||
|
if Heimdall_Data.config.macroer.debug then print(string.format("[%s] Module initialized", ModuleName)) end
|
||||||
print("Heimdall - Macroer loaded")
|
print(string.format("[%s] Module initialized", ModuleName))
|
||||||
end
|
end,
|
||||||
|
}
|
||||||
|
@@ -1,30 +1,36 @@
|
|||||||
local addonname, shared = ...
|
local _, shared = ...
|
||||||
---@cast shared HeimdallShared
|
---@cast shared HeimdallShared
|
||||||
---@cast addonname string
|
local ModuleName = "Messenger"
|
||||||
|
|
||||||
---@diagnostic disable-next-line: missing-fields
|
---@class HeimdallMessengerConfig
|
||||||
shared.Messenger = {}
|
---@field enabled boolean
|
||||||
function shared.Messenger.Init()
|
---@field debug boolean
|
||||||
---@class Message
|
---@field interval number
|
||||||
---@field message string
|
|
||||||
---@field channel string
|
|
||||||
---@field data string
|
|
||||||
|
|
||||||
local function GetChannelId(channelName)
|
---@class HeimdallMessengerData
|
||||||
local channels = { GetChannelList() }
|
---@field queue ReactiveValue<table<string, Message>>
|
||||||
for i = 1, #channels, 2 do
|
---@field ticker Timer?
|
||||||
local id = channels[i]
|
|
||||||
local name = channels[i + 1]
|
---@class Message
|
||||||
if name == channelName then
|
---@field message string
|
||||||
return id
|
---@field channel string
|
||||||
end
|
---@field data string
|
||||||
end
|
|
||||||
end
|
---@class Messenger
|
||||||
|
shared.Messenger = {
|
||||||
|
---@param message Message
|
||||||
|
Enqueue = function(message) table.insert(shared.messenger.queue, message) end,
|
||||||
|
Init = function()
|
||||||
|
shared.messenger = {
|
||||||
|
queue = ReactiveValue.new({}),
|
||||||
|
}
|
||||||
|
|
||||||
local function FindOrJoinChannel(channelName, password)
|
local function FindOrJoinChannel(channelName, password)
|
||||||
local channelId = GetChannelName(channelName)
|
local channelId = GetChannelName(channelName)
|
||||||
if channelId == 0 then
|
if channelId == 0 then
|
||||||
print("Channel", tostring(channelName), "not found, joining")
|
if Heimdall_Data.config.messenger.debug then
|
||||||
|
print(string.format("[%s] Channel not found, joining: %s", ModuleName, channelName))
|
||||||
|
end
|
||||||
if password then
|
if password then
|
||||||
JoinPermanentChannel(channelName, password)
|
JoinPermanentChannel(channelName, password)
|
||||||
else
|
else
|
||||||
@@ -32,53 +38,139 @@ function shared.Messenger.Init()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
channelId = GetChannelName(channelName)
|
channelId = GetChannelName(channelName)
|
||||||
|
if Heimdall_Data.config.messenger.debug then
|
||||||
|
print(string.format("[%s] Channel found with ID: %s (%s)", ModuleName, channelId, channelName))
|
||||||
|
end
|
||||||
return channelId
|
return channelId
|
||||||
end
|
end
|
||||||
|
|
||||||
---@diagnostic disable-next-line: missing-fields
|
|
||||||
if not shared.messenger then shared.messenger = {} end
|
|
||||||
if not shared.messenger.queue then shared.messenger.queue = {} end
|
|
||||||
if not shared.messenger.ticker then
|
if not shared.messenger.ticker then
|
||||||
local function DoMessage()
|
local function DoMessage()
|
||||||
if not Heimdall_Data.config.messenger.enabled then return end
|
-- if Heimdall_Data.config.messenger.debug then
|
||||||
|
-- print(
|
||||||
|
-- string.format(
|
||||||
|
-- "[%s] Processing message queue - Size: %d",
|
||||||
|
-- ModuleName,
|
||||||
|
-- #shared.messenger.queue:get()
|
||||||
|
-- )
|
||||||
|
-- )
|
||||||
|
-- end
|
||||||
|
|
||||||
|
if not Heimdall_Data.config.messenger.enabled then
|
||||||
|
-- if Heimdall_Data.config.messenger.debug then
|
||||||
|
-- print(string.format("[%s] Module disabled, skipping message processing", ModuleName))
|
||||||
|
-- end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
---@type Message
|
---@type Message
|
||||||
local message = shared.messenger.queue[1]
|
local message = shared.messenger.queue[1]
|
||||||
if not message then return end
|
if not message then
|
||||||
if not message.message or message.message == "" then return end
|
-- if Heimdall_Data.config.messenger.debug then
|
||||||
if not message.channel or message.channel == "" then return end
|
-- print(string.format("[%s] Message queue empty", ModuleName))
|
||||||
|
-- end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
if Heimdall_Data.config.messenger.debug then shared.dump(message, "[%s] Processing message:") end
|
||||||
|
|
||||||
|
if not message.message or message.message == "" then
|
||||||
|
if Heimdall_Data.config.messenger.debug then
|
||||||
|
shared.dump(message, string.format("[%s] Invalid message: empty content", ModuleName))
|
||||||
|
end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
if not message.channel or message.channel == "" then
|
||||||
|
if Heimdall_Data.config.messenger.debug then
|
||||||
|
shared.dump(message, string.format("[%s] Invalid message: no channel specified", ModuleName))
|
||||||
|
end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
if string.find(message.channel, "^C") then
|
||||||
|
if Heimdall_Data.config.messenger.debug then
|
||||||
|
shared.dump(
|
||||||
|
message,
|
||||||
|
string.format("[%s] Converting channel type from C to CHANNEL", ModuleName)
|
||||||
|
)
|
||||||
|
end
|
||||||
|
message.channel = "CHANNEL"
|
||||||
|
elseif string.find(message.channel, "^W") then
|
||||||
|
if Heimdall_Data.config.messenger.debug then
|
||||||
|
shared.dump(
|
||||||
|
message,
|
||||||
|
string.format("[%s] Converting channel type from W to WHISPER", ModuleName)
|
||||||
|
)
|
||||||
|
end
|
||||||
|
message.channel = "WHISPER"
|
||||||
|
end
|
||||||
|
|
||||||
if message.channel == "CHANNEL" and message.data and string.match(message.data, "%D") then
|
if message.channel == "CHANNEL" and message.data and string.match(message.data, "%D") then
|
||||||
print("Channel presented as string:", message.data)
|
if Heimdall_Data.config.messenger.debug then
|
||||||
|
shared.dump(message, string.format("[%s] Processing channel message:", ModuleName))
|
||||||
|
end
|
||||||
local channelId = GetChannelName(message.data)
|
local channelId = GetChannelName(message.data)
|
||||||
if channelId == 0 then
|
if channelId == 0 then
|
||||||
print("Channel not found, joining")
|
if Heimdall_Data.config.messenger.debug then
|
||||||
channelId = FindOrJoinChannel(message.data)
|
shared.dump(message, string.format("[%s] Channel not found, joining:", ModuleName))
|
||||||
|
end
|
||||||
|
channelId = FindOrJoinChannel(message.data)
|
||||||
|
if Heimdall_Data.config.messenger.debug then
|
||||||
|
print(string.format("[%s] Channel join result - ID: %s", ModuleName, channelId))
|
||||||
|
end
|
||||||
end
|
end
|
||||||
print("Channel resolved to id", channelId)
|
|
||||||
message.data = tostring(channelId)
|
message.data = tostring(channelId)
|
||||||
end
|
end
|
||||||
|
|
||||||
table.remove(shared.messenger.queue, 1)
|
table.remove(shared.messenger.queue, 1)
|
||||||
if not message.message or message.message == "" then return end
|
if not message.message or message.message == "" then
|
||||||
if not message.channel or message.channel == "" then return end
|
if Heimdall_Data.config.messenger.debug then
|
||||||
if not message.data or message.data == "" then return end
|
shared.dump(message, string.format("[%s] Skipping empty message", ModuleName))
|
||||||
|
end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
if not message.channel or message.channel == "" then
|
||||||
|
if Heimdall_Data.config.messenger.debug then
|
||||||
|
shared.dump(message, string.format("[%s] Skipping message with no channel", ModuleName))
|
||||||
|
end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
if not message.data or message.data == "" then
|
||||||
|
if Heimdall_Data.config.messenger.debug then
|
||||||
|
shared.dump(message, string.format("[%s] Skipping message with no data", ModuleName))
|
||||||
|
end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
if Heimdall_Data.config.messenger.debug then
|
||||||
|
shared.dump(message, string.format("[%s] Sending message:", ModuleName))
|
||||||
|
end
|
||||||
|
if string.len(message.message) > 255 then
|
||||||
|
shared.dump(message, string.format("[%s] Message too long!!!!: %s", ModuleName, message.message))
|
||||||
|
return
|
||||||
|
end
|
||||||
SendChatMessage(message.message, message.channel, nil, message.data)
|
SendChatMessage(message.message, message.channel, nil, message.data)
|
||||||
end
|
end
|
||||||
local function Tick()
|
local function Tick()
|
||||||
|
-- if Heimdall_Data.config.messenger.debug then
|
||||||
|
-- print(string.format("[%s] Tick - Queue size: %d", ModuleName, #shared.messenger.queue:get()))
|
||||||
|
-- end
|
||||||
DoMessage()
|
DoMessage()
|
||||||
shared.messenger.ticker = C_Timer.NewTimer(Heimdall_Data.config.messenger.interval, Tick, 1)
|
shared.messenger.ticker = C_Timer.NewTimer(Heimdall_Data.config.messenger.interval, Tick, 1)
|
||||||
end
|
end
|
||||||
Tick()
|
Tick()
|
||||||
end
|
end
|
||||||
|
|
||||||
--C_Timer.NewTicker(2, function()
|
if Heimdall_Data.config.messenger.debug then
|
||||||
-- print("Q")
|
print(
|
||||||
-- table.insert(data.messenger.queue, {
|
string.format(
|
||||||
-- channel = "CHANNEL",
|
"[%s] Module initialized with interval: %s",
|
||||||
-- data = "Foobar",
|
ModuleName,
|
||||||
-- message = "TEST"
|
Heimdall_Data.config.messenger.interval
|
||||||
-- })
|
)
|
||||||
--end)
|
)
|
||||||
|
end
|
||||||
print("Heimdall - Messenger loaded")
|
print(string.format("[%s] Module initialized", ModuleName))
|
||||||
end
|
end,
|
||||||
|
}
|
||||||
|
597
Modules/MinimapTagger.lua
Normal file
597
Modules/MinimapTagger.lua
Normal file
@@ -0,0 +1,597 @@
|
|||||||
|
local _, shared = ...
|
||||||
|
---@cast shared HeimdallShared
|
||||||
|
local ModuleName = "MinimapTagger"
|
||||||
|
|
||||||
|
---@class HeimdallMinimapTaggerConfig
|
||||||
|
---@field enabled boolean
|
||||||
|
---@field debug boolean
|
||||||
|
---@field channels string[]
|
||||||
|
---@field throttle number
|
||||||
|
---@field scale number
|
||||||
|
---@field tagTTL number
|
||||||
|
---@field tagSound boolean
|
||||||
|
---@field tagSoundFile string
|
||||||
|
---@field tagSoundThrottle number
|
||||||
|
---@field tagTextureFile string
|
||||||
|
---@field alertTTL number
|
||||||
|
---@field alertSound boolean
|
||||||
|
---@field alertSoundFile string
|
||||||
|
---@field alertSoundThrottle number
|
||||||
|
---@field alertTextureFile string
|
||||||
|
---@field combatTTL number
|
||||||
|
---@field combatSound boolean
|
||||||
|
---@field combatSoundFile string
|
||||||
|
---@field combatSoundThrottle number
|
||||||
|
---@field combatTextureFile string
|
||||||
|
---@field helpTTL number
|
||||||
|
---@field helpSound boolean
|
||||||
|
---@field helpSoundFile string
|
||||||
|
---@field helpSoundThrottle number
|
||||||
|
---@field helpTextureFile string
|
||||||
|
|
||||||
|
local HeimdallRoot = "Interface\\AddOns\\Heimdall\\"
|
||||||
|
local SoundRoot = HeimdallRoot .. "Sounds\\"
|
||||||
|
local TextureRoot = HeimdallRoot .. "Texture\\"
|
||||||
|
--/run local a=GetChannelName("Agent")local b,c=GetPlayerMapPosition("player")b,c=b*100,c*100;local d=string.format("I need help at %s (%s) [%s](%2.2f, %2.2f)",GetZoneText(),GetSubZoneText(),GetCurrentMapAreaID(),b,c)SendChatMessage(d,"CHANNEL",nil,a)
|
||||||
|
|
||||||
|
---@class MinimapTagger
|
||||||
|
shared.MinimapTagger = {
|
||||||
|
Init = function()
|
||||||
|
---@param x number
|
||||||
|
---@param y number
|
||||||
|
---@param frame Frame
|
||||||
|
---@param scale number?
|
||||||
|
---@param ttl number?
|
||||||
|
local function PlantFrame(x, y, frame, scale, ttl)
|
||||||
|
if not BattlefieldMinimap then
|
||||||
|
if Heimdall_Data.config.minimapTagger.debug then
|
||||||
|
print(string.format("[%s] BattlefieldMinimap not found", ModuleName))
|
||||||
|
end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
scale = scale or 1
|
||||||
|
ttl = ttl or 1
|
||||||
|
local w, h = BattlefieldMinimap:GetSize()
|
||||||
|
w, h = w * BattlefieldMinimap:GetEffectiveScale(), h * BattlefieldMinimap:GetEffectiveScale()
|
||||||
|
local maxSize = w > h and w or h
|
||||||
|
if Heimdall_Data.config.minimapTagger.debug then
|
||||||
|
print(string.format("[%s] Minimap size: %d", ModuleName, maxSize))
|
||||||
|
print(string.format("[%s] Scale: %d", ModuleName, scale))
|
||||||
|
print(string.format("[%s] TTL: %d", ModuleName, ttl))
|
||||||
|
end
|
||||||
|
local iconSize = maxSize * 0.05
|
||||||
|
iconSize = iconSize * scale
|
||||||
|
|
||||||
|
x, y = x / 100, y / 100
|
||||||
|
-- Could do with how... I have no idea, but this seems more accurate than without
|
||||||
|
--x, y = x - 0.01, y - 0.01
|
||||||
|
local offsetx, offsety = w * x, h * y
|
||||||
|
if Heimdall_Data.config.minimapTagger.debug then
|
||||||
|
print(string.format("[%s] Alert position: %d, %d", ModuleName, x, y))
|
||||||
|
print(string.format("[%s] Alert offset: %d, %d", ModuleName, offsetx, offsety))
|
||||||
|
end
|
||||||
|
|
||||||
|
frame:Hide()
|
||||||
|
frame:SetSize(iconSize, iconSize)
|
||||||
|
frame:SetFrameStrata("HIGH")
|
||||||
|
frame:SetFrameLevel(100)
|
||||||
|
frame:SetPoint("CENTER", BattlefieldMinimap, "TOPLEFT", offsetx, -offsety)
|
||||||
|
if Heimdall_Data.config.minimapTagger.debug then
|
||||||
|
print(string.format("[%s] Alert frame created, OnUpdate hooked", ModuleName))
|
||||||
|
end
|
||||||
|
frame:SetScript("OnShow", function(self)
|
||||||
|
self:SetAlpha(1)
|
||||||
|
self.custom.busy = true
|
||||||
|
self.custom.progress = 0
|
||||||
|
self:SetScript("OnUpdate", function(selff, elapsed)
|
||||||
|
self.custom.progress = self.custom.progress + elapsed
|
||||||
|
local progress = self.custom.progress / ttl
|
||||||
|
-- if Heimdall_Data.config.minimapTagger.debug then
|
||||||
|
-- print(string.format("[%s] Alert progress%%: %f", ModuleName, progress))
|
||||||
|
-- print(string.format("[%s] Alert progress: %f", ModuleName, self.custom.progress))
|
||||||
|
-- print(string.format("[%s] Alert ttl: %d", ModuleName, Heimdall_Data.config.minimapTagger.ttl))
|
||||||
|
-- end
|
||||||
|
self:SetAlpha(1 - progress)
|
||||||
|
|
||||||
|
if progress >= 1 then
|
||||||
|
self:Hide()
|
||||||
|
self.custom.busy = false
|
||||||
|
self:SetScript("OnUpdate", nil)
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
end)
|
||||||
|
frame:Show()
|
||||||
|
end
|
||||||
|
|
||||||
|
--region Alert
|
||||||
|
---@type Frame[]
|
||||||
|
local alertFramePool = {}
|
||||||
|
local alertFramePoolMaxSize = 20
|
||||||
|
for i = 1, alertFramePoolMaxSize do
|
||||||
|
local frame = CreateFrame("Frame")
|
||||||
|
frame.custom = { busy = false }
|
||||||
|
local texture = frame:CreateTexture(nil, "ARTWORK")
|
||||||
|
texture:SetAllPoints(frame)
|
||||||
|
texture:SetTexture(TextureRoot .. Heimdall_Data.config.minimapTagger.alertTextureFile)
|
||||||
|
table.insert(alertFramePool, frame)
|
||||||
|
end
|
||||||
|
local muteAlertUntil = 0
|
||||||
|
---@param x number|nil
|
||||||
|
---@param y number|nil
|
||||||
|
---@param scale number?
|
||||||
|
---@param doTag boolean?
|
||||||
|
local function PlantAlert(x, y, scale, doTag)
|
||||||
|
if x == nil or y == nil then
|
||||||
|
if Heimdall_Data.config.minimapTagger.debug then
|
||||||
|
print(string.format("[%s] Alert position is nil, ignoring", ModuleName))
|
||||||
|
end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
if doTag == nil then doTag = true end
|
||||||
|
local frame = nil
|
||||||
|
for _, alertFrame in ipairs(alertFramePool) do
|
||||||
|
---@diagnostic disable-next-line: undefined-field
|
||||||
|
if not alertFrame.custom.busy then
|
||||||
|
frame = alertFrame
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if not frame then
|
||||||
|
if Heimdall_Data.config.minimapTagger.debug then
|
||||||
|
print(string.format("[%s] Alert frame pool is full and could not get frame", ModuleName))
|
||||||
|
end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
if Heimdall_Data.config.minimapTagger.alertSound then
|
||||||
|
if Heimdall_Data.config.minimapTagger.debug then
|
||||||
|
print(
|
||||||
|
string.format(
|
||||||
|
"[%s] Playing alert sound: %s",
|
||||||
|
ModuleName,
|
||||||
|
Heimdall_Data.config.minimapTagger.alertSoundFile
|
||||||
|
)
|
||||||
|
)
|
||||||
|
end
|
||||||
|
if muteAlertUntil > GetTime() then
|
||||||
|
if Heimdall_Data.config.minimapTagger.debug then
|
||||||
|
print(string.format("[%s] Alert sound is muted until %d", ModuleName, muteAlertUntil))
|
||||||
|
end
|
||||||
|
else
|
||||||
|
muteAlertUntil = GetTime() + Heimdall_Data.config.minimapTagger.alertSoundThrottle
|
||||||
|
local ok = PlaySoundFile(SoundRoot .. Heimdall_Data.config.minimapTagger.alertSoundFile, "Master")
|
||||||
|
if not ok and Heimdall_Data.config.minimapTagger.debug then
|
||||||
|
print(
|
||||||
|
string.format(
|
||||||
|
"[%s] Failed to play alert sound: %s",
|
||||||
|
ModuleName,
|
||||||
|
Heimdall_Data.config.minimapTagger.alertSoundFile
|
||||||
|
)
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if doTag then PlantFrame(x, y, frame, scale, Heimdall_Data.config.minimapTagger.alertTTL) end
|
||||||
|
end
|
||||||
|
--endregion
|
||||||
|
|
||||||
|
--region Tag
|
||||||
|
---@type Frame[]
|
||||||
|
local tagFramePool = {}
|
||||||
|
local tagFramePoolMaxSize = 20
|
||||||
|
for i = 1, tagFramePoolMaxSize do
|
||||||
|
local frame = CreateFrame("Frame")
|
||||||
|
frame.custom = { busy = false }
|
||||||
|
local texture = frame:CreateTexture(nil, "ARTWORK")
|
||||||
|
texture:SetAllPoints(frame)
|
||||||
|
texture:SetTexture(TextureRoot .. Heimdall_Data.config.minimapTagger.tagTextureFile)
|
||||||
|
table.insert(tagFramePool, frame)
|
||||||
|
end
|
||||||
|
local muteTagUntil = 0
|
||||||
|
---@param x number|nil
|
||||||
|
---@param y number|nil
|
||||||
|
---@param scale number?
|
||||||
|
---@param doTag boolean?
|
||||||
|
local function PlantTag(x, y, scale, doTag)
|
||||||
|
if x == nil or y == nil then
|
||||||
|
if Heimdall_Data.config.minimapTagger.debug then
|
||||||
|
print(string.format("[%s] Tag position is nil, ignoring", ModuleName))
|
||||||
|
end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
if doTag == nil then doTag = true end
|
||||||
|
local frame = nil
|
||||||
|
for _, tagFrame in ipairs(tagFramePool) do
|
||||||
|
---@diagnostic disable-next-line: undefined-field
|
||||||
|
if not tagFrame.custom.busy then
|
||||||
|
frame = tagFrame
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if not frame then
|
||||||
|
if Heimdall_Data.config.minimapTagger.debug then
|
||||||
|
print(string.format("[%s] Tag frame pool is full and could not get frame", ModuleName))
|
||||||
|
end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
if Heimdall_Data.config.minimapTagger.tagSound then
|
||||||
|
if Heimdall_Data.config.minimapTagger.debug then
|
||||||
|
print(
|
||||||
|
string.format(
|
||||||
|
"[%s] Playing tag sound: %s",
|
||||||
|
ModuleName,
|
||||||
|
Heimdall_Data.config.minimapTagger.tagSoundFile
|
||||||
|
)
|
||||||
|
)
|
||||||
|
end
|
||||||
|
if muteTagUntil > GetTime() then
|
||||||
|
if Heimdall_Data.config.minimapTagger.debug then
|
||||||
|
print(string.format("[%s] Tag sound is muted until %d", ModuleName, muteTagUntil))
|
||||||
|
end
|
||||||
|
else
|
||||||
|
muteTagUntil = GetTime() + Heimdall_Data.config.minimapTagger.tagSoundThrottle
|
||||||
|
local ok = PlaySoundFile(SoundRoot .. Heimdall_Data.config.minimapTagger.tagSoundFile, "Master")
|
||||||
|
if not ok and Heimdall_Data.config.minimapTagger.debug then
|
||||||
|
print(
|
||||||
|
string.format(
|
||||||
|
"[%s] Failed to play tag sound: %s",
|
||||||
|
ModuleName,
|
||||||
|
Heimdall_Data.config.minimapTagger.tagSoundFile
|
||||||
|
)
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if doTag then PlantFrame(x, y, frame, scale, Heimdall_Data.config.minimapTagger.tagTTL) end
|
||||||
|
end
|
||||||
|
--endregion
|
||||||
|
|
||||||
|
--region Combat
|
||||||
|
---@type Frame[]
|
||||||
|
local combatFramePool = {}
|
||||||
|
local combatFramePoolMaxSize = 20
|
||||||
|
for i = 1, combatFramePoolMaxSize do
|
||||||
|
local frame = CreateFrame("Frame")
|
||||||
|
frame.custom = { busy = false }
|
||||||
|
local texture = frame:CreateTexture(nil, "ARTWORK")
|
||||||
|
texture:SetAllPoints(frame)
|
||||||
|
texture:SetTexture(TextureRoot .. Heimdall_Data.config.minimapTagger.combatTextureFile)
|
||||||
|
table.insert(combatFramePool, frame)
|
||||||
|
end
|
||||||
|
local muteCombatUntil = 0
|
||||||
|
---@param x number|nil
|
||||||
|
---@param y number|nil
|
||||||
|
---@param scale number?
|
||||||
|
---@param doTag boolean?
|
||||||
|
local function PlantCombat(x, y, scale, doTag)
|
||||||
|
if x == nil or y == nil then
|
||||||
|
if Heimdall_Data.config.minimapTagger.debug then
|
||||||
|
print(string.format("[%s] Combat position is nil, ignoring", ModuleName))
|
||||||
|
end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
if doTag == nil then doTag = true end
|
||||||
|
local frame = nil
|
||||||
|
for _, combatFrame in ipairs(combatFramePool) do
|
||||||
|
---@diagnostic disable-next-line: undefined-field
|
||||||
|
if not combatFrame.custom.busy then
|
||||||
|
frame = combatFrame
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if not frame then
|
||||||
|
if Heimdall_Data.config.minimapTagger.debug then
|
||||||
|
print(string.format("[%s] Battle frame pool is full and could not get frame", ModuleName))
|
||||||
|
end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
if Heimdall_Data.config.minimapTagger.combatSound then
|
||||||
|
if Heimdall_Data.config.minimapTagger.debug then
|
||||||
|
print(
|
||||||
|
string.format(
|
||||||
|
"[%s] Playing combat sound: %s",
|
||||||
|
ModuleName,
|
||||||
|
Heimdall_Data.config.minimapTagger.combatSoundFile
|
||||||
|
)
|
||||||
|
)
|
||||||
|
end
|
||||||
|
if muteCombatUntil > GetTime() then
|
||||||
|
if Heimdall_Data.config.minimapTagger.debug then
|
||||||
|
print(string.format("[%s] Combat sound is muted until %d", ModuleName, muteCombatUntil))
|
||||||
|
end
|
||||||
|
else
|
||||||
|
muteCombatUntil = GetTime() + Heimdall_Data.config.minimapTagger.combatSoundThrottle
|
||||||
|
local ok = PlaySoundFile(SoundRoot .. Heimdall_Data.config.minimapTagger.combatSoundFile, "Master")
|
||||||
|
if not ok and Heimdall_Data.config.minimapTagger.debug then
|
||||||
|
print(
|
||||||
|
string.format(
|
||||||
|
"[%s] Failed to play combat sound: %s",
|
||||||
|
ModuleName,
|
||||||
|
Heimdall_Data.config.minimapTagger.combatSoundFile
|
||||||
|
)
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if doTag then PlantFrame(x, y, frame, scale, Heimdall_Data.config.minimapTagger.combatTTL) end
|
||||||
|
end
|
||||||
|
--endregion
|
||||||
|
|
||||||
|
--region Help
|
||||||
|
---@type Frame[]
|
||||||
|
local helpFramePool = {}
|
||||||
|
local helpFramePoolMaxSize = 20
|
||||||
|
for i = 1, helpFramePoolMaxSize do
|
||||||
|
local frame = CreateFrame("Frame")
|
||||||
|
frame.custom = { busy = false }
|
||||||
|
local texture = frame:CreateTexture(nil, "ARTWORK")
|
||||||
|
texture:SetAllPoints(frame)
|
||||||
|
texture:SetTexture(TextureRoot .. Heimdall_Data.config.minimapTagger.helpTextureFile)
|
||||||
|
table.insert(helpFramePool, frame)
|
||||||
|
end
|
||||||
|
local muteHelpUntil = 0
|
||||||
|
---@param x number|nil
|
||||||
|
---@param y number|nil
|
||||||
|
---@param scale number?
|
||||||
|
---@param doTag boolean?
|
||||||
|
local function PlantHelp(x, y, scale, doTag)
|
||||||
|
if x == nil or y == nil then
|
||||||
|
if Heimdall_Data.config.minimapTagger.debug then
|
||||||
|
print(string.format("[%s] Help position is nil, ignoring", ModuleName))
|
||||||
|
end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
if doTag == nil then doTag = true end
|
||||||
|
local frame = nil
|
||||||
|
for _, helpFrame in ipairs(helpFramePool) do
|
||||||
|
---@diagnostic disable-next-line: undefined-field
|
||||||
|
if not helpFrame.custom.busy then
|
||||||
|
frame = helpFrame
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if not frame then
|
||||||
|
if Heimdall_Data.config.minimapTagger.debug then
|
||||||
|
print(string.format("[%s] Help frame pool is full and could not get frame", ModuleName))
|
||||||
|
end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
if Heimdall_Data.config.minimapTagger.helpSound then
|
||||||
|
if Heimdall_Data.config.minimapTagger.debug then
|
||||||
|
print(
|
||||||
|
string.format(
|
||||||
|
"[%s] Playing help sound: %s",
|
||||||
|
ModuleName,
|
||||||
|
Heimdall_Data.config.minimapTagger.helpSoundFile
|
||||||
|
)
|
||||||
|
)
|
||||||
|
end
|
||||||
|
if muteHelpUntil > GetTime() then
|
||||||
|
if Heimdall_Data.config.minimapTagger.debug then
|
||||||
|
print(string.format("[%s] Help sound is muted until %d", ModuleName, muteHelpUntil))
|
||||||
|
end
|
||||||
|
else
|
||||||
|
muteHelpUntil = GetTime() + Heimdall_Data.config.minimapTagger.helpSoundThrottle
|
||||||
|
local ok = PlaySoundFile(SoundRoot .. Heimdall_Data.config.minimapTagger.helpSoundFile, "Master")
|
||||||
|
if not ok and Heimdall_Data.config.minimapTagger.debug then
|
||||||
|
print(
|
||||||
|
string.format(
|
||||||
|
"[%s] Failed to play help sound: %s",
|
||||||
|
ModuleName,
|
||||||
|
Heimdall_Data.config.minimapTagger.helpSoundFile
|
||||||
|
)
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if doTag then PlantFrame(x, y, frame, scale, Heimdall_Data.config.minimapTagger.helpTTL) end
|
||||||
|
end
|
||||||
|
--endregion
|
||||||
|
|
||||||
|
local pauseUntil = 0
|
||||||
|
local frame = CreateFrame("Frame")
|
||||||
|
frame:RegisterEvent("WORLD_MAP_UPDATE")
|
||||||
|
frame:SetScript("OnEvent", function(self, event, addon)
|
||||||
|
if pauseUntil > GetTime() then return end
|
||||||
|
pauseUntil = GetTime() + 1
|
||||||
|
if not BattlefieldMinimap then
|
||||||
|
if Heimdall_Data.config.minimapTagger.debug then
|
||||||
|
print(string.format("[%s] BattlefieldMinimap not found", ModuleName))
|
||||||
|
end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
if not Heimdall_Data.config.minimapTagger.enabled then
|
||||||
|
if Heimdall_Data.config.minimapTagger.debug then
|
||||||
|
print(string.format("[%s] MinimapTagger is disabled", ModuleName))
|
||||||
|
end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local scale = Heimdall_Data.config.minimapTagger.scale
|
||||||
|
BattlefieldMinimap:SetScale(scale)
|
||||||
|
BattlefieldMinimap:SetMovable(true)
|
||||||
|
BattlefieldMinimap:EnableMouse(true)
|
||||||
|
BattlefieldMinimap:RegisterForDrag("LeftButton")
|
||||||
|
BattlefieldMinimap:SetScript("OnDragStart", function(selff) selff:StartMoving() end)
|
||||||
|
BattlefieldMinimap:SetScript("OnDragStop", function(selff) selff:StopMovingOrSizing() end)
|
||||||
|
BattlefieldMinimapBackground:Hide()
|
||||||
|
BattlefieldMinimapCloseButton:Hide()
|
||||||
|
BattlefieldMinimapCorner:Hide()
|
||||||
|
BattlefieldMinimap:HookScript("OnHide", function(selff)
|
||||||
|
for _, alertFrame in ipairs(alertFramePool) do
|
||||||
|
alertFrame:Hide()
|
||||||
|
---@diagnostic disable-next-line: undefined-field
|
||||||
|
alertFrame.custom.busy = false
|
||||||
|
end
|
||||||
|
for _, tagFrame in ipairs(tagFramePool) do
|
||||||
|
tagFrame:Hide()
|
||||||
|
---@diagnostic disable-next-line: undefined-field
|
||||||
|
tagFrame.custom.busy = false
|
||||||
|
end
|
||||||
|
-- What the fuck is this global?
|
||||||
|
for _, battleFrame in ipairs(battleFramePool) do
|
||||||
|
battleFrame:Hide()
|
||||||
|
battleFrame.custom.busy = false
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
end)
|
||||||
|
|
||||||
|
local chatFrame = CreateFrame("Frame")
|
||||||
|
chatFrame:RegisterEvent("CHAT_MSG_CHANNEL")
|
||||||
|
chatFrame:SetScript("OnEvent", function(self, event, msg, sender, ...)
|
||||||
|
--if Heimdall_Data.config.echoer.debug then
|
||||||
|
-- print(string.format("[%s] Channel message received from: %s", ModuleName, sender))
|
||||||
|
--end
|
||||||
|
|
||||||
|
if not Heimdall_Data.config.minimapTagger.enabled then
|
||||||
|
--if Heimdall_Data.config.echoer.debug then
|
||||||
|
-- print(string.format("[%s] Module disabled, ignoring message", ModuleName))
|
||||||
|
--end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local channelId = select(6, ...)
|
||||||
|
local _, channelname = GetChannelName(channelId)
|
||||||
|
local ok = false
|
||||||
|
for _, channel in pairs(Heimdall_Data.config.minimapTagger.channels) do
|
||||||
|
if channelname == channel then
|
||||||
|
ok = true
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if not ok then
|
||||||
|
if Heimdall_Data.config.minimapTagger.debug then
|
||||||
|
print(
|
||||||
|
string.format(
|
||||||
|
"[%s] Ignoring message from non-master channel: %s, need %s",
|
||||||
|
ModuleName,
|
||||||
|
channelname,
|
||||||
|
Heimdall_Data.config.minimapTagger.masterChannel
|
||||||
|
)
|
||||||
|
)
|
||||||
|
end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
if Heimdall_Data.config.minimapTagger.debug then
|
||||||
|
print(string.format("[%s] Processing message from master channel: %s", ModuleName, sender))
|
||||||
|
shared.dump(Heimdall_Data.config.minimapTagger)
|
||||||
|
end
|
||||||
|
|
||||||
|
local doTag = true
|
||||||
|
local messageMapId = string.match(msg, "%[(%d+)%]") or 0
|
||||||
|
if messageMapId then messageMapId = tonumber(messageMapId) end
|
||||||
|
|
||||||
|
local currentMapId = GetCurrentMapAreaID()
|
||||||
|
if currentMapId ~= messageMapId then
|
||||||
|
if Heimdall_Data.config.minimapTagger.debug then
|
||||||
|
print(
|
||||||
|
string.format(
|
||||||
|
"[%s] Current map ID (%d) does not match message map ID (%d), ignoring message",
|
||||||
|
ModuleName,
|
||||||
|
currentMapId,
|
||||||
|
messageMapId
|
||||||
|
)
|
||||||
|
)
|
||||||
|
end
|
||||||
|
doTag = false
|
||||||
|
end
|
||||||
|
|
||||||
|
--region Tag
|
||||||
|
if string.find(msg, "^I see") then
|
||||||
|
if Heimdall_Data.config.minimapTagger.tagTTL == 0 then
|
||||||
|
if Heimdall_Data.config.minimapTagger.debug then
|
||||||
|
print(string.format("[%s] Tag TTL is 0, ignoring message: %s", ModuleName, msg))
|
||||||
|
end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local x, y = string.match(msg, "%((%d+%.%d+)%s*,%s*(%d+%.%d+)%)")
|
||||||
|
if Heimdall_Data.config.minimapTagger.debug then
|
||||||
|
print(string.format("[%s] Found alert position: %s, %s", ModuleName, tostring(x), tostring(y)))
|
||||||
|
end
|
||||||
|
if x and y then PlantTag(tonumber(x), tonumber(y), 2, doTag) end
|
||||||
|
end
|
||||||
|
--endregion
|
||||||
|
--region Combat
|
||||||
|
if string.find(msg, "^I am in combat with") then
|
||||||
|
if Heimdall_Data.config.minimapTagger.combatTTL == 0 then
|
||||||
|
if Heimdall_Data.config.minimapTagger.debug then
|
||||||
|
print(string.format("[%s] Combat TTL is 0, ignoring message: %s", ModuleName, msg))
|
||||||
|
end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
if Heimdall_Data.config.minimapTagger.debug then
|
||||||
|
print(string.format("[%s] Found combat alert in message: %s", ModuleName, msg))
|
||||||
|
end
|
||||||
|
local x, y = string.match(msg, "%((%d+%.%d+)%s*,%s*(%d+%.%d+)%)")
|
||||||
|
if Heimdall_Data.config.minimapTagger.debug then
|
||||||
|
print(string.format("[%s] Found combat position: %s, %s", ModuleName, tostring(x), tostring(y)))
|
||||||
|
end
|
||||||
|
if x and y then PlantCombat(tonumber(x), tonumber(y), 2, doTag) end
|
||||||
|
end
|
||||||
|
--endregion
|
||||||
|
--region Death
|
||||||
|
if string.find(msg, " killed ") then
|
||||||
|
if Heimdall_Data.config.minimapTagger.alertTTL == 0 then
|
||||||
|
if Heimdall_Data.config.minimapTagger.debug then
|
||||||
|
print(string.format("[%s] Alert TTL is 0, ignoring message: %s", ModuleName, msg))
|
||||||
|
end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
if Heimdall_Data.config.minimapTagger.debug then
|
||||||
|
print(string.format("[%s] Found death alert in message: %s", ModuleName, msg))
|
||||||
|
end
|
||||||
|
local x, y = string.match(msg, "%((%d+%.%d+)%s*,%s*(%d+%.%d+)%)")
|
||||||
|
if Heimdall_Data.config.minimapTagger.debug then
|
||||||
|
print(string.format("[%s] Found death position: %s, %s", ModuleName, tostring(x), tostring(y)))
|
||||||
|
end
|
||||||
|
if x and y then PlantAlert(tonumber(x), tonumber(y), 2, doTag) end
|
||||||
|
end
|
||||||
|
--endregion
|
||||||
|
--region Help
|
||||||
|
if string.find(msg, "I need help") then
|
||||||
|
if Heimdall_Data.config.minimapTagger.helpTTL == 0 then
|
||||||
|
if Heimdall_Data.config.minimapTagger.debug then
|
||||||
|
print(string.format("[%s] Help TTL is 0, ignoring message: %s", ModuleName, msg))
|
||||||
|
end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
if Heimdall_Data.config.minimapTagger.debug then
|
||||||
|
print(string.format("[%s] Found help alert in message: %s", ModuleName, msg))
|
||||||
|
end
|
||||||
|
local x, y = string.match(msg, "%((%d+%.%d+)%s*,%s*(%d+%.%d+)%)")
|
||||||
|
if Heimdall_Data.config.minimapTagger.debug then
|
||||||
|
print(string.format("[%s] Found help position: %s, %s", ModuleName, tostring(x), tostring(y)))
|
||||||
|
end
|
||||||
|
if x and y then
|
||||||
|
x, y = tonumber(x), tonumber(y)
|
||||||
|
PlantHelp(x, y, 1, doTag)
|
||||||
|
---@diagnostic disable-next-line: undefined-global
|
||||||
|
if TomTom then
|
||||||
|
if Heimdall_Data.config.minimapTagger.debug then
|
||||||
|
print(string.format("[%s] Adding help waypoint to TomTom", ModuleName))
|
||||||
|
end
|
||||||
|
local areaId = string.match(msg, "%[(%d+)%]") or 0
|
||||||
|
if areaId then areaId = tonumber(areaId) end
|
||||||
|
if Heimdall_Data.config.minimapTagger.debug then
|
||||||
|
print(string.format("[%s] Area ID: %s", ModuleName, tostring(areaId)))
|
||||||
|
end
|
||||||
|
|
||||||
|
---@diagnostic disable-next-line: undefined-global
|
||||||
|
TomTom:AddMFWaypoint(areaId, nil, x / 100, y / 100, {
|
||||||
|
title = "Help " .. sender,
|
||||||
|
world = true,
|
||||||
|
from = "Heimdall",
|
||||||
|
crazy = true,
|
||||||
|
})
|
||||||
|
else
|
||||||
|
if Heimdall_Data.config.minimapTagger.debug then
|
||||||
|
print(string.format("[%s] No tomtom no waypoint", ModuleName))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
--endregion
|
||||||
|
end)
|
||||||
|
|
||||||
|
print(string.format("[%s] Module initialized", ModuleName))
|
||||||
|
end,
|
||||||
|
}
|
85
Modules/Network.lua
Normal file
85
Modules/Network.lua
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
local _, shared = ...
|
||||||
|
---@cast shared HeimdallShared
|
||||||
|
local ModuleName = "Network"
|
||||||
|
|
||||||
|
---@class HeimdallNetworkConfig
|
||||||
|
---@field enabled boolean
|
||||||
|
---@field debug boolean
|
||||||
|
---@field members string[]
|
||||||
|
---@field updateInterval number
|
||||||
|
|
||||||
|
---@class HeimdallNetworkData
|
||||||
|
---@field ticker Timer?
|
||||||
|
|
||||||
|
---@class Network
|
||||||
|
shared.Network = {
|
||||||
|
Init = function()
|
||||||
|
if not shared.network then shared.network = {} end
|
||||||
|
local updatePending = false
|
||||||
|
|
||||||
|
local function FriendListUpdate()
|
||||||
|
updatePending = false
|
||||||
|
if not Heimdall_Data.config.network.enabled then return end
|
||||||
|
---@type table<string, boolean>
|
||||||
|
local friends = {}
|
||||||
|
for i = 1, GetNumFriends() do
|
||||||
|
local name, _, _, _, connected, _, _, _ = GetFriendInfo(i)
|
||||||
|
if name then
|
||||||
|
friends[name] = connected
|
||||||
|
if Heimdall_Data.config.network.debug then
|
||||||
|
print(
|
||||||
|
string.format("[%s] Friend %s is %s", ModuleName, name, connected and "online" or "offline")
|
||||||
|
)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
if Heimdall_Data.config.network.debug then
|
||||||
|
print(string.format("[%s] Friend %s is nil", ModuleName, i))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
for _, member in ipairs(Heimdall_Data.config.network.members) do
|
||||||
|
if friends[member] == nil and member ~= UnitName("player") then
|
||||||
|
if Heimdall_Data.config.network.debug then
|
||||||
|
print(string.format("[%s] Adding friend %s", ModuleName, member))
|
||||||
|
end
|
||||||
|
AddFriend(member)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
friends[UnitName("player")] = true
|
||||||
|
|
||||||
|
shared.networkNodes = {}
|
||||||
|
-- Why are we skipping this again...?
|
||||||
|
-- if false then shared.networkNodes[#shared.networkNodes + 1] = UnitName("player") end
|
||||||
|
for _, player in ipairs(Heimdall_Data.config.network.members) do
|
||||||
|
if friends[player] then
|
||||||
|
shared.networkNodes[#shared.networkNodes + 1] = player
|
||||||
|
if Heimdall_Data.config.network.debug then
|
||||||
|
print(string.format("[%s] Adding network node %s", ModuleName, player))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if Heimdall_Data.config.network.debug then
|
||||||
|
print(string.format("[%s] Network nodes:", ModuleName))
|
||||||
|
shared.dump(shared.networkNodes)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local friendsFrame = CreateFrame("Frame")
|
||||||
|
friendsFrame:RegisterEvent("FRIENDLIST_UPDATE")
|
||||||
|
friendsFrame:SetScript("OnEvent", function(self, event, ...) end)
|
||||||
|
|
||||||
|
local function NetworkTick()
|
||||||
|
if Heimdall_Data.config.network.debug then print("Network module is updating.") end
|
||||||
|
ShowFriends()
|
||||||
|
updatePending = true
|
||||||
|
C_Timer.After(1, function()
|
||||||
|
if updatePending then FriendListUpdate() end
|
||||||
|
end)
|
||||||
|
shared.network.ticker = C_Timer.NewTimer(Heimdall_Data.config.network.updateInterval, NetworkTick, 1)
|
||||||
|
end
|
||||||
|
|
||||||
|
NetworkTick()
|
||||||
|
print(string.format("[%s] Module initialized", ModuleName))
|
||||||
|
end,
|
||||||
|
}
|
204
Modules/NetworkMessenger.lua
Normal file
204
Modules/NetworkMessenger.lua
Normal file
@@ -0,0 +1,204 @@
|
|||||||
|
local _, shared = ...
|
||||||
|
---@cast shared HeimdallShared
|
||||||
|
local ModuleName = "NetworkMessenger"
|
||||||
|
|
||||||
|
---@class HeimdallNetworkMessengerConfig
|
||||||
|
---@field enabled boolean
|
||||||
|
---@field debug boolean
|
||||||
|
---@field interval number
|
||||||
|
|
||||||
|
---@class HeimdallNetworkMessengerData
|
||||||
|
---@field queue table<string, Message>
|
||||||
|
---@field ticker Timer?
|
||||||
|
|
||||||
|
---@class NetworkMessenger
|
||||||
|
shared.NetworkMessenger = {
|
||||||
|
---@param message Message
|
||||||
|
Enqueue = function(message) table.insert(shared.networkMessenger.queue, message) end,
|
||||||
|
Init = function()
|
||||||
|
RegisterAddonMessagePrefix(Heimdall_Data.config.addonPrefix)
|
||||||
|
|
||||||
|
shared.networkMessenger = {
|
||||||
|
queue = ReactiveValue.new({}),
|
||||||
|
}
|
||||||
|
|
||||||
|
if not shared.networkMessenger.ticker then
|
||||||
|
local function DoMessage()
|
||||||
|
--if Heimdall_Data.config.networkMessenger.debug then
|
||||||
|
-- print(string.format("[%s] Processing network message queue", ModuleName))
|
||||||
|
--end
|
||||||
|
if not Heimdall_Data.config.networkMessenger.enabled then
|
||||||
|
--if Heimdall_Data.config.networkMessenger.debug then
|
||||||
|
-- print(string.format("[%s] Module disabled, skipping network message processing", ModuleName))
|
||||||
|
--end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
---@type Message
|
||||||
|
local message = shared.networkMessenger.queue[1]
|
||||||
|
if not message then
|
||||||
|
--if Heimdall_Data.config.networkMessenger.debug then
|
||||||
|
-- print(string.format("[%s] Network message queue empty", ModuleName))
|
||||||
|
--end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
if not message.message or message.message == "" then
|
||||||
|
if Heimdall_Data.config.networkMessenger.debug then
|
||||||
|
print(string.format("[%s] Invalid network message: empty content", ModuleName))
|
||||||
|
end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
if not message.channel or message.channel == "" then
|
||||||
|
if Heimdall_Data.config.networkMessenger.debug then
|
||||||
|
print(string.format("[%s] Invalid network message: no channel specified", ModuleName))
|
||||||
|
end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
table.remove(shared.networkMessenger.queue, 1)
|
||||||
|
if not message.message or message.message == "" then
|
||||||
|
if Heimdall_Data.config.networkMessenger.debug then
|
||||||
|
print(string.format("[%s] Skipping empty network message", ModuleName))
|
||||||
|
end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
if not message.channel or message.channel == "" then
|
||||||
|
if Heimdall_Data.config.networkMessenger.debug then
|
||||||
|
print(string.format("[%s] Skipping network message with no channel", ModuleName))
|
||||||
|
end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
if not message.data or message.data == "" then
|
||||||
|
if Heimdall_Data.config.networkMessenger.debug then
|
||||||
|
print(string.format("[%s] Skipping network message with no data", ModuleName))
|
||||||
|
end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
if Heimdall_Data.config.networkMessenger.debug then
|
||||||
|
print(
|
||||||
|
string.format(
|
||||||
|
"[%s] Sending network message: '%s' to %s:%s",
|
||||||
|
ModuleName,
|
||||||
|
message.message,
|
||||||
|
message.channel,
|
||||||
|
message.data
|
||||||
|
)
|
||||||
|
)
|
||||||
|
end
|
||||||
|
local payload = string.format("dmessage|%s|%s|%s", message.message, message.channel, message.data)
|
||||||
|
if Heimdall_Data.config.networkMessenger.debug then
|
||||||
|
print(string.format("[%s] Payload: %s", ModuleName, payload))
|
||||||
|
end
|
||||||
|
if not shared.networkNodes or #shared.networkNodes == 0 then
|
||||||
|
if Heimdall_Data.config.networkMessenger.debug then
|
||||||
|
print(string.format("[%s] No network nodes found, wtf????", ModuleName))
|
||||||
|
end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local target = shared.networkNodes[1]
|
||||||
|
SendAddonMessage(Heimdall_Data.config.addonPrefix, payload, "WHISPER", target)
|
||||||
|
end
|
||||||
|
local function Tick()
|
||||||
|
--if Heimdall_Data.config.networkMessenger.debug then
|
||||||
|
-- local queueSize = #shared.networkMessenger.queue
|
||||||
|
-- print(string.format("[%s] Queue check - Network messages pending: %d", ModuleName, queueSize))
|
||||||
|
--end
|
||||||
|
DoMessage()
|
||||||
|
shared.networkMessenger.ticker =
|
||||||
|
C_Timer.NewTimer(Heimdall_Data.config.networkMessenger.interval, Tick, 1)
|
||||||
|
end
|
||||||
|
Tick()
|
||||||
|
end
|
||||||
|
|
||||||
|
-- If we are the leader then we delegate messages (dmessage)
|
||||||
|
-- If we get a "message" command from leader then we send the message
|
||||||
|
|
||||||
|
local nextIdx = 1
|
||||||
|
local addonMsgFrame = CreateFrame("Frame")
|
||||||
|
addonMsgFrame:RegisterEvent("CHAT_MSG_ADDON")
|
||||||
|
addonMsgFrame:SetScript("OnEvent", function(self, event, prefix, message, channel, source)
|
||||||
|
if not Heimdall_Data.config.networkMessenger.enabled then return end
|
||||||
|
if prefix ~= Heimdall_Data.config.addonPrefix then return end
|
||||||
|
source = string.match(source, "[^%-]+")
|
||||||
|
|
||||||
|
if Heimdall_Data.config.networkMessenger.debug then
|
||||||
|
print(string.format("[%s] Received message from %s: %s", ModuleName, source, message))
|
||||||
|
end
|
||||||
|
if #shared.networkNodes == 0 then
|
||||||
|
if Heimdall_Data.config.networkMessenger.debug then
|
||||||
|
print(string.format("[%s] No network nodes found, wtf????", ModuleName))
|
||||||
|
end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
-- There should always be at least one network node ergo should always exist a leader
|
||||||
|
-- Because the us, the player, is also a node
|
||||||
|
--local networkLeader = shared.networkNodes[1]
|
||||||
|
--if source ~= networkLeader then
|
||||||
|
-- if Heimdall_Data.config.networkMessenger.debug then
|
||||||
|
-- print(string.format("[%s] Message from %s is not from the network leader (%s)", ModuleName, source,
|
||||||
|
-- networkLeader))
|
||||||
|
-- end
|
||||||
|
-- return
|
||||||
|
--end
|
||||||
|
|
||||||
|
local parts = shared.Split(message, "|")
|
||||||
|
if Heimdall_Data.config.networkMessenger.debug then
|
||||||
|
print(string.format("[%s] Received message parts:", ModuleName))
|
||||||
|
shared.dump(parts)
|
||||||
|
end
|
||||||
|
local command = strtrim(parts[1])
|
||||||
|
if command == "message" then
|
||||||
|
local content = strtrim(tostring(parts[2]))
|
||||||
|
local targetchannel = strtrim(tostring(parts[3]))
|
||||||
|
local target = strtrim(tostring(parts[4]))
|
||||||
|
if Heimdall_Data.config.networkMessenger.debug then
|
||||||
|
print(
|
||||||
|
string.format(
|
||||||
|
"[%s] Received message command: %s %s %s",
|
||||||
|
ModuleName,
|
||||||
|
content,
|
||||||
|
targetchannel,
|
||||||
|
target
|
||||||
|
)
|
||||||
|
)
|
||||||
|
end
|
||||||
|
---@type Message
|
||||||
|
local msg = {
|
||||||
|
channel = targetchannel,
|
||||||
|
message = content,
|
||||||
|
data = target,
|
||||||
|
}
|
||||||
|
table.insert(shared.messenger.queue, msg)
|
||||||
|
elseif command == "dmessage" then
|
||||||
|
if Heimdall_Data.config.networkMessenger.debug then
|
||||||
|
print(string.format("[%s] Received dmessage command", ModuleName))
|
||||||
|
end
|
||||||
|
parts[1] = "message"
|
||||||
|
local content = table.concat(parts, "|")
|
||||||
|
|
||||||
|
if nextIdx > #shared.networkNodes then nextIdx = 1 end
|
||||||
|
local recipient = shared.networkNodes[nextIdx]
|
||||||
|
nextIdx = nextIdx + 1
|
||||||
|
if Heimdall_Data.config.networkMessenger.debug then
|
||||||
|
print(string.format("[%s] Sending message %s to %s", ModuleName, content, recipient))
|
||||||
|
end
|
||||||
|
SendAddonMessage(Heimdall_Data.config.addonPrefix, content, "WHISPER", recipient)
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
--/run Heimdall_Data.Test()
|
||||||
|
Heimdall_Data.Test = function()
|
||||||
|
local testmsg = {
|
||||||
|
channel = "W",
|
||||||
|
message = "Hi, mom!",
|
||||||
|
data = "Secundus",
|
||||||
|
}
|
||||||
|
for i = 1, 36 do
|
||||||
|
table.insert(shared.networkMessenger.queue, testmsg)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
print(string.format("[%s] Module initialized", ModuleName))
|
||||||
|
end,
|
||||||
|
}
|
307
Modules/Noter.lua
Normal file
307
Modules/Noter.lua
Normal file
@@ -0,0 +1,307 @@
|
|||||||
|
local _, shared = ...
|
||||||
|
---@cast shared HeimdallShared
|
||||||
|
local ModuleName = "Noter"
|
||||||
|
|
||||||
|
---@class HeimdallNoterConfig
|
||||||
|
---@field enabled boolean
|
||||||
|
---@field debug boolean
|
||||||
|
---@field channels string[]
|
||||||
|
---@field lastNotes number
|
||||||
|
|
||||||
|
---@class Note
|
||||||
|
---@field source string
|
||||||
|
---@field for string
|
||||||
|
---@field date string
|
||||||
|
---@field note string
|
||||||
|
|
||||||
|
---@class Noter
|
||||||
|
shared.Noter = {
|
||||||
|
Init = function()
|
||||||
|
-- ---Hopefully this will not be necessary
|
||||||
|
-- ---@param text string
|
||||||
|
-- ---@param size number
|
||||||
|
-- ---@return string[]
|
||||||
|
-- local function Partition(text, size)
|
||||||
|
-- local words = {}
|
||||||
|
-- for word in text:gmatch("[^,]+") do
|
||||||
|
-- words[#words + 1] = word
|
||||||
|
-- end
|
||||||
|
|
||||||
|
-- local ret = {}
|
||||||
|
-- local currentChunk = ""
|
||||||
|
|
||||||
|
-- for _, word in ipairs(words) do
|
||||||
|
-- if #currentChunk + #word + 1 <= size then
|
||||||
|
-- currentChunk = currentChunk .. (currentChunk == "" and word or " " .. word)
|
||||||
|
-- else
|
||||||
|
-- if #currentChunk > 0 then ret[#ret + 1] = currentChunk end
|
||||||
|
-- currentChunk = word
|
||||||
|
-- end
|
||||||
|
-- end
|
||||||
|
|
||||||
|
-- if #currentChunk > 0 then ret[#ret + 1] = currentChunk end
|
||||||
|
|
||||||
|
-- return ret
|
||||||
|
-- end
|
||||||
|
---@param array any[]
|
||||||
|
---@return any[]
|
||||||
|
local function Compact(array)
|
||||||
|
local compacted = {}
|
||||||
|
for _, v in pairs(array) do
|
||||||
|
compacted[#compacted + 1] = v
|
||||||
|
end
|
||||||
|
return compacted
|
||||||
|
end
|
||||||
|
|
||||||
|
---@param name string
|
||||||
|
---@param args string[]
|
||||||
|
local function DeleteNotes(name, args)
|
||||||
|
if Heimdall_Data.config.noter.debug then
|
||||||
|
print(string.format("[%s] Delete note command received for: %s", ModuleName, name))
|
||||||
|
end
|
||||||
|
local range = args[4]
|
||||||
|
if range then
|
||||||
|
if Heimdall_Data.config.noter.debug then
|
||||||
|
print(string.format("[%s] Range received for delete note: %s", ModuleName, range))
|
||||||
|
end
|
||||||
|
local indices = shared.Split(range, "..")
|
||||||
|
if Heimdall_Data.config.noter.debug then
|
||||||
|
print(string.format("[%s] Indices for range deletion: %s", ModuleName, table.concat(indices, ", ")))
|
||||||
|
shared.dump(indices)
|
||||||
|
end
|
||||||
|
local start = tonumber(indices[1])
|
||||||
|
local finish = tonumber(indices[2])
|
||||||
|
|
||||||
|
if not start then
|
||||||
|
if Heimdall_Data.config.noter.debug then
|
||||||
|
print(
|
||||||
|
string.format("[%s] Invalid start range for delete note: %s", ModuleName, tostring(start))
|
||||||
|
)
|
||||||
|
end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
if not finish then finish = start end
|
||||||
|
if Heimdall_Data.config.noter.debug then
|
||||||
|
print(string.format("[%s] Deleting note range %s to %s for: %s", ModuleName, start, finish, name))
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Here, because we are deleting random notes, we lose the "iterative" index property
|
||||||
|
-- Ie it's not longer 1..100, it might be 1..47, 50, 68..100
|
||||||
|
-- Which means that we cannot use ipairs, bad!
|
||||||
|
for i = start, finish do
|
||||||
|
if not Heimdall_Data.config.notes[name] then Heimdall_Data.config.notes[name] = {} end
|
||||||
|
if not Heimdall_Data.config.notes[name][i] then
|
||||||
|
if Heimdall_Data.config.noter.debug then
|
||||||
|
print(string.format("[%s] Note at index %s does not exist", ModuleName, i))
|
||||||
|
end
|
||||||
|
else
|
||||||
|
if Heimdall_Data.config.noter.debug then
|
||||||
|
print(string.format("[%s] Deleting note %s at index %s", ModuleName, name, i))
|
||||||
|
shared.dump(Heimdall_Data.config.notes[name][i])
|
||||||
|
end
|
||||||
|
Heimdall_Data.config.notes[name][i] = nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
Heimdall_Data.config.notes[name] = Compact(Heimdall_Data.config.notes[name])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
---@param channel string
|
||||||
|
---@param index number
|
||||||
|
---@param note Note
|
||||||
|
local function PrintNote(channel, index, note)
|
||||||
|
if Heimdall_Data.config.noter.debug then
|
||||||
|
print(string.format("[%s] Printing note at index %d for: %s", ModuleName, index, note.source))
|
||||||
|
print(string.format("[%s] [%s][%d] %s: %s", ModuleName, note.source, index, note.date, note.note))
|
||||||
|
end
|
||||||
|
---@type Message
|
||||||
|
local msg = {
|
||||||
|
channel = "C",
|
||||||
|
data = channel,
|
||||||
|
message = string.format("[%s][%d] %s: %s", note.source, index, note.date, note.note),
|
||||||
|
}
|
||||||
|
if Heimdall_Data.config.networkMessenger.enabled then
|
||||||
|
shared.NetworkMessenger.Enqueue(msg)
|
||||||
|
elseif Heimdall_Data.config.messenger.enabled then
|
||||||
|
shared.Messenger.Enqueue(msg)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
---@param name string
|
||||||
|
---@param args string[]
|
||||||
|
local function PrintNotes(channel, name, args)
|
||||||
|
if Heimdall_Data.config.noter.debug then
|
||||||
|
print(string.format("[%s] Print note command received for: %s", ModuleName, name))
|
||||||
|
end
|
||||||
|
local range = args[3]
|
||||||
|
if not range then
|
||||||
|
if Heimdall_Data.config.noter.debug then
|
||||||
|
print(
|
||||||
|
string.format(
|
||||||
|
"[%s] No range specified for print note, defaulting to last %d notes",
|
||||||
|
ModuleName,
|
||||||
|
Heimdall_Data.config.noter.lastNotes
|
||||||
|
)
|
||||||
|
)
|
||||||
|
end
|
||||||
|
local notes = Heimdall_Data.config.notes[name] or {}
|
||||||
|
local start = math.max(1, #notes - Heimdall_Data.config.noter.lastNotes + 1)
|
||||||
|
local finish = #notes
|
||||||
|
if Heimdall_Data.config.noter.debug then
|
||||||
|
print(string.format("[%s] Printing notes from %d to %d for: %s", ModuleName, start, finish, name))
|
||||||
|
end
|
||||||
|
for i = start, finish do
|
||||||
|
PrintNote(channel, i, notes[i])
|
||||||
|
end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
if range then
|
||||||
|
if Heimdall_Data.config.noter.debug then
|
||||||
|
print(string.format("[%s] Range received for print note: %s", ModuleName, range))
|
||||||
|
end
|
||||||
|
local indices = shared.Split(range, "..")
|
||||||
|
if Heimdall_Data.config.noter.debug then
|
||||||
|
print(string.format("[%s] Indices for range printing: %s", ModuleName, table.concat(indices, ", ")))
|
||||||
|
shared.dump(indices)
|
||||||
|
end
|
||||||
|
local start = tonumber(indices[1])
|
||||||
|
local finish = tonumber(indices[2])
|
||||||
|
|
||||||
|
if not start then
|
||||||
|
if Heimdall_Data.config.noter.debug then
|
||||||
|
print(string.format("[%s] Invalid start range for print note: %s", ModuleName, tostring(start)))
|
||||||
|
end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
if not finish then finish = start end
|
||||||
|
if Heimdall_Data.config.noter.debug then
|
||||||
|
print(string.format("[%s] Printing note range %s to %s for: %s", ModuleName, start, finish, name))
|
||||||
|
end
|
||||||
|
|
||||||
|
for i = start, finish do
|
||||||
|
if not Heimdall_Data.config.notes[name] then Heimdall_Data.config.notes[name] = {} end
|
||||||
|
if not Heimdall_Data.config.notes[name][i] then
|
||||||
|
if Heimdall_Data.config.noter.debug then
|
||||||
|
print(string.format("[%s] Note at index %s does not exist", ModuleName, i))
|
||||||
|
end
|
||||||
|
else
|
||||||
|
if Heimdall_Data.config.noter.debug then
|
||||||
|
print(string.format("[%s] Printing note %s at index %s", ModuleName, name, i))
|
||||||
|
shared.dump(Heimdall_Data.config.notes[name][i])
|
||||||
|
end
|
||||||
|
PrintNote(channel, i, Heimdall_Data.config.notes[name][i])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
---@param name string
|
||||||
|
---@param sender string
|
||||||
|
---@param args string[]
|
||||||
|
local function AddNote(name, sender, args)
|
||||||
|
if not Heimdall_Data.config.notes[name] then Heimdall_Data.config.notes[name] = {} end
|
||||||
|
if Heimdall_Data.config.noter.debug then
|
||||||
|
print(string.format("[%s] Adding note for: %s from: %s", ModuleName, name, sender))
|
||||||
|
shared.dump(args)
|
||||||
|
end
|
||||||
|
local msgparts = {}
|
||||||
|
for i = 3, #args do
|
||||||
|
msgparts[#msgparts + 1] = args[i]
|
||||||
|
end
|
||||||
|
local msg = table.concat(msgparts, " ")
|
||||||
|
|
||||||
|
if Heimdall_Data.config.noter.debug then
|
||||||
|
print(string.format("[%s] Adding note for: %s from: %s", ModuleName, name, sender))
|
||||||
|
print(string.format("[%s] Note: %s", ModuleName, msg))
|
||||||
|
end
|
||||||
|
|
||||||
|
local note = {
|
||||||
|
source = sender,
|
||||||
|
date = date("%Y-%m-%dT%H:%M:%S"),
|
||||||
|
note = msg,
|
||||||
|
}
|
||||||
|
|
||||||
|
if Heimdall_Data.config.noter.debug then
|
||||||
|
print(string.format("[%s] Adding note", ModuleName))
|
||||||
|
shared.dump(note)
|
||||||
|
end
|
||||||
|
table.insert(Heimdall_Data.config.notes[name], note)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Here's the plan:
|
||||||
|
-- Implement a "note" command, that will do everything
|
||||||
|
-- Saying "note <name> <note>" will add a note to the list for the character
|
||||||
|
-- Saying "note <name>" will list last N notes
|
||||||
|
-- Saying "note <name> i" will list the i-th note
|
||||||
|
-- Saying "note <name> i..j" will list notes from i to j
|
||||||
|
-- Saying "note <name> delete i" will delete the i-th note
|
||||||
|
-- Saying "note <name> delete i..j" will delete notes from i to j
|
||||||
|
local noterChannelFrame = CreateFrame("Frame")
|
||||||
|
noterChannelFrame:RegisterEvent("CHAT_MSG_CHANNEL")
|
||||||
|
noterChannelFrame:SetScript("OnEvent", function(self, event, msg, sender, ...)
|
||||||
|
--if Heimdall_Data.config.noter.debug then
|
||||||
|
-- print(string.format("[%s] Event received", ModuleName))
|
||||||
|
-- shared.dump(Heimdall_Data.config.noter)
|
||||||
|
--end
|
||||||
|
if not Heimdall_Data.config.noter.enabled then
|
||||||
|
--if Heimdall_Data.config.noter.debug then
|
||||||
|
-- print(string.format("[%s] Module disabled, ignoring event", ModuleName))
|
||||||
|
--end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local channelId = select(6, ...)
|
||||||
|
local _, channelname = GetChannelName(channelId)
|
||||||
|
local ok = false
|
||||||
|
for _, channel in pairs(Heimdall_Data.config.noter.channels) do
|
||||||
|
if channelname == channel then
|
||||||
|
ok = true
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if not ok then
|
||||||
|
--if Heimdall_Data.config.noter.debug then
|
||||||
|
-- print(string.format("[%s] Channel %s does not match the master channel %s", ModuleName, channelname, Heimdall_Data.config.noter.masterChannel))
|
||||||
|
--end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
sender = string.match(sender, "^[^-]+")
|
||||||
|
if Heimdall_Data.config.noter.debug then
|
||||||
|
print(string.format("[%s] Message from: %s", ModuleName, sender))
|
||||||
|
shared.dump(Heimdall_Data.config.noter)
|
||||||
|
end
|
||||||
|
|
||||||
|
if not msg or msg == "" then
|
||||||
|
if Heimdall_Data.config.noter.debug then
|
||||||
|
print(string.format("[%s] Empty message, ignoring", ModuleName))
|
||||||
|
end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local args = { strsplit(" ", msg) }
|
||||||
|
if Heimdall_Data.config.noter.debug then
|
||||||
|
print(string.format("[%s] Arguments received: %s", ModuleName, table.concat(args, ", ")))
|
||||||
|
shared.dump(args)
|
||||||
|
end
|
||||||
|
local command = args[1]
|
||||||
|
if command == "note" then
|
||||||
|
local name = strtrim(string.lower(args[2] or ""))
|
||||||
|
if Heimdall_Data.config.noter.debug then
|
||||||
|
print(string.format("[%s] Note command received for: %s", ModuleName, name))
|
||||||
|
end
|
||||||
|
local note = strtrim(args[3] or "")
|
||||||
|
if Heimdall_Data.config.noter.debug then print(string.format("[%s] Note: %s", ModuleName, note)) end
|
||||||
|
if note == "delete" then
|
||||||
|
DeleteNotes(name, args)
|
||||||
|
elseif string.find(note, "^[%d%.]*$") then
|
||||||
|
PrintNotes(channelname, name, args)
|
||||||
|
else
|
||||||
|
AddNote(name, sender, args)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
print(string.format("[%s] Module initialized", ModuleName))
|
||||||
|
end,
|
||||||
|
}
|
@@ -8,12 +8,8 @@ local function Init()
|
|||||||
if otherType == "table" and other._type and other._type == self._type and other._value then
|
if otherType == "table" and other._type and other._type == self._type and other._value then
|
||||||
return self._value + other._value
|
return self._value + other._value
|
||||||
end
|
end
|
||||||
if otherType == "string" and self._type == otherType then
|
if otherType == "string" and self._type == otherType then return self._value .. other end
|
||||||
return self._value .. other
|
if otherType == "number" and self._type == otherType then return self._value + other end
|
||||||
end
|
|
||||||
if otherType == "number" and self._type == otherType then
|
|
||||||
return self._value + other
|
|
||||||
end
|
|
||||||
return nil
|
return nil
|
||||||
end,
|
end,
|
||||||
---@param self ReactiveValue
|
---@param self ReactiveValue
|
||||||
@@ -24,9 +20,7 @@ local function Init()
|
|||||||
if otherType == "table" and other._type and other._type == self._type and other._value then
|
if otherType == "table" and other._type and other._type == self._type and other._value then
|
||||||
return self._value * other._value
|
return self._value * other._value
|
||||||
end
|
end
|
||||||
if otherType == "number" and self._type == otherType then
|
if otherType == "number" and self._type == otherType then return self._value * other end
|
||||||
return self._value * other
|
|
||||||
end
|
|
||||||
return nil
|
return nil
|
||||||
end,
|
end,
|
||||||
---@param self ReactiveValue
|
---@param self ReactiveValue
|
||||||
@@ -37,9 +31,7 @@ local function Init()
|
|||||||
if otherType == "table" and other._type and other._type == self._type and other._value then
|
if otherType == "table" and other._type and other._type == self._type and other._value then
|
||||||
return self._value - other._value
|
return self._value - other._value
|
||||||
end
|
end
|
||||||
if otherType == "number" and self._type == otherType then
|
if otherType == "number" and self._type == otherType then return self._value - other end
|
||||||
return self._value - other
|
|
||||||
end
|
|
||||||
return nil
|
return nil
|
||||||
end,
|
end,
|
||||||
---@param self ReactiveValue
|
---@param self ReactiveValue
|
||||||
@@ -50,9 +42,7 @@ local function Init()
|
|||||||
if otherType == "table" and other._type and other._type == self._type and other._value then
|
if otherType == "table" and other._type and other._type == self._type and other._value then
|
||||||
return self._value / other._value
|
return self._value / other._value
|
||||||
end
|
end
|
||||||
if otherType == "number" and self._type == otherType then
|
if otherType == "number" and self._type == otherType then return self._value / other end
|
||||||
return self._value / other
|
|
||||||
end
|
|
||||||
return nil
|
return nil
|
||||||
end,
|
end,
|
||||||
---@param self ReactiveValue
|
---@param self ReactiveValue
|
||||||
@@ -63,9 +53,7 @@ local function Init()
|
|||||||
if otherType == "table" and other._type and other._type == self._type and other._value then
|
if otherType == "table" and other._type and other._type == self._type and other._value then
|
||||||
return self._value % other._value
|
return self._value % other._value
|
||||||
end
|
end
|
||||||
if otherType == "number" and self._type == otherType then
|
if otherType == "number" and self._type == otherType then return self._value % other end
|
||||||
return self._value % other
|
|
||||||
end
|
|
||||||
return nil
|
return nil
|
||||||
end,
|
end,
|
||||||
---@param self ReactiveValue
|
---@param self ReactiveValue
|
||||||
@@ -76,9 +64,7 @@ local function Init()
|
|||||||
if otherType == "table" and other._type and other._type == self._type and other._value then
|
if otherType == "table" and other._type and other._type == self._type and other._value then
|
||||||
return self._value ^ other._value
|
return self._value ^ other._value
|
||||||
end
|
end
|
||||||
if otherType == "number" and self._type == otherType then
|
if otherType == "number" and self._type == otherType then return self._value ^ other end
|
||||||
return self._value ^ other
|
|
||||||
end
|
|
||||||
return nil
|
return nil
|
||||||
end,
|
end,
|
||||||
---@param self ReactiveValue
|
---@param self ReactiveValue
|
||||||
@@ -134,19 +120,13 @@ local function Init()
|
|||||||
---@param self ReactiveValue
|
---@param self ReactiveValue
|
||||||
---@return number
|
---@return number
|
||||||
__len = function(self)
|
__len = function(self)
|
||||||
if self._type == "table" then
|
if self._type == "table" then return #self._value end
|
||||||
return #self._value
|
if self._type == "string" then return string.len(self._value) end
|
||||||
end
|
|
||||||
if self._type == "string" then
|
|
||||||
return string.len(self._value)
|
|
||||||
end
|
|
||||||
return 0
|
return 0
|
||||||
end,
|
end,
|
||||||
---@param self ReactiveValue
|
---@param self ReactiveValue
|
||||||
---@return string
|
---@return string
|
||||||
__tostring = function(self)
|
__tostring = function(self) return tostring(self._value) end,
|
||||||
return tostring(self._value)
|
|
||||||
end,
|
|
||||||
---@param self ReactiveValue
|
---@param self ReactiveValue
|
||||||
---@param key string
|
---@param key string
|
||||||
---@param value any
|
---@param value any
|
||||||
@@ -168,9 +148,7 @@ local function Init()
|
|||||||
-- If the value being assigned is a ReactiveValue
|
-- If the value being assigned is a ReactiveValue
|
||||||
-- Then listen to changes on it as well
|
-- Then listen to changes on it as well
|
||||||
-- And propagate those changes upwards
|
-- And propagate those changes upwards
|
||||||
if self._recursive and getmetatable(value) == getmetatable(self) then
|
if self._recursive and getmetatable(value) == getmetatable(self) then self:_setupListeners(key, value) end
|
||||||
self:_setupListeners(key, value)
|
|
||||||
end
|
|
||||||
|
|
||||||
self:_notify()
|
self:_notify()
|
||||||
self:_notifyFieldChanged(ChangedKey)
|
self:_notifyFieldChanged(ChangedKey)
|
||||||
@@ -181,18 +159,12 @@ local function Init()
|
|||||||
---@return any|nil
|
---@return any|nil
|
||||||
__index = function(self, key)
|
__index = function(self, key)
|
||||||
local value = rawget(self, key)
|
local value = rawget(self, key)
|
||||||
if value ~= nil then
|
if value ~= nil then return value end
|
||||||
return value
|
if rawget(self, "_type") ~= "table" then return nil end
|
||||||
end
|
|
||||||
if rawget(self, "_type") ~= "table" then
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
local innerTable = rawget(self, "_value")
|
local innerTable = rawget(self, "_value")
|
||||||
if innerTable ~= nil then
|
if innerTable ~= nil then return rawget(innerTable, key) end
|
||||||
return rawget(innerTable, key)
|
|
||||||
end
|
|
||||||
return nil
|
return nil
|
||||||
end
|
end,
|
||||||
-- __index = ReactiveValue
|
-- __index = ReactiveValue
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -343,14 +315,10 @@ local function Init()
|
|||||||
self._recursive = recursive or false
|
self._recursive = recursive or false
|
||||||
|
|
||||||
---@return any
|
---@return any
|
||||||
self.get = function(self)
|
self.get = function(self) return self._value end
|
||||||
return self._value
|
|
||||||
end
|
|
||||||
---@param newValue any
|
---@param newValue any
|
||||||
self.set = function(self, newValue)
|
self.set = function(self, newValue)
|
||||||
if self._value == newValue then
|
if self._value == newValue then return end
|
||||||
return
|
|
||||||
end
|
|
||||||
if type(newValue) ~= self._type then
|
if type(newValue) ~= self._type then
|
||||||
error("Expected " .. self._type .. ", got " .. type(newValue))
|
error("Expected " .. self._type .. ", got " .. type(newValue))
|
||||||
return
|
return
|
||||||
@@ -364,22 +332,16 @@ local function Init()
|
|||||||
return function() end
|
return function() end
|
||||||
end
|
end
|
||||||
self._listeners[callback] = true
|
self._listeners[callback] = true
|
||||||
return function()
|
return function() self._listeners[callback] = nil end
|
||||||
self._listeners[callback] = nil
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
self.onFieldChange = function(self, field, callback)
|
self.onFieldChange = function(self, field, callback)
|
||||||
if type(callback) ~= "function" then
|
if type(callback) ~= "function" then
|
||||||
error("Expected function, got " .. type(callback))
|
error("Expected function, got " .. type(callback))
|
||||||
return function() end
|
return function() end
|
||||||
end
|
end
|
||||||
if self._fieldListeners[field] == nil then
|
if self._fieldListeners[field] == nil then self._fieldListeners[field] = {} end
|
||||||
self._fieldListeners[field] = {}
|
|
||||||
end
|
|
||||||
self._fieldListeners[field][callback] = true
|
self._fieldListeners[field][callback] = true
|
||||||
return function()
|
return function() self._fieldListeners[field][callback] = nil end
|
||||||
self._fieldListeners[field][callback] = nil
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
self.onAnyFieldChange = function(self, callback, depth)
|
self.onAnyFieldChange = function(self, callback, depth)
|
||||||
depth = depth or 99999
|
depth = depth or 99999
|
||||||
@@ -387,13 +349,9 @@ local function Init()
|
|||||||
error("Expected function, got " .. type(callback))
|
error("Expected function, got " .. type(callback))
|
||||||
return function() end
|
return function() end
|
||||||
end
|
end
|
||||||
if self._anyFieldListeners[depth] == nil then
|
if self._anyFieldListeners[depth] == nil then self._anyFieldListeners[depth] = {} end
|
||||||
self._anyFieldListeners[depth] = {}
|
|
||||||
end
|
|
||||||
self._anyFieldListeners[depth][callback] = true
|
self._anyFieldListeners[depth][callback] = true
|
||||||
return function()
|
return function() self._anyFieldListeners[depth][callback] = nil end
|
||||||
self._anyFieldListeners[depth][callback] = nil
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
self.once = function(self, callback)
|
self.once = function(self, callback)
|
||||||
if type(callback) ~= "function" then
|
if type(callback) ~= "function" then
|
||||||
@@ -401,15 +359,11 @@ local function Init()
|
|||||||
return function() end
|
return function() end
|
||||||
end
|
end
|
||||||
self._oneTimeListeners[callback] = true
|
self._oneTimeListeners[callback] = true
|
||||||
return function()
|
return function() self._oneTimeListeners[callback] = nil end
|
||||||
self._oneTimeListeners[callback] = nil
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
self._setupAllListenersRecursively = function(self)
|
self._setupAllListenersRecursively = function(self)
|
||||||
if self._type ~= "table" then
|
if self._type ~= "table" then return end
|
||||||
return
|
|
||||||
end
|
|
||||||
for key, value in pairs(self._value) do
|
for key, value in pairs(self._value) do
|
||||||
self:_setupListeners(key, value, true)
|
self:_setupListeners(key, value, true)
|
||||||
end
|
end
|
||||||
@@ -419,12 +373,8 @@ local function Init()
|
|||||||
---@param recursive boolean?
|
---@param recursive boolean?
|
||||||
self._setupListeners = function(self, key, value, recursive)
|
self._setupListeners = function(self, key, value, recursive)
|
||||||
recursive = recursive or false
|
recursive = recursive or false
|
||||||
if self._type ~= "table" then
|
if self._type ~= "table" then return end
|
||||||
return
|
if getmetatable(value) ~= getmetatable(self) then return end
|
||||||
end
|
|
||||||
if getmetatable(value) ~= getmetatable(self) then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
value._recursive = true
|
value._recursive = true
|
||||||
if value._type == "table" then
|
if value._type == "table" then
|
||||||
value:onAnyFieldChange(function(key2)
|
value:onAnyFieldChange(function(key2)
|
||||||
@@ -440,14 +390,10 @@ local function Init()
|
|||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
if recursive then
|
if recursive then value:_setupAllListenersRecursively() end
|
||||||
value:_setupAllListenersRecursively()
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
if recursive then
|
if recursive then self:_setupAllListenersRecursively() end
|
||||||
self:_setupAllListenersRecursively()
|
|
||||||
end
|
|
||||||
|
|
||||||
self._notify = function(self)
|
self._notify = function(self)
|
||||||
for listener, _ in pairs(self._oneTimeListeners) do
|
for listener, _ in pairs(self._oneTimeListeners) do
|
||||||
@@ -474,9 +420,7 @@ local function Init()
|
|||||||
end
|
end
|
||||||
|
|
||||||
local strfield = table.concat(field, ".")
|
local strfield = table.concat(field, ".")
|
||||||
if self._fieldListeners[strfield] == nil then
|
if self._fieldListeners[strfield] == nil then return end
|
||||||
return
|
|
||||||
end
|
|
||||||
for listener, _ in pairs(self._fieldListeners[strfield]) do
|
for listener, _ in pairs(self._fieldListeners[strfield]) do
|
||||||
-- task.spawn(listener, value, type(value))
|
-- task.spawn(listener, value, type(value))
|
||||||
listener(value, type(value))
|
listener(value, type(value))
|
||||||
@@ -539,7 +483,7 @@ local function Init()
|
|||||||
-- S local clbk = test:onChange(function(value)
|
-- S local clbk = test:onChange(function(value)
|
||||||
-- S invocations = invocations + 1
|
-- S invocations = invocations + 1
|
||||||
-- S print("test changed to")
|
-- S print("test changed to")
|
||||||
-- S dumpTable(value, 0)
|
-- S dump(value, 0)
|
||||||
-- S end)
|
-- S end)
|
||||||
-- S test:set({1, 2, 3, 4})
|
-- S test:set({1, 2, 3, 4})
|
||||||
-- S assert(invocations == 1)
|
-- S assert(invocations == 1)
|
||||||
@@ -572,7 +516,7 @@ local function Init()
|
|||||||
-- S test:once(function(value)
|
-- S test:once(function(value)
|
||||||
-- S invocations = invocations + 1
|
-- S invocations = invocations + 1
|
||||||
-- S print("test changed to")
|
-- S print("test changed to")
|
||||||
-- S dumpTable(value, 0)
|
-- S dump(value, 0)
|
||||||
-- S end)
|
-- S end)
|
||||||
-- S test:set({3, 2, 1})
|
-- S test:set({3, 2, 1})
|
||||||
-- S assert(invocations == 1)
|
-- S assert(invocations == 1)
|
||||||
@@ -583,7 +527,7 @@ local function Init()
|
|||||||
-- S test:onChange(function(value)
|
-- S test:onChange(function(value)
|
||||||
-- S invocations = invocations + 1
|
-- S invocations = invocations + 1
|
||||||
-- S print("test changed to")
|
-- S print("test changed to")
|
||||||
-- S dumpTable(value, 0)
|
-- S dump(value, 0)
|
||||||
-- S end)
|
-- S end)
|
||||||
-- S test:onAnyFieldChange(function(field, value)
|
-- S test:onAnyFieldChange(function(field, value)
|
||||||
-- S invocations = invocations + 1
|
-- S invocations = invocations + 1
|
||||||
@@ -661,7 +605,5 @@ local frame = CreateFrame("Frame")
|
|||||||
frame:RegisterEvent("PLAYER_LOGIN")
|
frame:RegisterEvent("PLAYER_LOGIN")
|
||||||
frame:RegisterEvent("PLAYER_ENTERING_WORLD")
|
frame:RegisterEvent("PLAYER_ENTERING_WORLD")
|
||||||
frame:RegisterEvent("GUILD_ROSTER_UPDATE")
|
frame:RegisterEvent("GUILD_ROSTER_UPDATE")
|
||||||
frame:SetScript("OnEvent", function(self, event, ...)
|
frame:SetScript("OnEvent", function(self, event, ...) Init() end)
|
||||||
Init()
|
|
||||||
end)
|
|
||||||
Init()
|
Init()
|
||||||
|
92
Modules/Sniffer.lua
Normal file
92
Modules/Sniffer.lua
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
local _, shared = ...
|
||||||
|
---@cast shared HeimdallShared
|
||||||
|
local ModuleName = "Sniffer"
|
||||||
|
|
||||||
|
---@class HeimdallSnifferConfig
|
||||||
|
---@field enabled boolean
|
||||||
|
---@field debug boolean
|
||||||
|
---@field channels string[]
|
||||||
|
---@field throttle number -- throttleTime in the original code, matching config name now
|
||||||
|
---@field zoneOverride string?
|
||||||
|
---@field stinky boolean
|
||||||
|
|
||||||
|
---@class Sniffer
|
||||||
|
shared.Sniffer = {
|
||||||
|
Init = function()
|
||||||
|
if Heimdall_Data.config.sniffer.debug then print(string.format("[%s] Module initializing", ModuleName)) end
|
||||||
|
local smellThrottle = {}
|
||||||
|
local SmellStinky = function(stinky)
|
||||||
|
if Heimdall_Data.config.sniffer.debug then
|
||||||
|
print(string.format("%s: SmellStinky", ModuleName))
|
||||||
|
shared.dump(Heimdall_Data.config.sniffer)
|
||||||
|
end
|
||||||
|
if not Heimdall_Data.config.sniffer.enabled then return end
|
||||||
|
if Heimdall_Data.config.sniffer.stinky and not shared.IsStinky(stinky) then
|
||||||
|
if Heimdall_Data.config.sniffer.debug then
|
||||||
|
print(string.format("%s: Stinky not found in config", ModuleName))
|
||||||
|
end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
if smellThrottle[stinky] and GetTime() - smellThrottle[stinky] < Heimdall_Data.config.sniffer.throttle then
|
||||||
|
if Heimdall_Data.config.sniffer.debug then print(string.format("%s: Throttled", ModuleName)) end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
smellThrottle[stinky] = GetTime()
|
||||||
|
|
||||||
|
for _, channel in pairs(Heimdall_Data.config.sniffer.channels) do
|
||||||
|
local locale = shared.GetLocaleForChannel(channel)
|
||||||
|
local text = string.format(shared._L("snifferStinky", locale), stinky)
|
||||||
|
---@type Message
|
||||||
|
local msg = {
|
||||||
|
channel = "C",
|
||||||
|
data = channel,
|
||||||
|
message = text,
|
||||||
|
}
|
||||||
|
if Heimdall_Data.config.sniffer.debug then
|
||||||
|
print(string.format("[%s] Queuing sniffer message", ModuleName))
|
||||||
|
shared.dump(msg)
|
||||||
|
end
|
||||||
|
table.insert(shared.messenger.queue, msg)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local cleuFrame = CreateFrame("Frame")
|
||||||
|
cleuFrame:RegisterEvent("COMBAT_LOG_EVENT_UNFILTERED")
|
||||||
|
cleuFrame:SetScript("OnEvent", function(self, event, ...)
|
||||||
|
if Heimdall_Data.config.sniffer.debug then
|
||||||
|
print(string.format("[%s] Received event: %s", ModuleName, event))
|
||||||
|
end
|
||||||
|
if not Heimdall_Data.config.sniffer.enabled then
|
||||||
|
if Heimdall_Data.config.sniffer.debug then
|
||||||
|
print(string.format("[%s] Module disabled, ignoring event", ModuleName))
|
||||||
|
end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local source, destination, err
|
||||||
|
source, err = CLEUParser.GetSourceName(...)
|
||||||
|
if Heimdall_Data.config.sniffer.debug then
|
||||||
|
print(string.format("[%s] Processing source: %s", ModuleName, source))
|
||||||
|
end
|
||||||
|
if err then
|
||||||
|
if Heimdall_Data.config.sniffer.debug then
|
||||||
|
print(string.format("[%s] Error parsing source: %s", ModuleName, err))
|
||||||
|
end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
SmellStinky(source)
|
||||||
|
destination, err = CLEUParser.GetDestName(...)
|
||||||
|
if Heimdall_Data.config.sniffer.debug then
|
||||||
|
print(string.format("[%s] Processing destination: %s", ModuleName, destination))
|
||||||
|
end
|
||||||
|
if err then
|
||||||
|
if Heimdall_Data.config.sniffer.debug then
|
||||||
|
print(string.format("[%s] Error parsing destination: %s", ModuleName, err))
|
||||||
|
end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
SmellStinky(destination)
|
||||||
|
end)
|
||||||
|
if Heimdall_Data.config.sniffer.debug then print(string.format("[%s] Module initialized", ModuleName)) end
|
||||||
|
print(string.format("[%s] Module initialized", ModuleName))
|
||||||
|
end,
|
||||||
|
}
|
@@ -1,10 +1,21 @@
|
|||||||
local addonname, shared = ...
|
local _, shared = ...
|
||||||
---@cast shared HeimdallShared
|
---@cast shared HeimdallShared
|
||||||
---@cast addonname string
|
local ModuleName = "Spotter"
|
||||||
|
|
||||||
---@diagnostic disable-next-line: missing-fields
|
---@class HeimdallSpotterConfig
|
||||||
shared.Spotter = {}
|
---@field enabled boolean
|
||||||
function shared.Spotter.Init()
|
---@field debug boolean
|
||||||
|
---@field everyone boolean
|
||||||
|
---@field hostile boolean
|
||||||
|
---@field alliance boolean
|
||||||
|
---@field stinky boolean
|
||||||
|
---@field channels string[]
|
||||||
|
---@field zoneOverride string?
|
||||||
|
---@field throttleTime number
|
||||||
|
|
||||||
|
---@class Spotter
|
||||||
|
shared.Spotter = {
|
||||||
|
Init = function()
|
||||||
local function FormatHP(hp)
|
local function FormatHP(hp)
|
||||||
if hp > 1e9 then
|
if hp > 1e9 then
|
||||||
return string.format("%.1fB", hp / 1e9)
|
return string.format("%.1fB", hp / 1e9)
|
||||||
@@ -27,15 +38,52 @@ function shared.Spotter.Init()
|
|||||||
---@return boolean
|
---@return boolean
|
||||||
---@return string? error
|
---@return string? error
|
||||||
local function ShouldNotify(unit, name, faction, hostile)
|
local function ShouldNotify(unit, name, faction, hostile)
|
||||||
if Heimdall_Data.config.agents[name] then return false end
|
if Heimdall_Data.config.spotter.debug then
|
||||||
|
print(string.format("[%s] Checking notification criteria for %s (%s)", ModuleName, name, faction))
|
||||||
|
end
|
||||||
|
|
||||||
|
if shared.AgentTracker.IsAgent(name) then
|
||||||
|
if Heimdall_Data.config.spotter.debug then
|
||||||
|
print(string.format("[%s] Skipping agent: %s", ModuleName, name))
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
if Heimdall_Data.config.spotter.stinky then
|
if Heimdall_Data.config.spotter.stinky then
|
||||||
if Heimdall_Data.config.stinkies[name] then return true end
|
if shared.IsStinky(name) then
|
||||||
|
if Heimdall_Data.config.spotter.debug then
|
||||||
|
print(string.format("[%s] Notifying - Found stinky: %s", ModuleName, name))
|
||||||
end
|
end
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
if Heimdall_Data.config.spotter.alliance then
|
if Heimdall_Data.config.spotter.alliance then
|
||||||
if faction == "Alliance" then return true end
|
if faction == "Alliance" then
|
||||||
|
if Heimdall_Data.config.spotter.debug then
|
||||||
|
print(string.format("[%s] Notifying - Found Alliance player: %s", ModuleName, name))
|
||||||
end
|
end
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
if Heimdall_Data.config.spotter.hostile then
|
if Heimdall_Data.config.spotter.hostile then
|
||||||
if hostile then return true end
|
if hostile then
|
||||||
|
if Heimdall_Data.config.spotter.debug then
|
||||||
|
print(string.format("[%s] Notifying - Found hostile player: %s", ModuleName, name))
|
||||||
|
end
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if Heimdall_Data.config.spotter.debug then
|
||||||
|
print(
|
||||||
|
string.format(
|
||||||
|
"[%s] Using everyone setting: %s",
|
||||||
|
ModuleName,
|
||||||
|
tostring(Heimdall_Data.config.spotter.everyone)
|
||||||
|
)
|
||||||
|
)
|
||||||
end
|
end
|
||||||
return Heimdall_Data.config.spotter.everyone
|
return Heimdall_Data.config.spotter.everyone
|
||||||
end
|
end
|
||||||
@@ -43,14 +91,32 @@ function shared.Spotter.Init()
|
|||||||
---@param unit string
|
---@param unit string
|
||||||
---@return string?
|
---@return string?
|
||||||
local function NotifySpotted(unit)
|
local function NotifySpotted(unit)
|
||||||
|
if Heimdall_Data.config.spotter.debug then
|
||||||
|
print(string.format("[%s] Processing spotted unit: %s", ModuleName, unit))
|
||||||
|
end
|
||||||
|
|
||||||
if not unit then return string.format("Could not find unit %s", tostring(unit)) end
|
if not unit then return string.format("Could not find unit %s", tostring(unit)) end
|
||||||
if not UnitIsPlayer(unit) then return nil end
|
if not UnitIsPlayer(unit) then
|
||||||
|
if Heimdall_Data.config.spotter.debug then
|
||||||
|
print(string.format("[%s] Ignoring non-player unit: %s", ModuleName, unit))
|
||||||
|
end
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
local name = UnitName(unit)
|
local name = UnitName(unit)
|
||||||
if not name then return string.format("Could not find name for unit %s", tostring(unit)) end
|
if not name then return string.format("Could not find name for unit %s", tostring(unit)) end
|
||||||
|
if Heimdall_Data.config.spotter.debug then
|
||||||
|
print(string.format("[%s] Processing player: %s", ModuleName, name))
|
||||||
|
end
|
||||||
|
|
||||||
local time = GetTime()
|
local time = GetTime()
|
||||||
if throttleTable[name] and time - throttleTable[name] < Heimdall_Data.config.spotter.throttleTime then
|
if throttleTable[name] and time - throttleTable[name] < Heimdall_Data.config.spotter.throttleTime then
|
||||||
|
if Heimdall_Data.config.spotter.debug then
|
||||||
|
local remainingTime = Heimdall_Data.config.spotter.throttleTime - (time - throttleTable[name])
|
||||||
|
print(
|
||||||
|
string.format("[%s] Player %s throttled for %.1f more seconds", ModuleName, name, remainingTime)
|
||||||
|
)
|
||||||
|
end
|
||||||
return string.format("Throttled %s", tostring(name))
|
return string.format("Throttled %s", tostring(name))
|
||||||
end
|
end
|
||||||
throttleTable[name] = time
|
throttleTable[name] = time
|
||||||
@@ -59,66 +125,114 @@ function shared.Spotter.Init()
|
|||||||
if not race then return string.format("Could not find race for unit %s", tostring(unit)) end
|
if not race then return string.format("Could not find race for unit %s", tostring(unit)) end
|
||||||
local faction = shared.raceMap[race]
|
local faction = shared.raceMap[race]
|
||||||
if not faction then return string.format("Could not find faction for race %s", tostring(race)) end
|
if not faction then return string.format("Could not find faction for race %s", tostring(race)) end
|
||||||
|
if Heimdall_Data.config.spotter.debug then
|
||||||
|
print(string.format("[%s] Player %s is %s (%s)", ModuleName, name, race, faction))
|
||||||
|
end
|
||||||
|
|
||||||
local hostile = UnitCanAttack("player", unit)
|
local hostile = UnitCanAttack("player", unit)
|
||||||
|
if Heimdall_Data.config.spotter.debug then
|
||||||
|
print(string.format("[%s] Player %s is %s", ModuleName, name, hostile and "hostile" or "friendly"))
|
||||||
|
end
|
||||||
|
|
||||||
local doNotify = ShouldNotify(unit, name, faction, hostile)
|
local doNotify = ShouldNotify(unit, name, faction, hostile)
|
||||||
if not doNotify then return string.format("Not notifying for %s", tostring(name)) end
|
if not doNotify then
|
||||||
|
if Heimdall_Data.config.spotter.debug then
|
||||||
|
print(string.format("[%s] Skipping notification for %s", ModuleName, name))
|
||||||
|
end
|
||||||
|
return string.format("Not notifying for %s", tostring(name))
|
||||||
|
end
|
||||||
|
|
||||||
local hp = UnitHealth(unit)
|
local hp = UnitHealth(unit)
|
||||||
if not hp then return string.format("Could not find hp for unit %s", tostring(unit)) end
|
if not hp then return string.format("Could not find hp for unit %s", tostring(unit)) end
|
||||||
|
|
||||||
local maxHp = UnitHealthMax(unit)
|
local maxHp = UnitHealthMax(unit)
|
||||||
if not maxHp then return string.format("Could not find maxHp for unit %s", tostring(unit)) end
|
if not maxHp then return string.format("Could not find maxHp for unit %s", tostring(unit)) end
|
||||||
|
if Heimdall_Data.config.spotter.debug then
|
||||||
|
print(string.format("[%s] Player %s health: %s/%s", ModuleName, name, FormatHP(hp), FormatHP(maxHp)))
|
||||||
|
end
|
||||||
|
|
||||||
local class = UnitClass(unit)
|
local class = UnitClass(unit)
|
||||||
if not class then return string.format("Could not find class for unit %s", tostring(unit)) end
|
if not class then return string.format("Could not find class for unit %s", tostring(unit)) end
|
||||||
|
|
||||||
local location = Heimdall_Data.config.spotter.zoneOverride
|
local zone, subzone = GetZoneText() or "Unknown", GetSubZoneText() or "Unknown"
|
||||||
if not location or location == "" then
|
if Heimdall_Data.config.spotter.zoneOverride then
|
||||||
local zone = GetZoneText()
|
zone = Heimdall_Data.config.spotter.zoneOverride or ""
|
||||||
if not zone then return string.format("Could not find zone for unit %s", tostring(unit)) end
|
subzone = ""
|
||||||
local subzone = GetSubZoneText()
|
|
||||||
if not subzone then subzone = "" end
|
|
||||||
location = string.format("%s (%s)", zone, subzone)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
local x, y = GetPlayerMapPosition("player")
|
local x, y = GetPlayerMapPosition("player")
|
||||||
local stinky = Heimdall_Data.config.stinkies[name] or false
|
if Heimdall_Data.config.spotter.debug then
|
||||||
local text = string.format("I see (%s) %s/%s %s of race %s (%s) with health %s/%s at %s (%2.2f, %2.2f)",
|
print(string.format("[%s] Player %s coordinates: %.2f, %.2f", ModuleName, name, x * 100, y * 100))
|
||||||
hostile and "Hostile" or "Friendly",
|
end
|
||||||
|
|
||||||
|
local pvpOn = UnitIsPVP(unit)
|
||||||
|
local stinky = shared.IsStinky(name) or false
|
||||||
|
SetMapToCurrentZone()
|
||||||
|
SetMapByID(GetCurrentMapAreaID())
|
||||||
|
local areaId = tostring(GetCurrentMapAreaID())
|
||||||
|
|
||||||
|
for _, channel in pairs(Heimdall_Data.config.spotter.channels) do
|
||||||
|
if Heimdall_Data.config.spotter.debug then
|
||||||
|
print(string.format("[%s] Processing channel: %s", ModuleName, channel))
|
||||||
|
end
|
||||||
|
local locale = shared.GetLocaleForChannel(channel)
|
||||||
|
local text = string.format(
|
||||||
|
shared._L("spotterSpotted", locale),
|
||||||
|
hostile and shared._L("hostile", locale) or shared._L("friendly", locale),
|
||||||
name,
|
name,
|
||||||
class,
|
shared._L(class, locale),
|
||||||
stinky and string.format("(%s)", "!!!!") or "",
|
stinky and string.format("(%s)", "!!!!") or "",
|
||||||
race,
|
shared._L(race, locale),
|
||||||
faction,
|
shared._L(faction, locale),
|
||||||
FormatHP(hp),
|
pvpOn and shared._L("pvpOn", locale) or shared._L("pvpOff", locale),
|
||||||
FormatHP(maxHp),
|
string.gsub(FormatHP(hp), "M", "kk"),
|
||||||
location,
|
string.gsub(FormatHP(maxHp), "M", "kk"),
|
||||||
x * 100, y * 100)
|
shared._L(zone, locale),
|
||||||
|
shared._L(subzone, locale),
|
||||||
|
areaId,
|
||||||
|
x * 100,
|
||||||
|
y * 100
|
||||||
|
)
|
||||||
|
|
||||||
---@type Message
|
---@type Message
|
||||||
local msg = {
|
local msg = {
|
||||||
channel = "CHANNEL",
|
channel = "C",
|
||||||
data = Heimdall_Data.config.spotter.notifyChannel,
|
data = channel,
|
||||||
message = text
|
message = text,
|
||||||
}
|
}
|
||||||
--shared.dumpTable(msg)
|
if Heimdall_Data.config.spotter.debug then
|
||||||
|
print(string.format("[%s] Queuing spotter message", ModuleName))
|
||||||
|
shared.dump(msg)
|
||||||
|
end
|
||||||
table.insert(shared.messenger.queue, msg)
|
table.insert(shared.messenger.queue, msg)
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
local frame = CreateFrame("Frame")
|
local frame = CreateFrame("Frame")
|
||||||
frame:RegisterEvent("NAME_PLATE_UNIT_ADDED")
|
frame:RegisterEvent("NAME_PLATE_UNIT_ADDED")
|
||||||
frame:RegisterEvent("UNIT_TARGET")
|
frame:RegisterEvent("UNIT_TARGET")
|
||||||
frame:SetScript("OnEvent", function(self, event, unit)
|
frame:SetScript("OnEvent", function(self, event, unit)
|
||||||
if not Heimdall_Data.config.spotter.enabled then return end
|
if Heimdall_Data.config.spotter.debug then
|
||||||
if event == "UNIT_TARGET" then
|
print(string.format("[%s] Event received: %s for unit: %s", ModuleName, event, unit or "target"))
|
||||||
unit = "target"
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if not Heimdall_Data.config.spotter.enabled then
|
||||||
|
if Heimdall_Data.config.spotter.debug then
|
||||||
|
print(string.format("[%s] Module disabled, ignoring event", ModuleName))
|
||||||
|
end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
if event == "UNIT_TARGET" then unit = "target" end
|
||||||
|
|
||||||
local err = NotifySpotted(unit)
|
local err = NotifySpotted(unit)
|
||||||
if err then
|
if err then
|
||||||
print(string.format("Error notifying %s: %s", tostring(unit), tostring(err)))
|
if Heimdall_Data.config.spotter.debug then
|
||||||
|
print(string.format("[%s] Error processing unit %s: %s", ModuleName, unit, err))
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
|
|
||||||
print("Heimdall - Spotter loaded")
|
if Heimdall_Data.config.spotter.debug then print(string.format("[%s] Module initialized", ModuleName)) end
|
||||||
end
|
print(string.format("[%s] Module initialized", ModuleName))
|
||||||
|
end,
|
||||||
|
}
|
||||||
|
83
Modules/StinkyCache.lua
Normal file
83
Modules/StinkyCache.lua
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
local _, shared = ...
|
||||||
|
---@cast shared HeimdallShared
|
||||||
|
local ModuleName = "StinkyCache"
|
||||||
|
|
||||||
|
---@class HeimdallStinkyCacheConfig
|
||||||
|
---@field enabled boolean
|
||||||
|
---@field debug boolean
|
||||||
|
---@field commander string
|
||||||
|
---@field ttl number
|
||||||
|
|
||||||
|
---@class HeimdallStinkyCacheData
|
||||||
|
---@field stinkies table<string, {value: number, timestamp: number}>
|
||||||
|
|
||||||
|
---@class StinkyCache
|
||||||
|
shared.StinkyCache = {
|
||||||
|
Init = function()
|
||||||
|
shared.stinkyCache = {
|
||||||
|
stinkies = {},
|
||||||
|
}
|
||||||
|
|
||||||
|
---@param name string
|
||||||
|
local function AskCommander(name)
|
||||||
|
if Heimdall_Data.config.stinkyCache.debug then
|
||||||
|
print(
|
||||||
|
string.format(
|
||||||
|
"[%s] Asking commander %s about %s",
|
||||||
|
ModuleName,
|
||||||
|
Heimdall_Data.config.stinkyCache.commander,
|
||||||
|
name
|
||||||
|
)
|
||||||
|
)
|
||||||
|
end
|
||||||
|
local messageParts = { "isstinky", name }
|
||||||
|
local message = table.concat(messageParts, "|")
|
||||||
|
SendAddonMessage(
|
||||||
|
Heimdall_Data.config.addonPrefix,
|
||||||
|
message,
|
||||||
|
"WHISPER",
|
||||||
|
Heimdall_Data.config.stinkyCache.commander
|
||||||
|
)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local addonMessageFrame = CreateFrame("Frame")
|
||||||
|
addonMessageFrame:RegisterEvent("CHAT_MSG_ADDON")
|
||||||
|
addonMessageFrame:SetScript("OnEvent", function(self, event, msg, sender, ...)
|
||||||
|
if sender == Heimdall_Data.config.stinkyCache.commander then
|
||||||
|
if Heimdall_Data.config.stinkyCache.debug then
|
||||||
|
print(
|
||||||
|
string.format(
|
||||||
|
"[%s] Received stinky from commander %s: %s",
|
||||||
|
ModuleName,
|
||||||
|
Heimdall_Data.config.stinkyCache.commander,
|
||||||
|
msg
|
||||||
|
)
|
||||||
|
)
|
||||||
|
end
|
||||||
|
local parts = { strsplit("|", msg) }
|
||||||
|
local name, value = parts[1], parts[2]
|
||||||
|
shared.stinkyCache.stinkies[name] = { value = value, timestamp = time() }
|
||||||
|
else
|
||||||
|
if Heimdall_Data.config.stinkyCache.debug then
|
||||||
|
print(string.format("[%s] Received stinky from non-commander %s: %s", ModuleName, sender, msg))
|
||||||
|
end
|
||||||
|
local parts = { strsplit("|", msg) }
|
||||||
|
local command, name = parts[1], parts[2]
|
||||||
|
if parts[1] == "isstinky" then local res = Heimdall_Data.config.stinkies[parts[2]] end
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
setmetatable(shared.stinkyCache.stinkies, {
|
||||||
|
__index = function(self, key)
|
||||||
|
local value = rawget(self, key)
|
||||||
|
local now = GetTime()
|
||||||
|
if value == nil or now - value.timestamp > Heimdall_Data.config.stinkyCache.ttl then
|
||||||
|
AskCommander(key)
|
||||||
|
end
|
||||||
|
return rawget(self, key)
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
print(string.format("[%s] Module initialized", ModuleName))
|
||||||
|
end,
|
||||||
|
}
|
@@ -1,109 +1,364 @@
|
|||||||
local addonname, shared = ...
|
local _, shared = ...
|
||||||
---@cast shared HeimdallShared
|
---@cast shared HeimdallShared
|
||||||
---@cast addonname string
|
local ModuleName = "StinkyTracker"
|
||||||
|
|
||||||
---@diagnostic disable-next-line: missing-fields
|
---@class Stinky
|
||||||
shared.StinkyTracker = {}
|
---@field name string
|
||||||
function shared.StinkyTracker.Init()
|
---@field class string
|
||||||
|
---@field seenAt number
|
||||||
|
---@field hostile boolean
|
||||||
|
|
||||||
|
---@class HeimdallStinkyTrackerConfig
|
||||||
|
---@field enabled boolean
|
||||||
|
---@field debug boolean
|
||||||
|
---@field ignoredTimeout number
|
||||||
|
---@field channels string[]
|
||||||
|
|
||||||
|
---@class StinkyTrackerData
|
||||||
|
---@field stinkies ReactiveValue<table<string, Stinky>>
|
||||||
|
---@field ignored ReactiveValue<table<string, number>>
|
||||||
|
|
||||||
|
---@class StinkyTracker
|
||||||
|
shared.StinkyTracker = {
|
||||||
|
---@param stinky Stinky
|
||||||
|
---@return boolean
|
||||||
|
Track = function(stinky)
|
||||||
|
if Heimdall_Data.config.stinkyTracker.debug then
|
||||||
|
print(string.format("[%s] Request to track stinky: %s (%s)", ModuleName, stinky.name, stinky.class))
|
||||||
|
end
|
||||||
|
local ignored = shared.stinkyTracker.ignored[stinky.name]
|
||||||
|
-- TODO: Add a config option for the ignored timeout
|
||||||
|
if ignored and ignored > GetTime() - 60 then
|
||||||
|
if Heimdall_Data.config.stinkyTracker.debug then
|
||||||
|
print(
|
||||||
|
string.format(
|
||||||
|
"[%s] Stinky is ignored, not tracking: %s (%s)",
|
||||||
|
ModuleName,
|
||||||
|
stinky.name,
|
||||||
|
stinky.class
|
||||||
|
)
|
||||||
|
)
|
||||||
|
shared.dump(shared.stinkyTracker.ignored:get())
|
||||||
|
shared.dump(shared.stinkyTracker.stinkies:get())
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
else
|
||||||
|
-- Timed out or was never ignored
|
||||||
|
shared.stinkyTracker.stinkies[stinky.name] = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
shared.stinkyTracker.stinkies[stinky.name] = stinky
|
||||||
|
if Heimdall_Data.config.stinkyTracker.debug then
|
||||||
|
print(string.format("[%s] Stinky is now tracked: %s (%s)", ModuleName, stinky.name, stinky.class))
|
||||||
|
shared.dump(shared.stinkyTracker.stinkies:get())
|
||||||
|
shared.dump(shared.stinkyTracker.ignored:get())
|
||||||
|
end
|
||||||
|
return true
|
||||||
|
end,
|
||||||
|
|
||||||
|
---@param name string
|
||||||
|
---@return nil
|
||||||
|
Ignore = function(name)
|
||||||
|
if Heimdall_Data.config.stinkyTracker.debug then
|
||||||
|
print(string.format("[%s] Request to ignore stinky: %s", ModuleName, name))
|
||||||
|
end
|
||||||
|
shared.stinkyTracker.ignored[name] = GetTime()
|
||||||
|
shared.stinkyTracker.stinkies[name] = nil
|
||||||
|
if Heimdall_Data.config.stinkyTracker.debug then
|
||||||
|
print(string.format("[%s] Stinky is now ignored: %s", ModuleName, name))
|
||||||
|
shared.dump(shared.stinkyTracker.ignored:get())
|
||||||
|
shared.dump(shared.stinkyTracker.stinkies:get())
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
|
||||||
|
---@param name string
|
||||||
|
---@return boolean
|
||||||
|
IsStinky = function(name)
|
||||||
|
if not shared.stinkyTracker.stinkies then return false end
|
||||||
|
if not shared.stinkyTracker.stinkies[name] then return false end
|
||||||
|
if shared.stinkyTracker.ignored[name] then return false end
|
||||||
|
return true
|
||||||
|
end,
|
||||||
|
|
||||||
|
---@param callback fun(stinkies: table<string, Stinky>)
|
||||||
|
---@return nil
|
||||||
|
OnChange = function(callback) shared.stinkyTracker.stinkies:onChange(callback) end,
|
||||||
|
|
||||||
|
---@param callback fun(name: string, stinky: Stinky)
|
||||||
|
---@return nil
|
||||||
|
ForEach = function(callback)
|
||||||
|
---@type table<string, Stinky>
|
||||||
|
local stinkies = shared.stinkyTracker.stinkies:get()
|
||||||
|
for name, stinky in pairs(stinkies) do
|
||||||
|
callback(name, stinky)
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
|
||||||
|
Init = function()
|
||||||
shared.stinkyTracker = {
|
shared.stinkyTracker = {
|
||||||
stinkies = ReactiveValue.new({})
|
stinkies = ReactiveValue.new({}),
|
||||||
|
ignored = ReactiveValue.new({}),
|
||||||
}
|
}
|
||||||
|
|
||||||
local whoRegex = "([^ -/]+)-?%w*/(%w+)"
|
local whoRegex = "([^ -/]+)-?%w*/(%w+)"
|
||||||
---@param msg string
|
---@param msg string
|
||||||
---@return table<string, stinky>
|
---@return table<string, Stinky>
|
||||||
local function ParseWho(msg)
|
local function ParseWho(msg)
|
||||||
|
if Heimdall_Data.config.stinkyTracker.debug then
|
||||||
|
print(string.format("[%s] Parsing WHO message: '%s'", ModuleName, msg))
|
||||||
|
end
|
||||||
local stinkies = {}
|
local stinkies = {}
|
||||||
for name, class in string.gmatch(msg, whoRegex) do
|
for name, class in string.gmatch(msg, whoRegex) do
|
||||||
stinkies[name] = {
|
stinkies[name] = {
|
||||||
name = name,
|
name = name,
|
||||||
class = class,
|
class = class,
|
||||||
seenAt = GetTime(),
|
seenAt = GetTime(),
|
||||||
hostile = true
|
hostile = true,
|
||||||
}
|
}
|
||||||
|
if Heimdall_Data.config.stinkyTracker.debug then
|
||||||
|
print(
|
||||||
|
string.format(
|
||||||
|
"[%s] Found hostile player: %s (%s) at %s",
|
||||||
|
ModuleName,
|
||||||
|
name,
|
||||||
|
class,
|
||||||
|
date("%H:%M:%S", time())
|
||||||
|
)
|
||||||
|
)
|
||||||
|
shared.dump(stinkies)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
return stinkies
|
return stinkies
|
||||||
end
|
end
|
||||||
|
|
||||||
local seeRegex = "I see %((%w+)%) ([^ -/]+)-?%w*/(%w+)"
|
local seeRegex = "I see %((%w+)%) ([^ -/]+)-?%w*/(%w+)"
|
||||||
---@param msg string
|
---@param msg string
|
||||||
---@return table<string, stinky>
|
---@return table<string, Stinky>
|
||||||
local function ParseSee(msg)
|
local function ParseSee(msg)
|
||||||
|
if Heimdall_Data.config.stinkyTracker.debug then
|
||||||
|
print(string.format("[%s] Parsing SEE message: '%s'", ModuleName, msg))
|
||||||
|
end
|
||||||
local stinkies = {}
|
local stinkies = {}
|
||||||
local aggression, name, class = string.match(msg, seeRegex)
|
local aggression, name, class = string.match(msg, seeRegex)
|
||||||
if not name or not class then
|
if not name or not class then
|
||||||
|
if Heimdall_Data.config.stinkyTracker.debug then
|
||||||
|
print(string.format("[%s] Error: Invalid SEE message format", ModuleName))
|
||||||
|
end
|
||||||
return stinkies
|
return stinkies
|
||||||
end
|
end
|
||||||
local stinky = {
|
local stinky = {
|
||||||
name = name,
|
name = name,
|
||||||
class = class,
|
class = class,
|
||||||
seenAt = GetTime(),
|
seenAt = GetTime(),
|
||||||
hostile = aggression == "Hostile"
|
hostile = aggression == "hostile",
|
||||||
}
|
}
|
||||||
stinkies[name] = stinky
|
stinkies[name] = stinky
|
||||||
|
if Heimdall_Data.config.stinkyTracker.debug then
|
||||||
|
print(
|
||||||
|
string.format(
|
||||||
|
"[%s] Found stinky in SEE: %s (%s) - %s at %s",
|
||||||
|
ModuleName,
|
||||||
|
name,
|
||||||
|
class,
|
||||||
|
aggression,
|
||||||
|
date("%H:%M:%S", time())
|
||||||
|
)
|
||||||
|
)
|
||||||
|
shared.dump(stinkies)
|
||||||
|
end
|
||||||
return stinkies
|
return stinkies
|
||||||
end
|
end
|
||||||
local arrivedRegex = "([^ -/]+)-?%w* of class (%w+)"
|
|
||||||
local arrivedRegexAlt = "([^ -/]+)-?%w* %(!!!!%) of class (%w+)"
|
local arrivedRegex = "([^ -/]+)-?%w*; c:([^;]+)"
|
||||||
|
local arrivedRegexAlt = "([^ -/]+)-?%w*%(!!!!%); c:([^;]+)"
|
||||||
---@param msg string
|
---@param msg string
|
||||||
---@return table<string, stinky>
|
---@return table<string, Stinky>
|
||||||
local function ParseArrived(msg)
|
local function ParseArrived(msg)
|
||||||
|
if Heimdall_Data.config.stinkyTracker.debug then
|
||||||
|
print(string.format("%s: Parsing arrived message: %s", ModuleName, msg))
|
||||||
|
end
|
||||||
local stinkies = {}
|
local stinkies = {}
|
||||||
local name, class = string.match(msg, arrivedRegex)
|
local name, class = string.match(msg, arrivedRegex)
|
||||||
if not name or not class then
|
if not name or not class then
|
||||||
name, class = string.match(msg, arrivedRegexAlt)
|
name, class = string.match(msg, arrivedRegexAlt)
|
||||||
end
|
end
|
||||||
if not name or not class then
|
if not name or not class then
|
||||||
|
if Heimdall_Data.config.stinkyTracker.debug then
|
||||||
|
print(string.format("%s: No valid stinky found in arrived message", ModuleName))
|
||||||
|
end
|
||||||
return stinkies
|
return stinkies
|
||||||
end
|
end
|
||||||
local stinky = {
|
local stinky = {
|
||||||
name = name,
|
name = name,
|
||||||
class = class,
|
class = class,
|
||||||
seenAt = GetTime(),
|
seenAt = GetTime(),
|
||||||
hostile = true
|
hostile = true,
|
||||||
}
|
}
|
||||||
stinkies[name] = stinky
|
stinkies[name] = stinky
|
||||||
|
if Heimdall_Data.config.stinkyTracker.debug then
|
||||||
|
print(string.format("%s: Found stinky in arrived: %s/%s", ModuleName, name, class))
|
||||||
|
shared.dump(stinkies)
|
||||||
|
end
|
||||||
return stinkies
|
return stinkies
|
||||||
end
|
end
|
||||||
|
|
||||||
local frame = CreateFrame("Frame")
|
local frame = CreateFrame("Frame")
|
||||||
frame:RegisterEvent("CHAT_MSG_CHANNEL")
|
frame:RegisterEvent("CHAT_MSG_CHANNEL")
|
||||||
frame:SetScript("OnEvent", function(self, event, msg, sender, ...)
|
frame:SetScript("OnEvent", function(self, event, msg, sender, ...)
|
||||||
if not Heimdall_Data.config.stinkyTracker.enabled then return end
|
--if Heimdall_Data.config.stinkyTracker.debug then
|
||||||
|
-- print(string.format("[%s] Event received: %s from %s", ModuleName, event, sender))
|
||||||
|
--end
|
||||||
|
if not Heimdall_Data.config.stinkyTracker.enabled then
|
||||||
|
--if Heimdall_Data.config.stinkyTracker.debug then
|
||||||
|
-- print(string.format("[%s] Module disabled, ignoring event", ModuleName))
|
||||||
|
--end
|
||||||
|
return
|
||||||
|
end
|
||||||
local channelId = select(6, ...)
|
local channelId = select(6, ...)
|
||||||
local _, channelname = GetChannelName(channelId)
|
local _, channelname = GetChannelName(channelId)
|
||||||
if channelname ~= Heimdall_Data.config.stinkyTracker.masterChannel then return end
|
local ok = false
|
||||||
|
for _, channel in pairs(Heimdall_Data.config.stinkyTracker.channels) do
|
||||||
if string.find(msg, "^who:") then
|
if channel == channelname then
|
||||||
local whoStinkies = ParseWho(msg)
|
ok = true
|
||||||
for name, stinky in pairs(whoStinkies) do
|
break
|
||||||
if stinky.hostile then
|
|
||||||
shared.stinkyTracker.stinkies[name] = stinky
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
if not ok then
|
||||||
|
if Heimdall_Data.config.stinkyTracker.debug then
|
||||||
|
print(string.format("[%s] Ignoring message from non-master channel: %s", ModuleName, channelname))
|
||||||
|
end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
if Heimdall_Data.config.stinkyTracker.debug then
|
||||||
|
print(string.format("[%s] Processing message from master channel: %s", ModuleName, sender))
|
||||||
|
shared.dump(Heimdall_Data.config.stinkyTracker)
|
||||||
|
end
|
||||||
|
|
||||||
|
local stinkies = {}
|
||||||
|
if string.find(msg, "^who:") then
|
||||||
|
if Heimdall_Data.config.stinkyTracker.debug then
|
||||||
|
print(string.format("[%s] Processing WHO message from %s", ModuleName, sender))
|
||||||
|
end
|
||||||
|
local whoStinkies = ParseWho(msg)
|
||||||
|
if Heimdall_Data.config.stinkyTracker.debug then
|
||||||
|
print(string.format("[%s] Found stinkies in WHO message", ModuleName))
|
||||||
|
shared.dump(whoStinkies)
|
||||||
|
end
|
||||||
|
for name, stinky in pairs(whoStinkies) do
|
||||||
|
stinkies[name] = stinky
|
||||||
|
end
|
||||||
end
|
end
|
||||||
if string.find(msg, "^I see") then
|
if string.find(msg, "^I see") then
|
||||||
|
if Heimdall_Data.config.stinkyTracker.debug then
|
||||||
|
print(string.format("[%s] Processing SEE message from %s", ModuleName, sender))
|
||||||
|
end
|
||||||
local seeStinkies = ParseSee(msg)
|
local seeStinkies = ParseSee(msg)
|
||||||
|
if Heimdall_Data.config.stinkyTracker.debug then
|
||||||
|
print(string.format("[%s] Found stinkies in SEE message", ModuleName))
|
||||||
|
shared.dump(seeStinkies)
|
||||||
|
end
|
||||||
for name, stinky in pairs(seeStinkies) do
|
for name, stinky in pairs(seeStinkies) do
|
||||||
if stinky.hostile then
|
stinkies[name] = stinky
|
||||||
shared.stinkyTracker.stinkies[name] = stinky
|
|
||||||
end
|
|
||||||
if not stinky.hostile then
|
|
||||||
shared.stinkyTracker.stinkies[name] = nil
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
if string.find(msg, "arrived to") or string.find(msg, "moved to") then
|
||||||
|
if Heimdall_Data.config.stinkyTracker.debug then
|
||||||
|
print(string.format("[%s] Processing ARRIVED message from %s", ModuleName, sender))
|
||||||
end
|
end
|
||||||
if string.find(msg, " and guild ") then
|
|
||||||
local arrivedStinkies = ParseArrived(msg)
|
local arrivedStinkies = ParseArrived(msg)
|
||||||
|
if Heimdall_Data.config.stinkyTracker.debug then
|
||||||
|
print(string.format("[%s] Found stinkies in ARRIVED message", ModuleName))
|
||||||
|
shared.dump(arrivedStinkies)
|
||||||
|
end
|
||||||
for name, stinky in pairs(arrivedStinkies) do
|
for name, stinky in pairs(arrivedStinkies) do
|
||||||
|
stinkies[name] = stinky
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
for name, stinky in pairs(stinkies) do
|
||||||
|
if shared.stinkyTracker.ignored[name] then
|
||||||
|
if Heimdall_Data.config.stinkyTracker.debug then
|
||||||
|
print(string.format("[%s] Ignoring stinky: %s (%s)", ModuleName, name, stinky.class))
|
||||||
|
end
|
||||||
|
shared.stinkyTracker.ignored[name] = nil
|
||||||
|
else
|
||||||
shared.stinkyTracker.stinkies[name] = stinky
|
shared.stinkyTracker.stinkies[name] = stinky
|
||||||
|
if Heimdall_Data.config.stinkyTracker.debug then
|
||||||
|
print(string.format("[%s] Added stinky: %s (%s)", ModuleName, name, stinky.class))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
for name, stinky in pairs(shared.stinkyTracker.stinkies) do
|
end
|
||||||
if Heimdall_Data.config.agents[name] then
|
|
||||||
|
-- Log total stinky count after processing
|
||||||
|
if Heimdall_Data.config.stinkyTracker.debug then
|
||||||
|
local count = 0
|
||||||
|
for _ in pairs(shared.stinkyTracker.stinkies:get()) do
|
||||||
|
count = count + 1
|
||||||
|
end
|
||||||
|
print(string.format("[%s] Current total stinkies tracked: %d", ModuleName, count))
|
||||||
|
end
|
||||||
|
|
||||||
|
shared.StinkyTracker.ForEach(function(name, stinky)
|
||||||
|
if shared.AgentTracker.IsAgent(name) then
|
||||||
shared.stinkyTracker.stinkies[name] = nil
|
shared.stinkyTracker.stinkies[name] = nil
|
||||||
|
if Heimdall_Data.config.stinkyTracker.debug then
|
||||||
|
print(string.format("[%s] Removed agent from stinkies: %s", ModuleName, name))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
|
end)
|
||||||
|
|
||||||
print("Heimdall - StinkyTracker loaded")
|
local targetFrame = CreateFrame("Frame")
|
||||||
end
|
targetFrame:RegisterEvent("UNIT_TARGET")
|
||||||
|
targetFrame:SetScript("OnEvent", function(self, event, unit)
|
||||||
|
if Heimdall_Data.config.stinkyTracker.debug then
|
||||||
|
print(string.format("[%s] Event received: %s for unit: %s", ModuleName, event, unit or "target"))
|
||||||
|
end
|
||||||
|
unit = "target"
|
||||||
|
|
||||||
|
if not Heimdall_Data.config.stinkyTracker.enabled then
|
||||||
|
if Heimdall_Data.config.stinkyTracker.debug then
|
||||||
|
print(string.format("[%s] Module disabled, ignoring event", ModuleName))
|
||||||
|
end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local name = UnitName(unit)
|
||||||
|
if not UnitIsPlayer(unit) then
|
||||||
|
if Heimdall_Data.config.stinkyTracker.debug then
|
||||||
|
print(string.format("[%s] Target %s is not a player, nothing to do", ModuleName, name))
|
||||||
|
end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local enemy = UnitCanAttack("player", unit)
|
||||||
|
if enemy then
|
||||||
|
if Heimdall_Data.config.stinkyTracker.debug then
|
||||||
|
print(string.format("[%s] Target %s is enemy - tracking as stinky", ModuleName, name))
|
||||||
|
end
|
||||||
|
shared.stinkyTracker.stinkies[name] = {
|
||||||
|
name = name,
|
||||||
|
class = UnitClass(unit),
|
||||||
|
seenAt = GetTime(),
|
||||||
|
hostile = true,
|
||||||
|
}
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
if not shared.stinkyTracker.stinkies[name] then
|
||||||
|
if Heimdall_Data.config.stinkyTracker.debug then
|
||||||
|
print(string.format("[%s] Target %s is friendly and not stinky, nothing to do", ModuleName, name))
|
||||||
|
end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
if Heimdall_Data.config.stinkyTracker.debug then
|
||||||
|
print(string.format("[%s] Target %s is friendly and stinky - removing from stinkies", ModuleName, name))
|
||||||
|
end
|
||||||
|
shared.stinkyTracker.stinkies[name] = nil
|
||||||
|
end)
|
||||||
|
|
||||||
|
if Heimdall_Data.config.stinkyTracker.debug then print(string.format("[%s] Module initialized", ModuleName)) end
|
||||||
|
print(string.format("[%s] Module initialized", ModuleName))
|
||||||
|
end,
|
||||||
|
}
|
||||||
|
@@ -1,10 +1,25 @@
|
|||||||
local addonname, shared = ...
|
local _, shared = ...
|
||||||
---@cast shared HeimdallShared
|
---@cast shared HeimdallShared
|
||||||
---@cast addonname string
|
local ModuleName = "Whoer"
|
||||||
|
|
||||||
---@diagnostic disable-next-line: missing-fields
|
---@class HeimdallWhoConfig
|
||||||
shared.Whoer = {}
|
---@field enabled boolean
|
||||||
function shared.Whoer.Init()
|
---@field debug boolean
|
||||||
|
---@field ignored table<string, boolean>
|
||||||
|
---@field channels string[]
|
||||||
|
---@field ttl number
|
||||||
|
---@field doWhisper boolean
|
||||||
|
---@field zoneNotifyFor table<string, boolean>
|
||||||
|
---@field queries string
|
||||||
|
|
||||||
|
---@class HeimdallWhoData
|
||||||
|
---@field updateTicker Timer?
|
||||||
|
---@field whoTicker Timer?
|
||||||
|
|
||||||
|
local whoWaiting = false
|
||||||
|
---@class Whoer
|
||||||
|
shared.Whoer = {
|
||||||
|
Init = function()
|
||||||
if not Heimdall_Data.who then Heimdall_Data.who = {} end
|
if not Heimdall_Data.who then Heimdall_Data.who = {} end
|
||||||
if not Heimdall_Data.who.data then Heimdall_Data.who.data = {} end
|
if not Heimdall_Data.who.data then Heimdall_Data.who.data = {} end
|
||||||
|
|
||||||
@@ -31,7 +46,7 @@ function shared.Whoer.Init()
|
|||||||
---@return Player
|
---@return Player
|
||||||
new = function(name, guild, race, class, zone)
|
new = function(name, guild, race, class, zone)
|
||||||
local self = setmetatable({}, {
|
local self = setmetatable({}, {
|
||||||
__index = Player
|
__index = Player,
|
||||||
})
|
})
|
||||||
self.name = name
|
self.name = name
|
||||||
self.guild = guild
|
self.guild = guild
|
||||||
@@ -46,31 +61,17 @@ function shared.Whoer.Init()
|
|||||||
end,
|
end,
|
||||||
---@return string
|
---@return string
|
||||||
ToString = function(self)
|
ToString = function(self)
|
||||||
local out = string.format("%s %s %s\nFirst: %s Last: %s Seen: %3d",
|
local out = string.format(
|
||||||
|
"%s %s %s\nFirst: %s Last: %s Seen: %3d",
|
||||||
shared.padString(self.name, 16, true),
|
shared.padString(self.name, 16, true),
|
||||||
shared.padString(self.guild, 26, false),
|
shared.padString(self.guild, 26, false),
|
||||||
shared.padString(self.zone, 26, false),
|
shared.padString(self.zone, 26, false),
|
||||||
shared.padString(self.firstSeen, 10, true),
|
shared.padString(self.firstSeen, 10, true),
|
||||||
shared.padString(self.lastSeen, 10, true),
|
shared.padString(self.lastSeen, 10, true),
|
||||||
self.seenCount)
|
self.seenCount
|
||||||
|
)
|
||||||
return string.format("|cFF%s%s|r", shared.classColors[self.class], out)
|
return string.format("|cFF%s%s|r", shared.classColors[self.class], out)
|
||||||
end,
|
end,
|
||||||
---@return string
|
|
||||||
NotifyMessage = function(self)
|
|
||||||
local text = string.format(
|
|
||||||
"%s %s of class %s, race %s (%s) and guild %s in %s, first seen: %s, last seen: %s, times seen: %d",
|
|
||||||
self.name,
|
|
||||||
self.stinky and "(!!!!)" or "",
|
|
||||||
self.class,
|
|
||||||
self.race,
|
|
||||||
tostring(shared.raceMap[self.race]),
|
|
||||||
self.guild,
|
|
||||||
self.zone,
|
|
||||||
self.firstSeen,
|
|
||||||
self.lastSeen,
|
|
||||||
self.seenCount)
|
|
||||||
return text
|
|
||||||
end
|
|
||||||
}
|
}
|
||||||
|
|
||||||
---@class WHOQuery
|
---@class WHOQuery
|
||||||
@@ -82,83 +83,273 @@ function shared.Whoer.Init()
|
|||||||
---@return WHOQuery
|
---@return WHOQuery
|
||||||
new = function(query, filters)
|
new = function(query, filters)
|
||||||
local self = setmetatable({}, {
|
local self = setmetatable({}, {
|
||||||
__index = WHOQuery
|
__index = WHOQuery,
|
||||||
})
|
})
|
||||||
self.query = query
|
self.query = query
|
||||||
self.filters = filters
|
self.filters = filters
|
||||||
return self
|
return self
|
||||||
end
|
end,
|
||||||
}
|
}
|
||||||
|
|
||||||
---@alias WHOFilter fun(name: string, guild: string, level: number, race: string, class: string, zone: string): boolean
|
---@class WHOFilter
|
||||||
|
---@field Run fun(name: string, guild: string, level: number, race: string, class: string, zone: string): boolean
|
||||||
|
---@field key string
|
||||||
---@type WHOFilter
|
---@type WHOFilter
|
||||||
local NotSiegeOfOrgrimmarFilter = function(name, guild, level, race, class, zone)
|
local NotSiegeOfOrgrimmarFilter = {
|
||||||
if not zone then
|
Run = function(name, guild, level, race, class, zone)
|
||||||
return false
|
if not zone then return false end
|
||||||
end
|
|
||||||
return zone ~= "Siege of Orgrimmar"
|
return zone ~= "Siege of Orgrimmar"
|
||||||
end
|
end,
|
||||||
|
key = "notsoo",
|
||||||
|
}
|
||||||
---@type WHOFilter
|
---@type WHOFilter
|
||||||
local AllianceFilter = function(name, guild, level, race, class, zone)
|
local AllianceFilter = {
|
||||||
|
Run = function(name, guild, level, race, class, zone)
|
||||||
if not race then return false end
|
if not race then return false end
|
||||||
if not shared.raceMap[race] then return false end
|
if not shared.raceMap[race] then return false end
|
||||||
return shared.raceMap[race] == "Alliance"
|
return shared.raceMap[race] == "Alliance"
|
||||||
|
end,
|
||||||
|
key = "ally",
|
||||||
|
}
|
||||||
|
|
||||||
|
---@class WhoQueryService
|
||||||
|
---@field queries WHOQuery[]
|
||||||
|
---@field filters WHOFilter[]
|
||||||
|
---@field getFilter fun(key: string): WHOFilter?
|
||||||
|
---@field WhoQueryToString fun(query: WHOQuery): string
|
||||||
|
---@field WhoQueryFromString fun(query: string): WHOQuery
|
||||||
|
---@field WhoQueriesToString fun(queries: WHOQuery[]): string
|
||||||
|
---@field WhoQueriesFromString fun(queries: string): WHOQuery[]
|
||||||
|
shared.WhoQueryService = {
|
||||||
|
queries = {},
|
||||||
|
filters = {
|
||||||
|
NotSiegeOfOrgrimmarFilter,
|
||||||
|
AllianceFilter,
|
||||||
|
},
|
||||||
|
---@param key string
|
||||||
|
---@return WHOFilter?
|
||||||
|
getFilter = function(key)
|
||||||
|
for _, filter in pairs(shared.WhoQueryService.filters) do
|
||||||
|
if filter.key == key then return filter end
|
||||||
|
end
|
||||||
|
return nil
|
||||||
|
end,
|
||||||
|
---@param query WHOQuery
|
||||||
|
---@return string
|
||||||
|
WhoQueryToString = function(query)
|
||||||
|
local ret = ""
|
||||||
|
ret = ret .. query.query
|
||||||
|
ret = ret .. ";"
|
||||||
|
for _, filter in pairs(query.filters) do
|
||||||
|
ret = ret .. filter.key .. ";"
|
||||||
|
end
|
||||||
|
return ret
|
||||||
|
end,
|
||||||
|
---@param queries WHOQuery[]
|
||||||
|
---@return string
|
||||||
|
WhoQueriesToString = function(queries)
|
||||||
|
local ret = ""
|
||||||
|
for _, query in pairs(queries) do
|
||||||
|
ret = ret .. shared.WhoQueryService.WhoQueryToString(query) .. "\n"
|
||||||
|
end
|
||||||
|
return ret
|
||||||
|
end,
|
||||||
|
---@param query string
|
||||||
|
---@return WHOQuery
|
||||||
|
WhoQueryFromString = function(query)
|
||||||
|
local queryParts = shared.Split(query, ";")
|
||||||
|
local filters = {}
|
||||||
|
for _, filterKey in pairs(queryParts) do
|
||||||
|
local filter = shared.WhoQueryService.getFilter(filterKey)
|
||||||
|
if not filter then
|
||||||
|
if Heimdall_Data.config.who.debug then
|
||||||
|
print(string.format("[%s] Filter %s not found", ModuleName, filterKey))
|
||||||
|
end
|
||||||
|
else
|
||||||
|
if Heimdall_Data.config.who.debug then
|
||||||
|
print(string.format("[%s] Filter %s found", ModuleName, filterKey))
|
||||||
end
|
end
|
||||||
|
|
||||||
local whoQueryIdx = 1
|
table.insert(filters, filter)
|
||||||
---@type WHOQuery[]
|
end
|
||||||
local whoQueries = {
|
end
|
||||||
WHOQuery.new("g-\"БеспредеЛ\"", {}),
|
if Heimdall_Data.config.who.debug then
|
||||||
--WHOQuery.new("g-\"Dovahkin\"", {}),
|
print(string.format("[%s] WHO query: %s with %d filters", ModuleName, queryParts[1], #filters))
|
||||||
WHOQuery.new(
|
end
|
||||||
"z-\"Orgrimmar\" z-\"Durotar\" z-\"Valley of Trials\" r-\"Human\" r-\"Dwarf\" r-\"Night Elf\"",
|
shared.dump(filters)
|
||||||
{ NotSiegeOfOrgrimmarFilter, AllianceFilter }),
|
return WHOQuery.new(queryParts[1], filters)
|
||||||
WHOQuery.new(
|
end,
|
||||||
"z-\"Orgrimmar\" z-\"Durotar\" z-\"Valley of Trials\" r-\"Gnome\" r-\"Draenei\" r-\"Worgen\"",
|
---@param queryStr string
|
||||||
{ NotSiegeOfOrgrimmarFilter, AllianceFilter }),
|
---@return WHOQuery[]
|
||||||
WHOQuery.new(
|
WhoQueriesFromString = function(queryStr)
|
||||||
"z-\"Orgrimmar\" z-\"Durotar\" z-\"Valley of Trials\" r-\"Kul Tiran\" r-\"Dark Iron Dwarf\" r-\"Void Elf\"",
|
local queries = shared.Split(queryStr, "\n")
|
||||||
{ NotSiegeOfOrgrimmarFilter, AllianceFilter }),
|
local ret = {}
|
||||||
WHOQuery.new(
|
for _, query in pairs(queries) do
|
||||||
"z-\"Orgrimmar\" z-\"Durotar\" z-\"Valley of Trials\" r-\"Lightforged Draenei\" r-\"Mechagnome\"",
|
table.insert(ret, shared.WhoQueryService.WhoQueryFromString(query))
|
||||||
{ NotSiegeOfOrgrimmarFilter, AllianceFilter }),
|
end
|
||||||
WHOQuery.new("Kekv Firobot Tomoki", {})
|
return ret
|
||||||
|
end,
|
||||||
}
|
}
|
||||||
local ttl = #whoQueries * 2
|
shared.WhoQueryService.queries = shared.WhoQueryService.WhoQueriesFromString(Heimdall_Data.config.who.queries)
|
||||||
|
|
||||||
|
---@param inputZone string
|
||||||
|
---@return boolean
|
||||||
|
shared.Whoer.ShouldNotifyForZone = shared.Memoize(function(inputZone)
|
||||||
|
if not Heimdall_Data.config.who.debug then
|
||||||
|
print(string.format("[%s] ShouldNotifyForZone %s", ModuleName, inputZone))
|
||||||
|
end
|
||||||
|
for zone, _ in pairs(Heimdall_Data.config.who.zoneNotifyFor) do
|
||||||
|
if Heimdall_Data.config.who.debug then
|
||||||
|
print(string.format("[%s] Checking zone %s", ModuleName, zone))
|
||||||
|
end
|
||||||
|
if zone == "*" then return true end
|
||||||
|
if string.find(inputZone, zone) then
|
||||||
|
if not Heimdall_Data.config.who.debug then
|
||||||
|
print(
|
||||||
|
string.format(
|
||||||
|
"[%s] ShouldNotifyForZone %s is true thanks to %s",
|
||||||
|
ModuleName,
|
||||||
|
inputZone,
|
||||||
|
zone
|
||||||
|
)
|
||||||
|
)
|
||||||
|
end
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if not Heimdall_Data.config.who.debug then
|
||||||
|
print(string.format("[%s] ShouldNotifyForZone %s is false", ModuleName, inputZone))
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
end)
|
||||||
|
|
||||||
|
-----@type WHOQuery[]
|
||||||
|
--local whoQueries = {
|
||||||
|
-- WHOQuery.new("g-\"БеспредеЛ\"", {}),
|
||||||
|
-- WHOQuery.new("g-\"ЗАО бещёки\"", {}),
|
||||||
|
-- WHOQuery.new("g-\"КОНИЛИНГУСЫ\"", {}),
|
||||||
|
-- --WHOQuery.new("g-\"Dovahkin\"", {}),
|
||||||
|
-- WHOQuery.new(
|
||||||
|
-- "z-\"Orgrimmar\" z-\"Durotar\" z-\"Valley of Trials\" r-\"Human\" r-\"Dwarf\" r-\"Night Elf\"",
|
||||||
|
-- { NotSiegeOfOrgrimmarFilter, AllianceFilter }),
|
||||||
|
-- WHOQuery.new(
|
||||||
|
-- "z-\"Orgrimmar\" z-\"Durotar\" z-\"Valley of Trials\" r-\"Gnome\" r-\"Draenei\" r-\"Worgen\"",
|
||||||
|
-- { NotSiegeOfOrgrimmarFilter, AllianceFilter }),
|
||||||
|
-- WHOQuery.new(
|
||||||
|
-- "z-\"Orgrimmar\" z-\"Durotar\" z-\"Valley of Trials\" r-\"Kul Tiran\" r-\"Dark Iron Dwarf\" r-\"Void Elf\"",
|
||||||
|
-- { NotSiegeOfOrgrimmarFilter, AllianceFilter }),
|
||||||
|
-- WHOQuery.new(
|
||||||
|
-- "z-\"Orgrimmar\" z-\"Durotar\" z-\"Valley of Trials\" r-\"Lightforged Draenei\" r-\"Mechagnome\"",
|
||||||
|
-- { NotSiegeOfOrgrimmarFilter, AllianceFilter }),
|
||||||
|
-- WHOQuery.new("Kekv Firobot Tomoki Mld Alltros", {})
|
||||||
|
--}
|
||||||
|
local whoQueryIdx = 1
|
||||||
---@type WHOQuery?
|
---@type WHOQuery?
|
||||||
local lastQuery = nil
|
local lastQuery = nil
|
||||||
|
|
||||||
---@param player Player
|
---@param player Player
|
||||||
---@return string?
|
---@return string?
|
||||||
local function Notify(player)
|
local function Notify(player)
|
||||||
if not Heimdall_Data.config.who.enabled then return end
|
if Heimdall_Data.config.who.debug then
|
||||||
if not player then return string.format("Cannot notify for nil player %s", tostring(player)) end
|
print(string.format("[%s] Processing notification for player: %s", ModuleName, player.name))
|
||||||
if not Heimdall_Data.config.who.zoneNotifyFor[player.zone] then
|
print(
|
||||||
return string.format("Not notifying for zone %s",
|
string.format(
|
||||||
tostring(player.zone))
|
"[%s] Player details - Guild: %s, Race: %s, Class: %s, Zone: %s",
|
||||||
|
ModuleName,
|
||||||
|
player.guild,
|
||||||
|
player.race,
|
||||||
|
player.class,
|
||||||
|
player.zone
|
||||||
|
)
|
||||||
|
)
|
||||||
|
print(
|
||||||
|
string.format(
|
||||||
|
"[%s] Player history - First seen: %s, Last seen: %s, Seen count: %d",
|
||||||
|
ModuleName,
|
||||||
|
player.firstSeen,
|
||||||
|
player.lastSeen,
|
||||||
|
player.seenCount
|
||||||
|
)
|
||||||
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
local text = player:NotifyMessage()
|
if not Heimdall_Data.config.who.enabled then
|
||||||
---@type Message
|
if Heimdall_Data.config.who.debug then
|
||||||
local msg = {
|
print(string.format("[%s] Module disabled, skipping notification", ModuleName))
|
||||||
channel = "CHANNEL",
|
end
|
||||||
data = Heimdall_Data.config.who.notifyChannel,
|
return
|
||||||
message = text
|
end
|
||||||
}
|
|
||||||
table.insert(shared.messenger.queue, msg)
|
|
||||||
|
|
||||||
if Heimdall_Data.config.who.doWhisper then
|
if not player then
|
||||||
for _, name in pairs(Heimdall_Data.config.whisperNotify) do
|
if Heimdall_Data.config.who.debug then
|
||||||
|
print(string.format("[%s] Error: Cannot notify for nil player", ModuleName))
|
||||||
|
end
|
||||||
|
return string.format("Cannot notify for nil player %s", tostring(player))
|
||||||
|
end
|
||||||
|
|
||||||
|
if not shared.Whoer.ShouldNotifyForZone(player.zone) then
|
||||||
|
--if not Heimdall_Data.config.who.zoneNotifyFor[player.zone] then
|
||||||
|
if Heimdall_Data.config.who.debug then
|
||||||
|
print(
|
||||||
|
string.format(
|
||||||
|
"[%s] Skipping notification - Zone '%s' not in notify list",
|
||||||
|
ModuleName,
|
||||||
|
player.zone
|
||||||
|
)
|
||||||
|
)
|
||||||
|
end
|
||||||
|
return string.format("Not notifying for zone %s", tostring(player.zone))
|
||||||
|
end
|
||||||
|
|
||||||
|
for _, channel in pairs(Heimdall_Data.config.who.channels) do
|
||||||
|
local locale = shared.GetLocaleForChannel(channel)
|
||||||
|
local text = string.format(
|
||||||
|
shared._L("whoerNew", locale),
|
||||||
|
player.name,
|
||||||
|
player.stinky and "(!!!!)" or "",
|
||||||
|
shared._L(player.class, locale),
|
||||||
|
--shared._L(player.race, locale),
|
||||||
|
shared._L(shared.raceMap[player.race] or "unknown", locale),
|
||||||
|
player.guild,
|
||||||
|
shared._L(player.zone, locale)
|
||||||
|
)
|
||||||
---@type Message
|
---@type Message
|
||||||
local msg = {
|
local msg = {
|
||||||
channel = "WHISPER",
|
channel = "C",
|
||||||
data = name,
|
data = channel,
|
||||||
message = text
|
message = text,
|
||||||
}
|
}
|
||||||
table.insert(shared.messenger.queue, msg)
|
if Heimdall_Data.config.who.debug then
|
||||||
|
print(string.format("[%s] Queuing channel notification", ModuleName))
|
||||||
|
shared.dump(msg)
|
||||||
|
end
|
||||||
|
if Heimdall_Data.config.networkMessenger.enabled then
|
||||||
|
shared.NetworkMessenger.Enqueue(msg)
|
||||||
|
elseif Heimdall_Data.config.messenger.enabled then
|
||||||
|
shared.Messenger.Enqueue(msg)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--if Heimdall_Data.config.who.doWhisper then
|
||||||
|
-- if Heimdall_Data.config.who.debug then
|
||||||
|
-- print(string.format("[%s] Processing whisper notifications for %d recipients", ModuleName,
|
||||||
|
-- #Heimdall_Data.config.whisperNotify))
|
||||||
|
-- end
|
||||||
|
-- for _, name in pairs(Heimdall_Data.config.whisperNotify) do
|
||||||
|
-- ---@type Message
|
||||||
|
-- local msg = {
|
||||||
|
-- channel = "W",
|
||||||
|
-- data = name,
|
||||||
|
-- message = text
|
||||||
|
-- }
|
||||||
|
-- if Heimdall_Data.config.who.debug then
|
||||||
|
-- print(string.format("[%s] Queuing whisper to %s", ModuleName, name))
|
||||||
|
-- end
|
||||||
|
-- --table.insert(shared.messenger.queue, msg)
|
||||||
|
-- table.insert(shared.networkMessenger.queue, msg)
|
||||||
|
-- end
|
||||||
|
--end
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
---@param player Player
|
---@param player Player
|
||||||
@@ -167,37 +358,53 @@ function shared.Whoer.Init()
|
|||||||
local function NotifyZoneChanged(player, zone)
|
local function NotifyZoneChanged(player, zone)
|
||||||
if not Heimdall_Data.config.who.enabled then return end
|
if not Heimdall_Data.config.who.enabled then return end
|
||||||
if not player then return string.format("Cannot notify for nil player %s", tostring(player)) end
|
if not player then return string.format("Cannot notify for nil player %s", tostring(player)) end
|
||||||
if not Heimdall_Data.config.who.zoneNotifyFor[zone]
|
--if not Heimdall_Data.config.who.zoneNotifyFor[zone]
|
||||||
and not Heimdall_Data.config.who.zoneNotifyFor[player.zone] then
|
-- and not Heimdall_Data.config.who.zoneNotifyFor[player.zone] then
|
||||||
|
if not shared.Whoer.ShouldNotifyForZone(zone) and not shared.Whoer.ShouldNotifyForZone(player.zone) then
|
||||||
return string.format("Not notifying for zones %s and %s", tostring(zone), tostring(player.zone))
|
return string.format("Not notifying for zones %s and %s", tostring(zone), tostring(player.zone))
|
||||||
end
|
end
|
||||||
local text = string.format("%s of class %s (%s - %s) and guild %s moved to %s",
|
for _, channel in pairs(Heimdall_Data.config.who.channels) do
|
||||||
|
local locale = shared.GetLocaleForChannel(channel)
|
||||||
|
local text = string.format(
|
||||||
|
shared._L("whoerMoved", locale),
|
||||||
player.name,
|
player.name,
|
||||||
player.class,
|
player.stinky and "(!!!!)" or "",
|
||||||
player.race,
|
shared._L(player.class, locale),
|
||||||
shared.raceMap[player.race] or "Unknown",
|
--shared._L(player.race, locale),
|
||||||
|
shared._L(shared.raceMap[player.race] or "unknown", locale),
|
||||||
player.guild,
|
player.guild,
|
||||||
zone)
|
shared._L(zone, locale)
|
||||||
|
)
|
||||||
|
|
||||||
---@type Message
|
---@type Message
|
||||||
local msg = {
|
local msg = {
|
||||||
channel = "CHANNEL",
|
channel = "C",
|
||||||
data = Heimdall_Data.config.who.notifyChannel,
|
data = channel,
|
||||||
message = text
|
message = text,
|
||||||
}
|
}
|
||||||
table.insert(shared.messenger.queue, msg)
|
if Heimdall_Data.config.who.debug then
|
||||||
|
print(string.format("[%s] Queuing channel notification", ModuleName))
|
||||||
|
shared.dump(msg)
|
||||||
|
end
|
||||||
|
if Heimdall_Data.config.networkMessenger.enabled then
|
||||||
|
shared.NetworkMessenger.Enqueue(msg)
|
||||||
|
elseif Heimdall_Data.config.messenger.enabled then
|
||||||
|
shared.Messenger.Enqueue(msg)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
if Heimdall_Data.config.who.doWhisper then
|
--if Heimdall_Data.config.who.doWhisper then
|
||||||
for _, name in pairs(Heimdall_Data.config.whisperNotify) do
|
-- for _, name in pairs(Heimdall_Data.config.whisperNotify) do
|
||||||
---@type Message
|
-- ---@type Message
|
||||||
local msg = {
|
-- local msg = {
|
||||||
channel = "WHISPER",
|
-- channel = "W",
|
||||||
data = name,
|
-- data = name,
|
||||||
message = text
|
-- message = text
|
||||||
}
|
-- }
|
||||||
table.insert(shared.messenger.queue, msg)
|
-- --table.insert(shared.messenger.queue, msg)
|
||||||
end
|
-- table.insert(shared.networkMessenger.queue, msg)
|
||||||
end
|
-- end
|
||||||
|
--end
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
@@ -206,36 +413,53 @@ function shared.Whoer.Init()
|
|||||||
local function NotifyGone(player)
|
local function NotifyGone(player)
|
||||||
if not Heimdall_Data.config.who.enabled then return end
|
if not Heimdall_Data.config.who.enabled then return end
|
||||||
if not player then return string.format("Cannot notify for nil player %s", tostring(player)) end
|
if not player then return string.format("Cannot notify for nil player %s", tostring(player)) end
|
||||||
if not Heimdall_Data.config.who.zoneNotifyFor[player.zone] then
|
--if not Heimdall_Data.config.who.zoneNotifyFor[player.zone] then
|
||||||
return string.format("Not notifying for zone %s",
|
if not shared.Whoer.ShouldNotifyForZone(player.zone) then
|
||||||
tostring(player.zone))
|
return string.format("Not notifying for zone %s", tostring(player.zone))
|
||||||
end
|
end
|
||||||
|
|
||||||
local text = string.format("%s of class %s and guild %s left %s",
|
for _, channel in pairs(Heimdall_Data.config.who.channels) do
|
||||||
|
local locale = shared.GetLocaleForChannel(channel)
|
||||||
|
local text = string.format(
|
||||||
|
shared._L("whoerGone", locale),
|
||||||
player.name,
|
player.name,
|
||||||
player.class,
|
player.stinky and "(!!!!)" or "",
|
||||||
|
shared._L(player.class, locale),
|
||||||
|
--shared._L(player.race, locale),
|
||||||
|
shared._L(shared.raceMap[player.race] or "unknown", locale),
|
||||||
player.guild,
|
player.guild,
|
||||||
player.zone)
|
shared._L(player.zone, locale)
|
||||||
|
)
|
||||||
|
|
||||||
---@type Message
|
---@type Message
|
||||||
local msg = {
|
local msg = {
|
||||||
channel = "CHANNEL",
|
channel = "C",
|
||||||
data = Heimdall_Data.config.who.notifyChannel,
|
data = channel,
|
||||||
message = text
|
message = text,
|
||||||
}
|
}
|
||||||
table.insert(shared.messenger.queue, msg)
|
if Heimdall_Data.config.who.debug then
|
||||||
|
print(string.format("[%s] Queuing channel notification", ModuleName))
|
||||||
|
shared.dump(msg)
|
||||||
|
end
|
||||||
|
if Heimdall_Data.config.networkMessenger.enabled then
|
||||||
|
shared.NetworkMessenger.Enqueue(msg)
|
||||||
|
elseif Heimdall_Data.config.messenger.enabled then
|
||||||
|
shared.Messenger.Enqueue(msg)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
if Heimdall_Data.config.who.doWhisper then
|
--if Heimdall_Data.config.who.doWhisper then
|
||||||
for _, name in pairs(Heimdall_Data.config.whisperNotify) do
|
-- for _, name in pairs(Heimdall_Data.config.whisperNotify) do
|
||||||
---@type Message
|
-- ---@type Message
|
||||||
local msg = {
|
-- local msg = {
|
||||||
channel = "WHISPER",
|
-- channel = "W",
|
||||||
data = name,
|
-- data = name,
|
||||||
message = text
|
-- message = text
|
||||||
}
|
-- }
|
||||||
table.insert(shared.messenger.queue, msg)
|
-- --table.insert(shared.messenger.queue, msg)
|
||||||
end
|
-- table.insert(shared.networkMessenger.queue, msg)
|
||||||
end
|
-- end
|
||||||
|
--end
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
@@ -243,60 +467,162 @@ function shared.Whoer.Init()
|
|||||||
local frame = CreateFrame("Frame")
|
local frame = CreateFrame("Frame")
|
||||||
frame:RegisterEvent("WHO_LIST_UPDATE")
|
frame:RegisterEvent("WHO_LIST_UPDATE")
|
||||||
frame:SetScript("OnEvent", function(self, event, ...)
|
frame:SetScript("OnEvent", function(self, event, ...)
|
||||||
if not Heimdall_Data.config.who.enabled then return end
|
if Heimdall_Data.config.who.debug then
|
||||||
---@type WHOQuery?
|
print(string.format("[%s] WHO list update received", ModuleName))
|
||||||
local query = lastQuery
|
print(
|
||||||
if not query then
|
string.format("[%s] Query index: %d/%d", ModuleName, whoQueryIdx, #shared.WhoQueryService.queries)
|
||||||
print("No query wtf?")
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
if not Heimdall_Data.config.who.enabled then
|
||||||
|
if Heimdall_Data.config.who.debug then
|
||||||
|
print(string.format("[%s] Module disabled, ignoring WHO update", ModuleName))
|
||||||
|
end
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
for i = 1, GetNumWhoResults() do
|
---@type WHOQuery?
|
||||||
local name, guild, level, race, class, zone = GetWhoInfo(i)
|
local query = lastQuery
|
||||||
local continue = false
|
if not query then
|
||||||
--print(name, guild, level, race, class, zone)
|
if Heimdall_Data.config.who.debug then
|
||||||
|
print(string.format("[%s] Error: No active WHO query found", ModuleName))
|
||||||
|
end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local results = GetNumWhoResults()
|
||||||
|
if Heimdall_Data.config.who.debug then
|
||||||
|
print(string.format("[%s] Processing %d WHO results for query: %s", ModuleName, results, query.query))
|
||||||
|
end
|
||||||
|
|
||||||
|
for i = 1, results do
|
||||||
|
local name, guild, level, race, class, zone = GetWhoInfo(i)
|
||||||
|
if Heimdall_Data.config.who.debug then
|
||||||
|
print(
|
||||||
|
string.format(
|
||||||
|
"[%s] Processing result %d/%d: %s/%s/%s",
|
||||||
|
ModuleName,
|
||||||
|
i,
|
||||||
|
results,
|
||||||
|
name,
|
||||||
|
class,
|
||||||
|
zone
|
||||||
|
)
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
local continue = false
|
||||||
---@type WHOFilter[]
|
---@type WHOFilter[]
|
||||||
local filters = query.filters
|
local filters = query.filters
|
||||||
for _, filter in pairs(filters) do
|
for _, filter in pairs(filters) do
|
||||||
if not filter(name, guild, level, race, class, zone) then
|
if Heimdall_Data.config.who.debug then
|
||||||
-- Mega scuffed, yes...
|
print(
|
||||||
-- But wow does not have gotos
|
string.format(
|
||||||
|
"[%s] Running filter %s on %s/%s/%s",
|
||||||
|
ModuleName,
|
||||||
|
filter.key,
|
||||||
|
name,
|
||||||
|
class,
|
||||||
|
zone
|
||||||
|
)
|
||||||
|
)
|
||||||
|
end
|
||||||
|
if not filter.Run(name, guild, level, race, class, zone) then
|
||||||
|
if Heimdall_Data.config.who.debug then
|
||||||
|
print(
|
||||||
|
string.format(
|
||||||
|
"[%s] Player %s filtered out by WHO filter %s",
|
||||||
|
ModuleName,
|
||||||
|
name,
|
||||||
|
filter.key
|
||||||
|
)
|
||||||
|
)
|
||||||
|
end
|
||||||
|
continue = true
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if Heimdall_Data.config.who.ignored[name] then
|
||||||
|
if Heimdall_Data.config.who.debug then
|
||||||
|
print(string.format("[%s] Ignoring blacklisted player: %s", ModuleName, name))
|
||||||
|
end
|
||||||
continue = true
|
continue = true
|
||||||
end
|
end
|
||||||
end
|
|
||||||
if Heimdall_Data.config.who.ignored[name] then continue = true end
|
|
||||||
--print(continue)
|
|
||||||
|
|
||||||
|
if Heimdall_Data.config.who.debug then
|
||||||
|
print(string.format("[%s] Player %s is not blacklisted", ModuleName, name))
|
||||||
|
end
|
||||||
if not continue then
|
if not continue then
|
||||||
|
if Heimdall_Data.config.who.debug then
|
||||||
|
print(string.format("[%s] Player %s is not filtered out", ModuleName, name))
|
||||||
|
end
|
||||||
local timestamp = date("%Y-%m-%dT%H:%M:%S")
|
local timestamp = date("%Y-%m-%dT%H:%M:%S")
|
||||||
local player = HeimdallStinkies[name]
|
local player = HeimdallStinkies[name]
|
||||||
if not player then
|
if not player then
|
||||||
|
if Heimdall_Data.config.who.debug then
|
||||||
|
print(
|
||||||
|
string.format("[%s] New player detected: %s (%s) in %s", ModuleName, name, class, zone)
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
player = Player.new(name, guild, race, class, zone)
|
player = Player.new(name, guild, race, class, zone)
|
||||||
if not Heimdall_Data.who then Heimdall_Data.who = {} end
|
if not Heimdall_Data.who then Heimdall_Data.who = {} end
|
||||||
if not Heimdall_Data.who.data then Heimdall_Data.who.data = {} end
|
if not Heimdall_Data.who.data then Heimdall_Data.who.data = {} end
|
||||||
local existing = Heimdall_Data.who.data[name]
|
local existing = Heimdall_Data.who.data[name]
|
||||||
|
|
||||||
if existing then
|
if existing then
|
||||||
|
if Heimdall_Data.config.who.debug then
|
||||||
|
print(
|
||||||
|
string.format(
|
||||||
|
"[%s] Found existing data for %s - Last seen: %s, Count: %d",
|
||||||
|
ModuleName,
|
||||||
|
name,
|
||||||
|
existing.lastSeen or "never",
|
||||||
|
existing.seenCount or 0
|
||||||
|
)
|
||||||
|
)
|
||||||
|
end
|
||||||
player.lastSeen = existing.lastSeen or "never"
|
player.lastSeen = existing.lastSeen or "never"
|
||||||
player.firstSeen = existing.firstSeen or "never"
|
player.firstSeen = existing.firstSeen or "never"
|
||||||
player.seenCount = existing.seenCount or 0
|
player.seenCount = existing.seenCount or 0
|
||||||
end
|
end
|
||||||
|
|
||||||
if player.firstSeen == "never" then
|
if player.firstSeen == "never" then
|
||||||
player.firstSeen = timestamp
|
player.firstSeen = timestamp
|
||||||
|
if Heimdall_Data.config.who.debug then
|
||||||
|
print(
|
||||||
|
string.format(
|
||||||
|
"[%s] First time seeing player: %s at %s",
|
||||||
|
ModuleName,
|
||||||
|
name,
|
||||||
|
timestamp
|
||||||
|
)
|
||||||
|
)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local stinky = Heimdall_Data.config.stinkies[name]
|
local stinky = shared.IsStinky(name)
|
||||||
if stinky then
|
if stinky then
|
||||||
|
if Heimdall_Data.config.who.debug then
|
||||||
|
print(string.format("[%s] Player %s marked as stinky!", ModuleName, name))
|
||||||
|
end
|
||||||
player.stinky = true
|
player.stinky = true
|
||||||
--PlaySoundFile("Interface\\Sounds\\Domination.ogg", "Master")
|
--PlaySoundFile("Interface\\Sounds\\Domination.ogg", "Master")
|
||||||
else
|
-- else
|
||||||
--PlaySoundFile("Interface\\Sounds\\Cloak.ogg", "Master")
|
-- PlaySoundFile("Interface\\Sounds\\Cloak.ogg", "Master")
|
||||||
end
|
end
|
||||||
|
|
||||||
local err = Notify(player)
|
local err = Notify(player)
|
||||||
if err then
|
if err then
|
||||||
print(string.format("Error notifying for %s: %s", tostring(name), tostring(err)))
|
print(
|
||||||
|
string.format(
|
||||||
|
"[%s] Error notifying for %s: %s",
|
||||||
|
ModuleName,
|
||||||
|
tostring(name),
|
||||||
|
tostring(err)
|
||||||
|
)
|
||||||
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
player.lastSeen = timestamp
|
player.lastSeen = timestamp
|
||||||
@@ -306,6 +632,17 @@ function shared.Whoer.Init()
|
|||||||
|
|
||||||
player.lastSeenInternal = GetTime()
|
player.lastSeenInternal = GetTime()
|
||||||
if player.zone ~= zone then
|
if player.zone ~= zone then
|
||||||
|
if Heimdall_Data.config.who.debug then
|
||||||
|
print(
|
||||||
|
string.format(
|
||||||
|
"[%s] Player %s zone changed from %s to %s",
|
||||||
|
ModuleName,
|
||||||
|
name,
|
||||||
|
player.zone,
|
||||||
|
zone
|
||||||
|
)
|
||||||
|
)
|
||||||
|
end
|
||||||
local err = NotifyZoneChanged(player, zone)
|
local err = NotifyZoneChanged(player, zone)
|
||||||
if err then
|
if err then
|
||||||
print(string.format("Error notifying for %s: %s", tostring(name), tostring(err)))
|
print(string.format("Error notifying for %s: %s", tostring(name), tostring(err)))
|
||||||
@@ -321,7 +658,8 @@ function shared.Whoer.Init()
|
|||||||
end
|
end
|
||||||
-- Turns out WA cannot do this (
|
-- Turns out WA cannot do this (
|
||||||
-- aura_env.UpdateMacro()
|
-- aura_env.UpdateMacro()
|
||||||
_G["FriendsFrameCloseButton"]:Click()
|
-- No longer needed with the hook to friends frame show
|
||||||
|
-- _G["FriendsFrameCloseButton"]:Click()
|
||||||
end)
|
end)
|
||||||
|
|
||||||
do
|
do
|
||||||
@@ -345,15 +683,39 @@ function shared.Whoer.Init()
|
|||||||
local function DoQuery()
|
local function DoQuery()
|
||||||
if not Heimdall_Data.config.who.enabled then return end
|
if not Heimdall_Data.config.who.enabled then return end
|
||||||
|
|
||||||
local query = whoQueries[whoQueryIdx]
|
local query = shared.WhoQueryService.queries[whoQueryIdx]
|
||||||
whoQueryIdx = whoQueryIdx + 1
|
if not query then
|
||||||
if whoQueryIdx > #whoQueries then
|
if Heimdall_Data.config.who.debug then
|
||||||
|
print(
|
||||||
|
string.format("[%s] Error: No WHO query found to run at index %d", ModuleName, whoQueryIdx)
|
||||||
|
)
|
||||||
whoQueryIdx = 1
|
whoQueryIdx = 1
|
||||||
end
|
end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
if Heimdall_Data.config.who.debug then
|
||||||
|
print(
|
||||||
|
string.format(
|
||||||
|
"[%s] Running WHO query %d/%d: %s",
|
||||||
|
ModuleName,
|
||||||
|
whoQueryIdx,
|
||||||
|
#shared.WhoQueryService.queries,
|
||||||
|
query.query
|
||||||
|
)
|
||||||
|
)
|
||||||
|
print(string.format("[%s] Query has %d filters", ModuleName, #query.filters))
|
||||||
|
for i, filter in ipairs(query.filters) do
|
||||||
|
print(string.format("[%s] Filter %d: %s", ModuleName, i, filter.key))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
whoQueryIdx = whoQueryIdx + 1
|
||||||
|
if whoQueryIdx > #shared.WhoQueryService.queries then whoQueryIdx = 1 end
|
||||||
lastQuery = query
|
lastQuery = query
|
||||||
--print(string.format("Running who query: %s", tostring(query.query)))
|
whoWaiting = true
|
||||||
---@diagnostic disable-next-line: param-type-mismatch
|
---@diagnostic disable-next-line: param-type-mismatch
|
||||||
SetWhoToUI(1)
|
SetWhoToUI(1)
|
||||||
|
SetWhoToUI(1)
|
||||||
SendWho(query.query)
|
SendWho(query.query)
|
||||||
end
|
end
|
||||||
local function Tick()
|
local function Tick()
|
||||||
@@ -362,6 +724,12 @@ function shared.Whoer.Init()
|
|||||||
end
|
end
|
||||||
Tick()
|
Tick()
|
||||||
end
|
end
|
||||||
|
local original_FriendsFrame_OnEvent = FriendsFrame_OnEvent
|
||||||
|
local function my_FriendsFrame_OnEvent(self, event, ...)
|
||||||
|
if not (event == "WHO_LIST_UPDATE" and whoWaiting) then original_FriendsFrame_OnEvent(self, event, ...) end
|
||||||
|
end
|
||||||
|
FriendsFrame_OnEvent = my_FriendsFrame_OnEvent
|
||||||
|
|
||||||
print("Heimdall - Whoer loaded")
|
print(string.format("[%s] Module initialized", ModuleName))
|
||||||
end
|
end,
|
||||||
|
}
|
||||||
|
BIN
Sounds/MGSSpot.ogg
(Stored with Git LFS)
Normal file
BIN
Sounds/MGSSpot.ogg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
Sounds/MedicGangsterParadise.ogg
(Stored with Git LFS)
Normal file
BIN
Sounds/MedicGangsterParadise.ogg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
Sounds/OOF.ogg
(Stored with Git LFS)
Normal file
BIN
Sounds/OOF.ogg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
Sounds/StarScream.ogg
(Stored with Git LFS)
Normal file
BIN
Sounds/StarScream.ogg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
Texture/Aura1.tga
(Stored with Git LFS)
Normal file
BIN
Texture/Aura1.tga
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
Texture/Aura10.tga
(Stored with Git LFS)
Normal file
BIN
Texture/Aura10.tga
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
Texture/Aura100.tga
(Stored with Git LFS)
Normal file
BIN
Texture/Aura100.tga
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
Texture/Aura101.tga
(Stored with Git LFS)
Normal file
BIN
Texture/Aura101.tga
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
Texture/Aura102.tga
(Stored with Git LFS)
Normal file
BIN
Texture/Aura102.tga
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
Texture/Aura103.tga
(Stored with Git LFS)
Normal file
BIN
Texture/Aura103.tga
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
Texture/Aura104.tga
(Stored with Git LFS)
Normal file
BIN
Texture/Aura104.tga
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
Texture/Aura105.tga
(Stored with Git LFS)
Normal file
BIN
Texture/Aura105.tga
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
Texture/Aura106.tga
(Stored with Git LFS)
Normal file
BIN
Texture/Aura106.tga
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
Texture/Aura107.tga
(Stored with Git LFS)
Normal file
BIN
Texture/Aura107.tga
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
Texture/Aura108.tga
(Stored with Git LFS)
Normal file
BIN
Texture/Aura108.tga
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
Texture/Aura109.tga
(Stored with Git LFS)
Normal file
BIN
Texture/Aura109.tga
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
Texture/Aura11.tga
(Stored with Git LFS)
Normal file
BIN
Texture/Aura11.tga
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
Texture/Aura110.tga
(Stored with Git LFS)
Normal file
BIN
Texture/Aura110.tga
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
Texture/Aura111.tga
(Stored with Git LFS)
Normal file
BIN
Texture/Aura111.tga
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
Texture/Aura112.tga
(Stored with Git LFS)
Normal file
BIN
Texture/Aura112.tga
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
Texture/Aura113.tga
(Stored with Git LFS)
Normal file
BIN
Texture/Aura113.tga
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
Texture/Aura114.tga
(Stored with Git LFS)
Normal file
BIN
Texture/Aura114.tga
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
Texture/Aura115.tga
(Stored with Git LFS)
Normal file
BIN
Texture/Aura115.tga
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
Texture/Aura116.tga
(Stored with Git LFS)
Normal file
BIN
Texture/Aura116.tga
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
Texture/Aura117.tga
(Stored with Git LFS)
Normal file
BIN
Texture/Aura117.tga
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
Texture/Aura118.tga
(Stored with Git LFS)
Normal file
BIN
Texture/Aura118.tga
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
Texture/Aura119.tga
(Stored with Git LFS)
Normal file
BIN
Texture/Aura119.tga
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
Texture/Aura12.tga
(Stored with Git LFS)
Normal file
BIN
Texture/Aura12.tga
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
Texture/Aura120.tga
(Stored with Git LFS)
Normal file
BIN
Texture/Aura120.tga
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
Texture/Aura121.tga
(Stored with Git LFS)
Normal file
BIN
Texture/Aura121.tga
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
Texture/Aura122.tga
(Stored with Git LFS)
Normal file
BIN
Texture/Aura122.tga
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
Texture/Aura123.tga
(Stored with Git LFS)
Normal file
BIN
Texture/Aura123.tga
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
Texture/Aura124.tga
(Stored with Git LFS)
Normal file
BIN
Texture/Aura124.tga
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
Texture/Aura125.tga
(Stored with Git LFS)
Normal file
BIN
Texture/Aura125.tga
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
Texture/Aura126.tga
(Stored with Git LFS)
Normal file
BIN
Texture/Aura126.tga
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
Texture/Aura127.tga
(Stored with Git LFS)
Normal file
BIN
Texture/Aura127.tga
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
Texture/Aura128.tga
(Stored with Git LFS)
Normal file
BIN
Texture/Aura128.tga
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
Texture/Aura129.tga
(Stored with Git LFS)
Normal file
BIN
Texture/Aura129.tga
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
Texture/Aura13.tga
(Stored with Git LFS)
Normal file
BIN
Texture/Aura13.tga
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
Texture/Aura130.tga
(Stored with Git LFS)
Normal file
BIN
Texture/Aura130.tga
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
Texture/Aura131.tga
(Stored with Git LFS)
Normal file
BIN
Texture/Aura131.tga
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
Texture/Aura132.tga
(Stored with Git LFS)
Normal file
BIN
Texture/Aura132.tga
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
Texture/Aura133.tga
(Stored with Git LFS)
Normal file
BIN
Texture/Aura133.tga
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
Texture/Aura134.tga
(Stored with Git LFS)
Normal file
BIN
Texture/Aura134.tga
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
Texture/Aura135.tga
(Stored with Git LFS)
Normal file
BIN
Texture/Aura135.tga
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
Texture/Aura136.tga
(Stored with Git LFS)
Normal file
BIN
Texture/Aura136.tga
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
Texture/Aura137.tga
(Stored with Git LFS)
Normal file
BIN
Texture/Aura137.tga
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
Texture/Aura138.tga
(Stored with Git LFS)
Normal file
BIN
Texture/Aura138.tga
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
Texture/Aura139.tga
(Stored with Git LFS)
Normal file
BIN
Texture/Aura139.tga
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
Texture/Aura14.tga
(Stored with Git LFS)
Normal file
BIN
Texture/Aura14.tga
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
Texture/Aura140.tga
(Stored with Git LFS)
Normal file
BIN
Texture/Aura140.tga
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
Texture/Aura141.tga
(Stored with Git LFS)
Normal file
BIN
Texture/Aura141.tga
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
Texture/Aura142.tga
(Stored with Git LFS)
Normal file
BIN
Texture/Aura142.tga
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
Texture/Aura143.tga
(Stored with Git LFS)
Normal file
BIN
Texture/Aura143.tga
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
Texture/Aura144.tga
(Stored with Git LFS)
Normal file
BIN
Texture/Aura144.tga
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
Texture/Aura145.tga
(Stored with Git LFS)
Normal file
BIN
Texture/Aura145.tga
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
Texture/Aura15.tga
(Stored with Git LFS)
Normal file
BIN
Texture/Aura15.tga
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
Texture/Aura16.tga
(Stored with Git LFS)
Normal file
BIN
Texture/Aura16.tga
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
Texture/Aura17.tga
(Stored with Git LFS)
Normal file
BIN
Texture/Aura17.tga
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
Texture/Aura18.tga
(Stored with Git LFS)
Normal file
BIN
Texture/Aura18.tga
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
Texture/Aura19.tga
(Stored with Git LFS)
Normal file
BIN
Texture/Aura19.tga
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
Texture/Aura2.tga
(Stored with Git LFS)
Normal file
BIN
Texture/Aura2.tga
(Stored with Git LFS)
Normal file
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user