Switching from cMUD

seamer
Posts: 5
Joined: Tue Jul 28, 2020 1:19 am

Switching from cMUD

Post by seamer »

At the risk of sounding like a broken record :D

I have a decent amount of aliases and triggers in cMUD that work as intended. I have no idea how they would look written into something Mudlet would understand.

I won't bother you guys with the full set. If you could show me how to make it mudlet friendly, that would be amazing!

Code: Select all

#ALIAS seamermana {
    get all hole;
    wear @neckmana;
    rem @neckdam;
    wear @neckmana;
    put all.@neckdam hole;
    wear @headmana;
    put @headdam hole;
    wear @legsmana;
    put @legdam hole;
    wear @handsmana;
    put @handdam hole;
    wear @waistmana;
    put @waistdam hole;
    wear all;
    wear @heldmana;
    #if (@target == lich) {} {wear @shieldmana;put @shielddam hole};
    put @helddam hole;
    wear @aboutmana;
    put @aboutdam hole;
    #2 rem '@wristdam';
    #2 wear '@wristmana';
    #2 put '@wristdam' hole;
    wear @armsmana;
    put @armsdam hole;
    wear @lightmana;
    put @lightdam hole;
    #VARIABLE eq {0};
    #VARIABLE mood {peaceful}
} "manaeq"
"seamermana" is fairly simple. It does a full outfit exchange and utilises values stored in @variables - so @wristdam is treated as "put 'angel wristband' hole". And so forth. The 'manaeq' tag at the end is the name of the class the alias belongs to, so if I'm not in fight mode (I toggle between peaceful and pissy), running the command "seamermana" is pointless - it's inactive. The shield line - this particular target is known to carry an axe, and axes split shields, perm destructing them. If the script knows I'm fighting lich it skips the shield swap, and if I'm not fighting Lich it swaps +mana shield/+dam shield.

Code: Select all

#TRIGGER {Your (%*) {@damages} (%*)'s {@bodyparts}(*)} {
    #IF ( @fightcounter > @fight) {
        #IF (@hp < @maxhp) {
            #VARIABLE fightcounter 0;
            cast 'cure critical' self
        } 
        else {
            gore;
            #VARIABLE fightcounter 0
        }
    }
    #if (@mana > 100) {
        #IF ("%1" == "blast of lightning") {
            #alarm "fightcounter" +0.75 {
                cast 'lightning breath';
                #add fightcounter 1
            };
            #ABORT 1
        };
        #IF ("%1" == "blast of acid") {
            #alarm "fightcounter" +0.75 {
                cast 'acid breath';
                #add fightcounter 1
            };
            #ABORT 1
        };
        #IF ("%1" == "blast of flame") {
            #alarm "fightcounter" +0.75 {
                cast 'fire breath';
                #add fightcounter 1
            };
            #ABORT 1
        };
        #IF ("%1" == "blast of frost") {
            #alarm "fightcounter" +0.75 {
                cast 'frost breath;
                #add fightcounter 1
            };
            #ABORT 1
        };
        #IF ("%1" == "blast of gas") {
            #alarm "fightcounter" +0.75 {
                cast gas;
                #add fightcounter 1
            };
            #ABORT 1
        }
    };
    #if ("%1" == "divine power") {
        #abort 1
    };
    #if ("%1" == "flaming bite") {
        #abort 1
    };
    #if ("%1" == "Kick") {
        #if (@fightcounter < 15) {
            #alarm "fightcounter" +0.5 {
                Kick
            };
            #add fightcounter 1
        }
    };
    #if ("%1" == "gore") {
        #if (@gore < 15) {
            #alarm "fightcounter" +0.5 {
                gore
            };
            #add fightcounter 1
        } 
        else {
            #add fightcounter 1;
            gore;
            #abort 1
        }
    };
    #if ("%1" == "bash") {
        #if (@bash < 15) {
            #alarm "fightcounter" +0.5 {
                bash
            };
            #add fightcounter 1
        } 
        else {
            #var fightcounter 0;
            bash;
            #abort 1
        }
    }
} "fight" {case}
This fight script is a little more interesting, I think. @bodyparts and @damages contain arrays of known damage messages and body parts. @fightcounter counts how many times a particular spell/kick has been sent in a row, cuz at 20 repeated commands you get disconnected. The delay is to reduce the amount of times one action is triggered, in cmud the alarm is just re-started if it's appended before it casts. And if we get to 15 consecutive attacks, and our hp is lower than max, we throw in a cure critical. If we're fully healed, we're sending a kick. Thus, the fight counter is reset intelligently.

