ID:2145443
 
(See the best response by Ter13.)
I'm trying to add 1 to a players age every 6 hours. I'd like to also have players that are offline to age as well. The only way I can think of is to edit all of the savefiles ages. Am I thinking about this the wrong way, or is this how I should do it?

Best response
Don't store the age in the savefile at all. Store their birthdate and calculate their age when the savefile loads.

#define STARTING_AGE 12
/*
#define TICK_SECOND (10)
#define TICK_MINUTE (TICK_SECOND * 60)
#define TICK_HOUR (TICK_MINUTE * 60)
#define YEAR_TIME (TICK_HOUR * 6)
*/

#define YEAR_TIME 216000 //10 ticks/second * 60 seconds/minute * 60 minutes/hour * 6 hours/year = 216000 ticks/year

mob
var
birthday
ages //set to -1#INF to make this mob unaging even if controlled by a player
tmp
age = STARTING_AGE
New() //called automatically when an object is created
if(!birthday) birthday = world.realtime - YEAR_TIME*age //set the birthday based on the current age
if(ages&&ages!=-1#INF) Age() //if a non-player mob's prototype has ages set to 1, it will autostart aging without a player

Read(var/savefile/F) //called automatically whenever an object is read from a savefile
..()
age = round((world.realtime-birthday)/YEAR_TIME) //recover the age based on birthday

proc
//this is a loop that keeps track of aging while a mob is loaded.
Age()
set waitfor = 0 //keep this from hanging up the caller
//prevent the loop from executing more than once
if(ages!=null) return
var/time = world.time
ages = time
var/next_age = birthday + YEAR_TIME*(age+1)
while(ages==time) //loop as long as this call is current
if(world.realtime>=next_age) //if our birthday is here
++age //increment age
next_age = birthday + YEAR_TIME*(age+1) //set the next birthday
sleep(world.tick_lag) //we can check this at a lower frequency if we want. That'd be okay.

Login()
if(!ages&&ages!=-1#INF) Age() //start the aging loop if needed and not unaging
. = ..()

Logout()
if(!initial(ages)) ages = 0 //if this prototype doesn't age by default, stop aging to allow garbage collection
..()


Using time deltas is a way to acheive very efficient, very flexible programs. If you ever encounter a solution to a problem where you need to keep track of data for offline players, chances are that you are chasing down a bad solution. Generally, it's best to store the information in a form that can be recalculated on load, or to simply deal with that information at a later time through a third-party object/savefile.
This is actually pretty confusing to me since I've never done anything time-related in BYOND, but I started using this and I'm gaining 12 'age' a second.
Minor mistake on my part. It has been corrected. Give 'er a shot.
Er... Two minor mistakes. Sorry. Refactoring untested code is a bastard.