2 Status Attributes on same line

If someone wants to put two status attributes on the same line (like player. Alias followed by player. Score), how is that done?

Usually by making an attribute which contains the other two connected together; and using a changescript to update it. For example, you could set both the player's changedalias and changedscore script attributes to be:

this.aliasandscore = this.alias + " " + this.score

And then add the new aliasandscore attribute as a status attribute.

Excellent! And so easy as that! Thank you.

(okay, so I tried it, but I made some mistake.)

I pasted the code into a player script attribute called aliasandscore, changed every this to player, then, made aliasandscore a status attribute that would display only ! .
Error running script: Error compiling expression 'Replace(format, "!", value)': FunctionCallElement: Could find not function 'Replace(String, String, LazyLoadScript)'

I don't know.

I said:

set both the player's changedalias and changedscore script attributes

you said:

I pasted the code into a player script attribute called aliasandscore

Those aren't the same names. The Quest engine will automatically run a script attribute named changedalias when the player's alias changes; and run an attribute named changedscore when their score attribute changes.

The aliasandscore attribute is the one that these scripts set; so you can use it as a status attribute.


changed every this to player,

That won't break anything, but it's also not necessary. this is a reserved word meaning "the object that has this script attribute". I tend to use it, because it makes the script more resilient and less likely to be broken by future changes (guarding against hard-to-understand errors later in development)

Generally, if I'm posting bits of code, I'll use a different colour to highlight any names you need to change :)

Mrangel, this looks very similar to an error I'm working on in Pixie's combatlib. He's got something called a multi-attack monster. You drop several objects inside the monster, and his library scripts are meant to randomly pick one of the objects and then run the attack script using those attributes.

The error that comes back when the second attack comes in is like this:

Error running script: Error compiling expression 'Replace(this.attackdesc, "%", CapFirst(GetDisplayAlias (owner))) + " and misses."': FunctionCallElement: Could find not function 'Replace(Object, String, String)'

Which looks very like what Jennifer Wren's error is saying.... but reading this combined with your discussion here gives me an idea!

What if it's missing a required attribute? "attackdesc" isn't filled out on that second attack.... let me check...

Yes! That was it! You solved one of my problems while solving Ms. Jennifer's! all the library wants is an addition to the editor here "Required for multi-attack types" and probably also to be also on the appropriate combat tabs in the editor instead of only the "description" tab. That way when it is a monster attack, it's right with all the other fields that define it.

Thanks Mr. Angel. You're a hero in this forum! And also thanks Jennifer for your part in the inspiration and encouragement. It's encouraging to also see other folks learning as they try to build games!

Okay, I am a little bit confused. Can I make two identical player attributes, name one changealias and one changescore, set both to script, paste the script for this.aliasandscore into both, alike?
Then, if I do that, what would the "aliasandscore" attribute be?
And how would I express that in the status attribute? With just a ! ? Or with another copy of the same script? Or something else?
I have never had to create a changealias or changescore attribute, before. I have never created a changeattribute of any kind. I'm sorry if I am unusually confused. I do really want to know this and use it.

Oh, okay, I think I have it working. Amazing!!!

I'm so excited for you Jennifer!

For folks who saw this post and were completely confused, I found the place in the documentation that talks about Status Attributes and that also links over to documentation on change scripts at that bottom under "advanced options"

That means Jennifer is becoming advanced!!



Okay, I am a little bit confused. Can I make two identical player attributes, name one changealias and one changescore, set both to script, paste the script for this.aliasandscore into both, alike?

Yes. That's what I said you should do. But I should point out that the names are changedalias and changedscore; the word "changed" at the start of a script attribute's name has special behaviour.

And how would I express that in the status attribute? With just a ! ? Or with another copy of the same script? Or something else?

Look at what the script does - it creates an attribute whose name is aliasandscore, and whose value is the alias and the score joined together.

So you can add aliasandscore to be a status attribute, treating it like any other attribute. In this case, ! is probably exactly what you want.

Alternate answer:
It may be worth noting that a while ago I posted a piece of code in the forums which makes it easier to do complex stuff with status attributes, not needing changescripts at all… could be worth looking up if there's more than one attribute you want to do this kind of stuff with

If you include this function in your game, then you could just use alias + " " + score as an attribute name in the list of status attributes, and it should just work. (The function mentioned in that post replaces one of the ones in the core library, changing the way status attributes are processed)

Thankyou, mrangel, for the link. I will look into that. In the meantime, I was just surprised that it would take creating "changedscore", "changedalias", and "aliasandscore", on top of "score" and "alias". I was also unsure of needing to paste the same script in three attributes with nothing but name being different in them. (And I knew there could be something else I had to do with it, but what.)
However, I did try it out. Notice I posted that right after the previous reply. And was I ever surprised that it actually worked!
Thanks, again. Sorry it took me a while to figure out what you were saying, when it was actually not not in code, but entirely clear, and all of the instructions were right there in front of me. I just didn't believe they were.


