Welcome to the Achaea Forums! Please be sure to read the Forum Rules.

[Mudlet] Code Snippets

TysandrTysandr Posts: 439Member ✭✭✭✭ - Eminent
edited January 20 in Client Help
Purpose: To highlight all captures in a multimatch in a specific color

Requirements: Multimatch trigger, not using 'highlight' checkbox

Code:
local t = multimatches

for i=1, #t do
 local out = {}
 local n = t[i]
 moveCursorEnd()
 moveCursor(0, getLineNumber() - (#t - i))
 if #n > 1 then
   for j=2, #n do
    local v = 1
    while selectString( n[j], v ) ~= -1 do
      table.insert( out, { selectString(n[j], v), #n[j] } )
      v = v + 1
    end
   end
 end
 for i=1, #out do
   local p = out[i]
   local pos = p[1]
   local len = p[2]
   selectSection(pos, len)
   -- potentially use a lookup table for specific positions here
   fg('green')
   deselect()
 end
end

Output:

Sample trigger matched everything between  'Resources' & 'Organisations' and captured all numbers

Nexus: Accents, Autotriggers, Dragon Talismans
"As the child did... without the rope. Then fear will find you again."

RekhyrKyrra
«13

Comments

  • AustereAustere TennesseePosts: 2,193Member @@ - Legendary Achaean
    I'll play:

    function IsTargetted(person)
       if not person then return end
       target = target or "Austere"
       if person == target then 
         return true
       elseif string.findPattern(person, target) then
          return true
       else
          return false
       end
    end
    Uses: Allows matches of partial targets. Target "Aust" would work in the following:

     Austere stands up.
    ^(\w+) stands up\.$

    if IsTargetted(matches[2]) then
    cecho("<cyan>\n\n"..target.. " IS NO LONGER PRONE. HE|SHE IS UP!!\n\n")
    end


    TysandrVadimusesShirszae
  • VadimusesVadimuses Posts: 1,083Member @ - Epic Achaean
    If you ever want to see all the arguments that get passed to an event, define a function like this:

    function eventHandler(...)
      display{...}
    end

    TysandrAustere
  • VadimusesVadimuses Posts: 1,083Member @ - Epic Achaean
    Benchmarking code:

      stopwatch = stopwatch or createStopWatch()
      startStopWatch(stopwatch)

      [complicated code here]

      echo(string.format("Code ran for %ss\n",getStopWatchTime(stopwatch)))





    AustereRom
  • NazihkNazihk Posts: 985Member @ - Epic Achaean
    Austere said:
    I'll play:

    function IsTargetted(person)
       if not person then return end
       target = target or "Austere"
       if person == target then 
         return true
       elseif string.findPattern(person, target) then
          return true
       else
          return false
       end
    end
    Uses: Allows matches of partial targets. Target "Aust" would work in the following:

     Austere stands up.
    ^(\w+) stands up\.$

    if IsTargetted(matches[2]) then
    cecho("<cyan>\n\n"..target.. " IS NO LONGER PRONE. HE|SHE IS UP!!\n\n")
    end


    IIRC, this would match either "Austere" or "Faust". For that reason I prefer to use something like string.starts for this purpose, though you may have to add case handling to it if you use that one, I can't remember if that one is case-specific or not. 

    It can't completely avoid false positives(Hi, Antidas and Antonius), but it can avoid things like "Nazihk" and "Aziik".
    TysandrTorinn
  • AlyxeriAlyxeri Posts: 467Member ✭✭✭✭ - Eminent
    edited January 20
    This wasn't specifically for me, but I know how many use SVO so I made it anyway for someone.

    1. Use SVO?
    2. Hate the gem/veil changes?
    3. Got a chameleon tattoo?
    Alias pattern: ^tcham$

    Alias code:
    local ndbNameList = db:fetch(ndb.db.people)
    local me = gmcp.Char.Status.name
    chamNameList = {}
    for _, tab in pairs(ndbNameList) do
    if tab.name ~= me then
    table.insert(chamNameList, tab.name)
    end
    end
    send("TOUCH CHAMELEON "..chamNameList[math.random(1, #chamNameList)])
    If you want to, you can trigger the cham fading line afterwards to do:
    send("TOUCH CHAMELEON "..chamNameList[math.random(1, #chamNameList)])
    as well.

    What's it do? Simple. It fetches a list of names from ndb's database, from everyone you currently have tracked (noticed 0 lag whatsoever when I ran this, for reference. No worries there!), then touches your chameleon tattoo to a random name from that list.


    TysandrIsmay
  • VadimusesVadimuses Posts: 1,083Member @ - Epic Achaean
    If you want to reset a timer, this is a pretty useful pattern:

      if timeout_timer then killTimer(timeout_timer) end
      timeout_timer = tempTimer(5, function() <code here> end)

    If you call this over and over again before 5s, the timer will never fire. If you don't call it within 5s, it'll fire.


  • VenderVender Posts: 258Member ✭✭✭ - Distinguished
    edited January 20
    function doblink( room, color, duration )
    	local colorn, durationn
    	local r,g,b,br,bg,bb
    	room = tonumber(room)
    	if type(color) == "table" then
    		r,g,b,br,bg,bb = unpack(color)
       end
    	if not color then
    		r,g,b,br,bg,bb = 220,0,0,255,186,23
    	end
    	if not duration then durationn = 5 else durationn = duration end
    
    	highlightRoom(room,r,g,b,br,bg,bb,1,255,255)
    	for i=0.5, durationn do
    		tempTimer( i, function() highlightRoom( room, r,g,b,br,bg,bb, 1, 255, 255 ) end )
    		tempTimer( i+0.5, function() unHighlightRoom( room ) end )
    	end
    	tempTimer( durationn + 1, function() unHighlightRoom( room ) end )
    end
    A room blinker. I use this when I farsee or who b enemy targets and it will blink up the room they are located in. Very useful for PK.

    All credit goes to Tysandr who wrote this in Imperian.

    Locate Enemy Position
    
    local oldEchonums = mmp.echonums
    
    mmp.echonums = function(roomname)
      oldEchonums(roomname)
      local rooms = mmp.searchRoomExact(roomname)
    
      if not next(rooms) then
        echo "?" return nil end
    
      -- transform the kv table into a table of tables for cleaner code.
        -- + perhaps Mudlet in future will give this us anyway, sorted by relevancy
      local dt = {}
      for roomid,room in pairs(rooms) do
        dt[#dt+1] = {name = room, id = roomid}
      end
      jane.target.roomname = roomname
      jane.target.roomid = dt[1].id
      doblink( jane.target.roomid )
      jane.target.area = getRoomAreaName(getRoomArea(jane.target.roomid))
    end
    
    function roomIDExact(rname)
      local rooms = mmp.searchRoom(rname)
      local finalroom = {}
      for k, v in pairs(rooms) do
        if v == rname then
          table.insert(finalroom, k)
        end
      end
      return table.concat(finalroom, ", ")
    end
    
    This is how I get the room id and area and store it within my own system and blink the rooms.
    it's frustration that creates desire
    not the other way around
    unless you let it
    baby, I'll let it
    TysandrVadimusesRekhyr
  • TysandrTysandr Posts: 439Member ✭✭✭✭ - Eminent
    edited January 20
    Purpose: 'string.gsub' but exclude certain words

    Requirements: a table that contains the words to be excluded

    Code:
    s = string.gsnub(s, '(%w+)\.$', 'Tysandr.')
    
    ignorables = { 'mole' }
    
    -- requires 'ignorables' table
    string.gsnub = function(line,pattern,newPattern)
     line = string.gsub(line,pattern,
      function(str)
       if not table.contains(ignorables,str) then
        return newPattern
       end
      end)
     return line
    end

    Output:

    Nexus: Accents, Autotriggers, Dragon Talismans
    "As the child did... without the rope. Then fear will find you again."

  • AntoniusAntonius Posts: 4,550Member @@ - Legendary Achaean

    A couple of simple functions to pad a string with spaces so it matches a set length, truncating when the original string exceeds the specified length:

    function string:padleft(length)
    	if #self > length then
    		return self:substring(1, length)
    	end
    	
    	return string.rep(" ", length - #self) .. self
    end
    
    function string:padright(length)
    	if #self > length then
    		return self:substring(1, length)
    	end
    	
    	return self .. string.rep(" ", length - #self) 
    end
    
    TysandrVadimusesRekhyr
  • VadimusesVadimuses Posts: 1,083Member @ - Epic Achaean
    edited January 20
    Given a list table, returns a string with the values concatenated:

    function concatand(t)
      assert(type(t) == 'table', 'concatand: argument must be a table')

      if #t == 0 then return ''
      elseif #t == 1 then return t[1]
      else
        return table.concat(t, ', ', 1, #t-1) .. ', and '..t[#t]
      end
    end

    Example:

    local t = {'Bob', 'Mary', 'Ann'}
    print(concatand(t))
    -- Bob, Mary, and Ann 


    Tysandr
  • IsmayIsmay Posts: 559Member ✭✭✭✭ - Eminent
    I -love- this thread. You guys are code gods...
  • RekhyrRekhyr Posts: 56Member ✭✭✭ - Distinguished
    edited January 20
    repeating and action using serverside separator for reduced prompt spam.

    ^#(\d+) (.+)$

    local separator = "|"
    local n = tonumber(matches[2])
    
    for i = 1, n / 10, 1 do
      send(matches[3] .. string.rep(separator .. matches[3], 9), false)
    end
    
    if n % 10 ~= 0 then
      send(matches[3] .. string.rep(separator .. matches[3], (n % 10) - 1), false)
    end
    Tysandr
  • RekhyrRekhyr Posts: 56Member ✭✭✭ - Distinguished
    edited January 20
    This thread is lovely.. lots of cool ideas.

    Quality of life lua printf like, when string.format is too much to type every time

    function echof(...)
      echo(string.format(...))
    end
    
    function cechof(...)
      cecho(string.format(...))
    end
    
    ...
    Vadimuses
  • CyrCyr Posts: 89Member ✭✭✭ - Distinguished
    Alright, nothing fancy but a couple of things I get asked about sometimes.

    matching stuff for Charstats

    function thisupdatesbleed()
       bleed = tonumber(string.match(gmcp.Char.Vitals.charstats[1], "%d+"))
    end
    registerAnonymousEventHandler("gmcp.Char.Vitals", "thisupdatesbleed")
    
    Can be used as a base for any of the charstats things although for monks stances/forms or other things with strings you'd have to use a different match (should be able to use "%w+: (%w+)" or something similar, there's a bunch of ways to match

    and then a function that simply returns true if I'm in a party and false if I'm not for reporting purposes:
    function amIinParty()
      local i
      for i = 1, #gmcp.Comm.Channel.List do
        if gmcp.Comm.Channel.List[i].name == "party" then
          return true
        end
      end
      return false
    end


    Dunn tells you, "I hate you."
    SobriquetVadimusesTysandr
  • VadimusesVadimuses Posts: 1,083Member @ - Epic Achaean
    An oldie but goodie - keep the existing table or create a new one if if doesn't exist:

    mytable = mytable or {}


    TysandrRekhyrBrenex
  • TysandrTysandr Posts: 439Member ✭✭✭✭ - Eminent
    Someone wrote a pop-push implementation previously; wonder if it would be short enough to be a snippet.

    Would be very good for this thread.
    Nexus: Accents, Autotriggers, Dragon Talismans
    "As the child did... without the rope. Then fear will find you again."

  • VadimusesVadimuses Posts: 1,083Member @ - Epic Achaean
    edited January 22
    Capture GMCP balances:


    mystats.balance     = gmcp.Char.Vitals.bal == "1" and true or false
    mystats.equilibrium = gmcp.Char.Vitals.eq == "1" and true or false

    Turns the "1" in gmcp into a true/false boolean. You can apply this trick elsewhere to set the variable without a long if.

    TysandrPuxiSobriquet
  • AntoniusAntonius Posts: 4,550Member @@ - Legendary Achaean
    Vadimuses said:
    Capture GMCP balances:


    mystats.balance     = gmcp.Char.Vitals.bal == "1" and true or false
    mystats.equilibrium = gmcp.Char.Vitals.eq == "1" and true or false

    Turns the "1" in gmcp into a true/false boolean. You can apply this trick elsewhere to set the variable without a long if.

    gmcp.Char.Vitals.bal == "1" is already of type boolean, so you don't really need the "and true or false" part in there at all.
  • KeneanungKeneanung Posts: 585Member ✭✭✭✭ - Eminent
    Vadimuses said:
    Capture GMCP balances:


    mystats.balance     = gmcp.Char.Vitals.bal == "1" and true or false
    mystats.equilibrium = gmcp.Char.Vitals.eq == "1" and true or false

    Turns the "1" in gmcp into a true/false boolean. You can apply this trick elsewhere to set the variable without a long if.

    You can also just use
    mystats.balance     = gmcp.Char.Vitals.bal == "1"
    mystats.equilibrium = gmcp.Char.Vitals.eq == "1"
    Tysandr
  • KlendathuKlendathu Eye of the StormPosts: 2,981Member @@ - Legendary Achaean
    edited January 22
    Here's one I use a lot for subbing output from Achaea:
    -- replace line from MUD with colour-tagged string
    creplaceLine = function(str)
    	selectString(line,1)
    	replace("")
    	cinsertText(str)
    end
    It accepts colour arguments, etc, just the same as a cecho, just a quick shorthand thing. Example usage:

    regex trigger: ^You rip the air from the lungs of (\w+) in a single instant\, blood and mucus dripping from h(?:is|er) mouth as (?:|s)he doubles over with hacking coughs\.$
    creplaceLine("<white>[ASPHYXIATE]<reset> "..line)




    Tharos, the Announcer of Delos shouts, "It's near the end of the egghunt and I still haven't figured out how to pronounce Clean-dat-hoo."
    Tysandr
  • VadimusesVadimuses Posts: 1,083Member @ - Epic Achaean
    edited January 22
    That's a pretty useful one actually. Want to submit it to Mudlet?

    re: booleans - yes, but I find it helpful to be explicit in these things, esp. easier for beginners to read code.
  • PyoriPyori Posts: 785Member ✭✭✭✭✭ - Grand Achaean
  • TysandrTysandr Posts: 439Member ✭✭✭✭ - Eminent
    Be careful with this one:

    Purpose: Delete multiple lines below the trigger, up to the prompt.

    Requirements: Know how many lines you want to delete. Uses global variable.

    Code:
    function deleteFull(howMany)
     deleteLine()
     local howMany = howMany or 1
     mydeleter = true
     tempLineTrigger(1,howMany,
       [[
         if not isPrompt() and mydeleter then
          deleteLine()
         else
          mydeleter = false
         end
       ]])
    end

    Nexus: Accents, Autotriggers, Dragon Talismans
    "As the child did... without the rope. Then fear will find you again."

  • AntoniusAntonius Posts: 4,550Member @@ - Legendary Achaean

    Insert into ordered table t all the elements from ordered table nt.

    table.insertAll = function(t, nt)
    	for _, v in ipairs(nt) do
    		table.insert(t, v)
    	end
    end
    
  • TysandrTysandr Posts: 439Member ✭✭✭✭ - Eminent
    Antonius said:

    Insert into ordered table t all the elements from ordered table nt.

    table.insertAll = function(t, nt)
    	for _, v in ipairs(nt) do
    		table.insert(t, v)
    	end
    end
    
    @Antonius, got an Achaean use-case for this one?
    Nexus: Accents, Autotriggers, Dragon Talismans
    "As the child did... without the rope. Then fear will find you again."

  • AntoniusAntonius Posts: 4,550Member @@ - Legendary Achaean
    Tysandr said:
    Antonius said:

    Insert into ordered table t all the elements from ordered table nt.

    table.insertAll = function(t, nt)
    	for _, v in ipairs(nt) do
    		table.insert(t, v)
    	end
    end
    
    @Antonius, got an Achaean use-case for this one?
    I have a lot of functions which generate and return lists of commands for specific things (one for general stuff like stand, vault, parry, one for wielding, one for class-specific offense, etc.), so I use the above function to join those together into a single list to create aliases or queue commands from.
    Tysandr
  • ZekerosZekeros Posts: 25Member
    This sure beats having to waste space having a notepad on the monitor, or even worse, actually writing out aliases on a piece of paper :+1:
  • PyoriPyori Posts: 785Member ✭✭✭✭✭ - Grand Achaean
    People liked it...

    A nicer looking qwho

    Tysandr
«13
Sign In to Comment.