You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

606 lines
19 KiB

4 years ago
<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE muclient>
<muclient>
<plugin
name="Areia_Consider"
author="Areia"
id="434bc4b92d5e6ddf77d8e20c"
language="Lua"
purpose="Quick kill with consider"
save_state="n"
date_written="2021-04-11 21:00:00"
requires="5.06"
version="1.0"
>
<description trim="y">
<![CDATA[
]]>
</description>
</plugin>
<include name="constants.lua"/>
<aliases>
</aliases>
<triggers>
</triggers>
<script>
<![CDATA[
require "commas"
require "copytable"
require "gmcphelper"
require "tprint"
require "var"
require "wait"
dofile(GetInfo(60) .. "aardwolf_colors.lua")
--------------------------------------------------
-- Main
--------------------------------------------------
Main = {}
function Main.initialize()
AddAlias("alias_main_kill",
"^ac(?:k|\\s+kill)(?:\\s+(?<index>\\d+))?$", "",
alias_flag.Enabled + alias_flag.IgnoreAliasCase + alias_flag.RegularExpression + alias_flag.Temporary,
"Main.kill"
)
AddAlias("alias_main_kill_all",
"^ac(?:a|\\s+killall)$", "",
alias_flag.Enabled + alias_flag.IgnoreAliasCase + alias_flag.RegularExpression + alias_flag.Temporary,
"Main.kill_all"
)
end
function Main.kill(alias, line, wc)
local state = tonumber(gmcp("char.status.state"))
if not (state == 3 or state == 8) then
Utility.print("Character's state does not allow kill.")
return
end
if (#Consider.mobs == 0) then
Utility.print("No mobs considered. Considering...")
Consider.start()
return
end
local index = tonumber(wc.index) or 1
-- mobs are stored in reverse order, so we need to do a little math to find
-- the right one
local mob = Consider.mobs[#Consider.mobs + 1 - index]
if (not mob) then
Utility.print("There are only %d mobs currently indexed. Enter @Yac @wto refresh.")
return
end
if (mob.ignore) then
Utility.print("That mob is currently being ignored.")
return
end
Execute(Settings.get_kill_cmd(mob))
end
function Main.kill_all(alias, line, wc)
local state = tonumber(gmcp("char.status.state"))
if not (state == 3 or state == 8) then
Utility.print("Character's state does not allow kill.")
return
end
if (#Consider.mobs == 0) then
Utility.print("No mobs considered. Considering...")
Consider.start()
return
end
local cmds = {}
for _, mob in ipairs(Consider.mobs) do
if (not mob.ignore) then
table.insert(cmds, Settings.get_kill_cmd(mob))
end
end
if (#cmds == 0) then
Utility.print("All mobs in room are ignored.")
return
end
Execute(table.concat(cmds, ";"))
4 years ago
end
--------------------------------------------------
-- Settings
--------------------------------------------------
Settings = {}
function Settings.initialize()
AddAlias("alias_settings_auto_consider",
"^ac\\s+auto(?:\\s+(?<setting>\\w+))?$", "",
alias_flag.Enabled + alias_flag.IgnoreAliasCase + alias_flag.RegularExpression + alias_flag.Temporary,
"Settings.auto_consider"
)
AddAlias("alias_settings_ignore_flag_display",
"^ac\\s+ignore\\s+flags?$", "",
alias_flag.Enabled + alias_flag.IgnoreAliasCase + alias_flag.RegularExpression + alias_flag.Temporary,
"Settings.ignore_flag_display"
)
AddAlias("alias_settings_ignore_flag_toggle",
"^ac\\s+ignore\\s+flag\\s+(?<flag>\\w+)(?:\\s+(?<setting>\\w+))?$", "",
alias_flag.Enabled + alias_flag.IgnoreAliasCase + alias_flag.RegularExpression + alias_flag.Temporary,
"Settings.ignore_flag_toggle"
)
AddAlias("alias_settings_ignore_level_display",
"^ac\\s+ignore\\s+levels?$", "",
alias_flag.Enabled + alias_flag.IgnoreAliasCase + alias_flag.RegularExpression + alias_flag.Temporary,
"Settings.ignore_level_display"
)
AddAlias("alias_settings_ignore_level_toggle",
"^ac\\s+ignore\\s+level\\s+(?<level>\\d+)(?:\\s+(?<setting>\\w+))?$", "",
alias_flag.Enabled + alias_flag.IgnoreAliasCase + alias_flag.RegularExpression + alias_flag.Temporary,
"Settings.ignore_level_toggle"
)
AddAlias("alias_settings_kill_cmd",
"^ac\\s+killcmd(?:\\s+(?<setting>.+?))?$", "",
alias_flag.Enabled + alias_flag.IgnoreAliasCase + alias_flag.RegularExpression + alias_flag.Temporary,
"Settings.kill_cmd"
)
AddAlias("alias_settings_consider_output",
"^ac\\s+show(?:\\s+(?<setting>\\w+))?$", "",
alias_flag.Enabled + alias_flag.IgnoreAliasCase + alias_flag.RegularExpression + alias_flag.Temporary,
"Settings.consider_output"
)
Settings.load()
end
function Settings.default()
local default = {
autoConsider = false,
ignore = {
flags = {
aimed = true, evil = false, good = false,
sanctuary = true, wounded = true,
},
level = {}
},
killCmds = {"backstab"},
showConsiderOutput = false,
}
for i = 1, 13 do
table.insert(default.ignore.level, false)
end
return serialize.save_simple(default)
end
function Settings.load()
Settings.config = loadstring(string.format("return %s", var.config or Settings.default()))()
Settings.save()
end
function Settings.save()
var.config = serialize.save_simple(Settings.config)
end
function Settings.auto_consider(alias, line, wc)
local setting = wc.setting:lower()
if (setting == "") then
Settings.config.autoConsider = not Settings.config.autoConsider
elseif (setting == "on") then
Settings.config.autoConsider = true
elseif (setting == "off") then
Settings.config.autoConsider = false
else
Utility.print("Syntax: @Yac auto [on|off]")
return
end
Settings.save()
Utility.plugin_msg(string.format("%sabled auto-consider.", Settings.config.autoConsider and "@GEn" or "@RDis"))
end
function Settings.ignore_flag_display()
Utility.plugin_msg("Ignored flags:")
for _, flag in ipairs{"aimed", "evil", "good", "sanctuary", "wounded"} do
Utility.print(string.format(" @Y%-11.11s (%-5.5s@w)",
Utility.capitalize(flag), Settings.config.ignore.flags[flag] and "@GYes" or "@RNo"
))
end
end
function Settings.ignore_flag_toggle(alias, line, wc)
local flag = wc.flag:lower()
if not (flag == "aimed" or flag == "evil" or flag == "good"
or flag == "sanctuary" or flag == "wounded") then
Utility.print("Valid flags: @Yaimed@w, @Yevil@w, @Ygood@w, @Ysanctuary@w, @Ywounded")
return
end
local setting = wc.setting:lower()
if (setting == "") then
Settings.config.ignore.flags[flag] = not Settings.config.ignore.flags[flag]
elseif (setting == "on") then
Settings.config.ignore.flags[flag] = true
elseif (setting == "off") then
Settings.config.ignore.flags[flag] = false
else
Utility.print(string.format("Syntax: @Yac ignore flag %s [on|off]", flag))
return
end
Settings.save()
Utility.plugin_msg(string.format("%s @wignoring mobs with the @Y%s @wflag while killing all.",
Settings.config.ignore.flags[flag] and "@GNow" or "@RNo longer", flag
))
end
function Settings.ignore_level_display()
Utility.plugin_msg("Ignored levels:")
for i, range in ipairs(Consider.LEVEL_RANGE) do
Utility.print(string.format(" @Y%2.d@w. %-11.11s (%-5.5s@w)",
i, range, Settings.config.ignore.level[i] and "@GYes" or "@RNo"
))
end
end
function Settings.ignore_level_toggle(alias, line, wc)
local level = tonumber(wc.level)
if not (level >= 1 and level <= 13) then
Utility.print("Valid level ranges: @Y1 @wto @Y13")
return
end
local setting = wc.setting:lower()
if (setting == "") then
Settings.config.ignore.level[level] = not Settings.config.ignore.level[level]
elseif (setting == "on") then
Settings.config.ignore.level[level] = true
elseif (setting == "off") then
Settings.config.ignore.level[level] = false
else
Utility.print(string.format("Syntax: @Yac ignore level %d [on|off]", level))
return
end
Settings.save()
Utility.plugin_msg(string.format("%s @wignoring mobs in level range @y%s @wwhile killing all.",
Settings.config.ignore.level[level] and "@GNow" or "@RNo longer",
Consider.LEVEL_RANGE[level]
))
end
function Settings.should_ignore(mob)
-- ignore mob if it has divine protection
local ignoreMob = mob.protected
-- ignore if already ignored or mob's level range is set to ignored
ignoreMob = ignoreMob or Settings.config.ignore.level[mob.levelRange]
for flag in pairs(mob.flags) do
-- ignore if already ignored or mob has a flag that is set to be ignored
ignoreMob = ignoreMob or Settings.config.ignore.flags[flag]
end
return ignoreMob
end
function Settings.kill_cmd(alias, line, wc)
if (wc.setting ~= "") then
Settings.config.killCmds = utils.split(wc.setting, ";")
Settings.save()
end
Utility.plugin_msg("Kill command:",
string.format("@Y%s", Settings.get_kill_cmd_str())
)
end
function Settings.get_kill_cmd(mob)
local cmdList = {}
for _, cmd in ipairs(Settings.config.killCmds) do
local cmdStr = string.format("%s %d.'%s'", cmd, mob.index, mob.keywords)
table.insert(cmdList, cmdStr)
end
return table.concat(cmdList, ";")
end
function Settings.get_kill_cmd_str()
local cmdList = {}
for _, cmd in ipairs(Settings.config.killCmds) do
local cmdStr = string.format("%s <target>", cmd)
table.insert(cmdList, cmdStr)
end
return table.concat(cmdList, ";")
end
function Settings.consider_output(alias, line, wc)
local setting = wc.setting:lower()
if (setting == "") then
Settings.config.showConsiderOutput = not Settings.config.showConsiderOutput
elseif (setting == "on") then
Settings.config.showConsiderOutput = true
elseif (setting == "off") then
Settings.config.showConsiderOutput = false
else
Utility.print("Syntax: @Yac show [on|off]")
return
end
Settings.save()
Utility.plugin_msg(string.format("%sabled @wdisplay of consider output.", Settings.config.showConsiderOutput and "@GEn" or "@RDis"))
end
--------------------------------------------------
-- Consider
--------------------------------------------------
Consider = {}
function Consider.initialize()
AddAlias("alias_consider_mobs",
"^ac$", "",
alias_flag.Enabled + alias_flag.IgnoreAliasCase + alias_flag.RegularExpression + alias_flag.Temporary,
"Consider.start"
)
Consider.LEVEL_RANGE = {
"-20 or less", "-10 to -19", "-5 to -9", "-2 to -4",
"-1 to +1", "+2 to +4", "+5 to +9", "+10 to +15",
"+16 to +20", "+21 to +30", "+31 to +40", "+41 to +50",
"+51 or more"
}
Consider.OUTPUTS = {
"You would stomp (?<name>.+?) into the ground\\.",
"(?<name>.+?) would be easy, but is it even worth the work out\\?",
"No Problem! (?<name>.+?) is weak compared to you\\.",
"(?<name>.+?) looks a little worried about the idea\\.",
"(?<name>.+?) should be a fair fight!",
"(?<name>.+?) snickers nervously\\.",
"(?<name>.+?) chuckles at the thought of you fighting (?:him|her|it)\\.",
"Best run away from (?<name>.+?) while you can!",
"Challenging (?<name>.+?) would be either very brave or very stupid\\.",
"(?<name>.+?) would crush you like a bug!",
"(?<name>.+?) would dance on your grave!",
"(?<name>.+?) says 'BEGONE FROM MY SIGHT unworthy!'",
"You would be completely annihilated by (?<name>.+?)!",
"(?<name>.+?) has divine protection\\.",
}
for i, subpattern in ipairs(Consider.OUTPUTS) do
local triggerName = string.format("trigger_consider_mob%d", i)
AddTriggerEx(triggerName,
string.format("^(?<flags>(?:\\([\\w\\s]+\\)\\s*)+)?%s$", subpattern), "",
trigger_flag.OmitFromOutput + trigger_flag.RegularExpression + trigger_flag.Temporary,
custom_colour.NoChange, 0, "",
"Consider.mob", sendto.script, 100
)
SetTriggerOption(triggerName, "group", "trigger_group_consider_mobs")
end
AddTriggerEx("trigger_consider_mob_end",
"^\\{/consider\\}$", "",
trigger_flag.OmitFromOutput + trigger_flag.RegularExpression + trigger_flag.Temporary,
custom_colour.NoChange, 0, "",
"Consider.finish", sendto.script, 100
)
SetTriggerOption("trigger_consider_mob_end", "group", "trigger_group_consider_mobs")
Consider.KEYWORDS_TO_IGNORE = {["a"] = true, ["an"] = true, ["and"] = true,
["but"] = true, ["for"] = true, ["in"] = true, ["nor"] = true,
["of"] = true, ["on"] = true, ["or"] = true, ["so"] = true, ["some"] = true,
["the"] = true, ["to"] = true, ["too"] = true, ["with"] = true, ["yet"] = true,
["merdevil"] = true, ["onyx"] = true,
}
Consider.mobs = {} -- main mob info obtained from consider
Consider.keywordCount = {} -- keywords-to-count record used to track proper indices (see Consider.mob)
Consider.keywordCache = {} -- session name-to-keywords record (see Consider.get_mob_keywords)
end
function Consider.start()
local state = tonumber(gmcp("char.status.state"))
if not (state == 3 or state == 8) then -- neither active nor in combat
Utility.print("Character state does not allow consider.")
return
end
SendNoEcho("echo {consider}")
SendNoEcho("consider all")
SendNoEcho("echo {/consider}")
wait.make(Consider.start_CR)
end
function Consider.start_CR()
local line = wait.regexp("^\\{consider\\}$", 4, trigger_flag.OmitFromOutput)
if (not line) then
Utility.print("@RTimeout@w. Failed to obtain consider output.")
return
end
Consider.mobs = {}
Consider.keywordCount = {}
EnableTriggerGroup("trigger_group_consider_mobs", true)
end
function Consider.mob(trigger, line, wc)
local mob = {}
mob.name = wc.name
mob.keywords = Consider.get_mob_keywords(mob.name)
-- update count of mobs with these particular keywords. The count directly
-- determines the mob's proper index (i.e., is this 1.goblin, 2.goblin, etc.).
Consider.keywordCount[mob.keywords] = (Consider.keywordCount[mob.keywords] or 0) + 1
mob.index = Consider.keywordCount[mob.keywords]
mob.levelRange = tonumber(trigger:match("%d+"))
mob.protected = mob.levelRange == 14 -- divine protection
local flagsStr = wc.flags:lower()
mob.flags = {
aimed = flagsStr:match("%(a%)") or flagsStr:match("%(aimed%)"),
evil = flagsStr:match("%(r%)") or flagsStr:match("%(red aura%)"),
good = flagsStr:match("%(g%)") or flagsStr:match("%(golden aura%)"),
sanctuary = flagsStr:match("%(w%)") or flagsStr:match("%(white aura%)"),
wounded = flagsStr:match("%(wounded%)")
}
mob.ignore = Settings.should_ignore(mob)
table.insert(Consider.mobs, 1, mob)
if (Settings.config.showConsiderOutput) then
Utility.print(string.format("%-10.10s %s, %s, %s",
mob.ignore and "(Ignored)" or "", mob.name,
flagsStr ~= "" and flagsStr or "None",
Consider.LEVEL_RANGE[mob.levelRange]
))
end
end
function Consider.finish()
EnableTriggerGroup("trigger_group_consider_mobs", false)
local total = #Consider.mobs
if (total == 0) then
-- Utility.print("No mobs found.")
-- No real need to print here, since game output can handle this case itself.
return
end
local validTargets = 0
for _, mob in ipairs(Consider.mobs) do
validTargets = not mob.ignore and validTargets + 1 or validTargets
end
if (validTargets ~= total) then
Utility.print(string.format("@Y%d@w/@Y%d @wmob%s found.",
validTargets, total, total == 1 and "" or "s"
))
else
Utility.print(string.format("@Y%d @wmob%s found.",
total, total == 1 and "" or "s"
))
end
end
function Consider.get_mob_keywords(name)
if (Consider.keywordCache[name]) then
return Consider.keywordCache[name]
end
local keywords = {}
for word in name:lower():gmatch("[^%s]+") do -- iterate through each string of non-whitespace chars
if (not Consider.KEYWORDS_TO_IGNORE[word]) then -- if not in omit table, we want to use it
-- take only the first part of hyphenated (eg, long-haired) and weird
-- apostrophe'd (eg, N'Kari) words
word = word:gsub("(%a+)['-]%a+", "%1")
-- then strip away any other non-alphabetic characters
word = word:gsub("%A", "")
if (word ~= "") then
table.insert(keywords, word)
end
end
end
if (#keywords == 0) then
-- Must be quite an odd name... just return it and let the user deal with it
return name
end
local keywordsStr = table.concat(keywords, " ")
Consider.keywordCache[name] = keywordsStr
return keywordsStr
end
4 years ago
--------------------------------------------------
-- Utility
--------------------------------------------------
Utility = {}
function Utility.initialize()
-- General aliases
AddAlias("alias_utility_help",
"^ac\\s+help$", "",
alias_flag.Enabled + alias_flag.IgnoreAliasCase + alias_flag.RegularExpression + alias_flag.Temporary,
"Utility.display_help"
)
local initializers = {
Main.initialize,
Settings.initialize,
Consider.initialize,
4 years ago
}
for _, initializer in ipairs(initializers) do
initializer()
end
end
function Utility.deinitialize()
local aliases = GetAliasList()
if (aliases) then
for i = 1, #aliases do
EnableAlias(aliases[i], false)
DeleteAlias(aliases[i])
end
end
local triggers = GetTriggerList()
if (triggers) then
for i = 1, #triggers do
EnableTrigger(triggers[i], false)
DeleteTrigger(triggers[i])
end
end
end
function Utility.print(str)
-- Lets us use Aard color codes in our ColourNotes
AnsiNote(stylesToANSI(ColoursToStyles(string.format("@w%s@w", str))))
end
function Utility.plugin_msg(str, ...)
Utility.print(string.format("[@YAreiaConsider@w]: %s", str))
for _, arg in ipairs{...} do
Utility.print(string.format(" %s", arg))
end
4 years ago
end
function Utility.display_greeting()
end
function Utility.display_help()
Utility.print("TODO")
end
function Utility.capitalize(str)
return string.format("%s%s", str:sub(1, 1):upper(), str:sub(2))
end
4 years ago
--------------------------------------------------
-- Plugin Callbacks
--------------------------------------------------
function OnPluginInstall()
Utility.initialize()
Utility.display_greeting()
end
function OnPluginEnable()
OnPluginInstall()
end
function OnPluginClose()
Utility.deinitialize()
end
function OnPluginDisable()
OnPluginClose()
end
function OnPluginBroadcast(msg, id, name, text)
if (id == "3e7dedbe37e44942dd46d264") then
end
end
]]>
</script>
</muclient>