Skip to content

Mudlet Scripting

191012141518

Comments

  • Was working for me o.O - Are you using the delta release?
    image
  • Yup. Maybe it's just an issue with Windows 7 or something. I know I've seen other people mention having the same issue.
    image
  • IniarIniar Australia
    edited March 2015
    Something to share and maybe some code refinement if you can offer it:

    if class == "Deathknight" then

    local out = ""

    local f = {}

    local preSize,postSize,pointer = 0,0,0

    local style = {

    ["Rasping"] = 2,

    ["Chuckling softly"] = 19,

    ["In quiet undertones"] = 500,

    ["Steel in his voice"] = 13,

    ["Chuckling sinisterly"] = 16,

    ["Booming with malicious laughter"] = 88,

    }

    for k,v in pairs(style) do

    preSize = preSize + v

    end

    for k,v in pairs(style) do

    postSize = postSize + math.ceil(preSize/v)

    local t = {sn = tostring(k), pr = math.ceil(preSize/v)}

    table.insert(f,t)

    end

    table.sort(f,function (k1, k2) return k1.pr > k2.pr end)

    local go = math.random(postSize)

    for i=1,#f do

    pointer = pointer + f[i].pr

    if go <= pointer then

    out = f[i].sn

    break

    end

    end


    local str = ""

    str = "open bevor"..sp

    str = str.."say ("..out..") "..matches[2]..sp

    str = str.."close bevor"

    send(str)

    else

    send(str)

    end


    50,000 runs produces:


    {

      Rasping = 35138,

      ["Steel in his voice"] = 5531,

      ["Chuckling sinisterly"] = 4537,

      ["Chuckling softly"] = 3684,
      ["Booming with malicious laughter"] = 889,

      ["In quiet undertones"] = 221,

    }


    I went through a round-a-bout process because I wanted to be able to add further styles without a floor effect of '1' necessitating manual (or even scripted) re-adjustment of every existing value. Any code improvements would be appreciated.

    wit beyond measure is a Sidhe's greatest treasure
  • IniarIniar Australia
    And... super appropriate proc

    You open the bevor of your plate helm.
    Chuckling sinisterly, you say, "How does my market ad go again? He doesn't..."
    You quickly close the bevor of your plate helm.
    wit beyond measure is a Sidhe's greatest treasure
  • edited April 2015
    How does one go about setting up Mudlet to use a profile stored in Dropbox? I'm going between three computers now and keeping the system up to date has become a headache.
    無駄だ!無駄無駄無駄無駄無駄無駄無駄無駄無駄無駄無駄無駄!ザ・ワールド!時よ止まれ!くらえ!そして、時は動き出す。
    image
  • I think there are advanced ways to do it within Mudlet to autodownload from db at load; however, I did it the easy way and just used virtual folder/links with the dropbox sync folder on each location and kept the profile folders sync'd.  Seemed to work well though I don't have it set that way anymore.
  • I can't figure out where Mudlet keeps its profiles, is it within the application package itself? I'll try dropping the whole thing in there.
    無駄だ!無駄無駄無駄無駄無駄無駄無駄無駄無駄無駄無駄無駄!ザ・ワールド!時よ止まれ!くらえ!そして、時は動き出す。
    image
  • No. It depends on your OS. For windows its in the User directory sub folders.

    This link talks about a similar approach to what I did: http://forums.mudlet.org/viewtopic.php?f=9&t=2157
  • MathiausMathiaus Pennsylvania
    For Windows you're looking for .config folder under your user name with your set profiles. You can find it in your local drive through documents and settings.
    image
  • IniarIniar Australia
    I didn't realize how dependent my basher was on gmcp, until today. I had turned off all my triggers for the basher, and the darned thing still worked near perfectly. :/
    wit beyond measure is a Sidhe's greatest treasure
  • Iniar said:

    I didn't realize how dependent my basher was on gmcp, until today. I had turned off all my triggers for the basher, and the darned thing still worked near perfectly. :/

    Until you follow someone.
  • Cassius said:

    Iniar said:

    I didn't realize how dependent my basher was on gmcp, until today. I had turned off all my triggers for the basher, and the darned thing still worked near perfectly. :/

    Until you follow someone.
    That's because you don't automatically LOOK in a new room when you are following someone, so you don't get the GMCP update. If you set it up so you "looked" in a new room, your basher should still work.
  • Ultrix said:

    Cassius said:

    Iniar said:

    I didn't realize how dependent my basher was on gmcp, until today. I had turned off all my triggers for the basher, and the darned thing still worked near perfectly. :/

    Until you follow someone.
    That's because you don't automatically LOOK in a new room when you are following someone, so you don't get the GMCP update. If you set it up so you "looked" in a new room, your basher should still work.
    I do do that. Gagging the second room look is not fun. It's really annoying. I filed an IDEA awhile ago and it also came up in another thread recently.
  • Here is a spinoff on Iniar's script where you get a different prefix when you say something. This one is a bit simpler though and will give you a random prefix every time you say something. I've included a few example prefixes. By just filling in more values in the voices table, in the same way I've done, you'll get even more prefixes that the alias will choose from.


    Alias pattern:
    ^(say|') ?(.+)$


    Alias script:
    local voices = {
    "chuckling",
    "smiling",
    "jumping up and down",
    }
    local voice = voices[math.random(1,#voices)]
    send("say (" .. voice .. ") " .. matches[3])



    Enjoy!

  • Hello,

    I'm posting here because I'm new to coding and trying to get the hang of gmcp.

    What I'm trying to do right now is track targets as the areas I'm starting to get into have different ones and aren't just simple horde, undead, spirit type anymore. So I started looking into gmcp as I heard that would be the easiest way to capture them.

    When I do lua gmcp.Char.Items.List I get this..




    {
    location = "room",
    items = {
    {
    id = "1152",
    attrib = "m",
    name = "a large black spider",
    icon = "animal"
    },
    {
    id = "1151",
    attrib = "m",
    name = "a large black spider",
    icon = "animal"
    },
    {
    id = "261206",
    attrib = "m",
    name = "a savage grey wolf",
    icon = "animal"
    }
    }
    }

    The issue I am having right now, is how to go about adding the target names into a table and having my basic attack alias pull from that table. Eventually I will want to prioritize targets based on aggression and strength etc but for now, I'm just happy with capturing and not having to do target rat, target bird, target chipmunk etc.

    Any help is greatly appreciated.

    -Halse
  • Hello,

    I'm posting here because I'm new to coding and trying to get the hang of gmcp.

    What I'm trying to do right now is track targets as the areas I'm starting to get into have different ones and aren't just simple horde, undead, spirit type anymore. So I started looking into gmcp as I heard that would be the easiest way to capture them.

    When I do lua gmcp.Char.Items.List I get this..

    The issue I am having right now, is how to go about adding the target names into a table and having my basic attack alias pull from that table. Eventually I will want to prioritize targets based on aggression and strength etc but for now, I'm just happy with capturing and not having to do target rat, target bird, target chipmunk etc.

    Any help is greatly appreciated.

    -Halse


    As a general matter, most creatures in an area will respond to a generic type of keyword -- like, the bashable animals in Treslein's keep will respond to the "creature" keyword.

    Having said that, if you are trying to make a simple basher that tracks your targets on a per area basis, you may want to make use of the gmcp.Room.Info.area variable, as that will tell you what area you are in. From there, you can have a table that you can save when you exit the game (table.save), and load when you connect to the game (table.load) that will keep track of the various targets that are in the area.

    A more complex basher would take advantage of the mob name field (e.g., "a large black spider") and track the names for each area. You could then make use of the gmcp events for when there is a bashable creature in the room (or when one enter/leaves the room) via the gmcp.Char.Items.List.location = "room" ; gmcp.Char.Items.Add; and gmcp.Char.Items.Remove events.

  • IniarIniar Australia
    Anyone know how to fix the voting script?
    wit beyond measure is a Sidhe's greatest treasure
  • edited May 2015
    They changed up the POST form a little again meaning old vote scripts won't work.

    Replace the relevant part of your downloaded_file script:

    elseif filename:match("votePage", 1, true) then

    cecho("<white>.")

    io.input(filename)

    local s = io.read("*all")

    cecho("<white>.")

    local zq = string.match(s,'<input name="zq" type="hidden" value="(%x+)">')

    cecho("<white>.")

    local mudid = string.match(s,'<input type="hidden" name="mudid" value="(%d+)">')

    cecho("<white>.")

    local votehash = string.match(s,'<input type="hidden" name="votehash" value="(%x+)">')

    cecho("<white>.")

    -- local votestring = "http://www.topmudsites.com/vote.php?" .. "&do=in" .. "&oldhash=" .. oldhash .. "&zq=" .. zq .. "&mudid=" .. mudid .. "&votehash=" .. votehash

    local votestring = "http://www.topmudsites.com/vote.php?" .. "&do=in" .. "&zq=" .. zq .. "&mudid=" .. mudid .. "&votehash=" .. votehash

    cecho("<white>.")

    downloadFile(getMudletHomeDir().."/voteDone.html", votestring)

    image
  • So mine is this now and it has a syntax error somewhere I'm not spotting:

    function downloaded(_, filename)

    if not io.exists(filename) then return end

    elseif filename:match("votePage", 1, true) then

    cecho("<white>.")

    io.input(filename)

    local s = io.read("*all")

    cecho("<white>.")

    local zq = string.match(s,'<input name="zq" type="hidden" value="(%x+)">')

    cecho("<white>.")

    local mudid = string.match(s,'<input type="hidden" name="mudid" value="(%d+)">')

    cecho("<white>.")

    local votehash = string.match(s,'<input type="hidden" name="votehash" value="(%x+)">')

    cecho("<white>.")

    -- local votestring = "http://www.topmudsites.com/vote.php?" .. "&do=in" .. "&oldhash=" .. oldhash .. "&zq=" .. zq .. "&mudid=" .. mudid .. "&votehash=" .. votehash

    local votestring = "http://www.topmudsites.com/vote.php?" .. "&do=in" .. "&zq=" .. zq .. "&mudid=" .. mudid .. "&votehash=" .. votehash

    cecho("<white>.")

    downloadFile(getMudletHomeDir().."/voteDone.html", votestring)

    end

    end 

    無駄だ!無駄無駄無駄無駄無駄無駄無駄無駄無駄無駄無駄無駄!ザ・ワールド!時よ止まれ!くらえ!そして、時は動き出す。
    image
  • IniarIniar Australia
    Rasca said:
    So mine is this now and it has a syntax error somewhere I'm not spotting:

    function downloaded(_, filename)

    if not io.exists(filename) then return end

    elseif filename:match("votePage", 1, true) then

    cecho("<white>.")

    io.input(filename)

    local s = io.read("*all")

    cecho("<white>.")

    local zq = string.match(s,'<input name="zq" type="hidden" value="(%x+)">')

    cecho("<white>.")

    local mudid = string.match(s,'<input type="hidden" name="mudid" value="(%d+)">')

    cecho("<white>.")

    local votehash = string.match(s,'<input type="hidden" name="votehash" value="(%x+)">')

    cecho("<white>.")

    -- local votestring = "http://www.topmudsites.com/vote.php?" .. "&do=in" .. "&oldhash=" .. oldhash .. "&zq=" .. zq .. "&mudid=" .. mudid .. "&votehash=" .. votehash

    local votestring = "http://www.topmudsites.com/vote.php?" .. "&do=in" .. "&zq=" .. zq .. "&mudid=" .. mudid .. "&votehash=" .. votehash

    cecho("<white>.")

    downloadFile(getMudletHomeDir().."/voteDone.html", votestring)

    end

    end 


    wit beyond measure is a Sidhe's greatest treasure
  • edited May 2015

    Trying to make a table of demons.

    So far I have a script demons = {

    "Skyrax",

    "Rixil",

    "Eerion",

    "Arctar",

    "Scrag",

    "Pyradius",

    "Dameron",

    "Palpatar",

    "Nin'Kharsag",

    "Istria",

    "Marduk",

    "Belial",

    "Buul",

    "Cadmus",

    "Piridon",

    "Danaeus",

    "Lyncantha",

    "Hecate",

    "Golgotha"

    }


    If I see, "You focus upon your pact and a terrifying visage of Scrag, tender of the bloodleech pool appears briefly in" for example, I want to table.remove scrag. When I see "You are again unable to unleash Scrag" I need to table.insert. 


    I also need to factor in "You are again able to unleash a demon." to set demonbalance = 1.


    This way if shield = false and taint = 10 then I can do if table.contains(demons, pyradius) unleash pyradius, elseif table.contains (demons, scrag) unleash scrag [these are just examples]. I'm just not sure how to go about all of this even though I know what it is I need to accomplish.

    (Ring): Lartus says, "I heard Theophilus once threw a grenade and killed ten people."
    (Ring): Lartus says, "Then it exploded."

    (Ring): Zsetsu says, "Everyone's playing checkers, but Theophilus is playing chess."
  • IniarIniar Australia
    edited May 2015
    This is one way to do it...

    overall_balance = overall_balance or 1

    Message for return of overall balance
    You are again able to unleash a demon.

    overall_balance = 1

    Message for unleash of -any- demon
    ^You focus upon your pact and a terrifying visage of (\w+) appears (briefly) in front of (\w+), wreathed in flames\.
    ^You focus upon your pact and a terrifying visage of (.*), (.*) appears briefly in front of (\w+), wreathed in flames\.

    matches[2] -> name of the demon
    matches[3] -> throwaway
    matches[4] -> target

    overall_balance = 0
    table.remove(my_demons,table.index_of(my_demons,matches[2]))

    Personally, I have a great dislike of using indexed tables (tables using [1],[2],[3]). 
    • I cannot simply call up the value with a straight lookup - my_demons[matches[2]] = ?
    • There can be multiples of the same 'value' - a look up using table.index_of is non-unique
    • table.index_of only returns the first true position... if there are subsequent valid positions, it will not be returned, and it may not be readily apparent to you that there are 6 Scrags in your list.
    There are only two times when I would use an indexed list... when I need them to be ordered, and when you need the values to be concatenated easily. In this situation I would say to you... think about the underlying problem... You have two separate issues - one is to track balances, and one is to unleash demons based on a given preference, if and only if you have both overall and individual balance. 

    nb: be aware that Golgotha in this capture pattern is Jy'Barrak Golgotha

    Edit:

    Supposing one elaborates on the problem(s) at hand...

    (1) tracking balances of demons
    (2) choosing a demon based on a list (preference/priority)
    (3) allowing (2) to be fulfilled only if (1) allows each individual choice

    (1) and (2) should be easily achieved by a novice:

    (1) ... 
    • if message is that specific-balance is true, then specific-balance is true
    • if message is that overall-balance is true, then overall-balance is true
    • if message is that specific-balance is just consumed, then specific-balance is false/0 and overall-balance is false/0
    • if message is that attempted unleash failed, then specific-balance is false/0
    • if message is that attempted unleash failed because overall-balance is false, then overall-balance is false
    (2)

    my_priority_unleash = {
    "a",
    "b",
    "c",
    }

    (3)
    There are multiple ways to implement (3)... for example...

    if scrag_balance == 1 then unleash scrag
    elseif pyradius_balance == 1 then unleash pyradius
    elseif golgotha_balance == 1 then unleash golgotha

    This is simply a linear selection process. The best thing about this is that it offers you the granularity of choosing when and where to unleash... For example, we can elaborate...

    if my_health_is_low and arctar_balance == 1 then unleash arctar at me
    elseif enemy_taint < 20 and incinerate == 1 and pyradius_balance == 1 then unleash pyradius
    elseif golgotha_balance == 1 then unleash golgotha etc etc 

    This is excellent in terms of maximising your selection criteria, but is ponderous to code.

    Then you have the alternate method of simply automating selection down a list of things...

    for i=1,#my_list do
    local demon_to_choose = my_list[i]
    if balances[demon_to_choose] then
    unleash this demon
    break
    end
    end

    So what we all want to achieve is a way to intermarry the two... to maximize selection and minimize coding

    The way I personally do this is to have three components, in the short term, lengthy to code, in the long term, extremely flexible and easy to extend.

    Part A. Track the balances easily.

    summoner.balances.Hecate = summoner.balances.Hecate or true

    Part B. Have my default list, and create a generic selector

    summoner.queue_list = {
    "Belial",
    "Golgotha",
    "Hecate",
    "Pyradius",
    }

    function choose_demon(list)
    local t = table.deepcopy(summoner.queue_list)
    if list then t = table.deepcopy(list) end
    for i=1,#t do
    local demon = t[i]
    if summoner.balances[demon] then
    return demon
    end
    end
    end

    Part C. Modify the basic list based on your conditions/situation.

    local c = table.deepcopy(summoner.queue_list)
    if my_target_has_tree then
    table.insert(c,1,"Lyncantha")
    end
    if in_my_room("Kryss") and get_profession("Kryss","Deathknight") then
    table.insert(c,1,"Scrag")
    end
    if my_hp/my_max_hp <= 0.3 then 
    table.insert(c,1,"Arctar")
    table.insert(c,1,"Arctar Dameron") -- this I can use to parse later to cast Arctar if Dameron is true, but requires that the base selector is modified!
    end
    local demon = choose_demon(c)

    Why so elaborate?
    1. Making sure that I use deepcopy allows me to retain the original order of summoner.queue_list no matter where I am. I modify only copies of it.
    2. I can construct multiple selection criteria within a very fast schema.
    3. I can even opt to submit a completely different queue to summoner.queue_list by simply passing a new list to choose_demon... choose_demon(summoner.affliction_queue)
    4. I can modify -these- new lists with impunity using the same schema above.
    5. I can ditch any schema with impunity knowing that my selector will default to my original list.
    6. My balance tracking is completely isolated from my selection criteria - including both priority and conditional selection.
    7. Etc etc etc. While some people (aka Khizan) scoff at my 'codiness', without these constructs I would never have created and tested over 16 summoner affliction queues without tearing out my hair... for me it is as simple as going, let's move these things up and these things down, but also include that fact that if they are off focus but also have hellsight and just smoked a linseed, let's do C instead. And we'll make that a number 2 priority secondary only to saving my life with a self-danaeus unleash, but superior to arctar unleash. A situation as complex as that can be handled with 6 lines of code without disrupting your 'default' queue.


    wit beyond measure is a Sidhe's greatest treasure
  • I understood half of that.

    A for effort. Thanks.
    (Ring): Lartus says, "I heard Theophilus once threw a grenade and killed ten people."
    (Ring): Lartus says, "Then it exploded."

    (Ring): Zsetsu says, "Everyone's playing checkers, but Theophilus is playing chess."
  • A priority queue is pretty much ideal for this. You'll probably find it much more elegant than manually shifting things around in the table. It'd be a similar concept (run a function to update the priorities of the items in your queue), but has far fewer moving parts and eliminates all the table manipulations. Basically, this is a pretty common problem set, and someone has come up with the "best" way to do it already. (Note the "s.)

    You can google priority queue structure if you're interested in doing it that way. Alternatively, you can look at one of these lua implementations and modify/draw ideas from them, if you prefer:

    http://mirror.math.ku.edu/tex-archive/graphics/pgf/base/tex/generic/graphdrawing/lua/pgf/gd/lib/PriorityQueue.lua

    http://rosettacode.org/wiki/Priority_queue#Lua


  • *popcorn*

    My own hodgepodge frankenstein code for tracking demon balance is so inefficient, and this helps a lot in making it less messy-looking.

    10 points to Gryffindor!
    currently tentatively active
    (may vanish for periods of time)
  • Belief log parser, anyone? I need a way to measurably pat myself on the back.
     You say, "This is much harder than just being a normal person."
  • Pretty sure it is missing newish lines for shrine stuffs:
  • Thank you Cass. <3
     You say, "This is much harder than just being a normal person."
  • Coding noob here who gets very confused with complicated coding :(

    I want to write a simple tattooing script that will check tattoos and ink whatever tattoo designated on the first available tattoo slot. Does any kind soul have any suggestions, please?

    Thanks.
  • You don't need to specify a location to ink it. Just INK (tattoo) ON ANY OF (target)
Sign In or Register to comment.