ID:1558147
 
(See the best response by Ter13.)
Code:
mob
npc
Barber
icon='npc barber.dmi'
name="{NPC} Barber"
NPC=1
Click()
switch(alert("Would you like a hair cut?",,"Yes","No"))
if("Yes")
usr.overlays-='afro.dmi'
switch(alert("What style would you like?",,"Bald","Afro","Aizen"))
if("Bald")
usr.overlays-='afro.dmi'
usr.overlays-='aizen.dmi'
return
if("Afro")
var/hair='afro.dmi'
var/color=input("What color?","Color")as color
hair=initial(hair)
hair+=color
usr.overlays+=hair
return
if("Aizen")
var/hair='aizen.dmi'
var/color=input("What color?","Color")as color
hair=initial(hair)
hair+=color
usr.overlays+=hair
return
if("No")
return


Problem description: This adds the overlays just fine. Problem is, it won't remove them afterwords. Essentially I need to be able to reset the hair overlays that are on the mob each time, so they're not layering on top one another and making things look strange. Unfortunately that's exactly what is happening.

Best response
The problem is that you are modifying the overlay icon by changing its color. Therefore, it's not the default, and subtracting the icon name from the overlays list won't actually remove it.

My advice would be to use an overlay manager structure to associate overlays with a unique string name. For things like hair, that the player should only have one of at a time, this will ensure that the old overlay is removed prior to adding the new one. Just make sure the same type of thing uses the same name for the id category.

mob
var/tmp
list/managed_overlays = list()
proc
addOverlay(id,overlay)
if(id in managed_overlays)
removeOverlay(id)
overlays += overlay
managed_overlays[id] = overlays[overlays.len]

removeOverlay(id)
if(id in managed_overlays)
overlays -= managed_overlays[id]
managed_overlays.Remove(id)
So when calling the addOverlay proc for say, the afro hair style, would I put it in as "addOverlay("Afro",'afro.dmi')? I'm trying to work out in my head how I would integrate that into the colorizing, but it's confusing me.
No. Don't name it "afro". Name it "hair". That way adding future hairstyles will replace it.

var/hair = 'hairstyle.dmi'
hair += rgb(0,0,0)
usr.addOverlay("hair",hair)
I got it to work using your method. I appreciate the aid. There seems to be an issue with making it so that the player has no hair at all, however that's fixable by adding an empty overlay as a 'bald.dmi'. Unless there's an easier way to do it.
Use the removeOverlay function with the "hair" id to remove the hair.
That works for when the player is logged in, but for some reason when the player relogs and tries to do it again, the overlay that they had on when they logged out will not go away.

I defined the list as tmp as instructed, so it -shouldn't- be saving it upon log-out...
You should read my article on saving as to why saving the overlays list is only going to give you problems.

You can try to mark the managed_overlays list as not being tmp, and see if that works, but I don't recommend saving overlays at all.
Well there are only certain things that I would need to have saved, you know? Things that would annoy the player to have to redo every time they would log back in. You can imagine how logging back into a completely naked character would get irritating after a while.
You can imagine how logging back into a completely naked character would get irritating after a while.

Which is why you need a mechanism to store overlays without saving the overlays list, and then use that data to regenerate the overlays upon login.

Take a look at this thread, where I detail how to avoid saving the overlays list, but regenerate things like equipment overlays on login.

http://www.byond.com/forum/?post=1187381#comment9573260

Read that post, then scroll back up to take a look at the proposed equipment system.
I will.

Just as a little update though, removing the 'tmp' did fix the problem.
Actually, apparently not all is well.

I am getting an error with this, in regards to saving. It happened before, though I got it to go away by turning several variables into tmp variables.

However, even that is not helping now. This is what happens: I make a new character, go to the barber, and select a hairstyle. Then, I press my save button. Everything works as it should.

Now, I log off, then log back in. Try to press the save button again, and I get this error:
runtime error: bad output
proc name: SaveC (/mob/proc/SaveC)
usr: the asdfasdf (/mob)
src: the asdfasdf (/mob)
call stack:
the asdfasdf (/mob): SaveC()
the asdfasdf (/mob): Save()
You know, I linked to a tutorial on saving earlier in the thread.

This is what happens when you take shortcuts.
Any tips on managing overlay order using the system you suggested? As it is right now, the hairs overlay on top of everything, and there are certain things that need to ALWAYS be on-top.
http://www.byond.com/members/ Critical172?command=view_post&post=1449526#comment7910928

Look up FLOAT_LAYER in the reference.

mob
var/tmp
list/managed_overlays = list()
proc
addOverlay(id,overlay,layer)
if(id in managed_overlays)
removeOverlay(id)
overlays += overlay
var/atom/a = overlays[overlays.len] //we're going to cheat just a little bit here.
a.layer = layer //not sure if this will work, never tried direct appearance manipulation.
managed_overlays[id] = a

removeOverlay(id)
if(id in managed_overlays)
overlays -= managed_overlays[id]
managed_overlays.Remove(id)
The irony here is I was -just- looking at a post (http://www.byond.com/ forum/?post=1467998&hl=overlay%20layers#comment8287506) about float layers when I came back to this.

Unfortunately it didn't seem to work. When I set up the addOverlays() for each item, I did it as thus:

Mask:
src.addOverlay("mask",mask,FLOAT_LAYER-2)

Hair:
usr.addOverlay("hair",hair,FLOAT_LAYER-1)


I've tried switching the float numbers around, but it didn't seem to make a difference. Perhaps I'm calling it wrong?

This is the entire verb:
For mask:
Break_Mask()
if(src.Race=="Hollow"&&src.Rank=="Strong")
switch(alert("Do you wish to break off your mask and become an Arrancar? Be warned, this change is permanent."
,,"Yes","No"))
if("Yes")
var/tmp/mask=pick('mask 1.dmi','mask 2.dmi','mask 3.dmi','mask 4.dmi','mask 5.dmi','mask 6.dmi',
'mask 7.dmi','mask 8.dmi','mask 9.dmi','mask 10.dmi','mask 11.dmi','mask 12.dmi','mask 13.dmi'
'mask 14.dmi','mask 15.dmi','mask 16.dmi','mask 17.dmi','mask 18.dmi')
src.icon='male white.dmi'
src.Race="Arrancar"
src.addOverlay("mask",mask,FLOAT_LAYER-2)
src.contents+=new/obj/arrancarsuit
src.hasclothes["arrancarsuit"]=1
src.contents+=new/obj/zanpakutou
src.hasclothes["zanpakutou"]=1
src.pixel_x=0
if("No")
return

For hair:
Click()
switch(alert("Would you like a hair cut?",,"Yes","No"))
if("Yes")
switch(input("What style would you like?","Barber") in list("Bald","Afro","Amelie","Aizen",
"Asano","Byakuya","Chick","Emo","Gin","Hinamori","Ichigo","Ishida","Isshen","Jidanbou","Kira",
"Lisa","Matsumoto","Momo","Renji","Rukia","Sado","Sanna","Tetsuzaemon","Tousen","Ukitake",
"Urahara","Ururu","Yoruichi","Zaraki"))
if("Bald")
usr.removeOverlay("hair")
return
if("Afro")
var/tmp/hair='afro.dmi'
var/color=input("What color?","Color")as color
hair=initial(hair)
hair+=color
usr.addOverlay("hair",hair,FLOAT_LAYER-1)
I'm wondering if the simplest way to fix this is to turn everything (hair and masks) into objects with a defined layer all their own.