ID:2777200
 
Not a bug
BYOND Version:Every version since overlays were added
Operating System:All operating systems
Web Browser:Chrome 80.0.3987.99
Applies to:Dream Seeker
Status: Not a bug

This is not a bug. It may be an incorrect use of syntax or a limitation in the software. For further discussion on the matter, please consult the BYOND forums.
Descriptive Problem Summary:

I'm calling this a bug. It has hounded me for years, and I'm done working around it. Icon_states should display as they were created by the artist, everytime, and not randomly and arbitrarily displayed however DreamSeeker feels like.

Animated icon_states are improperly displayed when added to overlays and underlays. They begin on random frames and not the first frame, as they should.

Numbered Steps to Reproduce Problem:

1.) Create an animated icon_state.
2.) Add it to an overlays list.
3.) sleep() the number of ticks the animation lasts.
4.) Remove it from the overlays list.

Code Snippet (if applicable) to Reproduce Problem:
mob
icon = 'icon.dmi' // contains one icon_state named "animation" with 10 unique frames each with a delay of one tick

verb/Anim()
overlays += "animation"
sleep(10)
overlays -= "animation"


Expected Results:

The animation should play from frame one to frame ten everytime.

Actual Results:

The animation begins and ends on random frames, looping if the last frame is reached before the overlay is removed.

Does the problem occur:
Every time? Or how often?
Everytime

In other games?
Yes

In other user accounts?
Yes
On other computers?
Yes

When does the problem NOT occur?

The problem always occurs, but random chance will make the animation play properly from time to time.

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.)

This problem has existed in every version since overlays were added to BYOND.

Workarounds:

Create an obj where the animation should be, moving it with the atom if necessary, and flick() the animation on the obj instead of using overlays or underlays. Basically, build your own overlay system from scratch using objs and flick(), which is the only method available that ensures animated frames play fully from frame one to the final frame. No, you can't flick() an overlay or image, though the reference claims images can be flicked.

Or, manually animate the frames by making each one a separate icon_state, and adding and removing them to overlays in order, with a sleep(delay) between each addition and removal, to reconstruct the animation by hand in the code.
Lummox JR resolved issue (Not a bug)
The issue here is that overlays are not separate objects. Icon animation start times are based on when the client saw them or when the client saw an icon/state change on the main object, whichever came latest. But overlays are only dumb appearances and tie in to the parent object.

If you want specific timing behavior, this would be a case for using a temporary obj in visual contents. It will behave exactly the way you want it to, and it can still act like an overlay in terms of inheriting the parent object's ID, icon, state, etc. if you want via vis_flags.
I need to get more familiar with these fancy new appearances then. Seems much more has changed than I thought.
A quick approach that should work:
obj/timed_overlay
// this should act like a regular overlay
vis_flags = VIS_INHERIT_ID | VIS_INHERIT_ICON | VIS_INHERIT_DIR
icon_state = "overlay"
layer = FLOAT_LAYER
plane = FLOAT_PLANE

mob/verb/Anim()
var/obj/timed_overlay/O = new
vis_contents += O
sleep(10)
vis_contents -= O
Chef's kiss!

Thanks for the insight!