Thank you for linking to that code. I must have missed it when you first posted. You're something of a coding genius, and I don't understand exactly what the code says and does. But I save your suggestions, and look at them to see if new things I've learned can help me understand.

I've really only just discovered changedscripts and am seeing how they really work to make status attributes effective when combined with something like calling a function, or checking to see if the attribute is at a certain level.

Your brilliant code from the other post... does it essentially create a way for people to use status attributes more directly in the functions and scripts instead of using a change script to fire the functions and scripts?

Are you able to translate your code down to newbie language and say what the different parts of it do?

The first line, for example. It looks like it creates a function and gives it a name, then sets the names for what the expected parameters will be. Then sets the function to return a string?

With function "returns," I'm not really sure what goes on. The parts of the functions I sort of understand are that you tell them to do something with the parameters, or do something on their own.

So it seems to check and if statusAttributes already exists in the next line

and if it does, it creates a new dictionary named params

then uses a foreach which if I understand it correctly reads a list based on understanding what's in all those parenthesis.
and in this case adds whatever it was looking for to the the new dictionary.

The second foreach reads the statusAttributes dictionary and finds every "attri" for attribute?
and looks like it's adding the attributes to a list with a very complicated name that really must be some sort of parsing behavior?

Sometimes I imagine that thinking out loud in front of a genius can help them see how much we are or are not understanding about what they're saying.

Thanks for all that you do MrAngel. You really are a hero in these forums.

Are you able to translate your code down to newbie language and say what the different parts of it do?

That one is a little tough to explain; because it's designed to replace one of the core functions; so it has to be similar enough to the original that it will work as one part of an existing system.
It's actually a really inefficient way to solve that problem, but making it work efficiently would also mean making the code much more complex.

I can come up with a step-by-step explanation if you want; but not sure how newbie friendly I can make it.

I'll take the complicated one, then, and keep it in my "study" pile for homework haha

Are you able to translate your code down to newbie language and say what the different parts of it do?

OK :)

Here's a brief explanation of how that function works…

Click to expand
<function name="AddStatusAttributesForElement" parameters="status, element, statusAttributes" type="string">
We're overriding one of the default functions here. AddStatusAttributesForElement is called once for each statusattributes dictionary (of which there are 3 in different places). Its parameters are: * `status` - a stringlist, containing the lines of HTML for the status attributes panel. The function is expected to modify this list * `element` - the object whose attributes are being examined; this will usually be either `game` or the player object * `statusAttribute` - the statusattributes dictionary for that object
  •  if (not statusAttributes = null) {
    Fairly obvious - don't do all the expensive processing if there are no status attributes
  •   params = NewDictionary()
      foreach (attr, GetAttributeNames (element, true)) {
        dictionary add (params, attr, GetAttribute (element, attr))
    Here we're making a dictionary of all the attributes of the specified object. This is pretty inefficient with regards to memory; but only finding the attributes we need could be more complex than you would expect.
  •   foreach (attr, statusAttributes) {
        list add (status, FormatStatusAttribute(attr, eval (attr, params), StringDictionaryItem(statusAttributes, attr)))
    Then we loop over the entries in the status attributes dictionary, calling another built-in function, and adding the HTML it returns to the list.
    • The normal invocation of this function would be something like: FormatStatusAttribute ("health", 95, "Health: !%") - it formats the line for one status attribute, putting the value into the format string.
    • The change here is the second attribute:
      eval (attr, params)
      • eval takes a string and evaluates it as a Quest expression. So it could be something like 3+5 or health.
      • If you pass a second dictionary parameter to eval, its keys become local variables for evaluating that bit of code; just like the optional final parameter to invoke or do. In this case, we're passing it the key from the statusattributes dictionary, and a dictionary of all the attributes of the chosen object. So in the health example, the expression could be health and the dictionary contains all the attributes of the player object, so it just returns the local variable health - the same as the default behaviour
      • If the key is something like alias + " " + score, the expression is processed normally - and the attributes of the appropriate object are accessible as if they were local variables. That means you can put functions in here, or anything you want. It can be any function that returns a string ☺
      • And FormatStatusAttribute gets the result of that expression, instead of just a single attribute

Hope that makes some sense!

Fascinating! It does make some sense, though I need to learn a little bit more to understand all of it. I can see I would want to look at the original function to compare with what's changing. I did learn something immediately: I'd misunderstood the
if (not statusAttributes = null) {
line before. My brain was reading "If status attributes don't equal null" But your explanation reminds me that I have to read these lines "If there are no statusAttributes then 'null'." Which 'null' translates to "stop processing this function"

Sometimes I misread lines like that, and it takes me a while to figure out what it's actually saying on my own. So I'm very glad you shared your explanation. I'll continue to study it, and also return to it as I learn more about dictionaries.

Log in to post a reply.