ID:264145
 
Code:
mob
Readd_Overlays()
src.overlays = null
for(var/obj/item/I in src)
if(I.Equipped)
src.overlays += I
if(src.Hair)
src.overlays += src.Hair
for(var/obj/H in src)
if(istype(H, /obj/item/helm))
if(H.Equipped)
if(H.helmtype == "Circlet")
src.overlays -= src.Hair
if(src.targetedby)
var/obj/spelltarget/S = new()
var/image/i = S
src.overlays += i


Problem description:

The above proc is what I use to handle most, if not all, changes to overlays. It works just fine after you login, performing all the correct actions without any problems. However, when you logout and have overlays(or something equipped), then log back in, the overlays get stuck on the player, as a part of the icon evidently. Hair, however, is unaffected. It call still be changed and removed as normal.

Also, if you don't have any items equipped, overlays are removed as normal upon logging in, and hair is added normally. Yet if you do have something equipped, it adds the overlays and gets stuck on the icon.

I find this odd. I checked both my login and logout, as well as mob/New and Del, and obj/New and Del. There is nothing in any of the aforementioned procs that alters anything on any items in the players contents, nor anything that alters the players overlays.

What could be the problem? This never gave me any problems until recently, I'd say probably version 420 or so.

Step by Step:

1. Login
2. Equip something, maybe get a haircut
3.Logout
4. Login again
--messed up icon/overlays--
5.Unequip everything
6.Logout
7.Login
--overlays/icon normal, hair (if any) added--
You're equipping you're mob with obj.
if(I.Equipped)
src.overlays += I

// change that to:

if(I.Equipped)
src.overlays += I.icon
In response to Ruben7
Ruben7 wrote:
You're equipping your mob with obj.

Which is fine and valid. You probably shouldn't try attempting to help if you don't have a firm grasp on the subject yourself.
This is just how BYOND's saving works. If you initiate object saving on an object with overlays/underlays, they just get added onto the actual icon when they're saved. To work around that, you'd simply not save overlays (saving the bulk of savefile space; this should be done with all icons basically) and handle rebuilding them when the object is recreated. Since you already have a proc for recreating overlays*, all you need to do is modify your saving so it doesn't save overlays (can be done quickly and robustly by overriding Write()).

*: Your equipment system is done wrong. State of being equipped or not shouldn't be handled by the item, rather the mob should keep track of what it has equipped. This is much better, more useful, robust and cleaner. You could rewrite your proc like something like this after you fix that (of course this varies based on the final implementation method you'd use):
mob
var/list/equipment
Readd_Overlays()
src.overlays = null
for(var/X in src.equipment)
var/obj/O = src.equipment[X]
if(O)
src.overlays += O
else if(X == "helmet")
if(src.Hair)
src.overlays +== src.Hair

if(src.targetedby)
src.overlays += /obj/spelltarget

For more info on this, Lummox JR has an article on associative lists, and Wizkidd0123 has an equipment demo you could check out.

Also, I notice you're still doing this for some reason:
            var/obj/spelltarget/S = new()
var/image/i = S
src.overlays += i

This is basic knowledge I already told you at least twice before. It doesn't change anything if you create a new var defined as an /image (which means NOTHING; that is only used for compile-time error checking) and use that instead of S itself. What the above block is doing is simply this: create a new /obj and set the S var to a reference to it. Then declare a new variable i, and set it to the exact same reference (changing nothing). Then, use i to add to the overlays instead of S, but i is really just another name for S and it has no different effect, so it's not going to solve (nor help with) anything.
In response to Kaioken
Kaioken wrote:
This is just how BYOND's saving works. If you initiate object saving on an object with overlays/underlays, they just get added onto the actual icon when they're saved. To work around that, you'd simply not save overlays[...]

The overlays and underlays list are saved alongside the icon, not on top of it. The rest of the paragraph is valid, though, as his problems with "stuck" overlays would disappear if he were to simply clear the overlays list at some point, preferably before the mob is put into the savefile:
client/Del()
var/mob/m = src.mob
if(m)
m.overlays.Cut()
m.underlays.Cut()
//rest of saving
. = ..()

