ID:2407010
 
Descriptive Problem Summary:

When it comes to layering certain appearance part in my project, FLOAT_LAYERS are being manipulated and utilized as per the documentation. At that point, odd things occurs:

Clothing/Items generally are defined to FLOAT_LAYER-3, where additional input from players can manipulate it additionally down to FLOAT_LAYER-3.999.

Hair occupies FLOAT_LAYER-2

Items defined as hats/headpieces and various buff icons take FLOAT_LAYER-1

Finally auras take up FLOAT_LAYER as normal.

When it comes to interactions between headpieces and hair, it's perfectly predictable and replicable - no matter when each one is added, the headpieces will always go over hair. Likewise for buffs and auras. Likewise clothing and headpieces.

Problems occur when clothing is added after hair - and for some reason, it still goes on top of it, no matter how effectivelly low the FLOAT_LAYER is defined

Numbered Steps to Reproduce Problem:

1. choose hair
2. equip clothing
3. clothing ends up over hair

Code Snippet (if applicable) to Reproduce Problem:

Snippets from hair application code and item application code

if(src.TransActive()>=1 && src.Race=="Alien")
if(src.TransActive()==1)
if(src.Form1Hair)
Hair = image(icon=src.Form1Hair, pixel_x=Form1HairX, pixel_y=Form1HairY, layer=FLOAT_LAYER-2)
else if(src.TransActive()==2)
if(src.Form2Hair)
Hair = image(icon=src.Form2Hair, pixel_x=Form2HairX, pixel_y=Form2HairY, layer=FLOAT_LAYER-2)
else if(src.TransActive()==3)
if(src.Form3Hair)
Hair = image(icon=src.Form3Hair, pixel_x=Form3HairX, pixel_y=Form3HairY, layer=FLOAT_LAYER-2)
else if(src.TransActive()==4)
if(src.Form4Hair)
Hair = image(icon=src.Form4Hair, pixel_x=Form4HairX, pixel_y=Form4HairY, layer=FLOAT_LAYER-2)
else
if(HairB&&istype(HairB,/icon)&&src.Hair_Color)
HairB:Blend(src.Hair_Color, ICON_ADD)
Hair = image(icon=HairB, layer=FLOAT_LAYER-2)

src.overlays += Hair


obj/Items/proc/AlignEquip(mob/A)
var/placement=FLOAT_LAYER-3
if(istype(src,/obj/Items/Wearables))
if(src:LayerPriority)
placement-=src.LayerPriority
if(src:IsHat)
placement=FLOAT_LAYER-1
if(suffix)
suffix=null
var/icon/Icon=src.icon
if(istype(src, /obj/Items/Enchantment/Arcane_Mask))
Icon=icon('ArcanicEyes.dmi')
placement=FLOAT_LAYER-2
if(istype(src, /obj/Items/Wearables/Mask))
var/obj/Items/Wearables/Mask/M=src

var/image/T=image(M.OldIcon, pixel_x=M.OldX, pixel_y=M.OldY, loc = usr)
T.appearance_flags=68
world << T
spawn()
animate(T, alpha=255)
animate(T, alpha=0, time=3)
sleep(-1)
spawn()
usr.icon=M.OldIcon
usr.pixel_x=M.OldX
usr.pixel_y=M.OldY
animate(usr, alpha=0)
animate(usr, alpha=255, time=3)
sleep(-1)
spawn(3)
del T
sleep(-1)
usr.name=M.OldName
usr.playerdescription=M.OldDesc
usr.Text_Color=M.OldColor
else
var/image/im=image(icon=Icon, pixel_x=src.pixel_x, pixel_y=src.pixel_y, layer=placement)
usr.overlays-=im

else
suffix="*Equipped*"
var/icon/Icon=src.icon
if(istype(src, /obj/Items/Enchantment/Arcane_Mask))
Icon=icon('ArcanicEyes.dmi')
placement=FLOAT_LAYER-2
if(istype(src, /obj/Items/Wearables/Mask))
var/obj/Items/Wearables/Mask/M=src

