For all of the many times you want to run a command (or set of commands) repeatedly:
^loop (\d+) (.*)$
local t={} ; i=1
for str in string.gmatch(matches[3], "([^"..";".."]+)") do
t[i] = str
i = i + 1
end
for i=1,tonumber(matches[2]) do
for _,v in ipairs(t) do
send(v)
end
end
Usage: loop <#> <commands separated by ;>
e.g. loop 15 put spike in hole;get spike from hole
Rough calculation of the value of a level 40 figurine. Ignores divine realm size. You can specify whether it's a miniature figurine or not.
^esteem (mini )?(\d+)$
local value
local tatval
local poteenval
local bothval
local figurineesteem
local miniaturemult
local ministring
figurineesteem = tonumber(matches[3])
if matches[2] == "mini " then
miniaturemult = 0.02 * 40
ministring = "a mini w/ "
else
miniaturemult = 0
ministring = ""
end
value = figurineesteem * 100 * (1 + (2) + miniaturemult)
tatval = value * 1.1
poteenval = value * 1.5
bothval = tatval * 1.5
cecho(string.format("<green>You have %s%s esteem? It's worth:\n"..
" With no buffs: %s essence\n"..
" With divinetattoo: %s essence\n"..
" With poteen: %s essence\n"..
" With both: %s essence\n",
ministring,
format_int(figurineesteem),
format_int(value),
format_int(tatval),
format_int(poteenval),
format_int(bothval)
))
ETA: That won't work without this function, which you can just drop in a script somewhere. It just adds commas to numbers.
function format_int(number)
local i, j, minus, int, fraction = tostring(number):find('([-]?)(%d+)([.]?%d*)')
-- reverse the int-string and append a comma to all blocks of 3 digits
int = int:reverse():gsub("(%d%d%d)", "%1,")
-- reverse the int-string back remove an optional comma and put the
-- optional minus and fractional part back
return minus .. int:reverse():gsub("^,", "") .. fraction
end
If anyone else is still using the old M&MF influencing thing, and is curious to know which denizens in the room you've influenced already, try putting this in a script/alias/trigger/whatever:
function checkInfluenced(bool)
local long = bool or false
for k, v in pairs(mmi.roomnpcs) do
if v.influencable and v.influenced then
if long then cecho("<PaleGreen>"..v.longname.."\n") else cecho("<PaleGreen>X") end
elseif v.influencable and not v.influenced then
if long then cecho("<antique_white>"..v.longname.."\n") else cecho("<antique_white>.") end
end
end
end
In this quick little example I clumsily hacked together, you can choose whether you want to see the names of the denizens in the room by passing in "true" - false, or just nothing, will give you the short version.
Long:
Short:
I love this, so I modified it to do what I most often want: give me a number
function influencedNumber()
local total = 0
local done = 0
for k,v in pairs(mmi.roomnpcs) do
if v.influencable then
total = total + 1
end
if v.influencable and v.influenced then
done = done + 1
end
end
cecho("<PaleGreen>Influenced "..done.." out of "..total.." for this room.\n")
end
Or, if you have a filter function:
function influencedNumber()
local influencable = filter_dict(function(x) return x.influencable end, mmi.roomnpcs)
local influenced = filter_dict(function(x) return x.influenced end, influencable)
cecho("<PaleGreen>Influenced "..#influenced.." out of "..#influencable.." for this room.\n")
end
On the heels of my triple post... One more and then I'm going to bed.
A bit of functional programming in Lua:
function map(func, array)
local new_array = {}
for i,v in ipairs(array) do
new_array[i] = func(v)
end
return new_array
end
function remove_if(func, arr)
local new_array = {}
for _,v in arr do
if not func(v) then table.insert(new_array, v) end
end
return new_array
end
function filter(func, arr)
local new_array = {}
for _,v in arr do
if func(v) then table.insert(new_array, v) end
end
return new_array
end
function filter_dict(func, dict)
local new_dict = {}
for k,v in pairs(dict) do
if func(v) then table.insert(new_dict, v) end
end
return new_dict
end
Look up information on a player using the Lusternia API.
^api (\w+) ?(\w+)?$
-- downloads the lusternia API page for the chosen player, displays the info (or a single field)
local saveto = getMudletHomeDir().."/apiscrape.txt"
local url = "http://api.lusternia.com/characters/"..matches[2]..".json"
local field = matches[3] or nil
registerAnonymousEventHandler(
"sysDownloadDone",
function(_, filename)
if filename ~= saveto then
return true -- keep the event handler since this was not our file
end
local f, s, webpage = io.open(filename)
if f then webpage = f:read("*a"); io.close(f) end
local contents = yajl.to_value(webpage)
if field ~= nil then echo(field..": "..contents[field].."\n") else display(contents) end
os.remove(filename)
end,
true
)
downloadFile(saveto, url)
cecho("<white>Downloading <green>"..url.."<white> to <green>"..saveto.."\n")
If you're in a manse that you've mapped out and linked to the aetherplex, this alias lets you PATH TRACK directly from it. (By going to the aetherplex first, then using the game-side pathing from there.)
You know what I hate? Curios. You know. Those singles and other packs you get from the Wheel, amirite? Use this trigger in Mudlet to sell your pieces. Make sure you have 500 gold per piece you want to sell.
^(\d+)(\s+)(Rare|Piece)(\s+)(.+) <--- set to regex
send("CURIOMARKET ADD sell piece " ..matches[2].." FOR 2 credits") <--- change to whatever amount you want to put your pieces up for.
Once the trigger is set up, just do CURIO LIST PIECES.
Her voice firm and commanding, Terentia, the Even Bladed says to you, "You have kept your oath to Me, Parhelion. You have sworn to maintain Justice in these troubled times."
Yet if a boon be granted me, unworthy as I am, let it be for a steady hand with a clear eye and a fury most inflaming.
It's pretty straightforward! Consider a table with keys and values. pairs returns two iterators (lists that you can loop over); the first is the keys, the second is the values associated with those keys. So if you have
mytable = { a=1, b=2, c=3 }
And you do for k,v in pairs(mytable) do
then each time through the loop, k will be the next key (first time a, then b, then c), and v will be the value associated with that key (first time 1, then 2, then 3).
It APPEARS to get more complicated in my keg example, because the values are themselves tables, but just think of v as a variable that will have whatever the appropriate value is.
Since someone asked in an in-game clan, here's a quick code snippet to convert a list of comms (of the form "commname ### commname ### commname ###") to a sum:
function esteemFigurine()<br> if tonumber(gmcp.Char.Vitals.esteem) > 250 then<br> send("imbue figurine with 250 esteem")<br> end<br>end<br>registerAnonymousEventHandler("gmcp.Char.Vitals", "esteemFigurine")
Just a little tidbit to automatically imbue a figurine with esteem
You can remove all that conditional logic by using string.format. The format specifier %02d says "take a number, and format it to a width of at least 2 characters, filling with 0s"
local now = os.date("*t")
cecho(string.format("<pale_turquoise>%d-%d-%d @ %02d:%02d:%02d", now["year"], now["month"], now["day"], now["hour"], now["min"], now["sec"]))
local colors = { blue = 36073, brown = 11811, black = 11600, yellow = 9888, red = 10509, steel = 10185, white = 10457, purple = 47812, green = 9985, crystal = 12652, wooden = 10992, } local exitScript = [[script:sendAll("outr %sbutton", "touch %sbutton", false)]] function mapperButtons() if table.contains(gmcp.Room.Info.details, "the Prime Material Plane") and table.contains(gmcp.Room.Info.details, "outdoors") then for color, room in pairs(colors) do mmp.tempSpecialExit(gmcp.Room.Info.num, room, exitScript:format(color,color), 20) end else for color, room in pairs(colors) do mmp.tempSpecialExit(148, room, exitScript:format(color,color), 20) end end end registerAnonymousEventHandler("mmp link externals", "mapperButtons")
The script I used for integrating buttons into mudlet mapper's pathfinding when I was aethertrading. It will only use them to path to bubbles - it won't use buttons as a shortcut. Just toss it in a script and it's good to go!
local alertIDs = {"267079", "315983"} function itemAlert() local addEvent = gmcp.Char.Items.Add if addEvent.location ~= "inv" then return end for _, checkId in pairs(alertIDs) do if addEvent.item.id == checkId then cecho( "<sky_blue>" .. string.title(addEvent.item.name) .. " has returned to your inventory!" ) end end end registerAnonymousEventHandler("gmcp.Char.Items.Add", "itemAlert")
Small snippet that lets you watch for things returning to your inventory that might not give a message otherwise, like artifacts resetting after you loaned them out.
You can remove all that conditional logic by using string.format.
The format specifier %02d says "take a number, and format it to a width
of at least 2 characters, filling with 0s"
local now = os.date("*t")
cecho(string.format("<pale_turquoise>%d-%d-%d @ %02d:%02d:%02d", now["year"], now["month"], now["day"], now["hour"], now["min"], now["sec"]))
local time = getTime(true, "yyyy-MM-dd @ hh:mm:ss")
cecho("<pale_turquoise>"..time)
Further, this variant works for those of us with linebreak prompts:
local time = getTime(true, "yyyy-MM-dd @ hh:mm:ss")
if line == "" then -- we've got a linebreak prompt
moveCursorUp()
end
-- Insert at end of line
moveCursor(#getCurrentLine(), getLineNumber())
cinsertText("<pale_turquoise>"..time)
Stat delta calculation and echoing to prompt. Add this to a trigger with "prompt" selected:
myStats = myStats or {}
local tracked = {
"hp",
"mp",
"ego",
"essence",
"nl",
}
local short = {
["hp"] = "h",
["mp"] = "m",
["ego"] = "e",
["essence"] = "xp",
["nl"] = "xp",
}
local out = {}
local vitals = table.deepcopy(gmcp.Char.Vitals)
if not (vitals.hp == "0"
and vitals.mp == "0"
and vitals.ego == "0"
and vitals.pow == "0")
then
for _, stat in ipairs(tracked) do
if myStats[stat] and vitals[stat] and myStats[stat] ~= vitals[stat] then
local delta = tonumber(vitals[stat]) - tonumber(myStats[stat])
local short = short[stat] or ""
local color = "<green>"
if delta < 0 then color = "<red>" end
out[#out+1] = string.format("%s%+d%s", color, delta, short)
end
myStats[stat] = vitals[stat]
end
else
out[#out+1] = "<ansiRed>BLACKOUT!"
end
if myStats.level and myStats.level ~= gmcp.Char.Status.level then
local delta = tonumber(gmcp.Char.Status.level) - tonumber(myStats.level)
local color = "<green>"
if delta < 0 then color = "<red>" end
out[#out+1] = string.format("%s%+d level!", color, delta)
end
myStats.level = gmcp.Char.Status.level
if line == "" then -- we've got a linebreak prompt
moveCursorUp()
end
moveCursor(#getCurrentLine(), getLineNumber())
local out = table.concat(out, "<reset>, ")
if #out > 0 then cinsertText(" "..out) end
local chan = matches[2] or "clt1"
local vnum = gmcp.Room.Info.num
local room = gmcp.Room.Info.name
local area = gmcp.Room.Info.area
local out = string.format("%s I am at v%s (%s) in %s.", chan, vnum, room, area)
send(out, false)
Type "here" or "here channel" (where channel is one of ct, gt, clt, etc etc).
Looks like:
here echo I am at v4133 (Sombre Lane near the construction site) in the City of Magnagora.
Echo room vnums after each room title. Put this in any script.
function echoRoomNums()
local vnum = gmcp.Room.Info.num
local name = gmcp.Room.Info.name:split(" %(")[1]
tempPromptTrigger([[killTrigger(]]..tempBeginOfLineTrigger(name, function()
selectCurrentLine()
local colour = string.format("<%s,%s,%s>", getFgColor())
local text = string.format("<%s>v%s", mmp.settings.echocolour, vnum)
local cmd = string.format([[mmp.gotoRoom("%s")]], vnum)
local hint = "Go to "..vnum
decho(" "..colour.."(")
cechoLink(text, cmd, hint, true)
decho(colour..")")
end)..[[)]], 1)
end
echoRoomNumsHandler = echoRoomNumsHandler or registerAnonymousEventHandler("gmcp.Room.Info", echoRoomNums)
restock.mpackage consists of one alias, script, and trigger group that:
1. Preempts WARES commands by requesting the current rift list via GMCP 2. Interprets the list and indexes it by desc (a bottle of sparkling Golden Tonic) and shortname (goldentonic) 3. Catches the shop wares entries and tells you how much you have in the rift, if any 4. Gives you a single click option to restock (buying your deficit from 2k, or however many they have)
Sometimes colouring is good, so I made this to quickly see (and sometimes ignore) OOC clans with a quick recolouring and reformatting of certain clans. I've included org OOC clans that I was able to find, to add more just follow the Perl regex format to add new clans. Download here.
So, since I had to switch to Mudlet because of the OSX Catalina update awhile back, and had no desire to try and get demonnic's chatbox working (nothing against it, I just felt it was overcomplicated for my needs), I decided to build a chatbox out of the newish Adjustable Container stuff in Mudlet. It's simple, not tabbed, but it fits my needs perfectly. Been using it for a few months, had zero issues.
Screenshot:
Installation Instructions: 1. Create the Windows folder and 3 scripts specified in Scripts Layout below, pasting in the relevant section of code into each. 2. Restart Mudlet. 3. Move and resize to your liking (click-drag top to move, click-drag lower right to resize). You can optionally right click and hit "lock" to lock it in place and remove the green borders.
function win.handleCommChannelText()
local text = ansi2decho(win.stripMXP(gmcp.Comm.Channel.Text.text)) .. "\n"
win.chat:decho(text)
end
function win.stripMXP(str)
return str:gsub("\27%[4z\3.-\4", '')
end
registerAnonymousEventHandler("gmcp.Comm.Channel.Text", "win.handleCommChannelText")
GMCP enable chat code
function win.opencomms()
sendGMCP('Core.Supports.Add ["Comm.Channel 1"]')
end
registerAnonymousEventHandler("gmcp.Char.Name", "win.opencomms")
Comments
Usage: loop <#> <commands separated by ;>
e.g.
loop 15 put spike in hole;get spike from hole
ETA: That won't work without this function, which you can just drop in a script somewhere. It just adds commas to numbers.
Or, if you have a filter function:
A bit of functional programming in Lua:
<pre class="CodeBlock"><code>(?i)^path track (.+)$
If you're in a manse that you've mapped out and linked to the aetherplex, this alias lets you PATH TRACK directly from it. (By going to the aetherplex first, then using the game-side pathing from there.)
^(\d+)(\s+)(Rare|Piece)(\s+)(.+) <--- set to regex
send("CURIOMARKET ADD sell piece " ..matches[2].." FOR 2 credits") <--- change to whatever amount you want to put your pieces up for.
Once the trigger is set up, just do CURIO LIST PIECES.
Then, in an alias:
Estarra the Eternal says, "Give Shevat the floor please."
mytable = {
a=1,
b=2,
c=3
}
And you do
for k,v in pairs(mytable) do
then each time through the loop, k will be the next key (first time a, then b, then c), and v will be the value associated with that key (first time 1, then 2, then 3).
It APPEARS to get more complicated in my keg example, because the values are themselves tables, but just think of v as a variable that will have whatever the appropriate value is.
Crummy Incomplete Influencing Snippets Made In a Haste Without Proper Management of Memory or Coding But Hey They Work
Edit: I don't know what happened in this post, but here it is on PasteBin, too: https://pastebin.com/46ZQXY6M
setRoomName(gmcp.Room.Info.num,gmcp.Room.Info.name)
setRoomArea(gmcp.Room.Info.num,addAreaName(gmcp.Room.Info.area))
Toss this in an alias and it creates a room and sets the area, for when you want to map something like a timequake.
{
blue = 36073,
brown = 11811,
black = 11600,
yellow = 9888,
red = 10509,
steel = 10185,
white = 10457,
purple = 47812,
green = 9985,
crystal = 12652,
wooden = 10992,
}
local exitScript = [[script:sendAll("outr %sbutton", "touch %sbutton", false)]]
function mapperButtons()
if
table.contains(gmcp.Room.Info.details, "the Prime Material Plane") and
table.contains(gmcp.Room.Info.details, "outdoors")
then
for color, room in pairs(colors) do
mmp.tempSpecialExit(gmcp.Room.Info.num, room, exitScript:format(color,color), 20)
end
else
for color, room in pairs(colors) do
mmp.tempSpecialExit(148, room, exitScript:format(color,color), 20)
end
end
end
registerAnonymousEventHandler("mmp link externals", "mapperButtons")
It will only use them to path to bubbles - it won't use buttons as a shortcut.
Just toss it in a script and it's good to go!
function itemAlert()
local addEvent = gmcp.Char.Items.Add
if addEvent.location ~= "inv" then
return
end
for _, checkId in pairs(alertIDs) do
if addEvent.item.id == checkId then
cecho(
"<sky_blue>" .. string.title(addEvent.item.name) .. " has returned to your inventory!"
)
end
end
end
registerAnonymousEventHandler("gmcp.Char.Items.Add", "itemAlert")
Small snippet that lets you watch for things returning to your inventory that might not give a message otherwise, like artifacts resetting after you loaned them out.
I am at v4133 (Sombre Lane near the construction site) in the City of Magnagora.
Ever wanted to send a message to a Discord server webhook? Now you can!
Have fun!
1. Preempts WARES commands by requesting the current rift list via GMCP
2. Interprets the list and indexes it by desc (a bottle of sparkling Golden Tonic) and shortname (goldentonic)
3. Catches the shop wares entries and tells you how much you have in the rift, if any
4. Gives you a single click option to restock (buying your deficit from 2k, or however many they have)
Looks like this:
small chunk of code to maintain a table (sktrack.skills) which stays up to date with current skillsets and skills.
Screenshot:
Installation Instructions:
1. Create the Windows folder and 3 scripts specified in Scripts Layout below, pasting in the relevant section of code into each.
2. Restart Mudlet.
3. Move and resize to your liking (click-drag top to move, click-drag lower right to resize). You can optionally right click and hit "lock" to lock it in place and remove the green borders.
Scripts layout:
Windows code
Chat Window code
GMCP Chat Hook code
GMCP enable chat code