Considering he already runs a proc on login to recreate all the character overlays, fixing the problem in this manner shouldn't be very difficult.
In response to Mobius Evalon
i seemed to have quite a bit of overlay issues myself. I was trying to use copytext to copy part of the icon's name(for saving), then using icon(file(bla)) i tired loading, but that didn't work too well.

So in the end, i came up with a overlay system somewhat similiar to yours.

        icon_save()
for(var/Equipment/E in contents)
if(E && E.worn)
E.icon_called = 1
othervars["overlays"] += E.name
E.Equip()

icon = null
overlays = null

icon_load()
switch(othervars[TYPE])
if("Tan")
icon = 'Base (Tan).dmi'
if("White")
icon = 'Base (White).dmi'

var/hair
switch(othervars[HAIR])
if("Spikey Hair")
hair = 'Spikey Hair.dmi'
hair += rgb(othervars[HRED],othervars[HGREEN],othervars[HBLUE])
overlays += hair

for(var/Equipment/E in contents)
if(E && E.name in othervars["overlays"] )
E.icon_called = 1
E.Equip()


I was really against using a switch statement for this, but it was the only way i could get it to work.(doing stuff late at night isn't a good idea >_>)
In response to Axerob
Axerob wrote:
i seemed to have quite a bit of overlay issues myself. I was trying to use copytext to copy part of the icon's name(for saving), then using icon(file(bla)) i tired loading, but that didn't work too well.

Just file should work:
icon = file("Base ([othervars[TYPE]]).dmi")
In response to Mobius Evalon
Mobius Evalon wrote:
The overlays and underlays list are saved alongside the icon, not on top of it.

Yeah, true, I got misled by some old posts, that was wrong. There is some merit in considering them virtually a part of the icon after loading, though, as they can't be removed by any means, probably because the method that was used to add them wasn't saved, so they can't be removed individually by any, only by clearing the entire list.

preferably before the mob is put into the savefile:

Which would be in a Write() override really, not client/Del(). Also, those kind of lists can be simply set to null to be cleared instead of calling Cut(), as shown in the OP's code.
In response to Mobius Evalon
The path passed through the file proc must be a file which exists at run time. Files in single quotes exist at compile time and are stored in the rsc. So, using the file proc won't work here.
In response to Nickr5
Nickr5 wrote:
The path passed through the file proc must be a file which exists at run time. Files in single quotes exist at compile time and are stored in the rsc. So, using the file proc won't work here.

Oh, right. I was thinking about my firearms system that uses the file proc to grab firing/loading sounds, but I didn't think twice about my never specifying any of those files in code -- my bad, don't mind me =p

In the case of compile-time resources, yeah, you just have to use that switch, Axerob.
In response to Mobius Evalon
Yeah, i found this out a few days ago.(i just never posted here) Using the switch statement won't be too bad as long as i don't get 300 million hairs from my pixel artists >_<.
In response to Mobius Evalon
Mobius Evalon wrote:
Kaioken wrote:
This is just how BYOND's saving works. If you initiate object saving on an object with overlays/underlays, they just get added onto the actual icon when they're saved. To work around that, you'd simply not save overlays[...]

The overlays and underlays list are saved alongside the icon, not on top of it. The rest of the paragraph is valid, though, as his problems with "stuck" overlays would disappear if he were to simply clear the overlays list at some point, preferably before the mob is put into the savefile:
client/Del()
> var/mob/m = src.mob
> if(m)
> m.overlays.Cut()
> m.underlays.Cut()
> //rest of saving
> . = ..()

Considering he already runs a proc on login to recreate all the character overlays, fixing the problem in this manner shouldn't be very difficult.

No luck. Overlays are indeed cleared, I checked that by putting in a time delay from the mob login and the overlays being readded. It seems that the issue lies with Login() and overlays, since it only occurs then (equipping items and spell casting adds/removes overlays perfectly.)

I'm going to try making a proc to call the proc, see if calling it outside of Login changes anything.

EDIT: No difference. The issue definately lies with logging in and overlays though.
In response to Pyro_dragons
I don't remember all of the procs that are called when the player logs in, and I'm at workso I dont have th extra time tolook. Would someone remind refreshing my memory?