And finally, I followed the setup on Edru's adjustable tabbed windows page and got the layout. What's the easiest way to funnel information to those tabs? (https://github.com/Edru2/AdjustableTabWindow). I know how to capture it, I just don't know how to display it where I want it. :D

Sorry to ask the same old questions.. sometimes I just need to have it explained like I'm 5

Jor'Mox
Posts: 1142
Joined: Wed Apr 03, 2013 2:19 am

Re: Switching from cMUD

Post by Jor'Mox »

Okay, so firstly, you should know of the two main ways to construct a string containing a value from a variable, as you will clearly be making use of one or both of them quite a lot. The simplest way is to use the string concatenation symbol ".." to connect the various pieces, like this: "put all." .. neckdam .. " hole". The second way is to use the string.format function, which is nice when things get complicated. You would do so like this: string.format("put all.%s hole", neckdam). Note here that variables don't have any special symbol at the beginning that indicates that they are variables. You just type in the name, and they are good to go.

For your alias, you just need to put together a few different elements, the main one being either individual send function calls, or you can use sendAll to send a list of things all at once. I'll put an example of different ways this can be done, but I won't fill in each line for you, because that is just more than I want to type.
Code: [show] | [select all] lua
-- basic send functions  --  note that lines starting like this one are comments in Lua code
send("get all hole")
send("wear all")
-- using sendAll instead
sendAll("get all hole", "wear all")
-- using sendAll in a way that is a bit easier to read when you have a lot of lines to send
sendAll("get all hole",
    "wear all",
    "more stuff")
You obviously also need an "if" statement to handle the case when you are fighting a lich, which I'll demonstrate here.
Code: [show] | [select all] lua
if not target == "lich" then
    sendAll("wear " .. shieldmana, "put " .. shielddam .. " hole")
end
I see one spot where you are clearly executing the commands twice, and while you can use "for" loops to do things repeatedly in Lua, there is no convenient shorthand to simply repeat something X number of times the way you are doing it, so in this case, it would simply be easier to just type in the commands twice, rather than try to make something do that for you. If you needed to send a command a bunch of times, a "for" loop structure for that looks like this.
Code: [show] | [select all] lua
for i = 1, 10 do
    send("do stuff")
end
And lastly, you are setting a few variables, which would look like this.
Code: [show] | [select all] lua
eq = 0
mood = "peaceful"
Also, in case you hadn't figured it out yet, the pattern you would want to use ^seamermana$

The fight script is a bit more complicated, so I'll get to that in a bit.
Last edited by Jor'Mox on Sat Jan 28, 2023 10:25 pm, edited 1 time in total.

Jor'Mox
Posts: 1142
Joined: Wed Apr 03, 2013 2:19 am

Re: Switching from cMUD

Post by Jor'Mox »

I don't think there is a mechanism to use a table in your trigger patterns like you have done, so you will need a more complicated trigger pattern to match things in the way you are looking to. This is a pattern I made for my game that tries to capture all the relevant bits of info in a line such as what it looks like you are capturing (though my game has no body parts involved), but optimized to have as little repetition as possible within the pattern. Importantly, this pattern will grab anyone's attack, so you will see switches in there to handle that, which you obviously don't need or want. Regex pattern construction is... complicated.

Here is the pattern I used, with some newlines added in to make it easier to read, instead of trying to cram all on one line.

Code: Select all

(You|[\w\-\s,']+?)(?:(?<=You)r|'s)?(?:\s?((?<=Your )[\w\s]+?|(?<='s )[\w\s]+?|))(?: do[es]*| [\>\<\=\*]+|)
(m(?:a(?:ul|im)|iss)|de(?:cim|vast)ate|scratch|(?:graz|injur)e|hit|wound|H(?:ORRID|IDEOUS)|
D(?:IS(?:EMBOWEL|MEMBER)|E(?:MOLISH|VASTATE)|READFUL)|M(?:A(?:SSACR|NGL)E|UTILATE)|GHASTLY|
(?:(?:INDESCRIB|UNSPEAK)ABL|(?:OBLITER|ANNIHIL|ERADIC)AT)E)[esES]*(?: things to| [\>\<\=\*]+|) ([\w\-\s,']+)([\.!]+)
Here is code that I think does all of what your trigger code did before.
Code: [show] | [select all] lua
    if fightcounter > fight then
        if hp < maxhp then
            send("cast 'cure critical' self")
        else
            send("gore")
        end
        fightcounter = 0
    end
    if mana > 100 then
        if matches[2] == "blast of lightning" then
            if fightID then killTimer(fightID) end
            fightID = tempTimer(0.75, function ()
                send("cast 'lightning breath'")
                fightcounter = fightcounter + 1
                fightID = nil
                end)
        elseif matches[2] == "blast of acid" then
            if fightID then killTimer(fightID) end
            fightID = tempTimer(0.75, function ()
                send("cast 'acid breath'")
                fightcounter = fightcounter + 1
                fightID = nil
                end)
        elseif matches[2] == "blast of flame" then
            if fightID then killTimer(fightID) end
            fightID = tempTimer(0.75, function ()
                send("cast 'fire breath'")
                fightcounter = fightcounter + 1
                fightID = nil
                end)
        elseif matches[2] == "blast of acid" then
            if fightID then killTimer(fightID) end
            fightID = tempTimer(0.75, function ()
                send("cast 'acid breath'")
                fightcounter = fightcounter + 1
                fightID = nil
                end)
        elseif matches[2] == "blast of frost" then
            if fightID then killTimer(fightID) end
            fightID = tempTimer(0.75, function ()
                send("cast 'frost breath'")
                fightcounter = fightcounter + 1
                fightID = nil
                end)
        elseif matches[2] == "blast of gas" then
            if fightID then killTimer(fightID) end
            fightID = tempTimer(0.75, function ()
                send("cast gas")
                fightcounter = fightcounter + 1
                fightID = nil
                end)
        end
    elseif matches[2] == "divine power" then
        
    elseif matches[2] == "flaming bite" then
        
    elseif matches[2] == "Kick" then
        if fightcounter < 15 then
            if fightID then killTimer(fightID) end
            fightID = tempTimer(0.5, function ()
                send("kick")
                fightID = nil
                end)
            fightcounter = fightcounter + 1
        end
    elseif matches[2] == "gore" then
        fightcounter = fightcounter + 1
        if gore < 15 then
            if fightID then killTimer(fightID) end
            fightID = tempTimer(0.5, function ()
                send("gore")
                fightID = nil
                end)
        else
            send("gore")
        end
    elseif matches[2] == "bash" then
        if bash < 15 then
            if fightID then killTimer(fightID) end
            fightID = tempTimer(0.5, function ()
                send("bash")
                fightID = nil
                end)
            fightcounter = fightcounter + 1
        else
            fightcounter = 0
            send("bash")
        end
    end
I'm not sure what this part is about, so I don't have any code to address it: "fight" {case}

Jor'Mox
Posts: 1142
Joined: Wed Apr 03, 2013 2:19 am

Re: Switching from cMUD

Post by Jor'Mox »

Oh, about the chat windows, you send the text to the window you want like this:
Code: [show] | [select all] lua
--selects and copies an entire line to user window named "Chat"
selectCurrentLine()
copy()
appendBuffer("Chat")

seamer
Posts: 5
Joined: Tue Jul 28, 2020 1:19 am

Re: Switching from cMUD

Post by seamer »

Thanks for the feedback, I will of course dig through it and see how I go. :)

Jor'Mox
Posts: 1142
Joined: Wed Apr 03, 2013 2:19 am

Re: Switching from cMUD

Post by Jor'Mox »

If you find you really like the repeat functionality that you had in cMUD, you can more or less mimic it by just making a script and putting a simple function into it that will do what it does, like this:
Code: [show] | [select all] lua
function reSend(cmd, num)
    for i = 1, num do
        send(cmd)
    end
end
That way, you only have to do all the extra work of making a loop once, and then you just use the function call the same way you did in your alias: reSend("rem '" .. wristdam .. "'", 2) or reSend(string.format("rem '%s'", wristdam), 2)

seamer
Posts: 5
Joined: Tue Jul 28, 2020 1:19 am

Re: Switching from cMUD

Post by seamer »

Jor'Mox wrote:
Tue Jan 31, 2023 6:08 pm
If you find you really like the repeat functionality that you had in cMUD, you can more or less mimic it by just making a script and putting a simple function into it that will do what it does, like this:
Code: [show] | [select all] lua
function reSend(cmd, num)
    for i = 1, num do
        send(cmd)
    end
end
That way, you only have to do all the extra work of making a loop once, and then you just use the function call the same way you did in your alias: reSend("rem '" .. wristdam .. "'", 2) or reSend(string.format("rem '%s'", wristdam), 2)
Thank you for the suggestion. I have absolutely no idea what you're doing there. :D But that's me, not you. A bit beyond my ability yet, I suspect. All the things I don't understand are on me, please don't take that personally.

I played with basic combat recasts. This is what I'm running right now. (It's really basic, but it works. And that's half the battle)
Code: [show] | [select all] lua
if counter >= 15 then
        if msdp.HEALTH < msdp.HEALTH_MAX then
            send("cast 'cure critical' self")
        else
            send("gore")
        end
        counter = 0
    end
        if matches[2] == "lightning" then
                send("cast 'lightning breath'")
                counter = counter + 1
        elseif matches[2] == "acid" then
                send("cast 'acid breath'")
                counter = counter + 1
        elseif matches[2] == "flame" then
                send("cast 'fire breath'")
                counter = counter + 1
        elseif matches[2] == "acid" then
                send("cast 'acid breath'")
                counter = counter + 1
        elseif matches[2] == "frost" then
                send("cast 'frost breath'")
                counter = counter + 1
        elseif matches[2] == "gas" then
                send("cast gas")
                counter = counter + 1
    elseif matches[2] == "kick" then
        if counter < 15 then
                send("kick")
            counter = counter + 1
        end
    elseif matches[2] == "gore" then
        counter = counter + 1
        if gore < 15 then
                send("gore")
        else
            send("gore")
        end
    elseif matches[2] == "bash" then
        if bash < 15 then
                send("bash")
            counter = counter + 1
        else
            counter = 0
            send("bash")
        end
    end
Your suggestion of the recasting buffer kept throwing errors. The only way I could move forward was to strip the timer portions out.
Code: [show] | [select all] lua
            if fightID then killTimer(fightID) end
            fightID = tempTimer(0.75, function ()
                send("cast 'lightning breath'")
                fightcounter = fightcounter + 1
                fightID = nil
                end)
I was also unable to figure out how to populate edru's container stuff with text. Again, this is a me thing.
Attachments
Screenshot 2023-02-07 at 6.27.17 PM.png

Jor'Mox
Posts: 1142
Joined: Wed Apr 03, 2013 2:19 am

Re: Switching from cMUD

Post by Jor'Mox »

Looking at the code I had for the combat stuff, it looks like I just wasn't accounting for the initial nil value for the fightcounter variable. So you could use the timers as is, but at the very beginning of that code block, before any of the if statements, add this: fightcounter = fightcounter or 0

I will point out that you are using two variables in if statements, bash and gore, that don't seem to be used anywhere else. If you don't have something changing those values somewhere else, then those variables will always have a nil value, and your if statements are a waste of space. That said, the logic of what is happening in those if statements is rather confusing to me. The first if statement you have there will always set the counter variable to 0 if it starts out at or above 15. So later, when you check "kick" to see if counter is less than 15... it always will be. When you check "gore", you literally do the same thing regardless of the value of its presumed unique counter, but if you used the counter variable that you are using elsewhere instead, again the if statement is unnecessary anyway because it will never reach the relevant value. The same goes with "bash". So, you could rewrite what you have into this, if I'm reading it right.
Code: [show] | [select all] lua
counter = counter or 0
if counter >= 15 then
     if msdp.HEALTH < msdp.HEALTH_MAX then
          send("cast 'cure critical' self")
     else
          send("gore")
     end
     counter = 0
end
if matches[2] == "lightning" then
     send("cast 'lightning breath'")
     counter = counter + 1
elseif matches[2] == "acid" then
     send("cast 'acid breath'")
     counter = counter + 1
elseif matches[2] == "flame" then
     send("cast 'fire breath'")
     counter = counter + 1
elseif matches[2] == "frost" then
     send("cast 'frost breath'")
     counter = counter + 1
elseif matches[2] == "gas" then
     send("cast gas")
     counter = counter + 1
elseif matches[2] == "kick" then
     send("kick")
     counter = counter + 1
elseif matches[2] == "gore" then
     send("gore")
     counter = counter + 1
elseif matches[2] == "bash" then
     send("bash")
     counter = counter + 1
end
But, you can actually make things a bit simpler from a coding perspective, if you wanted, by using a table.
Code: [show] | [select all] lua
counter = counter or 0
local combatTbl = {kick = "kick", bash = "bash", gore = "gore", gas = "cast gas", frost = "cast 'frost breath'", acid = "cast 'acid breath'", flame = "cast 'fire breath'", lightning = "cast 'lightning breath'"}
if counter >= 15 then
     if msdp.HEALTH < msdp.HEALTH_MAX then
          send("cast 'cure critical' self")
     else
          send("gore")
     end
     counter = 0
end
if combatTbl[matches[2]] then
     send(combatTbl[matches[2]])
     counter = counter + 1
end

Jor'Mox
Posts: 1142
Joined: Wed Apr 03, 2013 2:19 am

Re: Switching from cMUD

Post by Jor'Mox »

seamer wrote:
Wed Feb 08, 2023 2:26 am
Jor'Mox wrote:
Tue Jan 31, 2023 6:08 pm
If you find you really like the repeat functionality that you had in cMUD, you can more or less mimic it by just making a script and putting a simple function into it that will do what it does, like this:
Code: [show] | [select all] lua
function reSend(cmd, num)
    for i = 1, num do
        send(cmd)
    end
end
That way, you only have to do all the extra work of making a loop once, and then you just use the function call the same way you did in your alias: reSend("rem '" .. wristdam .. "'", 2) or reSend(string.format("rem '%s'", wristdam), 2)
Thank you for the suggestion. I have absolutely no idea what you're doing there. :D But that's me, not you. A bit beyond my ability yet, I suspect. All the things I don't understand are on me, please don't take that personally.
So, to do this, you need to create a new, blank script, just like making an alias or trigger, just click the "Scripts" button instead, and then make a new one. Then, take the code for the function I wrote and just paste it in there. Save the script, and suddenly you now have access to that function anywhere you need it, as if it were a function that is part of Mudlet, like the send function. Just make sure the box next to the script's name is checked, and you are good to go.

Jor'Mox
Posts: 1142
Joined: Wed Apr 03, 2013 2:19 am

Re: Switching from cMUD

Post by Jor'Mox »

When it comes to getting the text into the containers that you have set up, can you post a screenshot of the trigger you have setup to try to capture that text? Please also show or otherwise include the code you have that is creating those containers (not the code for the containers themselves, just the stuff you have that makes each of them) so I can see what names you are giving them all, to reference when helping you get things up and running.

Post Reply