ID:2006540
 
Code:
//...The properly working proc
ShowStats()
src << "\n===Current Skills===: \n1: [ActiveSkills["skill1"]] \n2: \n3: \n4: \n5: \n6: \n7: \n8: \n9: \n===Passive Abilities===: \n10: \n11: \n12: \n13: \n14: \n15:\n===Cultural Abilities=== \n16: \n17: \n18:"

//note that the object, which is the skill name... we'll call it "Summon Giant Plush Ferret"...shows up as intended.

//However, another proc, using the same index "skill1" will return null. Calling ShowStats() will still show it is being there. Below is a code snippet from the "command" switch statement which handles text commands.

if ("cast")
//cast (slotnum) on (mobname) on a specific target
//cast (slotnum) will also work if attacking or if the spell targets self or room.
var/list/temp = Parse(list(" "),GetAttribute(command,t,scissors=" "),null,null,TRUE,null)
var/mob/target
if (temp.len == 3)
//We have 3 arguments, so find the mob.
target = CurrentRoom.Search(temp[3])
else if (temp.len == 1)
target = auto_attack_target
if (target)
//Now we try to grab our skill.
var/Skill/s
switch(temp[1])
if ("1","2","3","4","5","6","7","8","9","10")
//src << temp[1]
s = ActiveSkills["skill[temp[1]]"]
if ("c1","c2","c3")
temp[1] = copytext(temp[1],2,3)
s = ActiveSkills["cultural[temp[1]]"]
else
src << "Invalid slot!"
return
src << s
var foo = temp[1]
src << ActiveSkills["skill[temp[1]]"]
src << ActiveSkills["skill1"]
src << ActiveSkills.len
src << ActiveSkills["skill[foo]"]
src << ActiveSkills["skill1"]
src << temp[1]
src << "skill[temp[1]]"
src << ActiveSkills["melee attack"]
for (var/v in ActiveSkills)
src << "[v]: [ActiveSkills[v]]"

if (s)
if (s.CheckUsable(src,target))
//src << "1"
//src << s
spawn() s.Execute(src,target)
else
src << "There is no ability in that slot."
return

/*
Output:

>cast 1 on w

<--ActiveSkills["skill[temp[1]]"]
<--ActiveSkills["skill1"], tried to straight up access it without any concatenation
2 <--ActiveSkills.len, shows two skills in list as expected
<--ActiveSkills["skill[foo]"], tried switching with a non list concatenation in case it was that old bug where you couldn't access lists with indices being from other lists
<--ActiveSkills["skill1"], this time copied and pasted from the other proc because why not?
1 <--temp[1], to make sure we aren't having any stray characters
skill1 <--Double checking the concatenation
<--ActiveSkills["melee attack"], null. There is supposed to be a /Skill there.
---for loop---
melee attack: Melee Attack
skill1: Summon Giant Plush Ferret

The skills appear using the var/v in ActiveSkills for loop.
Conclusion: something dun broke
*/


Problem description:
Generally what's happening is that the typical way of accessing associative lists returns null for this one proc.

The expected result is to return the atom (which is normally the name of the atom) but this time it isn't returning it. However, it does return it in a proc that just lists your stats. After testing it to see if it's just me, it turns out I can verify that something is amiss.

The obvious workaround for this strange issue is to use a for loop, and return the skill from within the loop since it seems to access properly from there. Has anyone else encountered this issue?

Edit: I'll keep testing on my end to see if anything else is the problem (or I am missing something painfully obvious as can happen).

Edit2: Nevermind, the workaround does not work and instead returns null.

Edit 3: I have found the problem!
It appears that using the << operator alone in an associative list returns null when used with the << operator, but the data is just fine. Encapsulating it in quotes causes it to function as normal.

src << ActiveSkills["skill1"] //returns a null value/empty string? Will confused anyone trying to find problems
src << "[ActiveSkills[skill1]]" //returns Summon Giant Plush Ferrets, or, the actual value in list[index].
var/Skill/s = ActiveSkills["skill1"] //puts the expected atom there


This appears to be a bug with the latest update, was present in the last version as well.</<></<>
I'm going to go ahead and assume whatever's in activeSkills is a bunch of datums? In which case 'src << activeSkills["skill1"]' will output nothing, since datums don't have a name by default, there's nothing to output. You can't output the actual datum. If you go ahead and add a name var to your datum like

Skill
var
name = "Screeching Turtle Stance"


