Targeting?

I'm new to MUDs and I know nothing about coding, so trying to make the game comfortable for me to play by messing with things feels like trying to write a poem in a language I don't know.

I know what I want to do though:

I saw this video explaining about data capture, and I thought that it would be nice if by sending the command KILL I would receive back a list of the monsters in the room, in which each mob would be linked to an variable, like:

-KILL
Here are some people and creatures that you can attack:
1-DOG, 2-CAT, 3-SATAN

-KK M3 (KK=my attack, m3=satan)

The thing is, I'd like that I would be able to start using an alias for an attack, but then after attacking with an alias, I would like to be able to use hotkeys to keep attacking the same mob. As you can see I'm not interested in autobashers, I'm fine in being the one pressing buttons, picking the targets, etc. I want to be able to set things this way because with this I probably(I think) wouldn't need to change things for hunting ever again.

I tried setting things on my on, but I wasn't even able to set the data capture right, I thought it was because the id of the mob was set between "()" and if I put that thingie thing "(\w+)" inside of it I would need to put like this ^\((\w+)\)$ because I think I read you need to put \ before things that can also be accepted as commands. But even doing that it didn't work.



If anyone could help me out, that would be great. If someone knows of something someone put up that does the same thing, that's also great. Until then I think I'll be using nexus client to play.

PS: Forgive me if what I wrote sounds like nonsense, english is not my native language, and I'm really talking about something beyond my understanding.

