MU Soapbox

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

    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
    • RE: TinyMUX: Info Storage

      So, because I can't leave well enough alone, I designed a data-source and mostly data-type agnostic data storage module. It uses both the method above and the SQL method, because I'm a glutton for punishment (and honestly MySQL is interesting). It is here:

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

      That's the decompiled version, with the test object, plus a bunch of tests I used. I've tested it pretty thoroughly and am using it on the game I'm working on.

      If anyone uses it, poke me here and let me know if you encounter problems with it. I'm curious to see if anyone else encounters the stored procedure issues I ran into, or if they're just issues on my own machine.

      If people prefer it in a compiled format (just the code plskthx) let me know and I'll toss one up.

      (Edit to update the permalink.)

      posted in MU Code
      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
    • RE: TinyMUX: Info Storage

      Reason for code is essentially "because MUX doesn't have @clusters". This is sort of a polyfill for it - but only sort of, not exactly. I'd have to dig a lot deeper into everything clusters can do to make it a true polyfill.

      I gave this code a lot of thought today and decided I wanted to do more with it. I'm working on a fuller version that supports indexing.

      Why no SQL? Because I feel like sql(), a blocking call, is awkward and painful and non-native, and I've somewhat had it with "Your site's connection to the SQL server has dropped, please @restart!" messages. Fitting SQL's syntax, which I am fully fluent in, into softcode, hurts my soul. The right way to do it would be with @query, and well-written stored procedures, and honestly I felt that would be too much work for what I'm trying to do... but someone else could surely pull it off, and good luck to them.

      The key thing. I'm probably having a brain fart over how the entire thing works, but I wasn't able to make the lock detect that a player calling it was calling it through an inherited-permissions object. What I want:

      • Player can do +setdata command if it's not locked to wizards.
      • Player can NOT do setdata(target, attr:value). (Not even on himself - because the player could end up with a bunch of parent objects. Honestly what we're restricting here is who the target can be, but I want that to be handled completely in code, without staffers having to manually, say, add the dbref of the newest storage object to some attribute somewhere...)

      I fucked around with it and no matter how I arranged it, either both worked or neither did, so I said "fuck it" and went with the key thing.

      What's this about indexing? I'm working on a stat system. Stats have titles, values, descriptions, tags, and, occasionally, stamps (for approval, date/time marking, etc). Essentially these items function like columns in a database with each new stat being a row. A row deserves an ID. IDs let you...

      • Work with stats that have very similar names
      • Identify disparate bits of data without worry that a typo will lead to bugs
      • Stack categories in an attribute name like so: &_stat.3>2>47>5 JimBob=Cool gun stats here!

      I've got it about to the point where it will store both indexed and non-indexed data reliably and distinguish safely between the two, and have added the appropriate getdata function for it (accepts index OR attribute name), but I feel like I need to kick it more solidly before I release it. I also need to finish writing test code for it.

      I guess the answer to your question, @Thenomain, is... why would anyone need to store 25,000+ pieces of data (and not use SQL)? Coders, man. 😄 But also because it's easy and fun. I'm sure there are other ways to solve it, but this one took three lines - create(), tel(), set(). Everything else is gravy.

      posted in MU Code
      M
      Melpomene
    • TinyMUX: Info Storage

      Re: Information Storage Question

      So this came up in my own code. Some info for TinyMUX users with standard installs:

      • Data in a single attribute: 8000 characters counting the attribute name, plus attribute settings and seemingly some other weirdness, so really somewhere in the neighborhood of 7900 characters if you don't want to risk cutting it off.

      • Max attribute name length without data loss: 63

      • Attributes on a single object: I got up to 2665 in a number of tests with full-named attributes all filled with 7900+ characters of data, but some of my other tests I managed only as high as 2513, so decided to cut it off at 2500. Again, some kind of attribute naming scheme weirdness.

      • Number of attributes able to be stored on an object does not appear to have anything to do with the object's memory as reported by objmem() - you get the same results if you just put in a 1 for the value and use simple numeric attribute names.

      Testing methodology:

      @wait me=th attrcnt(#672)
      @dolist/notify lnum(700)=@set/quiet #672=_L.##:1
      

      Repeat in increments of 700 until object won't take anymore. MUX fails silently so you'll have to keep an eye on it.

      Next test:

      @dolist/notify lnum(700)=@set/quiet #672=_L.##.[iter(lnum(rand(sub(59,strlen(##)))),pickrand(a b c d e f g h i j k l m n o p q r s t u v w x y z),,@@)]:[repeat(0123456789, 799)]
      

      Screwing around like that got me the "magic" numbers above.

      I decided I didn't want to worry about this crap so I'd write code to do it for me. That code had the following requirements:

      1. Pure MUX. I leave the SQL to someone willing to write something that will do it right in a non-blocking fashion.
      2. Store at least 20k attributes.
      3. Do it all behind-the-scenes, no wizard intervention required when things get over-stuffed.
      4. Must not lose data. MUX's "I eat data for breakfast" habit bugged me.
      5. Must function transparently to the coder using it - so just like set().
      6. Be expandable in case 20k isn't enough.

      From that came this code, including all the documentation I could think of:

      @create Data Storage Functions <DSF>=10
      @set DSF=safe inherit
      
      @@ Unique key goes here. Required if you want to call this from code without
      @@ opening the function up to everyone.
      
      &vK DSF=UNIQUE KEY HERE
      
      
      @@ Exercise caution expanding this. On MUX with extensive testing I've found that
      @@ you can push this up to 2662, but my tests were inconclusive when I started
      @@ playing with attribute length. Data loss is possible with values higher than 2550.
      @@ Playing it safe and setting this low enough that there's lots of room.
      
      &d.max-attributes DSF=2500
      
      @@ From my tests, these work. 7900 because I ran into trouble with numbers past
      @@ 7940 with long attribute names. Rounding a bit because I like round numbers.
      
      &d.max-attr-name-length DSF=63
      
      &d.max-attr-value-length DSF=7900
      
      @@ Who can run this? Strong recommendation: at least wizard. Should take care of
      @@ your inherit objects and code stuff - we only want this being called by
      @@ system code if possible. Since I couldn't find a lock method that actually
      @@ worked I stuck in a unique key. Fix this if you know what the heck you're
      @@ doing.
      @@
      @@ Arg:
      @@  %0 - Unique key, if there is one.
      
      &l.canset DSF=or(gte(bittype(%#), 5), strmatch(%0, %vK))
      
      @@ Find the first parent that does NOT hit the attr cap, or the parent that
      @@ has the attribute on it, if it already exists.
      @@
      @@ Arg:
      @@  %0 - target object to parent
      @@  %1 - target attribute
      
      @@ Note: I don't like the naming convention here, but can't think of a better one.
      @@ If the name is too long (more than 399 characters on my game) it just gets
      @@ partially eaten. The objects are still there. I didn't implement a count
      @@ because I didn't want to call yet another function to get the number of
      @@ parents, since MUX doesn't have lparents(). The less recursion the better.
      
      &f.find-first-free-parent DSF=
      	if(
      		or(
      			lt(attrcnt(%0), v(d.max-attributes)),
      			hasattr(%0, %1)
      		),
      		%0,
      		if(
      			t(parent(%0)),
      			ulocal(f.find-first-free-parent, parent(%0), %1),
      			null(strcat(
      				setr(0, create(name(%0) - DSP %0, 10)),
      				parent(%0, %q0),
      				set(%q0, safe),
      				tel(%q0, loc(%0))
      			))%q0
      		)
      	)
      
      @@ Set the data (global user function, should be wiz-only)
      @@
      @@ Args:
      @@  %0 - target object
      @@  %1 - attr name:value (just like set())
      @@  %2 - optional key, required for calling if not a wizard
      @@ Results: Nothing, just like set().
      
      &f.global.setdata DSF=
      	case(1,
      		not(ulocal(l.canset, %2)),
      		#-1 ERROR: HIGHER PERMISSIONS REQUIRED.,
      		gt(strlen(%1), v(d.max-attr-value-length)),
      		#-2 ERROR: TOO MUCH DATA.,
      		not(strmatch(%1, *:*)),
      		#-3 ERROR: INVALID DATA FORMAT. MUST BE NAME:VALUE.,
      		gt(strlen(first(%1, :)), v(d.max-attr-name-length)),
      		#-4 ERROR: ATTRIBUTE NAME TOO LONG.,
      		if(
      			or(
      				t(setr(0, set(ulocal(f.find-first-free-parent, %0, first(%1, :)), %1))),
      				eq(strlen(%q0), 0)
      			),
      			@@(All good. Say nothing!),
      			%q0
      		)
      	)
      
      
      @@ All done! Anything past this point is gravy.
      
      @@ -----------------------------------------------------------------------------
      
      @@ Set function up on #1 with:
      @@ @startup #1=@fo me=@function/privilege/preserve setdata=#DBREF_OF_DSF_GOES_HERE/f.global.setdata
      @@
      @@ The function needs privilege to create its own objects and set data on things.
      @@ It needs preserve because we use %q0 in there and don't want to overwrite something else's %q0.
      @@ Because it's a privileged function, we need some other way to lock it down, thus the UNIQUE KEY thing.
      
      @@ Call function wherever you would call set(target, attrname:attrvalue) like so:
      @@ setdata(target, attrname:attrvalue)
      
      

      And some test code to use it...

      @@ And here's a simple tester. All it does is let staff AND PLAYERS add data to
      @@ a specified object. Because it has its own unique key, it can do that. If you
      @@ want to restrict it to a specific bit type, @lock it. This is just a proof of
      @@ concept.
      @@
      @@ Commands:
      @@  +setdata <attr>=<value>
      @@  +setdata/quiet <attr>=<value>
      @@  +getdata <attr>
      @@  +datastats
      
      @create Basic Data Storage Object <BDSO>=10
      @set BDSO=safe
      
      @create Data Storage Command Tester <DSCT>=10
      @set DSCT=safe inherit
      
      @fo me=&vD DSCT=[num(BDSO)]
      
      &vK DSCT=UNIQUE KEY HERE
      
      @@ Get all the data objects.
      @@
      @@ Args:
      @@  %0 - target object
      @@ Results: Nothing, just like set().
      
      &f.list-parents DSCT=if(t(parent(%0)), parent(%0) [u(f.list-parents, parent(%0))])
      
      @@ Set the data loudly.
      @@ Format: +setdata attrname=attrvalue
      @@ Result: "Set." or error.
      
      &cmd-+setdata DSCT=$+setdata *=*:@pemit %#=[if(or(t(setr(0, setdata(%vD, %0:%1, %vK))), eq(strlen(%q0), 0)), Set., %q0)];
      
      @@ Set the data quietly.
      @@ Format: +setdata attrname=attrvalue
      @@ Result: Nothing unless there's an error.
      
      &cmd-+setdata/quiet DSCT=$+setdata/quiet *=*:@switch [setr(0, setdata(%vD, %0:%1, %vK))]=,{},@pemit %#=%q0;
      
      @@ Get the data.
      @@ Format: +getdata attrname
      @@ Result: Data or a list of possible attributes it could be on using lattrp.
      
      &cmd-+getdata DSCT=$+getdata *:@pemit %#=[if(t(setr(0, xget(%vD, %0))), MSG: Your data is: %q0, MSG: Attribute not found. Did you mean: [lattrp(%vD/%0*)]?)];
      
      @@ Show some data stats.
      @@ Format: +datastats
      @@ Result: The stats.
      
      &cmd-+datastats DSCT=$+datastats:@pemit %#=[repeat(-, 80)]%RBase object: %vD%RParents: [setr(P, [u(f.list-parents, %vD)])]%R[iter(%vD %qP, if(t(itext(0)), [repeat(-, 80)]%R[itext(0)] Name: [name(itext(0))]%RAttributes: [attrcnt(itext(0))]%RObject memory used: [objmem(itext(0))]%R),,@@)][repeat(-, 80)]
      
      

      I dunno how to solve the key issue, I have a headcold. You could solve just by making the function not-wizard, but then it fails at its primary requirement.

      Throwing this up there in case someone besides me finds it useful and can solve the tricky bits.

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

      Found one that looks like it would work as a front end: MyBB It's got the group messaging thing, it's free, and it's MySQL-based, so poof, you can write a MU front-end for it to help out those users who don't want to pop open a browser.

      Personally I'd be happy with a system that notified me to check the forums on the game when something new came up. Maybe with links. No need to actually replicate the content in the game itself. But that's me, I'm not sure I use the game like a normal person.

      @Cobaltasaurus I hate to say it, but it's precisely because users aren't coders that I believe they want a web-based, or at least web-like, solution. They take one look at aJobs' code and quit, and by default, it doesn't do exactly what they want it to, so they all want/need at least small changes. Forums and point-and-click are way more intuitive. No having to remember the typed-out commands, no confusion between staff role and player role jobs... and if it works right, you even get those phone notifications people like. Wheeeeee.

      posted in MU Questions & Requests
      M
      Melpomene
    • RE: Anomaly Jobs: +myjob/cc

      @Rook I think that's what this forum exists for: derailing. XD I'm not up on my forum software and surfing the web isn't turning up much for forum software with "group messaging". It is apparently a thing, though - gaming forums use it for private Let's Plays. You know of any software that fits the definition?

      Also, what is this site running? I like its functionality but it lacks group messaging - maybe we could hack it in with a plugin or source edit.

      posted in MU Questions & Requests
      M
      Melpomene
    • RE: Anomaly Jobs: +myjob/cc

      @Rook The more I think about it, the more convinced I am that users want forums rather than bug tracking software. I can't see it being easy to find a forum software that fits those requirements either, but at least with that, private messages are an option. Maybe even private group messaging, which would take care of 1 and 2.

      posted in MU Questions & Requests
      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: Request: Halp!

      @Chime If you ever get around to doing that, gimme. 😄

      Have you got that vtables function documented anywhere? I would've used it if I'd known you didn't have to specify column widths, but the code I found didn't include documentation and taking apart someone else's code is always a PITA. I just want to know what format it expects things in.

      I found myself (mostly out of sheer "I CAN code so I WILL code!") making the equivalent of vtables in a different way: it expects a string formatted with two delimiters like so: a|b|c|d~e|f|g~h|i|j|k|l~m|n|o~p|q|r|s|t~u|v|w~x|y|z - and the two delimiters, and it outputs the whole set as a list of columns, fitting them to whatever width is available.

      Gimme if you've got it, reinventing the wheel is fun but I'm not sure I'm doing the world any good. 😉

      posted in MU Code
      M
      Melpomene
    • RE: Request: Halp!

      @Thenomain I don't think it was me figuring it out (I wouldn't know how to make it faster, f'rex) as much as seeing a div() and going "Oh! Arbitrary number of columns!" and then extrapolating. 😉 I am still not what I would consider "up" on the MU*code. Witness the fact that I forgot all about strtrunc and was using mid throughout my code! :facepalm:

      One of these days I will consider myself decent at this stuff. What strikes me as awesome about MUcode is this: it may look like spaghetti, it may be under-documented and a little obtuse... but it's remarkably good at getting the job done. I know of no other language that works with strings as well as MUcode does. (Perl does not count except for its regex abilities, which are murder and ought to be against the Geneva convention.)

      Also, in case that post was confusing for anyone (it could happen, it happened to me!), I am not Chime. 😄

      posted in MU Code
      M
      Melpomene
    • 1
    • 2
    • 1 / 2