Then you should see that name instead of nothing, though I might be wrong on that.

From what I can see though, no bugs are happening here.
In response to Rushnut
Rushnut wrote:
I'm going to go ahead and assume whatever's in activeSkills is a bunch of datums? In which case 'src << activeSkills["skill1"]' will output nothing, since datums don't have a name by default, there's nothing to output. You can't output the actual datum. If you go ahead and add a name var to your datum like

> Skill
> var
> name = "Screeching Turtle Stance"
>

Then you should see that name instead of nothing, though I might be wrong on that.

From what I can see though, no bugs are happening here.

After a bit of thought, I realized I just may have ran into a caveat that I never realized (and I don't think it was explained anywhere, or I missed it).

If you encapsulate a datum with quotes in m << SomeDatum, you'll get "/SomeDatum" in chat, and if it is a standard atom you'll get "the (area/turf/obj/mob)". If you were to, say, have an atom with an icon in (and I have done this numerous times):

atom/a = SomeFuntionToGetAnAtom()
SomeDatum/s = new
src << someAtom //No quotes, yields icon (if available) + atom.name
src << "[someAtom]" //Yields just the name
src << s //Yields null
src << "[s]" //Yields /SomeDatum


Lots of confusion arose since this is a revision of the old /Skill datum I wrote; the old one used the parent type /obj (which would further reinforce the caveat). The fact that one of my functions in the datum were buggered and the fact that there was a safety check (the if (s), to make sure we have a skill) also made me think that no /Skill was being returned or something was really, REALLY broken.

Thanks for the reply!
Have you tried giving the datum a name?
In response to Rushnut
Rushnut wrote:
Have you tried giving the datum a name?

Actually, it did have a name var (how else would I identify them quickly?).
An id tag or some reference or something, I don't know. All I do know is datums don't have a name var by default.
In response to Rushnut
Rushnut wrote:
An id tag or some reference or something, I don't know. All I do know is datums don't have a name var by default.

Well, they wouldn't, as mentioned above I just expected DM to toss a name/type by default or something other than null.
I'm not sure this is a bug so much as an inconsistency in what you would expect.

When you attempt to encapsulate a datum descendant in a string, the engine will first look to see if the instance has a name variable and attempt to use that. If there is no name variable, it will fall back to type.

However, the << operator has a few different contexts that it can be used for.

When the right hand operand is a string, it will attempt to send the text as a message if the left hand operand is a client or mob with a connected client.

When the left hand operand is a savefile, the right hand operand will be pushed into the buffer.

When the right hand operand is an /image, the left hand operand being a client/mob will insert the image object into the client's images list.

When the right hand operand is an /icon, the left hand operand being a client/mob will receive the image as part of a text output.

Again, I think this is simply due to the engine's growing pains where some specificity is required because a single operation was hamfisted into a number of different uses before the language really started to find a firm standard.
In response to Ter13
Ter13 wrote:
I'm not sure this is a bug so much as an inconsistency in what you would expect.

When you attempt to encapsulate a datum descendant in a string, the engine will first look to see if the instance has a name variable and attempt to use that. If there is no name variable, it will fall back to type.

However, the << operator has a few different contexts that it can be used for.

When the right hand operand is a string, it will attempt to send the text as a message if the left hand operand is a client or mob with a connected client.

When the left hand operand is a savefile, the right hand operand will be pushed into the buffer.

When the right hand operand is an /image, the left hand operand being a client/mob will insert the image object into the client's images list.

When the right hand operand is an /icon, the left hand operand being a client/mob will receive the image as part of a text output.

Again, I think this is simply due to the engine's growing pains where some specificity is required because a single operation was hamfisted into a number of different uses before the language really started to find a firm standard.

I figured it was probably an inconsistency (as mentioned in my next to last post. Still, it's a good discussion to have for future readers who get surprised by this, I say.
Yeah, what I find most interesting is that the stringification is using a look-down model for getting the name of an object. It expects that name will be defined on a datum later in the hierarchy than it actually appears, which is... Highly unusual.
In response to Ter13
Ter13 wrote:
Yeah, what I find most interesting is that the stringification is using a look-down model for getting the name of an object. It expects that name will be defined on a datum later in the hierarchy than it actually appears, which is... Highly unusual.

Unusual, but highly useful for keeping track of things and aiding in finding some bugs (well, for identifying which objects are where, anyway).