Comments

  • Ok, so... you're on the right track, sort of. What we're dealing with when we're doing aliases is called "regular expressions", or regex for short. They're like.... insanely confusing and the less you think about them the better, to be honest, aside from learning a few patterns that will help you. In regex, "\" is a special character, it's used in combination with other things to describe... well, something that includes a bunch of different stuff. For example, \w means "one letter or number". \w+ means "one or more letters or numbers.

     Brackets "()" create a "capture group", which is something you want to get out of the thing you typed, and use it in a sec. You combine these things, the "something matchers" and the "capture groups" to grab a specific thing you typed and use it in a command you want to send to the game.

    In mudlet, capture groups are numbered. You should think of them as starting from 2... just because. 

    So, if you put all this together, you can make an alias: kill (\w+)

    "kill" is the start. It's the same every time. (\w+) is a group of letters and numbers, no spaces, and it's something you can use later, by referring to it as "matches[2]". So, in the big text section for this alias, you write "send("kill "..matches[2]"

    When you use this alias, you type "kill rat". Mudlet then sends "kick rat" to the game.

    The ".." is important. It joins two strings of letters and numbers and whatever together (they're actually called strings). The space before the closing quote is important too - if you forget it, mudlet sends "kickrat", and the game whines at you.


    I know we're not quite at your original question yet, and that's because what you actually asked is... Kind of hard and I don't want to freak you out just yet. I just thought it was important to explain the brackets and slashes first.

    The next thing to know about is variables. Variables are just something mudlet will remember for you. I'm just going to write a script for you now, so you can see for yourself how it works and try to figure things out at your own pace - I'm going to use a few more things I haven't explained yet as well- ^ means "this has to begin at the start of what you type, and $ means "this has to end now". ? after something, whether or not its a capture group, means "maybe this will be here, maybe it won't:

    Alias input:   ^kk ?(\w+)?$

    NOTE that I put a ? after the space before the group as well. That's because if you just type "kk", there's not going to be a space after it, and mudlet cares about that.

    Script section:
    target = matches[2] or target
    send("kick "..target)

    OR here is a trick. It means "if I didn't get something in the first bit, try the next bit instead".

    so, if you type "kill rat", then mudlet goes "ok, target = rat. Now, kick target". Afterwards, you just type "kill". This time, it gets nothing, so it goes to the OR, and uses the EXISTING value of target, which is "rat" - so it just sends "kill rat" again

    Later, you type "kill fink" instead. So it makes target = fink now, and then sends "kick fink"

    One thing to watch out for: if you type "kill", and you've never typed "kill rat" since you last opened up mudlet, target won't equal anything at all - so mudlet won't know what to do. If you don't like this idea, then you can add another "or":

    target = matches[2] or target or "rat"

    Now, it first checks if you typed something, then it checks if it already remembers something, and then lastly, if all else fails, it defaults to rat.


    OK, so... I know I haven't explained how to type kill, get a list of things to kill, and then be able to choose from that list - that's because thats a LOT harder for now. It's best to use the approach I've explained here at first. Get that right, get comfortable with it, and then i'm TOTALLY happy to explain more... until EVENTUALLY I can teach you how to make a menu of things to kill, and choose something from the menu. In fact, I could tell you how to make them into links, that you just click, which makes them your target and sends the first hit - but it's better to start slow or your brain will melt, take it from me (my brain melts very easily)

  • That was beautifully explained. I can't thank you enough for taking your time to explain those things to me.

    About the KILL thing, it's a command from the game already(it gives you a list of the mobs in the room), so I could just put it on a key like F1. I thought that if I had the data capture set up like it was done in the video I could just write in the next line:

    m1, m2, m3, m4, m5 = matches[2], matches[3], matches[4], matches[5], matches[6]

    I wasn't sure, but it's supposed to assign a variable to each captured value right? But now that I think about it again this wouldn't work with just what I said because I would be getting the number of the mobs in my list.

    Anyway, I will do like you said and I will get familiar with everything you explained.

    Thanks again for teaching me all of this!
  • edited August 2018
    Ok, so, I hadn't used that command in a while, and it looks like it's changed a little, so I can try to think through this - I'm not really aware of anyone doing it this way... what you're describing is kind of like, a weird middle ground between the typical targeting alias most people use, and the sort of "detect everything in the room so I can kill it without typing what to target" approach that's more complicated. 

    The syntax you're using there is right - you can assign a bunch of variables at once like that, and it's a pretty good trick in a lot of cases

    The problem with your idea is that the command returns each thing you can kill on a new line - so they won't get added to the same matches[] list. Also, since you don't know how many lines will come through, you can't use a "basic" multi line trigger properly either.

    However, I just had an idea... It's NOT simple, really, but it's a way of getting what you want.

    You need more than one trigger, and you need to learn how to write mudlet code that interacts with "mudlet objects" - which gives you the ability to toggle your own triggers on and off. Then you need a more advanced kind of variable, a list/table - sounds easy, but they're... usually a pain lol. For me, anyway. 

    I'd put these triggers in their own folder in mudlet, to keep everything neat. You'll also want to give the one you're turning on and off a nice, easy to type name, because you're going to need to use it in your code (unlike usual where it's just for your reference). 

    The first trigger you make is the one that grabs a thing to kill. This is the one you're going to toggle, so you can name it something like captureKillable or something. It's a single line that you need to set to be  "perl regex" instead of "substring" or anything else. 

    Quick note about regex - you'll tear out way less hair if you use a "regex tester" website, like https://regex101.com. It not only tells you whether or not your pattern will work, it also actually explains what the hell is going on in a regular expression... Anyway, here's the first trigger. The bits that don't make sense will make sense in a sec (maybe lol).

    denizenId
    denizenCounter = denizenCounter + 1 -- increment the counter (we'll actually make it in a second)Pattern: ^\* (\S+(?: \S+)*) \((\d+)\)$
    
    Code:
    local denizenId = tostring(matches[3])
    myTargetList[denizenCounter] = 
    The pattern here is uh, a bit cooked, as they say. The \* means "treat the star as an actual star, not as a special regex character". If you don't escape the star, it's like a different version of a +, except this time it means "zero or more" instead of "one or more". (\S+(?: \S+)*) is a capture group that basically just says "a word, then maybe a space, and then maybe  some more words and spaces. This goes into matches[2], but we're not going to use it (unless you can think of something to do with it!). The last bit, (\d+), means "a number", and goes in matches[3]. Also note the \( and \) - this time we really do want brackets, not special capture group behaviour, to match the brackets in the actual game output.

    We save the bit we actually need to a LOCAL variable - its just a good idea, means they clean themselves up after the trigger is done. We won't need it around, because in the next bit, we are going to insert a record into a table, where the denizen's "key" is the current "denizenNumber", and the "value" is its ID in the game. That means you can look up the key in the table, and get back the ID of the thing (some people call this a dictionary). tostring(matches[3]) just turns the number into a string. It's just better this way, i think, for reasons. Now lastly (weird, i know), DEACTIVATE this trigger in mudlet.

    It's time for our next trigger - make the type "exact match" this time. Also, I'm using comments, which start with "--" in the code. They're for people to read, not mudlet, and don't do anything except say stuff. It's a good habit if you're like me and need to talk yourself through what you're trying to do as you write (or explain to someone else):

    Pattern: Here are some people and creatures that you can attack:
    
    Code:
    myTargetList = {} -- Create a new, empty table (clearing the old one from last time we ran this)
    denizenCounter = 1 -- create (or reset) a numeric variable called denizenCounter that will number the things in the room for us
    enableTrigger("captureKillable") -- Turn on the trigger we made before. 
    enableTrigger("stopCapturingKillable") -- turn on ANOTHER trigger, that we're about to make
    

    Now we need one last trigger to turn captureKillable off again. This time, set the trigger type to "Lua Function". This means instead of checking text from the game, we check some code - in this case we're basically waiting until we see the next prompt, which is when we know the game stopped listing denizens to kill. Call it something like stopCapturingKillable.

    Pattern: return isPrompt()
    
    Code:
    disableTrigger("captureKillable") -- turn it off again
    disableTrigger("stopCapturingKillable") -- turn THIS off again too, or else it'll fire on EVERY prompt, forever.
    
    Now, with these three triggers, you've basically copied what you see on the screen into mudlet's memory so you can use it in aliases, looking it up by a number, in order of what you saw on the screen.

    Now, to get what you ORIGINALLY wanted, make an alias:

    Pattern: ^kk ?(?:m(\d+))?$
    
    Code:
    
    <div><div>if matches[2] ~= nil then -- we only want to go here if you typed "kk m1" or whatever. Typing "kk" by itself will attack your LAST target.</div><div>&nbsp;&nbsp;&nbsp;&nbsp;local numberEntered = tonumber(matches[2])</div><div>&nbsp;&nbsp;&nbsp;&nbsp;target = myTargetList[numberEntered]  -- Look up the table with the number you typed, and save the denizen's ID to a variable called target</div><div>&nbsp;&nbsp;&nbsp;&nbsp;-- target is NOT local, and stays around to be used again, anywhere you like.</div><div>end -- Don't forget this lol, I always do</div><br><div>send("kick "..target)</div></div>
    

    And there you go! Now, type "kill" normally to get the list, mudlet captures it for you, then after you've done that, you can type kk m1, kk m2, etc,  and it will attack the denizens (in whatever order you saw them on the screen). Once you've specified at least once, you can just type "kk" to attack the same thing again.

    Note, there's almost definitely bugs in this - i only sort of tested it lol. And obviously you'll want to change the attack. But if you start here, and play around then sooner or later it'll all make sense and bit by bit you'll be able to work out how to do... more or less anything you need to do, just with these few concepts. Good luck!

  • Thanks Reyl, I really appreciate you teaching me all this! I definitely owe you on this one.

    I'll see if I get more familiar with lua then I'll try to apply what was said here.
Sign In or Register to comment.