ID:1314268
 
(See the best response by Kaiochao.)

obj
hair
layer = 97
short
long
spiky
puffy
New()
var/t = src.name
var/icon/i = new(file("hair/[t].dmi"))
src.icon = i
f// if I dont have this loop right here, the hair icons never appear on the players icon. I just don't see it.
spawn(20) goto f


Click()
usr.overlays.Remove(src)//this never works! i have to make "overlays = 0" to remove the hair.
if(src.name != "bald")
usr.overlays.Add(src)
usr.hairId = src

mob/proc
hair(var/i = 0)
set background = 1
winset(src, "hairGrid", null)
if(gender == "male")
var/list/groom=list()
var/A = new/obj/hair/spiky
var/B = new/obj/hair/long
var/C = new/obj/hair/short
var/D = new/obj/hair/puffy

groom.Add(A,B,C,D)
for(var/Z in groom)src << output(Z, "hairGrid:[++i]")

//this is basically how i am implementing the hair objects onto the grid.

Problem description: Okay so I made a window that holds a grid that displays the different hair styles a player can choose from. My problem is that without a loop under the hair objects, the hair never appears. In addition, I can't remove the hair without doing "usr.overlays = 0"

To reset your overlays list, use the Cut() proc or set it equal to null rather than 0. That's just a small personal preference of mine. You don't need to create a list to output the hair, you simply need one loop and that is it.

obj
hair
// with this they'll appear above the mob
layer = 4.01
// i don't know if you were being extremely
// lazy, but why are you setting their icon
// on obj/hair/New()?
short
icon = ''
long
icon = ''
pixie
icon = ''

Click()
if(!usr.equipped_hair)
usr.overlays += src
usr.equipped_hair = true
else
usr.overlays -= src
usr.equipped_hair = false

mob/var/equipped_hair = false
mob/verb/display_hair()
// in all honesty you would not need a list to
// display the hair, that's useless when you just
// need to output them using a loop and typesof()
for(var/a in typesof(/obj/hair) - /obj/hair)
usr << output(new a, "window.element:x,y")
In response to Neimo
Best response
Using file() doesn't work unless you package the files along with the game. This kind of laziness won't work well for you.

It doesn't look like you're removing the right hair. You're clicking a hair object, removing it, then adding it. What you probably want to do is remove a previously-chosen hair object, which you'd have to store on the player object.

It's strange that you're making an empty list and then adding new objects to it afterwards, when you could more easily do this to make a list of new objects:
var groom[] = newlist(
/obj/hair/spiky,
/obj/hair/long,
/obj/hair/short,
/obj/hair/puffy
)

Or even make a list using typesof: (by the way, Neimo, typesof() returns a list, so we're creating a list either way)
for(var/obj/hair/hair in typesof(/obj/hair) - /obj/hair)
src << output(hair, "hairGrid:[++i]")
winset(src, "hairGrid", "cells=[i]")

It's also bad that you're creating the variable 'i' in the arguments list of the proc. It doesn't make sense and it'd only be bad to actually pass an argument to it.
Thanks for responding :). Alright so I tried making a list using typesof but all that did was condense my code. Only one issue has been resolved. Without implementing a loop, the hair does don't display over the player.

obj
hair
layer = 4.01
short/icon = 'short.dmi'
long/icon = 'long.dmi'
spiky/icon = 'spikey.dmi'
puffy/icon = 'puffy.dmi'
New()

Loop// if I dont have this loop right here,
//the hair icons never appear on the players icon.
//I just don't see it.
spawn(20) goto Loop
Click()
usr.overlays -= usr.lastHair
usr.overlays += src
usr.lastHair = src


mob/proc
hair(var/i = 0)
set background = 1
winset(src, "hairGrid", null)
if(gender == "male")
for(var/a in typesof(/obj/hair) - /obj/hair)
src << output(new a, "barber.hairGrid:[++i]")

//without the "i" I won't be able to see the hair
//inside the grid. It doesn't display.

Bump.
As mentioned in the Skin Reference, you should not output temporary objects to a grid, as the grid does not count as a reference and they will be garbage collected.

The reason your loop works is because it makes /obj/hair/New() never complete, keeping an src reference to each hair object so they aren't deleted.

The proper solution is to store those hair objects in a list somewhere, and just output them from that. A global list would be fine in this case.
In response to DarkCampainger
So something along the lines of:

var/global
list/maleHair = list(new/obj/hair/male/spiky,new/obj/hair/male/puffy)

//this doesn't look right though.
In response to Luchasi
Yep. You can also use newlist() like Kaiochao mentioned to save typing 'new' if you like.

If you don't want to write out all the types, you can create them at runtime (such as in world/New(), or the first time they're used) by looping through typesof() like before.
In response to DarkCampainger
Okay I did it that way but the thing is, they don't display inside the grid. I only see numbers or I think they're Index values.

mob/proc
hair(var/i = 0)
set background = 1
winset(src, "hairGrid", null)
if(gender == "male")
for(var/t in maleHair)
usr << output(i, "barber.hairGrid:[++i]")
winset(usr, "barber.hairGrid", {"cells = "1x[i]""})
In response to Luchasi
You're sending 'i' to the grid instead of the hair object, haha.

Also, the line
winset(src, "hairGrid", null)

doesn't do anything.

winset(src, "barber.hairGrid", "cells=[i]")

This is what I showed you, and it's all you need, for a grid set as a "flexible list of entries".
Hahah thanks :D it works like a charm when I did this.

mob/proc
hair(var/i = 0)
set background = 1
if(gender == "male")
for(var/t in maleHair)
usr << output(t, "barber.hairGrid:[++i]")
winset(src, "barber.hairGrid", "cells=[i]")
In response to Luchasi
Extra tips time!

1. Making the 'i' variable in the arguments is bad! Put it in the body of the proc where it belongs.
2. You're using usr in your proc, which is unreliable and bad.
3. You only need to set the grid's "cells" at the end, so unindent it.
In response to Kaiochao
Thanks so much :D I think I got it ^_^