var/image/T=image(icon=M.icon, pixel_x=M.pixel_x, pixel_y=M.pixel_y, loc = usr)
T.appearance_flags=68
world << T
spawn()
animate(T, alpha=0)
animate(T, alpha=255, time=3)
sleep(-1)
spawn(3)
M.OldIcon=usr.icon
M.OldX=usr.pixel_x
M.OldY=usr.pixel_y
usr.icon=M.icon
usr.pixel_x=M.pixel_x
usr.pixel_y=M.pixel_y
usr.alpha=255
del T
sleep(-1)
M.OldName=usr.name
usr.name=M.NewName
M.OldDesc=usr.playerdescription
usr.playerdescription=M.NewDesc
M.OldColor=usr.Text_Color
usr.Text_Color=M.NewColor
else
var/image/im=image(icon=Icon, pixel_x=src.pixel_x, pixel_y=src.pixel_y, layer=placement)
usr.overlays+=im


Expected Results:

Clothing always ends under hair.

Actual Results:

Clothing equipped later ends up covering the hair.

Does the problem occur:
Every time? Or how often? Every time.
In other games? N/A
In other user accounts? N/A
On other computers? N/A

When does the problem NOT occur?

It doesn't occur as far as every ther FLOAT_LAYER interaction is concerned

Did the problem NOT occur in any earlier versions? If so, what was the last version that worked? (Visit http://www.byond.com/download/build to download old versions for testing.) Occured on stable and over the recent betas.

Workarounds:

None found at the moment. Altering the FLOAT_LAYERS to different values keeps the behaviour same.
Moved to Developer Help. This thread should have been posted here to rule out development issues before making the assumption you were dealing with a BYOND bug. While I wouldn't say it's entirely possible to rule out a BYOND bug at this point, there are many, many things wrong with this code and that needs to be addressed first.

Additionally, for future reference, if this is a bug it is not a Dream Maker issue; a bug that impacts how layers are applied is most likely a Dream Seeker issue, possibly Dream Daemon since the server does some pre-sorting of float layers.

So the issues here:

1) You have usr in your alignment proc. This should never happen, because usr has no business in procs. You already have a reference to the mob you want, which is the A argument.

2) You're using the icon() proc to create a modifiable icon but then not actually using it for anything.

3) The istype() check for that mask is clunky and terrible. Instead you should define a special version of AlignEquip() for that mask alone, to override the main proc.

4) The : operator is being abused.

5) The var copying you're doing for that mask looks like it would be better served by copying the whole appearance, although I'm not clear on why you're doing that at all.

6) The placement var should almost certainly be an obj var, defined as part of the prototype, instead of being set by this proc.

7) In your hair application routine, you should ditch all of the icon blending. Using a color matrix will produce a superior result in terms of resources and performance.

8) The fact that you have 12 different vars for different "form" hair versions in the hair routine is indicative of a major design flaw. At worst that should be 3 lists with 4 items each, or better yet a single list with 12 items. I'd wager even that is probably unnecessary.

Those are just some of the more obvious issues. The logic here is weirdly complex for something that ought to be simple, and for that reason I strongly suspect some other similar issues are in play.

To determine why the clothing is taking on a different order than expected, my advice would be to add a debugging verb that you can use to examine the overlays and determine their layer and appearance flags, along with the layer and appearance flags of the mob itself. To assist you in this, it would be ideal if you gave every image a name (just setting it to the type path, when it's clothing, would do) so you could compare them.

Also, and this is very important: Are you looking at clothing and hair applied in the same session, or did the hair get saved with the character and then loaded from a savefile? Savefiles handle overlays badly, which is why best practice is to ditch the overlays either before saving (temporarily) or just after loading, and always reapply them fresh after load. If your hair loaded from a savefile, it's likely the character icon is simply a fusion of the original icon and its overlays. This would cause the exact situation you're seeing.