Skip to content

Mudlet Scripting

1246718

Comments

  • edited October 2013
    The only way I know of to preserve order in dictionaries in lua is to make key value pairs actual tuples indexed numerically

    i.e.

    mylist={
        {a, "123"},
        {b, "234"}
    }


    In this table, the keys are not a and b, but rather 1 and 2. Element 1 is the tuple {b, "123"}. That means you have to dereference once to get the items in each element, but it keeps them in order.

    EDIT: There's probably some way to do it with metatables and making a new table class, I guess.
    I am the righteous one... 
    the claims are stated - it's the world I've created 
  • IniarIniar Australia
    wit beyond measure is a Sidhe's greatest treasure
  • MathiausMathiaus Pennsylvania
    I guess I want to then have a table with aff values and have the new table pull from that making it an indexed table, thusly pulling from the new table.
    image
  • How would I code a Trigger in Mudlet to let me know when somebody puts up a shield and aura defenses and when somebody has it done? 

    Also, does anyone know how to make a stance tracker for the Predator profession?
  • MathiausMathiaus Pennsylvania
    edited October 2013
    Get the line, and with the line, do something like:

    Line:
    ^(\w+) puts up (?:his|her) shield.$

    Script:
    Shieldtarget = matches[2]
    if string.find(Shieldtarget, target) == 1 then shield = true end

    That way you only track your target and not everyone doing it.
    image
  • Mathiaus said:
    Get the line, and with the line, do something like: Shieldtarget = matches[2] if string.find(Shieldtarget, target) == 1 then shield = true end That way you only track your target and not everyone doing it.
    Shieldtarget = matches[2]
    if string.find(Shieldtarget, target) == 1 then shield = true end



    This can be simplified to
    if string.find(matches[2],target) then
        shield = true
    end

    I am the righteous one... 
    the claims are stated - it's the world I've created 
  • MathiausMathiaus Pennsylvania
    Lionas said:


    Mathiaus said:

    Get the line, and with the line, do something like:

    Shieldtarget = matches[2]
    if string.find(Shieldtarget, target) == 1 then shield = true end

    That way you only track your target and not everyone doing it.


    Shieldtarget = matches[2]
    if string.find(Shieldtarget, target) == 1 then shield = true end



    This can be simplified to
    if string.find(matches[2],target) then
        shield = true
    end



    True enough, just used to using it for other things.
    image
  • edited October 2013
    You can also shorten some calls like for string.find in some situations.

    "Shieldtarget:find(target) == 1" should work, and I think "matches[2]:find(target) == 1" works as well.

    As far as dealing with un-indexed tables, you can add all the elements to an indexed table and sort them according to their elements.

    Context: "afflictions" is a table of each affliction you can see with "affliction list all" along with all details in their "affliction show [aff]" entry. It's normally stored as affliction[name] = {afflictionDetails} but gets changed to an indexed table and sorted by priority.


    lua display(afflictions["metrazol"])


     metrazol = {

        mental = false,

        physical = true,

        description = "Causes you to be unable to use two of your limbs.",

        curemessage = "You feel a tingling sensation run through your limbs as the paralysis fades.",

        name = "metrazol",

        priority = "1",

        purge = true,

        cure = "maidenhair",

        curetype = "plant",

        diagmessage = "has a paralysed (limbs)."

      }


    function sortedAfflictions()

      local sortedAffTable = {}

      for k, v in pairs(afflictions) do

        if v["priority"] then table.insert(sortedAffTable,v) end

      end

      table.sort(sortedAffTable, function (a,b) return (tonumber(a.priority) < tonumber(b.priority)) end )

      

      return sortedAffTable

    end


    Should be easy enough for you to modify that for your needs.

    Edit: Edited for not-as-ugliness.

    image
  • Thanks guys, I appreciate the help. I'll be sure to ask other complicated stuff.
  • So, this is something of a combination question: when I look at Outrider I see three main routes that are viable - salve pressure using an icecoated spear, tossed axes, nyordian, the smash surge, and limb targetting. Nightshade pressure using xeroderma/botulinum on a tossed axe (this is the only nightshade affliction I think I can deliver with a thrown axe?) a blackened spear, the lacerate surge, and chiltran/other Outrider specific toxins. Preferably I think the nightshade route is most effective when it runs over into  the salve route, though I'm still getting my act together to make that happen coherently and effectively. Either option leading to a shatter kill. And then the final option is bleeding/bloodfreeze, which I've had some success with, but it's difficult to keep someone pinned down that route without bailing on you. Is this all correct? If not, how should I tweak how I am thinking about the class?

    Secondly, and to bring this back on topic: timing axetosses seems like the most essential part of an Outrider's offense. Basically, I'm looking for recommendations for how to code/work an axetoss timer/thrower. Thankfully the balance is consistent at 2 seconds, regardless of axe stats... I roll athletic and don't have a diadem, so surging is faster than my spear attacks, but slower than my axetoss. My initial thought was queue eqbal axetoss however, it seems like I'll need the ability to switch toxins on the fly, additionally, this method gets wrecked by touch web or the person moving... so making my thoughts into a question: does anyone have a recommendation on how to handle this in Lua? And at least get me started? My coding ability is crap, so making it straightforward would be appreciated...
  • Aliases or macros to throw each axe with no fancy coding. That's what I would do. And did, it my time as Outrider ages ago.

  • Got it, thank you... so then my other question is, am I thinking about all of this correctly? Basically focus on nightshade/salve afflictions and work towards a shatter kill? Add in enough other afflictions to keep someone in the room with me and just hope for the best?
  • MathiausMathiaus Pennsylvania

    Not entirely sure what you're asking, since there is a lot there to code by the sounds of it.

    Temp Timers help with various things instead of making a timer and using enableTimer("timer")/disableTimer("timer"), by doing tempTimer(#, [[send("command")]]) where # is in seconds.

    Also, if you do go by the enable/disable route, it might work more since you can then disable it when need be (web, moved, etc) from what you described.

    Otherwise, hopefully someone with experience an outrider can help you out.

     

    image
  • -Don't ignore limb damage for setting up shatter. It's pretty key and knowing how people (G-bot) reacts to limb damage you can go from almost set up to slam dunk in about 2-3 balances.

    -Axes can be timed inside your client to throw axes (this is dangerous because they can hinder you or turtle and you're just derping along). You're probably better off getting the 'feel' of the timing and knowing when to throw. Also code yourself a message that says "Axe is about to hit" so you can get ready to capitalize on it. So many outriders (nyuck nyck) have wasted it because the 4 axes hit and they're doing something entirely unrelated to the affs they just gave me.

    -Highlights and echoes. Update things that are important to pushing what you want. I use the crap out of these especially with defiler since I have to change my strategy based on how derp-wagon entropy panned out.
  • So that leaves me another question: how do you guys think through limb damage? Is it best to do an alias or something to target limbs and change as necessary? Is there a particular way I should be handling this? Sorry for being newb status and asking a ton of basic questions right now, I am just new to all of this and I'm finally getting to the point where I think my character is getting developed enough to be more viable on my own without having to hide behind some of the better AM combatants all the time...
  • I'm lazy. I use the queue system to change my limb targets. One alias per limb. I highlight my opponent parrying with the limb I targeted and the fact it was parried. Then, because Azefel is awesome, there's an ascii man who has limb count hits per limb that I can keep track of visually if I want to push more than one. Targetting arms is fun because it prevents people from chain turtling, because that's apparently how the 'upper crust' pks.

    33%, 66% messages are your friend. They let you know exactly when you're going to break. Track them and code them to determine # of hits to break.
  • AmbroseAmbrose Texas
    edited October 2013
    Awesome, thank you for the help! Not gonna lie, I kind of enjoy getting pummeled by you and Kryss... I'm hoping each one is a learning experience that I get a little better on each time....
  • MathiausMathiaus Pennsylvania

    I have my limb targeting set from F9-F12, each hitting a limb with dsl/fsl/rsl etc based on if statements, and alt+F9-F12 incase I need to do just on slash on the leg to match up leg count.

    I've found it best to have a way to count how many hits your doing to each limb all together, add the hit counts between tremble and bruised, and have the sum of current hits + tremble/bruised hits = break limit for the limb. Just have to code a way to track it and such.

    Best thing to do about limbs too is have it check to see if you hit and have timers made that disable/enable when you hit the limb, reseting the timer back to 59 seconds. That way it'll reset the limb count on that limb if you haven't hit it in that time, that way your system isn't stacking 40 hits on one limb.

    When you hit too, since Imperian is set up weird for hits, have the hit line add to limb count and have the parries/rebounding add negative counts to the limbs, that way it's keeping proper counts too. If you know how to use multilines, it'll help a lot more in this aspect.

    image
  • IniarIniar Australia
    edited October 2013
    Mudlet doesn't do timers very well. Or triggers for that matter.

    if you're gonna create a timer system, make sure you invoke timers with names unless you're absolutely sure you'll never, ever, ever, ever want to stop that thing from going through.

    ala,
    local axe1 = axe19819

    axe1.."t" = tempTimer( #, yadayadayada )

    if you ever need to kill it, you can invoke it by name ie. killTimer( "axe19819t" )

    the only things I don't used named timers for are -after- someone smokes linseed or applied fenugreek, pmuch.

    Also, multilines are a bad idea because of the spammagedon that is Imperian.

    You point an imperious finger at Iniar, invoking the curse of breach.
    His curseward has failed!

    Is no guarantee. It can look like anything, including...

    You point ... breach.
    You gain 200 mana.
    You feel yourself slipping into the oblivion of Imperian spam.
    You lose 10 health.
    The area drains your awesomeness.
    His curseward has failed!

    What I do:
    Any line that is important, capture the variables in a table with a function ( mine is inbuff( uniqueid, arg2, arg3, arg4, etc etc ) )
    On the prompt, interpret.

    After my prompt, I may end up with
    buffer = {
    { "toxin", "me", "", "aconite" },
    { "dsl", "me", "Ambrose", "right arm" },
    { "toxin", "me", "", "mazanor" },
    { "dsl", "me", "Ambrose", "right leg" },
    { "parry", "", "", "1" },
    { "dsl", "Ahkan", "Mathiaus", "left arm" },
    { "parry", "", "", "1" },
    { "dsl", "Ahkan", "Mathiaus", "left arm" },
    { "parry", "", "", "1" },
    }

    Because it's inserted sequentially, you can process it sequentially so a (silly) generic message like 'he parries the attack with a deft maneuver' doesn' trip you up.

    local targt = ""
    local toxin = ""
    local affs = {}

    for i=1, #buffer do

    if buffer[i][1] == "dsl" then
    if me then
    targt = buffer[i][3]
    if toxin ~= ""/nil then
    revlookup toxin->aff
    add to aff table (who, what toxin)
    toxin = ""
    if buffer[i][4] ~= ""/nil then add limb count end 
    else
    targt = ""
    end
    elseif buffer[i][1] == "parry" then
    if targt == ""/nil then -- don't care
    else
    table.remove( last of aff table )
    limbcount = limbcount - 1
    end
    elseif buffer[i][1] == "toxin" then
    toxin = buffer[i][4]
    end

    end

    (something like that)

    The only (quite valid) reason of doing it this way is so it won't ever matter how many lines of prose Garryn puts in between your desiredmessage1 and desiredmessage2, you can always track it quite reliably if you flag your variables correctly. Even if he decides to change it drastically, you can always change the way you interpret the message in that one location. Finally, you get to interpret all your multiline triggers in one location. :(

    E: Manual is the best. For limbs.

    E: Also,

    learn to use locals for tables/values you want to interpret

    local skill = buffer[i][1]
    local target = buffer[i][3]

    if skill == "dsl" then -- do things end

    so when your buffer things changes drastically, you won't have to propagate your changes through the interpretation. You simply change the top of the script:

    local skill = buffer[i][200]
    wit beyond measure is a Sidhe's greatest treasure
  • @Iniar: I've not seen that problem with lines coming in out of order but then again I use lots of multiline triggers that capture the next several lines as wildcards to check for rebounding/parry/third party afflict/cure messages/etc.
  • I deal with things similarly to Cassius. You can either have a multiline for each possible thing that can happen(Pike parry or defend or whatever) or you can capture a blank linespacer in a multiline after it and look back at it in the trigger's code.
    image
  • Ambrose said:
    So that leaves me another question: how do you guys think through limb damage? Is it best to do an alias or something to target limbs and change as necessary? Is there a particular way I should be handling this? Sorry for being newb status and asking a ton of basic questions right now, I am just new to all of this and I'm finally getting to the point where I think my character is getting developed enough to be more viable on my own without having to hide behind some of the better AM combatants all the time...I'm
    I'm old school and lazy. I have highlights for hits and parries and rebounding and I count in my head. Frankly, I'm sure that this is how most experienced fighters end up counting it if they're not going full out KillButton. 

    I originally wrote a complicated limb-tracker as a Predator, only to find that I never actually looked at it because I was tracking in my head. Now I just generally skip the middleman and count entirely in my head when I play a limb class.

    "On the battlefield I am a god. I love war. The steel, the smell, the corpses. I wish there were more. On the first day I drove the Northmen back alone at the ford. Alone! On the second I carried the bridge! Me! Yesterday I climbed the Heroes! I love war! I… I wish it wasn’t over."

  • I am the righteous one... 
    the claims are stated - it's the world I've created 
  • This is kind of a laziness and inexperience thing, I am building a shield/rebounding tracker for pierce/deluge purposes. Does anyone have all the lines for shield/rebound breaking, razing, piercing, etc. that I can get?
  • AzefelAzefel Singapore
    edited November 2013
  • edited November 2013

    function sound.alarm(length, tone)

      local length = tonumber(length) or 4

      local tone = "C:\windows\media\Windows Message Nudge.wav"

      for i = 0, length, 0.4 do

        tempTimer( i, [[playSoundFile([=[C:\windows\media\Windows Message Nudge.wav]=])]] )

      end

    end

    What's the right way to replace the double nested file location with the contents of the tone variable? Tried a few things, none of which worked.

    Edit: Solution:

    function sound.alarm(length, tone)

      local length = tonumber(length) or 4

      local tone = [[C:\windows\media\Windows Message Nudge.wav]]

      for i = 0, length-1, 1 do

        tempTimer(i, function() playSoundFile(tone) end)

      end

    end

    image
  • MathiausMathiaus Pennsylvania

    I was wondering if anyone had the old minimapper script from this link:

    http://www.imperian.com/forum/mudlet-scripts

    for putting the ingame map in the corner.

    image
  • Kind of sloppy, and you might already be using the mapper namespace, but:

    ^mapshow$

    mapper = Geyser.Mapper:new({

    name = "mapper",

    x = "77%", y = "51%",

    width = "22%", height = "49%"

    })


    You could drop it in an init script to have it done when you start up, but I've got it aliased ATM for some reason.

    http://oi41.tinypic.com/2e1w0ma.jpg

    image
  • edited November 2013
    Voting system for Mudlet.

    Just right click and save to your C:\Users\<insert user name>\AppData\Local\Mudlet folder as Vote.xml, then install through Mudlet Package Manager.

    If you already use downloadFile and have an event handler for sysDownloadDone(like for TrueHonours), it'll probably be better if you add the code from mine to yours, instead of having two scripts handling that same event(when I tested it as a separate script to my truehonours script, it was causing the voting to get processed three times). If you don't know how to do this, pastebin your sysDownloadDone handling script and I can add the code for you.

    If anyone sees any obvious mistakes that I've made, or knows of a way to make two sysDownloadDone eventhandlers not act weird, lemme know.
    image
  • edited November 2013
    Here's my lua voting alias for CMUD (it uses socket.http). If you're willing to install the extra library, it removes the need for a completion callback.

    ETA: I know this is the mudlet thread. I posted it here because it's lua, so assuming you have socket.http installed where mudlet can find it, this will work.
    EDIT 2: You could also use luacurl, which is what I use for truehonors
    EDIT 3: Added links

    if not http then http = require("socket.http") end
    print("Connecting to grab info...")
    local page = http.request("http://www.topmudsites.com/vote-avasyu.html")
    local pzzzqaaz = string.match(page,'<input name="pzzzqaaz" type="hidden" value="(%x+)">')
    if pzzzqaaz then print("got pzzzqaaz") end
    local votehash = string.match(page,'<input type="hidden" name="votehash" value="(%x+)">')
    if votehash then print("got votehash") end
    local mudid = string.match(page,'<input type="hidden" name="mudid" value="(%d+)">')
    if mudid then print("got mudid") end
    print("Have info, voting now...")
    local r, c = http.request("http://www.topmudsites.com/vote.php","&do=in" .. "&pzzzqaaz=" .. pzzzqaaz .. "&mudid=" .. mudid .. "&votehash=" .. votehash)
    if c == 301 then
      print("Voting successful.")
      send("voted")
    else
      print("Voting failed, error code " .. c)
    end
    I am the righteous one... 
    the claims are stated - it's the world I've created 
Sign In or Register to comment.