ID:1936726
 
(See the best response by Ter13.)
Code:
        //"ChatList" is a list of 10 text vars, representing the last
//10 things sent to the chat box.
FadeText(mob/u)
var/list/x = u.ChatList
spawn(10)
//if the list hasnt changed since the proc was called
if(x == u.ChatList)
for(var/GUI/Text/msg in u.ChatList)
//fade everything
animate(msg, alpha = 0, time = 4)


Problem description:

FadeText() is called whenever I want to "fade" all GUI maptext of a certain kind. But there may be many things calling this proc more or less at once - so I need to make sure I only execute the proc ONCE when the proc hasn't been called in the last second. If it keeps getting called - so be it, the GUI stays there.

This is basically supposed to be code to cause the GUI to fade out on inactivity.

In the above method, I'm trying to see if the contents of List1 are the same as List2. Ideally the only way it would fail is if someone spammed the exact same thing over and over 10+ times - for which I would handle seperately.


Is there maybe a better method of doing this, instead?
Hmm, this doesn't solve the problem, only changes it. I need to check if the list has been modified or amended. This just ploughs ahead with whatever the list contained a few ticks ago and ignores additions.

This is especially pronounced for the anticipated fade time of about 5 seconds when out of testing.

It really needs to only call animate() from the most recent action, and when it does -- it needs to call everything in ChatList/all instances visible to the player.

Side note - is it possible to interrupt animate()? So that it stops what its doing?
Best response
You are both overcomplicating this.

mob
var/tmp
last_message = -1
list/chatlist = list()
proc
receiveMessage(msg)
set waitfor = FALSE
var/time = world.time
if(last_message-time>FADE_TIME)
var/len = chatlist.len
var/GUI/Test/o
//restore messages
for(var/count in 1 to len)
o = chatlist[count]
o.alpha = 255
//create the new message and add it to chatlist.
chatlist += new/GUI/Test(null,src,msg)
//check if we haven't added another message this frame. No reason to stack up the sleep more than once in the same frame.
if(last_message<time)
last_message = time
sleep(10)
if(last_message==time) //make sure stored time hasn't changed
//fade out the elements
var/len = chatlist.len
for(var/count in 1 to len)
animate(chatlist[count],time=4,alpha=0)


You'll have to adapt this approach to your particular system, but basically what this does is store the last time that a message was added as a world time offset. This allows us to know when a message has been added to prevent the fade-out, and it also lets us know how long it's been since the fade-out started/ended.

This way, you aren't dealing with list copies being generated all over the place, and iterating through lists over and over again to verify that nothing has changed.

This approach should nicely sidestep the problem in such a way that you don't have to to quite the same amount of work.

Side note - is it possible to interrupt animate()? So that it stops what its doing?

yes. Call animate on that object again.
In response to Ter13
AH yes, I often forget about using time!

I actually found a library for exactly what I was trying to do, despite not finding it last week.

Cheers! :) My chat box is looking pretty spiffy now.