MU Soapbox

    • Register
    • Login
    • Search
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Muxify
    • Mustard
    1. Home
    2. Melpomene
    M
    • Profile
    • Following 0
    • Followers 0
    • Topics 9
    • Posts 35
    • Best 6
    • Controversial 0
    • Groups 0

    Melpomene

    @Melpomene

    8
    Reputation
    186
    Profile views
    35
    Posts
    0
    Followers
    0
    Following
    Joined Last Online
    Website http://

    Melpomene Unfollow Follow

    Best posts made by Melpomene

    • MSG code

      https://gist.github.com/ADHdev/00a8e7a9cea5f46780768307a77fb4d2#file-msg-mu

      Global messaging system that stores the messages when you're offline, and can be prefixed as a text, a phone call, comms, telepathy, whatever.

      I got a headache while working on the chargen stuff and decided to bang something else out fast. (Sometimes you just need a working, fun piece of code.)

      Help files are included but the general gist is this:

      • msg <player>=<message>
      • msg/<type> <message> - type can be almost any one word, including "butt".
      • msg <message> - remembers all your previous settings

      Supports multi-messaging too. Let me know if you find any bugs.

      posted in MU Code
      M
      Melpomene
    • RE: Anomaly Jobs: +myjob/cc

      What people want out of +jobs that +jobs doesn't already provide: a professional, web-based bug/ticket-tracking system that is completely configurable and robust. IE, ZenDesk, Fogbugz, etc.

      Honestly, I think aJobs is the best you're going to get if you go completely MU-based. If you wanted to give the people what they want, though: make there be a jobs code that has a web component which is accessible from within the game via SQL queries. Pay more attention to the web component than the MUcode component because that's what they care about.

      Seriously though, the stuff people ask me to do to jobs is always "I wish it were a webpage" stuff. Sorting, searching, don't make tickets public except for users with X logins, allow group discussions in a ticket, make it send notices to my phone, yadda yadda. Every time they ask for a feature I miss the stuff I use at work.

      MUs have already embraced wiki. Who's to say the next thing they go for won't be Bugzilla? (Although really that's not the best for this task... but it's cheap, at least!)

      posted in MU Questions & Requests
      M
      Melpomene
    • RE: TinyMUX: Info Storage

      @Thenomain Re: Second: 😄 😄 😄 YUP. 😄

      Hrm, though, I tried those substitutions and failed. Let me... kick it again when I do not have a headcold. I would like to get rid of that stupid key. Maybe I did something wrong in my fever-haze.

      Yeah, the statpath idea was a good one, but I wanted shorter paths. Your comment on that Codebase Pot Pie thread about regexes in statpath searches, though, made me go "Hmm", and indexes was my idea of "maybe solve this". You still will have problems if you don't have delimiters, but... I think the lookups will be quicker. Maybe.

      What I'm working on is an essentially universal base, eventually to be shoved under a pile of system-specific code. This is just one piece of the API for it. I'll see about getting it on github at some point when it's either doneish or abandoned so other people can play with it.

      posted in MU Code
      M
      Melpomene
    • Code offering: Generic +reminders code

      A friend asked me for this. I hope someone finds it useful. Ulterior motive: I have server/code questions. It's easier to get those answered when one has provided a suitable offering. I don't have a repository, so here you go.


      Description/help file:

         +remind <name|me> to <stuff>[ <in|every> [<X>] <days|weeks|months>]
      
         Examples:
           +remind me to Call Mom - will remind you every day
           +remind me to Howl at the moooon! every month
           +remind John to send that log in 3 days
      
         +reminders - Show all the reminders you have set.
         +reminder/view 1 - view reminder #1.
         +reminder/cancel 1 - get rid of reminder #1.
         +reminder/note 1=<stuff> - any notes you want the reminder to send you
      
         Notes:
           All reminders are sent at 2 AM.
           This code considers "a month" to be 28 days.
           Units of time that are not recognized will default to "days".
           Do not use this code for precision. Most third-party apps work better.
      
         Code notes:
           Required functions: header, footer, isstaff, alert
           Required objects: Cron object of some kind
           Required permissions: WIZARD due to attr reading/setting
           Limitations:
             Players can run out of space on themselves by setting a million
             reminders.
           Regrets: Did not code the display number to NOT be the ID.
      
         Credits: Melpomene@NOLA (melpomine@gmail.com|nola.mechanipus.com 2967)
      

      Note: game is still in development. Feel free to log in and whatnot, just don't be surprised it's not up.


      Code, unexploded because exploding is even spammier:

      @create Generic Reminder Code <GRC>=10
      
      @set GRC=SAFE INHERIT
      
      @desc GRC=%R[space(3)]+remind <name|me> to <stuff>[ <in|every> [<X>] <days|weeks|months>]%R%R[space(3)]Examples:%R[space(5)]+remind me to Call Mom - will remind you every day%R[space(5)]+remind me to Howl at the moooon! every month%R[space(5)]+remind John to send that log in 3 days%R%R[space(3)]+reminders - Show all the reminders you have set.%R[space(3)]+reminder/view 1 - view reminder #1.%R[space(3)]+reminder/cancel 1 - get rid of reminder #1.%R[space(3)]+reminder/note 1=<stuff> - any notes you want the reminder to send you%R%R[space(3)]Notes:%R[space(5)]All reminders are sent at 2 AM.%R[space(5)]This code considers "a month" to be 28 days.%R[space(5)]Units of time that are not recognized will default to "days".%R[space(5)]Do not use this code for precision. Most third-party apps work better.%R%R[space(3)]Code notes:%R[space(5)]Required functions: header, footer, isstaff, alert%R[space(5)]Required objects: Cron object of some kind%R[space(5)]Required permissions: WIZARD due to attr reading/setting%R[space(5)]Limitations:%R[space(7)]Players can run out of space on themselves by setting a million%R[space(7)]reminders.%R[space(5)]Regrets: Did not code the display number to NOT be the ID.%R%R[space(3)]Credits: Melpomene@NOLA (melpomine@gmail.com|nola.mechanipus.com 2967)%R
      
      
      &cmd-+remind GRC=$+remind * to *:@switch setr(E, if(and(not(strmatch(setr(P, pmatch(case(%0, me, %N, %0))), %#)), not(isstaff(%#))), Only staffers may set reminders for anyone other than themselves., if(not(t(%qP)), Could not find player %0., setq(3, extract(%1, sub(words(%1), 2), 3))[null(iter(%q3, if(isnum(%i0), setq(4, 1)))[if(not(t(%q4)), setq(4, switch(%q3, * month, M, * months, M, * day, D, * days, D, * weeks, W, * week, W, 0)))])][if(not(t(%q4)), setq(3, ))][setq(C, switch(%q3, * month, M, * months, M, * day, D, * days, D, * weeks, W, * week, W, 0))][setq(R, switch(%q3, * in *, I, in *, I, * every *, E, every *, E, 0))][setq(N, trim(squish(iter(%q3, if(isnum(%i0), %i0)))))][if(or(not(t(%qN)), not(isnum(%qN))), setq(N, 1))][setq(S, if(or(strmatch(%q3, * in *), strmatch(%q3, in *)), extract(%1, 1, sub(words(%1), match(revwords(%1), in))), if(or(strmatch(%q3, * every *), strmatch(%q3, every *)), extract(%1, 1, sub(words(%1), match(revwords(%1), every))), %1)))][if(not(t(%qS)), Could not figure out what you wanted me to remind you of!, setq(T, convtime(timefmt($a $b $d 02:00:00 $Y, add(secs(), mul(%qN, case(%qC, W, 604800, M, 2419200, 86400)))))))])))=, {&_reminderCount %qP=setr(I, add(default(%qP/_reminderCount, 0), 1)); &_reminder-%qI-text %qP=%qS; &_reminder-%qI-cycle %qP=[if(t(%qC), %qC, D)]; &_reminder-%qI-next %qP=%qT; &_reminder-%qI-interval %qP=%qN; &_reminder-%qI-setter %qP=%#; &_reminder-%qI-repeat %qP=[case(%qR, I, 0, 1)]; @switch [gt(strlen(get(me/people-[setr(A, v(peopleCount))])), 7500)]=1, {&peopleCount me=setr(A, add(%qA, 1));}; &people-%qA me=[setunion(v(people-%qA), %qP)]; @set me/people-%qA=NO_COMMAND; @pemit %#=alert(Reminders) [case(%#, %qP, You, name(%qP))] will receive a reminder to "%qS" [case(%qR, I, in, every)] [if(gt(%qN, 1), %qN%b)][case(%qC, W, week, M, month, day)][if(gt(%qN, 1), s)][case(%qR, I,, . Your next reminder is)] on [timefmt($m/$d/$y at 2 AM, %qT)].[case(%qC, M, %bPlease note that a month is considered to be 28 days long.)];}, {@pemit %#=alert(Reminders) %qE;}
      @set GRC/cmd-+remind=no_parse
      
      &peopleCount GRC=1
      @set GRC/peopleCount=NO_COMMAND
      
      &trigger_reminders GRC=@dolist lattr(me/people-*)={@trigger me/trigger_parse-people=##;};
      @set GRC/trigger_reminders=NO_COMMAND
      
      &trigger_parse-people GRC=@dolist v(%0)={@trigger/notify me/trigger_remind-person=##; @wait me={@trigger me/trigger_clean-person=##;};}
      @set GRC/trigger_parse-people=NO_COMMAND
      
      &trigger_clean-person GRC=@switch words(lattr(%0/_reminder-*-text))=0, {@dolist lattr(me/people-*)={&## me=[setdiff(v(##), %0)];};}
      @set GRC/trigger_clean-person=NO_COMMAND
      
      &trigger_remind-person GRC=@switch t(setr(P, pmatch(%0)))=1, {@dolist lattr(%qP/_reminder-*-text)={@switch setq(0, first(rest(##, -), -))[setq(C, get(%qP/_reminder-%q0-cycle))][setq(I, get(%qP/_reminder-%q0-interval))][setq(R, get(%qP/_reminder-%q0-repeat))][setq(T, get(%qP/_reminder-%q0-next))][lt(%qT, add(secs(), 3600))]=1, {@mail/quick %qP/Reminder: [titlestr(setr(V, get(%qP/##)))]=%R%TRemember to: %qV[if(hasattr(%qP, _reminder-%q0-note), %R%R%TNote: [get(%qP/_reminder-%q0-note)])]%R%R This is a [case(%qR, 1, repeating, one-time)] reminder [case(setr(S, get(%qP/_reminder-%q0-setter)), %qP, you set for yourself, [name(%qS)] set for you)]. [case(%qR, 1, Your next reminder will be on [timefmt($m/$d/$y at 2 AM, convtime(timefmt($a $b $d 02:00:00 $Y, add(secs(), mul(%qI, case(%qC, W, 604800, M, 2419200, 86400))))))]. This reminder will recur every %qI [case(%qC, W, week, M, month, day)][if(gt(%qI, 1), s)].)] To learn more about +reminders, type +help reminders. Thank you!; @switch %qR=1, {&_reminder-%q0-next %qP=[convtime(timefmt($a $b $d 02:00:00 $Y, add(secs(), mul(%qI, case(%qC, W, 604800, M, 2419200, 86400)))))];}, {@wipe %qP/_reminder-%q0-*;}}}}
      @set GRC/trigger_remind-person=NO_COMMAND
      
      &cmd-+reminders GRC=$+reminders:@pemit %#=if(t(setr(R, lattr(%#/_reminder-*-text))), header(Your active reminders)[space(3)]%cu[ljust(ID, 5)] [ljust(Reminder text, 57)] [ljust(Next, 8)]%cn%R[iter(%qR, space(3)[ljust(setr(0, first(rest(%i0, -), -))., 5)] [ljust(mid(get(%#/%i0), 0, 57), 57)] [ljust(timefmt($m/$d/$y, get(%#/_reminder-%q0-next)), 8)],, %R)][footer(+reminder/view # for more.)], alert(Reminders) You have no active reminders.);
      
      &cmd-+reminder_view GRC=$+reminder/view *:@switch setr(E, if(not(hasattr(%#, _reminder-%0-text)), You don't have a reminder #%0.))=, {@pemit %#=header(Reminder #%0)%r[wrap(Text: [get(%#/_reminder-%0-text)], 78, Left, space(3))]%R[if(hasattr(%#, _reminder-%0-note), wrap(Note: [get(%#/_reminder-%0-note)], 78, Left, space(3))%R)][columns(Set by: [name(get(%#/_reminder-%0-setter))]|Repeating: [case(setr(R, get(%#/_reminder-%0-repeat)), 1, on, off)]|Next reminder: [timefmt($m/$d/$y at 2 AM, get(%#/_reminder-%0-next))]|Occurs [case(%qR, 1, every, in)]: [setr(I, get(%#/_reminder-%0-interval))] [case(get(%#/_reminder-%0-cycle), W, week, M, month, day)][if(gt(%qI, 1), s)], 36, |, 3)]%R[footer(+reminder/note %0=<note> to set a note.)];}, {@pemit %#=alert(Reminders) %qE;}
      @set GRC/cmd-+reminder_view=no_parse
      
      &cmd-+reminder_note GRC=$+reminder/note *=*:@switch setr(E, if(not(hasattr(%#, _reminder-%0-text)), You don't have a reminder #%0.))=, {&_reminder-%0-note %#=%1; @pemit %#=alert(Reminders) You set a note for #%0: %1;}, {@pemit %#=alert(Reminders) %qE;}
      @set GRC/cmd-+reminder_note=no_parse
      
      &cmd-+reminder_cancel GRC=$+reminder/cancel *:@switch setr(E, if(not(hasattr(%#, _reminder-%0-text)), You don't have a reminder #%0.))=, {@pemit %#=alert(Reminders) You have canceled reminder #%0. If you wish to recreate it, run these commands:%R%R+remind me to [get(%#/_reminder-%0-text)] [case(get(%#/_reminder-%0-repeat), 1, every, in)] [setr(I, get(%#/_reminder-%0-interval))] [case(get(%#/_reminder-%0-cycle), W, week, M, month, day)][if(gt(%qI, 1), s)][if(hasattr(%#, _reminder-%0-note), %R+reminder/note [add(get(%#/_reminderCount), 1)]=[get(%#/_reminder-%0-note)])]; @wipe %#/_reminder-%0-*;}, {@pemit %#=alert(Reminders) %qE;}
      @set GRC/cmd-+reminder_note=no_parse
      
      @pemit %#=SET A CRON JOB UP. Sample below. For the below code to work, you need to be either holding the cron or in its location. Otherwise, replace the word CRON with your cron's DBref.
      
      @force me=&cron_job_GenericReminders CRON=@trigger [num(GRC)]/trigger_reminders
      &cron_time_GenericReminders CRON=|||02|00|
      

      Usage, modification, and posting/hosting rights granted so long as you leave the credits in and unmodified except to append your own.

      posted in MU Code
      M
      Melpomene
    • Code offering: +autojobs

      Automatically create a job in X days/weeks/months or every X days/weeks/months. Because that could get horribly annoying, only staff can do it. It is managed by @forcing the player to +request something, however, so it does let players at least look at their autojobs (after all, they'll see them when they're +requested). This is based off my earlier Generic Reminders Code. I'll try to keep it up to date as I encounter bugs.

      The desc/help:

         +autojob <name>=<job title>[ <in|every> [<X>] <days|weeks|months>] (Staff)
      
         Examples:
           +autojob Jamie=Call Mom - will open a new job every day
           +autojob Jake=Howl at the moooon! every month
           +autojob John=Feeding Frenzy in 3 days
      
         +autojobs - Show all the autojobs you have set.
         +autojob/view 1 - view autojob #1 on yourself.
      
         Staff only:
      
         +autojob/view <name>/1 - view autojob #1 on <name>.
         +autojob/cancel <name>/1 - get rid of autojob #1 on <name>.
         +autojob/note <name>/1=<stuff> - any notes you want to include in the job
      
         Notes:
           All autojobs are created at 2 AM.
           This code considers "a month" to be 28 days.
           Units of time that are not recognized will default to "days".
           Do not use this code for precision. Most third-party apps work better.
      
         Code notes:
           Required functions: header, footer, isstaff, alert
           Required objects: Cron object of some kind, Anomaly Jobs
           Required permissions: WIZARD due to attr reading/setting & @forcing
           Limitations:
             Players can run out of space on themselves by setting a million
             autojobs.
           Regrets: Did not code the display number to NOT be the ID.
      
         Credits: Melpomene@NOLA (melpomine@gmail.com|nola.mechanipus.com 2967)
      
      

      The code:

      @create AutoJob Handler <AJH>=10
      
      @set AJH=SAFE INHERIT
      
      @desc AJH=%R[space(3)]+autojob <name>=<job title>[ <in|every> [<X>] <days|weeks|months>] (Staff)%R%R[space(3)]Examples:%R[space(5)]+autojob Jamie=Call Mom - will open a new job every day%R[space(5)]+autojob Jake=Howl at the moooon! every month%R[space(5)]+autojob John=Feeding Frenzy in 3 days%R%R[space(3)]+autojobs - Show all the autojobs you have set.%R[space(3)]+autojob/view 1 - view autojob #1 on yourself.%R%R[space(3)]Staff only:%R%R[space(3)]+autojob/view <name>/1 - view autojob #1 on <name>.%R[space(3)]+autojob/cancel <name>/1 - get rid of autojob #1 on <name>.%R[space(3)]+autojob/note <name>/1=<stuff> - any notes you want to include in the job%R%R[space(3)]Notes:%R[space(5)]All autojobs are created at 2 AM.%R[space(5)]This code considers "a month" to be 28 days.%R[space(5)]Units of time that are not recognized will default to "days".%R[space(5)]Do not use this code for precision. Most third-party apps work better.%R%R[space(3)]Code notes:%R[space(5)]Required functions: header, footer, isstaff, alert%R[space(5)]Required objects: Cron object of some kind, Anomaly Jobs%R[space(5)]Required permissions: WIZARD due to attr reading/setting & @forcing%R[space(5)]Limitations:%R[space(7)]Players can run out of space on themselves by setting a million%R[space(7)]autojobs.%R[space(5)]Regrets: Did not code the display number to NOT be the ID.%R%R[space(3)]Credits: Melpomene@NOLA (melpomine@gmail.com|nola.mechanipus.com 2967)%R
      
      
      &cmd-+autojob AJH=$+autojob *=*:@switch setr(E, if(not(isstaff(%#)), Only staffers may set autojobs., if(not(t(setr(P, pmatch(case(%0, me, %N, %0))), %#)), Could not find player %0., setq(3, extract(%1, sub(words(%1), 2), 3))[null(iter(%q3, if(isnum(%i0), setq(4, 1)))[if(not(t(%q4)), setq(4, switch(%q3, * month, M, * months, M, * day, D, * days, D, * weeks, W, * week, W, 0)))])][if(not(t(%q4)), setq(3, ))][setq(C, switch(%q3, * month, M, * months, M, * day, D, * days, D, * weeks, W, * week, W, 0))][setq(R, switch(%q3, * in *, I, in *, I, * every *, E, every *, E, 0))][setq(N, trim(squish(iter(%q3, if(isnum(%i0), %i0)))))][if(or(not(t(%qN)), not(isnum(%qN))), setq(N, 1))][setq(S, if(or(strmatch(%q3, * in *), strmatch(%q3, in *)), extract(%1, 1, sub(words(%1), match(revwords(%1), in))), if(or(strmatch(%q3, * every *), strmatch(%q3, every *)), extract(%1, 1, sub(words(%1), match(revwords(%1), every))), %1)))][if(not(t(%qS)), Could not figure out what you wanted me to autojob you of!, setq(T, convtime(timefmt($a $b $d 02:00:00 $Y, add(secs(), mul(%qN, case(%qC, W, 604800, M, 2419200, 86400)))))))])))=, {&_autojobCount %qP=setr(I, add(default(%qP/_autojobCount, 0), 1)); &_autojob-%qI-text %qP=%qS; &_autojob-%qI-cycle %qP=[if(t(%qC), %qC, D)]; &_autojob-%qI-next %qP=%qT; &_autojob-%qI-interval %qP=%qN; &_autojob-%qI-setter %qP=%#; &_autojob-%qI-repeat %qP=[case(%qR, I, 0, 1)]; @switch [gt(strlen(get(me/people-[setr(A, v(peopleCount))])), 7500)]=1, {&peopleCount me=setr(A, add(%qA, 1));}; &people-%qA me=[setunion(v(people-%qA), %qP)]; @set me/people-%qA=NO_COMMAND; @pemit %#=alert(autojobs) [name(%qP)] will open a job titled "%qS" [case(%qR, I, in, every)] [if(gt(%qN, 1), %qN%b)][case(%qC, W, week, M, month, day)][if(gt(%qN, 1), s)][case(%qR, I,, . The next autojob is)] on [timefmt($m/$d/$y at 2 AM, %qT)].[case(%qC, M, %bPlease note that a month is considered to be 28 days long.)];}, {@pemit %#=alert(autojobs) %qE;}
      @set AJH/cmd-+autojob=no_parse
      
      &peopleCount AJH=1
      @set AJH/peopleCount=NO_COMMAND
      
      &trigger_autojobs AJH=@dolist lattr(me/people-*)={@trigger me/trigger_parse-people=##;};
      @set AJH/trigger_autojobs=NO_COMMAND
      
      &trigger_parse-people AJH=@dolist v(%0)={@trigger/notify me/trigger_autojob-person=##; @wait me={@trigger me/trigger_clean-person=##;};}
      @set AJH/trigger_parse-people=NO_COMMAND
      
      &trigger_clean-person AJH=@switch words(lattr(%0/_autojob-*-text))=0, {@dolist lattr(me/people-*)={&## me=[setdiff(v(##), %0)];};}
      @set AJH/trigger_clean-person=NO_COMMAND
      
      &trigger_autojob-person AJH=@switch t(setr(P, pmatch(%0)))=1, {@dolist lattr(%qP/_autojob-*-text)={@switch setq(0, first(rest(##, -), -))[setq(C, get(%qP/_autojob-%q0-cycle))][setq(I, get(%qP/_autojob-%q0-interval))][setq(R, get(%qP/_autojob-%q0-repeat))][setq(T, get(%qP/_autojob-%q0-next))][setq(S, get(%qP/_autojob-%q0-setter))][lt(%qT, add(secs(), 3600))]=1, {@force %qP=+request [titlestr(setr(V, get(%qP/##)))]=%%R%%RAutojob: %qV[if(hasattr(%qP, _autojob-%q0-note), %%R%%R%%TNote: [get(%qP/_autojob-%q0-note)])]%R%R This is a [case(%qR, 1, repeating, one-time)] +autojob [name(%qS)] set for [name(%qP)]. [case(%qR, 1, The next +autojob will be on [timefmt($m/$d/$y at 2 AM, convtime(timefmt($a $b $d 02:00:00 $Y, add(secs(), mul(%qI, case(%qC, W, 604800, M, 2419200, 86400))))))]. This +autojob will recur every %qI [case(%qC, W, week, M, month, day)][if(gt(%qI, 1), s)].)] To learn more about +autojobs, type +help autojobs.; @switch %qR=1, {&_autojob-%q0-next %qP=[convtime(timefmt($a $b $d 02:00:00 $Y, add(secs(), mul(%qI, case(%qC, W, 604800, M, 2419200, 86400)))))];}, {@wipe %qP/_autojob-%q0-*;}}}}
      @set AJH/trigger_autojob-person=NO_COMMAND
      
      &cmd-+autojobs AJH=$+autojobs:@pemit %#=if(t(setr(R, lattr(%#/_autojob-*-text))), header(Your active autojobs)[space(3)]%cu[ljust(ID, 5)] [ljust(+autojob text, 57)] [ljust(Next, 8)]%cn%R[iter(%qR, space(3)[ljust(setr(0, first(rest(%i0, -), -))., 5)] [ljust(mid(get(%#/%i0), 0, 57), 57)] [ljust(timefmt($m/$d/$y, get(%#/_autojob-%q0-next)), 8)],, %R)][footer(+autojob/view # for more.)], alert(autojobs) You have no active autojobs.);
      
      &cmd-+autojobs_person AJH=$+autojobs *:@switch setr(E, if(not(isstaff(%#)), Only staffers may view another player's autojobs., if(not(t(setr(P, pmatch(case(%0, me, %N, %0))), %#)), Could not find player %0.)))=, {@pemit %#=if(t(setr(R, lattr(%qP/_autojob-*-text))), header([name(%qP)]'s active autojobs)[space(3)]%cu[ljust(ID, 5)] [ljust(+autojob text, 57)] [ljust(Next, 8)]%cn%R[iter(%qR, space(3)[ljust(setr(0, first(rest(%i0, -), -))., 5)] [ljust(mid(get(%qP/%i0), 0, 57), 57)] [ljust(timefmt($m/$d/$y, get(%qP/_autojob-%q0-next)), 8)],, %R)][footer(+autojob/view [name(%qP)]/# for more.)], alert(autojobs) [name(%qP)] has no active autojobs.);}, {@pemit %#=alert(autojobs) %qE;}}
      @set AJH/cmd-+autojobs_person=no_parse
      
      &cmd-+autojob_view AJH=$+autojob/view *:@switch strmatch(%0, */*)=1,{},{@switch setr(E, if(not(hasattr(%#, _autojob-%0-text)), You don't have a autojob #%0.))=, {@pemit %#=header(+autojob #%0)%r[wrap(Text: [get(%#/_autojob-%0-text)], 78, Left, space(3))]%R[if(hasattr(%#, _autojob-%0-note), wrap(Note: [get(%#/_autojob-%0-note)], 78, Left, space(3))%R)][columns(Set by: [name(get(%#/_autojob-%0-setter))]|Repeating: [case(setr(R, get(%#/_autojob-%0-repeat)), 1, on, off)]|Next autojob: [timefmt($m/$d/$y at 2 AM, get(%#/_autojob-%0-next))]|Occurs [case(%qR, 1, every, in)]: [setr(I, get(%#/_autojob-%0-interval))] [case(get(%#/_autojob-%0-cycle), W, week, M, month, day)][if(gt(%qI, 1), s)], 36, |, 3)]%R[footer(if(isstaff(%#), +autojob/note %N/%0=<note> to set a note.))];}, {@pemit %#=alert(autojobs) %qE;}}
      @set AJH/cmd-+autojob_view=no_parse
      
      &cmd-+autojob_view_person AJH=$+autojob/view */*:@switch setr(E, if(not(isstaff(%#)), Only staffers may view another player's autojobs., if(not(t(setr(P, pmatch(case(%0, me, %N, %0))), %#)), Could not find player %0., if(not(hasattr(%qP, _autojob-%1-text)), [name(%qP)] doesn't have a +autojob #%1.))))=, {@pemit %#=header([name(%qP)]'s +autojob #%1)%r[wrap(Text: [get(%qP/_autojob-%1-text)], 78, Left, space(3))]%R[if(hasattr(%qP, _autojob-%1-note), wrap(Note: [get(%qP/_autojob-%1-note)], 78, Left, space(3))%R)][columns(Set by: [name(get(%qP/_autojob-%1-setter))]|Repeating: [case(setr(R, get(%qP/_autojob-%1-repeat)), 1, on, off)]|Next +autojob: [timefmt($m/$d/$y at 2 AM, get(%qP/_autojob-%1-next))]|Occurs [case(%qR, 1, every, in)]: [setr(I, get(%qP/_autojob-%1-interval))] [case(get(%qP/_autojob-%1-cycle), W, week, M, month, day)][if(gt(%qI, 1), s)], 36, |, 3)]%R[footer(if(isstaff(%#), +autojob/note [name(%qP)]/%1=<note> to set a note.))];}, {@pemit %#=alert(autojobs) %qE;}
      @set AJH/cmd-+autojob_view_person=no_parse
      
      &cmd-+autojob_note AJH=$+autojob/note */*=*:@switch setr(E, if(not(isstaff(%#)), Only staffers may set autojob notes., if(not(t(setr(P, pmatch(case(%0, me, %N, %0))), %#)), Could not find player %0., if(not(hasattr(%qP, _autojob-%1-text)), [name(%qP)] doesn't have a +autojob #%1.))))=, {&_autojob-%1-note %qP=%2; @pemit %#=alert(autojobs) You set a note for #%1: %2;}, {@pemit %#=alert(autojobs) %qE;}
      @set AJH/cmd-+autojob_note=no_parse
      
      &cmd-+autojob_cancel AJH=$+autojob/cancel */*:@switch setr(E, if(not(isstaff(%#)), Only staffers may set autojobs., if(not(t(setr(P, pmatch(case(%0, me, %N, %0))), %#)), Could not find player %0., if(not(hasattr(%qP, _autojob-%1-text)), [name(%qP)] doesn't have a autojob #%1.))))=, {@pemit %#=alert(autojobs) You have canceled [name(%qP)]'s autojob #%1. If you wish to recreate it, run these commands:%R%R+autojob [name(%qP)]=[get(%qP/_autojob-%1-text)] [case(get(%qP/_autojob-%1-repeat), 1, every, in)] [setr(I, get(%qP/_autojob-%1-interval))] [case(get(%qP/_autojob-%1-cycle), W, week, M, month, day)][if(gt(%qI, 1), s)][if(hasattr(%qP, _autojob-%1-note), %R+autojob/note [add(get(%qP/_autojobCount), 1)]=[get(%qP/_autojob-%1-note)])]; @wipe %qP/_autojob-%1-*;}, {@pemit %#=alert(autojobs) %qE;}
      @set AJH/cmd-+autojob_note=no_parse
      
      @pemit %#=SET A CRON JOB UP. Sample below. For the below code to work, you need to be either holding the cron or in its location. Otherwise, replace the word CRON with your cron's DBref.
      
      @force me=&cron_job_AutoJobs CRON=@trigger [num(AJH)]/trigger_autojobs
      &cron_time_AutoJobs CRON=|||02|00|
      
      posted in MU Code
      M
      Melpomene
    • RE: Code Request: RP Nexus

      @Bobotron Honestly I'm not sure. It's a new game, the buildstaffers are stil working on policy. They might decide that digging your own is fine; they might decide that floating rooms are clutter... I don't even have a clue. I will note that on some games I've played, buildstaff controlled the quota with an iron fist - @digging was verboten unless you had a project in the Build Nexus and nobody but NOBODY could RP there. I doubt this game's buildstaffers would be that bad - they're too nice! - but the gods have decreed that there should be a RP Nexus so the players won't have to resort to @digging their own.

      @Thenomain OK, I'm giving this a shot. It took a bit of kicking - I found two bugs - but I believe I have it working. Below is the fixed +temproom function - two of the @asserts returned 0s for valid values, and the @trigger didn't specify what object had the trigger - since no @parent was specified I just went with an explicit call, set up during the install process.

      Also: I got 90% of the way through implementing this as a RP Nexus only, and one of the gods told me that they actually want +temprooms available everywhere, to anyone. D'oh! So yes, +temprooms is exactly what I needed. Working on that. 😑

      These are the changes I made, in case anyone wants them:

      &c.temproom trm=
      	$^\+?temproom (.*)$:
      		@assert [or( isstaff( %# ), u( f.valid-room?, loc( %# )))]=
      			{
      				 
      				@pemit %#=
      					You're not in a location that can take a temproom. 
      				}
      			;
      			 
      			think 
      				>> 
      				[setr(
      					 s, u( f.scrub_name, %1 )
      				)]
      				 %r  >> 
      				[setr(
      					 n, u( f.format.roomname, %qs )
      				)]
      				 %r  >> 
      				[setr(
      					 e, u( f.format.entrance, %qs )
      				)]
      				 %r  >> 
      				[setr(
      					 x, u( f.format.exit, %qs )
      				)]
      			;
      			@assert valid( roomname, %qn )=
      				{
      					@pemit %#=
      						u( .msg, temproom, I can't take that name for a temproom. ) 
      					}
      				;
      				 
      				@assert valid( exitname, %qn )=
      					{
      						 
      						@pemit %#=
      							u( .msg, temproom, I can't make that name into a good exit name. ) 
      						}
      					;
      					 
      					@assert not(t( match( elements( %qe, 2, %; ), v( d.illegal-anagrams ))))=
      						{
      							 
      							@pemit %#=
      								u( .msg, temproom, The exit name would be too close to commonly used commands. ) 
      							}
      						;
      						 
      						@assert not(cor( t( locate( %#, elements( %qe, 2, %; ), E )), t( locate( %#, elements( %qe, 3, %; ), E ))))=
      							{
      								 
      								@pemit %#=
      									u( .msg, temproom, That would create an exit with an identical name as an exit in that room. )
      								}
      							;
      							 
      							@trigger [v(d.digger)]/tr.dig-room=
      								loc( %# ), %qn, %qe, %qx, %#
      							;
      							 
      							@eval 
      								u( f.monitor, temproom:
      								[name(
      									 %# 
      								)]
      								 creates "%qs" off 
      								[name(
      									 loc( %# )
      								)]
      								 (
      								[loc(
      									 %# 
      								)]
      								))
      							;
      							
      
      posted in MU Code
      M
      Melpomene

    Latest posts made by Melpomene

    • Some +jobs mods

      I'm working on customizing Anomaly Jobs for a game I'm working on. I've always had issues with how +jobs works by default and I decided to knuckle down and Make It Do What I Want.

      A week later, I had this stack of stuff other people might find handy: https://github.com/MelpomeneMU/byzantine-opal/tree/main/auxilary functionality/%2Bjobs mods

      Iunno if anybody is still using that 10-20 year old tech but I got tired of waiting for something better to come along and I have realized that rewriting the sucker is more work than I want to do, so the next best thing is modding it.

      posted in Code
      M
      Melpomene
    • RE: NOLA: The Game That Care Forgot

      @Jennkryst Naah, +roll will just fail to find the stat and assume you don't have it and let you know in the output "hey, didn't find this stat". I was trying for a simple understandable answer from a player's perspective but now that I think about it, +roll isn't the best.

      OK, so the longer answer: You want to xp/spend player/Resources=1, you need to know how high Resources goes, what section of the sheet to put it on, what the XP cost is (because if it weren't a merit it might be a Discipline and those buggers are expensive!), etc.

      Now, if you trusted staff to just automatically give the right stat to the player for the right amount of XP, and the player to report if the staffer screwed it up, you could seriously just "stat/grant player=Resources:1" and then "xp/spend player=1 for Resources 1". However, people want the quick shortcuts. They want alert messages to fire off when the player doesn't have XP (if it was Dominate 5 and the player had 1 XP and also didn't even have Dominate 1, 2, 3, or 4, for example). They want the system to reject the command if the player doesn't have the prerequisites for the merit.

      For that, you need a database of the rules. Most of the rules - like Resources - are simple. Some of the rules are hard AF. (Health levels was a beeeyotch to understand when I first screwed with it.) The rule for Resources is just "1.2.3.4.5" and "Merit", meaning "it costs 1 XP per dot and can be any of the values 1, 2, 3, 4, or 5". The system takes care of the rest. The rules for, say, "Quick Draw", are a little bit tougher. (Plus it has a value that can be set to darn near anything.)

      That code is expressed like so:

      &MERIT.QUICK_DRAW_() [v(d.dd)]=1|*
      
      &PREREQUISITE.MERIT.QUICK_DRAW_() [v(d.dd)]=cand(u(.at_least, %0, attribute.Wits, 3), cor(u(.specialty_has, %0, Brawl Weaponry Firearms Athletics, %1), u(.has, %0, merit.[edit(%1, %b, _)])))
      
      &PREREQ-TEXT.MERIT.QUICK_DRAW_() [v(d.dd)]=Wits 3+, and the type is either a specialty for Brawl, Weaponry, Firearms, Athletics, or a learned Fighting Style
      

      Long answer satisfactory? 😄

      posted in Adver-tis-ments
      M
      Melpomene
    • RE: NOLA: The Game That Care Forgot

      @Jennkryst Because you want the code to be able to +roll Intelligence + Academics + Resources if that ever comes up. If we didn't have to do that it would be so much easier... though honestly I've been working on ways around that in my random codings lately. 😛

      posted in Adver-tis-ments
      M
      Melpomene
    • RE: Useful code on player bit

      Yeah. Not sure why games don't do that on their default player object. I haven't seen a situation in which anyone wanted their code to work on everyone in the same room with them. o.O

      I'm sort of surprised no one else has a stack of useful stuff they stick on their player bits by default. I can't be the only one who does this and I've been doing it for years - custom descers (basically a thing to list descs and swap between them), note-to-self type code... heck, I even threw an entire dice roller onto myself on one game that didn't have one. (It was dirt-simple but worked for what I needed it for.)

      Anybody? Anyone? Bueller?

      posted in MU Code
      M
      Melpomene
    • Useful code on player bit

      Because we're not always wizards and some things are just easy to do and ought to be done. (And some of us have too much caffeine in our bloodstreams and need a break from RL code.)

      // BEFORE YOU DO ANY OF THIS:
      
      @lock me=me
      
      // If you don't know why, don't use this code.
      
      // The automatic idler: After 15m puts you in a "hey I might be idle" state. After 30-60m (unless you have it turned off), takes you to the "yep I'm idle" state. After 6 hours, even if you have it set to keep you awake, runs the "I'm idle" commands. When you reconnect, it automatically remembers your STAY-awake/asleep state, but still fires your awake-actions anyway and marks you "awake". The idea was to have a single "aconnect" that fires when you "wake up" as well as when you connect. This is for games that just let people sit on them for all time, becoming idle and then unidle but never again firing the @aconnect unless someone got disconnected.
      
      // Commands: +wake; +sleep; +stay/a*;
      
      
      
      // Function: Interval
      
      // Input: me, *name, #dbref, or a time in seconds (for example, the time a post was made).
      
      // Output: Converts given seconds-ago or person's idle time into human-readable text. Returns only the top 2 significant intervals (weeks, days, hours, minutes, seconds).
      
      &f.interval me=if(t(setr(0, extract(squish(trim(strcat(setq(I, sub(secs(), if(isnum(%0), %0, sub(secs(), idle(%0))))), setq(W, div(%qI, 604800)), if(gt(%qW, 0), setq(I, sub(%qI, mul(%qW, 604800)))), setq(D, div(%qI, 86400)), if(gt(%qD, 0), setq(I, sub(%qI, mul(%qD, 86400)))), setq(H, div(%qI, 3600)), if(gt(%qH, 0), setq(I, sub(%qI, mul(%qH, 3600)))), setq(M, div(%qI, 60)), if(gt(%qM, 0), setq(I, sub(%qI, mul(%qM, 60)))), setq(S, %qI), if(t(%qW), %qWw)|, if(t(%qD), %qDd)|, if(t(%qH), %qHh)|, if(t(%qM), %qMm)|, if(t(%qS), %qSs)), b, |), |), 1, 2, |, %b))), %q0, 0s)
      
      // th ulocal(me/f.interval, me)
      // th ulocal(me/f.interval, *idleperson)
      // th ulocal(me/f.interval, sub(secs(), 102))
      // th ulocal(me/f.interval, sub(secs(), 400002))
      // th ulocal(me/f.interval, startsecs())
      
      &state-sleep me=1
      &stay-asleep me=0
      
      &awake-actions me=+watch; +bbscan; +wantrp/on;
      &asleep-actions me=+wantrp/off;
      
      &min-idle-before-promised-sleep me=900
      &max-idle-before-sleep me=1800
      &max-idle-before-forced-sleep me=21600
      &idle-check-interval me=1700
      
      &msg-idle-but-awake me=I've been idle for [ulocal(me/f.interval, me)] but I swear I'm here. It might take me a few minutes to respond.
      
      &msg-very-idle me=I've been idle for [ulocal(me/f.interval, me)] so I'm probably AFK.
      
      &msg-idling-soon me=I've been idle for [u(me/f.interval, me)] so I could be AFK or just typing a really long pose.
      
      &tr-wake me=@switch/first v(state-sleep)=0, {@trigger/quiet me/awake-actions; @set/quiet me=state-sleep:1;};
      
      &tr-sleep me=@switch/first v(state-sleep)=1, {th Getting sleepy.;@trigger/quiet me/asleep-actions; @set/quiet me=state-sleep:0;};
      
      &tr-wakeorsleep me=@switch/first or(eq(v(stay-asleep), 0), gte(idle(me), v(max-idle-before-forced-sleep)))=1,{ @switch/first gte(idle(me), v(max-idle-before-sleep))=1, { @trigger/quiet me/tr-sleep; }, { @trigger/quiet me/tr-wake; }; }
      
      &tr-wait-wakeorsleep me=@trigger/quiet me/tr-wakeorsleep; @wait v(idle-check-interval)=@trigger/quiet me/tr-wait-wakeorsleep;
      
      @idle me=case(1, gt(idle(me), v(max-idle-before-sleep)), case(and(v(stay-asleep), v(state-sleep)), 1, u(me/msg-idle-but-awake), u(me/msg-very-idle)), gt(idle(me), v(min-idle-before-promised-sleep)), u(me/msg-idling-soon),)
      
      @aconnect me=@set/quiet me=state-sleep:0[setq(S, v(stay-asleep))]; @set/quiet me=stay-asleep:0; @wait 5=@trigger/quiet me/tr-wait-wakeorsleep; @wait 6=@set/quiet me=stay-asleep:%qS;
      
      &CMD-WAKE me=$+wake:@switch/first v(state-sleep)=0, { @trigger/quiet me/tr-wake; },{ th You're already awake.; }
      
      &CMD-SLEEP me=$+sleep:@switch/first v(state-sleep)=1, { @trigger/quiet me/tr-sleep; },{ th You're already asleep.; }
      
      &cmd-stay me=$+stay/a*:@set/quiet me=stay-asleep:[not(v(stay-asleep))];th case(v(stay-asleep), 1, Staying, Letting fate decide if you stay) [case(v(state-sleep), 1, awake, asleep)].
      
      
      // Below is random stuff that I have written over the years to make RP less painful on games that aren't all coded up to my "standards" so to speak.
      
      
      // +msg: remembers the last person/people you texted with +msg and makes it so you can just type +msg <stuff> and it'll go to them.
      
      &CMD-+MSG me=$+msg *:@switch/first %0=*=*, {@set/quiet me=last-msg:[first(%0, =)]; @force me=+txt %0; }, { @force me=+txt [v(last-msg)]=%0; }
      
      
      // On my player bits, I often forget if I'm a wizbit or not. This catches my "+job"s and turns them into "+myjob"s. You need the no_parse or your formatting gets eaten when you +job/add <#>=<formatted stuff>.
      
      &CMD-+JOB me=$+job*:@force me=+myjob%0
      @set me/cmd-+job=no_parse
      

      Does anyone else have anything useful they stick on their PC bits? I might want to steal your code. 😄

      Edit: because I called the attr 'stay-asleep', not 'stay-sleep'. 😛 And because those idle messages were getting spammy so I sectioned them out.

      posted in MU Code
      M
      Melpomene
    • MSG code

      https://gist.github.com/ADHdev/00a8e7a9cea5f46780768307a77fb4d2#file-msg-mu

      Global messaging system that stores the messages when you're offline, and can be prefixed as a text, a phone call, comms, telepathy, whatever.

      I got a headache while working on the chargen stuff and decided to bang something else out fast. (Sometimes you just need a working, fun piece of code.)

      Help files are included but the general gist is this:

      • msg <player>=<message>
      • msg/<type> <message> - type can be almost any one word, including "butt".
      • msg <message> - remembers all your previous settings

      Supports multi-messaging too. Let me know if you find any bugs.

      posted in MU Code
      M
      Melpomene
    • RE: TinyMUX: Info Storage

      Updated the +help sample to actually use MVC structure (sort of). Added proper help files for it (ha!). I would now consider the +help thing a full-fledged piece of code and no longer "basic". It's ready to be repurposed for whatever data storage needs to happen.

      https://gist.github.com/ADHdev/0f16992826cac3bcd00266f33dbceb87#file-plushelp-txt

      There have been some minor updates to Cheapass Clusters as I discovered it wasn't storing raw code, and fixed a few other bugs.

      https://gist.github.com/ADHdev/66ccc9ac4a520da760045a456e3a301d#file-cheapassclusters-txt

      Not sure anyone's using these, but if you are, you probably ought to update.

      And for my next trick: anvils. ...or rather, a generic stat system. 😄 (Yes, so you non-WoDers can have a chargen that isn't locked to that system.) This will probably take some time, though. I'll start a new topic when ready.

      posted in MU Code
      M
      Melpomene
    • RE: TinyMUX: Info Storage

      @rook I used https://www.orcpie.fun/muxwriter.html to turn it into that because I want to be able to grab "%b" on the wiki end and translate it into "&nbsp;". (There will be <pre></pre> involved in this.) The idea here is to get something that doesn't involve wiki format translation - I'd rather translate MU* into wiki than vice versa. (We're using Dokuwiki, or at least we will be.) It would be a bit harder to parse text for "[space(\d+)]"; %b is a straight-up replace.

      Should be pretty simple to th (the text) and see it on a MU* if you're curious - it's just a formatted version of the Commands list from the top.

      posted in MU Code
      M
      Melpomene
    • RE: TinyMUX: Info Storage

      https://gist.github.com/ADHdev/0f16992826cac3bcd00266f33dbceb87#file-basic-help - and here's a basic +help thing using it. It takes the basic data object and improves on it somewhat - fixed a few bugs, changed the syntax to be friendlier, more standard.

      And yes, @Thenomain, C-style comments. XD

      (Edit to update link to better permalink.)

      posted in MU Code
      M
      Melpomene
    • RE: TinyMUX: Info Storage

      Meeeeeh, C-style comments... but I changed it, just for you. XD

      posted in MU Code
      M
      Melpomene