2 Status Attributes on same line
![](https://i.imgur.com/t1XUS1Kb.jpg)
Jennifer Wren
09 Nov 2023, 19:34If someone wants to put two status attributes on the same line (like player. Alias followed by player. Score), how is that done?
mrangel
10 Nov 2023, 02:39Usually 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.
![](https://i.imgur.com/t1XUS1Kb.jpg)
Jennifer Wren
10 Nov 2023, 14:56Excellent! And so easy as that! Thank you.
(okay, so I tried it, but I made some mistake.)
![](https://i.imgur.com/t1XUS1Kb.jpg)
Jennifer Wren
10 Nov 2023, 15:23I 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)'
![](https://i.imgur.com/t1XUS1Kb.jpg)
Jennifer Wren
10 Nov 2023, 15:37I don't know.
mrangel
10 Nov 2023, 18:04I said:
set both the player's
changedalias
andchangedscore
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.
Also:
changed every
this
toplayer
,
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 :)
Ip Man
10 Nov 2023, 21:11Mrangel, 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!
![](https://i.imgur.com/t1XUS1Kb.jpg)
Jennifer Wren
11 Nov 2023, 02:02Okay, 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.
![](https://i.imgur.com/t1XUS1Kb.jpg)
Jennifer Wren
11 Nov 2023, 02:19Oh, okay, I think I have it working. Amazing!!!
Ip Man
11 Nov 2023, 05:23I'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!!
https://docs.textadventures.co.uk/quest/status_attributes.html
https://docs.textadventures.co.uk/quest/change_scripts.html
mrangel
11 Nov 2023, 21:43Okay, 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)
![](https://i.imgur.com/t1XUS1Kb.jpg)
Jennifer Wren
12 Nov 2023, 01:17Thankyou, 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.
Ip Man
12 Nov 2023, 21:57MrAngel
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.
mrangel
13 Nov 2023, 11:30Are 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.
Ip Man
16 Nov 2023, 04:38I'll take the complicated one, then, and keep it in my "study" pile for homework haha
mrangel
17 Nov 2023, 09:30Are 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
Fairly obvious - don't do all the expensive processing if there are no status attributesif (not statusAttributes = null) {
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.params = NewDictionary() foreach (attr, GetAttributeNames (element, true)) { dictionary add (params, attr, GetAttribute (element, 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.foreach (attr, statusAttributes) { list add (status, FormatStatusAttribute(attr, eval (attr, params), StringDictionaryItem(statusAttributes, attr))) }
- 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 like3+5
orhealth
.- 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 toinvoke
ordo
. 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 behealth
and the dictionary contains all the attributes of the player object, so it just returns the local variablehealth
- 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
- The normal invocation of this function would be something like:
Hope that makes some sense!
Ip Man
19 Nov 2023, 01:34Fascinating! 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.