Attributes of type "object"...
gernotg
23 Jan 2014, 08:20Hello everyone,
Let's say my player is currently fighting a group of monsters. I want to store the monster that the player is currently attacking in an attribute called current_target. The idea is that during peaceful times, the attribute would not be set, but if the attribute is set, then the player will continue to attack that particular target.
It seems to me like that would be a reasonable thing to try to do, but the problem is that it doesn't appear to be legal not to specify a valid object in the declaration. Specifying "null" also doesn't appear to work. At first, I tried to get around that by pointing the object to the player himself to indicate that he's not currently attacking a monster, and that worked reasonably well.
<object name="player">
<inherit name="defaultplayer" />
<attr name="current_target0" type="object"></attr> // <-- This isn't legal
<attr name="current_target1" type="object">null</attr> // <-- This isn't legal either
<attr name="current_target2" type="object">player</attr> // <-- This is legal, though not very elegant
</object>
Note that during the game, I can set the attribute to null and compare it to null, but I can't get this to work in the declaration.
But now, I want to put this attribute into a type, to be inherited by players and monsters, and I also put this type into a separate library file, and this trick no longer works. In order to be universal, the type attribute of course can't point at the player, and even the game object doesn't exist yet when the library is loaded.
I suppose I could create a library that defines something like <object name="null_object"></object>, but null_object and null would still not be the same later on during the game. Am I really the first person to run into this? It seems to me that there should be a more elegant solution...
Let's say my player is currently fighting a group of monsters. I want to store the monster that the player is currently attacking in an attribute called current_target. The idea is that during peaceful times, the attribute would not be set, but if the attribute is set, then the player will continue to attack that particular target.
It seems to me like that would be a reasonable thing to try to do, but the problem is that it doesn't appear to be legal not to specify a valid object in the declaration. Specifying "null" also doesn't appear to work. At first, I tried to get around that by pointing the object to the player himself to indicate that he's not currently attacking a monster, and that worked reasonably well.
<object name="player">
<inherit name="defaultplayer" />
<attr name="current_target0" type="object"></attr> // <-- This isn't legal
<attr name="current_target1" type="object">null</attr> // <-- This isn't legal either
<attr name="current_target2" type="object">player</attr> // <-- This is legal, though not very elegant
</object>
Note that during the game, I can set the attribute to null and compare it to null, but I can't get this to work in the declaration.
But now, I want to put this attribute into a type, to be inherited by players and monsters, and I also put this type into a separate library file, and this trick no longer works. In order to be universal, the type attribute of course can't point at the player, and even the game object doesn't exist yet when the library is loaded.
I suppose I could create a library that defines something like <object name="null_object"></object>, but null_object and null would still not be the same later on during the game. Am I really the first person to run into this? It seems to me that there should be a more elegant solution...
gernotg
23 Jan 2014, 09:29Ugh, never mind. Simply not declaring the attribute works just fine. It really a little mind-boggling to me, but I guess that's part of what makes it interesting.
Maybe we can document this somewhere in the wiki...
Maybe we can document this somewhere in the wiki...

jaynabonne
23 Jan 2014, 21:29Quest doesn't have an "uninitialized" value for object attributes. You use the presence or absence to determine existence, if necessary. (If you use GetAttribute, it will return null if the attribute doesn't exist, so that is a convenience.) You could, in theory, define a NullObject to be a value holder if you really needed it, but usually you don't.
Quest follows more the JavaScript model for objects and attributes, in that attributes can be set dynamically, at any time, to any type. You don't need to pre-declare them the way you do in typed languages like C++. Also, you can reassign an attribute at runtime to different types. First it can be a string, then an integer. (I have used this to good effect myself.)
Assigning null to an attribute has the effect of deleting it from the object. You can never have an attribute (of any type) with value null.
You've come across the right solution - don't assign the attribute until you need it. And if you use GetAttribute to query it, you'll get null back if the attribute is not defined.
Quest follows more the JavaScript model for objects and attributes, in that attributes can be set dynamically, at any time, to any type. You don't need to pre-declare them the way you do in typed languages like C++. Also, you can reassign an attribute at runtime to different types. First it can be a string, then an integer. (I have used this to good effect myself.)
Assigning null to an attribute has the effect of deleting it from the object. You can never have an attribute (of any type) with value null.
You've come across the right solution - don't assign the attribute until you need it. And if you use GetAttribute to query it, you'll get null back if the attribute is not defined.
HegemonKhan
23 Jan 2014, 22:34an easy solution if you don't mind using it, is this:
(forgive me, as I'm still trying to learn equipment coding, and understanding object lists, so this code of mine may not work as it's probably not done correctly)
many people with (weapon) equipment do this (a quick example of my own making)
making a "null-in-effect" Object, ie: "unarmed~fists~HtH~Hand-to-Hand"
as this way you can exchange between your "null" (unarmed) Object and your "real" (wooden sword) object...
<object name="player">
-> <inherit name="editor_object" />
-> <inherit name="editor_object" />
-> <attr name="equipped_weapon" type="object">unarmed_weapon</attr>
</object>
<object name="global_storage_object">
-> <inherit name="editor_object" />
-> <object name="unarmed_weapon">
->-> <inherit name="editor_object" />
->-> <alias>unarmed</alias>
->-> <attr name="damage" type="int">1</attr>
-> </object>
-> <object name="wooden_sword_weapon">
->-> <inherit name="editor_object" />
->-> <alias>wooden sword</alias>
->-> <attr name="damage" type="int">10</attr>
-> </object>
-> <attr name="weapon_object_list">unarmed_weapon;wooden_sword_weapon</attr>
</object>
"equip" Verb:
show menu ("weapon or armor", split ("weapon;armor",";") {
-> if (result = "weapon") {
->-> show menu ("what weapon?", global_data_object.weapon_object_list, false) {
->->-> if (result = wooden_sword_weapon) {
->->->-> wooden_sword_weapon.parent = player
->->->-> player.equipped_weapon = wooden_sword_weapon
->->-> } else // ... etc
(forgive me, as I'm still trying to learn equipment coding, and understanding object lists, so this code of mine may not work as it's probably not done correctly)
many people with (weapon) equipment do this (a quick example of my own making)
making a "null-in-effect" Object, ie: "unarmed~fists~HtH~Hand-to-Hand"
as this way you can exchange between your "null" (unarmed) Object and your "real" (wooden sword) object...
<object name="player">
-> <inherit name="editor_object" />
-> <inherit name="editor_object" />
-> <attr name="equipped_weapon" type="object">unarmed_weapon</attr>
</object>
<object name="global_storage_object">
-> <inherit name="editor_object" />
-> <object name="unarmed_weapon">
->-> <inherit name="editor_object" />
->-> <alias>unarmed</alias>
->-> <attr name="damage" type="int">1</attr>
-> </object>
-> <object name="wooden_sword_weapon">
->-> <inherit name="editor_object" />
->-> <alias>wooden sword</alias>
->-> <attr name="damage" type="int">10</attr>
-> </object>
-> <attr name="weapon_object_list">unarmed_weapon;wooden_sword_weapon</attr>
</object>
"equip" Verb:
show menu ("weapon or armor", split ("weapon;armor",";") {
-> if (result = "weapon") {
->-> show menu ("what weapon?", global_data_object.weapon_object_list, false) {
->->-> if (result = wooden_sword_weapon) {
->->->-> wooden_sword_weapon.parent = player
->->->-> player.equipped_weapon = wooden_sword_weapon
->->-> } else // ... etc