[Mudlet] Code Snippets

edited January 2018 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

"All we have to decide is what to do with the time that is given to us."

«13

Comments

  • AustereAustere Tennessee
    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\.$<br><br>if IsTargetted(matches[2]) then<br>   cecho("<cyan>\n\n"..target.. " IS NO LONGER PRONE.  HE|SHE IS UP!!\n\n")<br>end


  • If you ever want to see all the arguments that get passed to an event, define a function like this:

    function eventHandler(...)<br>&nbsp; display{...}<br>end<br>

  • Benchmarking code:

    &nbsp; stopwatch = stopwatch or createStopWatch()<br>&nbsp; startStopWatch(stopwatch)<br><br>&nbsp; [complicated code here]<br><br>&nbsp; echo(string.format("Code ran for %ss\n",getStopWatchTime(stopwatch)))





  • 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\.$<br><br>if IsTargetted(matches[2]) then<br>   cecho("<cyan>\n\n"..target.. " IS NO LONGER PRONE.  HE|SHE IS UP!!\n\n")<br>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".
  • edited January 2018
    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?
    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)])
    Alias pattern: ^tcham$<br><br>Alias code:<br>
    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.


  • If you want to reset a timer, this is a pretty useful pattern:

    &nbsp; if timeout_timer then killTimer(timeout_timer) end<br>&nbsp; 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.


  • edited January 2018
    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.
    spread positivity
  • edited January 2018
    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:

    "All we have to decide is what to do with the time that is given to us."

  • 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
    
  • edited January 2018
    Given a list table, returns a string with the values concatenated:

    function concatand(t)<br>&nbsp; assert(type(t) == 'table', 'concatand: argument must be a table')<br><br>&nbsp; if #t == 0 then return ''<br>&nbsp; elseif #t == 1 then return t[1]<br>&nbsp; else<br>&nbsp;&nbsp;&nbsp; return table.concat(t, ', ', 1, #t-1) .. ', and '..t[#t]<br>&nbsp; end<br>end

    Example:

    <p>local t = {'Bob', 'Mary', 'Ann'}</p><p><br></p><p>print(concatand(t))</p><p><br></p>-- Bob, Mary, and Ann&nbsp; 


  • I -love- this thread. You guys are code gods...
    Give us -real- shop logs! Not another misinterpretation of features we ask for, turned into something that either doesn't help at all, or doesn't remotely resemble what we wanted to begin with.

    Thanks!

    Current position of some of the playerbase, instead of expressing a desire to fix problems:

    Vhaynna: "Honest question - if you don't like Achaea or the current admin, why do you even bother playing?"


  • edited January 2018
    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
  • edited January 2018
    This thread is lovely.. lots of cool ideas.

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

    <div>function echof(...)
    </div><div>  echo(string.format(...))
    </div><div>end
    
    function cechof(...)
      cecho(string.format(...))
    end
    
    ...</div>
  • 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."
    (Party): You say, "Bad plan coming right up."
  • An oldie but goodie - keep the existing table or create a new one if if doesn't exist:

    mytable = mytable or {}


  • 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.
    "All we have to decide is what to do with the time that is given to us."

  • edited January 2018
    Capture GMCP balances:


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

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

  • Vadimuses said:
    Capture GMCP balances:


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

    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.
  • Vadimuses said:
    Capture GMCP balances:


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

    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"<br>mystats.equilibrium = gmcp.Char.Vitals.eq == "1"
  • KlendathuKlendathu Eye of the Storm
    edited January 2018
    Here's one I use a lot for subbing output from Achaea:
    <div>-- replace line from MUD with colour-tagged string
    creplaceLine = function(str)
    <span>	</span>selectString(line,1)
    	replace("")
    	cinsertText(str)
    <span style="background-color: transparent; color: inherit; font-size: inherit; font-family: "lucida grande", "Lucida Sans Unicode", tahoma, sans-serif;">end</span></div>
    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."
  • edited January 2018
    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.
  • 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

    "All we have to decide is what to do with the time that is given to us."

  • 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 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?
    "All we have to decide is what to do with the time that is given to us."

  • 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.
  • 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:
Sign In or Register to comment.